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