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.
10 #include <SecureSocket.h>
12 #ifdef OPENSSL_ENABLED
13 # include <openssl/ssl.h>
14 # include <openssl/ssl3.h> // for TRACE_SESSION_KEY only
15 # include <openssl/err.h>
20 #include <Certificate.h>
21 #include <FindDirectory.h>
24 #include <AutoDeleter.h>
26 #include "CertificatePrivate.h"
29 //#define TRACE_SOCKET
31 # define TRACE(x...) printf(x)
33 # define TRACE(x...) ;
36 //#define TRACE_SESSION_KEY
39 #ifdef OPENSSL_ENABLED
41 #ifdef TRACE_SESSION_KEY
42 #if OPENSSL_VERSION_NUMBER < 0x10100000L
44 * print session id and master key in NSS keylog format (RSA
45 * Session-ID:<session id> Master-Key:<master key>)
47 int SSL_SESSION_print_keylog(BIO
*bp
, const SSL_SESSION
*x
)
53 if (x
->session_id_length
== 0 || x
->master_key_length
== 0)
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
61 if (BIO_puts(bp
, "RSA ") <= 0)
64 if (BIO_puts(bp
, "Session-ID:") <= 0)
66 for (i
= 0; i
< x
->session_id_length
; i
++) {
67 if (BIO_printf(bp
, "%02X", x
->session_id
[i
]) <= 0)
70 if (BIO_puts(bp
, " Master-Key:") <= 0)
72 for (i
= 0; i
< (size_t)x
->master_key_length
; i
++) {
73 if (BIO_printf(bp
, "%02X", x
->master_key
[i
]) <= 0)
76 if (BIO_puts(bp
, "\n") <= 0)
83 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
85 * print client random id and master key in NSS keylog format
86 * as session ID is not enough.
88 int SSL_SESSION_print_client_random(BIO
*bp
, const SSL
*ssl
)
90 const SSL_SESSION
*x
= SSL_get_session(ssl
);
95 if (x
->session_id_length
== 0 || x
->master_key_length
== 0)
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
103 if (BIO_puts(bp
, "CLIENT_RANDOM ") <= 0)
106 for (i
= 0; i
< sizeof(ssl
->s3
->client_random
); i
++) {
107 if (BIO_printf(bp
, "%02X", ssl
->s3
->client_random
[i
]) <= 0)
110 if (BIO_puts(bp
, " ") <= 0)
112 for (i
= 0; i
< (size_t)x
->master_key_length
; i
++) {
113 if (BIO_printf(bp
, "%02X", x
->master_key
[i
]) <= 0)
116 if (BIO_puts(bp
, "\n") <= 0)
123 #endif /* TRACE_SESSION_KEY */
125 class BSecureSocket::Private
{
130 status_t
InitCheck();
131 status_t
ErrorCode(int returnValue
);
133 static SSL_CTX
* Context();
134 static int VerifyCallback(int ok
, X509_STORE_CTX
* ctx
);
137 static void _CreateContext();
142 static int sDataIndex
;
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
150 static BIO
* sKeyLogBIO
;
156 /* static */ SSL_CTX
* BSecureSocket::Private::sContext
= NULL
;
157 /* static */ int BSecureSocket::Private::sDataIndex
;
158 /* static */ pthread_once_t
BSecureSocket::Private::sInitOnce
160 #ifdef TRACE_SESSION_KEY
161 /* static */ BIO
* BSecureSocket::Private::sKeyLogBIO
= NULL
;
165 BSecureSocket::Private::Private()
168 fBIO(BIO_new(BIO_s_socket()))
173 BSecureSocket::Private::~Private()
175 // SSL_free also frees the underlying BIO.
179 // The SSL session was never created (Connect() was not called or
180 // failed). We must free the BIO we created in the constructor.
187 BSecureSocket::Private::InitCheck()
196 BSecureSocket::Private::ErrorCode(int returnValue
)
198 int error
= SSL_get_error(fSSL
, returnValue
);
201 // Shouldn't happen...
203 case SSL_ERROR_ZERO_RETURN
:
207 // Probably no certificate
208 return B_NOT_ALLOWED
;
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
:
217 // TODO: translate SSL error codes!
218 fprintf(stderr
, "SSL %s\n", ERR_error_string(error
, NULL
));
224 /* static */ SSL_CTX
*
225 BSecureSocket::Private::Context()
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
);
236 /*! This is called each time a certificate verification occurs. It allows us to
237 catch failures and report them.
240 BSecureSocket::Private::VerifyCallback(int ok
, X509_STORE_CTX
* ctx
)
242 // OpenSSL already checked the certificate again the certificate store for
243 // us, and tells the result of that in the ok parameter.
245 // If the verification succeeded, no need for any further checks. Let's
246 // proceed with the connection.
250 // The certificate verification failed. Signal this to the BSecureSocket.
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
);
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
260 X509
* x509
= X509_STORE_CTX_get_current_cert(ctx
);
261 BCertificate::Private
* certificate
262 = new(std::nothrow
) BCertificate::Private(x509
);
264 if (certificate
== NULL
)
267 int error
= X509_STORE_CTX_get_error(ctx
);
268 const char* message
= X509_verify_cert_error_string(error
);
270 // Let the BSecureSocket (or subclass) decide if we should continue anyway.
271 BCertificate
failedCertificate(certificate
);
272 return socket
->CertificateVerificationFailed(failedCertificate
, message
);
277 static void apps_ssl_info_callback(const SSL
*s
, int where
, int ret
)
282 w
=where
& ~SSL_ST_MASK
;
284 if (w
& SSL_ST_CONNECT
)
286 else if (w
& SSL_ST_ACCEPT
)
291 if (where
& SSL_CB_LOOP
) {
292 fprintf(stderr
,"%s:%s\n", str
, SSL_state_string_long(s
));
293 } else if (where
& SSL_CB_ALERT
) {
294 str
= (where
& SSL_CB_READ
) ? "read" : "write";
295 fprintf(stderr
,"SSL3 alert %s:%s:%s\n",
297 SSL_alert_type_string_long(ret
),
298 SSL_alert_desc_string_long(ret
));
299 } else if (where
& SSL_CB_EXIT
) {
301 fprintf(stderr
,"%s:failed in %s\n",
302 str
,SSL_state_string_long(s
));
304 fprintf(stderr
,"%s:error in %s\n",
305 str
,SSL_state_string_long(s
));
313 BSecureSocket::Private::_CreateContext()
315 // We want SSL to report errors in human readable format.
316 SSL_load_error_strings();
318 sContext
= SSL_CTX_new(SSLv23_method());
321 // For debugging purposes: get all SSL messages to the standard error.
322 SSL_CTX_set_info_callback(sContext
, apps_ssl_info_callback
);
325 // Disable legacy protocols. They have known vulnerabilities.
326 SSL_CTX_set_options(sContext
, SSL_OP_NO_SSLv2
| SSL_OP_NO_SSLv3
);
328 // Disable SSL/TLS compression to prevent the CRIME attack.
329 SSL_CTX_set_options(sContext
, SSL_OP_NO_COMPRESSION
);
331 // Don't bother us with ERROR_WANT_READ.
332 SSL_CTX_set_mode(sContext
, SSL_MODE_AUTO_RETRY
);
334 // Setup cipher suites.
335 // These suites are mostly the same ones used by Firefox 47 and Chrome 50.
336 SSL_CTX_set_cipher_list(sContext
,
337 "ECDHE-ECDSA-AES128-GCM-SHA256:"
338 "ECDHE-RSA-AES128-GCM-SHA256:"
339 "ECDHE-ECDSA-AES256-GCM-SHA384:"
340 "ECDHE-RSA-AES256-GCM-SHA384:"
341 "ECDHE-ECDSA-CHACHA20-POLY1305-SHA256:"
342 "ECDHE-RSA-CHACHA20-POLY1305-SHA256:"
343 "ECDHE-ECDSA-AES256-SHA:"
344 "ECDHE-ECDSA-AES128-SHA:"
345 "ECDHE-RSA-AES128-SHA:"
346 "ECDHE-RSA-AES256-SHA:"
347 "DHE-RSA-AES128-SHA:"
348 "DHE-RSA-AES256-SHA:"
352 // Let OpenSSL choose the most appropriate D-H curve for us
353 SSL_CTX_set_ecdh_auto(sContext
, 1);
355 // Setup certificate verification
356 BPath certificateStore
;
357 find_directory(B_SYSTEM_DATA_DIRECTORY
, &certificateStore
);
358 certificateStore
.Append("ssl/CARootCertificates.pem");
359 // TODO we may want to add a non-packaged certificate directory?
360 // (would make it possible to store user-added certificate exceptions
362 SSL_CTX_load_verify_locations(sContext
, certificateStore
.Path(), NULL
);
363 SSL_CTX_set_verify(sContext
, SSL_VERIFY_PEER
, VerifyCallback
);
365 // OpenSSL 1.0.2 and later: use the alternate "trusted first" algorithm to validate certificate
366 // chains. This makes the validation stop as soon as a recognized certificate is found in the
367 // chain, instead of validating the whole chain, then seeing if the root certificate is known.
368 #ifdef X509_V_FLAG_TRUSTED_FIRST
369 X509_VERIFY_PARAM
* verifyParam
= X509_VERIFY_PARAM_new();
370 X509_VERIFY_PARAM_set_flags(verifyParam
, X509_V_FLAG_TRUSTED_FIRST
);
371 SSL_CTX_set1_param(sContext
, verifyParam
);
373 // TODO we need to free this after freeing the SSL context (which we currently never do)
374 // X509_VERIFY_PARAM_free(verifyParam);
377 // Get an unique index number for storing application data in SSL
378 // structs. We will store a pointer to the BSecureSocket class there.
379 sDataIndex
= SSL_get_ex_new_index(0, NULL
, NULL
, NULL
, NULL
);
381 #ifdef TRACE_SESSION_KEY
383 const char *logpath
= getenv("SSLKEYLOGFILE");
385 keylog
= fopen(logpath
, "w+");
387 fprintf(keylog
, "# Key Log File generated by Haiku Network Kit\n");
388 sKeyLogBIO
= BIO_new_fp(keylog
, BIO_NOCLOSE
);
394 // # pragma mark - BSecureSocket
397 BSecureSocket::BSecureSocket()
399 fPrivate(new(std::nothrow
) BSecureSocket::Private())
401 fInitStatus
= fPrivate
!= NULL
? fPrivate
->InitCheck() : B_NO_MEMORY
;
405 BSecureSocket::BSecureSocket(const BNetworkAddress
& peer
, bigtime_t timeout
)
407 fPrivate(new(std::nothrow
) BSecureSocket::Private())
409 fInitStatus
= fPrivate
!= NULL
? fPrivate
->InitCheck() : B_NO_MEMORY
;
410 Connect(peer
, timeout
);
414 BSecureSocket::BSecureSocket(const BSecureSocket
& other
)
418 fPrivate
= new(std::nothrow
) BSecureSocket::Private(*other
.fPrivate
);
419 // TODO: this won't work this way! - write working copy constructor for
422 if (fPrivate
!= NULL
)
423 SSL_set_ex_data(fPrivate
->fSSL
, Private::sDataIndex
, this);
425 fInitStatus
= B_NO_MEMORY
;
430 BSecureSocket::~BSecureSocket()
437 BSecureSocket::Accept(BAbstractSocket
*& _socket
)
440 BNetworkAddress peer
;
441 status_t error
= AcceptNext(fd
, peer
);
444 BSecureSocket
* socket
= new(std::nothrow
) BSecureSocket();
445 ObjectDeleter
<BSecureSocket
> socketDeleter(socket
);
446 if (socket
== NULL
|| socket
->InitCheck() != B_OK
) {
451 socket
->_SetTo(fd
, fLocal
, peer
);
452 error
= socket
->_SetupAccept();
457 socketDeleter
.Detach();
464 BSecureSocket::Connect(const BNetworkAddress
& peer
, bigtime_t timeout
)
466 status_t status
= InitCheck();
470 status
= BSocket::Connect(peer
, timeout
);
474 return _SetupConnect(peer
.HostName().String());
479 BSecureSocket::Disconnect()
482 if (fPrivate
->fSSL
!= NULL
)
483 SSL_shutdown(fPrivate
->fSSL
);
485 BSocket::Disconnect();
491 BSecureSocket::WaitForReadable(bigtime_t timeout
) const
493 if (fInitStatus
!= B_OK
)
498 if (SSL_pending(fPrivate
->fSSL
) > 0)
501 return BSocket::WaitForReadable(timeout
);
506 BSecureSocket::InitCheck()
508 if (fPrivate
== NULL
)
511 status_t state
= fPrivate
->InitCheck();
517 BSecureSocket::CertificateVerificationFailed(BCertificate
&, const char*)
519 // Until apps actually make use of the certificate API, let's keep the old
520 // behavior and accept all connections, even if the certificate validation
526 // #pragma mark - BDataIO implementation
530 BSecureSocket::Read(void* buffer
, size_t size
)
535 int bytesRead
= SSL_read(fPrivate
->fSSL
, buffer
, size
);
539 return fPrivate
->ErrorCode(bytesRead
);
544 BSecureSocket::Write(const void* buffer
, size_t size
)
549 int bytesWritten
= SSL_write(fPrivate
->fSSL
, buffer
, size
);
550 if (bytesWritten
>= 0)
553 return fPrivate
->ErrorCode(bytesWritten
);
558 BSecureSocket::_SetupCommon(const char* host
)
560 // Do this only after BSocket::Connect has checked wether we're already
561 // connected. We don't want to kill an existing SSL session, as that would
562 // likely crash the protocol loop for it.
563 if (fPrivate
->fSSL
!= NULL
) {
564 SSL_free(fPrivate
->fSSL
);
567 fPrivate
->fSSL
= SSL_new(BSecureSocket::Private::Context());
568 if (fPrivate
->fSSL
== NULL
) {
569 BSocket::Disconnect();
573 BIO_set_fd(fPrivate
->fBIO
, fSocket
, BIO_NOCLOSE
);
574 SSL_set_bio(fPrivate
->fSSL
, fPrivate
->fBIO
, fPrivate
->fBIO
);
575 SSL_set_ex_data(fPrivate
->fSSL
, Private::sDataIndex
, this);
577 BString hostString
= host
;
578 if (hostString
!= "")
579 SSL_set_tlsext_host_name(fPrivate
->fSSL
, host
);
588 BSecureSocket::_SetupConnect(const char* host
)
590 status_t error
= _SetupCommon(host
);
594 int returnValue
= SSL_connect(fPrivate
->fSSL
);
595 if (returnValue
<= 0) {
596 TRACE("SSLConnection can't connect\n");
597 BSocket::Disconnect();
598 return fPrivate
->ErrorCode(returnValue
);
601 #ifdef TRACE_SESSION_KEY
602 fprintf(stderr
, "SSL SESSION INFO:\n");
603 //SSL_SESSION_print_fp(stderr, SSL_get_session(fPrivate->fSSL));
604 SSL_SESSION_print_keylog(fPrivate
->sKeyLogBIO
, SSL_get_session(fPrivate
->fSSL
));
605 SSL_SESSION_print_client_random(fPrivate
->sKeyLogBIO
, fPrivate
->fSSL
);
606 fprintf(stderr
, "\n");
614 BSecureSocket::_SetupAccept()
616 status_t error
= _SetupCommon();
620 int returnValue
= SSL_accept(fPrivate
->fSSL
);
621 if (returnValue
<= 0) {
622 TRACE("SSLConnection can't accept\n");
623 BSocket::Disconnect();
624 return fPrivate
->ErrorCode(returnValue
);
631 #else // OPENSSL_ENABLED
634 // #pragma mark - No-SSL stubs
637 BSecureSocket::BSecureSocket()
642 BSecureSocket::BSecureSocket(const BNetworkAddress
& peer
, bigtime_t timeout
)
644 fInitStatus
= B_UNSUPPORTED
;
648 BSecureSocket::BSecureSocket(const BSecureSocket
& other
)
655 BSecureSocket::~BSecureSocket()
661 BSecureSocket::CertificateVerificationFailed(BCertificate
& certificate
, const char*)
669 BSecureSocket::Accept(BAbstractSocket
*& _socket
)
671 return B_UNSUPPORTED
;
676 BSecureSocket::Connect(const BNetworkAddress
& peer
, bigtime_t timeout
)
678 return fInitStatus
= B_UNSUPPORTED
;
683 BSecureSocket::Disconnect()
689 BSecureSocket::WaitForReadable(bigtime_t timeout
) const
691 return B_UNSUPPORTED
;
695 // #pragma mark - BDataIO implementation
699 BSecureSocket::Read(void* buffer
, size_t size
)
701 return B_UNSUPPORTED
;
706 BSecureSocket::Write(const void* buffer
, size_t size
)
708 return B_UNSUPPORTED
;
713 BSecureSocket::InitCheck()
715 return B_UNSUPPORTED
;
720 BSecureSocket::_SetupCommon(const char* host
)
722 return B_UNSUPPORTED
;
727 BSecureSocket::_SetupConnect(const char* host
)
729 return B_UNSUPPORTED
;
734 BSecureSocket::_SetupAccept()
736 return B_UNSUPPORTED
;
740 #endif // !OPENSSL_ENABLED