diff --git a/TCPSocket.cpp b/TCPSocket.cpp index 17f10dc..1d7b555 100644 --- a/TCPSocket.cpp +++ b/TCPSocket.cpp @@ -28,7 +28,16 @@ namespace core { } void TCPSocket::receiveData(coreutils::ZString &buffer) { - if(tlsInfo) { + // Dispatch on `ctx`, not `tlsInfo` - the SSL_CTX*-taking constructor + // (used for every accepted TCPSession) never sets `tlsInfo` at all, + // leaving it as uninitialized garbage that intermittently (whenever + // that garbage happened to be non-zero) routed a plain, non-TLS + // session's data through SSL_read()/SSL_write() against an + // uninitialized SSL*, segfaulting inside libssl. `ctx` is the + // reliable signal: real and non-NULL for an actual TLS server/ + // session (set in TLS::createContext(), inherited by sessions via + // TLS(SSL_CTX*)), safely NULL by default otherwise (see TLS.h). + if(ctx) { int len = TLS::receiveData(buffer); if(len >= 0) { coreutils::ZString zbuffer(buffer.getData(), len); @@ -40,7 +49,7 @@ namespace core { } int TCPSocket::sendData(const char *data, int length) { - if(tlsInfo) + if(ctx) return TLS::sendData(data, length); else return Socket::sendData(data, length); diff --git a/TLS.h b/TLS.h index 75f7a63..3bfdfb4 100644 --- a/TLS.h +++ b/TLS.h @@ -46,7 +46,12 @@ namespace core { void createContext(TLSInfo *tlsInfo); - SSL_CTX *ctx; + // A never-configured TLS object (either the listening TCPServer + // itself when constructed with tlsInfo=NULL, or a TCPSession spawned + // from one via TLS(SSL_CTX*)) must default to a real NULL here, not + // garbage - TCPSocket::receiveData()/sendData() key their TLS-vs- + // plain dispatch on this exact value (see TCPSocket.cpp). + SSL_CTX *ctx = NULL; protected: int receiveData(coreutils::ZString &buffer);