]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/openssl.c
8650ca8956d56bcad73df7f288c95b7d3b491eab
[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 void openssl_post_errors(int code, const char *errstring)
62 {
63    openssl_post_errors(NULL, code, errstring);
64 }
65
66
67 /*
68  * Post all per-thread openssl errors
69  */
70 void openssl_post_errors(JCR *jcr, int code, const char *errstring)
71 {
72    char buf[512];
73    unsigned long sslerr;
74
75    /* Pop errors off of the per-thread queue */
76    while((sslerr = ERR_get_error()) != 0) {
77       /* Acquire the human readable string */
78       ERR_error_string_n(sslerr, (char *) &buf, sizeof(buf));
79       Jmsg2(jcr, M_ERROR, 0, "%s: ERR=%s\n", errstring, buf);
80    }
81 }
82
83 /*
84  * Return an OpenSSL thread ID
85  *  Returns: thread ID
86  *
87  */
88 static unsigned long get_openssl_thread_id (void)
89 {
90    /* Comparison without use of pthread_equal() is mandated by the OpenSSL API */
91    return ((unsigned long) pthread_self());
92 }
93
94 /*
95  * Allocate a dynamic OpenSSL mutex
96  */
97 static struct CRYPTO_dynlock_value *openssl_create_dynamic_mutex (const char *file, int line)
98 {
99    struct CRYPTO_dynlock_value *dynlock;
100    int stat;
101
102    dynlock = (struct CRYPTO_dynlock_value *) malloc(sizeof(struct CRYPTO_dynlock_value));
103
104    if ((stat = pthread_mutex_init(&dynlock->mutex, NULL)) != 0) {
105       Emsg1(M_ABORT, 0, _("Unable to init mutex: ERR=%s\n"), strerror(stat));
106    }
107
108    return dynlock;
109 }
110
111 static void openssl_update_dynamic_mutex (int mode, struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
112 {
113    if (mode & CRYPTO_LOCK) {
114       P(dynlock->mutex);
115    } else {
116       V(dynlock->mutex);
117    }
118 }
119
120 static void openssl_destroy_dynamic_mutex (struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
121 {
122    int stat;
123
124    if ((stat = pthread_mutex_destroy(&dynlock->mutex)) != 0) {
125       Emsg1(M_ABORT, 0, _("Unable to destroy mutex: ERR=%s\n"), strerror(stat));
126    }
127
128    free(dynlock);
129 }
130
131 /*
132  * (Un)Lock a static OpenSSL mutex
133  */
134 static void openssl_update_static_mutex (int mode, int i, const char *file, int line)
135 {
136    if (mode & CRYPTO_LOCK) {
137       P(mutexes[i]);
138    } else {
139       V(mutexes[i]);
140    }
141 }
142
143 /*
144  * Initialize OpenSSL thread support
145  *  Returns: 0 on success
146  *           errno on failure
147  */
148 int openssl_init_threads (void)
149 {
150    int i, numlocks;
151    int stat;
152
153
154    /* Set thread ID callback */
155    CRYPTO_set_id_callback(get_openssl_thread_id);
156
157    /* Initialize static locking */
158    numlocks = CRYPTO_num_locks();
159    mutexes = (pthread_mutex_t *) malloc(numlocks * sizeof(pthread_mutex_t));
160    for (i = 0; i < numlocks; i++) {
161       if ((stat = pthread_mutex_init(&mutexes[i], NULL)) != 0) {
162          Emsg1(M_ERROR, 0, _("Unable to init mutex: ERR=%s\n"), strerror(stat));
163          return stat;
164       }
165    }
166
167    /* Set static locking callback */
168    CRYPTO_set_locking_callback(openssl_update_static_mutex);
169
170    /* Initialize dyanmic locking */
171    CRYPTO_set_dynlock_create_callback(openssl_create_dynamic_mutex);
172    CRYPTO_set_dynlock_lock_callback(openssl_update_dynamic_mutex);
173    CRYPTO_set_dynlock_destroy_callback(openssl_destroy_dynamic_mutex);
174
175    return 0;
176 }
177
178 /*
179  * Clean up OpenSSL threading support
180  */
181 void openssl_cleanup_threads (void)
182 {
183    int i, numlocks;
184    int stat;
185
186    /* Unset thread ID callback */
187    CRYPTO_set_id_callback(NULL);
188   
189    /* Deallocate static lock mutexes */
190    numlocks = CRYPTO_num_locks();
191    for (i = 0; i < numlocks; i++) {
192       if ((stat = pthread_mutex_destroy(&mutexes[i])) != 0) {
193          /* We don't halt execution, reporting the error should be sufficient */
194          Emsg1(M_ERROR, 0, _("Unable to destroy mutex: ERR=%s\n"), strerror(stat));
195       }
196    }
197
198    /* Unset static locking callback */
199    CRYPTO_set_locking_callback(NULL);
200
201    /* Free static lock array */
202    free(mutexes);
203
204    /* Unset dynamic locking callbacks */
205    CRYPTO_set_dynlock_create_callback(NULL);
206    CRYPTO_set_dynlock_lock_callback(NULL);
207    CRYPTO_set_dynlock_destroy_callback(NULL);
208 }
209
210
211 /*
212  * Seed OpenSSL PRNG
213  *  Returns: 1 on success
214  *           0 on failure
215  */
216 int openssl_seed_prng (void)
217 {
218    const char *names[]  = { "/dev/urandom", "/dev/random", NULL };
219    int i;
220
221    // ***FIXME***
222    // Win32 Support
223    // Read saved entropy?
224
225    for (i = 0; names[i]; i++) {
226       if (RAND_load_file(names[i], 1024) != -1) {
227          /* Success */
228          return 1;
229       }
230    }
231
232    /* Fail */
233    return 0;
234 }
235
236 /*
237  * Save OpenSSL Entropy
238  *  Returns: 1 on success
239  *           0 on failure
240  */
241 int openssl_save_prng (void)
242 {
243    // ***FIXME***
244    // Implement PRNG state save
245    return 1;
246 }
247
248 #endif /* HAVE_OPENSSL */