mirror of https://github.com/openssl/openssl.git
				
				
				
			Add a test to dynamically load and unload the libraries
This should demonstrate that the atexit() handling is working properly (or at least not crashing) on process exit. Reviewed-by: Tim Hudson <tjh@openssl.org>
This commit is contained in:
		
							parent
							
								
									5836780f43
								
							
						
					
					
						commit
						b987d748e4
					
				|  | @ -282,6 +282,12 @@ IF[{- !$disabled{tests} -}] | |||
|     DEPEND[dtls_mtu_test]=../libcrypto ../libssl | ||||
|   ENDIF | ||||
| 
 | ||||
|   IF[{- !disabled{shared} -}] | ||||
|     PROGRAMS_NO_INST=shlibloadtest | ||||
|     SOURCE[shlibloadtest]=shlibloadtest.c | ||||
|     INCLUDE[shlibloadtest]=../include | ||||
|   ENDIF | ||||
| 
 | ||||
|   IF[{- $disabled{shared} -}] | ||||
|     PROGRAMS_NO_INST=wpackettest cipher_overhead_test | ||||
|     SOURCE[wpackettest]=wpackettest.c testutil.c | ||||
|  |  | |||
|  | @ -0,0 +1,37 @@ | |||
| #! /usr/bin/env perl | ||||
| # Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. | ||||
| # | ||||
| # Licensed under the OpenSSL license (the "License").  You may not use | ||||
| # this file except in compliance with the License.  You can obtain a copy | ||||
| # in the file LICENSE in the source distribution or at | ||||
| # https://www.openssl.org/source/license.html | ||||
| 
 | ||||
| 
 | ||||
| use OpenSSL::Test qw/:DEFAULT bldtop_dir/; | ||||
| use OpenSSL::Test::Utils; | ||||
| 
 | ||||
| #Load configdata.pm | ||||
| 
 | ||||
| BEGIN { | ||||
|     setup("test_shlibload"); | ||||
| } | ||||
| use lib bldtop_dir('.'); | ||||
| use configdata; | ||||
| 
 | ||||
| plan skip_all => "Test only supported in a shared build" if disabled("shared"); | ||||
| 
 | ||||
| plan tests => 3; | ||||
| 
 | ||||
| ok(run(test(["shlibloadtest", "-crypto_first", | ||||
|              $unified_info{sharednames}->{libcrypto}, | ||||
|              $unified_info{sharednames}->{libssl}])), | ||||
|    "running shlibloadtest -crypto_first"); | ||||
| ok(run(test(["shlibloadtest", "-ssl_first", | ||||
|              $unified_info{sharednames}->{libcrypto}, | ||||
|              $unified_info{sharednames}->{libssl}])), | ||||
|    "running shlibloadtest -ssl_first"); | ||||
| ok(run(test(["shlibloadtest", "-just_crypto", | ||||
|              $unified_info{sharednames}->{libcrypto}, | ||||
|              $unified_info{sharednames}->{libssl}])), | ||||
|    "running shlibloadtest -just_crypto"); | ||||
| 
 | ||||
|  | @ -0,0 +1,243 @@ | |||
| /*
 | ||||
|  * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. | ||||
|  * | ||||
|  * Licensed under the OpenSSL license (the "License").  You may not use | ||||
|  * this file except in compliance with the License.  You can obtain a copy | ||||
|  * in the file LICENSE in the source distribution or at | ||||
|  * https://www.openssl.org/source/license.html
 | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <openssl/opensslv.h> | ||||
| 
 | ||||
| #define SSL_CTX_NEW "SSL_CTX_new" | ||||
| #define SSL_CTX_FREE "SSL_CTX_free" | ||||
| #define TLS_METHOD "TLS_method" | ||||
| 
 | ||||
| #define ERR_GET_ERROR "ERR_get_error" | ||||
| #define OPENSSL_VERSION_NUM_FUNC "OpenSSL_version_num" | ||||
| 
 | ||||
| typedef struct ssl_ctx_st SSL_CTX; | ||||
| typedef struct ssl_method_st SSL_METHOD; | ||||
| typedef const SSL_METHOD * (*TLS_method_t)(void); | ||||
| typedef SSL_CTX * (*SSL_CTX_new_t)(const SSL_METHOD *meth); | ||||
| typedef void (*SSL_CTX_free_t)(SSL_CTX *); | ||||
| 
 | ||||
| typedef unsigned long (*ERR_get_error_t)(void); | ||||
| typedef unsigned long (*OpenSSL_version_num_t)(void); | ||||
| 
 | ||||
| TLS_method_t TLS_method; | ||||
| SSL_CTX_new_t SSL_CTX_new; | ||||
| SSL_CTX_free_t SSL_CTX_free; | ||||
| 
 | ||||
| ERR_get_error_t ERR_get_error; | ||||
| OpenSSL_version_num_t OpenSSL_version_num; | ||||
| 
 | ||||
| 
 | ||||
| #ifdef DSO_DLFCN | ||||
| 
 | ||||
| # include <dlfcn.h> | ||||
| 
 | ||||
| typedef void * SHLIB; | ||||
| typedef void * SHLIB_SYM; | ||||
| 
 | ||||
| # define SHARED_LIBRARY_SUFFIX ".so" | ||||
| 
 | ||||
| static int shlib_load(char *filename, SHLIB *lib) | ||||
| { | ||||
|     char *tmpfile; | ||||
|     size_t filenamelen = strlen(filename); | ||||
| 
 | ||||
|     /* Total length = base filename len + suffix len + 1 for NULL terminator */ | ||||
|     tmpfile = malloc(filenamelen + sizeof(SHARED_LIBRARY_SUFFIX) + 1); | ||||
|     if (tmpfile == NULL) | ||||
|         return 0; | ||||
|     strcpy(tmpfile, filename); | ||||
|     strcpy(tmpfile + filenamelen, SHARED_LIBRARY_SUFFIX); | ||||
| 
 | ||||
|     *lib = dlopen(tmpfile, RTLD_GLOBAL | RTLD_LAZY); | ||||
|     free(tmpfile); | ||||
| 
 | ||||
|     if (*lib == NULL) | ||||
|         return 0; | ||||
| 
 | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| static int shlib_sym(SHLIB lib, const char *symname, SHLIB_SYM *sym) | ||||
| { | ||||
|     *sym = dlsym(lib, symname); | ||||
| 
 | ||||
|     return *sym != NULL; | ||||
| } | ||||
| 
 | ||||
| static int shlib_close(SHLIB lib) | ||||
| { | ||||
|     if (dlclose(lib) != 0) | ||||
|         return 0; | ||||
| 
 | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| #elif defined(DSO_WIN32) | ||||
| 
 | ||||
| # include <windows.h> | ||||
| 
 | ||||
| typedef HINSTANCE SHLIB; | ||||
| typedef void * SHLIB_SYM; | ||||
| 
 | ||||
| static int shlib_load(char *filename, SHLIB *lib) | ||||
| { | ||||
|     *lib = LoadLibraryA(filename); | ||||
|     if (*lib == NULL) | ||||
|         return 0; | ||||
| 
 | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| static int shlib_sym(SHLIB lib, const char *symname, SHLIB_SYM *sym) | ||||
| { | ||||
|     *sym = (SHLIB_SYM)GetProcAddress(lib, symname); | ||||
| 
 | ||||
|     return *sym != NULL; | ||||
| } | ||||
| 
 | ||||
| static int shlib_close(SHLIB lib) | ||||
| { | ||||
|     if (FreeLibrary(lib) == 0) | ||||
|         return 0; | ||||
| 
 | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| /* The test is only currently implemented for DSO_DLFCN and DSO_WIN32 */ | ||||
| #if defined(DSO_DLFCN) || defined(DSO_WIN32) | ||||
| 
 | ||||
| # define CRYPTO_FIRST_OPT    "-crypto_first" | ||||
| # define SSL_FIRST_OPT       "-ssl_first" | ||||
| # define JUST_CRYPTO_OPT     "-just_crypto" | ||||
| 
 | ||||
| enum test_types_en { | ||||
|     CRYPTO_FIRST, | ||||
|     SSL_FIRST, | ||||
|     JUST_CRYPTO | ||||
| }; | ||||
| 
 | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|     SHLIB ssllib, cryptolib; | ||||
|     SSL_CTX *ctx; | ||||
|     union { | ||||
|         void (*func) (void); | ||||
|         SHLIB_SYM sym; | ||||
|     } tls_method_sym, ssl_ctx_new_sym, ssl_ctx_free_sym, err_get_error_sym, | ||||
|     openssl_version_num_sym; | ||||
|     enum test_types_en test_type; | ||||
|     int i; | ||||
| 
 | ||||
|     if (argc != 4) { | ||||
|         printf("Unexpected number of arguments\n"); | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     if (strcmp(argv[1], CRYPTO_FIRST_OPT) == 0) { | ||||
|         test_type = CRYPTO_FIRST; | ||||
|     } else if (strcmp(argv[1], SSL_FIRST_OPT) == 0) { | ||||
|             test_type = SSL_FIRST; | ||||
|     } else if (strcmp(argv[1], JUST_CRYPTO_OPT) == 0) { | ||||
|             test_type = JUST_CRYPTO; | ||||
|     } else { | ||||
|         printf("Unrecognised argument\n"); | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     for (i = 0; i < 2; i++) { | ||||
|         if ((i == 0 && (test_type == CRYPTO_FIRST | ||||
|                        || test_type == JUST_CRYPTO)) | ||||
|                || (i == 1 && test_type == SSL_FIRST)) { | ||||
|             if (!shlib_load(argv[2], &cryptolib)) { | ||||
|                 printf("Unable to load libcrypto\n"); | ||||
|                 return 1; | ||||
|             } | ||||
|         } | ||||
|         if ((i == 0 && test_type == SSL_FIRST) | ||||
|                 || (i == 1 && test_type == CRYPTO_FIRST)) { | ||||
|             if (!shlib_load(argv[3], &ssllib)) { | ||||
|                 printf("Unable to load libssl\n"); | ||||
|                 return 1; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (test_type != JUST_CRYPTO) { | ||||
|         if (!shlib_sym(ssllib, TLS_METHOD, &tls_method_sym.sym) | ||||
|                 || !shlib_sym(ssllib, SSL_CTX_NEW, &ssl_ctx_new_sym.sym) | ||||
|                 || !shlib_sym(ssllib, SSL_CTX_FREE, &ssl_ctx_free_sym.sym)) { | ||||
|             printf("Unable to load ssl symbols\n"); | ||||
|             return 1; | ||||
|         } | ||||
| 
 | ||||
|         TLS_method = (TLS_method_t)tls_method_sym.func; | ||||
|         SSL_CTX_new = (SSL_CTX_new_t)ssl_ctx_new_sym.func; | ||||
|         SSL_CTX_free = (SSL_CTX_free_t)ssl_ctx_free_sym.func; | ||||
| 
 | ||||
|         ctx = SSL_CTX_new(TLS_method()); | ||||
|         if (ctx == NULL) { | ||||
|             printf("Unable to create SSL_CTX\n"); | ||||
|             return 1; | ||||
|         } | ||||
|         SSL_CTX_free(ctx); | ||||
|     } | ||||
| 
 | ||||
|     if (!shlib_sym(cryptolib, ERR_GET_ERROR, &err_get_error_sym.sym) | ||||
|             || !shlib_sym(cryptolib, OPENSSL_VERSION_NUM_FUNC, | ||||
|                           &openssl_version_num_sym.sym)) { | ||||
|         printf("Unable to load crypto symbols\n"); | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     ERR_get_error = (ERR_get_error_t)err_get_error_sym.func; | ||||
|     OpenSSL_version_num = (OpenSSL_version_num_t)openssl_version_num_sym.func; | ||||
| 
 | ||||
|     if (ERR_get_error() != 0) { | ||||
|         printf("Unexpected error in error queue\n"); | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     if (OpenSSL_version_num() != OPENSSL_VERSION_NUMBER) { | ||||
|         printf("Unexpected library version loaded\n"); | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     for (i = 0; i < 2; i++) { | ||||
|         if ((i == 0 && test_type == CRYPTO_FIRST) | ||||
|                 || (i == 1 && test_type == SSL_FIRST)) { | ||||
|             if (!shlib_close(ssllib)) { | ||||
|                 printf("Unable to close libssl\n"); | ||||
|                 return 1; | ||||
|             } | ||||
|         } | ||||
|         if ((i == 0 && (test_type == SSL_FIRST | ||||
|                        || test_type == JUST_CRYPTO)) | ||||
|                 || (i == 1 && test_type == CRYPTO_FIRST)) { | ||||
|             if (!shlib_close(cryptolib)) { | ||||
|                 printf("Unable to close libcrypto\n"); | ||||
|                 return 1; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     printf("Success\n"); | ||||
|     return 0; | ||||
| } | ||||
| #else | ||||
| int main(void) | ||||
| { | ||||
|     printf("Test not implemented on this platform\n"); | ||||
|     return 0; | ||||
| } | ||||
| #endif | ||||
		Loading…
	
		Reference in New Issue