]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/openssl.c
647f38eff12ab51d332a40e5554a23b7121a8b3b
[bacula/bacula] / bacula / src / lib / openssl.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2005-2014 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from many
7    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    Bacula® is a registered trademark of Kern Sibbald.
15 */
16 /*
17  * openssl.c OpenSSL support functions
18  *
19  * Author: Landon Fuller <landonf@opendarwin.org>
20  *
21  * Version $Id$
22  *
23  * This file was contributed to the Bacula project by Landon Fuller.
24  *
25  * Landon Fuller has been granted a perpetual, worldwide, non-exclusive,
26  * no-charge, royalty-free, irrevocable copyright license to reproduce,
27  * prepare derivative works of, publicly display, publicly perform,
28  * sublicense, and distribute the original work contributed by Landon Fuller
29  * to the Bacula project in source or object form.
30  *
31  * If you wish to license these contributions under an alternate open source
32  * license please contact Landon Fuller <landonf@opendarwin.org>.
33  */
34
35
36 #include "bacula.h"
37 #include <assert.h>
38
39 #ifdef HAVE_OPENSSL
40
41 /* Array of mutexes for use with OpenSSL static locking */
42 static pthread_mutex_t *mutexes;
43
44 /* OpenSSL dynamic locking structure */
45 struct CRYPTO_dynlock_value {
46    pthread_mutex_t mutex;
47 };
48
49 /*
50  * ***FIXME*** this is a sort of dummy to avoid having to
51  *   change all the existing code to pass either a jcr or
52  *   a NULL.  Passing a NULL causes the messages to be
53  *   printed by the daemon -- not very good :-(
54  */
55 void openssl_post_errors(int code, const char *errstring)
56 {
57    openssl_post_errors(NULL, code, errstring);
58 }
59
60
61 /*
62  * Post all per-thread openssl errors
63  */
64 void openssl_post_errors(JCR *jcr, int code, const char *errstring)
65 {
66    char buf[512];
67    unsigned long sslerr;
68
69    /* Pop errors off of the per-thread queue */
70    while((sslerr = ERR_get_error()) != 0) {
71       /* Acquire the human readable string */
72       ERR_error_string_n(sslerr, buf, sizeof(buf));
73       Dmsg3(50, "jcr=%p %s: ERR=%s\n", jcr, errstring, buf);
74       Qmsg2(jcr, M_ERROR, 0, "%s: ERR=%s\n", errstring, buf);
75    }
76 }
77
78 /*
79  * Return an OpenSSL thread ID
80  *  Returns: thread ID
81  *
82  */
83 static unsigned long get_openssl_thread_id(void)
84 {
85 #ifdef HAVE_WIN32
86    return (unsigned long)getpid();
87 #else
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 #endif
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 #endif /* HAVE_OPENSSL */