Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -34,25 +34,19 @@ AC_PATH_TOOL(AR, ar) AC_PROG_RANLIB 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 dnl We don't call AC_PROG_CPP, but only AC_PROG_OBJCPP and set CPP to OBJCPP Index: src/SSLSocket.h ================================================================== --- src/SSLSocket.h +++ src/SSLSocket.h @@ -31,20 +31,22 @@ @interface SSLSocket: OFTCPSocket { 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; @end Index: src/SSLSocket.m ================================================================== --- src/SSLSocket.m +++ src/SSLSocket.m @@ -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; Index: src/X509Certificate.m ================================================================== --- src/X509Certificate.m +++ src/X509Certificate.m @@ -18,13 +18,22 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * 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 #import