From c500331f6684588cd41b52dc438f9ab480b7d0ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 25 Apr 2013 01:31:20 +0200 Subject: [PATCH] BSecureSocket: prepared to do SSL error conversion. * For now, just print them to stderr; we don't really have matching error codes yet AFAICS. --- src/kits/network/libnetapi/SecureSocket.cpp | 113 +++++++++++--------- 1 file changed, 65 insertions(+), 48 deletions(-) diff --git a/src/kits/network/libnetapi/SecureSocket.cpp b/src/kits/network/libnetapi/SecureSocket.cpp index 7ba9370990..52d7edf65b 100644 --- a/src/kits/network/libnetapi/SecureSocket.cpp +++ b/src/kits/network/libnetapi/SecureSocket.cpp @@ -1,6 +1,6 @@ /* - * Copyright 2014 Haiku, Inc. - * Copyright 2011, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2013-2015 Haiku, Inc. + * Copyright 2011-2015, Axel Dörfler, axeld@pinc-software.de. * Copyright 2010, Clemens Zeidler * Distributed under the terms of the MIT License. */ @@ -38,15 +38,19 @@ public: ~Private(); status_t InitCheck(); + status_t ErrorCode(int returnValue); static SSL_CTX* Context(); static int VerifyCallback(int ok, X509_STORE_CTX* ctx); + private: - static void CreateContext(); + static void _CreateContext(); + public: SSL* fSSL; BIO* fBIO; static int sDataIndex; + private: static SSL_CTX* sContext; // FIXME When do we SSL_CTX_free it? @@ -90,27 +94,32 @@ BSecureSocket::Private::InitCheck() } -/* static */ void -BSecureSocket::Private::CreateContext() +status_t +BSecureSocket::Private::ErrorCode(int returnValue) { - sContext = SSL_CTX_new(SSLv23_method()); + int error = SSL_get_error(fSSL, returnValue); + switch (error) { + case SSL_ERROR_NONE: + // Shouldn't happen... + return B_NO_ERROR; + case SSL_ERROR_ZERO_RETURN: + // Socket is closed + return B_CANCELED; + case SSL_ERROR_SSL: + // Probably no certificate + return B_NOT_ALLOWED; - // Disable legacy protocols. They have known vulnerabilities. - SSL_CTX_set_options(sContext, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); - - // Setup certificate verification - BPath certificateStore; - find_directory(B_SYSTEM_DATA_DIRECTORY, &certificateStore); - certificateStore.Append("ssl/CARootCertificates.pem"); - // TODO we may want to add a non-packaged certificate directory? - // (would make it possible to store user-added certificate exceptions - // there) - SSL_CTX_load_verify_locations(sContext, certificateStore.Path(), NULL); - SSL_CTX_set_verify(sContext, SSL_VERIFY_PEER, VerifyCallback); - - // Get an unique index number for storing application data in SSL - // structs. We will store a pointer to the BSecureSocket class there. - sDataIndex = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_CONNECT: + case SSL_ERROR_WANT_ACCEPT: + case SSL_ERROR_WANT_X509_LOOKUP: + case SSL_ERROR_SYSCALL: + default: + // TODO: translate SSL error codes! + fprintf(stderr, "SSL error: %d\n", error); + return B_ERROR; + } } @@ -120,14 +129,15 @@ BSecureSocket::Private::Context() // We use lazy initialisation here, because reading certificates from disk // and parsing them is a relatively long operation and uses some memory. // We don't want programs that don't use SSL to waste resources with that. - pthread_once(&sInitOnce, CreateContext); + pthread_once(&sInitOnce, _CreateContext); return sContext; } -// This is called each time a certificate verification occurs. It allows us to -// catch failures and report them. +/*! This is called each time a certificate verification occurs. It allows us to + catch failures and report them. +*/ /* static */ int BSecureSocket::Private::VerifyCallback(int ok, X509_STORE_CTX* ctx) { @@ -165,6 +175,30 @@ BSecureSocket::Private::VerifyCallback(int ok, X509_STORE_CTX* ctx) } +/* static */ void +BSecureSocket::Private::_CreateContext() +{ + sContext = SSL_CTX_new(SSLv23_method()); + + // Disable legacy protocols. They have known vulnerabilities. + SSL_CTX_set_options(sContext, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + + // Setup certificate verification + BPath certificateStore; + find_directory(B_SYSTEM_DATA_DIRECTORY, &certificateStore); + certificateStore.Append("ssl/CARootCertificates.pem"); + // TODO we may want to add a non-packaged certificate directory? + // (would make it possible to store user-added certificate exceptions + // there) + SSL_CTX_load_verify_locations(sContext, certificateStore.Path(), NULL); + SSL_CTX_set_verify(sContext, SSL_VERIFY_PEER, VerifyCallback); + + // Get an unique index number for storing application data in SSL + // structs. We will store a pointer to the BSecureSocket class there. + sDataIndex = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); +} + + // # pragma mark - BSecureSocket @@ -238,25 +272,11 @@ BSecureSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout) SSL_set_bio(fPrivate->fSSL, fPrivate->fBIO, fPrivate->fBIO); SSL_set_ex_data(fPrivate->fSSL, Private::sDataIndex, this); - int sslStatus = SSL_connect(fPrivate->fSSL); - - if (sslStatus <= 0) { + int returnValue = SSL_connect(fPrivate->fSSL); + if (returnValue <= 0) { TRACE("SSLConnection can't connect\n"); BSocket::Disconnect(); - - switch (SSL_get_error(fPrivate->fSSL, sslStatus)) { - case SSL_ERROR_NONE: - // Shouldn't happen... - return B_NO_ERROR; - case SSL_ERROR_ZERO_RETURN: - // Socket is closed - return B_CANCELED; - case SSL_ERROR_SSL: - // Probably no certificate - return B_NOT_ALLOWED; - default: - return B_ERROR; - } + return fPrivate->ErrorCode(returnValue); } return B_OK; @@ -267,9 +287,8 @@ void BSecureSocket::Disconnect() { if (IsConnected()) { - if (fPrivate->fSSL != NULL) { + if (fPrivate->fSSL != NULL) SSL_shutdown(fPrivate->fSSL); - } BSocket::Disconnect(); } @@ -314,8 +333,7 @@ BSecureSocket::Read(void* buffer, size_t size) if (bytesRead >= 0) return bytesRead; - // TODO: translate SSL error codes! - return B_ERROR; + return fPrivate->ErrorCode(bytesRead); } @@ -329,8 +347,7 @@ BSecureSocket::Write(const void* buffer, size_t size) if (bytesWritten >= 0) return bytesWritten; - // TODO: translate SSL error codes! - return B_ERROR; + return fPrivate->ErrorCode(bytesWritten); }