]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Fix use after free in OSSL_HTTP_REQ_CTX_set1_req()
authorTomas Mraz <tomas@openssl.org>
Mon, 7 Jun 2021 14:56:20 +0000 (16:56 +0200)
committerPauli <pauli@openssl.org>
Thu, 10 Jun 2021 08:27:15 +0000 (18:27 +1000)
Fixes #15647

Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15648)

crypto/http/http_client.c

index e7e0183b590a5e703b93079992f271cf4decaad7..79fe9ccd41380fef8b243db5b0fa164c47eb1cee 100644 (file)
@@ -126,7 +126,8 @@ void OSSL_HTTP_REQ_CTX_free(OSSL_HTTP_REQ_CTX *rctx)
     if (rctx->free_wbio)
         BIO_free_all(rctx->wbio);
     /* do not free rctx->rbio */
-    BIO_free(rctx->mem); /* this may indirectly call ERR_clear_error() */
+    BIO_free(rctx->mem);
+    BIO_free(rctx->req);
     OPENSSL_free(rctx->buf);
     OPENSSL_free(rctx->proxy);
     OPENSSL_free(rctx->server);
@@ -260,8 +261,8 @@ int OSSL_HTTP_REQ_CTX_set_expected(OSSL_HTTP_REQ_CTX *rctx,
     return 1;
 }
 
-static int set_content(OSSL_HTTP_REQ_CTX *rctx,
-                       const char *content_type, BIO *req)
+static int set1_content(OSSL_HTTP_REQ_CTX *rctx,
+                        const char *content_type, BIO *req)
 {
     long req_len;
 
@@ -285,10 +286,16 @@ static int set_content(OSSL_HTTP_REQ_CTX *rctx,
             && BIO_printf(rctx->mem, "Content-Type: %s\r\n", content_type) <= 0)
         return 0;
 
-    rctx->req = req;
-    if ((req_len = BIO_ctrl(req, BIO_CTRL_INFO, 0, NULL)) <= 0)
-        return 1; /* streaming BIO may not support querying size */
-    return BIO_printf(rctx->mem, "Content-Length: %ld\r\n", req_len) > 0;
+    /* streaming BIO may not support querying size */
+    if ((req_len = BIO_ctrl(req, BIO_CTRL_INFO, 0, NULL)) <= 0
+        || BIO_printf(rctx->mem, "Content-Length: %ld\r\n", req_len) > 0) {
+        if (!BIO_up_ref(req))
+            return 0;
+        BIO_free(rctx->req);
+        rctx->req = req;
+        return 1;
+    }
+    return 0;
 }
 
 int OSSL_HTTP_REQ_CTX_set1_req(OSSL_HTTP_REQ_CTX *rctx, const char *content_type,
@@ -303,7 +310,7 @@ int OSSL_HTTP_REQ_CTX_set1_req(OSSL_HTTP_REQ_CTX *rctx, const char *content_type
     }
 
     res = (mem = ASN1_item_i2d_mem_bio(it, req)) != NULL
-        && set_content(rctx, content_type, mem);
+        && set1_content(rctx, content_type, mem);
     BIO_free(mem);
     return res;
 }
@@ -965,7 +972,7 @@ int OSSL_HTTP_set_request(OSSL_HTTP_REQ_CTX *rctx, const char *path,
         && add1_headers(rctx, headers, rctx->server)
         && OSSL_HTTP_REQ_CTX_set_expected(rctx, expected_content_type,
                                           expect_asn1, timeout, keep_alive)
-        && set_content(rctx, content_type, req);
+        && set1_content(rctx, content_type, req);
 }
 
 /*-