Providerized libssl fallout: cleanup init
[openssl.git] / ssl / ssl_init.c
1 /*
2  * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include "e_os.h"
11
12 #include "internal/err.h"
13 #include <openssl/crypto.h>
14 #include <openssl/evp.h>
15 #include <openssl/trace.h>
16 #include "ssl_local.h"
17 #include "internal/thread_once.h"
18
19 static int stopped;
20
21 static void ssl_library_stop(void);
22
23 static CRYPTO_ONCE ssl_base = CRYPTO_ONCE_STATIC_INIT;
24 static int ssl_base_inited = 0;
25 DEFINE_RUN_ONCE_STATIC(ossl_init_ssl_base)
26 {
27 #ifndef OPENSSL_NO_COMP
28     OSSL_TRACE(INIT, "ossl_init_ssl_base: "
29                "SSL_COMP_get_compression_methods()\n");
30     /*
31      * This will initialise the built-in compression algorithms. The value
32      * returned is a STACK_OF(SSL_COMP), but that can be discarded safely
33      */
34     SSL_COMP_get_compression_methods();
35 #endif
36     ssl_sort_cipher_list();
37     OSSL_TRACE(INIT,"ossl_init_ssl_base: SSL_add_ssl_module()\n");
38     /*
39      * We ignore an error return here. Not much we can do - but not that bad
40      * either. We can still safely continue.
41      */
42     OPENSSL_atexit(ssl_library_stop);
43     ssl_base_inited = 1;
44     return 1;
45 }
46
47 static CRYPTO_ONCE ssl_strings = CRYPTO_ONCE_STATIC_INIT;
48 static int ssl_strings_inited = 0;
49 DEFINE_RUN_ONCE_STATIC(ossl_init_load_ssl_strings)
50 {
51     /*
52      * OPENSSL_NO_AUTOERRINIT is provided here to prevent at compile time
53      * pulling in all the error strings during static linking
54      */
55 #if !defined(OPENSSL_NO_ERR) && !defined(OPENSSL_NO_AUTOERRINIT)
56     OSSL_TRACE(INIT, "ossl_init_load_ssl_strings: ERR_load_SSL_strings()\n");
57     ERR_load_SSL_strings();
58     ssl_strings_inited = 1;
59 #endif
60     return 1;
61 }
62
63 DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_ssl_strings,
64                            ossl_init_load_ssl_strings)
65 {
66     /* Do nothing in this case */
67     return 1;
68 }
69
70 static void ssl_library_stop(void)
71 {
72     /* Might be explicitly called and also by atexit */
73     if (stopped)
74         return;
75     stopped = 1;
76
77     if (ssl_base_inited) {
78 #ifndef OPENSSL_NO_COMP
79         OSSL_TRACE(INIT, "ssl_library_stop: "
80                    "ssl_comp_free_compression_methods_int()\n");
81         ssl_comp_free_compression_methods_int();
82 #endif
83     }
84
85     if (ssl_strings_inited) {
86         OSSL_TRACE(INIT, "ssl_library_stop: err_free_strings_int()\n");
87         /*
88          * If both crypto and ssl error strings are inited we will end up
89          * calling err_free_strings_int() twice - but that's ok. The second
90          * time will be a no-op. It's easier to do that than to try and track
91          * between the two libraries whether they have both been inited.
92          */
93         err_free_strings_int();
94     }
95 }
96
97 /*
98  * If this function is called with a non NULL settings value then it must be
99  * called prior to any threads making calls to any OpenSSL functions,
100  * i.e. passing a non-null settings value is assumed to be single-threaded.
101  */
102 int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS * settings)
103 {
104     static int stoperrset = 0;
105
106     if (stopped) {
107         if (!stoperrset) {
108             /*
109              * We only ever set this once to avoid getting into an infinite
110              * loop where the error system keeps trying to init and fails so
111              * sets an error etc
112              */
113             stoperrset = 1;
114             SSLerr(SSL_F_OPENSSL_INIT_SSL, ERR_R_INIT_FAIL);
115         }
116         return 0;
117     }
118
119     opts |= OPENSSL_INIT_ADD_ALL_CIPHERS
120          |  OPENSSL_INIT_ADD_ALL_DIGESTS;
121 #ifndef OPENSSL_NO_AUTOLOAD_CONFIG
122     if ((opts & OPENSSL_INIT_NO_LOAD_CONFIG) == 0)
123         opts |= OPENSSL_INIT_LOAD_CONFIG;
124 #endif
125
126     if (!OPENSSL_init_crypto(opts, settings))
127         return 0;
128
129     if (!RUN_ONCE(&ssl_base, ossl_init_ssl_base))
130         return 0;
131
132     if ((opts & OPENSSL_INIT_NO_LOAD_SSL_STRINGS)
133         && !RUN_ONCE_ALT(&ssl_strings, ossl_init_no_load_ssl_strings,
134                          ossl_init_load_ssl_strings))
135         return 0;
136
137     if ((opts & OPENSSL_INIT_LOAD_SSL_STRINGS)
138         && !RUN_ONCE(&ssl_strings, ossl_init_load_ssl_strings))
139         return 0;
140
141     return 1;
142 }