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