summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cluster.c9
-rw-r--r--src/connection.c6
-rw-r--r--src/networking.c11
-rw-r--r--src/tls.c28
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),
diff --git a/src/tls.c b/src/tls.c
index 07d1775f8..4f0ea4d65 100644
--- a/src/tls.c
+++ b/src/tls.c
@@ -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;
}