xref: /haiku/src/kits/network/libnetapi/SecureSocket.cpp (revision 6c2abee2f5e73c3fc81c33da51ac610f8bf1117a)
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 /* static */ void
183 BSecureSocket::Private::_CreateContext()
184 {
185 	sContext = SSL_CTX_new(SSLv23_method());
186 
187 	// Disable legacy protocols. They have known vulnerabilities.
188 	SSL_CTX_set_options(sContext, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
189 
190 	// Disable SSL/TLS compression to prevent the CRIME attack.
191 	SSL_CTX_set_options(sContext, SSL_OP_NO_COMPRESSION);
192 
193 	// Don't bother us with ERROR_WANT_READ.
194 	SSL_CTX_set_mode(sContext, SSL_MODE_AUTO_RETRY);
195 
196 	// Setup cipher suites.
197 	// These suites are mostly the same ones used by Firefox 47 and Chrome 50.
198 	SSL_CTX_set_cipher_list(sContext,
199 		"ECDHE-ECDSA-AES128-GCM-SHA256:"
200 		"ECDHE-RSA-AES128-GCM-SHA256:"
201 		"ECDHE-ECDSA-AES256-GCM-SHA384:"
202 		"ECDHE-RSA-AES256-GCM-SHA384:"
203 		"ECDHE-ECDSA-CHACHA20-POLY1305-SHA256:"
204 		"ECDHE-RSA-CHACHA20-POLY1305-SHA256:"
205 		"ECDHE-ECDSA-AES256-SHA:"
206 		"ECDHE-ECDSA-AES128-SHA:"
207 		"ECDHE-RSA-AES128-SHA:"
208 		"ECDHE-RSA-AES256-SHA:"
209 		"DHE-RSA-AES128-SHA:"
210 		"DHE-RSA-AES256-SHA:"
211 		"AES128-SHA:"
212 		"AES256-SHA");
213 
214 	// Let OpenSSL choose the most appropriate D-H curve for us
215 	SSL_CTX_set_ecdh_auto(sContext, 1);
216 
217 	// Setup certificate verification
218 	BPath certificateStore;
219 	find_directory(B_SYSTEM_DATA_DIRECTORY, &certificateStore);
220 	certificateStore.Append("ssl/CARootCertificates.pem");
221 	// TODO we may want to add a non-packaged certificate directory?
222 	// (would make it possible to store user-added certificate exceptions
223 	// there)
224 	SSL_CTX_load_verify_locations(sContext, certificateStore.Path(), NULL);
225 	SSL_CTX_set_verify(sContext, SSL_VERIFY_PEER, VerifyCallback);
226 
227 	// OpenSSL 1.0.2 and later: use the alternate "trusted first" algorithm to validate certificate
228 	// chains. This makes the validation stop as soon as a recognized certificate is found in the
229 	// chain, instead of validating the whole chain, then seeing if the root certificate is known.
230 #ifdef X509_V_FLAG_TRUSTED_FIRST
231 	X509_VERIFY_PARAM* verifyParam = X509_VERIFY_PARAM_new();
232 	X509_VERIFY_PARAM_set_flags(verifyParam, X509_V_FLAG_TRUSTED_FIRST);
233 	SSL_CTX_set1_param(sContext, verifyParam);
234 
235 	// TODO we need to free this after freeing the SSL context (which we currently never do)
236 	// X509_VERIFY_PARAM_free(verifyParam);
237 #endif
238 
239 	// Get an unique index number for storing application data in SSL
240 	// structs. We will store a pointer to the BSecureSocket class there.
241 	sDataIndex = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
242 }
243 
244 
245 // # pragma mark - BSecureSocket
246 
247 
248 BSecureSocket::BSecureSocket()
249 	:
250 	fPrivate(new(std::nothrow) BSecureSocket::Private())
251 {
252 	fInitStatus = fPrivate != NULL ? fPrivate->InitCheck() : B_NO_MEMORY;
253 }
254 
255 
256 BSecureSocket::BSecureSocket(const BNetworkAddress& peer, bigtime_t timeout)
257 	:
258 	fPrivate(new(std::nothrow) BSecureSocket::Private())
259 {
260 	fInitStatus = fPrivate != NULL ? fPrivate->InitCheck() : B_NO_MEMORY;
261 	Connect(peer, timeout);
262 }
263 
264 
265 BSecureSocket::BSecureSocket(const BSecureSocket& other)
266 	:
267 	BSocket(other)
268 {
269 	fPrivate = new(std::nothrow) BSecureSocket::Private(*other.fPrivate);
270 		// TODO: this won't work this way! - write working copy constructor for
271 		// Private.
272 
273 	if (fPrivate != NULL)
274 		SSL_set_ex_data(fPrivate->fSSL, Private::sDataIndex, this);
275 	else
276 		fInitStatus = B_NO_MEMORY;
277 
278 }
279 
280 
281 BSecureSocket::~BSecureSocket()
282 {
283 	delete fPrivate;
284 }
285 
286 
287 status_t
288 BSecureSocket::Accept(BAbstractSocket*& _socket)
289 {
290 	int fd = -1;
291 	BNetworkAddress peer;
292 	status_t error = AcceptNext(fd, peer);
293 	if (error != B_OK)
294 		return error;
295 	BSecureSocket* socket = new(std::nothrow) BSecureSocket();
296 	ObjectDeleter<BSecureSocket> socketDeleter(socket);
297 	if (socket == NULL || socket->InitCheck() != B_OK) {
298 		close(fd);
299 		return B_NO_MEMORY;
300 	}
301 
302 	socket->_SetTo(fd, fLocal, peer);
303 	error = socket->_SetupAccept();
304 	if (error != B_OK)
305 		return error;
306 
307 	_socket = socket;
308 	socketDeleter.Detach();
309 
310 	return B_OK;
311 }
312 
313 
314 status_t
315 BSecureSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout)
316 {
317 	status_t status = InitCheck();
318 	if (status != B_OK)
319 		return status;
320 
321 	status = BSocket::Connect(peer, timeout);
322 	if (status != B_OK)
323 		return status;
324 
325 	return _SetupConnect(peer.HostName().String());
326 }
327 
328 
329 void
330 BSecureSocket::Disconnect()
331 {
332 	if (IsConnected()) {
333 		if (fPrivate->fSSL != NULL)
334 			SSL_shutdown(fPrivate->fSSL);
335 
336 		BSocket::Disconnect();
337 	}
338 }
339 
340 
341 status_t
342 BSecureSocket::WaitForReadable(bigtime_t timeout) const
343 {
344 	if (fInitStatus != B_OK)
345 		return fInitStatus;
346 	if (!IsConnected())
347 		return B_ERROR;
348 
349 	if (SSL_pending(fPrivate->fSSL) > 0)
350 		return B_OK;
351 
352 	return BSocket::WaitForReadable(timeout);
353 }
354 
355 
356 status_t
357 BSecureSocket::InitCheck()
358 {
359 	if (fPrivate == NULL)
360 		return B_NO_MEMORY;
361 
362 	status_t state = fPrivate->InitCheck();
363 	return state;
364 }
365 
366 
367 bool
368 BSecureSocket::CertificateVerificationFailed(BCertificate&, const char*)
369 {
370 	// Until apps actually make use of the certificate API, let's keep the old
371 	// behavior and accept all connections, even if the certificate validation
372 	// didn't work.
373 	return true;
374 }
375 
376 
377 //	#pragma mark - BDataIO implementation
378 
379 
380 ssize_t
381 BSecureSocket::Read(void* buffer, size_t size)
382 {
383 	if (!IsConnected())
384 		return B_ERROR;
385 
386 	int bytesRead = SSL_read(fPrivate->fSSL, buffer, size);
387 	if (bytesRead >= 0)
388 		return bytesRead;
389 
390 	return fPrivate->ErrorCode(bytesRead);
391 }
392 
393 
394 ssize_t
395 BSecureSocket::Write(const void* buffer, size_t size)
396 {
397 	if (!IsConnected())
398 		return B_ERROR;
399 
400 	int bytesWritten = SSL_write(fPrivate->fSSL, buffer, size);
401 	if (bytesWritten >= 0)
402 		return bytesWritten;
403 
404 	return fPrivate->ErrorCode(bytesWritten);
405 }
406 
407 
408 status_t
409 BSecureSocket::_SetupCommon(const char* host)
410 {
411 	// Do this only after BSocket::Connect has checked wether we're already
412 	// connected. We don't want to kill an existing SSL session, as that would
413 	// likely crash the protocol loop for it.
414 	if (fPrivate->fSSL != NULL) {
415 		SSL_free(fPrivate->fSSL);
416 	}
417 
418 	fPrivate->fSSL = SSL_new(BSecureSocket::Private::Context());
419 	if (fPrivate->fSSL == NULL) {
420 		BSocket::Disconnect();
421 		return B_NO_MEMORY;
422 	}
423 
424 	BIO_set_fd(fPrivate->fBIO, fSocket, BIO_NOCLOSE);
425 	SSL_set_bio(fPrivate->fSSL, fPrivate->fBIO, fPrivate->fBIO);
426 	SSL_set_ex_data(fPrivate->fSSL, Private::sDataIndex, this);
427 	if (host != NULL) {
428 		BString hostString = host;
429 		if (hostString != "")
430 			SSL_set_tlsext_host_name(fPrivate->fSSL, host);
431 	}
432 
433 	return B_OK;
434 }
435 
436 
437 status_t
438 BSecureSocket::_SetupConnect(const char* host)
439 {
440 	status_t error = _SetupCommon(host);
441 	if (error != B_OK)
442 		return error;
443 
444 	int returnValue = SSL_connect(fPrivate->fSSL);
445 	if (returnValue <= 0) {
446 		TRACE("SSLConnection can't connect\n");
447 		BSocket::Disconnect();
448 		return fPrivate->ErrorCode(returnValue);
449 	}
450 
451 	return B_OK;
452 }
453 
454 
455 status_t
456 BSecureSocket::_SetupAccept()
457 {
458 	status_t error = _SetupCommon();
459 	if (error != B_OK)
460 		return error;
461 
462 	int returnValue = SSL_accept(fPrivate->fSSL);
463 	if (returnValue <= 0) {
464 		TRACE("SSLConnection can't accept\n");
465 		BSocket::Disconnect();
466 		return fPrivate->ErrorCode(returnValue);
467 	}
468 
469 	return B_OK;
470 }
471 
472 
473 #else	// OPENSSL_ENABLED
474 
475 
476 // #pragma mark - No-SSL stubs
477 
478 
479 BSecureSocket::BSecureSocket()
480 {
481 }
482 
483 
484 BSecureSocket::BSecureSocket(const BNetworkAddress& peer, bigtime_t timeout)
485 {
486 	fInitStatus = B_UNSUPPORTED;
487 }
488 
489 
490 BSecureSocket::BSecureSocket(const BSecureSocket& other)
491 	:
492 	BSocket(other)
493 {
494 }
495 
496 
497 BSecureSocket::~BSecureSocket()
498 {
499 }
500 
501 
502 bool
503 BSecureSocket::CertificateVerificationFailed(BCertificate& certificate, const char*)
504 {
505 	(void)certificate;
506 	return false;
507 }
508 
509 
510 status_t
511 BSecureSocket::Accept(BAbstractSocket*& _socket)
512 {
513 	return B_UNSUPPORTED;
514 }
515 
516 
517 status_t
518 BSecureSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout)
519 {
520 	return fInitStatus = B_UNSUPPORTED;
521 }
522 
523 
524 void
525 BSecureSocket::Disconnect()
526 {
527 }
528 
529 
530 status_t
531 BSecureSocket::WaitForReadable(bigtime_t timeout) const
532 {
533 	return B_UNSUPPORTED;
534 }
535 
536 
537 //	#pragma mark - BDataIO implementation
538 
539 
540 ssize_t
541 BSecureSocket::Read(void* buffer, size_t size)
542 {
543 	return B_UNSUPPORTED;
544 }
545 
546 
547 ssize_t
548 BSecureSocket::Write(const void* buffer, size_t size)
549 {
550 	return B_UNSUPPORTED;
551 }
552 
553 
554 status_t
555 BSecureSocket::InitCheck()
556 {
557 	return B_UNSUPPORTED;
558 }
559 
560 
561 status_t
562 BSecureSocket::_SetupCommon(const char* host)
563 {
564 	return B_UNSUPPORTED;
565 }
566 
567 
568 status_t
569 BSecureSocket::_SetupConnect(const char* host)
570 {
571 	return B_UNSUPPORTED;
572 }
573 
574 
575 status_t
576 BSecureSocket::_SetupAccept()
577 {
578 	return B_UNSUPPORTED;
579 }
580 
581 
582 #endif	// !OPENSSL_ENABLED
583