]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/openssl.c
Replace explicit checks for "/" with calls to IsPathSeparator, strchr with first_path...
[bacula/bacula] / bacula / src / lib / openssl.c
1 /*
2  * openssl.c OpenSSL support functions
3  *
4  * Author: Landon Fuller <landonf@opendarwin.org>
5  *
6  * Version $Id$
7  *
8  * This file was contributed to the Bacula project by Landon Fuller.
9  *
10  * Landon Fuller has been granted a perpetual, worldwide, non-exclusive,
11  * no-charge, royalty-free, irrevocable copyright license to reproduce,
12  * prepare derivative works of, publicly display, publicly perform,
13  * sublicense, and distribute the original work contributed by Landon Fuller
14  * to the Bacula project in source or object form.
15  *
16  * If you wish to license these contributions under an alternate open source
17  * license please contact Landon Fuller <landonf@opendarwin.org>.
18  */
19 /*
20    Bacula® - The Network Backup Solution
21
22    Copyright (C) 2005-2006 Free Software Foundation Europe e.V.
23
24    The main author of Bacula is Kern Sibbald, with contributions from
25    many others, a complete list can be found in the file AUTHORS.
26    This program is Free Software; you can redistribute it and/or
27    modify it under the terms of version two of the GNU General Public
28    License as published by the Free Software Foundation plus additions
29    that are listed in the file LICENSE.
30
31    This program is distributed in the hope that it will be useful, but
32    WITHOUT ANY WARRANTY; without even the implied warranty of
33    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34    General Public License for more details.
35
36    You should have received a copy of the GNU General Public License
37    along with this program; if not, write to the Free Software
38    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
39    02110-1301, USA.
40
41    Bacula® is a registered trademark of John Walker.
42    The licensor of Bacula is the Free Software Foundation Europe
43    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
44    Switzerland, email:ftf@fsfeurope.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 /*
63  * Post all per-thread openssl errors
64  */
65 void openssl_post_errors(int code, const char *errstring)
66 {
67    char buf[512];
68    unsigned long sslerr;
69
70    /* Pop errors off of the per-thread queue */
71    while((sslerr = ERR_get_error()) != 0) {
72       /* Acquire the human readable string */
73       ERR_error_string_n(sslerr, (char *) &buf, sizeof(buf));
74       Emsg2(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    /* Comparison without use of pthread_equal() is mandated by the OpenSSL API */
86    return ((unsigned long) pthread_self());
87 }
88
89 /*
90  * Allocate a dynamic OpenSSL mutex
91  */
92 static struct CRYPTO_dynlock_value *openssl_create_dynamic_mutex (const char *file, int line)
93 {
94    struct CRYPTO_dynlock_value *dynlock;
95    int stat;
96
97    dynlock = (struct CRYPTO_dynlock_value *) malloc(sizeof(struct CRYPTO_dynlock_value));
98
99    if ((stat = pthread_mutex_init(&dynlock->mutex, NULL)) != 0) {
100       Emsg1(M_ABORT, 0, _("Unable to init mutex: ERR=%s\n"), strerror(stat));
101    }
102
103    return dynlock;
104 }
105
106 static void openssl_update_dynamic_mutex (int mode, struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
107 {
108    if (mode & CRYPTO_LOCK) {
109       P(dynlock->mutex);
110    } else {
111       V(dynlock->mutex);
112    }
113 }
114
115 static void openssl_destroy_dynamic_mutex (struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
116 {
117    int stat;
118
119    if ((stat = pthread_mutex_destroy(&dynlock->mutex)) != 0) {
120       Emsg1(M_ABORT, 0, _("Unable to destroy mutex: ERR=%s\n"), strerror(stat));
121    }
122
123    free(dynlock);
124 }
125
126 /*
127  * (Un)Lock a static OpenSSL mutex
128  */
129 static void openssl_update_static_mutex (int mode, int i, const char *file, int line)
130 {
131    if (mode & CRYPTO_LOCK) {
132       P(mutexes[i]);
133    } else {
134       V(mutexes[i]);
135    }
136 }
137
138 /*
139  * Initialize OpenSSL thread support
140  *  Returns: 0 on success
141  *           errno on failure
142  */
143 int openssl_init_threads (void)
144 {
145    int i, numlocks;
146    int stat;
147
148
149    /* Set thread ID callback */
150    CRYPTO_set_id_callback(get_openssl_thread_id);
151
152    /* Initialize static locking */
153    numlocks = CRYPTO_num_locks();
154    mutexes = (pthread_mutex_t *) malloc(numlocks * sizeof(pthread_mutex_t));
155    for (i = 0; i < numlocks; i++) {
156       if ((stat = pthread_mutex_init(&mutexes[i], NULL)) != 0) {
157          Emsg1(M_ERROR, 0, _("Unable to init mutex: ERR=%s\n"), strerror(stat));
158          return stat;
159       }
160    }
161
162    /* Set static locking callback */
163    CRYPTO_set_locking_callback(openssl_update_static_mutex);
164
165    /* Initialize dyanmic locking */
166    CRYPTO_set_dynlock_create_callback(openssl_create_dynamic_mutex);
167    CRYPTO_set_dynlock_lock_callback(openssl_update_dynamic_mutex);
168    CRYPTO_set_dynlock_destroy_callback(openssl_destroy_dynamic_mutex);
169
170    return 0;
171 }
172
173 /*
174  * Clean up OpenSSL threading support
175  */
176 void openssl_cleanup_threads (void)
177 {
178    int i, numlocks;
179    int stat;
180
181    /* Unset thread ID callback */
182    CRYPTO_set_id_callback(NULL);
183   
184    /* Deallocate static lock mutexes */
185    numlocks = CRYPTO_num_locks();
186    for (i = 0; i < numlocks; i++) {
187       if ((stat = pthread_mutex_destroy(&mutexes[i])) != 0) {
188          /* We don't halt execution, reporting the error should be sufficient */
189          Emsg1(M_ERROR, 0, _("Unable to destroy mutex: ERR=%s\n"), strerror(stat));
190       }
191    }
192
193    /* Unset static locking callback */
194    CRYPTO_set_locking_callback(NULL);
195
196    /* Free static lock array */
197    free(mutexes);
198
199    /* Unset dynamic locking callbacks */
200    CRYPTO_set_dynlock_create_callback(NULL);
201    CRYPTO_set_dynlock_lock_callback(NULL);
202    CRYPTO_set_dynlock_destroy_callback(NULL);
203 }
204
205
206 /*
207  * Seed OpenSSL PRNG
208  *  Returns: 1 on success
209  *           0 on failure
210  */
211 int openssl_seed_prng (void)
212 {
213    const char *names[]  = { "/dev/urandom", "/dev/random", NULL };
214    int i;
215
216    // ***FIXME***
217    // Win32 Support
218    // Read saved entropy?
219
220    for (i = 0; names[i]; i++) {
221       if (RAND_load_file(names[i], 1024) != -1) {
222          /* Success */
223          return 1;
224       }
225    }
226
227    /* Fail */
228    return 0;
229 }
230
231 /*
232  * Save OpenSSL Entropy
233  *  Returns: 1 on success
234  *           0 on failure
235  */
236 int openssl_save_prng (void)
237 {
238    // ***FIXME***
239    // Implement PRNG state save
240    return 1;
241 }
242
243 #endif /* HAVE_OPENSSL */