]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/openssl.c
23ac946cfaeeffcbc12535f0fbb274e44e448edf
[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    /*
89     * Comparison without use of pthread_equal() is mandated by the OpenSSL API
90     *
91     * Note: this creates problems with the new Win32 pthreads
92     *   emulation code, which defines pthread_t as a structure.
93     */
94    return ((unsigned long)pthread_self());
95 }
96
97 /*
98  * Allocate a dynamic OpenSSL mutex
99  */
100 static struct CRYPTO_dynlock_value *openssl_create_dynamic_mutex (const char *file, int line)
101 {
102    struct CRYPTO_dynlock_value *dynlock;
103    int stat;
104
105    dynlock = (struct CRYPTO_dynlock_value *)malloc(sizeof(struct CRYPTO_dynlock_value));
106
107    if ((stat = pthread_mutex_init(&dynlock->mutex, NULL)) != 0) {
108       berrno be;
109       Jmsg1(NULL, M_ABORT, 0, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(stat));
110    }
111
112    return dynlock;
113 }
114
115 static void openssl_update_dynamic_mutex(int mode, struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
116 {
117    if (mode & CRYPTO_LOCK) {
118       P(dynlock->mutex);
119    } else {
120       V(dynlock->mutex);
121    }
122 }
123
124 static void openssl_destroy_dynamic_mutex(struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
125 {
126    int stat;
127
128    if ((stat = pthread_mutex_destroy(&dynlock->mutex)) != 0) {
129       berrno be;
130       Jmsg1(NULL, M_ABORT, 0, _("Unable to destroy mutex: ERR=%s\n"), be.bstrerror(stat));
131    }
132
133    free(dynlock);
134 }
135
136 /*
137  * (Un)Lock a static OpenSSL mutex
138  */
139 static void openssl_update_static_mutex (int mode, int i, const char *file, int line)
140 {
141    if (mode & CRYPTO_LOCK) {
142       P(mutexes[i]);
143    } else {
144       V(mutexes[i]);
145    }
146 }
147
148 /*
149  * Initialize OpenSSL thread support
150  *  Returns: 0 on success
151  *           errno on failure
152  */
153 static int openssl_init_threads (void)
154 {
155    int i, numlocks;
156    int stat;
157
158    /* Set thread ID callback */
159    CRYPTO_set_id_callback(get_openssl_thread_id);
160
161    /* Initialize static locking */
162    numlocks = CRYPTO_num_locks();
163    mutexes = (pthread_mutex_t *) malloc(numlocks * sizeof(pthread_mutex_t));
164    for (i = 0; i < numlocks; i++) {
165       if ((stat = pthread_mutex_init(&mutexes[i], NULL)) != 0) {
166          berrno be;
167          Jmsg1(NULL, M_FATAL, 0, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(stat));
168          return stat;
169       }
170    }
171
172    /* Set static locking callback */
173    CRYPTO_set_locking_callback(openssl_update_static_mutex);
174
175    /* Initialize dyanmic locking */
176    CRYPTO_set_dynlock_create_callback(openssl_create_dynamic_mutex);
177    CRYPTO_set_dynlock_lock_callback(openssl_update_dynamic_mutex);
178    CRYPTO_set_dynlock_destroy_callback(openssl_destroy_dynamic_mutex);
179
180    return 0;
181 }
182
183 /*
184  * Clean up OpenSSL threading support
185  */
186 static void openssl_cleanup_threads(void)
187 {
188    int i, numlocks;
189    int stat;
190
191    /* Unset thread ID callback */
192    CRYPTO_set_id_callback(NULL);
193
194    /* Deallocate static lock mutexes */
195    numlocks = CRYPTO_num_locks();
196    for (i = 0; i < numlocks; i++) {
197       if ((stat = pthread_mutex_destroy(&mutexes[i])) != 0) {
198          berrno be;
199          /* We don't halt execution, reporting the error should be sufficient */
200          Jmsg1(NULL, M_ERROR, 0, _("Unable to destroy mutex: ERR=%s\n"),
201                be.bstrerror(stat));
202       }
203    }
204
205    /* Unset static locking callback */
206    CRYPTO_set_locking_callback(NULL);
207
208    /* Free static lock array */
209    free(mutexes);
210
211    /* Unset dynamic locking callbacks */
212    CRYPTO_set_dynlock_create_callback(NULL);
213    CRYPTO_set_dynlock_lock_callback(NULL);
214    CRYPTO_set_dynlock_destroy_callback(NULL);
215 }
216
217 #endif
218
219 /*
220  * Seed OpenSSL PRNG
221  *  Returns: 1 on success
222  *           0 on failure
223  */
224 static int openssl_seed_prng (void)
225 {
226    const char *names[]  = { "/dev/urandom", "/dev/random", NULL };
227    int i;
228
229    // ***FIXME***
230    // Win32 Support
231    // Read saved entropy?
232
233    for (i = 0; names[i]; i++) {
234       if (RAND_load_file(names[i], 1024) != -1) {
235          /* Success */
236          return 1;
237       }
238    }
239
240    /* Fail */
241    return 0;
242 }
243
244 /*
245  * Save OpenSSL Entropy
246  *  Returns: 1 on success
247  *           0 on failure
248  */
249 static int openssl_save_prng (void)
250 {
251    // ***FIXME***
252    // Implement PRNG state save
253    return 1;
254 }
255
256 /*
257  * Perform global initialization of OpenSSL
258  * This function is not thread safe.
259  *  Returns: 0 on success
260  *           errno on failure
261  */
262 int init_crypto (void)
263 {
264    int stat = 0;
265
266 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
267    if ((stat = openssl_init_threads()) != 0) {
268       berrno be;
269       Jmsg1(NULL, M_ABORT, 0,
270         _("Unable to init OpenSSL threading: ERR=%s\n"), be.bstrerror(stat));
271    }
272
273    /* Load libssl and libcrypto human-readable error strings */
274    SSL_load_error_strings();
275
276    /* Initialize OpenSSL SSL  library */
277    SSL_library_init();
278
279    /* Register OpenSSL ciphers and digests */
280    OpenSSL_add_all_algorithms();
281 #endif
282
283    if (!openssl_seed_prng()) {
284       Jmsg0(NULL, M_ERROR_TERM, 0, _("Failed to seed OpenSSL PRNG\n"));
285    }
286
287    crypto_initialized = true;
288
289    return stat;
290 }
291
292 /*
293  * Perform global cleanup of OpenSSL
294  * All cryptographic operations must be completed before calling this function.
295  * This function is not thread safe.
296  *  Returns: 0 on success
297  *           errno on failure
298  */
299 int cleanup_crypto (void)
300 {
301    /*
302     * Ensure that we've actually been initialized; Doing this here decreases the
303     * complexity of client's termination/cleanup code.
304     */
305    if (!crypto_initialized) {
306       return 0;
307    }
308
309    if (!openssl_save_prng()) {
310       Jmsg0(NULL, M_ERROR, 0, _("Failed to save OpenSSL PRNG\n"));
311    }
312
313 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
314    openssl_cleanup_threads();
315
316    /* Free libssl and libcrypto error strings */
317    ERR_free_strings();
318
319    /* Free all ciphers and digests */
320    EVP_cleanup();
321
322    /* Free memory used by PRNG */
323    RAND_cleanup();
324 #endif
325
326    crypto_initialized = false;
327
328    return 0;
329 }
330
331 #else
332
333 /* Dummy routines */
334 int init_crypto (void) { return 0; }
335 int cleanup_crypto (void) { return 0; }
336
337 #endif /* HAVE_OPENSSL */