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: mrpre <mrpre@163.com> (cherry picked from commit bc450c5f63d39d0f0b8c97fa91d15bb8d688b86d)
This commit is contained in:
parent
10a8407a4f
commit
ebdfa71584
@ -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() {
|
|||||||
/* 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) {
|
|||||||
#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) {
|
|||||||
|
|
||||||
/* 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),
|
||||||
|
28
src/tls.c
28
src/tls.c
@ -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 *
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user