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