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.
This commit is contained in:
Jonathan Schleifer 2015-05-24 21:33:09 +02:00
parent 01b588e4d6
commit eed791dff1
No known key found for this signature in database
GPG key ID: 33E61C63EB4AE7B5
4 changed files with 139 additions and 36 deletions

View file

@ -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_SUBST(OBJOPENSSL_STATIC_LIB, "libobjopenssl.a")
]) ])
AC_CHECK_LIB(ssl, main, [LIBS="$LIBS -lssl"], [ PKG_CHECK_MODULES(openssl, [openssl >= 1.0.2], [
AC_MSG_ERROR(No libssl found! Please install OpenSSL!) CPPFLAGS="$CPPFLAGS $openssl_CFLAGS"
]) LIBS="$LIBS $openssl_LIBS"
AC_CHECK_LIB(crypto, main, [LIBS="$LIBS -lcrypto"], [ ], [
AC_MSG_ERROR(No libcrypto found! Please install OpenSSL!) AC_MSG_ERROR(You need openssl >= 1.0.2 installed!)
])
AC_CHECK_LIB(z, main, [LIBS="$LIBS -lz"], [
AC_MSG_ERROR(No libz found! Please install zlib!)
]) ])
AS_IF([test x"$GOBJC" = x"yes"], [ AS_IF([test x"$GOBJC" = x"yes"], [
OBJCFLAGS="$OBJCFLAGS -Wwrite-strings -Wpointer-arith" OBJCFLAGS="$OBJCFLAGS -Wwrite-strings -Wpointer-arith -Werror"
dnl We need -Wno-deprecated-declarations as OpenSSL is deprecated on
dnl OS X.
OBJCFLAGS="$OBJCFLAGS -Wno-deprecated-declarations"
]) ])
BUILDSYS_INIT BUILDSYS_INIT

View file

@ -33,17 +33,19 @@
SSL *_SSL; SSL *_SSL;
OFString *_certificateFile, *_privateKeyFile; OFString *_certificateFile, *_privateKeyFile;
const char *_privateKeyPassphrase; const char *_privateKeyPassphrase;
bool _requestsClientCertificates; bool _certificateVerificationEnabled;
bool _requestClientCertificatesEnabled;
} }
#ifdef OF_HAVE_PROPERTIES #ifdef OF_HAVE_PROPERTIES
@property bool requestsClientCertificates; @property (getter=isRequestClientCertificatesEnabled)
bool requestClientCertificatesEnabled;
#endif #endif
- initWithSocket: (OFTCPSocket*)socket; - initWithSocket: (OFTCPSocket*)socket;
- (void)SSL_super_close; - (void)SSL_super_close;
- (void)setRequestsClientCertificates: (bool)enabled; - (void)setRequestClientCertificatesEnabled: (bool)enabled;
- (bool)requestsClientCertificates; - (bool)isRequestClientCertificatesEnabled;
- (OFDataArray*)channelBindingDataWithType: (OFString*)type; - (OFDataArray*)channelBindingDataWithType: (OFString*)type;
- (X509Certificate*)peerCertificate; - (X509Certificate*)peerCertificate;
- (void)verifyPeerCertificate; - (void)verifyPeerCertificate;

View file

@ -27,8 +27,18 @@
#include <errno.h> #include <errno.h>
#include <assert.h> #include <assert.h>
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdocumentation"
#endif
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/x509v3.h>
#if defined(__clang__)
# pragma clang diagnostic pop
#endif
#import <ObjFW/OFThread.h> #import <ObjFW/OFThread.h>
#import <ObjFW/OFHTTPRequest.h> #import <ObjFW/OFHTTPRequest.h>
@ -116,11 +126,26 @@ locking_callback(int mode, int n, const char *file, int line)
exceptionWithClass: self]; exceptionWithClass: self];
} }
- init
{
self = [super init];
_certificateVerificationEnabled = true;
return self;
}
- initWithSocket: (OFTCPSocket*)socket - initWithSocket: (OFTCPSocket*)socket
{ {
self = [self init]; 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; return self;
} }
@ -138,18 +163,35 @@ locking_callback(int mode, int n, const char *file, int line)
SSL_free(SSL_); SSL_free(SSL_);
} }
- (void)startTLS - (void)SSL_startTLSWithExpectedHost: (OFString*)host
port: (uint16_t)port
{ {
of_string_encoding_t encoding; of_string_encoding_t encoding;
if ((_SSL = SSL_new(ctx)) == NULL || !SSL_set_fd(_SSL, _socket)) { if ((_SSL = SSL_new(ctx)) == NULL || !SSL_set_fd(_SSL, _socket)) {
[super close]; [super close];
@throw [OFConnectionFailedException @throw [OFConnectionFailedException
exceptionWithHost: nil exceptionWithHost: host
port: 0 port: port
socket: self]; 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); SSL_set_connect_state(_SSL);
encoding = [OFSystemInfo native8BitEncoding]; 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) { SSL_FILETYPE_PEM)) || SSL_connect(_SSL) != 1) {
[super close]; [super close];
@throw [OFConnectionFailedException @throw [OFConnectionFailedException
exceptionWithHost: nil exceptionWithHost: host
port: 0 port: port
socket: self]; socket: self];
} }
} }
- (void)startTLSWithExpectedHost: (OFString*)host
{
[self SSL_startTLSWithExpectedHost: host
port: 0];
}
- (void)connectToHost: (OFString*)host - (void)connectToHost: (OFString*)host
port: (uint16_t)port port: (uint16_t)port
{ {
[super connectToHost: host [super connectToHost: host
port: port]; port: port];
[self startTLS]; [self SSL_startTLSWithExpectedHost: host
port: port];
} }
- (instancetype)accept - (instancetype)accept
@ -190,7 +239,7 @@ locking_callback(int mode, int n, const char *file, int line)
errNo: 0]; errNo: 0];
} }
if (_requestsClientCertificates) if (_requestClientCertificatesEnabled)
SSL_set_verify(client->_SSL, SSL_VERIFY_PEER, NULL); SSL_set_verify(client->_SSL, SSL_VERIFY_PEER, NULL);
SSL_set_accept_state(client->_SSL); SSL_set_accept_state(client->_SSL);
@ -283,15 +332,14 @@ locking_callback(int mode, int n, const char *file, int line)
- (void)setDelegate: (id <OFTLSSocketDelegate>)delegate - (void)setDelegate: (id <OFTLSSocketDelegate>)delegate
{ {
/* FIXME */ /* TODO */
[self doesNotRecognizeSelector: _cmd]; OF_UNRECOGNIZED_SELECTOR
abort();
} }
- (id <OFTLSSocketDelegate>)delegate - (id <OFTLSSocketDelegate>)delegate
{ {
/* FIXME */ /* TODO */
return nil; OF_UNRECOGNIZED_SELECTOR
} }
- (void)setCertificateFile: (OFString*)certificateFile - (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) OF_SETTER(_certificateFile, certificateFile, true, 1)
} }
- (void)setCertificateFile: (OFString*)certificateFile
forSNIHost: (OFString*)SNIHost
{
/* TODO */
OF_UNRECOGNIZED_SELECTOR
}
- (OFString*)certificateFile - (OFString*)certificateFile
{ {
OF_GETTER(_certificateFile, true) OF_GETTER(_certificateFile, true)
} }
- (OFString*)certificateFileForSNIHost: (OFString*)SNIHost
{
/* TODO */
OF_UNRECOGNIZED_SELECTOR
}
- (void)setPrivateKeyFile: (OFString*)privateKeyFile - (void)setPrivateKeyFile: (OFString*)privateKeyFile
{ {
OF_SETTER(_privateKeyFile, privateKeyFile, true, 1) OF_SETTER(_privateKeyFile, privateKeyFile, true, 1)
} }
- (void)setPrivateKeyFile: (OFString*)privateKeyFile
forSNIHost: (OFString*)SNIHost
{
/* TODO */
OF_UNRECOGNIZED_SELECTOR
}
- (OFString*)privateKeyFile - (OFString*)privateKeyFile
{ {
OF_GETTER(_privateKeyFile, true) OF_GETTER(_privateKeyFile, true)
} }
- (OFString*)privateKeyFileForSNIHost: (OFString*)SNIHost
{
/* TODO */
OF_UNRECOGNIZED_SELECTOR
}
- (void)setPrivateKeyPassphrase: (const char*)privateKeyPassphrase - (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 - (const char*)privateKeyPassphrase
{ {
/* FIXME */ /* TODO */
return NULL; 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 - (OFDataArray*)channelBindingDataWithType: (OFString*)type

View file

@ -21,9 +21,18 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdocumentation"
#endif
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <openssl/x509v3.h> #include <openssl/x509v3.h>
#if defined(__clang__)
# pragma clang diagnostic pop
#endif
#import "X509Certificate.h" #import "X509Certificate.h"
#import <ObjFW/OFAutoreleasePool.h> #import <ObjFW/OFAutoreleasePool.h>