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