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