1 1.1 christos /* 2 1.1.1.7 christos * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos * 4 1.1.1.7 christos * Licensed under the Apache License 2.0 (the "License"). You may not use 5 1.1 christos * this file except in compliance with the License. You can obtain a copy 6 1.1 christos * in the file LICENSE in the source distribution or at 7 1.1 christos * https://www.openssl.org/source/license.html 8 1.1 christos */ 9 1.1 christos 10 1.1 christos #include <stdio.h> 11 1.1 christos #include <string.h> 12 1.1 christos #include <stdlib.h> 13 1.1 christos #include <openssl/opensslv.h> 14 1.1.1.4 christos #include <openssl/ssl.h> 15 1.1.1.7 christos #include <openssl/types.h> 16 1.1.1.7 christos #include "simpledynamic.h" 17 1.1 christos 18 1.1.1.4 christos typedef void DSO; 19 1.1 christos 20 1.1 christos typedef const SSL_METHOD * (*TLS_method_t)(void); 21 1.1 christos typedef SSL_CTX * (*SSL_CTX_new_t)(const SSL_METHOD *meth); 22 1.1 christos typedef void (*SSL_CTX_free_t)(SSL_CTX *); 23 1.1.1.5 christos typedef int (*OPENSSL_init_crypto_t)(uint64_t, void *); 24 1.1.1.5 christos typedef int (*OPENSSL_atexit_t)(void (*handler)(void)); 25 1.1 christos typedef unsigned long (*ERR_get_error_t)(void); 26 1.1.1.7 christos typedef unsigned long (*OPENSSL_version_major_t)(void); 27 1.1.1.7 christos typedef unsigned long (*OPENSSL_version_minor_t)(void); 28 1.1.1.7 christos typedef unsigned long (*OPENSSL_version_patch_t)(void); 29 1.1.1.4 christos typedef DSO * (*DSO_dsobyaddr_t)(void (*addr)(void), int flags); 30 1.1.1.4 christos typedef int (*DSO_free_t)(DSO *dso); 31 1.1 christos 32 1.1.1.4 christos typedef enum test_types_en { 33 1.1.1.4 christos CRYPTO_FIRST, 34 1.1.1.4 christos SSL_FIRST, 35 1.1.1.4 christos JUST_CRYPTO, 36 1.1.1.5 christos DSO_REFTEST, 37 1.1.1.5 christos NO_ATEXIT 38 1.1.1.4 christos } TEST_TYPE; 39 1.1 christos 40 1.1.1.4 christos static TEST_TYPE test_type; 41 1.1.1.4 christos static const char *path_crypto; 42 1.1.1.4 christos static const char *path_ssl; 43 1.1.1.5 christos static const char *path_atexit; 44 1.1 christos 45 1.1.1.7 christos #ifdef SD_INIT 46 1.1 christos 47 1.1.1.5 christos static int atexit_handler_done = 0; 48 1.1.1.5 christos 49 1.1.1.5 christos static void atexit_handler(void) 50 1.1.1.5 christos { 51 1.1.1.5 christos FILE *atexit_file = fopen(path_atexit, "w"); 52 1.1.1.5 christos 53 1.1.1.5 christos if (atexit_file == NULL) 54 1.1.1.5 christos return; 55 1.1.1.5 christos 56 1.1.1.5 christos fprintf(atexit_file, "atexit() run\n"); 57 1.1.1.5 christos fclose(atexit_file); 58 1.1.1.5 christos atexit_handler_done++; 59 1.1.1.5 christos } 60 1.1.1.5 christos 61 1.1.1.4 christos static int test_lib(void) 62 1.1 christos { 63 1.1.1.7 christos SD ssllib = SD_INIT; 64 1.1.1.7 christos SD cryptolib = SD_INIT; 65 1.1 christos SSL_CTX *ctx; 66 1.1 christos union { 67 1.1.1.4 christos void (*func)(void); 68 1.1.1.7 christos SD_SYM sym; 69 1.1.1.7 christos } symbols[5]; 70 1.1.1.4 christos TLS_method_t myTLS_method; 71 1.1.1.4 christos SSL_CTX_new_t mySSL_CTX_new; 72 1.1.1.4 christos SSL_CTX_free_t mySSL_CTX_free; 73 1.1.1.4 christos ERR_get_error_t myERR_get_error; 74 1.1.1.7 christos OPENSSL_version_major_t myOPENSSL_version_major; 75 1.1.1.7 christos OPENSSL_version_minor_t myOPENSSL_version_minor; 76 1.1.1.7 christos OPENSSL_version_patch_t myOPENSSL_version_patch; 77 1.1.1.5 christos OPENSSL_atexit_t myOPENSSL_atexit; 78 1.1.1.4 christos int result = 0; 79 1.1.1.4 christos 80 1.1.1.4 christos switch (test_type) { 81 1.1.1.4 christos case JUST_CRYPTO: 82 1.1.1.5 christos case DSO_REFTEST: 83 1.1.1.5 christos case NO_ATEXIT: 84 1.1.1.4 christos case CRYPTO_FIRST: 85 1.1.1.7 christos if (!sd_load(path_crypto, &cryptolib, SD_SHLIB)) { 86 1.1.1.5 christos fprintf(stderr, "Failed to load libcrypto\n"); 87 1.1.1.4 christos goto end; 88 1.1.1.5 christos } 89 1.1.1.5 christos if (test_type != CRYPTO_FIRST) 90 1.1.1.5 christos break; 91 1.1.1.5 christos /* Fall through */ 92 1.1.1.5 christos 93 1.1.1.4 christos case SSL_FIRST: 94 1.1.1.7 christos if (!sd_load(path_ssl, &ssllib, SD_SHLIB)) { 95 1.1.1.5 christos fprintf(stderr, "Failed to load libssl\n"); 96 1.1.1.4 christos goto end; 97 1.1.1.5 christos } 98 1.1.1.5 christos if (test_type != SSL_FIRST) 99 1.1.1.5 christos break; 100 1.1.1.7 christos if (!sd_load(path_crypto, &cryptolib, SD_SHLIB)) { 101 1.1.1.5 christos fprintf(stderr, "Failed to load libcrypto\n"); 102 1.1.1.4 christos goto end; 103 1.1.1.5 christos } 104 1.1.1.4 christos break; 105 1.1 christos } 106 1.1 christos 107 1.1.1.5 christos if (test_type == NO_ATEXIT) { 108 1.1.1.5 christos OPENSSL_init_crypto_t myOPENSSL_init_crypto; 109 1.1.1.5 christos 110 1.1.1.7 christos if (!sd_sym(cryptolib, "OPENSSL_init_crypto", &symbols[0].sym)) { 111 1.1.1.5 christos fprintf(stderr, "Failed to load OPENSSL_init_crypto symbol\n"); 112 1.1.1.5 christos goto end; 113 1.1.1.5 christos } 114 1.1.1.5 christos myOPENSSL_init_crypto = (OPENSSL_init_crypto_t)symbols[0].func; 115 1.1.1.5 christos if (!myOPENSSL_init_crypto(OPENSSL_INIT_NO_ATEXIT, NULL)) { 116 1.1.1.5 christos fprintf(stderr, "Failed to initialise libcrypto\n"); 117 1.1.1.5 christos goto end; 118 1.1.1.5 christos } 119 1.1.1.5 christos } 120 1.1.1.5 christos 121 1.1.1.5 christos if (test_type != JUST_CRYPTO 122 1.1.1.5 christos && test_type != DSO_REFTEST 123 1.1.1.5 christos && test_type != NO_ATEXIT) { 124 1.1.1.7 christos if (!sd_sym(ssllib, "TLS_method", &symbols[0].sym) 125 1.1.1.7 christos || !sd_sym(ssllib, "SSL_CTX_new", &symbols[1].sym) 126 1.1.1.7 christos || !sd_sym(ssllib, "SSL_CTX_free", &symbols[2].sym)) { 127 1.1.1.5 christos fprintf(stderr, "Failed to load libssl symbols\n"); 128 1.1.1.4 christos goto end; 129 1.1.1.5 christos } 130 1.1.1.4 christos myTLS_method = (TLS_method_t)symbols[0].func; 131 1.1.1.4 christos mySSL_CTX_new = (SSL_CTX_new_t)symbols[1].func; 132 1.1.1.4 christos mySSL_CTX_free = (SSL_CTX_free_t)symbols[2].func; 133 1.1.1.5 christos ctx = mySSL_CTX_new(myTLS_method()); 134 1.1.1.5 christos if (ctx == NULL) { 135 1.1.1.5 christos fprintf(stderr, "Failed to create SSL_CTX\n"); 136 1.1.1.4 christos goto end; 137 1.1.1.5 christos } 138 1.1.1.4 christos mySSL_CTX_free(ctx); 139 1.1.1.4 christos } 140 1.1.1.4 christos 141 1.1.1.7 christos if (!sd_sym(cryptolib, "ERR_get_error", &symbols[0].sym) 142 1.1.1.7 christos || !sd_sym(cryptolib, "OPENSSL_version_major", &symbols[1].sym) 143 1.1.1.7 christos || !sd_sym(cryptolib, "OPENSSL_version_minor", &symbols[2].sym) 144 1.1.1.7 christos || !sd_sym(cryptolib, "OPENSSL_version_patch", &symbols[3].sym) 145 1.1.1.7 christos || !sd_sym(cryptolib, "OPENSSL_atexit", &symbols[4].sym)) { 146 1.1.1.5 christos fprintf(stderr, "Failed to load libcrypto symbols\n"); 147 1.1.1.4 christos goto end; 148 1.1.1.5 christos } 149 1.1.1.4 christos myERR_get_error = (ERR_get_error_t)symbols[0].func; 150 1.1.1.5 christos if (myERR_get_error() != 0) { 151 1.1.1.5 christos fprintf(stderr, "Unexpected ERR_get_error() response\n"); 152 1.1.1.4 christos goto end; 153 1.1.1.5 christos } 154 1.1 christos 155 1.1.1.7 christos /* Library and header version should be identical in this test */ 156 1.1.1.7 christos myOPENSSL_version_major = (OPENSSL_version_major_t)symbols[1].func; 157 1.1.1.7 christos myOPENSSL_version_minor = (OPENSSL_version_minor_t)symbols[2].func; 158 1.1.1.7 christos myOPENSSL_version_patch = (OPENSSL_version_patch_t)symbols[3].func; 159 1.1.1.7 christos if (myOPENSSL_version_major() != OPENSSL_VERSION_MAJOR 160 1.1.1.7 christos || myOPENSSL_version_minor() != OPENSSL_VERSION_MINOR 161 1.1.1.7 christos || myOPENSSL_version_patch() != OPENSSL_VERSION_PATCH) { 162 1.1.1.5 christos fprintf(stderr, "Invalid library version number\n"); 163 1.1.1.4 christos goto end; 164 1.1.1.5 christos } 165 1.1.1.5 christos 166 1.1.1.7 christos myOPENSSL_atexit = (OPENSSL_atexit_t)symbols[4].func; 167 1.1.1.5 christos if (!myOPENSSL_atexit(atexit_handler)) { 168 1.1.1.5 christos fprintf(stderr, "Failed to register atexit handler\n"); 169 1.1.1.4 christos goto end; 170 1.1.1.5 christos } 171 1.1 christos 172 1.1.1.3 christos if (test_type == DSO_REFTEST) { 173 1.1.1.3 christos # ifdef DSO_DLFCN 174 1.1.1.4 christos DSO_dsobyaddr_t myDSO_dsobyaddr; 175 1.1.1.4 christos DSO_free_t myDSO_free; 176 1.1.1.4 christos 177 1.1.1.3 christos /* 178 1.1.1.3 christos * This is resembling the code used in ossl_init_base() and 179 1.1.1.3 christos * OPENSSL_atexit() to block unloading the library after dlclose(). 180 1.1.1.3 christos * We are not testing this on Windows, because it is done there in a 181 1.1.1.3 christos * completely different way. Especially as a call to DSO_dsobyaddr() 182 1.1.1.3 christos * will always return an error, because DSO_pathbyaddr() is not 183 1.1.1.3 christos * implemented there. 184 1.1.1.3 christos */ 185 1.1.1.7 christos if (!sd_sym(cryptolib, "DSO_dsobyaddr", &symbols[0].sym) 186 1.1.1.7 christos || !sd_sym(cryptolib, "DSO_free", &symbols[1].sym)) { 187 1.1.1.5 christos fprintf(stderr, "Unable to load DSO symbols\n"); 188 1.1.1.4 christos goto end; 189 1.1.1.5 christos } 190 1.1.1.3 christos 191 1.1.1.4 christos myDSO_dsobyaddr = (DSO_dsobyaddr_t)symbols[0].func; 192 1.1.1.4 christos myDSO_free = (DSO_free_t)symbols[1].func; 193 1.1.1.3 christos 194 1.1.1.3 christos { 195 1.1.1.3 christos DSO *hndl; 196 1.1.1.3 christos /* use known symbol from crypto module */ 197 1.1.1.5 christos hndl = myDSO_dsobyaddr((void (*)(void))myERR_get_error, 0); 198 1.1.1.5 christos if (hndl == NULL) { 199 1.1.1.5 christos fprintf(stderr, "DSO_dsobyaddr() failed\n"); 200 1.1.1.4 christos goto end; 201 1.1.1.5 christos } 202 1.1.1.4 christos myDSO_free(hndl); 203 1.1.1.3 christos } 204 1.1.1.3 christos # endif /* DSO_DLFCN */ 205 1.1.1.3 christos } 206 1.1.1.3 christos 207 1.1.1.7 christos if (!sd_close(cryptolib)) { 208 1.1.1.5 christos fprintf(stderr, "Failed to close libcrypto\n"); 209 1.1.1.5 christos goto end; 210 1.1.1.5 christos } 211 1.1.1.7 christos cryptolib = SD_INIT; 212 1.1.1.5 christos 213 1.1.1.5 christos if (test_type == CRYPTO_FIRST || test_type == SSL_FIRST) { 214 1.1.1.7 christos if (!sd_close(ssllib)) { 215 1.1.1.5 christos fprintf(stderr, "Failed to close libssl\n"); 216 1.1.1.4 christos goto end; 217 1.1.1.5 christos } 218 1.1.1.7 christos ssllib = SD_INIT; 219 1.1.1.4 christos } 220 1.1.1.4 christos 221 1.1.1.5 christos # if defined(OPENSSL_NO_PINSHARED) \ 222 1.1.1.5 christos && defined(__GLIBC__) \ 223 1.1.1.5 christos && defined(__GLIBC_PREREQ) \ 224 1.1.1.5 christos && defined(OPENSSL_SYS_LINUX) 225 1.1.1.5 christos # if __GLIBC_PREREQ(2, 3) 226 1.1.1.5 christos /* 227 1.1.1.5 christos * If we didn't pin the so then we are hopefully on a platform that supports 228 1.1.1.5 christos * running atexit() on so unload. If not we might crash. We know this is 229 1.1.1.5 christos * true on linux since glibc 2.2.3 230 1.1.1.5 christos */ 231 1.1.1.5 christos if (test_type != NO_ATEXIT && atexit_handler_done != 1) { 232 1.1.1.5 christos fprintf(stderr, "atexit() handler did not run\n"); 233 1.1.1.5 christos goto end; 234 1.1.1.5 christos } 235 1.1.1.5 christos # endif 236 1.1.1.5 christos # endif 237 1.1.1.5 christos 238 1.1.1.4 christos result = 1; 239 1.1.1.4 christos end: 240 1.1.1.7 christos if (cryptolib != SD_INIT) 241 1.1.1.7 christos sd_close(cryptolib); 242 1.1.1.7 christos if (ssllib != SD_INIT) 243 1.1.1.7 christos sd_close(ssllib); 244 1.1.1.4 christos return result; 245 1.1 christos } 246 1.1.1.4 christos #endif 247 1.1.1.4 christos 248 1.1.1.4 christos 249 1.1.1.5 christos /* 250 1.1.1.5 christos * shlibloadtest should not use the normal test framework because we don't want 251 1.1.1.5 christos * it to link against libcrypto (which the framework uses). The point of the 252 1.1.1.5 christos * test is to check dynamic loading and unloading of libcrypto/libssl. 253 1.1.1.5 christos */ 254 1.1.1.5 christos int main(int argc, char *argv[]) 255 1.1 christos { 256 1.1.1.5 christos const char *p; 257 1.1.1.5 christos 258 1.1.1.5 christos if (argc != 5) { 259 1.1.1.5 christos fprintf(stderr, "Incorrect number of arguments\n"); 260 1.1.1.5 christos return 1; 261 1.1.1.5 christos } 262 1.1.1.5 christos 263 1.1.1.5 christos p = argv[1]; 264 1.1.1.4 christos 265 1.1.1.4 christos if (strcmp(p, "-crypto_first") == 0) { 266 1.1.1.4 christos test_type = CRYPTO_FIRST; 267 1.1.1.4 christos } else if (strcmp(p, "-ssl_first") == 0) { 268 1.1.1.4 christos test_type = SSL_FIRST; 269 1.1.1.4 christos } else if (strcmp(p, "-just_crypto") == 0) { 270 1.1.1.4 christos test_type = JUST_CRYPTO; 271 1.1.1.4 christos } else if (strcmp(p, "-dso_ref") == 0) { 272 1.1.1.5 christos test_type = DSO_REFTEST; 273 1.1.1.5 christos } else if (strcmp(p, "-no_atexit") == 0) { 274 1.1.1.5 christos test_type = NO_ATEXIT; 275 1.1.1.4 christos } else { 276 1.1.1.5 christos fprintf(stderr, "Unrecognised argument\n"); 277 1.1.1.5 christos return 1; 278 1.1.1.5 christos } 279 1.1.1.5 christos path_crypto = argv[2]; 280 1.1.1.5 christos path_ssl = argv[3]; 281 1.1.1.5 christos path_atexit = argv[4]; 282 1.1.1.5 christos if (path_crypto == NULL || path_ssl == NULL) { 283 1.1.1.5 christos fprintf(stderr, "Invalid libcrypto/libssl path\n"); 284 1.1.1.5 christos return 1; 285 1.1.1.4 christos } 286 1.1.1.4 christos 287 1.1.1.7 christos #ifdef SD_INIT 288 1.1.1.5 christos if (!test_lib()) 289 1.1.1.5 christos return 1; 290 1.1 christos #endif 291 1.1.1.5 christos return 0; 292 1.1.1.4 christos } 293