]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/tls.c
- Integrated TLS network encryption
[bacula/bacula] / bacula / src / lib / tls.c
1 /*
2  * tls.c TLS support functions
3  *
4  * Author: Landon Fuller <landonf@threerings.net>
5  *
6  * Version $Id$
7  *
8  * Copyright (C) 2005 Kern Sibbald
9  *
10  * This file was contributed to the Bacula project by Landon Fuller
11  * and Three Rings Design, Inc.
12  *
13  * Three Rings Design, Inc. has been granted a perpetual, worldwide,
14  * non-exclusive, no-charge, royalty-free, irrevocable copyright
15  * license to reproduce, prepare derivative works of, publicly
16  * display, publicly perform, sublicense, and distribute the original
17  * work contributed by Three Rings Design, Inc. and its employees to
18  * the Bacula project in source or object form.
19  *
20  * If you wish to license contributions from Three Rings Design, Inc,
21  * under an alternate open source license please contact
22  * Landon Fuller <landonf@threerings.net>.
23  */
24 /*  
25    This library is free software; you can redistribute it and/or
26    modify it under the terms of the GNU Lesser General Public
27    License as published by the Free Software Foundation; either
28    version 2.1 of the License, or (at your option) any later version.
29   
30    This library is distributed in the hope that it will be useful,
31    but WITHOUT ANY WARRANTY; without even the implied warranty of
32    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
33    Lesser General Public License for more details.
34   
35    You should have received a copy of the GNU Lesser General Public
36    License along with this library; if not, write to the Free
37    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
38    MA 02111-1307, USA.
39  */
40
41
42 #include "bacula.h"
43 #include <assert.h>
44
45 extern time_t watchdog_time;
46
47 #ifdef HAVE_TLS /* Is TLS enabled? */
48
49 #ifdef HAVE_OPENSSL /* How about OpenSSL? */
50
51 /* No anonymous ciphers, no <128 bit ciphers, no export ciphers, no MD5 ciphers */
52 #define TLS_DEFAULT_CIPHERS "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"
53
54 /* Array of mutexes for use with OpenSSL static locking */
55 static pthread_mutex_t *mutexes;
56
57 /* OpenSSL dynamic locking structure */
58 struct CRYPTO_dynlock_value {
59    pthread_mutex_t mutex;
60 };
61
62 /* Are we initialized? */
63 static int tls_initialized = false;
64
65 /* TLS Context Structure */
66 struct TLS_Context {
67    SSL_CTX *openssl;
68    TLS_PEM_PASSWD_CB *pem_callback;
69    const void *pem_userdata;
70 };
71
72 struct TLS_Connection {
73    SSL *openssl;
74 };
75
76 /* post all per-thread openssl errors */
77 static void openssl_post_errors(int code, const char *errstring)
78 {
79    char buf[512];
80    unsigned long sslerr;
81
82    /* Pop errors off of the per-thread queue */
83    while((sslerr = ERR_get_error()) != 0) {
84       /* Acquire the human readable string */
85       ERR_error_string_n(sslerr, (char *) &buf, sizeof(buf));
86       Emsg2(M_ERROR, 0, "%s: ERR=%s\n", errstring, buf);
87    }
88 }
89
90 /*
91  * OpenSSL certificate verification callback.
92  * OpenSSL has already performed internal certificate verification.
93  * We just report any errors that occured.
94  */
95 static int openssl_verify_peer(int ok, X509_STORE_CTX *store)
96 {
97
98    if (!ok) {
99       X509 *cert = X509_STORE_CTX_get_current_cert(store);
100       int depth = X509_STORE_CTX_get_error_depth(store);
101       int err = X509_STORE_CTX_get_error(store);
102       char issuer[256];
103       char subject[256];
104
105       X509_NAME_oneline(X509_get_issuer_name(cert), issuer, 256);
106       X509_NAME_oneline(X509_get_subject_name(cert), subject, 256);
107
108       Emsg5(M_ERROR, 0, _("Error with certificate at depth: %d, issuer = %s,"
109                           " subject = %s, ERR=%d:%s\n"), depth, issuer,
110                           subject, err, X509_verify_cert_error_string(err));
111
112    }
113
114    return ok;
115 }
116
117 /*
118  * Default PEM encryption passphrase callback.
119  * Returns an empty password.
120  */
121 static int tls_default_pem_callback(char *buf, int size, const void *userdata)
122 {
123    bstrncpy(buf, "", size);
124    return (strlen(buf));
125 }
126
127 /* Dispatch user PEM encryption callbacks */
128 static int openssl_pem_callback_dispatch (char *buf, int size, int rwflag, void *userdata)
129 {
130    TLS_CONTEXT *ctx = (TLS_CONTEXT *) userdata;
131    return (ctx->pem_callback(buf, size, ctx->pem_userdata));
132 }
133
134 /*
135  * Create a new TLS_CONTEXT instance.
136  *  Returns: Pointer to TLS_CONTEXT instance on success
137  *           NULL on failure;
138  */
139 TLS_CONTEXT *new_tls_context(const char *ca_certfile, const char *ca_certdir,
140                              const char *certfile, const char *keyfile,
141                              TLS_PEM_PASSWD_CB *pem_callback,
142                              const void *pem_userdata, const char *dhfile,
143                              bool verify_peer)
144 {
145    TLS_CONTEXT *ctx;
146    BIO *bio;
147    DH *dh;
148
149    ctx = (TLS_CONTEXT *) malloc(sizeof(TLS_CONTEXT));
150
151    /* Allocate our OpenSSL TLSv1 Context */
152    ctx->openssl = SSL_CTX_new(TLSv1_method());
153
154    if (!ctx->openssl) {
155       openssl_post_errors(M_ERROR, _("Error initializing SSL context"));
156       goto err;
157    }
158
159    /* Set up pem encryption callback */
160    if (pem_callback) {
161       ctx->pem_callback = pem_callback;
162       ctx->pem_userdata = pem_userdata;
163    } else {
164       ctx->pem_callback = tls_default_pem_callback;
165       ctx->pem_userdata = NULL;
166    }
167    SSL_CTX_set_default_passwd_cb(ctx->openssl, openssl_pem_callback_dispatch);
168    SSL_CTX_set_default_passwd_cb_userdata(ctx->openssl, (void *) ctx);
169
170    /*
171     * Set certificate verification paths. This requires that at least one
172     * value be non-NULL
173     */
174    if (ca_certfile || ca_certdir) {
175       if (!SSL_CTX_load_verify_locations(ctx->openssl, ca_certfile, ca_certdir)) {
176          openssl_post_errors(M_ERROR, _("Error loading certificate verification stores"));
177          goto err;
178       }
179    } else if (verify_peer) {
180       /* At least one CA is required for peer verification */
181       Emsg0(M_ERROR, 0, _("Either a certificate file or a directory must be"
182                          " specified as a verification store\n"));
183       goto err;
184    }
185
186    /*
187     * Load our certificate file, if available. This file may also contain a
188     * private key, though this usage is somewhat unusual.
189     */
190    if (certfile) {
191       if (!SSL_CTX_use_certificate_chain_file(ctx->openssl, certfile)) {
192          openssl_post_errors(M_ERROR, _("Error loading certificate file"));
193          goto err;
194       }
195    }
196
197    /* Load our private key. */
198    if (keyfile) {
199       if (!SSL_CTX_use_PrivateKey_file(ctx->openssl, keyfile, SSL_FILETYPE_PEM)) {
200          openssl_post_errors(M_ERROR, _("Error loading private key"));
201          goto err;
202       }
203    }
204
205    /* Load Diffie-Hellman Parameters. */
206    if (dhfile) {
207       if (!(bio = BIO_new_file(dhfile, "r"))) {
208          openssl_post_errors(M_ERROR, _("Unable to open DH parameters file"));
209          goto err;
210       }
211       dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
212       BIO_free(bio);
213       if (!dh) {
214          openssl_post_errors(M_ERROR, _("Unable to load DH parameters from specified file"));
215          goto err;
216       }
217       if (!SSL_CTX_set_tmp_dh(ctx->openssl, dh)) {
218          openssl_post_errors(M_ERROR, _("Failed to set TLS Diffie-Hellman parameters"));
219          DH_free(dh);
220          goto err;
221       }
222       /* Enable Single-Use DH for Ephemeral Keying */
223       SSL_CTX_set_options(ctx->openssl, SSL_OP_SINGLE_DH_USE);
224    }
225
226    if (SSL_CTX_set_cipher_list(ctx->openssl, TLS_DEFAULT_CIPHERS) != 1) {
227       Emsg0(M_ERROR, 0, _("Error setting cipher list, no valid ciphers available\n"));
228       goto err;
229    }
230
231    /* Verify Peer Certificate */
232    if (verify_peer) {
233            /* SSL_VERIFY_FAIL_IF_NO_PEER_CERT has no effect in client mode */
234            SSL_CTX_set_verify(ctx->openssl,
235                               SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
236                               openssl_verify_peer);
237    }
238
239    return ctx;
240
241 err:
242    /* Clean up after ourselves */
243    if(ctx->openssl) {
244       SSL_CTX_free(ctx->openssl);
245    }
246    free(ctx);
247    return NULL;
248 }
249
250 /*
251  * Free TLS_CONTEXT instance
252  */
253 void free_tls_context(TLS_CONTEXT *ctx)
254 {
255    SSL_CTX_free(ctx->openssl);
256    free(ctx);
257 }
258
259 /*
260  * Verifies a list of common names against the certificate
261  * commonName attribute.
262  *  Returns: true on success
263  *           false on failure
264  */
265 bool tls_postconnect_verify_cn(TLS_CONNECTION *tls, alist *verify_list)
266 {
267    SSL *ssl = tls->openssl;
268    X509 *cert;
269    X509_NAME *subject;
270    int auth_success = false;
271    char data[256];
272
273    /* Check if peer provided a certificate */
274    if (!(cert = SSL_get_peer_certificate(ssl))) {
275       Emsg0(M_ERROR, 0, _("Peer failed to present a TLS certificate\n"));
276       return false;
277    }
278
279    if ((subject = X509_get_subject_name(cert)) != NULL) {
280       if (X509_NAME_get_text_by_NID(subject, NID_commonName, data, sizeof(data)) > 0) {
281          char *cn;
282          /* NULL terminate data */
283          data[255] = 0;
284
285          /* Try all the CNs in the list */
286          foreach_alist(cn, verify_list) {
287             if (strcasecmp(data, cn) == 0) {
288                auth_success = true;
289             }
290          }
291       }
292    }
293
294    X509_free(cert);
295    return auth_success;
296 }
297
298 /*
299  * Verifies a peer's hostname against the subjectAltName and commonName
300  * attributes.
301  *  Returns: true on success
302  *           false on failure
303  */
304 bool tls_postconnect_verify_host(TLS_CONNECTION *tls, const char *host)
305 {
306    SSL *ssl = tls->openssl;
307    X509 *cert;
308    X509_NAME *subject;
309    int auth_success = false;
310    int extensions;
311    char data[256];
312    int i, j;
313
314
315    /* Check if peer provided a certificate */
316    if (!(cert = SSL_get_peer_certificate(ssl))) {
317       Emsg1(M_ERROR, 0, _("Peer %s failed to present a TLS certificate\n"), host);
318       return false;
319    }
320
321    /* Check subjectAltName extensions first */
322    if ((extensions = X509_get_ext_count(cert)) > 0) {
323       for (i = 0; i < extensions; i++) {
324          X509_EXTENSION *ext;
325          const char *extname;
326
327          ext = X509_get_ext(cert, i);
328          extname = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
329
330          if (strcmp(extname, "subjectAltName") == 0) {
331             X509V3_EXT_METHOD *method;
332             STACK_OF(CONF_VALUE) *val;
333             CONF_VALUE *nval;
334             unsigned char *data;
335             void *extstr = NULL;
336
337             /* Get x509 extension method structure */
338             if (!(method = X509V3_EXT_get(ext))) {
339                break;
340             }
341
342             data = ext->value->data;
343
344 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
345             if (method->it) {
346                /* New style ASN1 */
347
348                /* Decode ASN1 item in data */
349                extstr = ASN1_item_d2i(NULL, &data, ext->value->length,
350                                       ASN1_ITEM_ptr(method->it));
351             } else {
352                /* Old style ASN1 */
353
354                /* Decode ASN1 item in data */
355                extstr = method->d2i(NULL, &data, ext->value->length);
356             }
357
358 #else
359             extstr = method->d2i(NULL, &data, ext->value->length);
360 #endif
361
362             /* Iterate through to find the dNSName field(s) */
363             val = method->i2v(method, extstr, NULL);
364
365             /* dNSName shortname is "DNS" */
366             for (j = 0; j < sk_CONF_VALUE_num(val); j++) {
367                nval = sk_CONF_VALUE_value(val, j);
368                if (strcmp(nval->name, "DNS") == 0) {
369                   if (strcasecmp(nval->name, host) == 0) {
370                      auth_success = true;
371                      goto success;
372                   }
373                }
374             }
375          }
376       }
377    }
378
379    /* Try verifying against the subject name */
380    if (!auth_success) {
381       if ((subject = X509_get_subject_name(cert)) != NULL) {
382          if (X509_NAME_get_text_by_NID(subject, NID_commonName, data, sizeof(data)) > 0) {
383             /* NULL terminate data */
384             data[255] = 0;
385             if (strcasecmp(data, host) == 0) {
386                auth_success = true;
387             }
388          }
389       }
390    }
391
392
393 success:
394    X509_free(cert);
395
396    return auth_success;
397 }
398
399 /*
400  * Create a new TLS_CONNECTION instance.
401  *
402  * Returns: Pointer to TLS_CONNECTION instance on success
403  *          NULL on failure;
404  */
405 TLS_CONNECTION *new_tls_connection (TLS_CONTEXT *ctx, int fd)
406 {
407    BIO *bio;
408
409    /*
410     * Create a new BIO and assign the fd.
411     * The caller will remain responsible for closing the associated fd
412     */
413    bio = BIO_new(BIO_s_socket());
414    if (!bio) {
415       /* Not likely, but never say never */
416       openssl_post_errors(M_ERROR, "Error creating file descriptor-based BIO");
417       return NULL; /* Nothing allocated, nothing to clean up */
418    }
419    BIO_set_fd(bio, fd, BIO_NOCLOSE);
420
421    /* Allocate our new tls connection */
422    TLS_CONNECTION *tls = (TLS_CONNECTION *) malloc(sizeof(TLS_CONNECTION));
423
424    /* Create the SSL object and attach the socket BIO */
425    if ((tls->openssl = SSL_new(ctx->openssl)) == NULL) {
426       /* Not likely, but never say never */
427       openssl_post_errors(M_ERROR, "Error creating new SSL object");
428       goto err;
429    }
430
431    SSL_set_bio(tls->openssl, bio, bio);
432
433    /* Non-blocking partial writes */
434    SSL_set_mode(tls->openssl, SSL_MODE_ENABLE_PARTIAL_WRITE|SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
435
436    return (tls);
437
438 err:
439    /* Clean up */
440    BIO_free(bio);
441    SSL_free(tls->openssl);
442    free(tls);
443
444    return NULL;
445 }
446
447 /*
448  * Free TLS_CONNECTION instance
449  */
450 void free_tls_connection (TLS_CONNECTION *tls)
451 {
452    SSL_free(tls->openssl);
453    free(tls);
454 }
455
456 /* Does all the manual labor for tls_bsock_accept() and tls_bsock_connect() */
457 static inline bool openssl_bsock_session_start(BSOCK *bsock, bool server)
458 {
459    TLS_CONNECTION *tls = bsock->tls;
460    int err;
461    int fdmax, flags;
462    int stat = true;
463    fd_set fdset;
464    struct timeval tv;
465
466    /* Zero the fdset, we'll set our fd prior to each invocation of select() */
467    FD_ZERO(&fdset);
468    tv.tv_sec = 10;
469    tv.tv_usec = 0;
470    fdmax = bsock->fd + 1;
471
472    /* Ensure that socket is non-blocking */
473    flags = bnet_set_nonblocking(bsock);
474
475    /* start timer */
476    bsock->timer_start = watchdog_time;
477    bsock->timed_out = 0;
478
479    for (;;) { 
480       if (server) {
481          err = SSL_accept(tls->openssl);
482       } else {
483          err = SSL_connect(tls->openssl);
484       }
485
486       /* Handle errors */
487       switch (SSL_get_error(tls->openssl, err)) {
488            case SSL_ERROR_NONE:
489               stat = true;
490               goto cleanup;
491            case SSL_ERROR_ZERO_RETURN:
492               /* TLS connection was cleanly shut down */
493               openssl_post_errors(M_ERROR, "Connect failure");
494               stat = false;
495               goto cleanup;
496            case SSL_ERROR_WANT_READ:
497               /* If we timeout of a select, this will be unset */
498               FD_SET((unsigned) bsock->fd, &fdset);
499               /* Block until we can read */
500               select(fdmax, &fdset, NULL, &fdset, &tv);
501               break;
502            case SSL_ERROR_WANT_WRITE:
503               /* If we timeout of a select, this will be unset */
504               FD_SET((unsigned) bsock->fd, &fdset);
505               /* Block until we can write */
506               select(fdmax, NULL, &fdset, &fdset, &tv);
507               break;
508            default:
509               /* Socket Error Occured */
510               openssl_post_errors(M_ERROR, "Connect failure");
511               stat = false;
512               goto cleanup;
513       }
514
515       if (bsock->timed_out) {
516          goto cleanup;
517       }
518    }
519
520 cleanup:
521    /* Restore saved flags */
522    bnet_restore_blocking(bsock, flags);
523    /* Clear timer */
524    bsock->timer_start = 0;
525
526    return stat;
527 }
528
529 /*
530  * Initiates a TLS connection with the server.
531  *  Returns: true on success
532  *           false on failure
533  */
534 bool tls_bsock_connect(BSOCK *bsock)
535 {
536    /* SSL_connect(bsock->tls) */
537    return (openssl_bsock_session_start(bsock, false));
538 }
539
540 /*
541  * Listens for a TLS connection from a client.
542  *  Returns: true on success
543  *           false on failure
544  */
545 bool tls_bsock_accept(BSOCK *bsock)
546 {
547    /* SSL_accept(bsock->tls) */
548    return (openssl_bsock_session_start(bsock, true));
549 }
550
551 /*
552  * Shutdown TLS_CONNECTION instance
553  */
554 void tls_bsock_shutdown (BSOCK *bsock)
555 {
556    /*
557     * SSL_shutdown must be called twice to fully complete the process -
558     * The first time to initiate the shutdown handshake, and the second to
559     * receive the peer's reply.
560     *
561     * However, it is valid to close the SSL connection after the initial
562     * shutdown notification is sent to the peer, without waiting for the
563     * peer's reply, as long as you do not plan to re-use that particular
564     * SSL connection object.
565     *
566     * Because we do not re-use SSL connection objects, I do not bother
567     * calling SSL_shutdown a second time.
568     *
569     * In addition, if the underlying socket is blocking, SSL_shutdown()
570     * will not return until the current stage of the shutdown process has
571     * completed or an error has occured. By setting the socket blocking
572     * we can avoid the ugly for()/switch()/select() loop.
573     */
574    int err;
575    int flags;
576
577    /* Set socket blocking for shutdown */
578    flags = bnet_set_blocking(bsock);
579
580    err = SSL_shutdown(bsock->tls->openssl);
581
582    switch (SSL_get_error(bsock->tls->openssl, err)) {
583       case SSL_ERROR_NONE:
584          break;
585       case SSL_ERROR_ZERO_RETURN:
586          /* TLS connection was shut down on us via a TLS protocol-level closure */
587          openssl_post_errors(M_ERROR, _("TLS shutdown failure."));
588          break;
589       default:
590          /* Socket Error Occured */
591          openssl_post_errors(M_ERROR, _("TLS shutdown failure."));
592          break;
593    }
594
595    /* Restore saved flags */
596    bnet_restore_blocking(bsock, flags);
597 }
598
599 /* Does all the manual labor for tls_bsock_readn() and tls_bsock_writen() */
600 static inline int openssl_bsock_readwrite(BSOCK *bsock, char *ptr, int nbytes, bool write)
601 {
602    TLS_CONNECTION *tls = bsock->tls;
603    int fdmax, flags;
604    fd_set fdset;
605    struct timeval tv;
606    int nleft = 0;
607    int nwritten = 0;
608
609    /* Zero the fdset, we'll set our fd prior to each invocation of select() */
610    FD_ZERO(&fdset);
611    tv.tv_sec = 10;
612    tv.tv_usec = 0;
613    fdmax = bsock->fd + 1;
614
615    /* Ensure that socket is non-blocking */
616    flags = bnet_set_nonblocking(bsock);
617
618    /* start timer */
619    bsock->timer_start = watchdog_time;
620    bsock->timed_out = 0;
621
622    nleft = nbytes;
623
624    while (nleft > 0) { 
625
626       if (write) {
627          nwritten = SSL_write(tls->openssl, ptr, nleft);
628       } else {
629          nwritten = SSL_read(tls->openssl, ptr, nleft);
630       }
631
632       /* Handle errors */
633       switch (SSL_get_error(tls->openssl, nwritten)) {
634          case SSL_ERROR_NONE:
635             nleft -= nwritten;
636             if (nleft) {
637                ptr += nwritten;
638             }
639             break;
640          case SSL_ERROR_ZERO_RETURN:
641             /* TLS connection was cleanly shut down */
642             openssl_post_errors(M_ERROR, _("TLS read/write failure."));
643             goto cleanup;
644          case SSL_ERROR_WANT_READ:
645             /* If we timeout of a select, this will be unset */
646             FD_SET((unsigned) bsock->fd, &fdset);
647             /* Block until we can read */
648             select(fdmax, &fdset, NULL, &fdset, &tv);
649             break;
650          case SSL_ERROR_WANT_WRITE:
651             /* If we timeout of a select, this will be unset */
652             FD_SET((unsigned) bsock->fd, &fdset);
653             /* Block until we can write */
654             select(fdmax, NULL, &fdset, &fdset, &tv);
655             break;
656          default:
657             /* Socket Error Occured */
658             openssl_post_errors(M_ERROR, _("TLS read/write failure."));
659             goto cleanup;
660       }
661
662       /* Everything done? */
663       if (nleft == 0) {
664          goto cleanup;
665       }
666
667       /* Timeout/Termination, let's take what we can get */
668       if (bsock->timed_out || bsock->terminated) {
669          goto cleanup;
670       }
671    }
672
673 cleanup:
674    /* Restore saved flags */
675    bnet_restore_blocking(bsock, flags);
676
677    /* Clear timer */
678    bsock->timer_start = 0;
679
680    return nbytes - nleft;
681 }
682
683
684 int tls_bsock_writen(BSOCK *bsock, char *ptr, int32_t nbytes) {
685    /* SSL_write(bsock->tls->openssl, ptr, nbytes) */
686    return (openssl_bsock_readwrite(bsock, ptr, nbytes, true));
687 }
688
689 int tls_bsock_readn(BSOCK *bsock, char *ptr, int32_t nbytes) {
690    /* SSL_read(bsock->tls->openssl, ptr, nbytes) */
691    return (openssl_bsock_readwrite(bsock, ptr, nbytes, false));
692 }
693
694 /*
695  * Return an OpenSSL thread ID
696  *  Returns: thread ID
697  *
698  */
699 static unsigned long get_openssl_thread_id (void)
700 {
701    /* Comparison without use of pthread_equal() is mandated by the OpenSSL API */
702    return ((unsigned long) pthread_self());
703 }
704
705 /*
706  * Allocate a dynamic OpenSSL mutex
707  */
708 static struct CRYPTO_dynlock_value *openssl_create_dynamic_mutex (const char *file, int line)
709 {
710    struct CRYPTO_dynlock_value *dynlock;
711    int stat;
712
713    dynlock = (struct CRYPTO_dynlock_value *) malloc(sizeof(struct CRYPTO_dynlock_value));
714
715    if ((stat = pthread_mutex_init(&dynlock->mutex, NULL)) != 0) {
716       Emsg1(M_ABORT, 0, "Unable to init mutex: ERR=%s\n", strerror(stat));
717    }
718
719    return dynlock;
720 }
721
722 static void openssl_update_dynamic_mutex (int mode, struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
723 {
724    if (mode & CRYPTO_LOCK) {
725       P(dynlock->mutex);
726    } else {
727       V(dynlock->mutex);
728    }
729 }
730
731 static void openssl_destroy_dynamic_mutex (struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
732 {
733    int stat;
734
735    if ((stat = pthread_mutex_destroy(&dynlock->mutex)) != 0) {
736       Emsg1(M_ABORT, 0, "Unable to destroy mutex: ERR=%s\n", strerror(stat));
737    }
738
739    free(dynlock);
740 }
741
742 /*
743  * (Un)Lock a static OpenSSL mutex
744  */
745 static void openssl_update_static_mutex (int mode, int i, const char *file, int line)
746 {
747    if (mode & CRYPTO_LOCK) {
748       P(mutexes[i]);
749    } else {
750       V(mutexes[i]);
751    }
752 }
753
754 /*
755  * Initialize OpenSSL thread support
756  *  Returns: 0 on success
757  *           errno on failure
758  */
759 static int openssl_init_threads (void)
760 {
761    int i, numlocks;
762    int stat;
763
764
765    /* Set thread ID callback */
766    CRYPTO_set_id_callback(get_openssl_thread_id);
767
768    /* Initialize static locking */
769    numlocks = CRYPTO_num_locks();
770    mutexes = (pthread_mutex_t *) malloc(numlocks * sizeof(pthread_mutex_t));
771    for (i = 0; i < numlocks; i++) {
772       if ((stat = pthread_mutex_init(&mutexes[i], NULL)) != 0) {
773          Emsg1(M_ERROR, 0, "Unable to init mutex: ERR=%s\n", strerror(stat));
774          return stat;
775       }
776    }
777
778    /* Set static locking callback */
779    CRYPTO_set_locking_callback(openssl_update_static_mutex);
780
781    /* Initialize dyanmic locking */
782    CRYPTO_set_dynlock_create_callback(openssl_create_dynamic_mutex);
783    CRYPTO_set_dynlock_lock_callback(openssl_update_dynamic_mutex);
784    CRYPTO_set_dynlock_destroy_callback(openssl_destroy_dynamic_mutex);
785
786    return 0;
787 }
788
789 /*
790  * Clean up OpenSSL threading support
791  */
792 static void openssl_cleanup_threads (void)
793 {
794    int i, numlocks;
795    int stat;
796
797    /* Unset thread ID callback */
798    CRYPTO_set_id_callback(NULL);
799   
800    /* Deallocate static lock mutexes */
801    numlocks = CRYPTO_num_locks();
802    for (i = 0; i < numlocks; i++) {
803       if ((stat = pthread_mutex_destroy(&mutexes[i])) != 0) {
804          /* We don't halt execution, reporting the error should be sufficient */
805          Emsg1(M_ERROR, 0, "Unable to destroy mutex: ERR=%s\n", strerror(stat));
806       }
807    }
808
809    /* Unset static locking callback */
810    CRYPTO_set_locking_callback(NULL);
811
812    /* Free static lock array */
813    free(mutexes);
814
815    /* Unset dynamic locking callbacks */
816    CRYPTO_set_dynlock_create_callback(NULL);
817    CRYPTO_set_dynlock_lock_callback(NULL);
818    CRYPTO_set_dynlock_destroy_callback(NULL);
819 }
820
821
822 /*
823  * Seed TLS PRNG
824  *  Returns: 1 on success
825  *           0 on failure
826  */
827 static int seed_tls_prng (void)
828 {
829    const char *names[]  = { "/dev/urandom", "/dev/random", NULL };
830    int i;
831
832    // ***FIXME***
833    // Win32 Support
834    // Read saved entropy?
835
836    for (i = 0; names[i]; i++) {
837       if (RAND_load_file(names[i], 1024) != -1) {
838          /* Success */
839          return 1;
840       }
841    }
842
843    /* Fail */
844    return 0;
845 }
846
847 /*
848  * Save TLS Entropy
849  *  Returns: 1 on success
850  *           0 on failure
851  */
852 static int save_tls_prng (void)
853 {
854    // ***FIXME***
855    // Implement PRNG state save
856    return 1;
857 }
858
859 /*
860  * Perform global initialization of TLS
861  * This function is not thread safe.
862  *  Returns: 0 on success
863  *           errno on failure
864  */
865 int init_tls (void)
866 {
867    int stat;
868
869    if ((stat = openssl_init_threads()) != 0) {
870       Emsg1(M_ABORT, 0, "Unable to init OpenSSL threading: ERR=%s\n", strerror(stat));
871    }
872
873    /* Load libssl and libcrypto human-readable error strings */
874    SSL_load_error_strings();
875
876    /* Register OpenSSL ciphers */
877    SSL_library_init();
878
879    if (!seed_tls_prng()) {
880       Emsg0(M_ERROR_TERM, 0, _("Failed to seed OpenSSL PRNG\n"));
881    }
882
883    tls_initialized = true;
884
885    return stat;
886 }
887
888 /*
889  * Perform global cleanup of TLS
890  * All TLS connections must be closed before calling this function.
891  * This function is not thread safe.
892  *  Returns: 0 on success
893  *           errno on failure
894  */
895 int cleanup_tls (void)
896 {
897    /*
898     * Ensure that we've actually been initialized; Doing this here decreases the
899     * complexity of client's termination/cleanup code.
900     */
901    if (!tls_initialized) {
902       return 0;
903    }
904
905    if (!save_tls_prng()) {
906       Emsg0(M_ERROR, 0, _("Failed to save OpenSSL PRNG\n"));
907    }
908
909    openssl_cleanup_threads();
910
911    /* Free libssl and libcrypto error strings */
912    ERR_free_strings();
913
914    /* Free memory used by PRNG */
915    RAND_cleanup();
916
917    tls_initialized = false;
918
919    return 0;
920 }
921
922 #else /* HAVE_OPENSSL */
923 # error No TLS implementation available.
924 #endif /* !HAVE_OPENSSL */
925
926 #endif /* HAVE_TLS */