From 068e3d73ce6814879832c9400c10afe2458c2004 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Wed, 26 Apr 2017 14:00:35 +0100 Subject: [PATCH] Fix an s_server infinite loop Commit c4666bfa changed s_server so that it asked libssl rather than the underlying socket whether an error is retryable or not on the basis that libssl has more information. That is true unfortunately the method used was wrong - it only checks libssl's own internal state rather than both libssl and the BIO. Should use SSL_get_error() instead. This issue can cause an infinite loop because some errors could appear as retryable when in fact they are not. Reviewed-by: Rich Salz Reviewed-by: Tim Hudson (Merged from https://github.com/openssl/openssl/pull/3317) --- apps/s_server.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/apps/s_server.c b/apps/s_server.c index e597ecbeb1..815549b0c6 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -2609,6 +2609,16 @@ static void close_accept_socket(void) } } +static int is_retryable(SSL *con, int i) +{ + int err = SSL_get_error(con, i); + + /* If it's not a fatal error, it must be retryable */ + return (err != SSL_ERROR_SSL) + && (err != SSL_ERROR_SYSCALL) + && (err != SSL_ERROR_ZERO_RETURN); +} + static int init_ssl_connection(SSL *con) { int i; @@ -2651,7 +2661,7 @@ static int init_ssl_connection(SSL *con) i = SSL_accept(con); if (i <= 0) - retry = !SSL_want_nothing(con); + retry = is_retryable(con, i); #ifdef CERT_CB_TEST_RETRY { while (i <= 0 @@ -2661,7 +2671,7 @@ static int init_ssl_connection(SSL *con) "LOOKUP from certificate callback during accept\n"); i = SSL_accept(con); if (i <= 0) - retry = !SSL_want_nothing(con); + retry = is_retryable(con, i); } } #endif @@ -2682,7 +2692,7 @@ static int init_ssl_connection(SSL *con) BIO_printf(bio_s_out, "LOOKUP not successful\n"); i = SSL_accept(con); if (i <= 0) - retry = !SSL_want_nothing(con); + retry = is_retryable(con, i); } #endif } while (i < 0 && SSL_waiting_for_async(con)); -- 2.25.1