OSSL_HTTP_get(): Fix timeout handling on redirection
authorDr. David von Oheimb <David.von.Oheimb@siemens.com>
Mon, 29 Nov 2021 09:07:08 +0000 (10:07 +0100)
committerDr. David von Oheimb <dev@ddvo.net>
Thu, 9 Dec 2021 17:10:07 +0000 (18:10 +0100)
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17190)

crypto/err/openssl.txt
crypto/http/http_client.c
crypto/http/http_err.c
include/openssl/httperr.h

index 777a0de19d7ff176bebb3069516c1f0b126ba988..6e75af9b8bba3407717e9615ee06a0fce6f85715 100644 (file)
@@ -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
index d8e54c03a9d603ba719504ddb51b83e1c9e78884..a85bfcec42dc8f35f7d16d66b56bbf8ad6fcc666 100644 (file)
@@ -463,6 +463,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.
@@ -1071,6 +1086,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);
@@ -1101,7 +1117,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;
index b2f2cfb1879ebf26308e337e2e5757fe150ed6c3..332ad926d3672a16bff46818d697e19a6569dc32 100644 (file)
@@ -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),
index b639ef0051fbb5aa90668b38086f2e9e36400641..ee089592034cc68fa5c0ba545232a34c8b3b8060 100644 (file)
@@ -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