2 Bacula® - The Network Backup Solution
4 Copyright (C) 2005-2007 Free Software Foundation Europe e.V.
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 and included
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.
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
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.
29 * openssl.c OpenSSL support functions
31 * Author: Landon Fuller <landonf@opendarwin.org>
35 * This file was contributed to the Bacula project by Landon Fuller.
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.
43 * If you wish to license these contributions under an alternate open source
44 * license please contact Landon Fuller <landonf@opendarwin.org>.
53 /* Array of mutexes for use with OpenSSL static locking */
54 static pthread_mutex_t *mutexes;
56 /* OpenSSL dynamic locking structure */
57 struct CRYPTO_dynlock_value {
58 pthread_mutex_t mutex;
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 :-(
67 void openssl_post_errors(int code, const char *errstring)
69 openssl_post_errors(get_jcr_from_tid(), code, errstring);
74 * Post all per-thread openssl errors
76 void openssl_post_errors(JCR *jcr, int code, const char *errstring)
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 Qmsg2(jcr, M_ERROR, 0, "%s: ERR=%s\n", errstring, buf);
91 * Return an OpenSSL thread ID
95 static unsigned long get_openssl_thread_id(void)
97 /* Comparison without use of pthread_equal() is mandated by the OpenSSL API */
99 * Note that this creates problems with the new Win32 pthreads
100 * emulation code, which defines pthread_t as a structure. For
101 * this reason, we continue to use a very old implementation.
103 return ((unsigned long)pthread_self());
107 * Allocate a dynamic OpenSSL mutex
109 static struct CRYPTO_dynlock_value *openssl_create_dynamic_mutex (const char *file, int line)
111 struct CRYPTO_dynlock_value *dynlock;
114 dynlock = (struct CRYPTO_dynlock_value *)malloc(sizeof(struct CRYPTO_dynlock_value));
116 if ((stat = pthread_mutex_init(&dynlock->mutex, NULL)) != 0) {
118 Jmsg1(get_jcr_from_tid(), M_ABORT, 0, _("Unable to init mutex: ERR=%s\n"),
125 static void openssl_update_dynamic_mutex(int mode, struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
127 if (mode & CRYPTO_LOCK) {
134 static void openssl_destroy_dynamic_mutex(struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
138 if ((stat = pthread_mutex_destroy(&dynlock->mutex)) != 0) {
140 Jmsg1(get_jcr_from_tid(), M_ABORT, 0, _("Unable to destroy mutex: ERR=%s\n"),
148 * (Un)Lock a static OpenSSL mutex
150 static void openssl_update_static_mutex (int mode, int i, const char *file, int line)
152 if (mode & CRYPTO_LOCK) {
160 * Initialize OpenSSL thread support
161 * Returns: 0 on success
164 int openssl_init_threads (void)
170 /* Set thread ID callback */
171 CRYPTO_set_id_callback(get_openssl_thread_id);
173 /* Initialize static locking */
174 numlocks = CRYPTO_num_locks();
175 mutexes = (pthread_mutex_t *) malloc(numlocks * sizeof(pthread_mutex_t));
176 for (i = 0; i < numlocks; i++) {
177 if ((stat = pthread_mutex_init(&mutexes[i], NULL)) != 0) {
179 Jmsg1(get_jcr_from_tid(), M_ERROR, 0, _("Unable to init mutex: ERR=%s\n"),
185 /* Set static locking callback */
186 CRYPTO_set_locking_callback(openssl_update_static_mutex);
188 /* Initialize dyanmic locking */
189 CRYPTO_set_dynlock_create_callback(openssl_create_dynamic_mutex);
190 CRYPTO_set_dynlock_lock_callback(openssl_update_dynamic_mutex);
191 CRYPTO_set_dynlock_destroy_callback(openssl_destroy_dynamic_mutex);
197 * Clean up OpenSSL threading support
199 void openssl_cleanup_threads(void)
204 /* Unset thread ID callback */
205 CRYPTO_set_id_callback(NULL);
207 /* Deallocate static lock mutexes */
208 numlocks = CRYPTO_num_locks();
209 for (i = 0; i < numlocks; i++) {
210 if ((stat = pthread_mutex_destroy(&mutexes[i])) != 0) {
212 /* We don't halt execution, reporting the error should be sufficient */
213 Jmsg1(get_jcr_from_tid(), M_ERROR, 0, _("Unable to destroy mutex: ERR=%s\n"),
218 /* Unset static locking callback */
219 CRYPTO_set_locking_callback(NULL);
221 /* Free static lock array */
224 /* Unset dynamic locking callbacks */
225 CRYPTO_set_dynlock_create_callback(NULL);
226 CRYPTO_set_dynlock_lock_callback(NULL);
227 CRYPTO_set_dynlock_destroy_callback(NULL);
233 * Returns: 1 on success
236 int openssl_seed_prng (void)
238 const char *names[] = { "/dev/urandom", "/dev/random", NULL };
243 // Read saved entropy?
245 for (i = 0; names[i]; i++) {
246 if (RAND_load_file(names[i], 1024) != -1) {
257 * Save OpenSSL Entropy
258 * Returns: 1 on success
261 int openssl_save_prng (void)
264 // Implement PRNG state save
268 #endif /* HAVE_OPENSSL */