From: Dr. David von Oheimb Date: Mon, 23 May 2022 17:43:56 +0000 (+0200) Subject: http_client.c: Dump response on error when tracing is enabled X-Git-Tag: openssl-3.2.0-alpha1~2598 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e8fdb0603572bf051dad6abc56291cdf1313a905;p=thirdparty%2Fopenssl.git http_client.c: Dump response on error when tracing is enabled Reviewed-by: Tomas Mraz Reviewed-by: Dmitry Belyavskiy Reviewed-by: David von Oheimb (Merged from https://github.com/openssl/openssl/pull/18386) --- diff --git a/crypto/http/http_client.c b/crypto/http/http_client.c index c2b8f09ac14..790b03fa939 100644 --- a/crypto/http/http_client.c +++ b/crypto/http/http_client.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "internal/sockets.h" #include "internal/common.h" /* for ossl_assert() */ @@ -485,6 +486,7 @@ static int may_still_retry(time_t max_time, int *ptimeout) int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) { int i, found_expected_ct = 0, found_keep_alive = 0; + int found_text_ct = 0; long n; size_t resp_len; const unsigned char *p; @@ -540,6 +542,8 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) case OHS_WRITE_INIT: rctx->len_to_send = BIO_get_mem_data(rctx->mem, &rctx->pos); rctx->state = OHS_WRITE_HDR; + if (OSSL_TRACE_ENABLED(HTTP)) + OSSL_TRACE(HTTP, "Sending request header:\n"); /* fall thru */ case OHS_WRITE_HDR: @@ -548,6 +552,10 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) /* Copy some chunk of data from rctx->req to rctx->wbio */ if (rctx->len_to_send > 0) { + if (OSSL_TRACE_ENABLED(HTTP) + && rctx->state == OHS_WRITE_HDR && rctx->len_to_send <= INT_MAX) + OSSL_TRACE2(HTTP, "%.*s", (int)rctx->len_to_send, rctx->pos); + i = BIO_write(rctx->wbio, rctx->pos, rctx->len_to_send); if (i <= 0) { if (BIO_should_retry(rctx->wbio)) @@ -631,6 +639,13 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) return 0; } + /* dump all response header lines */ + if (OSSL_TRACE_ENABLED(HTTP)) { + if (rctx->state == OHS_FIRSTLINE) + OSSL_TRACE(HTTP, "Received response header:\n"); + OSSL_TRACE1(HTTP, "%s", buf); + } + /* First line */ if (rctx->state == OHS_FIRSTLINE) { switch (parse_http_line1(buf, &found_keep_alive)) { @@ -669,15 +684,20 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) rctx->redirection_url = value; return 0; } - if (rctx->state == OHS_HEADERS && rctx->expected_ct != NULL - && OPENSSL_strcasecmp(key, "Content-Type") == 0) { - if (OPENSSL_strcasecmp(rctx->expected_ct, value) != 0) { - ERR_raise_data(ERR_LIB_HTTP, HTTP_R_UNEXPECTED_CONTENT_TYPE, - "expected=%s, actual=%s", - rctx->expected_ct, value); - return 0; + if (OPENSSL_strcasecmp(key, "Content-Type") == 0) { + if (rctx->state == OHS_HEADERS + && rctx->expected_ct != NULL) { + if (OPENSSL_strcasecmp(rctx->expected_ct, value) != 0) { + ERR_raise_data(ERR_LIB_HTTP, + HTTP_R_UNEXPECTED_CONTENT_TYPE, + "expected=%s, actual=%s", + rctx->expected_ct, value); + return 0; + } + found_expected_ct = 1; } - found_expected_ct = 1; + if (OPENSSL_strncasecmp(value, "text/", 5) == 0) + found_text_ct = 1; } /* https://tools.ietf.org/html/rfc7230#section-6.3 Persistence */ @@ -717,8 +737,12 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) rctx->keep_alive = 0; } - if (rctx->state == OHS_ERROR) + if (rctx->state == OHS_ERROR) { + if (OSSL_TRACE_ENABLED(HTTP) + && found_text_ct && BIO_get_mem_data(rctx->mem, &p) > 0) + OSSL_TRACE1(HTTP, "%s", p); return 0; + } if (rctx->expected_ct != NULL && !found_expected_ct) { ERR_raise_data(ERR_LIB_HTTP, HTTP_R_MISSING_CONTENT_TYPE, diff --git a/crypto/trace.c b/crypto/trace.c index d790409a2d6..09a08a6512d 100644 --- a/crypto/trace.c +++ b/crypto/trace.c @@ -138,8 +138,9 @@ static const struct trace_category_st trace_categories[] = { TRACE_CATEGORY_(STORE), TRACE_CATEGORY_(DECODER), TRACE_CATEGORY_(ENCODER), - TRACE_CATEGORY_(REF_COUNT) -}; + TRACE_CATEGORY_(REF_COUNT), + TRACE_CATEGORY_(HTTP), +}; /* KEEP THIS LIST IN SYNC with #define OSSL_TRACE_CATEGORY_... in trace.h */ const char *OSSL_trace_get_category_name(int num) { diff --git a/doc/man1/openssl-cmp.pod.in b/doc/man1/openssl-cmp.pod.in index 6bbea0b0891..17223beea00 100644 --- a/doc/man1/openssl-cmp.pod.in +++ b/doc/man1/openssl-cmp.pod.in @@ -1060,6 +1060,10 @@ although they usually contain hints that would be helpful for diagnostics. For assisting in such cases the CMP client offers a workaround via the B<-unprotected_errors> option, which allows accepting such negative messages. +If OpenSSL was built with trace support enabled +and the environment variable B includes B, +the request and response headers of HTTP transfers are printed. + =head1 EXAMPLES =head2 Simple examples using the default OpenSSL configuration file diff --git a/doc/man1/openssl.pod b/doc/man1/openssl.pod index c3a93fdce4b..b3de6934e5e 100644 --- a/doc/man1/openssl.pod +++ b/doc/man1/openssl.pod @@ -710,8 +710,8 @@ see L. Enable tracing output of OpenSSL library, by name. This output will only make sense if you know OpenSSL internals well. -Also, it might not give you any output at all, depending on how -OpenSSL was built. +Also, it might not give you any output at all +if OpenSSL was built without tracing support. The value is a comma separated list of names, with the following available: @@ -766,6 +766,10 @@ policy evaluation. BIGNUM context. +=item B + +HTTP client diagnostics + =back =back diff --git a/doc/man3/OSSL_HTTP_REQ_CTX.pod b/doc/man3/OSSL_HTTP_REQ_CTX.pod index ecfa4428270..36b460dbccb 100644 --- a/doc/man3/OSSL_HTTP_REQ_CTX.pod +++ b/doc/man3/OSSL_HTTP_REQ_CTX.pod @@ -213,6 +213,13 @@ This may be omitted if the GET method is used and "keep-alive" is not requested. When the request context is fully prepared, the HTTP exchange may be performed with OSSL_HTTP_REQ_CTX_nbio() or OSSL_HTTP_REQ_CTX_exchange(). +=head1 NOTES + +When built with tracing enabled, OSSL_HTTP_REQ_CTX_nbio() and all functions +using it, such as OSSL_HTTP_REQ_CTX_exchange() and L, +may be traced using B. +See also L and L. + =head1 RETURN VALUES OSSL_HTTP_REQ_CTX_new() returns a pointer to a B, or NULL @@ -248,7 +255,8 @@ L, L, L, L, -L +L, +L =head1 HISTORY diff --git a/doc/man3/OSSL_HTTP_transfer.pod b/doc/man3/OSSL_HTTP_transfer.pod index 7e823db3eab..bb29a5d3e65 100644 --- a/doc/man3/OSSL_HTTP_transfer.pod +++ b/doc/man3/OSSL_HTTP_transfer.pod @@ -245,6 +245,10 @@ C, C, C, C, C, and C, have been chosen for maximal compatibility with other HTTP client implementations such as wget, curl, and git. +When built with tracing enabled, OSSL_HTTP_transfer() and all functions using it +may be traced using B. +See also L and L. + =head1 RETURN VALUES OSSL_HTTP_open() returns on success a B, else NULL. @@ -266,7 +270,8 @@ OSSL_HTTP_close() returns 0 if anything went wrong while disconnecting, else 1. L, L, L, L, -L +L, +L =head1 HISTORY diff --git a/include/openssl/trace.h b/include/openssl/trace.h index 28200133673..059644299e4 100644 --- a/include/openssl/trace.h +++ b/include/openssl/trace.h @@ -57,8 +57,10 @@ extern "C" { # define OSSL_TRACE_CATEGORY_DECODER 15 # define OSSL_TRACE_CATEGORY_ENCODER 16 # define OSSL_TRACE_CATEGORY_REF_COUNT 17 +# define OSSL_TRACE_CATEGORY_HTTP 18 /* Count of available categories. */ -# define OSSL_TRACE_CATEGORY_NUM 18 +# define OSSL_TRACE_CATEGORY_NUM 19 +/* KEEP THIS LIST IN SYNC with trace_categories[] in crypto/trace.c */ /* Returns the trace category number for the given |name| */ int OSSL_trace_get_category_num(const char *name);