2 Bacula® - The Network Backup Solution
4 Copyright (C) 2005-2014 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from many
7 others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 Bacula® is a registered trademark of Kern Sibbald.
17 * openssl.c OpenSSL support functions
19 * Author: Landon Fuller <landonf@opendarwin.org>
23 * This file was contributed to the Bacula project by Landon Fuller.
25 * Landon Fuller has been granted a perpetual, worldwide, non-exclusive,
26 * no-charge, royalty-free, irrevocable copyright license to reproduce,
27 * prepare derivative works of, publicly display, publicly perform,
28 * sublicense, and distribute the original work contributed by Landon Fuller
29 * to the Bacula project in source or object form.
31 * If you wish to license these contributions under an alternate open source
32 * license please contact Landon Fuller <landonf@opendarwin.org>.
41 /* Array of mutexes for use with OpenSSL static locking */
42 static pthread_mutex_t *mutexes;
44 /* OpenSSL dynamic locking structure */
45 struct CRYPTO_dynlock_value {
46 pthread_mutex_t mutex;
50 * ***FIXME*** this is a sort of dummy to avoid having to
51 * change all the existing code to pass either a jcr or
52 * a NULL. Passing a NULL causes the messages to be
53 * printed by the daemon -- not very good :-(
55 void openssl_post_errors(int code, const char *errstring)
57 openssl_post_errors(NULL, code, errstring);
62 * Post all per-thread openssl errors
64 void openssl_post_errors(JCR *jcr, int code, const char *errstring)
69 /* Pop errors off of the per-thread queue */
70 while((sslerr = ERR_get_error()) != 0) {
71 /* Acquire the human readable string */
72 ERR_error_string_n(sslerr, buf, sizeof(buf));
73 Dmsg3(50, "jcr=%p %s: ERR=%s\n", jcr, errstring, buf);
74 Qmsg2(jcr, M_ERROR, 0, "%s: ERR=%s\n", errstring, buf);
79 * Return an OpenSSL thread ID
83 static unsigned long get_openssl_thread_id(void)
86 return (unsigned long)getpid();
89 * Comparison without use of pthread_equal() is mandated by the OpenSSL API
91 * Note: this creates problems with the new Win32 pthreads
92 * emulation code, which defines pthread_t as a structure.
94 return ((unsigned long)pthread_self());
99 * Allocate a dynamic OpenSSL mutex
101 static struct CRYPTO_dynlock_value *openssl_create_dynamic_mutex (const char *file, int line)
103 struct CRYPTO_dynlock_value *dynlock;
106 dynlock = (struct CRYPTO_dynlock_value *)malloc(sizeof(struct CRYPTO_dynlock_value));
108 if ((stat = pthread_mutex_init(&dynlock->mutex, NULL)) != 0) {
110 Jmsg1(NULL, M_ABORT, 0, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(stat));
116 static void openssl_update_dynamic_mutex(int mode, struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
118 if (mode & CRYPTO_LOCK) {
125 static void openssl_destroy_dynamic_mutex(struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
129 if ((stat = pthread_mutex_destroy(&dynlock->mutex)) != 0) {
131 Jmsg1(NULL, M_ABORT, 0, _("Unable to destroy mutex: ERR=%s\n"), be.bstrerror(stat));
138 * (Un)Lock a static OpenSSL mutex
140 static void openssl_update_static_mutex (int mode, int i, const char *file, int line)
142 if (mode & CRYPTO_LOCK) {
150 * Initialize OpenSSL thread support
151 * Returns: 0 on success
154 int openssl_init_threads (void)
160 /* Set thread ID callback */
161 CRYPTO_set_id_callback(get_openssl_thread_id);
163 /* Initialize static locking */
164 numlocks = CRYPTO_num_locks();
165 mutexes = (pthread_mutex_t *) malloc(numlocks * sizeof(pthread_mutex_t));
166 for (i = 0; i < numlocks; i++) {
167 if ((stat = pthread_mutex_init(&mutexes[i], NULL)) != 0) {
169 Jmsg1(NULL, M_FATAL, 0, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(stat));
174 /* Set static locking callback */
175 CRYPTO_set_locking_callback(openssl_update_static_mutex);
177 /* Initialize dyanmic locking */
178 CRYPTO_set_dynlock_create_callback(openssl_create_dynamic_mutex);
179 CRYPTO_set_dynlock_lock_callback(openssl_update_dynamic_mutex);
180 CRYPTO_set_dynlock_destroy_callback(openssl_destroy_dynamic_mutex);
186 * Clean up OpenSSL threading support
188 void openssl_cleanup_threads(void)
193 /* Unset thread ID callback */
194 CRYPTO_set_id_callback(NULL);
196 /* Deallocate static lock mutexes */
197 numlocks = CRYPTO_num_locks();
198 for (i = 0; i < numlocks; i++) {
199 if ((stat = pthread_mutex_destroy(&mutexes[i])) != 0) {
201 /* We don't halt execution, reporting the error should be sufficient */
202 Jmsg1(NULL, M_ERROR, 0, _("Unable to destroy mutex: ERR=%s\n"),
207 /* Unset static locking callback */
208 CRYPTO_set_locking_callback(NULL);
210 /* Free static lock array */
213 /* Unset dynamic locking callbacks */
214 CRYPTO_set_dynlock_create_callback(NULL);
215 CRYPTO_set_dynlock_lock_callback(NULL);
216 CRYPTO_set_dynlock_destroy_callback(NULL);
222 * Returns: 1 on success
225 int openssl_seed_prng (void)
227 const char *names[] = { "/dev/urandom", "/dev/random", NULL };
232 // Read saved entropy?
234 for (i = 0; names[i]; i++) {
235 if (RAND_load_file(names[i], 1024) != -1) {
246 * Save OpenSSL Entropy
247 * Returns: 1 on success
250 int openssl_save_prng (void)
253 // Implement PRNG state save
257 #endif /* HAVE_OPENSSL */