]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/openssl.c
Restore win32 dir from Branch-5.2 and update it
[bacula/bacula] / bacula / src / lib / openssl.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2016 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is 
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  * openssl.c OpenSSL support functions
21  *
22  * Author: Landon Fuller <landonf@opendarwin.org>
23  *
24  * This file was contributed to the Bacula project by Landon Fuller.
25  *
26  * Landon Fuller has been granted a perpetual, worldwide, non-exclusive,
27  * no-charge, royalty-free, irrevocable copyright license to reproduce,
28  * prepare derivative works of, publicly display, publicly perform,
29  * sublicense, and distribute the original work contributed by Landon Fuller
30  * to the Bacula project in source or object form.
31  *
32  * If you wish to license these contributions under an alternate open source
33  * license please contact Landon Fuller <landonf@opendarwin.org>.
34  */
35
36
37 #include "bacula.h"
38 #include <assert.h>
39
40 #ifdef HAVE_OPENSSL
41
42 /* Are we initialized? */
43 static int crypto_initialized = false;
44 /*
45  * ***FIXME*** this is a sort of dummy to avoid having to
46  *   change all the existing code to pass either a jcr or
47  *   a NULL.  Passing a NULL causes the messages to be
48  *   printed by the daemon -- not very good :-(
49  */
50 void openssl_post_errors(int code, const char *errstring)
51 {
52    openssl_post_errors(NULL, code, errstring);
53 }
54
55 /*
56  * Post all per-thread openssl errors
57  */
58 void openssl_post_errors(JCR *jcr, int code, const char *errstring)
59 {
60    char buf[512];
61    unsigned long sslerr;
62
63    /* Pop errors off of the per-thread queue */
64    while((sslerr = ERR_get_error()) != 0) {
65       /* Acquire the human readable string */
66       ERR_error_string_n(sslerr, buf, sizeof(buf));
67       Dmsg3(50, "jcr=%p %s: ERR=%s\n", jcr, errstring, buf);
68       Qmsg2(jcr, M_ERROR, 0, "%s: ERR=%s\n", errstring, buf);
69    }
70 }
71
72 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
73 /* Array of mutexes for use with OpenSSL static locking */
74 static pthread_mutex_t *mutexes;
75
76 /* OpenSSL dynamic locking structure */
77 struct CRYPTO_dynlock_value {
78    pthread_mutex_t mutex;
79 };
80
81 /*
82  * Return an OpenSSL thread ID
83  *  Returns: thread ID
84  *
85  */
86 static unsigned long get_openssl_thread_id(void)
87 {
88 #ifdef HAVE_WIN32
89    return (unsigned long)GetCurrentThreadId();
90 #else
91    /*
92     * Comparison without use of pthread_equal() is mandated by the OpenSSL API
93     *
94     * Note: this creates problems with the new Win32 pthreads
95     *   emulation code, which defines pthread_t as a structure.
96     */
97    return ((unsigned long)pthread_self());
98 #endif
99 }
100
101 /*
102  * Allocate a dynamic OpenSSL mutex
103  */
104 static struct CRYPTO_dynlock_value *openssl_create_dynamic_mutex (const char *file, int line)
105 {
106    struct CRYPTO_dynlock_value *dynlock;
107    int stat;
108
109    dynlock = (struct CRYPTO_dynlock_value *)malloc(sizeof(struct CRYPTO_dynlock_value));
110
111    if ((stat = pthread_mutex_init(&dynlock->mutex, NULL)) != 0) {
112       berrno be;
113       Jmsg1(NULL, M_ABORT, 0, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(stat));
114    }
115
116    return dynlock;
117 }
118
119 static void openssl_update_dynamic_mutex(int mode, struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
120 {
121    if (mode & CRYPTO_LOCK) {
122       P(dynlock->mutex);
123    } else {
124       V(dynlock->mutex);
125    }
126 }
127
128 static void openssl_destroy_dynamic_mutex(struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
129 {
130    int stat;
131
132    if ((stat = pthread_mutex_destroy(&dynlock->mutex)) != 0) {
133       berrno be;
134       Jmsg1(NULL, M_ABORT, 0, _("Unable to destroy mutex: ERR=%s\n"), be.bstrerror(stat));
135    }
136
137    free(dynlock);
138 }
139
140 /*
141  * (Un)Lock a static OpenSSL mutex
142  */
143 static void openssl_update_static_mutex (int mode, int i, const char *file, int line)
144 {
145    if (mode & CRYPTO_LOCK) {
146       P(mutexes[i]);
147    } else {
148       V(mutexes[i]);
149    }
150 }
151
152 /*
153  * Initialize OpenSSL thread support
154  *  Returns: 0 on success
155  *           errno on failure
156  */
157 static int openssl_init_threads (void)
158 {
159    int i, numlocks;
160    int stat;
161
162    /* Set thread ID callback */
163    CRYPTO_set_id_callback(get_openssl_thread_id);
164
165    /* Initialize static locking */
166    numlocks = CRYPTO_num_locks();
167    mutexes = (pthread_mutex_t *) malloc(numlocks * sizeof(pthread_mutex_t));
168    for (i = 0; i < numlocks; i++) {
169       if ((stat = pthread_mutex_init(&mutexes[i], NULL)) != 0) {
170          berrno be;
171          Jmsg1(NULL, M_FATAL, 0, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(stat));
172          return stat;
173       }
174    }
175
176    /* Set static locking callback */
177    CRYPTO_set_locking_callback(openssl_update_static_mutex);
178
179    /* Initialize dyanmic locking */
180    CRYPTO_set_dynlock_create_callback(openssl_create_dynamic_mutex);
181    CRYPTO_set_dynlock_lock_callback(openssl_update_dynamic_mutex);
182    CRYPTO_set_dynlock_destroy_callback(openssl_destroy_dynamic_mutex);
183
184    return 0;
185 }
186
187 /*
188  * Clean up OpenSSL threading support
189  */
190 static void openssl_cleanup_threads(void)
191 {
192    int i, numlocks;
193    int stat;
194
195    /* Unset thread ID callback */
196    CRYPTO_set_id_callback(NULL);
197
198    /* Deallocate static lock mutexes */
199    numlocks = CRYPTO_num_locks();
200    for (i = 0; i < numlocks; i++) {
201       if ((stat = pthread_mutex_destroy(&mutexes[i])) != 0) {
202          berrno be;
203          /* We don't halt execution, reporting the error should be sufficient */
204          Jmsg1(NULL, M_ERROR, 0, _("Unable to destroy mutex: ERR=%s\n"),
205                be.bstrerror(stat));
206       }
207    }
208
209    /* Unset static locking callback */
210    CRYPTO_set_locking_callback(NULL);
211
212    /* Free static lock array */
213    free(mutexes);
214
215    /* Unset dynamic locking callbacks */
216    CRYPTO_set_dynlock_create_callback(NULL);
217    CRYPTO_set_dynlock_lock_callback(NULL);
218    CRYPTO_set_dynlock_destroy_callback(NULL);
219 }
220
221 #endif
222
223 /*
224  * Seed OpenSSL PRNG
225  *  Returns: 1 on success
226  *           0 on failure
227  */
228 static int openssl_seed_prng (void)
229 {
230    const char *names[]  = { "/dev/urandom", "/dev/random", NULL };
231    int i;
232
233    // ***FIXME***
234    // Win32 Support
235    // Read saved entropy?
236
237    for (i = 0; names[i]; i++) {
238       if (RAND_load_file(names[i], 1024) != -1) {
239          /* Success */
240          return 1;
241       }
242    }
243
244    /* Fail */
245    return 0;
246 }
247
248 /*
249  * Save OpenSSL Entropy
250  *  Returns: 1 on success
251  *           0 on failure
252  */
253 static int openssl_save_prng (void)
254 {
255    // ***FIXME***
256    // Implement PRNG state save
257    return 1;
258 }
259
260 /*
261  * Perform global initialization of OpenSSL
262  * This function is not thread safe.
263  *  Returns: 0 on success
264  *           errno on failure
265  */
266 int init_crypto (void)
267 {
268    int stat = 0;
269
270 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
271    if ((stat = openssl_init_threads()) != 0) {
272       berrno be;
273       Jmsg1(NULL, M_ABORT, 0,
274         _("Unable to init OpenSSL threading: ERR=%s\n"), be.bstrerror(stat));
275    }
276
277    /* Load libssl and libcrypto human-readable error strings */
278    SSL_load_error_strings();
279
280    /* Initialize OpenSSL SSL  library */
281    SSL_library_init();
282
283    /* Register OpenSSL ciphers and digests */
284    OpenSSL_add_all_algorithms();
285 #endif
286
287    if (!openssl_seed_prng()) {
288       Jmsg0(NULL, M_ERROR_TERM, 0, _("Failed to seed OpenSSL PRNG\n"));
289    }
290
291    crypto_initialized = true;
292
293    return stat;
294 }
295
296 /*
297  * Perform global cleanup of OpenSSL
298  * All cryptographic operations must be completed before calling this function.
299  * This function is not thread safe.
300  *  Returns: 0 on success
301  *           errno on failure
302  */
303 int cleanup_crypto (void)
304 {
305    /*
306     * Ensure that we've actually been initialized; Doing this here decreases the
307     * complexity of client's termination/cleanup code.
308     */
309    if (!crypto_initialized) {
310       return 0;
311    }
312
313    if (!openssl_save_prng()) {
314       Jmsg0(NULL, M_ERROR, 0, _("Failed to save OpenSSL PRNG\n"));
315    }
316
317 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
318    openssl_cleanup_threads();
319
320    /* Free libssl and libcrypto error strings */
321    ERR_free_strings();
322
323    /* Free all ciphers and digests */
324    EVP_cleanup();
325
326    /* Free memory used by PRNG */
327    RAND_cleanup();
328 #endif
329
330    crypto_initialized = false;
331
332    return 0;
333 }
334
335 #else
336
337 /* Dummy routines */
338 int init_crypto (void) { return 0; }
339 int cleanup_crypto (void) { return 0; }
340
341 #endif /* HAVE_OPENSSL */