[openssl] master update

dev at ddvo.net dev at ddvo.net
Tue Feb 2 06:55:33 UTC 2021


The branch master has been updated
       via  6aab42c39060c7aa39d96c7a265ddc661cea2ed8 (commit)
       via  4d190f99ef1b6fa8c49ca1fd9bda872e5f51ec93 (commit)
       via  a6d40689ecfb5246c67feee3b8aa5698bb062e90 (commit)
       via  d337af18919a5c24c6f1d0ceb9fdb7aaf1beaef4 (commit)
       via  8e716147971971beb9ce747c74822abd24c6be13 (commit)
       via  673474b1640a0265530ad42868d1c8b7d33bef77 (commit)
      from  f2db0528d8d7015ba39faca78a16e5e820db9df6 (commit)


- Log -----------------------------------------------------------------
commit 6aab42c39060c7aa39d96c7a265ddc661cea2ed8
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Mon Jan 25 20:44:39 2021 +0100

    OSSL_HTTP_REQ_CTX.pod and OSSL_HTTP_transfer.pod: various improvements
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13960)

commit 4d190f99ef1b6fa8c49ca1fd9bda872e5f51ec93
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Fri Jan 29 19:08:45 2021 +0100

    Constify OSSL_HTTP_REQ_CTX_get0_mem_bio()
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13960)

commit a6d40689ecfb5246c67feee3b8aa5698bb062e90
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Mon Jan 25 22:54:17 2021 +0100

    HTTP: add more error detection to low-level API
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13960)

commit d337af18919a5c24c6f1d0ceb9fdb7aaf1beaef4
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Mon Jan 25 19:49:58 2021 +0100

    HTTP: Fix mistakes and unclarities on maxline and max_resp_len params
    
    Also rename internal structure fields iobuf(len) to readbuf(len) for clarity
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13960)

commit 8e716147971971beb9ce747c74822abd24c6be13
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Mon Jan 25 19:25:18 2021 +0100

    Fix not backwards-compat X509_http_nbio() and X509_CRL_http_nbio()
    
    Provides partial fix of #13127.
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13960)

commit 673474b1640a0265530ad42868d1c8b7d33bef77
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Mon Jan 25 16:18:40 2021 +0100

    OSSL_HTTP_REQ_CTX_nbio(): Revert to having state var that keeps req len still to send
    
    Otherwise, sending goes wrong in case BIO_write(rctx->wbio, ...) is incomplete at first.
    
    Fixes #13938
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13960)

-----------------------------------------------------------------------

Summary of changes:
 crypto/err/openssl.txt          |  1 +
 crypto/http/http_client.c       | 82 +++++++++++++++++++++++------------------
 crypto/http/http_err.c          |  2 +
 doc/man3/OSSL_HTTP_REQ_CTX.pod  | 47 ++++++++++++++---------
 doc/man3/OSSL_HTTP_transfer.pod | 13 ++++---
 doc/man3/X509_load_http.pod     |  4 +-
 include/openssl/http.h          |  5 ++-
 include/openssl/httperr.h       |  1 +
 include/openssl/x509.h.in       |  8 +++-
 9 files changed, 100 insertions(+), 63 deletions(-)

diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 8418463fc7..9bc59a4bfb 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -2641,6 +2641,7 @@ HTTP_R_ERROR_PARSING_CONTENT_LENGTH:119:error parsing content length
 HTTP_R_ERROR_PARSING_URL:101:error parsing url
 HTTP_R_ERROR_RECEIVING:103:error receiving
 HTTP_R_ERROR_SENDING:102:error sending
+HTTP_R_FAILED_READING_DATA:128:failed reading data
 HTTP_R_INCONSISTENT_CONTENT_LENGTH:120:inconsistent content length
 HTTP_R_INVALID_PORT_NUMBER:123:invalid port number
 HTTP_R_INVALID_URL_PATH:125:invalid url path
diff --git a/crypto/http/http_client.c b/crypto/http/http_client.c
index 6b627e15b0..56fb876ee6 100644
--- a/crypto/http/http_client.c
+++ b/crypto/http/http_client.c
@@ -42,23 +42,21 @@
 
 struct ossl_http_req_ctx_st {
     int state;                  /* Current I/O state */
-    unsigned char *iobuf;       /* Line buffer */
-    int iobuflen;               /* Line buffer length */
+    unsigned char *readbuf;     /* Buffer for reading response by line */
+    int readbuflen;             /* Buffer length, equals maxline */
     BIO *wbio;                  /* BIO to send request to */
     BIO *rbio;                  /* BIO to read response from */
     BIO *mem;                   /* Memory BIO response is built into */
     int method_POST;            /* HTTP method is "POST" (else "GET") */
     const char *expected_ct;    /* expected Content-Type, or NULL */
     int expect_asn1;            /* response must be ASN.1-encoded */
+    long len_to_send;           /* number of bytes in request still to send */
     unsigned long resp_len;     /* length of response */
     unsigned long max_resp_len; /* Maximum length of response */
     time_t max_time;            /* Maximum end time of the transfer, or 0 */
     char *redirection_url;      /* Location given with HTTP status 301/302 */
 };
 
-#define HTTP_DEFAULT_MAX_LINE_LENGTH (4 * 1024)
-#define HTTP_DEFAULT_MAX_RESP_LEN (100 * 1024)
-
 /* HTTP states */
 
 #define OHS_NOREAD          0x1000 /* If set no reading should be performed */
@@ -68,7 +66,7 @@ struct ossl_http_req_ctx_st {
 #define OHS_HEADERS         2 /* MIME headers being read */
 #define OHS_ASN1_HEADER     3 /* HTTP initial header (tag+length) being read */
 #define OHS_CONTENT         4 /* HTTP content octets being read */
-#define OHS_WRITE_INIT     (5 | OHS_NOREAD) /* 1st call: ready to start I/O */
+#define OHS_WRITE_INIT     (5 | OHS_NOREAD) /* 1st call: ready to start send */
 #define OHS_WRITE          (6 | OHS_NOREAD) /* Request being sent */
 #define OHS_FLUSH          (7 | OHS_NOREAD) /* Request being flushed */
 #define OHS_DONE           (8 | OHS_NOREAD) /* Completed */
@@ -91,13 +89,12 @@ OSSL_HTTP_REQ_CTX *OSSL_HTTP_REQ_CTX_new(BIO *wbio, BIO *rbio,
     if ((rctx = OPENSSL_zalloc(sizeof(*rctx))) == NULL)
         return NULL;
     rctx->state = OHS_ERROR;
-    rctx->iobuflen = maxline > 0 ? maxline : HTTP_DEFAULT_MAX_LINE_LENGTH;
-    rctx->iobuf = OPENSSL_malloc(rctx->iobuflen);
+    rctx->readbuflen = maxline > 0 ? maxline : HTTP_DEFAULT_MAX_LINE_LENGTH;
+    rctx->readbuf = OPENSSL_malloc(rctx->readbuflen);
     rctx->wbio = wbio;
     rctx->rbio = rbio;
-    rctx->mem = BIO_new(BIO_s_mem());
-    if (rctx->iobuf == NULL || rctx->mem == NULL) {
-        OSSL_HTTP_REQ_CTX_free(rctx);
+    if (rctx->readbuf == NULL) {
+        OPENSSL_free(rctx);
         return NULL;
     }
     rctx->method_POST = method_POST;
@@ -106,6 +103,7 @@ OSSL_HTTP_REQ_CTX *OSSL_HTTP_REQ_CTX_new(BIO *wbio, BIO *rbio,
     rctx->resp_len = 0;
     OSSL_HTTP_REQ_CTX_set_max_response_length(rctx, max_resp_len);
     rctx->max_time = timeout > 0 ? time(NULL) + timeout : 0;
+    /* everything else is 0, e.g. rctx->len_to_send, or NULL, e.g. rctx->mem  */
     return rctx;
 }
 
@@ -114,11 +112,11 @@ void OSSL_HTTP_REQ_CTX_free(OSSL_HTTP_REQ_CTX *rctx)
     if (rctx == NULL)
         return;
     BIO_free(rctx->mem); /* this may indirectly call ERR_clear_error() */
-    OPENSSL_free(rctx->iobuf);
+    OPENSSL_free(rctx->readbuf);
     OPENSSL_free(rctx);
 }
 
-BIO *OSSL_HTTP_REQ_CTX_get0_mem_bio(OSSL_HTTP_REQ_CTX *rctx)
+BIO *OSSL_HTTP_REQ_CTX_get0_mem_bio(const OSSL_HTTP_REQ_CTX *rctx)
 {
     if (rctx == NULL) {
         ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
@@ -149,6 +147,9 @@ int OSSL_HTTP_REQ_CTX_set_request_line(OSSL_HTTP_REQ_CTX *rctx,
         ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
+    BIO_free(rctx->mem);
+    if ((rctx->mem = BIO_new(BIO_s_mem())) == NULL)
+        return 0;
 
     if (BIO_printf(rctx->mem, "%s ", rctx->method_POST ? "POST" : "GET") <= 0)
         return 0;
@@ -183,6 +184,10 @@ int OSSL_HTTP_REQ_CTX_add1_header(OSSL_HTTP_REQ_CTX *rctx,
         ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
+    if (rctx->mem == NULL) {
+        ERR_raise(ERR_LIB_HTTP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+        return 0;
+    }
 
     if (BIO_puts(rctx->mem, name) <= 0)
         return 0;
@@ -198,8 +203,8 @@ int OSSL_HTTP_REQ_CTX_add1_header(OSSL_HTTP_REQ_CTX *rctx,
     return 1;
 }
 
-static int OSSL_HTTP_REQ_CTX_content(OSSL_HTTP_REQ_CTX *rctx,
-                                     const char *content_type, BIO *req_mem)
+static int OSSL_HTTP_REQ_CTX_set_content(OSSL_HTTP_REQ_CTX *rctx,
+                                         const char *content_type, BIO *req_mem)
 {
     const unsigned char *req;
     long req_len;
@@ -208,7 +213,7 @@ static int OSSL_HTTP_REQ_CTX_content(OSSL_HTTP_REQ_CTX *rctx,
         ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
-    if (!rctx->method_POST) {
+    if (rctx->mem == NULL || !rctx->method_POST) {
         ERR_raise(ERR_LIB_HTTP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
         return 0;
     }
@@ -255,7 +260,7 @@ int OSSL_HTTP_REQ_CTX_i2d(OSSL_HTTP_REQ_CTX *rctx, const char *content_type,
     }
 
     res = (mem = HTTP_asn1_item2bio(it, req)) != NULL
-        && OSSL_HTTP_REQ_CTX_content(rctx, content_type, mem);
+        && OSSL_HTTP_REQ_CTX_set_content(rctx, content_type, mem);
     BIO_free(mem);
     return res;
 }
@@ -315,7 +320,7 @@ OSSL_HTTP_REQ_CTX *HTTP_REQ_CTX_new(BIO *wbio, BIO *rbio, int use_http_proxy,
                                            path)
         && OSSL_HTTP_REQ_CTX_add1_headers(rctx, headers, server)
         && (req_mem == NULL
-            || OSSL_HTTP_REQ_CTX_content(rctx, content_type, req_mem)))
+            || OSSL_HTTP_REQ_CTX_set_content(rctx, content_type, req_mem)))
         return rctx;
 
     OSSL_HTTP_REQ_CTX_free(rctx);
@@ -408,7 +413,8 @@ static int check_set_resp_len(OSSL_HTTP_REQ_CTX *rctx, unsigned long len)
                        "length=%lu, max=%lu", len, rctx->max_resp_len);
     if (rctx->resp_len != 0 && rctx->resp_len != len)
         ERR_raise_data(ERR_LIB_HTTP, HTTP_R_INCONSISTENT_CONTENT_LENGTH,
-                       "length=%lu, before=%lu", len, rctx->resp_len);
+                       "ASN.1 length=%lu, Content-Length=%lu",
+                       len, rctx->resp_len);
     rctx->resp_len = len;
     return 1;
 }
@@ -420,7 +426,7 @@ static int check_set_resp_len(OSSL_HTTP_REQ_CTX *rctx, unsigned long len)
 int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
 {
     int i;
-    long n, n_to_send = 0;
+    long n;
     unsigned long resp_len;
     const unsigned char *p;
     char *key, *value, *line_end = NULL;
@@ -429,19 +435,24 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
         ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
+    if (rctx->mem == NULL || rctx->wbio == NULL || rctx->rbio == NULL) {
+        ERR_raise(ERR_LIB_HTTP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+        return 0;
+    }
 
     rctx->redirection_url = NULL;
  next_io:
     if ((rctx->state & OHS_NOREAD) == 0) {
-        n = BIO_read(rctx->rbio, rctx->iobuf, rctx->iobuflen);
+        n = BIO_read(rctx->rbio, rctx->readbuf, rctx->readbuflen);
         if (n <= 0) {
             if (BIO_should_retry(rctx->rbio))
                 return -1;
+            ERR_raise(ERR_LIB_HTTP, HTTP_R_FAILED_READING_DATA);
             return 0;
         }
 
         /* Write data to memory BIO */
-        if (BIO_write(rctx->mem, rctx->iobuf, n) != n)
+        if (BIO_write(rctx->mem, rctx->readbuf, n) != n)
             return 0;
     }
 
@@ -456,14 +467,13 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
 
         /* fall thru */
     case OHS_WRITE_INIT:
-        n_to_send = BIO_get_mem_data(rctx->mem, NULL);
+        rctx->len_to_send = BIO_get_mem_data(rctx->mem, NULL);
         rctx->state = OHS_WRITE;
 
         /* fall thru */
     case OHS_WRITE:
-        n = BIO_get_mem_data(rctx->mem, &p);
-
-        i = BIO_write(rctx->wbio, p + (n - n_to_send), n_to_send);
+        n = BIO_get_mem_data(rctx->mem, &p) - rctx->len_to_send;
+        i = BIO_write(rctx->wbio, p + n, rctx->len_to_send);
 
         if (i <= 0) {
             if (BIO_should_retry(rctx->wbio))
@@ -472,9 +482,9 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
             return 0;
         }
 
-        n_to_send -= i;
+        rctx->len_to_send -= i;
 
-        if (n_to_send > 0)
+        if (rctx->len_to_send > 0)
             goto next_io;
 
         rctx->state = OHS_FLUSH;
@@ -513,13 +523,13 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
          */
         n = BIO_get_mem_data(rctx->mem, &p);
         if (n <= 0 || memchr(p, '\n', n) == 0) {
-            if (n >= rctx->iobuflen) {
+            if (n >= rctx->readbuflen) {
                 rctx->state = OHS_ERROR;
                 return 0;
             }
             goto next_io;
         }
-        n = BIO_gets(rctx->mem, (char *)rctx->iobuf, rctx->iobuflen);
+        n = BIO_gets(rctx->mem, (char *)rctx->readbuf, rctx->readbuflen);
 
         if (n <= 0) {
             if (BIO_should_retry(rctx->mem))
@@ -529,7 +539,7 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
         }
 
         /* Don't allow excessive lines */
-        if (n == rctx->iobuflen) {
+        if (n == rctx->readbuflen) {
             ERR_raise(ERR_LIB_HTTP, HTTP_R_RESPONSE_LINE_TOO_LONG);
             rctx->state = OHS_ERROR;
             return 0;
@@ -537,7 +547,7 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
 
         /* First line */
         if (rctx->state == OHS_FIRSTLINE) {
-            switch (parse_http_line1((char *)rctx->iobuf)) {
+            switch (parse_http_line1((char *)rctx->readbuf)) {
             case HTTP_STATUS_CODE_OK:
                 rctx->state = OHS_HEADERS;
                 goto next_line;
@@ -555,7 +565,7 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
                 return 0;
             }
         }
-        key = (char *)rctx->iobuf;
+        key = (char *)rctx->readbuf;
         value = strchr(key, ':');
         if (value != NULL) {
             *(value++) = '\0';
@@ -596,8 +606,8 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
             }
         }
 
-        /* Look for blank line: end of headers */
-        for (p = rctx->iobuf; *p != '\0'; p++) {
+        /* Look for blank line indicating end of headers */
+        for (p = rctx->readbuf; *p != '\0'; p++) {
             if (*p != '\r' && *p != '\n')
                 break;
         }
@@ -1177,7 +1187,7 @@ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port,
             BIO_printf(fbio, "Proxy-Authorization: Basic %s\r\n", proxyauthenc);
             OPENSSL_clear_free(proxyauthenc, strlen(proxyauthenc));
         }
-     proxy_end:
+    proxy_end:
         OPENSSL_clear_free(proxyauth, len);
         if (proxyauthenc == NULL)
             goto end;
diff --git a/crypto/http/http_err.c b/crypto/http/http_err.c
index ec46fb9304..49e56bedbf 100644
--- a/crypto/http/http_err.c
+++ b/crypto/http/http_err.c
@@ -25,6 +25,8 @@ static const ERR_STRING_DATA HTTP_str_reasons[] = {
     {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ERROR_PARSING_URL), "error parsing url"},
     {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ERROR_RECEIVING), "error receiving"},
     {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ERROR_SENDING), "error sending"},
+    {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_FAILED_READING_DATA),
+    "failed reading data"},
     {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_INCONSISTENT_CONTENT_LENGTH),
     "inconsistent content length"},
     {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_INVALID_PORT_NUMBER),
diff --git a/doc/man3/OSSL_HTTP_REQ_CTX.pod b/doc/man3/OSSL_HTTP_REQ_CTX.pod
index 3955359978..0b730b4e17 100644
--- a/doc/man3/OSSL_HTTP_REQ_CTX.pod
+++ b/doc/man3/OSSL_HTTP_REQ_CTX.pod
@@ -40,7 +40,7 @@ OSSL_HTTP_REQ_CTX_set_max_response_length
  ASN1_VALUE *OSSL_HTTP_REQ_CTX_sendreq_d2i(OSSL_HTTP_REQ_CTX *rctx,
                                            const ASN1_ITEM *it);
 
- BIO *OSSL_HTTP_REQ_CTX_get0_mem_bio(OSSL_HTTP_REQ_CTX *rctx);
+ BIO *OSSL_HTTP_REQ_CTX_get0_mem_bio(const OSSL_HTTP_REQ_CTX *rctx);
  void OSSL_HTTP_REQ_CTX_set_max_response_length(OSSL_HTTP_REQ_CTX *rctx,
                                                 unsigned long len);
 
@@ -56,10 +56,13 @@ should be preferred.
 OSSL_HTTP_REQ_CTX_new() allocates a new HTTP request context structure,
 which gets populated with the B<BIO> to send the request to (I<wbio>),
 the B<BIO> to read the response from (I<rbio>, which may be equal to I<wbio>),
+the maximum expected response header line length (I<maxline>, where a value <= 0
+indicates that the B<HTTP_DEFAULT_MAX_LINE_LENGTH> of 4KiB should be used;
+this length is also used as the number of content bytes read at a time),
 the request method (I<method_POST>, which may be 1 to indicate that the C<POST>
 method is to be used, or 0 to indicate that the C<GET> method is to be used),
-the maximum expected response header length (I<max_resp_len>,
-where any zero or less indicates the default of 4KiB),
+the maximum allowed response content length (I<max_resp_len>, where 0 means
+that the B<HTTP_DEFAULT_MAX_RESP_LEN> is used, which currently is 100 KiB),
 a response timeout measure in seconds (I<timeout>,
 where 0 indicates no timeout, i.e., waiting indefinitely),
 the expected MIME content type of the response (I<expected_content_type>,
@@ -87,31 +90,38 @@ For example, to add a C<Host> header for C<example.com> you would call:
 
  OSSL_HTTP_REQ_CTX_add1_header(ctx, "Host", "example.com");
 
-OSSL_HTTP_REQ_CTX_i2d() finalizes the HTTP request context by adding the DER
-encoding of I<req>, using the ASN.1 template I<it> to do the encoding.  The
-HTTP header C<Content-Length> is automatically filled out, and if
+OSSL_HTTP_REQ_CTX_i2d() finalizes the HTTP request context by adding
+the DER encoding of I<req>, using the ASN.1 template I<it> to do the encoding.
+The HTTP header C<Content-Length> is automatically filled out, and if
 I<content_type> isn't NULL, the HTTP header C<Content-Type> is also added with
 its content as value.  All of this ends up in the internal memory B<BIO>.
 This requires that I<method_POST> was 1 in the OSSL_HTTP_REQ_CTX_new() call.
 
-OSSL_HTTP_REQ_CTX_nbio() attempts the exchange of request and response via HTTP,
-using the I<rbio> and I<wbio> that were given in the OSSL_HTTP_REQ_CTX_new()
-call.  When successful, the contents of the internal memory B<BIO> is replaced
-with the contents of the HTTP response, without the response headers.
+OSSL_HTTP_REQ_CTX_nbio() attempts to send the request prepared I<rctx>
+and gathering the response via HTTP, using the I<rbio> and I<wbio>
+that were given when calling OSSL_HTTP_REQ_CTX_new().
+When successful, the contents of the internal memory B<BIO> contains
+the contents of the HTTP response, without the response headers.
 It may need to be called again if its result is -1, which indicates
 L<BIO_should_retry(3)>.  In such a case it is advisable to sleep a little in
-between to prevent a busy loop.
+between using L<BIO_wait(3)> on the read BIO to prevent a busy loop.
 
 OSSL_HTTP_REQ_CTX_sendreq_d2i() calls OSSL_HTTP_REQ_CTX_nbio(), possibly
 several times until a timeout is reached, and DER decodes the received
 response using the ASN.1 template I<it>.
 
-OSSL_HTTP_REQ_CTX_set_max_response_length() sets the maximum response length
-for I<rctx> to I<len>. If the response exceeds this length an error occurs.
-If not set a default value of 100k is used.
-
-OSSL_HTTP_REQ_CTX_get0_mem_bio() returns the internal memory B<BIO>.  This can
-be used to affect the HTTP request text.  I<Use with caution!>
+OSSL_HTTP_REQ_CTX_get0_mem_bio() returns the internal memory B<BIO>.
+Before sending the request, this could used to modify the HTTP request text.
+I<Use with caution!>
+After receiving a response via HTTP, the BIO represents
+the current state of reading the response headers and contents.
+
+OSSL_HTTP_REQ_CTX_set_max_response_length() sets the maximum allowed
+response content length for I<rctx> to I<len>. If not set or I<len> is 0
+then the B<HTTP_DEFAULT_MAX_RESP_LEN> is used, which currently is 100 KiB.
+If the C<Content-Length> header is present and exceeds this value or
+the content is an ASN.1 encoded structure with a length exceeding this value
+or both length indications are present but disagree then an error occurs.
 
 =head1 WARNINGS
 
@@ -167,6 +177,9 @@ OSSL_HTTP_REQ_CTX_get0_mem_bio() returns the internal memory B<BIO>.
 
 =head1 SEE ALSO
 
+L<BIO_should_retry(3)>,
+L<BIO_wait(3)>,
+L<OSSL_HTTP_get(3)>,
 L<OSSL_HTTP_transfer(3)>
 
 =head1 COPYRIGHT
diff --git a/doc/man3/OSSL_HTTP_transfer.pod b/doc/man3/OSSL_HTTP_transfer.pod
index dda59201cf..cb38d0124f 100644
--- a/doc/man3/OSSL_HTTP_transfer.pod
+++ b/doc/man3/OSSL_HTTP_transfer.pod
@@ -123,9 +123,11 @@ while using a proxy for HTTPS connections requires a suitable callback function
 such as OSSL_HTTP_proxy_connect(), described below.
 
 The I<maxline> parameter specifies the response header maximum line length,
-where 0 indicates the default value, which currently is 4k.
+where a value <= 0 indicates that the B<HTTP_DEFAULT_MAX_LINE_LENGTH> of 4KiB
+should be used.
+This length is also used as the number of content bytes that are read at a time.
 The I<max_resp_len> parameter specifies the maximum response length,
-where 0 indicates the default value, which currently is 100k.
+where 0 indicates B<HTTP_DEFAULT_MAX_RESP_LEN>, which currently is 100 KiB.
 
 An ASN.1-encoded response is expected by OSSL_HTTP_get_asn1() and
 OSSL_HTTP_post_asn1(), while for OSSL_HTTP_get() or OSSL_HTTP_transfer()
@@ -217,9 +219,10 @@ other HTTP client implementations such as wget, curl, and git.
 
 =head1 RETURN VALUES
 
-OSSL_HTTP_get(), OSSL_HTTP_get_asn1(), OSSL_HTTP_post_asn1(), and
-OSSL_HTTP_transfer() return on success the data received via HTTP, else NULL.
-Error conditions include connection/transfer timeout, parse errors, etc.
+On success, OSSL_HTTP_get(), OSSL_HTTP_get_asn1(), OSSL_HTTP_post_asn1(), and
+OSSL_HTTP_transfer() return a memory BIO containing the data received via HTTP.
+This must be freed by the caller. On failure, NULL is returned.
+Failure conditions include connection/transfer timeout, parse errors, etc.
 
 OSSL_HTTP_proxy_connect() and OSSL_HTTP_parse_url()
 return 1 on success, 0 on error.
diff --git a/doc/man3/X509_load_http.pod b/doc/man3/X509_load_http.pod
index 483597b5b8..47a0e74760 100644
--- a/doc/man3/X509_load_http.pod
+++ b/doc/man3/X509_load_http.pod
@@ -15,8 +15,8 @@ X509_CRL_http_nbio
  X509 *X509_load_http(const char *url, BIO *bio, BIO *rbio, int timeout);
  X509_CRL *X509_CRL_load_http(const char *url, BIO *bio, BIO *rbio, int timeout);
 
- #define X509_http_nbio(url)
- #define X509_CRL_http_nbio(url)
+ #define X509_http_nbio(rctx, pcert)
+ #define X509_CRL_http_nbio(rctx, pcrl)
 
 =head1 DESCRIPTION
 
diff --git a/include/openssl/http.h b/include/openssl/http.h
index b35302289f..6c3ddd8ce8 100644
--- a/include/openssl/http.h
+++ b/include/openssl/http.h
@@ -35,6 +35,9 @@ typedef BIO *(*OSSL_HTTP_bio_cb_t)(BIO *bio, void *arg, int connect, int detail)
 # define OPENSSL_HTTP_PROXY "HTTP_PROXY"
 # define OPENSSL_HTTPS_PROXY "HTTPS_PROXY"
 
+#define HTTP_DEFAULT_MAX_LINE_LENGTH (4 * 1024)
+#define HTTP_DEFAULT_MAX_RESP_LEN (100 * 1024)
+
 OSSL_HTTP_REQ_CTX *OSSL_HTTP_REQ_CTX_new(BIO *wbio, BIO *rbio,
                                          int method_GET, int maxline,
                                          unsigned long max_resp_len,
@@ -52,7 +55,7 @@ int OSSL_HTTP_REQ_CTX_i2d(OSSL_HTTP_REQ_CTX *rctx, const char *content_type,
 int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx);
 ASN1_VALUE *OSSL_HTTP_REQ_CTX_sendreq_d2i(OSSL_HTTP_REQ_CTX *rctx,
                                           const ASN1_ITEM *it);
-BIO *OSSL_HTTP_REQ_CTX_get0_mem_bio(OSSL_HTTP_REQ_CTX *rctx);
+BIO *OSSL_HTTP_REQ_CTX_get0_mem_bio(const OSSL_HTTP_REQ_CTX *rctx);
 void OSSL_HTTP_REQ_CTX_set_max_response_length(OSSL_HTTP_REQ_CTX *rctx,
                                                unsigned long len);
 
diff --git a/include/openssl/httperr.h b/include/openssl/httperr.h
index 4bf52bacb9..716feac39b 100644
--- a/include/openssl/httperr.h
+++ b/include/openssl/httperr.h
@@ -34,6 +34,7 @@
 # define HTTP_R_ERROR_PARSING_URL                         101
 # define HTTP_R_ERROR_RECEIVING                           103
 # define HTTP_R_ERROR_SENDING                             102
+# define HTTP_R_FAILED_READING_DATA                       128
 # define HTTP_R_INCONSISTENT_CONTENT_LENGTH               120
 # define HTTP_R_INVALID_PORT_NUMBER                       123
 # define HTTP_R_INVALID_URL_PATH                          125
diff --git a/include/openssl/x509.h.in b/include/openssl/x509.h.in
index bb22abef6b..8a3cb2e4d0 100644
--- a/include/openssl/x509.h.in
+++ b/include/openssl/x509.h.in
@@ -403,9 +403,13 @@ int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type,
                      unsigned char *md, unsigned int *len);
 
 X509 *X509_load_http(const char *url, BIO *bio, BIO *rbio, int timeout);
-# define X509_http_nbio(url) X509_load_http(url, NULL, NULL, 0)
+# define X509_http_nbio(rctx, pcert) \
+    OSSL_HTTP_REQ_CTX_sendreq_d2i(rctx, (ASN1_VALUE **)(pcert), \
+                                  ASN1_ITEM_rptr(X509))
 X509_CRL *X509_CRL_load_http(const char *url, BIO *bio, BIO *rbio, int timeout);
-# define X509_CRL_http_nbio(url) X509_CRL_load_http(url, NULL,  NULL, 0)
+# define X509_CRL_http_nbio(rctx, pcrl) \
+    OSSL_HTTP_REQ_CTX_sendreq_d2i(rctx, (ASN1_VALUE **)(pcrl), \
+                                  ASN1_ITEM_rptr(X509_CRL))
 
 # ifndef OPENSSL_NO_STDIO
 X509 *d2i_X509_fp(FILE *fp, X509 **x509);


More information about the openssl-commits mailing list