*Hugo Landau*
+ * New limit on HTTP response headers is introduced to HTTP client. The
+ default limit is set to 256 header lines. If limit is exceeded the
+ response processing stops with error HTTP_R_RESPONSE_TOO_MANY_HDRLINES.
+ Application may call OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines(3)
+ to change the default. Setting the value to 0 disables the limit.
+
+ *Alexandr Nedvedicky*
+
OpenSSL 3.2
-----------
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_RESPONSE_TOO_MANY_HDRLINES:130:response too many hdrlines
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
time_t max_time; /* Maximum end time of current transfer, or 0 */
time_t max_total_time; /* Maximum end time of total transfer, or 0 */
char *redirection_url; /* Location obtained from HTTP status 301/302 */
+ size_t max_hdr_lines; /* Max. number of http hdr lines, or 0 */
};
/* HTTP states */
rctx->buf = OPENSSL_malloc(rctx->buf_size);
rctx->wbio = wbio;
rctx->rbio = rbio;
+ rctx->max_hdr_lines = OSSL_HTTP_DEFAULT_MAX_RESP_HDR_LINES;
if (rctx->buf == NULL) {
OPENSSL_free(rctx);
return NULL;
return res;
}
+void OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines(OSSL_HTTP_REQ_CTX *rctx,
+ size_t count)
+{
+ if (rctx == NULL) {
+ ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+ return;
+ }
+ rctx->max_hdr_lines = count;
+}
+
static int add1_headers(OSSL_HTTP_REQ_CTX *rctx,
const STACK_OF(CONF_VALUE) *headers, const char *host)
{
size_t resp_len;
const unsigned char *p;
char *buf, *key, *value, *line_end = NULL;
+ size_t resp_hdr_lines = 0;
if (rctx == NULL) {
ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
+ resp_hdr_lines++;
+ if (rctx->max_hdr_lines != 0 && rctx->max_hdr_lines < resp_hdr_lines) {
+ ERR_raise(ERR_LIB_HTTP, HTTP_R_RESPONSE_TOO_MANY_HDRLINES);
+ OSSL_TRACE(HTTP, "Received too many headers\n");
+ rctx->state = OHS_ERROR;
+ return 0;
+ }
+
/* Don't allow excessive lines */
if (n == rctx->buf_size) {
ERR_raise(ERR_LIB_HTTP, HTTP_R_RESPONSE_LINE_TOO_LONG);
if (OSSL_TRACE_ENABLED(HTTP))
OSSL_TRACE(HTTP, "]\n");
+ resp_hdr_lines = 0;
+
if (rctx->keep_alive != 0 /* do not let server initiate keep_alive */
&& !found_keep_alive /* otherwise there is no change */) {
if (rctx->keep_alive == 2) {
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
#include <openssl/httperr.h>
#include "crypto/httperr.h"
-#ifndef OPENSSL_NO_ERR
+#ifndef OPENSSL_NO_HTTP
+
+# ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA HTTP_str_reasons[] = {
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ASN1_LEN_EXCEEDS_MAX_RESP_LEN),
"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_RESPONSE_TOO_MANY_HDRLINES),
+ "response too many hdrlines"},
{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"},
{0, NULL}
};
-#endif
+# endif
int ossl_err_load_HTTP_strings(void)
{
-#ifndef OPENSSL_NO_ERR
+# ifndef OPENSSL_NO_ERR
if (ERR_reason_error_string(HTTP_str_reasons[0].error) == NULL)
ERR_load_strings_const(HTTP_str_reasons);
-#endif
+# endif
return 1;
}
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif
OSSL_HTTP_REQ_CTX_get0_mem_bio,
OSSL_HTTP_REQ_CTX_get_resp_len,
OSSL_HTTP_REQ_CTX_set_max_response_length,
-OSSL_HTTP_is_alive
+OSSL_HTTP_is_alive,
+OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines
- HTTP client low-level functions
=head1 SYNOPSIS
int OSSL_HTTP_is_alive(const OSSL_HTTP_REQ_CTX *rctx);
+ void OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines(OSSL_HTTP_REQ_CTX *rctx,
+ size_t count);
+
=head1 DESCRIPTION
B<OSSL_HTTP_REQ_CTX> is a context structure for an HTTP request and response,
for any reason at the server side, it will notice this obtaining an
I/O error when trying to send the next request via I<rctx>.
+The OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines() function changes the limit
+for the number of HTTP headers which can be received in a response. The default
+value is 256. If the number of HTTP headers in a response exceeds the limit,
+then the HTTP_R_RESPONSE_TOO_MANY_HDRLINES error is indicated.
+
=head1 WARNINGS
The server's response may be unexpected if the hostname that was used to
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
extern "C" {
# endif
+# ifndef OPENSSL_NO_HTTP
+
int ossl_err_load_HTTP_strings(void);
+# endif
# ifdef __cplusplus
}
#define OSSL_HTTP_DEFAULT_MAX_LINE_LEN (4 * 1024)
#define OSSL_HTTP_DEFAULT_MAX_RESP_LEN (100 * 1024)
+#define OSSL_HTTP_DEFAULT_MAX_RESP_HDR_LINES 256
+
/* Low-level HTTP API */
OSSL_HTTP_REQ_CTX *OSSL_HTTP_REQ_CTX_new(BIO *wbio, BIO *rbio, int buf_size);
const char *OSSL_HTTP_adapt_proxy(const char *proxy, const char *no_proxy,
const char *server, int use_ssl);
+void OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines(OSSL_HTTP_REQ_CTX *rctx,
+ size_t count);
# endif /* !defined(OPENSSL_NO_HTTP) */
# ifdef __cplusplus
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
# 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_RESPONSE_TOO_MANY_HDRLINES 130
# define HTTP_R_RETRY_TIMEOUT 129
# define HTTP_R_SERVER_CANCELED_CONNECTION 127
# define HTTP_R_SOCK_NOT_SUPPORTED 122
return test_http_keep_alive('1', 2, 0);
}
+static int test_http_resp_hdr_limit(size_t limit)
+{
+ BIO *wbio = BIO_new(BIO_s_mem());
+ BIO *rbio = BIO_new(BIO_s_mem());
+ BIO *mem = NULL;
+ server_args mock_args = { NULL, NULL, NULL, '0', 0 };
+ int res = 0;
+ OSSL_HTTP_REQ_CTX *rctx = NULL;
+
+ if (TEST_ptr(wbio) == 0 || TEST_ptr(rbio) == 0)
+ goto err;
+
+ mock_args.txt = text1;
+ mock_args.content_type = "text/plain";
+ mock_args.version = '1';
+ mock_args.out = rbio;
+ mock_args.content_type = "text/plain";
+
+ BIO_set_callback_ex(wbio, http_bio_cb_ex);
+ BIO_set_callback_arg(wbio, (char *)&mock_args);
+
+ rctx = OSSL_HTTP_REQ_CTX_new(wbio, rbio, 8192);
+ if (TEST_ptr(rctx) == 0)
+ goto err;
+
+ if (!TEST_true(OSSL_HTTP_REQ_CTX_set_request_line(rctx, 0 /* GET */,
+ NULL, NULL, RPATH)))
+ goto err;
+
+ OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines(rctx, limit);
+ mem = OSSL_HTTP_REQ_CTX_exchange(rctx);
+
+ if (limit == 1)
+ res = TEST_ptr_null(mem);
+ else
+ res = TEST_ptr(mem);
+
+ err:
+ BIO_free(wbio);
+ BIO_free(rbio);
+ OSSL_HTTP_REQ_CTX_free(rctx);
+
+ return res;
+}
+
+static int test_hdr_resp_hdr_limit_none(void)
+{
+ return test_http_resp_hdr_limit(0);
+}
+
+static int test_hdr_resp_hdr_limit_short(void)
+{
+ return (test_http_resp_hdr_limit(1));
+}
+
+static int test_hdr_resp_hdr_limit_256(void)
+{
+ return test_http_resp_hdr_limit(256);
+}
+
void cleanup_tests(void)
{
X509_free(x509);
ADD_TEST(test_http_keep_alive_1_require_yes);
ADD_TEST(test_http_keep_alive_0_require_no);
ADD_TEST(test_http_keep_alive_1_require_no);
+ ADD_TEST(test_hdr_resp_hdr_limit_none);
+ ADD_TEST(test_hdr_resp_hdr_limit_short);
+ ADD_TEST(test_hdr_resp_hdr_limit_256);
return 1;
}
X509_STORE_get1_objects ? 3_3_0 EXIST::FUNCTION:
OPENSSL_LH_set_thunks ? 3_3_0 EXIST::FUNCTION:
OPENSSL_LH_doall_arg_thunk ? 3_3_0 EXIST::FUNCTION:
+OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines ? 3_3_0 EXIST::FUNCTION:HTTP