Index: src/SSLSocket.m ================================================================== --- src/SSLSocket.m +++ src/SSLSocket.m @@ -378,11 +378,13 @@ block: (of_tcp_socket_async_connect_block_t)block { [super asyncConnectToHost: host port: port runLoopMode: runLoopMode - block: ^ (SSLSocket *sock, id exception) { + block: ^ (OFTCPSocket *sock_, id exception) { + SSLSocket *sock = (SSLSocket *)sock_; + if (exception == nil) { @try { [sock SSL_startTLSWithExpectedHost: host port: port]; } @catch (id e) { @@ -446,10 +448,20 @@ - (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length { ssize_t ret; + /* + * There is no SSL session yet. However, it might be necessary to read + * 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]; + if (length > INT_MAX) @throw [OFOutOfRangeException exception]; if (_socket == INVALID_SOCKET) @throw [OFNotOpenException exceptionWithObject: self]; @@ -477,10 +489,24 @@ - (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length { int bytesWritten; + /* + * There is no SSL session yet. However, it might be necessary to read + * 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. + * + * 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]; + if (_socket == INVALID_SOCKET) @throw [OFNotOpenException exceptionWithObject: self]; if (length > INT_MAX) @throw [OFOutOfRangeException exception];