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.
- checksums.yaml +4 -4
- data/CHANGELOG +30 -1
- data/CONTRIBUTING.md +1 -1
- data/CONTRIBUTORS +2 -0
- data/bin/passenger-install-nginx-module +18 -13
- data/build/agent.rb +1 -0
- data/build/basics.rb +1 -0
- data/build/cxx_tests.rb +6 -1
- data/build/misc.rb +3 -0
- data/build/packaging.rb +5 -17
- data/build/support/cxx_dependency_map.rb +100 -0
- data/build/support/vendor/cxxcodebuilder/lib/cxxcodebuilder/builder.rb +4 -1
- data/build/test_basics.rb +12 -2
- data/dev/ci/run_travis.sh +6 -2
- data/doc/Users guide Apache.html +7 -2
- data/doc/Users guide Apache.txt +4 -0
- data/resources/templates/error_layout.css +70 -84
- data/resources/templates/error_layout.html.template +84 -93
- data/resources/templates/standalone/http.erb +17 -13
- data/resources/templates/standalone/server.erb +2 -1
- data/resources/templates/undisclosed_error.html.template +52 -51
- data/resources/update_check_client_cert.p12 +0 -0
- data/resources/update_check_client_cert.pem +89 -0
- data/resources/update_check_server_pubkey.pem +14 -0
- data/src/agent/Core/ApplicationPool/ErrorRenderer.h +15 -1
- data/src/agent/Core/Controller.h +3 -2
- data/src/agent/Core/Controller/CheckoutSession.cpp +5 -4
- data/src/agent/Core/Controller/ForwardResponse.cpp +1 -1
- data/src/agent/Core/Controller/InitRequest.cpp +2 -0
- data/src/agent/Core/Controller/InitializationAndShutdown.cpp +1 -0
- data/src/agent/Core/Controller/Request.h +1 -0
- data/src/agent/Core/CoreMain.cpp +99 -2
- data/src/agent/Core/OptionParser.h +18 -1
- data/src/agent/Core/SecurityUpdateChecker.h +559 -0
- data/src/agent/Shared/Base.cpp +6 -1
- data/src/agent/TempDirToucher/TempDirToucherMain.cpp +52 -0
- data/src/agent/Watchdog/InstanceDirToucher.cpp +1 -2
- data/src/agent/Watchdog/WatchdogMain.cpp +31 -40
- data/src/apache2_module/Configuration.cpp +12 -0
- data/src/apache2_module/Configuration.hpp +5 -0
- data/src/apache2_module/ConfigurationCommands.cpp +19 -19
- data/src/apache2_module/ConfigurationCommands.cpp.cxxcodebuilder +2 -2
- data/src/apache2_module/ConfigurationFields.hpp +19 -19
- data/src/apache2_module/ConfigurationFields.hpp.cxxcodebuilder +2 -2
- data/src/apache2_module/ConfigurationSetters.cpp +19 -19
- data/src/apache2_module/ConfigurationSetters.cpp.cxxcodebuilder +2 -2
- data/src/apache2_module/CreateDirConfig.cpp +19 -19
- data/src/apache2_module/CreateDirConfig.cpp.cxxcodebuilder +2 -2
- data/src/apache2_module/Hooks.cpp +10 -1
- data/src/apache2_module/MergeDirConfig.cpp +19 -19
- data/src/apache2_module/MergeDirConfig.cpp.cxxcodebuilder +2 -2
- data/src/apache2_module/SetHeaders.cpp +19 -19
- data/src/apache2_module/SetHeaders.cpp.cxxcodebuilder +2 -2
- data/src/cxx_supportlib/Constants.h +22 -22
- data/src/cxx_supportlib/Constants.h.cxxcodebuilder +4 -1
- data/src/cxx_supportlib/Crypto.cpp +977 -0
- data/src/cxx_supportlib/Crypto.h +147 -0
- data/src/cxx_supportlib/InstanceDirectory.h +55 -2
- data/src/cxx_supportlib/Utils/Curl.h +24 -10
- data/src/cxx_supportlib/Utils/JsonUtils.h +1 -1
- data/src/cxx_supportlib/oxt/detail/spin_lock_darwin.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/system/error_code.hpp +3 -3
- data/src/cxx_supportlib/vendor-modified/jsoncpp/json-forwards.h +167 -92
- data/src/cxx_supportlib/vendor-modified/jsoncpp/json.h +1827 -1542
- data/src/cxx_supportlib/vendor-modified/jsoncpp/jsoncpp.cpp +4705 -3652
- data/src/cxx_supportlib/vendor-modified/libev/Changes +46 -15
- data/src/cxx_supportlib/vendor-modified/libev/LICENSE +1 -1
- data/src/cxx_supportlib/vendor-modified/libev/Makefile.in +215 -128
- data/src/cxx_supportlib/vendor-modified/libev/aclocal.m4 +466 -275
- data/src/cxx_supportlib/vendor-modified/libev/config.guess +312 -418
- data/src/cxx_supportlib/vendor-modified/libev/config.sub +246 -105
- data/src/cxx_supportlib/vendor-modified/libev/configure +276 -72
- data/src/cxx_supportlib/vendor-modified/libev/configure.ac +2 -1
- data/src/cxx_supportlib/vendor-modified/libev/depcomp +346 -185
- data/src/cxx_supportlib/vendor-modified/libev/ev++.h +1 -1
- data/src/cxx_supportlib/vendor-modified/libev/ev.c +530 -190
- data/src/cxx_supportlib/vendor-modified/libev/ev.h +23 -14
- data/src/cxx_supportlib/vendor-modified/libev/ev_epoll.c +12 -6
- data/src/cxx_supportlib/vendor-modified/libev/ev_kqueue.c +9 -5
- data/src/cxx_supportlib/vendor-modified/libev/ev_poll.c +6 -3
- data/src/cxx_supportlib/vendor-modified/libev/ev_port.c +8 -4
- data/src/cxx_supportlib/vendor-modified/libev/ev_select.c +4 -2
- data/src/cxx_supportlib/vendor-modified/libev/ev_vars.h +3 -2
- data/src/cxx_supportlib/vendor-modified/libev/ev_win32.c +3 -4
- data/src/cxx_supportlib/vendor-modified/libev/install-sh +433 -219
- data/src/cxx_supportlib/vendor-modified/libev/libev.m4 +6 -6
- data/src/cxx_supportlib/vendor-modified/libev/ltmain.sh +2 -2
- data/src/cxx_supportlib/vendor-modified/libev/missing +167 -288
- data/src/cxx_supportlib/vendor-modified/libev/mkinstalldirs +72 -21
- data/src/cxx_supportlib/vendor-modified/modp_b64.cpp +4 -106
- data/src/cxx_supportlib/vendor-modified/modp_b64_data.h +37 -1
- data/src/cxx_supportlib/vendor-modified/modp_b64_strict_aliasing.cpp +119 -0
- data/src/helper-scripts/node-loader.js +72 -1
- data/src/nginx_module/CacheLocationConfig.c +52 -19
- data/src/nginx_module/CacheLocationConfig.c.cxxcodebuilder +2 -2
- data/src/nginx_module/Configuration.c +26 -1
- data/src/nginx_module/Configuration.h +2 -0
- data/src/nginx_module/ConfigurationCommands.c +35 -19
- data/src/nginx_module/ConfigurationCommands.c.cxxcodebuilder +2 -2
- data/src/nginx_module/ContentHandler.c +1 -1
- data/src/nginx_module/CreateLocationConfig.c +22 -19
- data/src/nginx_module/CreateLocationConfig.c.cxxcodebuilder +2 -2
- data/src/nginx_module/LocationConfig.h +21 -19
- data/src/nginx_module/LocationConfig.h.cxxcodebuilder +2 -2
- data/src/nginx_module/MergeLocationConfig.c +25 -19
- data/src/nginx_module/MergeLocationConfig.c.cxxcodebuilder +2 -2
- data/src/nginx_module/ngx_http_passenger_module.c +8 -4
- data/src/ruby_supportlib/phusion_passenger.rb +9 -4
- data/src/ruby_supportlib/phusion_passenger/admin_tools/instance.rb +2 -2
- data/src/ruby_supportlib/phusion_passenger/admin_tools/instance_registry.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/common_library.rb +13 -0
- data/src/ruby_supportlib/phusion_passenger/config/nginx_engine_compiler.rb +5 -2
- data/src/ruby_supportlib/phusion_passenger/constants.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +15 -3
- data/src/ruby_supportlib/phusion_passenger/platform_info/crypto.rb +51 -0
- data/src/ruby_supportlib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +7 -0
- data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +17 -0
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb +4 -2
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +4 -0
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command/nginx_engine.rb +5 -0
- data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/app.rb +19 -10
- data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/base.rb +25 -0
- data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/gdb_controller.rb +38 -103
- data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/lldb_controller.rb +178 -0
- data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/utils.rb +94 -0
- data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/version.rb +2 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core.rb +2 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/version_data.rb +2 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.travis +5 -3
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.travis-with-sudo +9 -7
- 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/
|
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
|
-
*
|
3
|
-
*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2010-2016 Phusion Holding B.V.
|
4
4
|
*
|
5
|
-
*
|
6
|
-
*
|
5
|
+
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
|
+
* trademarks of Phusion Holding B.V.
|
7
7
|
*
|
8
|
-
*
|
9
|
-
*
|
10
|
-
*
|
11
|
-
*
|
12
|
-
*
|
13
|
-
*
|
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
|
-
*
|
16
|
-
*
|
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
|
-
*
|
19
|
-
*
|
20
|
-
*
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
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/
|
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
|
-
*
|
3
|
-
*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2010-2016 Phusion Holding B.V.
|
4
4
|
*
|
5
|
-
*
|
6
|
-
*
|
5
|
+
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
|
+
* trademarks of Phusion Holding B.V.
|
7
7
|
*
|
8
|
-
*
|
9
|
-
*
|
10
|
-
*
|
11
|
-
*
|
12
|
-
*
|
13
|
-
*
|
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
|
-
*
|
16
|
-
*
|
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
|
-
*
|
19
|
-
*
|
20
|
-
*
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
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/
|
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
|
-
*
|
3
|
-
*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2010-2016 Phusion Holding B.V.
|
4
4
|
*
|
5
|
-
*
|
6
|
-
*
|
5
|
+
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
|
+
* trademarks of Phusion Holding B.V.
|
7
7
|
*
|
8
|
-
*
|
9
|
-
*
|
10
|
-
*
|
11
|
-
*
|
12
|
-
*
|
13
|
-
*
|
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
|
-
*
|
16
|
-
*
|
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
|
-
*
|
19
|
-
*
|
20
|
-
*
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
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/
|
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
|
-
*
|
3
|
-
*
|
2
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
+
* Copyright (c) 2010-2016 Phusion Holding B.V.
|
4
4
|
*
|
5
|
-
*
|
6
|
-
*
|
5
|
+
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
6
|
+
* trademarks of Phusion Holding B.V.
|
7
7
|
*
|
8
|
-
*
|
9
|
-
*
|
10
|
-
*
|
11
|
-
*
|
12
|
-
*
|
13
|
-
*
|
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
|
-
*
|
16
|
-
*
|
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
|
-
*
|
19
|
-
*
|
20
|
-
*
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
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/
|
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
|
-
*
|
3
|
-
*
|
4
|
-
*
|
2
|
+
* encoding: utf-8
|
3
|
+
* Phusion Passenger - https://www.phusionpassenger.com/
|
4
|
+
* Copyright (c) 2010-2016 Phusion Holding B.V.
|
5
5
|
*
|
6
|
-
*
|
7
|
-
*
|
6
|
+
* "Passenger", "Phusion Passenger" and "Union Station" are registered
|
7
|
+
* trademarks of Phusion Holding B.V.
|
8
8
|
*
|
9
|
-
*
|
10
|
-
*
|
11
|
-
*
|
12
|
-
*
|
13
|
-
*
|
14
|
-
*
|
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
|
-
*
|
17
|
-
*
|
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
|
-
*
|
20
|
-
*
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
25
|
-
*
|
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
|
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
|
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
|
-
|
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
|