]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/openssl.c
96ffcb52bf111ff13db4905cbbaf1ba2fa512e42
[bacula/bacula] / bacula / src / lib / openssl.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2005-2007 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation plus additions
11    that are listed in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  * openssl.c OpenSSL support functions
30  *
31  * Author: Landon Fuller <landonf@opendarwin.org>
32  *
33  * Version $Id$
34  *
35  * This file was contributed to the Bacula project by Landon Fuller.
36  *
37  * Landon Fuller has been granted a perpetual, worldwide, non-exclusive,
38  * no-charge, royalty-free, irrevocable copyright license to reproduce,
39  * prepare derivative works of, publicly display, publicly perform,
40  * sublicense, and distribute the original work contributed by Landon Fuller
41  * to the Bacula project in source or object form.
42  *
43  * If you wish to license these contributions under an alternate open source
44  * license please contact Landon Fuller <landonf@opendarwin.org>.
45  */
46
47
48 #include "bacula.h"
49 #include <assert.h>
50
51 #ifdef HAVE_OPENSSL
52
53 /* Array of mutexes for use with OpenSSL static locking */
54 static pthread_mutex_t *mutexes;
55
56 /* OpenSSL dynamic locking structure */
57 struct CRYPTO_dynlock_value {
58    pthread_mutex_t mutex;
59 };
60
61 /*
62  * ***FIXME*** this is a sort of dummy to avoid having to
63  *   change all the existing code to pass either a jcr or
64  *   a NULL.  Passing a NULL causes the messages to be
65  *   printed by the daemon -- not very good :-(
66  */
67 void openssl_post_errors(int code, const char *errstring)
68 {
69    openssl_post_errors(NULL, code, errstring);
70 }
71
72
73 /*
74  * Post all per-thread openssl errors
75  */
76 void openssl_post_errors(JCR *jcr, int code, const char *errstring)
77 {
78    char buf[512];
79    unsigned long sslerr;
80
81    /* Pop errors off of the per-thread queue */
82    while((sslerr = ERR_get_error()) != 0) {
83       /* Acquire the human readable string */
84       ERR_error_string_n(sslerr, buf, sizeof(buf));
85       Dmsg3(100, "jcr=%p %s: ERR=%s\n", jcr, errstring, buf);
86       Jmsg2(jcr, M_ERROR, 0, "%s: ERR=%s\n", errstring, buf);
87    }
88 }
89
90 /*
91  * Return an OpenSSL thread ID
92  *  Returns: thread ID
93  *
94  */
95 static unsigned long get_openssl_thread_id(void)
96 {
97    /* Comparison without use of pthread_equal() is mandated by the OpenSSL API */
98    return ((unsigned long)pthread_self());
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       Emsg1(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       Emsg1(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 int openssl_init_threads (void)
158 {
159    int i, numlocks;
160    int stat;
161
162
163    /* Set thread ID callback */
164    CRYPTO_set_id_callback(get_openssl_thread_id);
165
166    /* Initialize static locking */
167    numlocks = CRYPTO_num_locks();
168    mutexes = (pthread_mutex_t *) malloc(numlocks * sizeof(pthread_mutex_t));
169    for (i = 0; i < numlocks; i++) {
170       if ((stat = pthread_mutex_init(&mutexes[i], NULL)) != 0) {
171          berrno be;
172          Emsg1(M_ERROR, 0, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(stat));
173          return stat;
174       }
175    }
176
177    /* Set static locking callback */
178    CRYPTO_set_locking_callback(openssl_update_static_mutex);
179
180    /* Initialize dyanmic locking */
181    CRYPTO_set_dynlock_create_callback(openssl_create_dynamic_mutex);
182    CRYPTO_set_dynlock_lock_callback(openssl_update_dynamic_mutex);
183    CRYPTO_set_dynlock_destroy_callback(openssl_destroy_dynamic_mutex);
184
185    return 0;
186 }
187
188 /*
189  * Clean up OpenSSL threading support
190  */
191 void openssl_cleanup_threads(void)
192 {
193    int i, numlocks;
194    int stat;
195
196    /* Unset thread ID callback */
197    CRYPTO_set_id_callback(NULL);
198   
199    /* Deallocate static lock mutexes */
200    numlocks = CRYPTO_num_locks();
201    for (i = 0; i < numlocks; i++) {
202       if ((stat = pthread_mutex_destroy(&mutexes[i])) != 0) {
203          berrno be;
204          /* We don't halt execution, reporting the error should be sufficient */
205          Emsg1(M_ERROR, 0, _("Unable to destroy mutex: ERR=%s\n"), 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
222 /*
223  * Seed OpenSSL PRNG
224  *  Returns: 1 on success
225  *           0 on failure
226  */
227 int openssl_seed_prng (void)
228 {
229    const char *names[]  = { "/dev/urandom", "/dev/random", NULL };
230    int i;
231
232    // ***FIXME***
233    // Win32 Support
234    // Read saved entropy?
235
236    for (i = 0; names[i]; i++) {
237       if (RAND_load_file(names[i], 1024) != -1) {
238          /* Success */
239          return 1;
240       }
241    }
242
243    /* Fail */
244    return 0;
245 }
246
247 /*
248  * Save OpenSSL Entropy
249  *  Returns: 1 on success
250  *           0 on failure
251  */
252 int openssl_save_prng (void)
253 {
254    // ***FIXME***
255    // Implement PRNG state save
256    return 1;
257 }
258
259 #endif /* HAVE_OPENSSL */