From: Dr. David von Oheimb Date: Mon, 29 Nov 2021 09:07:08 +0000 (+0100) Subject: OSSL_HTTP_get(): Fix timeout handling on redirection X-Git-Tag: openssl-3.0.1~34 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=93838762b406efe3aad9c807a0fd1f48e6efe3ab;p=thirdparty%2Fopenssl.git OSSL_HTTP_get(): Fix timeout handling on redirection Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/17190) (cherry picked from commit f0d5a3b6ea1bbe4e5dac5b69d853c015db635621) --- diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 777a0de19d7..6e75af9b8bb 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -779,6 +779,7 @@ HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP:112:redirection from https to http HTTP_R_REDIRECTION_NOT_ENABLED:116:redirection not enabled HTTP_R_RESPONSE_LINE_TOO_LONG:113:response line too long HTTP_R_RESPONSE_PARSE_ERROR:104:response parse error +HTTP_R_RETRY_TIMEOUT:129:retry timeout HTTP_R_SERVER_CANCELED_CONNECTION:127:server canceled connection HTTP_R_SOCK_NOT_SUPPORTED:122:sock not supported HTTP_R_STATUS_CODE_UNSUPPORTED:114:status code unsupported diff --git a/crypto/http/http_client.c b/crypto/http/http_client.c index 23677ca12fb..7f8d8fc8d7d 100644 --- a/crypto/http/http_client.c +++ b/crypto/http/http_client.c @@ -464,6 +464,21 @@ static int check_set_resp_len(OSSL_HTTP_REQ_CTX *rctx, size_t len) return 1; } +static int may_still_retry(time_t max_time, int *ptimeout) +{ + time_t time_diff, now = time(NULL); + + if (max_time != 0) { + if (max_time < now) { + ERR_raise(ERR_LIB_HTTP, HTTP_R_RETRY_TIMEOUT); + return 0; + } + time_diff = max_time - now; + *ptimeout = time_diff > INT_MAX ? INT_MAX : (int)time_diff; + } + return 1; +} + /* * Try exchanging request and response via HTTP on (non-)blocking BIO in rctx. * Returns 1 on success, 0 on error or redirection, -1 on BIO_should_retry. @@ -1081,6 +1096,7 @@ BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy, int use_ssl; OSSL_HTTP_REQ_CTX *rctx; BIO *resp = NULL; + time_t max_time = timeout > 0 ? time(NULL) + timeout : 0; if (url == NULL) { ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); @@ -1111,7 +1127,8 @@ BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy, } OPENSSL_free(path); if (resp == NULL && redirection_url != NULL) { - if (redirection_ok(++n_redirs, current_url, redirection_url)) { + if (redirection_ok(++n_redirs, current_url, redirection_url) + && may_still_retry(max_time, &timeout)) { (void)BIO_reset(bio); OPENSSL_free(current_url); current_url = redirection_url; diff --git a/crypto/http/http_err.c b/crypto/http/http_err.c index b2f2cfb1879..332ad926d36 100644 --- a/crypto/http/http_err.c +++ b/crypto/http/http_err.c @@ -55,6 +55,7 @@ static const ERR_STRING_DATA HTTP_str_reasons[] = { "response line too long"}, {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RESPONSE_PARSE_ERROR), "response parse error"}, + {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RETRY_TIMEOUT), "retry timeout"}, {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SERVER_CANCELED_CONNECTION), "server canceled connection"}, {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SOCK_NOT_SUPPORTED), diff --git a/include/openssl/httperr.h b/include/openssl/httperr.h index b639ef0051f..ee089592034 100644 --- a/include/openssl/httperr.h +++ b/include/openssl/httperr.h @@ -44,6 +44,7 @@ # define HTTP_R_REDIRECTION_NOT_ENABLED 116 # define HTTP_R_RESPONSE_LINE_TOO_LONG 113 # define HTTP_R_RESPONSE_PARSE_ERROR 104 +# define HTTP_R_RETRY_TIMEOUT 129 # define HTTP_R_SERVER_CANCELED_CONNECTION 127 # define HTTP_R_SOCK_NOT_SUPPORTED 122 # define HTTP_R_STATUS_CODE_UNSUPPORTED 114