xref: /haiku/src/kits/network/libnetapi/SecureSocket.cpp (revision 4d8811742fa447ec05b4993a16a0931bc29aafab)
1 /*
2  * Copyright 2013-2016 Haiku, Inc.
3  * Copyright 2011-2015, Axel Dörfler, axeld@pinc-software.de.
4  * Copyright 2016, Rene Gollent, rene@gollent.com.
5  * Copyright 2010, Clemens Zeidler <haiku@clemens-zeidler.de>
6  * Distributed under the terms of the MIT License.
7  */
8 
9 
10 #include <SecureSocket.h>
11 
12 #ifdef OPENSSL_ENABLED
13 #	include <openssl/ssl.h>
14 #	include <openssl/err.h>
15 #endif
16 
17 #include <pthread.h>
18 
19 #include <Certificate.h>
20 #include <FindDirectory.h>
21 #include <Path.h>
22 
23 #include <AutoDeleter.h>
24 
25 #include "CertificatePrivate.h"
26 
27 
28 //#define TRACE_SOCKET
29 #ifdef TRACE_SOCKET
30 #	define TRACE(x...) printf(x)
31 #else
32 #	define TRACE(x...) ;
33 #endif
34 
35 
36 #ifdef OPENSSL_ENABLED
37 
38 
39 class BSecureSocket::Private {
40 public:
41 								Private();
42 								~Private();
43 
44 			status_t			InitCheck();
45 			status_t			ErrorCode(int returnValue);
46 
47 	static	SSL_CTX*			Context();
48 	static	int					VerifyCallback(int ok, X509_STORE_CTX* ctx);
49 
50 private:
51 	static	void				_CreateContext();
52 
53 public:
54 			SSL*				fSSL;
55 			BIO*				fBIO;
56 	static	int					sDataIndex;
57 
58 private:
59 	static	SSL_CTX*			sContext;
60 		// FIXME When do we SSL_CTX_free it?
61 	static	pthread_once_t		sInitOnce;
62 };
63 
64 
65 /* static */ SSL_CTX* BSecureSocket::Private::sContext = NULL;
66 /* static */ int BSecureSocket::Private::sDataIndex;
67 /* static */ pthread_once_t BSecureSocket::Private::sInitOnce
68 	= PTHREAD_ONCE_INIT;
69 
70 
71 BSecureSocket::Private::Private()
72 	:
73 	fSSL(NULL),
74 	fBIO(BIO_new(BIO_s_socket()))
75 {
76 }
77 
78 
79 BSecureSocket::Private::~Private()
80 {
81 	// SSL_free also frees the underlying BIO.
82 	if (fSSL != NULL)
83 		SSL_free(fSSL);
84 	else {
85 		// The SSL session was never created (Connect() was not called or
86 		// failed). We must free the BIO we created in the constructor.
87 		BIO_free(fBIO);
88 	}
89 }
90 
91 
92 status_t
93 BSecureSocket::Private::InitCheck()
94 {
95 	if (fBIO == NULL)
96 		return B_NO_MEMORY;
97 	return B_OK;
98 }
99 
100 
101 status_t
102 BSecureSocket::Private::ErrorCode(int returnValue)
103 {
104 	int error = SSL_get_error(fSSL, returnValue);
105 	switch (error) {
106 		case SSL_ERROR_NONE:
107 			// Shouldn't happen...
108 			return B_NO_ERROR;
109 		case SSL_ERROR_ZERO_RETURN:
110 			// Socket is closed
111 			return B_CANCELED;
112 		case SSL_ERROR_SSL:
113 			// Probably no certificate
114 			return B_NOT_ALLOWED;
115 
116 		case SSL_ERROR_WANT_READ:
117 		case SSL_ERROR_WANT_WRITE:
118 		case SSL_ERROR_WANT_CONNECT:
119 		case SSL_ERROR_WANT_ACCEPT:
120 		case SSL_ERROR_WANT_X509_LOOKUP:
121 		case SSL_ERROR_SYSCALL:
122 		default:
123 			// TODO: translate SSL error codes!
124 			fprintf(stderr, "SSL %s\n", ERR_error_string(error, NULL));
125 			return B_ERROR;
126 	}
127 }
128 
129 
130 /* static */ SSL_CTX*
131 BSecureSocket::Private::Context()
132 {
133 	// We use lazy initialisation here, because reading certificates from disk
134 	// and parsing them is a relatively long operation and uses some memory.
135 	// We don't want programs that don't use SSL to waste resources with that.
136 	pthread_once(&sInitOnce, _CreateContext);
137 
138 	return sContext;
139 }
140 
141 
142 /*!	This is called each time a certificate verification occurs. It allows us to
143 	catch failures and report them.
144 */
145 /* static */ int
146 BSecureSocket::Private::VerifyCallback(int ok, X509_STORE_CTX* ctx)
147 {
148 	// OpenSSL already checked the certificate again the certificate store for
149 	// us, and tells the result of that in the ok parameter.
150 
151 	// If the verification succeeded, no need for any further checks. Let's
152 	// proceed with the connection.
153 	if (ok)
154 		return ok;
155 
156 	// The certificate verification failed. Signal this to the BSecureSocket.
157 
158 	// First of all, get the affected BSecureSocket
159 	SSL* ssl = (SSL*)X509_STORE_CTX_get_ex_data(ctx,
160 		SSL_get_ex_data_X509_STORE_CTX_idx());
161 	BSecureSocket* socket = (BSecureSocket*)SSL_get_ex_data(ssl, sDataIndex);
162 
163 	// Get the certificate that we could not validate (this may not be the one
164 	// we got from the server, but something higher up in the certificate
165 	// chain)
166 	X509* x509 = X509_STORE_CTX_get_current_cert(ctx);
167 	BCertificate::Private* certificate
168 		= new(std::nothrow) BCertificate::Private(x509);
169 
170 	if (certificate == NULL)
171 		return 0;
172 
173 	int error = X509_STORE_CTX_get_error(ctx);
174 	const char* message = X509_verify_cert_error_string(error);
175 
176 	// Let the BSecureSocket (or subclass) decide if we should continue anyway.
177 	BCertificate failedCertificate(certificate);
178 	return socket->CertificateVerificationFailed(failedCertificate, message);
179 }
180 
181 
182 #if TRACE_SSL
183 static void apps_ssl_info_callback(const SSL *s, int where, int ret)
184 {
185 	const char *str;
186 	int w;
187 
188 	w=where& ~SSL_ST_MASK;
189 
190 	if (w & SSL_ST_CONNECT) str="SSL_connect";
191 	else if (w & SSL_ST_ACCEPT) str="SSL_accept";
192 	else str="undefined";
193 
194 	if (where & SSL_CB_LOOP)
195 	{
196 		fprintf(stderr,"%s:%s\n",str,SSL_state_string_long(s));
197 	}
198 	else if (where & SSL_CB_ALERT)
199 	{
200 		str=(where & SSL_CB_READ)?"read":"write";
201 		fprintf(stderr,"SSL3 alert %s:%s:%s\n",
202 				str,
203 				SSL_alert_type_string_long(ret),
204 				SSL_alert_desc_string_long(ret));
205 	}
206 	else if (where & SSL_CB_EXIT)
207 	{
208 		if (ret == 0)
209 			fprintf(stderr,"%s:failed in %s\n",
210 					str,SSL_state_string_long(s));
211 		else if (ret < 0)
212 		{
213 			fprintf(stderr,"%s:error in %s\n",
214 					str,SSL_state_string_long(s));
215 		}
216 	}
217 }
218 #endif
219 
220 
221 /* static */ void
222 BSecureSocket::Private::_CreateContext()
223 {
224 	// We want SSL to report errors in human readable format.
225 	SSL_load_error_strings();
226 
227 	sContext = SSL_CTX_new(SSLv23_method());
228 
229 #if TRACE_SSL
230 	// For debugging purposes: get all SSL messages to the standard error.
231 	SSL_CTX_set_info_callback(sContext, apps_ssl_info_callback);
232 #endif
233 
234 	// Disable legacy protocols. They have known vulnerabilities.
235 	SSL_CTX_set_options(sContext, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
236 
237 	// Disable SSL/TLS compression to prevent the CRIME attack.
238 	SSL_CTX_set_options(sContext, SSL_OP_NO_COMPRESSION);
239 
240 	// Don't bother us with ERROR_WANT_READ.
241 	SSL_CTX_set_mode(sContext, SSL_MODE_AUTO_RETRY);
242 
243 	// Setup cipher suites.
244 	// These suites are mostly the same ones used by Firefox 47 and Chrome 50.
245 	SSL_CTX_set_cipher_list(sContext,
246 		"ECDHE-ECDSA-AES128-GCM-SHA256:"
247 		"ECDHE-RSA-AES128-GCM-SHA256:"
248 		"ECDHE-ECDSA-AES256-GCM-SHA384:"
249 		"ECDHE-RSA-AES256-GCM-SHA384:"
250 		"ECDHE-ECDSA-CHACHA20-POLY1305-SHA256:"
251 		"ECDHE-RSA-CHACHA20-POLY1305-SHA256:"
252 		"ECDHE-ECDSA-AES256-SHA:"
253 		"ECDHE-ECDSA-AES128-SHA:"
254 		"ECDHE-RSA-AES128-SHA:"
255 		"ECDHE-RSA-AES256-SHA:"
256 		"DHE-RSA-AES128-SHA:"
257 		"DHE-RSA-AES256-SHA:"
258 		"AES128-SHA:"
259 		"AES256-SHA");
260 
261 	// Let OpenSSL choose the most appropriate D-H curve for us
262 	SSL_CTX_set_ecdh_auto(sContext, 1);
263 
264 	// Setup certificate verification
265 	BPath certificateStore;
266 	find_directory(B_SYSTEM_DATA_DIRECTORY, &certificateStore);
267 	certificateStore.Append("ssl/CARootCertificates.pem");
268 	// TODO we may want to add a non-packaged certificate directory?
269 	// (would make it possible to store user-added certificate exceptions
270 	// there)
271 	SSL_CTX_load_verify_locations(sContext, certificateStore.Path(), NULL);
272 	SSL_CTX_set_verify(sContext, SSL_VERIFY_PEER, VerifyCallback);
273 
274 	// OpenSSL 1.0.2 and later: use the alternate "trusted first" algorithm to validate certificate
275 	// chains. This makes the validation stop as soon as a recognized certificate is found in the
276 	// chain, instead of validating the whole chain, then seeing if the root certificate is known.
277 #ifdef X509_V_FLAG_TRUSTED_FIRST
278 	X509_VERIFY_PARAM* verifyParam = X509_VERIFY_PARAM_new();
279 	X509_VERIFY_PARAM_set_flags(verifyParam, X509_V_FLAG_TRUSTED_FIRST);
280 	SSL_CTX_set1_param(sContext, verifyParam);
281 
282 	// TODO we need to free this after freeing the SSL context (which we currently never do)
283 	// X509_VERIFY_PARAM_free(verifyParam);
284 #endif
285 
286 	// Get an unique index number for storing application data in SSL
287 	// structs. We will store a pointer to the BSecureSocket class there.
288 	sDataIndex = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
289 }
290 
291 
292 // # pragma mark - BSecureSocket
293 
294 
295 BSecureSocket::BSecureSocket()
296 	:
297 	fPrivate(new(std::nothrow) BSecureSocket::Private())
298 {
299 	fInitStatus = fPrivate != NULL ? fPrivate->InitCheck() : B_NO_MEMORY;
300 }
301 
302 
303 BSecureSocket::BSecureSocket(const BNetworkAddress& peer, bigtime_t timeout)
304 	:
305 	fPrivate(new(std::nothrow) BSecureSocket::Private())
306 {
307 	fInitStatus = fPrivate != NULL ? fPrivate->InitCheck() : B_NO_MEMORY;
308 	Connect(peer, timeout);
309 }
310 
311 
312 BSecureSocket::BSecureSocket(const BSecureSocket& other)
313 	:
314 	BSocket(other)
315 {
316 	fPrivate = new(std::nothrow) BSecureSocket::Private(*other.fPrivate);
317 		// TODO: this won't work this way! - write working copy constructor for
318 		// Private.
319 
320 	if (fPrivate != NULL)
321 		SSL_set_ex_data(fPrivate->fSSL, Private::sDataIndex, this);
322 	else
323 		fInitStatus = B_NO_MEMORY;
324 
325 }
326 
327 
328 BSecureSocket::~BSecureSocket()
329 {
330 	delete fPrivate;
331 }
332 
333 
334 status_t
335 BSecureSocket::Accept(BAbstractSocket*& _socket)
336 {
337 	int fd = -1;
338 	BNetworkAddress peer;
339 	status_t error = AcceptNext(fd, peer);
340 	if (error != B_OK)
341 		return error;
342 	BSecureSocket* socket = new(std::nothrow) BSecureSocket();
343 	ObjectDeleter<BSecureSocket> socketDeleter(socket);
344 	if (socket == NULL || socket->InitCheck() != B_OK) {
345 		close(fd);
346 		return B_NO_MEMORY;
347 	}
348 
349 	socket->_SetTo(fd, fLocal, peer);
350 	error = socket->_SetupAccept();
351 	if (error != B_OK)
352 		return error;
353 
354 	_socket = socket;
355 	socketDeleter.Detach();
356 
357 	return B_OK;
358 }
359 
360 
361 status_t
362 BSecureSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout)
363 {
364 	status_t status = InitCheck();
365 	if (status != B_OK)
366 		return status;
367 
368 	status = BSocket::Connect(peer, timeout);
369 	if (status != B_OK)
370 		return status;
371 
372 	return _SetupConnect(peer.HostName().String());
373 }
374 
375 
376 void
377 BSecureSocket::Disconnect()
378 {
379 	if (IsConnected()) {
380 		if (fPrivate->fSSL != NULL)
381 			SSL_shutdown(fPrivate->fSSL);
382 
383 		BSocket::Disconnect();
384 	}
385 }
386 
387 
388 status_t
389 BSecureSocket::WaitForReadable(bigtime_t timeout) const
390 {
391 	if (fInitStatus != B_OK)
392 		return fInitStatus;
393 	if (!IsConnected())
394 		return B_ERROR;
395 
396 	if (SSL_pending(fPrivate->fSSL) > 0)
397 		return B_OK;
398 
399 	return BSocket::WaitForReadable(timeout);
400 }
401 
402 
403 status_t
404 BSecureSocket::InitCheck()
405 {
406 	if (fPrivate == NULL)
407 		return B_NO_MEMORY;
408 
409 	status_t state = fPrivate->InitCheck();
410 	return state;
411 }
412 
413 
414 bool
415 BSecureSocket::CertificateVerificationFailed(BCertificate&, const char*)
416 {
417 	// Until apps actually make use of the certificate API, let's keep the old
418 	// behavior and accept all connections, even if the certificate validation
419 	// didn't work.
420 	return true;
421 }
422 
423 
424 //	#pragma mark - BDataIO implementation
425 
426 
427 ssize_t
428 BSecureSocket::Read(void* buffer, size_t size)
429 {
430 	if (!IsConnected())
431 		return B_ERROR;
432 
433 	int bytesRead = SSL_read(fPrivate->fSSL, buffer, size);
434 	if (bytesRead >= 0)
435 		return bytesRead;
436 
437 	return fPrivate->ErrorCode(bytesRead);
438 }
439 
440 
441 ssize_t
442 BSecureSocket::Write(const void* buffer, size_t size)
443 {
444 	if (!IsConnected())
445 		return B_ERROR;
446 
447 	int bytesWritten = SSL_write(fPrivate->fSSL, buffer, size);
448 	if (bytesWritten >= 0)
449 		return bytesWritten;
450 
451 	return fPrivate->ErrorCode(bytesWritten);
452 }
453 
454 
455 status_t
456 BSecureSocket::_SetupCommon(const char* host)
457 {
458 	// Do this only after BSocket::Connect has checked wether we're already
459 	// connected. We don't want to kill an existing SSL session, as that would
460 	// likely crash the protocol loop for it.
461 	if (fPrivate->fSSL != NULL) {
462 		SSL_free(fPrivate->fSSL);
463 	}
464 
465 	fPrivate->fSSL = SSL_new(BSecureSocket::Private::Context());
466 	if (fPrivate->fSSL == NULL) {
467 		BSocket::Disconnect();
468 		return B_NO_MEMORY;
469 	}
470 
471 	BIO_set_fd(fPrivate->fBIO, fSocket, BIO_NOCLOSE);
472 	SSL_set_bio(fPrivate->fSSL, fPrivate->fBIO, fPrivate->fBIO);
473 	SSL_set_ex_data(fPrivate->fSSL, Private::sDataIndex, this);
474 	if (host != NULL) {
475 		BString hostString = host;
476 		if (hostString != "")
477 			SSL_set_tlsext_host_name(fPrivate->fSSL, host);
478 	}
479 
480 	return B_OK;
481 }
482 
483 
484 status_t
485 BSecureSocket::_SetupConnect(const char* host)
486 {
487 	status_t error = _SetupCommon(host);
488 	if (error != B_OK)
489 		return error;
490 
491 	int returnValue = SSL_connect(fPrivate->fSSL);
492 	if (returnValue <= 0) {
493 		TRACE("SSLConnection can't connect\n");
494 		BSocket::Disconnect();
495 		return fPrivate->ErrorCode(returnValue);
496 	}
497 
498 	return B_OK;
499 }
500 
501 
502 status_t
503 BSecureSocket::_SetupAccept()
504 {
505 	status_t error = _SetupCommon();
506 	if (error != B_OK)
507 		return error;
508 
509 	int returnValue = SSL_accept(fPrivate->fSSL);
510 	if (returnValue <= 0) {
511 		TRACE("SSLConnection can't accept\n");
512 		BSocket::Disconnect();
513 		return fPrivate->ErrorCode(returnValue);
514 	}
515 
516 	return B_OK;
517 }
518 
519 
520 #else	// OPENSSL_ENABLED
521 
522 
523 // #pragma mark - No-SSL stubs
524 
525 
526 BSecureSocket::BSecureSocket()
527 {
528 }
529 
530 
531 BSecureSocket::BSecureSocket(const BNetworkAddress& peer, bigtime_t timeout)
532 {
533 	fInitStatus = B_UNSUPPORTED;
534 }
535 
536 
537 BSecureSocket::BSecureSocket(const BSecureSocket& other)
538 	:
539 	BSocket(other)
540 {
541 }
542 
543 
544 BSecureSocket::~BSecureSocket()
545 {
546 }
547 
548 
549 bool
550 BSecureSocket::CertificateVerificationFailed(BCertificate& certificate, const char*)
551 {
552 	(void)certificate;
553 	return false;
554 }
555 
556 
557 status_t
558 BSecureSocket::Accept(BAbstractSocket*& _socket)
559 {
560 	return B_UNSUPPORTED;
561 }
562 
563 
564 status_t
565 BSecureSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout)
566 {
567 	return fInitStatus = B_UNSUPPORTED;
568 }
569 
570 
571 void
572 BSecureSocket::Disconnect()
573 {
574 }
575 
576 
577 status_t
578 BSecureSocket::WaitForReadable(bigtime_t timeout) const
579 {
580 	return B_UNSUPPORTED;
581 }
582 
583 
584 //	#pragma mark - BDataIO implementation
585 
586 
587 ssize_t
588 BSecureSocket::Read(void* buffer, size_t size)
589 {
590 	return B_UNSUPPORTED;
591 }
592 
593 
594 ssize_t
595 BSecureSocket::Write(const void* buffer, size_t size)
596 {
597 	return B_UNSUPPORTED;
598 }
599 
600 
601 status_t
602 BSecureSocket::InitCheck()
603 {
604 	return B_UNSUPPORTED;
605 }
606 
607 
608 status_t
609 BSecureSocket::_SetupCommon(const char* host)
610 {
611 	return B_UNSUPPORTED;
612 }
613 
614 
615 status_t
616 BSecureSocket::_SetupConnect(const char* host)
617 {
618 	return B_UNSUPPORTED;
619 }
620 
621 
622 status_t
623 BSecureSocket::_SetupAccept()
624 {
625 	return B_UNSUPPORTED;
626 }
627 
628 
629 #endif	// !OPENSSL_ENABLED
630