1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2005-2010 Free Software Foundation Europe e.V.
5    Copyright (C) 2014-2018 Bareos GmbH & Co. KG
6 
7    This program is Free Software; you can redistribute it and/or
8    modify it under the terms of version three of the GNU Affero General Public
9    License as published by the Free Software Foundation and included
10    in the file LICENSE.
11 
12    This program is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15    Affero General Public License for more details.
16 
17    You should have received a copy of the GNU Affero General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20    02110-1301, USA.
21 */
22 /*
23  * tls_openssl.c TLS support functions when using OPENSSL backend.
24  *
25  * Author: Landon Fuller <landonf@threerings.net>
26  */
27 
28 #include <assert.h>
29 #include "include/bareos.h"
30 #include "lib/bpoll.h"
31 #include "lib/crypto_openssl.h"
32 
33 #if defined(HAVE_TLS) && defined(HAVE_OPENSSL)
34 
35 #include <openssl/asn1.h>
36 #include <openssl/asn1t.h>
37 #include <openssl/err.h>
38 #include <openssl/ssl.h>
39 #include <openssl/x509v3.h>
40 
41 #include "lib/tls_openssl.h"
42 #include "lib/tls_openssl_private.h"
43 #include "lib/bstringlist.h"
44 #include "include/jcr.h"
45 
46 #include "parse_conf.h"
47 
TlsOpenSsl()48 TlsOpenSsl::TlsOpenSsl() : d_(new TlsOpenSslPrivate)
49 {
50   /* the SSL_CTX object is the factory that creates
51    * openssl objects, so initialize this first */
52 
53 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
54   d_->openssl_ctx_ = SSL_CTX_new(TLS_method());
55 #else
56   d_->openssl_ctx_ = SSL_CTX_new(SSLv23_method());
57 #endif
58 
59   if (!d_->openssl_ctx_) {
60     OpensslPostErrors(M_FATAL, _("Error initializing SSL context"));
61     return;
62   }
63 
64   SSL_CTX_set_options(d_->openssl_ctx_, SSL_OP_ALL);
65 
66   SSL_CTX_set_options(d_->openssl_ctx_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
67 }
68 
~TlsOpenSsl()69 TlsOpenSsl::~TlsOpenSsl()
70 {
71   Dmsg0(100, "Destruct TLsOpenSsl Implementation Object\n");
72 }
73 
init()74 bool TlsOpenSsl::init()
75 {
76   return d_->init();
77 }
78 
SetTlsPskClientContext(const PskCredentials & credentials)79 void TlsOpenSsl::SetTlsPskClientContext(const PskCredentials &credentials)
80 {
81   if (!d_->openssl_ctx_) {
82     Dmsg0(50, "Could not set TLS_PSK CLIENT context (no SSL_CTX)\n");
83   } else {
84   BStringList ident(credentials.get_identity(), AsciiControlCharacters::RecordSeparator());
85   Dmsg1(50, "Preparing TLS_PSK CLIENT context for identity %s\n", ident.JoinReadable().c_str());
86     d_->ClientContextInsertCredentials(credentials);
87     SSL_CTX_set_psk_client_callback(d_->openssl_ctx_, TlsOpenSslPrivate::psk_client_cb);
88   }
89 }
90 
SetTlsPskServerContext(ConfigurationParser * config,GetTlsPskByFullyQualifiedResourceNameCb_t cb)91 void TlsOpenSsl::SetTlsPskServerContext(ConfigurationParser *config, GetTlsPskByFullyQualifiedResourceNameCb_t cb)
92 {
93   if (!d_->openssl_ctx_) {
94     Dmsg0(50, "Could not prepare TLS_PSK SERVER callback (no SSL_CTX)\n");
95   } else if (!config) {
96     Dmsg0(50, "Could not prepare TLS_PSK SERVER callback (no config)\n");
97   } else if (!cb) {
98     Dmsg0(50, "Could not prepare TLS_PSK SERVER callback (no callback)\n");
99   } else {
100   Dmsg0(50, "Preparing TLS_PSK SERVER callback\n");
101   SSL_CTX_set_ex_data(d_->openssl_ctx_,
102                       TlsOpenSslPrivate::SslCtxExDataIndex::kGetTlsPskByFullyQualifiedResourceNameCb,
103                       (void *)cb);
104   SSL_CTX_set_ex_data(d_->openssl_ctx_,
105                       TlsOpenSslPrivate::SslCtxExDataIndex::kConfigurationParserPtr,
106                       (void *)config);
107 
108     SSL_CTX_set_psk_server_callback(d_->openssl_ctx_, TlsOpenSslPrivate::psk_server_cb);
109   }
110 }
111 
TlsCipherGetName() const112 std::string TlsOpenSsl::TlsCipherGetName() const
113 {
114   if (!d_->openssl_) {
115     return std::string();
116   }
117 
118   const SSL_CIPHER *cipher = SSL_get_current_cipher(d_->openssl_);
119 
120   if (cipher) {
121     return std::string(SSL_CIPHER_get_name(cipher));
122   }
123 
124   return std::string();
125 }
126 
TlsLogConninfo(JobControlRecord * jcr,const char * host,int port,const char * who) const127 void TlsOpenSsl::TlsLogConninfo(JobControlRecord *jcr, const char *host, int port, const char *who) const
128 {
129   if (!d_->openssl_) {
130     Qmsg(jcr, M_INFO, 0, _("No openssl to %s at %s:%d established\n"), who, host, port);
131   } else {
132     std::string cipher_name = TlsCipherGetName();
133     Qmsg(jcr, M_INFO, 0, _("Connected %s at %s:%d, encryption: %s\n"), who, host, port,
134          cipher_name.empty() ? "Unknown" : cipher_name.c_str());
135   }
136 }
137 
138 /*
139  * Verifies a list of common names against the certificate commonName attribute.
140  *
141  * Returns: true on success
142  *          false on failure
143  */
TlsPostconnectVerifyCn(JobControlRecord * jcr,const std::vector<std::string> & verify_list)144 bool TlsOpenSsl::TlsPostconnectVerifyCn(JobControlRecord *jcr, const std::vector<std::string> &verify_list)
145 {
146   X509 *cert;
147   X509_NAME *subject;
148   bool auth_success = false;
149 
150   if (!(cert = SSL_get_peer_certificate(d_->openssl_))) {
151     Qmsg0(jcr, M_ERROR, 0, _("Peer failed to present a TLS certificate\n"));
152     return false;
153   }
154 
155   if ((subject = X509_get_subject_name(cert)) != NULL) {
156     char data[256]; /* nullterminated by X509_NAME_get_text_by_NID */
157     if (X509_NAME_get_text_by_NID(subject, NID_commonName, data, sizeof(data)) > 0) {
158       std::string cn;
159       for (const std::string &cn : verify_list) {
160         std::string d(data);
161         Dmsg2(120, "comparing CNs: cert-cn=%s, allowed-cn=%s\n", data, cn.c_str());
162         if (d.compare(cn) == 0) {
163           auth_success = true;
164         }
165       }
166     }
167   }
168 
169   X509_free(cert);
170   return auth_success;
171 }
172 
173 /*
174  * Verifies a peer's hostname against the subjectAltName and commonName attributes.
175  *
176  * Returns: true on success
177  *          false on failure
178  */
TlsPostconnectVerifyHost(JobControlRecord * jcr,const char * host)179 bool TlsOpenSsl::TlsPostconnectVerifyHost(JobControlRecord *jcr, const char *host)
180 {
181   int i, j;
182   int extensions;
183   int cnLastPos = -1;
184   X509 *cert;
185   X509_NAME *subject;
186   X509_NAME_ENTRY *neCN;
187   ASN1_STRING *asn1CN;
188   bool auth_success = false;
189 
190   if (!(cert = SSL_get_peer_certificate(d_->openssl_))) {
191     Qmsg1(jcr, M_ERROR, 0, _("Peer %s failed to present a TLS certificate\n"), host);
192     return false;
193   }
194 
195   /*
196    * Check subjectAltName extensions first
197    */
198   if ((extensions = X509_get_ext_count(cert)) > 0) {
199     for (i = 0; i < extensions; i++) {
200       X509_EXTENSION *ext;
201       const char *extname;
202 
203       ext     = X509_get_ext(cert, i);
204       extname = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
205 
206       if (bstrcmp(extname, "subjectAltName")) {
207 #if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
208         const X509V3_EXT_METHOD *method;
209 #else
210         X509V3_EXT_METHOD *method;
211 #endif
212         STACK_OF(CONF_VALUE) * val;
213         CONF_VALUE *nval;
214         void *extstr = NULL;
215 #if (OPENSSL_VERSION_NUMBER >= 0x0090800FL)
216         const unsigned char *ext_value_data;
217 #else
218         unsigned char *ext_value_data;
219 #endif
220 
221         if (!(method = X509V3_EXT_get(ext))) {
222           break;
223         }
224 
225         ext_value_data = X509_EXTENSION_get_data(ext)->data;
226 
227 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
228         if (method->it) {
229           extstr = ASN1_item_d2i(NULL, &ext_value_data, X509_EXTENSION_get_data(ext)->length,
230                                  ASN1_ITEM_ptr(method->it));
231         } else {
232           /*
233            * Old style ASN1
234            * Decode ASN1 item in data
235            */
236           extstr = method->d2i(NULL, &ext_value_data, X509_EXTENSION_get_data(ext)->length);
237         }
238 
239 #else
240         extstr = method->d2i(NULL, &ext_value_data, ext->value->length);
241 #endif
242 
243         /*
244          * Iterate through to find the dNSName field(s)
245          */
246         val = method->i2v(method, extstr, NULL);
247 
248         for (j = 0; j < sk_CONF_VALUE_num(val); j++) {
249           nval = sk_CONF_VALUE_value(val, j);
250           if (bstrcmp(nval->name, "DNS")) {
251             if (Bstrcasecmp(nval->value, host)) {
252               auth_success = true;
253               goto success;
254             }
255           }
256         }
257       }
258     }
259   }
260 
261   /*
262    * Try verifying against the subject name
263    */
264   if (!auth_success) {
265     if ((subject = X509_get_subject_name(cert)) != NULL) {
266       /*
267        * Loop through all CNs
268        */
269       for (;;) {
270         cnLastPos = X509_NAME_get_index_by_NID(subject, NID_commonName, cnLastPos);
271         if (cnLastPos == -1) {
272           break;
273         }
274         neCN   = X509_NAME_get_entry(subject, cnLastPos);
275         asn1CN = X509_NAME_ENTRY_get_data(neCN);
276         if (Bstrcasecmp((const char *)asn1CN->data, host)) {
277           auth_success = true;
278           break;
279         }
280       }
281     }
282   }
283 
284 success:
285   X509_free(cert);
286 
287   return auth_success;
288 }
289 
TlsBsockConnect(BareosSocket * bsock)290 bool TlsOpenSsl::TlsBsockConnect(BareosSocket *bsock) { return d_->OpensslBsockSessionStart(bsock, false); }
291 
TlsBsockAccept(BareosSocket * bsock)292 bool TlsOpenSsl::TlsBsockAccept(BareosSocket *bsock) { return d_->OpensslBsockSessionStart(bsock, true); }
293 
TlsBsockShutdown(BareosSocket * bsock)294 void TlsOpenSsl::TlsBsockShutdown(BareosSocket *bsock)
295 {
296   /*
297    * SSL_shutdown must be called twice to fully complete the process -
298    * The first time to initiate the shutdown handshake, and the second to
299    * receive the peer's reply.
300    *
301    * In addition, if the underlying socket is blocking, SSL_shutdown()
302    * will not return until the current stage of the shutdown process has
303    * completed or an error has occurred. By setting the socket blocking
304    * we can avoid the ugly for()/switch()/select() loop.
305    */
306 
307   if (!d_->openssl_) { return; }
308 
309   /* Set socket blocking for shutdown */
310   bsock->SetBlocking();
311 
312   btimer_t *tid = StartBsockTimer(bsock, 60 * 2);
313 
314   int err_shutdown = SSL_shutdown(d_->openssl_);
315 
316   StopBsockTimer(tid);
317 
318   if (err_shutdown == 0) {
319     /* Complete the shutdown with the second call */
320     tid = StartBsockTimer(bsock, 60 * 2);
321     err_shutdown = SSL_shutdown(d_->openssl_);
322     StopBsockTimer(tid);
323   }
324 
325   int ssl_error = SSL_get_error(d_->openssl_, err_shutdown);
326 
327   /*
328    * There may be more errors on the thread-local error-queue.
329    * As we just shutdown our context and looked at the errors that we were
330    * interested in we clear the queue so nobody else gets to read an error
331    * that may have occured here.
332    */
333   ERR_clear_error(); // empties the current thread's openssl error queue
334 
335   SSL_free(d_->openssl_);
336   d_->openssl_ = nullptr;
337 
338 
339   JobControlRecord *jcr = bsock->get_jcr();
340 
341   if (jcr && jcr->is_passive_client_connection_probing) {
342     return;
343   }
344 
345   std::string message {_("TLS shutdown failure.")};
346 
347   switch (ssl_error) {
348     case SSL_ERROR_NONE:
349       break;
350     case SSL_ERROR_ZERO_RETURN:
351       /* TLS connection was shut down on us via a TLS protocol-level closure */
352       OpensslPostErrors(jcr, M_ERROR, message.c_str());
353       break;
354     default:
355       /* Socket Error Occurred */
356       OpensslPostErrors(jcr, M_ERROR, message.c_str());
357       break;
358   }
359 }
360 
TlsBsockWriten(BareosSocket * bsock,char * ptr,int32_t nbytes)361 int TlsOpenSsl::TlsBsockWriten(BareosSocket *bsock, char *ptr, int32_t nbytes)
362 {
363   return d_->OpensslBsockReadwrite(bsock, ptr, nbytes, true);
364 }
365 
TlsBsockReadn(BareosSocket * bsock,char * ptr,int32_t nbytes)366 int TlsOpenSsl::TlsBsockReadn(BareosSocket *bsock, char *ptr, int32_t nbytes)
367 {
368   return d_->OpensslBsockReadwrite(bsock, ptr, nbytes, false);
369 }
370 
371 #endif /* HAVE_TLS  && HAVE_OPENSSL */
372