Index: src/SSLSocket.h ================================================================== --- src/SSLSocket.h +++ src/SSLSocket.h @@ -35,24 +35,25 @@ OF_ASSUME_NONNULL_BEGIN @class X509Certificate; -@interface SSLSocket: OFTCPSocket +@interface SSLSocket: OFTLSSocket { SSL *_SSL; OFString *_certificateFile, *_privateKeyFile; const char *_privateKeyPassphrase; - bool _verifiesCertificates, _requestsClientCertificates; + bool _requestsClientCertificates; } +@property (copy, nonatomic) OFString *certificateFile, *privateKeyFile; +@property (nonatomic) const char *privateKeyPassphrase; @property (nonatomic) bool requestsClientCertificates; @property OF_NULLABLE_PROPERTY (readonly, nonatomic) X509Certificate *peerCertificate; -- (instancetype)initWithSocket: (OFTCPSocket *)socket; - (OFData *)channelBindingDataWithType: (OFString *)type; - (nullable X509Certificate *)peerCertificate; - (void)verifyPeerCertificate; @end OF_ASSUME_NONNULL_END Index: src/SSLSocket.m ================================================================== --- src/SSLSocket.m +++ src/SSLSocket.m @@ -75,95 +75,23 @@ else OFEnsure(OFPlainMutexUnlock(&SSLMutexes[n]) == 0); } @interface SSLSocket () -- (void)SSL_startTLSWithExpectedHost: (OFString *)host port: (uint16_t)port; - (void)SSL_super_close; -@end - -@interface SSLSocket_ConnectDelegate: OFObject -{ - SSLSocket *_socket; - OFString *_host; - uint16_t _port; - id _delegate; -} - -- (instancetype)initWithSocket: (SSLSocket *)sock - host: (OFString *)host - port: (uint16_t)port - delegate: (id )delegate; -@end - -@implementation SSLSocket_ConnectDelegate -- (instancetype)initWithSocket: (SSLSocket *)sock - host: (OFString *)host - port: (uint16_t)port - delegate: (id )delegate -{ - self = [super init]; - - @try { - _socket = [sock retain]; - _host = [host copy]; - _port = port; - _delegate = [delegate retain]; - - _socket.delegate = self; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - if (_socket.delegate == self) - _socket.delegate = _delegate; - - [_socket release]; - [_delegate release]; - - [super dealloc]; -} - -- (void)socket: (OFTCPSocket *)sock - didConnectToHost: (OFString *)host - port: (uint16_t)port - exception: (id)exception -{ - if (exception == nil) { - @try { - [(SSLSocket *)sock SSL_startTLSWithExpectedHost: _host - port: _port]; - } @catch (id e) { - exception = e; - } - } - - _socket.delegate = _delegate; - [_delegate socket: sock - didConnectToHost: host - port: port - exception: exception]; -} @end @implementation SSLSocket @dynamic delegate; @synthesize certificateFile = _certificateFile; @synthesize privateKeyFile = _privateKeyFile; @synthesize privateKeyPassphrase = _privateKeyPassphrase; -@synthesize verifiesCertificates = _verifiesCertificates; @synthesize requestsClientCertificates = _requestsClientCertificates; + (void)load { - OFTLSSocketClass = self; + OFTLSSocketImplementation = self; } + (void)initialize { int m; @@ -200,34 +128,10 @@ if (SSL_CTX_set_default_verify_paths(ctx) == 0) @throw [OFInitializationFailedException exceptionWithClass: self]; } -- (instancetype)init -{ - self = [super init]; - - _verifiesCertificates = true; - - return self; -} - -- (instancetype)initWithSocket: (OFTCPSocket *)socket -{ - self = [self init]; - - @try { - if ((_socket = dup(socket->_socket)) < 0) - @throw [OFInitializationFailedException exception]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - - (void)dealloc { SSL *SSL_ = _SSL; [_privateKeyFile release]; @@ -237,11 +141,11 @@ if (SSL_ != NULL) SSL_free(SSL_); } -- (void)SSL_startTLSWithExpectedHost: (OFString *)host port: (uint16_t)port +- (void)startTLSForHost: (OFString *)host port: (uint16_t)port { OFStringEncoding encoding; if ((_SSL = SSL_new(ctx)) == NULL || SSL_set_fd(_SSL, _socket) != 1) { unsigned long error = ERR_get_error(); @@ -327,59 +231,13 @@ socket: self SSLError: error]; } } -- (void)startTLSWithExpectedHost: (OFString *)host -{ - [self SSL_startTLSWithExpectedHost: host port: 0]; -} - -- (void)asyncConnectToHost: (OFString *)host - port: (uint16_t)port - runLoopMode: (OFRunLoopMode)runLoopMode -{ - void *pool = objc_autoreleasePoolPush(); - - [[[SSLSocket_ConnectDelegate alloc] - initWithSocket: self - host: host - port: port - delegate: _delegate] autorelease]; - [super asyncConnectToHost: host port: port runLoopMode: runLoopMode]; - - objc_autoreleasePoolPop(pool); -} - -#ifdef OF_HAVE_BLOCKS -- (void)asyncConnectToHost: (OFString *)host - port: (uint16_t)port - runLoopMode: (OFRunLoopMode)runLoopMode - block: (OFTCPSocketAsyncConnectBlock)block -{ - [super asyncConnectToHost: host - port: port - runLoopMode: runLoopMode - block: ^ (id exception) { - if (exception == nil) { - @try { - [self SSL_startTLSWithExpectedHost: host - port: port]; - } @catch (id e) { - block(e); - return; - } - } - - block(exception); - }]; -} -#endif - - (instancetype)accept { - SSLSocket *client = (SSLSocket *)[super accept]; + SSLSocket *client = [self TCPAccept]; OFStringEncoding encoding; if ((client->_SSL = SSL_new(ctx)) == NULL || !SSL_set_fd(client->_SSL, client->_socket)) { [client SSL_super_close]; @@ -431,11 +289,11 @@ * from and write to the socket before negotiating an SSL session: For * example, the socket might be connected to a SOCKS5 proxy and needs * to establish a SOCKS5 connection before negotiating an SSL session. */ if (_SSL == NULL) - return [super lowlevelReadIntoBuffer: buffer length: length]; + return [self lowlevelTCPReadIntoBuffer: buffer length: length]; if (length > INT_MAX) @throw [OFOutOfRangeException exception]; if (_socket == INVALID_SOCKET) @@ -474,11 +332,11 @@ * TODO: Think of a way to make this safer, so that it's impossible to * forget to establish an SSL session and then send unencrypted data by * accident. */ if (_SSL == NULL) - return [super lowlevelWriteBuffer: buffer length: length]; + return [self lowlevelTCPWriteBuffer: buffer length: length]; if (_socket == INVALID_SOCKET) @throw [OFNotOpenException exceptionWithObject: self]; if (length > INT_MAX) @@ -491,55 +349,16 @@ errNo: 0]; return bytesWritten; } -- (bool)hasDataInReadBuffer +- (bool)lowlevelIsAtEndOfStream { if (_SSL != NULL && SSL_pending(_SSL) > 0) - return true; - - return super.hasDataInReadBuffer; -} - -- (void)setCertificateFile: (OFString *)certificateFile - forSNIHost: (OFString *)SNIHost -{ - /* TODO */ - OF_UNRECOGNIZED_SELECTOR -} - -- (OFString *)certificateFileForSNIHost: (OFString *)SNIHost -{ - /* TODO */ - OF_UNRECOGNIZED_SELECTOR -} - -- (void)setPrivateKeyFile: (OFString *)privateKeyFile - forSNIHost: (OFString *)SNIHost -{ - /* TODO */ - OF_UNRECOGNIZED_SELECTOR -} - -- (OFString *)privateKeyFileForSNIHost: (OFString *)SNIHost -{ - /* TODO */ - OF_UNRECOGNIZED_SELECTOR -} - -- (void)setPrivateKeyPassphrase: (const char *)privateKeyPassphrase - forSNIHost: (OFString *)SNIHost -{ - /* TODO */ - OF_UNRECOGNIZED_SELECTOR -} - -- (const char *)privateKeyPassphraseForSNIHost: (OFString *)SNIHost -{ - /* TODO */ - OF_UNRECOGNIZED_SELECTOR + return false; + + return [self lowlevelTCPIsAtEndOfStream]; } - (OFData *)channelBindingDataWithType: (OFString *)type { size_t length;