]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/tls.c
1acb404e56300684783a7f3de3bfb4163fddf355
[bacula/bacula] / bacula / src / lib / tls.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 and included
11    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  * tls.c TLS support functions
30  *
31  * Author: Landon Fuller <landonf@threerings.net>
32  *
33  * Version $Id$
34  *
35  * This file was contributed to the Bacula project by Landon Fuller
36  * and Three Rings Design, Inc.
37  *
38  * Three Rings Design, Inc. has been granted a perpetual, worldwide,
39  * non-exclusive, no-charge, royalty-free, irrevocable copyright
40  * license to reproduce, prepare derivative works of, publicly
41  * display, publicly perform, sublicense, and distribute the original
42  * work contributed by Three Rings Design, Inc. and its employees to
43  * the Bacula project in source or object form.
44  *
45  * If you wish to license contributions from Three Rings Design, Inc,
46  * under an alternate open source license please contact
47  * Landon Fuller <landonf@threerings.net>.
48  */
49
50
51 #include "bacula.h"
52 #include <assert.h>
53
54 extern time_t watchdog_time;
55
56 #ifdef HAVE_TLS /* Is TLS enabled? */
57
58 #ifdef HAVE_OPENSSL /* How about OpenSSL? */
59
60 /* No anonymous ciphers, no <128 bit ciphers, no export ciphers, no MD5 ciphers */
61 #define TLS_DEFAULT_CIPHERS "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"
62
63 /* TLS Context Structure */
64 struct TLS_Context {
65    SSL_CTX *openssl;
66    CRYPTO_PEM_PASSWD_CB *pem_callback;
67    const void *pem_userdata;
68    bool tls_enable;
69    bool tls_require;
70 };
71
72 struct TLS_Connection {
73    SSL *openssl;
74 };
75
76 /*
77  * OpenSSL certificate verification callback.
78  * OpenSSL has already performed internal certificate verification.
79  * We just report any errors that occured.
80  */
81 static int openssl_verify_peer(int ok, X509_STORE_CTX *store)
82 {
83    if (!ok) {
84       X509 *cert = X509_STORE_CTX_get_current_cert(store);
85       int depth = X509_STORE_CTX_get_error_depth(store);
86       int err = X509_STORE_CTX_get_error(store);
87       char issuer[256];
88       char subject[256];
89
90       X509_NAME_oneline(X509_get_issuer_name(cert), issuer, 256);
91       X509_NAME_oneline(X509_get_subject_name(cert), subject, 256);
92
93       Jmsg5(get_jcr_from_tid(), M_ERROR, 0, _("Error with certificate at depth: %d, issuer = %s,"
94                           " subject = %s, ERR=%d:%s\n"), depth, issuer,
95                           subject, err, X509_verify_cert_error_string(err));
96
97    }
98
99    return ok;
100 }
101
102 /* Dispatch user PEM encryption callbacks */
103 static int tls_pem_callback_dispatch (char *buf, int size, int rwflag, void *userdata)
104 {
105    TLS_CONTEXT *ctx = (TLS_CONTEXT *)userdata;
106    return (ctx->pem_callback(buf, size, ctx->pem_userdata));
107 }
108
109 /*
110  * Create a new TLS_CONTEXT instance.
111  *  Returns: Pointer to TLS_CONTEXT instance on success
112  *           NULL on failure;
113  */
114 TLS_CONTEXT *new_tls_context(const char *ca_certfile, const char *ca_certdir,
115                              const char *certfile, const char *keyfile,
116                              CRYPTO_PEM_PASSWD_CB *pem_callback,
117                              const void *pem_userdata, const char *dhfile,
118                              bool verify_peer)
119 {
120    TLS_CONTEXT *ctx;
121    BIO *bio;
122    DH *dh;
123
124    ctx = (TLS_CONTEXT *)malloc(sizeof(TLS_CONTEXT));
125
126    /* Allocate our OpenSSL TLSv1 Context */
127    ctx->openssl = SSL_CTX_new(TLSv1_method());
128
129    if (!ctx->openssl) {
130       openssl_post_errors(M_ERROR, _("Error initializing SSL context"));
131       goto err;
132    }
133
134    /* Set up pem encryption callback */
135    if (pem_callback) {
136       ctx->pem_callback = pem_callback;
137       ctx->pem_userdata = pem_userdata;
138    } else {
139       ctx->pem_callback = crypto_default_pem_callback;
140       ctx->pem_userdata = NULL;
141    }
142    SSL_CTX_set_default_passwd_cb(ctx->openssl, tls_pem_callback_dispatch);
143    SSL_CTX_set_default_passwd_cb_userdata(ctx->openssl, (void *) ctx);
144
145    /*
146     * Set certificate verification paths. This requires that at least one
147     * value be non-NULL
148     */
149    if (ca_certfile || ca_certdir) {
150       if (!SSL_CTX_load_verify_locations(ctx->openssl, ca_certfile, ca_certdir)) {
151          openssl_post_errors(M_ERROR, _("Error loading certificate verification stores"));
152          goto err;
153       }
154    } else if (verify_peer) {
155       /* At least one CA is required for peer verification */
156       Jmsg0(get_jcr_from_tid(), M_ERROR, 0, _("Either a certificate file or a directory must be"
157                          " specified as a verification store\n"));
158       goto err;
159    }
160
161    /*
162     * Load our certificate file, if available. This file may also contain a
163     * private key, though this usage is somewhat unusual.
164     */
165    if (certfile) {
166       if (!SSL_CTX_use_certificate_chain_file(ctx->openssl, certfile)) {
167          openssl_post_errors(M_ERROR, _("Error loading certificate file"));
168          goto err;
169       }
170    }
171
172    /* Load our private key. */
173    if (keyfile) {
174       if (!SSL_CTX_use_PrivateKey_file(ctx->openssl, keyfile, SSL_FILETYPE_PEM)) {
175          openssl_post_errors(M_ERROR, _("Error loading private key"));
176          goto err;
177       }
178    }
179
180    /* Load Diffie-Hellman Parameters. */
181    if (dhfile) {
182       if (!(bio = BIO_new_file(dhfile, "r"))) {
183          openssl_post_errors(M_ERROR, _("Unable to open DH parameters file"));
184          goto err;
185       }
186       dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
187       BIO_free(bio);
188       if (!dh) {
189          openssl_post_errors(M_ERROR, _("Unable to load DH parameters from specified file"));
190          goto err;
191       }
192       if (!SSL_CTX_set_tmp_dh(ctx->openssl, dh)) {
193          openssl_post_errors(M_ERROR, _("Failed to set TLS Diffie-Hellman parameters"));
194          DH_free(dh);
195          goto err;
196       }
197       /* Enable Single-Use DH for Ephemeral Keying */
198       SSL_CTX_set_options(ctx->openssl, SSL_OP_SINGLE_DH_USE);
199    }
200
201    if (SSL_CTX_set_cipher_list(ctx->openssl, TLS_DEFAULT_CIPHERS) != 1) {
202       Jmsg0(get_jcr_from_tid(), M_ERROR, 0,
203              _("Error setting cipher list, no valid ciphers available\n"));
204       goto err;
205    }
206
207    /* Verify Peer Certificate */
208    if (verify_peer) {
209       /* SSL_VERIFY_FAIL_IF_NO_PEER_CERT has no effect in client mode */
210       SSL_CTX_set_verify(ctx->openssl,
211                          SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
212                          openssl_verify_peer);
213    }
214
215    return ctx;
216
217 err:
218    /* Clean up after ourselves */
219    if(ctx->openssl) {
220       SSL_CTX_free(ctx->openssl);
221    }
222    free(ctx);
223    return NULL;
224 }
225
226 /*
227  * Free TLS_CONTEXT instance
228  */
229 void free_tls_context(TLS_CONTEXT *ctx)
230 {
231    SSL_CTX_free(ctx->openssl);
232    free(ctx);
233 }
234
235 bool get_tls_require(TLS_CONTEXT *ctx) 
236 {
237    return ctx->tls_require;
238 }
239
240 bool get_tls_enable(TLS_CONTEXT *ctx) 
241 {
242    return ctx->tls_enable;
243 }
244
245
246 /*
247  * Verifies a list of common names against the certificate
248  * commonName attribute.
249  *  Returns: true on success
250  *           false on failure
251  */
252 bool tls_postconnect_verify_cn(TLS_CONNECTION *tls, alist *verify_list)
253 {
254    SSL *ssl = tls->openssl;
255    X509 *cert;
256    X509_NAME *subject;
257    bool auth_success = false;
258    char data[256];
259
260    /* Check if peer provided a certificate */
261    if (!(cert = SSL_get_peer_certificate(ssl))) {
262       Jmsg0(get_jcr_from_tid(), M_ERROR, 0, _("Peer failed to present a TLS certificate\n"));
263       return false;
264    }
265
266    if ((subject = X509_get_subject_name(cert)) != NULL) {
267       if (X509_NAME_get_text_by_NID(subject, NID_commonName, data, sizeof(data)) > 0) {
268          char *cn;
269          /* NULL terminate data */
270          data[255] = 0;
271
272          /* Try all the CNs in the list */
273          foreach_alist(cn, verify_list) {
274             if (strcasecmp(data, cn) == 0) {
275                auth_success = true;
276             }
277          }
278       }
279    }
280
281    X509_free(cert);
282    return auth_success;
283 }
284
285 /*
286  * Verifies a peer's hostname against the subjectAltName and commonName
287  * attributes.
288  *  Returns: true on success
289  *           false on failure
290  */
291 bool tls_postconnect_verify_host(TLS_CONNECTION *tls, const char *host)
292 {
293    SSL *ssl = tls->openssl;
294    X509 *cert;
295    X509_NAME *subject;
296    bool auth_success = false;
297    int extensions;
298    char data[256];
299    int i, j;
300
301
302    /* Check if peer provided a certificate */
303    if (!(cert = SSL_get_peer_certificate(ssl))) {
304       Jmsg1(get_jcr_from_tid(), M_ERROR, 0, 
305             _("Peer %s failed to present a TLS certificate\n"), host);
306       return false;
307    }
308
309    /* Check subjectAltName extensions first */
310    if ((extensions = X509_get_ext_count(cert)) > 0) {
311       for (i = 0; i < extensions; i++) {
312          X509_EXTENSION *ext;
313          const char *extname;
314
315          ext = X509_get_ext(cert, i);
316          extname = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
317
318          if (strcmp(extname, "subjectAltName") == 0) {
319             X509V3_EXT_METHOD *method;
320             STACK_OF(CONF_VALUE) *val;
321             CONF_VALUE *nval;
322             void *extstr = NULL;
323 #if (OPENSSL_VERSION_NUMBER >= 0x0090800FL)
324             const unsigned char *ext_value_data;
325 #else
326             unsigned char *ext_value_data;
327 #endif
328
329             /* Get x509 extension method structure */
330             if (!(method = X509V3_EXT_get(ext))) {
331                break;
332             }
333
334             ext_value_data = ext->value->data;
335
336 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
337             if (method->it) {
338                /* New style ASN1 */
339
340                /* Decode ASN1 item in data */
341                extstr = ASN1_item_d2i(NULL, &ext_value_data, ext->value->length,
342                                       ASN1_ITEM_ptr(method->it));
343             } else {
344                /* Old style ASN1 */
345
346                /* Decode ASN1 item in data */
347                extstr = method->d2i(NULL, &ext_value_data, ext->value->length);
348             }
349
350 #else
351             extstr = method->d2i(NULL, &ext_value_data, ext->value->length);
352 #endif
353
354             /* Iterate through to find the dNSName field(s) */
355             val = method->i2v(method, extstr, NULL);
356
357             /* dNSName shortname is "DNS" */
358             for (j = 0; j < sk_CONF_VALUE_num(val); j++) {
359                nval = sk_CONF_VALUE_value(val, j);
360                if (strcmp(nval->name, "DNS") == 0) {
361                   if (strcasecmp(nval->value, host) == 0) {
362                      auth_success = true;
363                      goto success;
364                   }
365                }
366             }
367          }
368       }
369    }
370
371    /* Try verifying against the subject name */
372    if (!auth_success) {
373       if ((subject = X509_get_subject_name(cert)) != NULL) {
374          if (X509_NAME_get_text_by_NID(subject, NID_commonName, data, sizeof(data)) > 0) {
375             /* NULL terminate data */
376             data[255] = 0;
377             if (strcasecmp(data, host) == 0) {
378                auth_success = true;
379             }
380          }
381       }
382    }
383
384 success:
385    X509_free(cert);
386
387    return auth_success;
388 }
389
390 /*
391  * Create a new TLS_CONNECTION instance.
392  *
393  * Returns: Pointer to TLS_CONNECTION instance on success
394  *          NULL on failure;
395  */
396 TLS_CONNECTION *new_tls_connection(TLS_CONTEXT *ctx, int fd)
397 {
398    BIO *bio;
399
400    /*
401     * Create a new BIO and assign the fd.
402     * The caller will remain responsible for closing the associated fd
403     */
404    bio = BIO_new(BIO_s_socket());
405    if (!bio) {
406       /* Not likely, but never say never */
407       openssl_post_errors(M_ERROR, _("Error creating file descriptor-based BIO"));
408       return NULL; /* Nothing allocated, nothing to clean up */
409    }
410    BIO_set_fd(bio, fd, BIO_NOCLOSE);
411
412    /* Allocate our new tls connection */
413    TLS_CONNECTION *tls = (TLS_CONNECTION *)malloc(sizeof(TLS_CONNECTION));
414
415    /* Create the SSL object and attach the socket BIO */
416    if ((tls->openssl = SSL_new(ctx->openssl)) == NULL) {
417       /* Not likely, but never say never */
418       openssl_post_errors(M_ERROR, _("Error creating new SSL object"));
419       goto err;
420    }
421
422    SSL_set_bio(tls->openssl, bio, bio);
423
424    /* Non-blocking partial writes */
425    SSL_set_mode(tls->openssl, SSL_MODE_ENABLE_PARTIAL_WRITE|SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
426
427    return tls;
428
429 err:
430    /* Clean up */
431    BIO_free(bio);
432    SSL_free(tls->openssl);
433    free(tls);
434    return NULL;
435 }
436
437 /*
438  * Free TLS_CONNECTION instance
439  */
440 void free_tls_connection(TLS_CONNECTION *tls)
441 {
442    SSL_free(tls->openssl);
443    free(tls);
444 }
445
446 /* Does all the manual labor for tls_bsock_accept() and tls_bsock_connect() */
447 static inline bool openssl_bsock_session_start(BSOCK *bsock, bool server)
448 {
449    TLS_CONNECTION *tls = bsock->tls;
450    int err;
451    int fdmax, flags;
452    int stat = true;
453    fd_set fdset;
454    struct timeval tv;
455
456    /* Zero the fdset, we'll set our fd prior to each invocation of select() */
457    FD_ZERO(&fdset);
458    fdmax = bsock->m_fd + 1;
459
460    /* Ensure that socket is non-blocking */
461    flags = bsock->set_nonblocking();
462
463    /* start timer */
464    bsock->timer_start = watchdog_time;
465    bsock->clear_timed_out();
466
467    for (;;) { 
468       if (server) {
469          err = SSL_accept(tls->openssl);
470       } else {
471          err = SSL_connect(tls->openssl);
472       }
473
474       /* Handle errors */
475       switch (SSL_get_error(tls->openssl, err)) {
476       case SSL_ERROR_NONE:
477          stat = true;
478          goto cleanup;
479       case SSL_ERROR_ZERO_RETURN:
480          /* TLS connection was cleanly shut down */
481          openssl_post_errors(M_ERROR, _("Connect failure"));
482          stat = false;
483          goto cleanup;
484       case SSL_ERROR_WANT_READ:
485          /* If we timeout of a select, this will be unset */
486          FD_SET((unsigned) bsock->m_fd, &fdset);
487          /* Set our timeout */
488          tv.tv_sec = 10;
489          tv.tv_usec = 0;
490          /* Block until we can read */
491          select(fdmax, &fdset, NULL, &fdset, &tv);
492          break;
493       case SSL_ERROR_WANT_WRITE:
494          /* If we timeout of a select, this will be unset */
495          FD_SET((unsigned) bsock->m_fd, &fdset);
496          /* Set our timeout */
497          tv.tv_sec = 10;
498          tv.tv_usec = 0;
499          /* Block until we can write */
500          select(fdmax, NULL, &fdset, &fdset, &tv);
501          break;
502       default:
503          /* Socket Error Occured */
504          openssl_post_errors(M_ERROR, _("Connect failure"));
505          stat = false;
506          goto cleanup;
507       }
508
509       if (bsock->is_timed_out()) {
510          goto cleanup;
511       }
512    }
513
514 cleanup:
515    /* Restore saved flags */
516    bsock->restore_blocking(flags);
517    /* Clear timer */
518    bsock->timer_start = 0;
519
520    return stat;
521 }
522
523 /*
524  * Initiates a TLS connection with the server.
525  *  Returns: true on success
526  *           false on failure
527  */
528 bool tls_bsock_connect(BSOCK *bsock)
529 {
530    /* SSL_connect(bsock->tls) */
531    return openssl_bsock_session_start(bsock, false);
532 }
533
534 /*
535  * Listens for a TLS connection from a client.
536  *  Returns: true on success
537  *           false on failure
538  */
539 bool tls_bsock_accept(BSOCK *bsock)
540 {
541    /* SSL_accept(bsock->tls) */
542    return openssl_bsock_session_start(bsock, true);
543 }
544
545 /*
546  * Shutdown TLS_CONNECTION instance
547  */
548 void tls_bsock_shutdown(BSOCK *bsock)
549 {
550    /*
551     * SSL_shutdown must be called twice to fully complete the process -
552     * The first time to initiate the shutdown handshake, and the second to
553     * receive the peer's reply.
554     *
555     * However, it is valid to close the SSL connection after the initial
556     * shutdown notification is sent to the peer, without waiting for the
557     * peer's reply, as long as you do not plan to re-use that particular
558     * SSL connection object.
559     *
560     * Because we do not re-use SSL connection objects, I do not bother
561     * calling SSL_shutdown a second time.
562     *
563     * In addition, if the underlying socket is blocking, SSL_shutdown()
564     * will not return until the current stage of the shutdown process has
565     * completed or an error has occured. By setting the socket blocking
566     * we can avoid the ugly for()/switch()/select() loop.
567     */
568    int err;
569    int flags;
570
571    /* Set socket blocking for shutdown */
572    bsock->set_blocking();
573
574    err = SSL_shutdown(bsock->tls->openssl);
575
576    switch (SSL_get_error(bsock->tls->openssl, err)) {
577    case SSL_ERROR_NONE:
578       break;
579    case SSL_ERROR_ZERO_RETURN:
580       /* TLS connection was shut down on us via a TLS protocol-level closure */
581       openssl_post_errors(M_ERROR, _("TLS shutdown failure."));
582       break;
583    default:
584       /* Socket Error Occured */
585       openssl_post_errors(M_ERROR, _("TLS shutdown failure."));
586       break;
587    }
588 }
589
590 /* Does all the manual labor for tls_bsock_readn() and tls_bsock_writen() */
591 static inline int openssl_bsock_readwrite(BSOCK *bsock, char *ptr, int nbytes, bool write)
592 {
593    TLS_CONNECTION *tls = bsock->tls;
594    int fdmax, flags;
595    fd_set fdset;
596    struct timeval tv;
597    int nleft = 0;
598    int nwritten = 0;
599
600    /* Zero the fdset, we'll set our fd prior to each invocation of select() */
601    FD_ZERO(&fdset);
602    fdmax = bsock->m_fd + 1;
603
604    /* Ensure that socket is non-blocking */
605    flags = bsock->set_nonblocking();
606
607    /* start timer */
608    bsock->timer_start = watchdog_time;
609    bsock->clear_timed_out();
610
611    nleft = nbytes;
612
613    while (nleft > 0) { 
614       if (write) {
615          nwritten = SSL_write(tls->openssl, ptr, nleft);
616       } else {
617          nwritten = SSL_read(tls->openssl, ptr, nleft);
618       }
619
620       /* Handle errors */
621       switch (SSL_get_error(tls->openssl, nwritten)) {
622       case SSL_ERROR_NONE:
623          nleft -= nwritten;
624          if (nleft) {
625             ptr += nwritten;
626          }
627          break;
628
629       case SSL_ERROR_WANT_READ:
630       case SSL_ERROR_WANT_WRITE:
631          /* If we timeout on a select, this will be unset */
632          FD_SET((unsigned)bsock->m_fd, &fdset);
633          tv.tv_sec = 10;
634          tv.tv_usec = 0;
635          /* Block until we can read or write */
636          select(fdmax, NULL, &fdset, &fdset, &tv);
637          break;
638
639       case SSL_ERROR_ZERO_RETURN:
640          /* TLS connection was cleanly shut down */
641          /* Fall through wanted */
642       default:
643          /* Socket Error Occured */
644          openssl_post_errors(M_ERROR, _("TLS read/write failure."));
645          goto cleanup;
646       }
647
648       /* Everything done? */
649       if (nleft == 0) {
650          goto cleanup;
651       }
652
653       /* Timeout/Termination, let's take what we can get */
654       if (bsock->is_timed_out() || bsock->is_terminated()) {
655          goto cleanup;
656       }
657    }
658
659 cleanup:
660    /* Restore saved flags */
661    bsock->restore_blocking(flags);
662
663    /* Clear timer */
664    bsock->timer_start = 0;
665    return nbytes - nleft;
666 }
667
668
669 int tls_bsock_writen(BSOCK *bsock, char *ptr, int32_t nbytes) 
670 {
671    /* SSL_write(bsock->tls->openssl, ptr, nbytes) */
672    return openssl_bsock_readwrite(bsock, ptr, nbytes, true);
673 }
674
675 int tls_bsock_readn(BSOCK *bsock, char *ptr, int32_t nbytes) 
676 {
677    /* SSL_read(bsock->tls->openssl, ptr, nbytes) */
678    return openssl_bsock_readwrite(bsock, ptr, nbytes, false);
679 }
680
681 #else /* HAVE_OPENSSL */
682 # error No TLS implementation available.
683 #endif /* !HAVE_OPENSSL */
684
685
686 #else     /* TLS NOT enabled, dummy routines substituted */
687
688
689 /* Dummy routines */
690 TLS_CONTEXT *new_tls_context(const char *ca_certfile, const char *ca_certdir,
691                              const char *certfile, const char *keyfile,
692                              CRYPTO_PEM_PASSWD_CB *pem_callback,
693                              const void *pem_userdata, const char *dhfile,
694                              bool verify_peer)
695 {
696    return NULL;
697 }
698 void free_tls_context(TLS_CONTEXT *ctx) { }
699
700 void tls_bsock_shutdown(BSOCK *bsock) { }
701
702 void free_tls_connection(TLS_CONNECTION *tls) { }
703
704 bool get_tls_require(TLS_CONTEXT *ctx) 
705 {
706    return false;
707 }
708
709 bool get_tls_enable(TLS_CONTEXT *ctx) 
710 {
711    return false;
712 }
713
714 #endif /* HAVE_TLS */