Commit 1c05b87e authored by Yossi Gottlieb's avatar Yossi Gottlieb Committed by Oran Agra
Browse files

TLS: Propagate and handle SSL_new() failures. (#7576)



The connection API may create an accepted connection object in an error
state, and callers are expected to check it before attempting to use it.
Co-authored-by: default avatarmrpre <mrpre@163.com>
(cherry picked from commit 784ceeb9)
parent 67750ce3
...@@ -672,6 +672,15 @@ void clusterAcceptHandler(aeEventLoop *el, int fd, void *privdata, int mask) { ...@@ -672,6 +672,15 @@ void clusterAcceptHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
connection *conn = server.tls_cluster ? connection *conn = server.tls_cluster ?
connCreateAcceptedTLS(cfd, TLS_CLIENT_AUTH_YES) : connCreateAcceptedSocket(cfd); 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); connNonBlock(conn);
connEnableTcpNoDelay(conn); connEnableTcpNoDelay(conn);
......
...@@ -85,8 +85,12 @@ connection *connCreateSocket() { ...@@ -85,8 +85,12 @@ connection *connCreateSocket() {
/* Create a new socket-type connection that is already associated with /* Create a new socket-type connection that is already associated with
* an accepted connection. * 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. * 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 *connCreateAcceptedSocket(int fd) {
connection *conn = connCreateSocket(); connection *conn = connCreateSocket();
......
...@@ -895,8 +895,18 @@ void clientAcceptHandler(connection *conn) { ...@@ -895,8 +895,18 @@ void clientAcceptHandler(connection *conn) {
#define MAX_ACCEPTS_PER_CALL 1000 #define MAX_ACCEPTS_PER_CALL 1000
static void acceptCommonHandler(connection *conn, int flags, char *ip) { static void acceptCommonHandler(connection *conn, int flags, char *ip) {
client *c; client *c;
char conninfo[100];
UNUSED(ip); 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. /* Limit the number of connections we take at the same time.
* *
* Admission control will happen before a client is created and connAccept() * Admission control will happen before a client is created and connAccept()
...@@ -925,7 +935,6 @@ static void acceptCommonHandler(connection *conn, int flags, char *ip) { ...@@ -925,7 +935,6 @@ static void acceptCommonHandler(connection *conn, int flags, char *ip) {
/* Create connection and client */ /* Create connection and client */
if ((c = createClient(conn)) == NULL) { if ((c = createClient(conn)) == NULL) {
char conninfo[100];
serverLog(LL_WARNING, serverLog(LL_WARNING,
"Error registering fd event for the new client: %s (conn: %s)", "Error registering fd event for the new client: %s (conn: %s)",
connGetLastError(conn), connGetLastError(conn),
......
...@@ -337,11 +337,34 @@ connection *connCreateTLS(void) { ...@@ -337,11 +337,34 @@ connection *connCreateTLS(void) {
return (connection *) conn; 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) { connection *connCreateAcceptedTLS(int fd, int require_auth) {
tls_connection *conn = (tls_connection *) connCreateTLS(); tls_connection *conn = (tls_connection *) connCreateTLS();
conn->c.fd = fd; conn->c.fd = fd;
conn->c.state = CONN_STATE_ACCEPTING; conn->c.state = CONN_STATE_ACCEPTING;
if (!conn->ssl) {
updateTLSError(conn);
conn->c.state = CONN_STATE_ERROR;
return (connection *) conn;
}
switch (require_auth) { switch (require_auth) {
case TLS_CLIENT_AUTH_NO: case TLS_CLIENT_AUTH_NO:
SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
...@@ -384,10 +407,7 @@ static int handleSSLReturnCode(tls_connection *conn, int ret_value, WantIOType * ...@@ -384,10 +407,7 @@ static int handleSSLReturnCode(tls_connection *conn, int ret_value, WantIOType *
break; break;
default: default:
/* Error! */ /* Error! */
conn->c.last_errno = 0; updateTLSError(conn);
if (conn->ssl_error) zfree(conn->ssl_error);
conn->ssl_error = zmalloc(512);
ERR_error_string_n(ERR_get_error(), conn->ssl_error, 512);
break; break;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment