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