1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 // To show that this test actually tests something, you can change
20 // MANUAL_OPENSSL_INIT to 0 to cause automatic OpenSSL init/cleanup,
21 // which will cause the test to fail
22 #define MANUAL_OPENSSL_INIT 1
23 #ifdef _WIN32
24 #include <winsock2.h>
25 #endif
26 
27 #include <boost/test/unit_test.hpp>
28 #include <openssl/evp.h>
29 #include <thrift/transport/TSSLSocket.h>
30 
31 using namespace apache::thrift::transport;
32 
make_isolated_sslsocketfactory()33 void make_isolated_sslsocketfactory() {
34   // Here we create an isolated TSSLSocketFactory to ensure the
35   // constructor and destructor of TSSLSocketFactory get run.  Thus
36   // without manual initialization normally OpenSSL would be
37   // uninitialized after this function.
38   TSSLSocketFactory factory;
39 }
40 
openssl_init()41 void openssl_init() {
42 #if MANUAL_OPENSSL_INIT
43   TSSLSocketFactory::setManualOpenSSLInitialization(true);
44   initializeOpenSSL();
45 #endif
46 }
47 
openssl_cleanup()48 void openssl_cleanup() {
49 #if MANUAL_OPENSSL_INIT
50   cleanupOpenSSL();
51 #endif
52 }
53 
test_openssl_availability()54 void test_openssl_availability() {
55   // Check whether Thrift leaves OpenSSL functionality available after
56   // the last TSSLSocketFactory is destroyed when manual
57   // initialization is set
58   openssl_init();
59   make_isolated_sslsocketfactory();
60 
61   // The following function is one that will fail if OpenSSL is
62   // uninitialized.  It might also fail on very old versions of
63   // OpenSSL...
64   const EVP_MD* md = EVP_get_digestbyname("SHA256");
65   BOOST_CHECK(md != nullptr);
66   openssl_cleanup();
67 }
68 
69 #ifdef BOOST_TEST_DYN_LINK
init_unit_test_suite()70 bool init_unit_test_suite() {
71   boost::unit_test::test_suite* suite = &boost::unit_test::framework::master_test_suite();
72   suite->p_name.value = "OpenSSLManualInit";
73 
74   suite->add(BOOST_TEST_CASE(test_openssl_availability));
75 
76   return true;
77 }
78 
main(int argc,char * argv[])79 int main( int argc, char* argv[] ) {
80   return ::boost::unit_test::unit_test_main(&init_unit_test_suite,argc,argv);
81 }
82 #else
init_unit_test_suite(int argc,char * argv[])83 boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) {
84   THRIFT_UNUSED_VARIABLE(argc);
85   THRIFT_UNUSED_VARIABLE(argv);
86   boost::unit_test::test_suite* suite = &boost::unit_test::framework::master_test_suite();
87   suite->p_name.value = "OpenSSLManualInit";
88 
89   suite->add(BOOST_TEST_CASE(test_openssl_availability));
90 
91   return nullptr;
92 }
93 #endif