From eed791dff14fea21f56e26bbbf0f25025a643908 Mon Sep 17 00:00:00 2001 From: Jonathan Schleifer Date: Sun, 24 May 2015 21:33:09 +0200 Subject: [PATCH] Conform to OFTLSSocket This also introduces automatic certificate verification and enables it by default, as required by OFTLSSocket. There are still TODOs until OFTLSSocket is fully implemented. --- configure.ac | 18 ++---- src/SSLSocket.h | 10 +-- src/SSLSocket.m | 138 ++++++++++++++++++++++++++++++++++++------ src/X509Certificate.m | 9 +++ 4 files changed, 139 insertions(+), 36 deletions(-) diff --git a/configure.ac b/configure.ac index dcac5f4..7c2c589 100644 --- a/configure.ac +++ b/configure.ac @@ -36,21 +36,15 @@ AS_IF([test x"$enable_static" = x"yes" -o x"$enable_shared" = x"no"], [ AC_SUBST(OBJOPENSSL_STATIC_LIB, "libobjopenssl.a") ]) -AC_CHECK_LIB(ssl, main, [LIBS="$LIBS -lssl"], [ - AC_MSG_ERROR(No libssl found! Please install OpenSSL!) -]) -AC_CHECK_LIB(crypto, main, [LIBS="$LIBS -lcrypto"], [ - AC_MSG_ERROR(No libcrypto found! Please install OpenSSL!) -]) -AC_CHECK_LIB(z, main, [LIBS="$LIBS -lz"], [ - AC_MSG_ERROR(No libz found! Please install zlib!) +PKG_CHECK_MODULES(openssl, [openssl >= 1.0.2], [ + CPPFLAGS="$CPPFLAGS $openssl_CFLAGS" + LIBS="$LIBS $openssl_LIBS" +], [ + AC_MSG_ERROR(You need openssl >= 1.0.2 installed!) ]) AS_IF([test x"$GOBJC" = x"yes"], [ - OBJCFLAGS="$OBJCFLAGS -Wwrite-strings -Wpointer-arith" - dnl We need -Wno-deprecated-declarations as OpenSSL is deprecated on - dnl OS X. - OBJCFLAGS="$OBJCFLAGS -Wno-deprecated-declarations" + OBJCFLAGS="$OBJCFLAGS -Wwrite-strings -Wpointer-arith -Werror" ]) BUILDSYS_INIT diff --git a/src/SSLSocket.h b/src/SSLSocket.h index fa33bb8..2eda0da 100644 --- a/src/SSLSocket.h +++ b/src/SSLSocket.h @@ -33,17 +33,19 @@ SSL *_SSL; OFString *_certificateFile, *_privateKeyFile; const char *_privateKeyPassphrase; - bool _requestsClientCertificates; + bool _certificateVerificationEnabled; + bool _requestClientCertificatesEnabled; } #ifdef OF_HAVE_PROPERTIES -@property bool requestsClientCertificates; +@property (getter=isRequestClientCertificatesEnabled) + bool requestClientCertificatesEnabled; #endif - initWithSocket: (OFTCPSocket*)socket; - (void)SSL_super_close; -- (void)setRequestsClientCertificates: (bool)enabled; -- (bool)requestsClientCertificates; +- (void)setRequestClientCertificatesEnabled: (bool)enabled; +- (bool)isRequestClientCertificatesEnabled; - (OFDataArray*)channelBindingDataWithType: (OFString*)type; - (X509Certificate*)peerCertificate; - (void)verifyPeerCertificate; diff --git a/src/SSLSocket.m b/src/SSLSocket.m index 7cf0776..012e5d6 100644 --- a/src/SSLSocket.m +++ b/src/SSLSocket.m @@ -27,8 +27,18 @@ #include #include +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdocumentation" +#endif + #include #include +#include + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif #import #import @@ -116,11 +126,26 @@ locking_callback(int mode, int n, const char *file, int line) exceptionWithClass: self]; } +- init +{ + self = [super init]; + + _certificateVerificationEnabled = true; + + return self; +} + - initWithSocket: (OFTCPSocket*)socket { self = [self init]; - _socket = dup(socket->_socket); + @try { + if ((_socket = dup(socket->_socket)) < 0) + @throw [OFInitializationFailedException exception]; + } @catch (id e) { + [self release]; + @throw e; + } return self; } @@ -138,18 +163,35 @@ locking_callback(int mode, int n, const char *file, int line) SSL_free(SSL_); } -- (void)startTLS +- (void)SSL_startTLSWithExpectedHost: (OFString*)host + port: (uint16_t)port { of_string_encoding_t encoding; if ((_SSL = SSL_new(ctx)) == NULL || !SSL_set_fd(_SSL, _socket)) { [super close]; @throw [OFConnectionFailedException - exceptionWithHost: nil - port: 0 + exceptionWithHost: host + port: port socket: self]; } + if (_certificateVerificationEnabled) { + X509_VERIFY_PARAM *param = SSL_get0_param(_SSL); + + X509_VERIFY_PARAM_set_hostflags(param, + X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); + + if (X509_VERIFY_PARAM_set1_host(param, + [host UTF8String], [host UTF8StringLength]) == 0) + @throw [OFConnectionFailedException + exceptionWithHost: host + port: port + socket: self]; + + SSL_set_verify(_SSL, SSL_VERIFY_PEER, NULL); + } + SSL_set_connect_state(_SSL); encoding = [OFSystemInfo native8BitEncoding]; @@ -162,19 +204,26 @@ locking_callback(int mode, int n, const char *file, int line) SSL_FILETYPE_PEM)) || SSL_connect(_SSL) != 1) { [super close]; @throw [OFConnectionFailedException - exceptionWithHost: nil - port: 0 + exceptionWithHost: host + port: port socket: self]; } } +- (void)startTLSWithExpectedHost: (OFString*)host +{ + [self SSL_startTLSWithExpectedHost: host + port: 0]; +} + - (void)connectToHost: (OFString*)host port: (uint16_t)port { [super connectToHost: host port: port]; - [self startTLS]; + [self SSL_startTLSWithExpectedHost: host + port: port]; } - (instancetype)accept @@ -190,7 +239,7 @@ locking_callback(int mode, int n, const char *file, int line) errNo: 0]; } - if (_requestsClientCertificates) + if (_requestClientCertificatesEnabled) SSL_set_verify(client->_SSL, SSL_VERIFY_PEER, NULL); SSL_set_accept_state(client->_SSL); @@ -283,15 +332,14 @@ locking_callback(int mode, int n, const char *file, int line) - (void)setDelegate: (id )delegate { - /* FIXME */ - [self doesNotRecognizeSelector: _cmd]; - abort(); + /* TODO */ + OF_UNRECOGNIZED_SELECTOR } - (id )delegate { - /* FIXME */ - return nil; + /* TODO */ + OF_UNRECOGNIZED_SELECTOR } - (void)setCertificateFile: (OFString*)certificateFile @@ -299,40 +347,90 @@ locking_callback(int mode, int n, const char *file, int line) OF_SETTER(_certificateFile, certificateFile, true, 1) } +- (void)setCertificateFile: (OFString*)certificateFile + forSNIHost: (OFString*)SNIHost +{ + /* TODO */ + OF_UNRECOGNIZED_SELECTOR +} + - (OFString*)certificateFile { OF_GETTER(_certificateFile, true) } +- (OFString*)certificateFileForSNIHost: (OFString*)SNIHost +{ + /* TODO */ + OF_UNRECOGNIZED_SELECTOR +} + - (void)setPrivateKeyFile: (OFString*)privateKeyFile { OF_SETTER(_privateKeyFile, privateKeyFile, true, 1) } +- (void)setPrivateKeyFile: (OFString*)privateKeyFile + forSNIHost: (OFString*)SNIHost +{ + /* TODO */ + OF_UNRECOGNIZED_SELECTOR +} + - (OFString*)privateKeyFile { OF_GETTER(_privateKeyFile, true) } +- (OFString*)privateKeyFileForSNIHost: (OFString*)SNIHost +{ + /* TODO */ + OF_UNRECOGNIZED_SELECTOR +} + - (void)setPrivateKeyPassphrase: (const char*)privateKeyPassphrase { - /* FIXME */ + /* TODO */ + OF_UNRECOGNIZED_SELECTOR +} + +- (void)setPrivateKeyPassphrase: (const char*)privateKeyPassphrase + forSNIHost: (OFString*)SNIHost +{ + /* TODO */ + OF_UNRECOGNIZED_SELECTOR } - (const char*)privateKeyPassphrase { - /* FIXME */ - return NULL; + /* TODO */ + OF_UNRECOGNIZED_SELECTOR } -- (void)setRequestsClientCertificates: (bool)enabled +- (const char*)privateKeyPassphraseForSNIHost: (OFString*)SNIHost { - _requestsClientCertificates = enabled; + /* TODO */ + OF_UNRECOGNIZED_SELECTOR } -- (bool)requestsClientCertificates +- (void)setCertificateVerificationEnabled: (bool)enabled { - return _requestsClientCertificates; + _certificateVerificationEnabled = enabled; +} + +- (bool)isCertificateVerificationEnabled +{ + return _certificateVerificationEnabled; +} + +- (void)setRequestClientCertificatesEnabled: (bool)enabled +{ + _requestClientCertificatesEnabled = enabled; +} + +- (bool)isRequestClientCertificatesEnabled +{ + return _requestClientCertificatesEnabled; } - (OFDataArray*)channelBindingDataWithType: (OFString*)type diff --git a/src/X509Certificate.m b/src/X509Certificate.m index 5e7714b..6ec9afa 100644 --- a/src/X509Certificate.m +++ b/src/X509Certificate.m @@ -21,9 +21,18 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdocumentation" +#endif + #include #include +#if defined(__clang__) +# pragma clang diagnostic pop +#endif + #import "X509Certificate.h" #import