@@ -24,13 +24,23 @@ */ #include #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 #import #import @@ -113,16 +123,31 @@ if (SSL_CTX_set_default_verify_paths(ctx) == 0) @throw [OFInitializationFailedException 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; } - (void)dealloc @@ -136,21 +161,38 @@ if (SSL_ != NULL) 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]; @@ -160,23 +202,30 @@ !SSL_use_certificate_file(_SSL, [_certificateFile cStringWithEncoding: encoding], 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 { SSLSocket *client = (SSLSocket*)[super accept]; @@ -188,11 +237,11 @@ /* FIXME: Get a proper errno */ @throw [OFAcceptFailedException exceptionWithSocket: self errNo: 0]; } - if (_requestsClientCertificates) + if (_requestClientCertificatesEnabled) SSL_set_verify(client->_SSL, SSL_VERIFY_PEER, NULL); SSL_set_accept_state(client->_SSL); encoding = [OFSystemInfo native8BitEncoding]; @@ -281,60 +330,109 @@ return [super hasDataInReadBuffer]; } - (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 { 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 +{ + /* TODO */ + OF_UNRECOGNIZED_SELECTOR +} - (void)setPrivateKeyPassphrase: (const char*)privateKeyPassphrase + forSNIHost: (OFString*)SNIHost { - /* FIXME */ + /* TODO */ + OF_UNRECOGNIZED_SELECTOR } - (const char*)privateKeyPassphrase { - /* FIXME */ - return NULL; + /* TODO */ + OF_UNRECOGNIZED_SELECTOR +} + +- (const char*)privateKeyPassphraseForSNIHost: (OFString*)SNIHost +{ + /* TODO */ + OF_UNRECOGNIZED_SELECTOR +} + +- (void)setCertificateVerificationEnabled: (bool)enabled +{ + _certificateVerificationEnabled = enabled; +} + +- (bool)isCertificateVerificationEnabled +{ + return _certificateVerificationEnabled; } -- (void)setRequestsClientCertificates: (bool)enabled +- (void)setRequestClientCertificatesEnabled: (bool)enabled { - _requestsClientCertificates = enabled; + _requestClientCertificatesEnabled = enabled; } -- (bool)requestsClientCertificates +- (bool)isRequestClientCertificatesEnabled { - return _requestsClientCertificates; + return _requestClientCertificatesEnabled; } - (OFDataArray*)channelBindingDataWithType: (OFString*)type { size_t length;