passenger 5.0.30 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +30 -1
  3. data/CONTRIBUTING.md +1 -1
  4. data/CONTRIBUTORS +2 -0
  5. data/bin/passenger-install-nginx-module +18 -13
  6. data/build/agent.rb +1 -0
  7. data/build/basics.rb +1 -0
  8. data/build/cxx_tests.rb +6 -1
  9. data/build/misc.rb +3 -0
  10. data/build/packaging.rb +5 -17
  11. data/build/support/cxx_dependency_map.rb +100 -0
  12. data/build/support/vendor/cxxcodebuilder/lib/cxxcodebuilder/builder.rb +4 -1
  13. data/build/test_basics.rb +12 -2
  14. data/dev/ci/run_travis.sh +6 -2
  15. data/doc/Users guide Apache.html +7 -2
  16. data/doc/Users guide Apache.txt +4 -0
  17. data/resources/templates/error_layout.css +70 -84
  18. data/resources/templates/error_layout.html.template +84 -93
  19. data/resources/templates/standalone/http.erb +17 -13
  20. data/resources/templates/standalone/server.erb +2 -1
  21. data/resources/templates/undisclosed_error.html.template +52 -51
  22. data/resources/update_check_client_cert.p12 +0 -0
  23. data/resources/update_check_client_cert.pem +89 -0
  24. data/resources/update_check_server_pubkey.pem +14 -0
  25. data/src/agent/Core/ApplicationPool/ErrorRenderer.h +15 -1
  26. data/src/agent/Core/Controller.h +3 -2
  27. data/src/agent/Core/Controller/CheckoutSession.cpp +5 -4
  28. data/src/agent/Core/Controller/ForwardResponse.cpp +1 -1
  29. data/src/agent/Core/Controller/InitRequest.cpp +2 -0
  30. data/src/agent/Core/Controller/InitializationAndShutdown.cpp +1 -0
  31. data/src/agent/Core/Controller/Request.h +1 -0
  32. data/src/agent/Core/CoreMain.cpp +99 -2
  33. data/src/agent/Core/OptionParser.h +18 -1
  34. data/src/agent/Core/SecurityUpdateChecker.h +559 -0
  35. data/src/agent/Shared/Base.cpp +6 -1
  36. data/src/agent/TempDirToucher/TempDirToucherMain.cpp +52 -0
  37. data/src/agent/Watchdog/InstanceDirToucher.cpp +1 -2
  38. data/src/agent/Watchdog/WatchdogMain.cpp +31 -40
  39. data/src/apache2_module/Configuration.cpp +12 -0
  40. data/src/apache2_module/Configuration.hpp +5 -0
  41. data/src/apache2_module/ConfigurationCommands.cpp +19 -19
  42. data/src/apache2_module/ConfigurationCommands.cpp.cxxcodebuilder +2 -2
  43. data/src/apache2_module/ConfigurationFields.hpp +19 -19
  44. data/src/apache2_module/ConfigurationFields.hpp.cxxcodebuilder +2 -2
  45. data/src/apache2_module/ConfigurationSetters.cpp +19 -19
  46. data/src/apache2_module/ConfigurationSetters.cpp.cxxcodebuilder +2 -2
  47. data/src/apache2_module/CreateDirConfig.cpp +19 -19
  48. data/src/apache2_module/CreateDirConfig.cpp.cxxcodebuilder +2 -2
  49. data/src/apache2_module/Hooks.cpp +10 -1
  50. data/src/apache2_module/MergeDirConfig.cpp +19 -19
  51. data/src/apache2_module/MergeDirConfig.cpp.cxxcodebuilder +2 -2
  52. data/src/apache2_module/SetHeaders.cpp +19 -19
  53. data/src/apache2_module/SetHeaders.cpp.cxxcodebuilder +2 -2
  54. data/src/cxx_supportlib/Constants.h +22 -22
  55. data/src/cxx_supportlib/Constants.h.cxxcodebuilder +4 -1
  56. data/src/cxx_supportlib/Crypto.cpp +977 -0
  57. data/src/cxx_supportlib/Crypto.h +147 -0
  58. data/src/cxx_supportlib/InstanceDirectory.h +55 -2
  59. data/src/cxx_supportlib/Utils/Curl.h +24 -10
  60. data/src/cxx_supportlib/Utils/JsonUtils.h +1 -1
  61. data/src/cxx_supportlib/oxt/detail/spin_lock_darwin.hpp +2 -0
  62. data/src/cxx_supportlib/vendor-modified/boost/system/error_code.hpp +3 -3
  63. data/src/cxx_supportlib/vendor-modified/jsoncpp/json-forwards.h +167 -92
  64. data/src/cxx_supportlib/vendor-modified/jsoncpp/json.h +1827 -1542
  65. data/src/cxx_supportlib/vendor-modified/jsoncpp/jsoncpp.cpp +4705 -3652
  66. data/src/cxx_supportlib/vendor-modified/libev/Changes +46 -15
  67. data/src/cxx_supportlib/vendor-modified/libev/LICENSE +1 -1
  68. data/src/cxx_supportlib/vendor-modified/libev/Makefile.in +215 -128
  69. data/src/cxx_supportlib/vendor-modified/libev/aclocal.m4 +466 -275
  70. data/src/cxx_supportlib/vendor-modified/libev/config.guess +312 -418
  71. data/src/cxx_supportlib/vendor-modified/libev/config.sub +246 -105
  72. data/src/cxx_supportlib/vendor-modified/libev/configure +276 -72
  73. data/src/cxx_supportlib/vendor-modified/libev/configure.ac +2 -1
  74. data/src/cxx_supportlib/vendor-modified/libev/depcomp +346 -185
  75. data/src/cxx_supportlib/vendor-modified/libev/ev++.h +1 -1
  76. data/src/cxx_supportlib/vendor-modified/libev/ev.c +530 -190
  77. data/src/cxx_supportlib/vendor-modified/libev/ev.h +23 -14
  78. data/src/cxx_supportlib/vendor-modified/libev/ev_epoll.c +12 -6
  79. data/src/cxx_supportlib/vendor-modified/libev/ev_kqueue.c +9 -5
  80. data/src/cxx_supportlib/vendor-modified/libev/ev_poll.c +6 -3
  81. data/src/cxx_supportlib/vendor-modified/libev/ev_port.c +8 -4
  82. data/src/cxx_supportlib/vendor-modified/libev/ev_select.c +4 -2
  83. data/src/cxx_supportlib/vendor-modified/libev/ev_vars.h +3 -2
  84. data/src/cxx_supportlib/vendor-modified/libev/ev_win32.c +3 -4
  85. data/src/cxx_supportlib/vendor-modified/libev/install-sh +433 -219
  86. data/src/cxx_supportlib/vendor-modified/libev/libev.m4 +6 -6
  87. data/src/cxx_supportlib/vendor-modified/libev/ltmain.sh +2 -2
  88. data/src/cxx_supportlib/vendor-modified/libev/missing +167 -288
  89. data/src/cxx_supportlib/vendor-modified/libev/mkinstalldirs +72 -21
  90. data/src/cxx_supportlib/vendor-modified/modp_b64.cpp +4 -106
  91. data/src/cxx_supportlib/vendor-modified/modp_b64_data.h +37 -1
  92. data/src/cxx_supportlib/vendor-modified/modp_b64_strict_aliasing.cpp +119 -0
  93. data/src/helper-scripts/node-loader.js +72 -1
  94. data/src/nginx_module/CacheLocationConfig.c +52 -19
  95. data/src/nginx_module/CacheLocationConfig.c.cxxcodebuilder +2 -2
  96. data/src/nginx_module/Configuration.c +26 -1
  97. data/src/nginx_module/Configuration.h +2 -0
  98. data/src/nginx_module/ConfigurationCommands.c +35 -19
  99. data/src/nginx_module/ConfigurationCommands.c.cxxcodebuilder +2 -2
  100. data/src/nginx_module/ContentHandler.c +1 -1
  101. data/src/nginx_module/CreateLocationConfig.c +22 -19
  102. data/src/nginx_module/CreateLocationConfig.c.cxxcodebuilder +2 -2
  103. data/src/nginx_module/LocationConfig.h +21 -19
  104. data/src/nginx_module/LocationConfig.h.cxxcodebuilder +2 -2
  105. data/src/nginx_module/MergeLocationConfig.c +25 -19
  106. data/src/nginx_module/MergeLocationConfig.c.cxxcodebuilder +2 -2
  107. data/src/nginx_module/ngx_http_passenger_module.c +8 -4
  108. data/src/ruby_supportlib/phusion_passenger.rb +9 -4
  109. data/src/ruby_supportlib/phusion_passenger/admin_tools/instance.rb +2 -2
  110. data/src/ruby_supportlib/phusion_passenger/admin_tools/instance_registry.rb +1 -1
  111. data/src/ruby_supportlib/phusion_passenger/common_library.rb +13 -0
  112. data/src/ruby_supportlib/phusion_passenger/config/nginx_engine_compiler.rb +5 -2
  113. data/src/ruby_supportlib/phusion_passenger/constants.rb +1 -1
  114. data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +15 -3
  115. data/src/ruby_supportlib/phusion_passenger/platform_info/crypto.rb +51 -0
  116. data/src/ruby_supportlib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +7 -0
  117. data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +17 -0
  118. data/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb +4 -2
  119. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +4 -0
  120. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/nginx_engine.rb +5 -0
  121. data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/app.rb +19 -10
  122. data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/base.rb +25 -0
  123. data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/gdb_controller.rb +38 -103
  124. data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/lldb_controller.rb +178 -0
  125. data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/utils.rb +94 -0
  126. data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/version.rb +2 -2
  127. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core.rb +2 -2
  128. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/version_data.rb +2 -2
  129. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.travis +5 -3
  130. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.travis-with-sudo +9 -7
  131. metadata +14 -4
@@ -23,12 +23,12 @@
23
23
  # THE SOFTWARE.
24
24
 
25
25
  # This file uses the cxxcodebuilder API. Learn more at:
26
- # https://github.com/phusion/passenger/cxxcodebuilder
26
+ # https://github.com/phusion/cxxcodebuilder
27
27
 
28
28
  require 'phusion_passenger/apache2/config_options'
29
29
 
30
30
  def main
31
- comment copyright_header_for(__FILE__)
31
+ comment copyright_header_for(__FILE__), 1
32
32
 
33
33
  separator
34
34
 
@@ -1,27 +1,27 @@
1
1
  /*
2
- * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2010-2016 Phusion Holding B.V.
2
+ * Phusion Passenger - https://www.phusionpassenger.com/
3
+ * Copyright (c) 2010-2016 Phusion Holding B.V.
4
4
  *
5
- * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
- * trademarks of Phusion Holding B.V.
5
+ * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
+ * trademarks of Phusion Holding B.V.
7
7
  *
8
- * Permission is hereby granted, free of charge, to any person obtaining a copy
9
- * of this software and associated documentation files (the "Software"), to deal
10
- * in the Software without restriction, including without limitation the rights
11
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
- * copies of the Software, and to permit persons to whom the Software is
13
- * furnished to do so, subject to the following conditions:
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
14
  *
15
- * The above copyright notice and this permission notice shall be included in
16
- * all copies or substantial portions of the Software.
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
17
  *
18
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
- * THE SOFTWARE.
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
25
  */
26
26
 
27
27
  /*
@@ -23,12 +23,12 @@
23
23
  # THE SOFTWARE.
24
24
 
25
25
  # This file uses the cxxcodebuilder API. Learn more at:
26
- # https://github.com/phusion/passenger/cxxcodebuilder
26
+ # https://github.com/phusion/cxxcodebuilder
27
27
 
28
28
  require 'phusion_passenger/apache2/config_options'
29
29
 
30
30
  def main
31
- comment copyright_header_for(__FILE__)
31
+ comment copyright_header_for(__FILE__), 1
32
32
 
33
33
  separator
34
34
 
@@ -1,27 +1,27 @@
1
1
  /*
2
- * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2010-2016 Phusion Holding B.V.
2
+ * Phusion Passenger - https://www.phusionpassenger.com/
3
+ * Copyright (c) 2010-2016 Phusion Holding B.V.
4
4
  *
5
- * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
- * trademarks of Phusion Holding B.V.
5
+ * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
+ * trademarks of Phusion Holding B.V.
7
7
  *
8
- * Permission is hereby granted, free of charge, to any person obtaining a copy
9
- * of this software and associated documentation files (the "Software"), to deal
10
- * in the Software without restriction, including without limitation the rights
11
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
- * copies of the Software, and to permit persons to whom the Software is
13
- * furnished to do so, subject to the following conditions:
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
14
  *
15
- * The above copyright notice and this permission notice shall be included in
16
- * all copies or substantial portions of the Software.
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
17
  *
18
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
- * THE SOFTWARE.
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
25
  */
26
26
 
27
27
  /*
@@ -23,12 +23,12 @@
23
23
  # THE SOFTWARE.
24
24
 
25
25
  # This file uses the cxxcodebuilder API. Learn more at:
26
- # https://github.com/phusion/passenger/cxxcodebuilder
26
+ # https://github.com/phusion/cxxcodebuilder
27
27
 
28
28
  require 'phusion_passenger/apache2/config_options'
29
29
 
30
30
  def main
31
- comment copyright_header_for(__FILE__)
31
+ comment copyright_header_for(__FILE__), 1
32
32
 
33
33
  separator
34
34
 
@@ -1274,10 +1274,18 @@ public:
1274
1274
  const char *webServerDesc = ap_get_server_version();
1275
1275
  #endif
1276
1276
 
1277
+ ap_version_t version;
1278
+ ap_get_server_revision(&version);
1279
+ string webServerVersion = toString(version.major) + "." + toString(version.minor) + "." + toString(version.patch);
1280
+ if (version.add_string != NULL) {
1281
+ webServerVersion.append(version.add_string);
1282
+ }
1283
+
1277
1284
  VariantMap params;
1278
1285
  params
1279
1286
  .setPid ("web_server_control_process_pid", getpid())
1280
1287
  .set ("server_software", webServerDesc)
1288
+ .set ("server_version", webServerVersion)
1281
1289
  .setBool("multi_app", true)
1282
1290
  .setBool("load_shell_envvars", true)
1283
1291
  .set ("file_descriptor_log_file", (serverConfig.fileDescriptorLogFile == NULL)
@@ -1285,6 +1293,8 @@ public:
1285
1293
  .setInt ("socket_backlog", serverConfig.socketBacklog)
1286
1294
  .set ("data_buffer_dir", serverConfig.dataBufferDir)
1287
1295
  .set ("instance_registry_dir", serverConfig.instanceRegistryDir)
1296
+ .setBool("disable_security_update_check", serverConfig.disableSecurityUpdateCheck)
1297
+ .set ("security_update_check_proxy", serverConfig.securityUpdateCheckProxy)
1288
1298
  .setBool("user_switching", serverConfig.userSwitching)
1289
1299
  .set ("default_user", serverConfig.defaultUser)
1290
1300
  .set ("default_group", serverConfig.defaultGroup)
@@ -1722,4 +1732,3 @@ passenger_register_hooks(apr_pool_t *p) {
1722
1732
  /**
1723
1733
  * @}
1724
1734
  */
1725
-
@@ -1,27 +1,27 @@
1
1
  /*
2
- * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2010-2016 Phusion Holding B.V.
2
+ * Phusion Passenger - https://www.phusionpassenger.com/
3
+ * Copyright (c) 2010-2016 Phusion Holding B.V.
4
4
  *
5
- * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
- * trademarks of Phusion Holding B.V.
5
+ * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
+ * trademarks of Phusion Holding B.V.
7
7
  *
8
- * Permission is hereby granted, free of charge, to any person obtaining a copy
9
- * of this software and associated documentation files (the "Software"), to deal
10
- * in the Software without restriction, including without limitation the rights
11
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
- * copies of the Software, and to permit persons to whom the Software is
13
- * furnished to do so, subject to the following conditions:
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
14
  *
15
- * The above copyright notice and this permission notice shall be included in
16
- * all copies or substantial portions of the Software.
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
17
  *
18
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
- * THE SOFTWARE.
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
25
  */
26
26
 
27
27
  /*
@@ -23,12 +23,12 @@
23
23
  # THE SOFTWARE.
24
24
 
25
25
  # This file uses the cxxcodebuilder API. Learn more at:
26
- # https://github.com/phusion/passenger/cxxcodebuilder
26
+ # https://github.com/phusion/cxxcodebuilder
27
27
 
28
28
  require 'phusion_passenger/apache2/config_options'
29
29
 
30
30
  def main
31
- comment copyright_header_for(__FILE__)
31
+ comment copyright_header_for(__FILE__), 1
32
32
 
33
33
  separator
34
34
 
@@ -1,27 +1,27 @@
1
1
  /*
2
- * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2010-2016 Phusion Holding B.V.
2
+ * Phusion Passenger - https://www.phusionpassenger.com/
3
+ * Copyright (c) 2010-2016 Phusion Holding B.V.
4
4
  *
5
- * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
- * trademarks of Phusion Holding B.V.
5
+ * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
+ * trademarks of Phusion Holding B.V.
7
7
  *
8
- * Permission is hereby granted, free of charge, to any person obtaining a copy
9
- * of this software and associated documentation files (the "Software"), to deal
10
- * in the Software without restriction, including without limitation the rights
11
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
- * copies of the Software, and to permit persons to whom the Software is
13
- * furnished to do so, subject to the following conditions:
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
14
  *
15
- * The above copyright notice and this permission notice shall be included in
16
- * all copies or substantial portions of the Software.
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
17
  *
18
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
- * THE SOFTWARE.
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
25
  */
26
26
 
27
27
  /*
@@ -23,12 +23,12 @@
23
23
  # THE SOFTWARE.
24
24
 
25
25
  # This file uses the cxxcodebuilder API. Learn more at:
26
- # https://github.com/phusion/passenger/cxxcodebuilder
26
+ # https://github.com/phusion/cxxcodebuilder
27
27
 
28
28
  require 'phusion_passenger/apache2/config_options'
29
29
 
30
30
  def main
31
- comment copyright_header_for(__FILE__)
31
+ comment copyright_header_for(__FILE__), 1
32
32
 
33
33
  separator
34
34
 
@@ -1,28 +1,28 @@
1
1
  /*
2
- * encoding: utf-8
3
- * Phusion Passenger - https://www.phusionpassenger.com/
4
- * Copyright (c) 2010-2016 Phusion Holding B.V.
2
+ * encoding: utf-8
3
+ * Phusion Passenger - https://www.phusionpassenger.com/
4
+ * Copyright (c) 2010-2016 Phusion Holding B.V.
5
5
  *
6
- * "Passenger", "Phusion Passenger" and "Union Station" are registered
7
- * trademarks of Phusion Holding B.V.
6
+ * "Passenger", "Phusion Passenger" and "Union Station" are registered
7
+ * trademarks of Phusion Holding B.V.
8
8
  *
9
- * Permission is hereby granted, free of charge, to any person obtaining a copy
10
- * of this software and associated documentation files (the "Software"), to deal
11
- * in the Software without restriction, including without limitation the rights
12
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
- * copies of the Software, and to permit persons to whom the Software is
14
- * furnished to do so, subject to the following conditions:
9
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ * of this software and associated documentation files (the "Software"), to deal
11
+ * in the Software without restriction, including without limitation the rights
12
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ * copies of the Software, and to permit persons to whom the Software is
14
+ * furnished to do so, subject to the following conditions:
15
15
  *
16
- * The above copyright notice and this permission notice shall be included in
17
- * all copies or substantial portions of the Software.
16
+ * The above copyright notice and this permission notice shall be included in
17
+ * all copies or substantial portions of the Software.
18
18
  *
19
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
- * THE SOFTWARE.
19
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
+ * THE SOFTWARE.
26
26
  */
27
27
  #ifndef _PASSENGER_CONSTANTS_H_
28
28
  #define _PASSENGER_CONSTANTS_H_
@@ -80,7 +80,7 @@
80
80
  #define PASSENGER_API_VERSION_MAJOR 0
81
81
  #define PASSENGER_API_VERSION_MINOR 3
82
82
  #define PASSENGER_DEFAULT_USER "nobody"
83
- #define PASSENGER_VERSION "5.0.30"
83
+ #define PASSENGER_VERSION "5.1.0"
84
84
  #define POOL_HELPER_THREAD_STACK_SIZE 262144
85
85
  #define PROCESS_SHUTDOWN_TIMEOUT 60
86
86
  #define PROCESS_SHUTDOWN_TIMEOUT_DISPLAY "1 minute"
@@ -89,7 +89,7 @@
89
89
  #define RPM_DEV_PACKAGE "passenger-devel"
90
90
  #define RPM_MAIN_PACKAGE "passenger"
91
91
  #define RPM_NGINX_PACKAGE "nginx"
92
- #define SERVER_INSTANCE_DIR_STRUCTURE_MAJOR_VERSION 3
92
+ #define SERVER_INSTANCE_DIR_STRUCTURE_MAJOR_VERSION 4
93
93
  #define SERVER_INSTANCE_DIR_STRUCTURE_MINOR_VERSION 0
94
94
  #define SERVER_INSTANCE_DIR_STRUCTURE_MIN_SUPPORTED_MINOR_VERSION 0
95
95
  #define SERVER_KIT_MAX_SERVER_ENDPOINTS 4
@@ -23,7 +23,10 @@
23
23
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
24
  # THE SOFTWARE.
25
25
 
26
- comment copyright_header_for(__FILE__)
26
+ # This file uses the cxxcodebuilder API. Learn more at:
27
+ # https://github.com/phusion/cxxcodebuilder
28
+
29
+ comment copyright_header_for(__FILE__), 1
27
30
 
28
31
  guard_macros '_PASSENGER_CONSTANTS_H_' do
29
32
  comment %q{
@@ -0,0 +1,977 @@
1
+ /*
2
+ * Phusion Passenger - https://www.phusionpassenger.com/
3
+ * Copyright (c) 2010-2016 Phusion Holding B.V.
4
+ *
5
+ * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
+ * trademarks of Phusion Holding B.V.
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+
27
+ #include <Crypto.h>
28
+ #include <modp_b64.h>
29
+ #include <Logging.h>
30
+ #include <string>
31
+ #include <Utils/SystemTime.h>
32
+ #include <Utils/StrIntUtils.h>
33
+
34
+ #if BOOST_OS_MACOS
35
+ #else
36
+ #include <openssl/aes.h>
37
+ #endif
38
+
39
+ #define AES_KEY_BYTESIZE (256/8)
40
+ #define AES_CBC_IV_BYTESIZE (128/8)
41
+
42
+ namespace Passenger {
43
+
44
+ using namespace std;
45
+ using namespace boost;
46
+ using namespace oxt;
47
+
48
+ #if BOOST_OS_MACOS
49
+
50
+ Crypto::Crypto() {
51
+ }
52
+
53
+ Crypto::~Crypto() {
54
+ }
55
+
56
+ CFDictionaryRef Crypto::createQueryDict(const char *label) {
57
+ if (kSecClassIdentity != NULL) {
58
+ const size_t size = 5L;
59
+ CFTypeRef keys[size];
60
+ CFTypeRef values[size];
61
+ CFDictionaryRef queryDict;
62
+ CFStringRef cfLabel = CFStringCreateWithCString(NULL, label,
63
+ kCFStringEncodingUTF8);
64
+
65
+ /* Set up our search criteria and expected results: */
66
+ values[0] = kSecClassIdentity; /* we want a certificate and a key */
67
+ keys[0] = kSecClass;
68
+ values[1] = kCFBooleanTrue; /* we need a reference */
69
+ keys[1] = kSecReturnRef;
70
+ values[2] = kSecMatchLimitOne; /* one is enough, thanks */
71
+ keys[2] = kSecMatchLimit;
72
+ /* identity searches need a SecPolicyRef in order to work */
73
+ values[3] = SecPolicyCreateSSL(false, NULL);
74
+ keys[3] = kSecMatchPolicy;
75
+ values[4] = cfLabel;
76
+ keys[4] = kSecMatchSubjectWholeString;
77
+ queryDict = CFDictionaryCreate(NULL, (const void **) keys,
78
+ (const void **) values, size,
79
+ &kCFCopyStringDictionaryKeyCallBacks,
80
+ &kCFTypeDictionaryValueCallBacks);
81
+ CFRelease(values[3]);
82
+ CFRelease(cfLabel);
83
+
84
+ return queryDict;
85
+ }
86
+ return NULL;
87
+ }
88
+
89
+ OSStatus Crypto::lookupKeychainItem(const char *label, SecIdentityRef *oIdentity) {
90
+ OSStatus status = errSecItemNotFound;
91
+
92
+ CFDictionaryRef queryDict = createQueryDict(label);
93
+ if (queryDict) {
94
+ /* Do we have a match? */
95
+ status = SecItemCopyMatching(queryDict, (CFTypeRef *) oIdentity);
96
+ CFRelease(queryDict);
97
+ }
98
+ return status;
99
+ }
100
+
101
+ SecAccessRef Crypto::createAccess(const char *cLabel) {
102
+ SecAccessRef access = NULL;
103
+ CFStringRef label = CFStringCreateWithCString(NULL, cLabel, kCFStringEncodingUTF8);
104
+ if (SecAccessCreate(label, NULL, &access)) {
105
+ logError("SecAccessCreate failed.");
106
+ CFRelease(label);
107
+ return NULL;
108
+ }
109
+ CFRelease(label);
110
+ return access;
111
+ }
112
+
113
+ OSStatus Crypto::copyIdentityFromPKCS12File(const char *cPath,
114
+ const char *cPassword,
115
+ const char *cLabel) {
116
+ OSStatus status = errSecItemNotFound;
117
+ CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL,
118
+ (const UInt8 *) cPath, strlen(cPath), false);
119
+ CFStringRef password = cPassword ? CFStringCreateWithCString(NULL,
120
+ cPassword, kCFStringEncodingUTF8) : NULL;
121
+
122
+ CFReadStreamRef cfrs = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
123
+ SecTransformRef readTransform = SecTransformCreateReadTransformWithReadStream(cfrs);
124
+ CFErrorRef error = NULL;
125
+ CFDataRef pkcsData = (CFDataRef) SecTransformExecute(readTransform, &error);
126
+ if (error != NULL) {
127
+ logFreeErrorExtended("ReadTransform", error);
128
+ return status;
129
+ }
130
+
131
+ SecAccessRef access = createAccess(cLabel);
132
+ CFTypeRef cKeys[] = {kSecImportExportPassphrase, kSecImportExportAccess};
133
+ CFTypeRef cValues[] = {password, access};
134
+ CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues, 2L, NULL, NULL);
135
+ CFArrayRef items = NULL;
136
+
137
+ /* Here we go: */
138
+ status = SecPKCS12Import(pkcsData, options, &items);
139
+ if (!(status == noErr && items && CFArrayGetCount(items))) {
140
+ string suffix = string("Please check for a certificate labeled: ") + cLabel + " in your keychain, and remove the associated private key. For more help please read: https://www.phusionpassenger.com/library/admin/standalone/mac_keychain_popups.html";
141
+ string prefix = "Loading Passenger Cert failed";
142
+ if (status == noErr) {
143
+ status = errSecAuthFailed;
144
+ logError( prefix + ". " + suffix );
145
+ }else{
146
+ CFStringRef str = SecCopyErrorMessageString(status, NULL);
147
+ logError( prefix + ": " + CFStringGetCStringPtr(str, kCFStringEncodingUTF8) + "\n" + suffix );
148
+ CFRelease(str);
149
+ }
150
+ }
151
+
152
+ if (items) {
153
+ CFRelease(items);
154
+ }
155
+ CFRelease(options);
156
+ CFRelease(access);
157
+ if (pkcsData) {
158
+ CFRelease(pkcsData);
159
+ }
160
+ CFRelease(readTransform);
161
+ CFRelease(cfrs);
162
+ if (password) {
163
+ CFRelease(password);
164
+ }
165
+ CFRelease(url);
166
+ return status;
167
+ }
168
+
169
+ void Crypto::killKey(const char *cLabel) {
170
+ SecIdentityRef id = NULL;
171
+ OSStatus status = lookupKeychainItem(cLabel, &id);
172
+ if (status != errSecItemNotFound) {
173
+
174
+ CFArrayRef itemList = CFArrayCreate(NULL, (const void **) &id, 1, NULL);
175
+ CFTypeRef keys[] = { kSecClass, kSecMatchItemList, kSecMatchLimit };
176
+ CFTypeRef values[] = { kSecClassIdentity, itemList, kSecMatchLimitAll };
177
+
178
+ CFDictionaryRef dict = CFDictionaryCreate(NULL, keys, values, 3L, NULL, NULL);
179
+ OSStatus oserr = SecItemDelete(dict);
180
+ if (oserr) {
181
+ CFStringRef str = SecCopyErrorMessageString(oserr, NULL);
182
+ logError(string("Removing Passenger Cert from keychain failed: ") + CFStringGetCStringPtr(str, kCFStringEncodingUTF8) +
183
+ " Please remove the private key from the certificate labeled " + cLabel + " in your keychain.");
184
+ CFRelease(str);
185
+ }
186
+ CFRelease(dict);
187
+ CFRelease(itemList);
188
+ } else {
189
+ CFStringRef str = SecCopyErrorMessageString(status, NULL);
190
+ logError(string("Finding Passenger Cert failed: ") + CFStringGetCStringPtr(str, kCFStringEncodingUTF8) );
191
+ CFRelease(str);
192
+ }
193
+ }
194
+
195
+ bool Crypto::preAuthKey(const char *path, const char *passwd, const char *cLabel) {
196
+ SecIdentityRef id = NULL;
197
+ if (lookupKeychainItem(cLabel, &id) == errSecItemNotFound) {
198
+ OSStatus oserr = SecKeychainSetUserInteractionAllowed(false);
199
+ if (oserr) {
200
+ CFStringRef str = SecCopyErrorMessageString(oserr, NULL);
201
+ logError(string("Disabling GUI Keychain interaction failed: ") + CFStringGetCStringPtr(str, kCFStringEncodingUTF8));
202
+ CFRelease(str);
203
+ }
204
+ oserr = copyIdentityFromPKCS12File(path, passwd, cLabel);
205
+ bool success = (noErr == oserr);
206
+ if (!success) {
207
+ CFStringRef str = SecCopyErrorMessageString(oserr, NULL);
208
+ logError(string("Pre authorizing the Passenger client certificate failed: ") + CFStringGetCStringPtr(str, kCFStringEncodingUTF8));
209
+ CFRelease(str);
210
+ }
211
+ oserr = SecKeychainSetUserInteractionAllowed(true);
212
+ if (oserr) {
213
+ //This is really bad, we should probably ask the user to reboot.
214
+ CFStringRef str = SecCopyErrorMessageString(oserr, NULL);
215
+ logError(string("Re-enabling GUI Keychain interaction failed with error: ") + CFStringGetCStringPtr(str, kCFStringEncodingUTF8) +
216
+ " Please reboot as soon as possible, thanks.");
217
+ CFRelease(str);
218
+ }
219
+ return success;
220
+ } else {
221
+ logError(string("Passenger client certificate was found in the keychain unexpectedly, you may see keychain popups until you remove the private key from the certificate labeled ") + cLabel + " in your keychain.");
222
+ if (id) {
223
+ CFRelease(id);
224
+ }
225
+ return false;
226
+ }
227
+ }
228
+
229
+ bool Crypto::generateRandomChars(unsigned char *rndChars, int rndLen) {
230
+ FILE *fPtr = fopen("/dev/random", "r");
231
+ if (fPtr == NULL) {
232
+ CFIndex errNum = errno;
233
+ char* errMsg = strerror(errno);
234
+ const UInt8 numKeys = 4;
235
+ CFTypeRef userInfoKeys[numKeys] = { kCFErrorFilePathKey,
236
+ kCFErrorLocalizedDescriptionKey,
237
+ kCFErrorLocalizedFailureReasonKey,
238
+ kCFErrorLocalizedRecoverySuggestionKey };
239
+ CFTypeRef userInfoValues[numKeys] = { CFSTR("/dev/random"),
240
+ CFSTR("Couldn't open file for reading."),
241
+ CFStringCreateWithCStringNoCopy(NULL, errMsg, kCFStringEncodingUTF8, NULL),
242
+ CFSTR("Have you tried turning it off and on again?") };
243
+
244
+ CFErrorRef error = CFErrorCreateWithUserInfoKeysAndValues(NULL, kCFErrorDomainOSStatus, errNum, userInfoKeys, userInfoValues, numKeys);
245
+ logFreeErrorExtended("SecVerifyTransformCreate", error);
246
+ return false;
247
+ }
248
+ for (int i = 0; i < rndLen; i++) {
249
+ rndChars[i] = fgetc(fPtr);
250
+ }
251
+ fclose(fPtr);
252
+
253
+ return true;
254
+ }
255
+
256
+ bool Crypto::generateAndAppendNonce(string &nonce) {
257
+ nonce.append(toString(SystemTime::getUsec()));
258
+
259
+ int rndLen = 16;
260
+ unsigned char rndChars[rndLen];
261
+
262
+ if (generateRandomChars(rndChars, rndLen)) {
263
+ char rndChars64[rndLen * 2];
264
+ modp_b64_encode(rndChars64, (const char *) rndChars, rndLen);
265
+
266
+ nonce.append(rndChars64);
267
+ return true;
268
+ } else {
269
+ return false;
270
+ }
271
+ }
272
+
273
+ CFDataRef Crypto::genIV(size_t ivSize) {
274
+ UInt8 *ivBytesPtr = (UInt8*) malloc(ivSize);//freed when iv is freed
275
+ if (generateRandomChars(ivBytesPtr, ivSize)) {
276
+ return CFDataCreateWithBytesNoCopy(NULL, ivBytesPtr, ivSize, kCFAllocatorMalloc);
277
+ } else {
278
+ return NULL;
279
+ }
280
+ }
281
+
282
+ bool Crypto::getKeyBytes(SecKeyRef cryptokey, void **target, size_t &len) {
283
+ const CSSM_KEY *cssmKey;
284
+ CSSM_WRAP_KEY wrappedKey = {{0}};
285
+
286
+ CSSM_CSP_HANDLE cspHandle = 0;
287
+ CSSM_CC_HANDLE ccHandle = 0;
288
+
289
+ const CSSM_ACCESS_CREDENTIALS *creds;
290
+ CSSM_RETURN error = SecKeyGetCredentials(cryptokey,
291
+ CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED,
292
+ kSecCredentialTypeDefault, &creds);
293
+ if (error != CSSM_OK) { cssmPerror("SecKeyGetCredentials", error); }
294
+
295
+ error = SecKeyGetCSSMKey(cryptokey, &cssmKey);
296
+ if (error != CSSM_OK) { cssmPerror("SecKeyGetCSSMKey", error); }
297
+
298
+ error = SecKeyGetCSPHandle(cryptokey, &cspHandle);
299
+ if (error != CSSM_OK) { cssmPerror("SecKeyGetCSPHandle", error); }
300
+
301
+ error = CSSM_CSP_CreateSymmetricContext(cspHandle,
302
+ CSSM_ALGID_NONE,
303
+ CSSM_ALGMODE_NONE,
304
+ creds,
305
+ NULL,
306
+ NULL,
307
+ CSSM_PADDING_NONE,
308
+ 0,
309
+ &ccHandle);
310
+ if (error != CSSM_OK) { cssmPerror("CSSM_CSP_CreateSymmetricContext",error); }
311
+
312
+ CSSM_WrapKey(ccHandle,
313
+ creds,
314
+ cssmKey,
315
+ NULL,
316
+ &wrappedKey);
317
+ cssmPerror("CSSM_WrapKey", error);
318
+
319
+ CSSM_DeleteContext(ccHandle);
320
+
321
+ len = wrappedKey.KeyData.Length;
322
+
323
+ return innerMemoryBridge(wrappedKey.KeyData.Data,target,wrappedKey.KeyData.Length);
324
+ }
325
+
326
+ bool Crypto::encryptAES256(char *dataChars, size_t dataLen, AESEncResult &aesEnc) {
327
+ CFErrorRef error = NULL;
328
+ bool retVal = false;
329
+
330
+ CFNumberRef cfSize = NULL;
331
+ CFDictionaryRef parameters = NULL;
332
+ SecKeyRef cryptokey = NULL;
333
+ CFDataRef iv = NULL;
334
+ SecTransformRef encrypt = NULL;
335
+ CFDataRef message = NULL;
336
+ CFDataRef enc = NULL;
337
+
338
+ do {
339
+ UInt32 size = kSecAES256; // c++ is dumb
340
+ CFNumberRef cfSize = CFNumberCreate(NULL, kCFNumberSInt32Type, &size);
341
+ CFTypeRef cKeys[] = {kSecAttrKeyType, kSecAttrKeySizeInBits};
342
+ CFTypeRef cValues[] = {kSecAttrKeyTypeAES, cfSize};
343
+ CFDictionaryRef parameters = CFDictionaryCreate(NULL, cKeys, cValues, 2L, NULL, NULL);
344
+ if (parameters == NULL) {
345
+ logError("CFDictionaryCreate failed.");
346
+ retVal = false;
347
+ break;
348
+ }
349
+
350
+ SecKeyRef cryptokey = SecKeyGenerateSymmetric(parameters, &error);
351
+ if (error != NULL) {
352
+ logFreeErrorExtended("SecKeyGenerateSymmetric", error);
353
+ retVal = false;
354
+ break;
355
+ }
356
+
357
+ if (!getKeyBytes(cryptokey, (void **) &aesEnc.key, aesEnc.keyLen)) {
358
+ retVal = false;
359
+ break;
360
+ }
361
+
362
+ CFDataRef iv = genIV(AES_CBC_IV_BYTESIZE);
363
+ if (iv == NULL) {
364
+ logError("genIV failed.");
365
+ retVal = false;
366
+ break;
367
+ } else if (!memoryBridge(iv, (void **) &aesEnc.iv, aesEnc.ivLen)) {
368
+ retVal = false;
369
+ break;
370
+ }
371
+
372
+ SecTransformRef encrypt = SecEncryptTransformCreate(cryptokey, &error);
373
+ if (error != NULL) {
374
+ logFreeErrorExtended("SecEncryptTransformCreate", error);
375
+ retVal = false;
376
+ break;
377
+ }
378
+ SecTransformSetAttribute(encrypt, kSecIVKey, iv, &error);
379
+ if (error != NULL) {
380
+ logFreeErrorExtended("SecTransformSetAttribute", error);
381
+ retVal = false;
382
+ break;
383
+ }
384
+ CFDataRef message = CFDataCreateWithBytesNoCopy(NULL,
385
+ (UInt8*) dataChars,
386
+ dataLen,
387
+ kCFAllocatorNull);
388
+ SecTransformSetAttribute(encrypt, kSecTransformInputAttributeName, message, &error);
389
+ if (error != NULL) {
390
+ logFreeErrorExtended("SecTransformSetAttribute", error);
391
+ retVal = false;
392
+ break;
393
+ }
394
+ CFDataRef enc = (CFDataRef) SecTransformExecute(encrypt, &error);
395
+ if (error != NULL) {
396
+ logFreeErrorExtended("SecTransformExecute", error);
397
+ retVal = false;
398
+ break;
399
+ }
400
+
401
+ if (!memoryBridge(enc, (void **) &aesEnc.encrypted, aesEnc.encryptedLen)) {
402
+ retVal = false;
403
+ break;
404
+ }
405
+ retVal = true;
406
+ } while (false);
407
+
408
+ if (enc) { CFRelease(enc); }
409
+ if (message) { CFRelease(message); }
410
+ if (encrypt) { CFRelease(encrypt); }
411
+ if (iv) { CFRelease(iv); }
412
+ if (cryptokey) { CFRelease(cryptokey); }
413
+ if (parameters) { CFRelease(parameters); }
414
+ if (cfSize) { CFRelease(cfSize); }
415
+
416
+ return retVal;
417
+ }
418
+
419
+ void Crypto::freeAESEncrypted(AESEncResult &aesEnc) {
420
+ if (aesEnc.encrypted != NULL) {
421
+ free(aesEnc.encrypted);
422
+ aesEnc.encrypted = NULL;
423
+ }
424
+ if (aesEnc.iv != NULL) {
425
+ free(aesEnc.iv);
426
+ aesEnc.iv = NULL;
427
+ }
428
+ if (aesEnc.key != NULL) {
429
+ memset(aesEnc.key, 0, aesEnc.keyLen);
430
+ free(aesEnc.key);
431
+ aesEnc.key = NULL;
432
+ }
433
+ }
434
+
435
+ bool Crypto::encryptRSA(unsigned char *dataChars, size_t dataLen,
436
+ string encryptPubKeyPath, unsigned char **encryptedCharsPtr, size_t &encryptedLen) {
437
+ bool retVal = false;
438
+ CFErrorRef error = NULL;
439
+ SecKeyRef rsaPubKey = loadPubKey(encryptPubKeyPath.c_str());
440
+
441
+ CFDataRef aesKeyData = NULL;
442
+ SecTransformRef rsaEncryptContext = NULL;
443
+ CFDataRef encryptedKey = NULL;
444
+
445
+ do {
446
+ if (rsaPubKey == NULL) {
447
+ logError("loadPubKey failed");
448
+ retVal = false;
449
+ break;
450
+ }
451
+
452
+ aesKeyData = CFDataCreateWithBytesNoCopy(NULL, (UInt8*) dataChars, dataLen, kCFAllocatorNull);
453
+ if (aesKeyData == NULL) {
454
+ logError("CFDataCreateWithBytesNoCopy failed");
455
+ retVal = false;
456
+ break;
457
+ }
458
+
459
+ rsaEncryptContext = SecEncryptTransformCreate(rsaPubKey, &error);
460
+ if (error) {
461
+ logFreeErrorExtended("SecEncryptTransformCreate", error);
462
+ retVal = false;
463
+ break;
464
+ }
465
+ SecTransformSetAttribute(rsaEncryptContext,
466
+ kSecPaddingKey,
467
+ kSecPaddingOAEPKey,
468
+ &error);
469
+ if (error) {
470
+ logFreeErrorExtended("SecTransformSetAttribute", error);
471
+ retVal = false;
472
+ break;
473
+ }
474
+
475
+ SecTransformSetAttribute(rsaEncryptContext, kSecTransformInputAttributeName, aesKeyData, &error);
476
+ if (error) {
477
+ logFreeErrorExtended("SecTransformSetAttribute", error);
478
+ retVal = false;
479
+ break;
480
+ }
481
+ encryptedKey = (CFDataRef) SecTransformExecute(rsaEncryptContext, &error);
482
+ if (error) {
483
+ logFreeErrorExtended("SecTransformExecute", error);
484
+ retVal = false;
485
+ break;
486
+ }
487
+
488
+ if (!memoryBridge(encryptedKey, (void **) encryptedCharsPtr, encryptedLen)) {
489
+ retVal = false;
490
+ break;
491
+ }
492
+ retVal = true;
493
+ } while (false);
494
+
495
+ if (encryptedKey) { CFRelease(encryptedKey); }
496
+ if (rsaEncryptContext) { CFRelease(rsaEncryptContext); }
497
+ if (aesKeyData) { CFRelease(aesKeyData); }
498
+ if (rsaPubKey) { CFRelease(rsaPubKey); }
499
+
500
+ return retVal;
501
+ }
502
+
503
+ bool Crypto::memoryBridge(CFDataRef input, void **target, size_t &len) {
504
+ len = CFDataGetLength(input);
505
+ return innerMemoryBridge((void *) CFDataGetBytePtr(input), target, len);
506
+ }
507
+
508
+ bool Crypto::innerMemoryBridge(void *input, void **target, size_t len){
509
+ *target = malloc(len);
510
+ if (*target == NULL) {
511
+ logError("malloc failed: " + toString(len));
512
+ return false;
513
+ }
514
+ memcpy(*target, input, len);
515
+ return true;
516
+ }
517
+
518
+ bool Crypto::verifySignature(string signaturePubKeyPath, char *signatureChars, int signatureLen, string data) {
519
+ SecKeyRef rsaPubKey = NULL;
520
+ bool result = false;
521
+
522
+ SecTransformRef verifier = NULL;
523
+ CFNumberRef cfSize = NULL;
524
+ do {
525
+ rsaPubKey = loadPubKey(signaturePubKeyPath.c_str());
526
+ if (rsaPubKey == NULL) {
527
+ logError("Failed to load public key at " + signaturePubKeyPath);
528
+ break;
529
+ }
530
+
531
+ CFDataRef signatureRef = CFDataCreateWithBytesNoCopy(NULL, (UInt8*) signatureChars, signatureLen, kCFAllocatorNull);
532
+
533
+ CFDataRef dataRef = CFDataCreateWithBytesNoCopy(NULL, (UInt8*) data.c_str(), data.length(), kCFAllocatorNull);
534
+
535
+ CFErrorRef error = NULL;
536
+ verifier = SecVerifyTransformCreate(rsaPubKey, signatureRef, &error);
537
+ if (error) {
538
+ logFreeErrorExtended("SecVerifyTransformCreate", error);
539
+ result = -20;
540
+ break;
541
+ }
542
+
543
+ SecTransformSetAttribute(verifier, kSecTransformInputAttributeName, dataRef, &error);
544
+ if (error) {
545
+ logFreeErrorExtended("SecTransformSetAttribute InputName", error);
546
+ result = -21;
547
+ break;
548
+ }
549
+
550
+ SecTransformSetAttribute(verifier, kSecDigestTypeAttribute, kSecDigestSHA2, &error);
551
+ if (error) {
552
+ logFreeErrorExtended("SecTransformSetAttribute DigestType", error);
553
+ result = -22;
554
+ break;
555
+ }
556
+
557
+ UInt32 size = kSecAES256; // c++ is dumb
558
+ cfSize = CFNumberCreate(NULL, kCFNumberSInt32Type, &size);
559
+ SecTransformSetAttribute(verifier, kSecDigestLengthAttribute, cfSize, &error);
560
+ if (error) {
561
+ logFreeErrorExtended("SecTransformSetAttribute DigestLength", error);
562
+ result = -23;
563
+ break;
564
+ }
565
+
566
+ CFTypeRef verifyResult = SecTransformExecute(verifier, &error);
567
+ if (error) {
568
+ logFreeErrorExtended("SecTransformExecute", error);
569
+ result = -24;
570
+ break;
571
+ }
572
+
573
+ result = (verifyResult == kCFBooleanTrue);
574
+ } while(0);
575
+
576
+ if (cfSize) {
577
+ CFRelease(cfSize);
578
+ }
579
+ if (verifier) {
580
+ CFRelease(verifier);
581
+ }
582
+ freePubKey(rsaPubKey);
583
+
584
+ return result;
585
+ }
586
+
587
+ PUBKEY_TYPE Crypto::loadPubKey(const char *filename) {
588
+ SecKeyRef pubKey = NULL;
589
+ CFDataRef keyData = NULL;
590
+ CFURLRef url = NULL;
591
+ CFReadStreamRef cfrs = NULL;
592
+ SecTransformRef readTransform = NULL;
593
+ CFArrayRef temparray = NULL;
594
+ do {
595
+ url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
596
+ (UInt8*) filename, strlen(filename), false);
597
+ if (url == NULL) {
598
+ logError("CFURLCreateFromFileSystemRepresentation failed.");
599
+ break;
600
+ }
601
+
602
+ cfrs = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
603
+ if (cfrs == NULL) {
604
+ logError("CFReadStreamCreateWithFile failed");
605
+ break;
606
+ }
607
+
608
+ readTransform = SecTransformCreateReadTransformWithReadStream(cfrs);
609
+ if (readTransform == NULL) {
610
+ logError("SecTransformCreateReadTransformWithReadStream failed");
611
+ break;
612
+ }
613
+ CFErrorRef error = NULL;
614
+ keyData = (CFDataRef) SecTransformExecute(readTransform, &error);
615
+ if (keyData == NULL) {
616
+ logError("SecTransformExecute failed to get keyData");
617
+ break;
618
+ }
619
+ if (error) {
620
+ logFreeErrorExtended("SecTransformExecute", error);
621
+ break;
622
+ }
623
+
624
+ SecExternalItemType itemType = kSecItemTypePublicKey;
625
+ SecExternalFormat externalFormat = kSecFormatPEMSequence;
626
+ OSStatus oserr = SecItemImport(keyData,
627
+ NULL, // filename or extension
628
+ &externalFormat, // See SecExternalFormat for details
629
+ &itemType,
630
+ 0, // See SecItemImportExportFlags for details, Note that PEM formatting
631
+ // is determined internally via inspection of the incoming data, so
632
+ // the kSecItemPemArmour flag is ignored.
633
+ NULL,
634
+ NULL, // Don't import into a keychain
635
+ &temparray);
636
+ if (oserr) {
637
+ CFStringRef str = SecCopyErrorMessageString(oserr, NULL);
638
+ logError(string("SecItemImport: ") + CFStringGetCStringPtr(str, kCFStringEncodingUTF8));
639
+ CFRelease(str);
640
+ break;
641
+ }
642
+ pubKey = (SecKeyRef) CFArrayGetValueAtIndex(temparray, 0);
643
+ CFRetain(pubKey); //bump ref count, now we own this and need to release it eventually
644
+ } while (0);
645
+
646
+ if (keyData) {
647
+ CFRelease(keyData); //might be wrong to release here, not sure if SecItemImport makes a copy of the bytes, it looks like it does
648
+ //https://opensource.apple.com/source/libsecurity_keychain/libsecurity_keychain-55035/lib/SecImport.cpp
649
+ //http://opensource.apple.com//source/libsecurity_keychain/libsecurity_keychain-14/lib/SecImportExportPem.cpp
650
+ }
651
+ if (temparray) {
652
+ CFRelease(temparray);
653
+ }
654
+ if (readTransform) {
655
+ CFRelease(readTransform);
656
+ }
657
+ if (cfrs) {
658
+ CFRelease(cfrs);
659
+ }
660
+ if (url) {
661
+ CFRelease(url);
662
+ }
663
+
664
+ return pubKey;
665
+ }
666
+
667
+ void Crypto::freePubKey(PUBKEY_TYPE pubKey) {
668
+ if (pubKey) {
669
+ CFRelease(pubKey);
670
+ }
671
+ }
672
+
673
+ void Crypto::logFreeErrorExtended(const StaticString &prefix, CFErrorRef &error) {
674
+ if (error) {
675
+ CFStringRef description = CFErrorCopyDescription((CFErrorRef) error);
676
+ CFStringRef failureReason = CFErrorCopyFailureReason((CFErrorRef) error);
677
+ CFStringRef recoverySuggestion = CFErrorCopyRecoverySuggestion((CFErrorRef) error);
678
+
679
+ logError(prefix +
680
+ ": " + CFStringGetCStringPtr(description, kCFStringEncodingUTF8) +
681
+ "; " + CFStringGetCStringPtr(failureReason, kCFStringEncodingUTF8) +
682
+ "; " + CFStringGetCStringPtr(recoverySuggestion, kCFStringEncodingUTF8)
683
+ );
684
+
685
+ CFRelease(recoverySuggestion);
686
+ CFRelease(failureReason);
687
+ CFRelease(description);
688
+ CFRelease(error);
689
+ error = NULL;
690
+ }
691
+ }
692
+
693
+ #else
694
+
695
+ Crypto::Crypto() {
696
+ OpenSSL_add_all_algorithms();
697
+ }
698
+
699
+ Crypto::~Crypto() {
700
+ EVP_cleanup();
701
+ }
702
+
703
+ bool Crypto::generateAndAppendNonce(string &nonce) {
704
+ nonce.append(toString(SystemTime::getUsec()));
705
+
706
+ int rndLen = 16;
707
+ unsigned char rndChars[rndLen];
708
+
709
+ if (1 != RAND_bytes(rndChars, rndLen)) {
710
+ logErrorExtended("RAND_bytes failed for nonce");
711
+ return false;
712
+ }
713
+
714
+ char rndChars64[rndLen * 2];
715
+ modp_b64_encode(rndChars64, (const char *) rndChars, rndLen);
716
+
717
+ nonce.append(rndChars64);
718
+ return true;
719
+ }
720
+
721
+ bool Crypto::encryptAES256(char *dataChars, size_t dataLen, AESEncResult &aesEnc) {
722
+ assert(dataLen > 0 && dataChars != NULL);
723
+
724
+ aesEnc.encrypted = NULL;
725
+ aesEnc.key = NULL;
726
+ aesEnc.iv = NULL;
727
+
728
+ bool result = false;
729
+ EVP_CIPHER_CTX *aesEncryptContext = NULL;
730
+
731
+ do {
732
+ // 1. Generate random key (secret) and init vector to be used for the encryption
733
+ aesEnc.keyLen = AES_KEY_BYTESIZE;
734
+ aesEnc.key = (unsigned char*) OPENSSL_malloc(aesEnc.keyLen);
735
+ if (aesEnc.key == NULL) {
736
+ logErrorExtended("OPENSSL_malloc failed");
737
+ break;
738
+ }
739
+
740
+ aesEnc.ivLen = AES_CBC_IV_BYTESIZE;
741
+ aesEnc.iv = (unsigned char*) malloc(aesEnc.ivLen); // not secret
742
+ if (aesEnc.iv == NULL) {
743
+ logError("malloc for IV failed");
744
+ break;
745
+ }
746
+
747
+ if (1 != RAND_bytes(aesEnc.key, aesEnc.keyLen)) {
748
+ logErrorExtended("RAND_bytes failed for AES key");
749
+ break;
750
+ }
751
+ if (1 != RAND_bytes(aesEnc.iv, aesEnc.ivLen)) {
752
+ logErrorExtended("RAND_bytes failed for IV");
753
+ break;
754
+ }
755
+
756
+ // 2. Get ready to encrypt
757
+ aesEncryptContext = EVP_CIPHER_CTX_new();
758
+ if (aesEncryptContext == NULL) {
759
+ logErrorExtended("EVP_CIPHER_CTX_new failed");
760
+ break;
761
+ }
762
+
763
+ aesEnc.encrypted = (unsigned char*) malloc(dataLen + AES_BLOCK_SIZE); // not secret
764
+ if (aesEnc.encrypted == NULL) {
765
+ logError("malloc for encryptedChars failed " + toString(dataLen + AES_BLOCK_SIZE));
766
+ break;
767
+ }
768
+
769
+ // 3. Let's go
770
+ if (1 != EVP_EncryptInit_ex(aesEncryptContext, EVP_aes_256_cbc(), NULL, aesEnc.key, aesEnc.iv)) {
771
+ logErrorExtended("EVP_EncryptInit_ex failed");
772
+ break;
773
+ }
774
+
775
+ size_t blockLength = 0;
776
+ size_t writeIdx = 0;
777
+ if (1 != EVP_EncryptUpdate(aesEncryptContext, aesEnc.encrypted + writeIdx, (int *) &blockLength, (unsigned char*) dataChars, dataLen)) {
778
+ logErrorExtended("EVP_EncryptUpdate failed");
779
+ break;
780
+ }
781
+ writeIdx += blockLength;
782
+
783
+ if (1 != EVP_EncryptFinal_ex(aesEncryptContext, aesEnc.encrypted + writeIdx, (int *) &blockLength)) {
784
+ logErrorExtended("EVP_EncryptFinal_ex failed");
785
+ break;
786
+ }
787
+ writeIdx += blockLength;
788
+ aesEnc.encryptedLen = writeIdx;
789
+
790
+ result = true;
791
+ } while(0);
792
+
793
+ if (!result) {
794
+ // convenience: free the result if it's not valid anyway
795
+ freeAESEncrypted(aesEnc);
796
+ }
797
+
798
+ if (aesEncryptContext != NULL) {
799
+ EVP_CIPHER_CTX_free(aesEncryptContext);
800
+ }
801
+
802
+ return result;
803
+ }
804
+
805
+ void Crypto::freeAESEncrypted(AESEncResult &aesEnc) {
806
+ if (aesEnc.encrypted != NULL) {
807
+ free(aesEnc.encrypted);
808
+ aesEnc.encrypted = NULL;
809
+ }
810
+ if (aesEnc.iv != NULL) {
811
+ free(aesEnc.iv);
812
+ aesEnc.iv = NULL;
813
+ }
814
+
815
+ // Secret parts were allocated differently
816
+ if (aesEnc.key != NULL) {
817
+ OPENSSL_free(aesEnc.key);
818
+ aesEnc.key = NULL;
819
+ }
820
+ }
821
+
822
+ bool Crypto::encryptRSA(unsigned char *dataChars, size_t dataLen,
823
+ string encryptPubKeyPath, unsigned char **encryptedCharsPtr, size_t &encryptedLen) {
824
+ RSA *rsaPubKey = NULL;
825
+ EVP_PKEY *rsaPubKeyEVP = NULL;
826
+ EVP_PKEY_CTX *ctx = NULL;
827
+ bool result = false;
828
+
829
+ do {
830
+ // 1. Get the RSA public key to encrypt with
831
+ rsaPubKey = loadPubKey(encryptPubKeyPath.c_str());
832
+ if (rsaPubKey == NULL) {
833
+ logError("Failed to load public key at " + encryptPubKeyPath);
834
+ break;
835
+ }
836
+
837
+ rsaPubKeyEVP = EVP_PKEY_new();
838
+ if (1 != EVP_PKEY_assign_RSA(rsaPubKeyEVP, rsaPubKey)) {
839
+ logErrorExtended("EVP_PKEY_assign_RSA");
840
+ freePubKey(rsaPubKey); // since it's not tied to EVP key yet
841
+ break;
842
+ }
843
+
844
+ // 2. Prepare for encryption
845
+ ctx = EVP_PKEY_CTX_new(rsaPubKeyEVP, NULL);
846
+ if (ctx == NULL) {
847
+ logErrorExtended("EVP_PKEY_CTX_new");
848
+ break;
849
+ }
850
+ if (1 != EVP_PKEY_encrypt_init(ctx)) {
851
+ logErrorExtended("EVP_PKEY_encrypt_init");
852
+ break;
853
+ }
854
+ if (1 != EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING)) {
855
+ logErrorExtended("EVP_PKEY_CTX_set_rsa_padding");
856
+ break;
857
+ }
858
+
859
+ // 3. First encrypt to get encryptedLen
860
+ if (1 != EVP_PKEY_encrypt(ctx, NULL, &encryptedLen, (unsigned char *) dataChars, dataLen)) {
861
+ logErrorExtended("EVP_PKEY_encrypt (first)");
862
+ break;
863
+ }
864
+
865
+ *encryptedCharsPtr = (unsigned char *) malloc(encryptedLen); // not secret
866
+ if (*encryptedCharsPtr == NULL) {
867
+ logError("malloc for encryptedChars failed" + toString(encryptedLen));
868
+ break;
869
+ }
870
+
871
+ if (1 != EVP_PKEY_encrypt(ctx, (unsigned char *) *encryptedCharsPtr, &encryptedLen,
872
+ (unsigned char *) dataChars, AES_KEY_BYTESIZE)) {
873
+ logErrorExtended("EVP_PKEY_encrypt (second)");
874
+ break;
875
+ }
876
+
877
+ result = true;
878
+ } while (0);
879
+
880
+ if (ctx != NULL) {
881
+ EVP_PKEY_CTX_free(ctx);
882
+ }
883
+ if (rsaPubKeyEVP != NULL) {
884
+ EVP_PKEY_free(rsaPubKeyEVP); // also frees the rsaPubKey
885
+ }
886
+
887
+ return result;
888
+ }
889
+
890
+ bool Crypto::verifySignature(string signaturePubKeyPath, char *signatureChars, int signatureLen, string data) {
891
+ RSA *rsaPubKey = NULL;
892
+ EVP_PKEY *rsaPubKeyEVP = NULL;
893
+ EVP_MD_CTX *mdctx = NULL;
894
+ bool result = false;
895
+
896
+ do {
897
+ rsaPubKey = loadPubKey(signaturePubKeyPath.c_str());
898
+ if (rsaPubKey == NULL) {
899
+ logError("Failed to load public key at " + signaturePubKeyPath);
900
+ break;
901
+ }
902
+
903
+ rsaPubKeyEVP = EVP_PKEY_new();
904
+ if (!EVP_PKEY_assign_RSA(rsaPubKeyEVP, rsaPubKey)) {
905
+ freePubKey(rsaPubKey);
906
+ logErrorExtended("EVP_PKEY_assign_RSA");
907
+ break;
908
+ }
909
+
910
+ if (!(mdctx = EVP_MD_CTX_create())) {
911
+ logErrorExtended("EVP_MD_CTX_create");
912
+ break;
913
+ }
914
+
915
+ if (1 != EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, rsaPubKeyEVP)) {
916
+ logErrorExtended("EVP_DigestVerifyInit");
917
+ break;
918
+ }
919
+
920
+ if (1 != EVP_DigestVerifyUpdate(mdctx, data.c_str(), data.length())) {
921
+ logErrorExtended("EVP_DigestVerifyUpdate");
922
+ break;
923
+ }
924
+
925
+ if (1 != EVP_DigestVerifyFinal(mdctx, (unsigned char *) signatureChars, signatureLen)) {
926
+ logErrorExtended("EVP_DigestVerifyFinal");
927
+ break;
928
+ }
929
+
930
+ result = true;
931
+ } while(0);
932
+
933
+ if (mdctx) {
934
+ EVP_MD_CTX_destroy(mdctx);
935
+ }
936
+
937
+ if (rsaPubKeyEVP) {
938
+ EVP_PKEY_free(rsaPubKeyEVP);
939
+ // freePubKey not needed, already free by EVP_PKEY_free.
940
+ }
941
+
942
+ return result;
943
+ }
944
+
945
+ PUBKEY_TYPE Crypto::loadPubKey(const char *filename) {
946
+ FILE *fp = fopen(filename, "rb");
947
+ if (fp == NULL) {
948
+ return NULL;
949
+ }
950
+
951
+ RSA *rsa = RSA_new();
952
+ rsa = PEM_read_RSA_PUBKEY(fp, &rsa, NULL, NULL);
953
+ fclose(fp);
954
+ return rsa;
955
+ }
956
+
957
+ void Crypto::freePubKey(PUBKEY_TYPE pubKey) {
958
+ if (pubKey) {
959
+ RSA_free(pubKey);
960
+ }
961
+ }
962
+
963
+ void Crypto::logErrorExtended(const StaticString &prefix) {
964
+ char err[500];
965
+ ERR_load_crypto_strings();
966
+ ERR_error_string(ERR_get_error(), err);
967
+ P_ERROR(prefix << ": " << err);
968
+ ERR_free_strings();
969
+ }
970
+
971
+ #endif
972
+
973
+ void Crypto::logError(const StaticString &error) {
974
+ P_ERROR(error);
975
+ }
976
+
977
+ } // namespace Passenger