diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cluster.c | 9 | ||||
-rw-r--r-- | src/connection.c | 6 | ||||
-rw-r--r-- | src/networking.c | 11 | ||||
-rw-r--r-- | src/tls.c | 28 |
4 files changed, 48 insertions, 6 deletions
diff --git a/src/cluster.c b/src/cluster.c index 485683cf0..350aa7b6a 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -672,6 +672,15 @@ void clusterAcceptHandler(aeEventLoop *el, int fd, void *privdata, int mask) { connection *conn = server.tls_cluster ? connCreateAcceptedTLS(cfd, TLS_CLIENT_AUTH_YES) : connCreateAcceptedSocket(cfd); + + /* Make sure connection is not in an error state */ + if (connGetState(conn) != CONN_STATE_ACCEPTING) { + serverLog(LL_VERBOSE, + "Error creating an accepting connection for cluster node: %s", + connGetLastError(conn)); + connClose(conn); + return; + } connNonBlock(conn); connEnableTcpNoDelay(conn); diff --git a/src/connection.c b/src/connection.c index 2015c9195..09fa12f2a 100644 --- a/src/connection.c +++ b/src/connection.c @@ -85,8 +85,12 @@ connection *connCreateSocket() { /* Create a new socket-type connection that is already associated with * an accepted connection. * - * The socket is not read for I/O until connAccept() was called and + * The socket is not ready for I/O until connAccept() was called and * invoked the connection-level accept handler. + * + * Callers should use connGetState() and verify the created connection + * is not in an error state (which is not possible for a socket connection, + * but could but possible with other protocols). */ connection *connCreateAcceptedSocket(int fd) { connection *conn = connCreateSocket(); diff --git a/src/networking.c b/src/networking.c index e3b62f151..a3c04efa6 100644 --- a/src/networking.c +++ b/src/networking.c @@ -895,8 +895,18 @@ void clientAcceptHandler(connection *conn) { #define MAX_ACCEPTS_PER_CALL 1000 static void acceptCommonHandler(connection *conn, int flags, char *ip) { client *c; + char conninfo[100]; UNUSED(ip); + if (connGetState(conn) != CONN_STATE_ACCEPTING) { + serverLog(LL_VERBOSE, + "Accepted client connection in error state: %s (conn: %s)", + connGetLastError(conn), + connGetInfo(conn, conninfo, sizeof(conninfo))); + connClose(conn); + return; + } + /* Limit the number of connections we take at the same time. * * Admission control will happen before a client is created and connAccept() @@ -925,7 +935,6 @@ static void acceptCommonHandler(connection *conn, int flags, char *ip) { /* Create connection and client */ if ((c = createClient(conn)) == NULL) { - char conninfo[100]; serverLog(LL_WARNING, "Error registering fd event for the new client: %s (conn: %s)", connGetLastError(conn), @@ -337,11 +337,34 @@ connection *connCreateTLS(void) { return (connection *) conn; } +/* Fetch the latest OpenSSL error and store it in the connection */ +static void updateTLSError(tls_connection *conn) { + conn->c.last_errno = 0; + if (conn->ssl_error) zfree(conn->ssl_error); + conn->ssl_error = zmalloc(512); + ERR_error_string_n(ERR_get_error(), conn->ssl_error, 512); +} + +/* Create a new TLS connection that is already associated with + * an accepted underlying file descriptor. + * + * The socket is not ready for I/O until connAccept() was called and + * invoked the connection-level accept handler. + * + * Callers should use connGetState() and verify the created connection + * is not in an error state. + */ connection *connCreateAcceptedTLS(int fd, int require_auth) { tls_connection *conn = (tls_connection *) connCreateTLS(); conn->c.fd = fd; conn->c.state = CONN_STATE_ACCEPTING; + if (!conn->ssl) { + updateTLSError(conn); + conn->c.state = CONN_STATE_ERROR; + return (connection *) conn; + } + switch (require_auth) { case TLS_CLIENT_AUTH_NO: SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); @@ -384,10 +407,7 @@ static int handleSSLReturnCode(tls_connection *conn, int ret_value, WantIOType * break; default: /* Error! */ - conn->c.last_errno = 0; - if (conn->ssl_error) zfree(conn->ssl_error); - conn->ssl_error = zmalloc(512); - ERR_error_string_n(ERR_get_error(), conn->ssl_error, 512); + updateTLSError(conn); break; } |