diff options
author | thegeorg <thegeorg@yandex-team.com> | 2022-09-15 12:50:39 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2022-09-15 12:50:39 +0300 |
commit | 239edf05410a4716215db2bf9a0027c05b5d8126 (patch) | |
tree | 9275e8632007661f1897e73bb8ace977d4e1586a | |
parent | 883652acb26e399a42efb42c90d38480af15cee2 (diff) | |
download | ydb-239edf05410a4716215db2bf9a0027c05b5d8126.tar.gz |
curl + nghttp2: Backport PRs to make ltws validation less picky
This is backport of:
* curl [PR #9448](https://github.com/curl/curl/pull/9448)
* nghttp2 [PR #1792](https://github.com/nghttp2/nghttp2/pull/1792)
-rw-r--r-- | contrib/libs/curl/lib/http2.c | 23 | ||||
-rw-r--r-- | contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2.h | 12 | ||||
-rw-r--r-- | contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2ver.h | 4 | ||||
-rw-r--r-- | contrib/libs/nghttp2/lib/nghttp2_http.c | 32 | ||||
-rw-r--r-- | contrib/libs/nghttp2/lib/nghttp2_option.c | 7 | ||||
-rw-r--r-- | contrib/libs/nghttp2/lib/nghttp2_option.h | 5 | ||||
-rw-r--r-- | contrib/libs/nghttp2/lib/nghttp2_session.c | 12 | ||||
-rw-r--r-- | contrib/libs/nghttp2/lib/nghttp2_session.h | 3 | ||||
-rw-r--r-- | contrib/libs/nghttp2/lib/nghttp2_stream.h | 3 |
9 files changed, 96 insertions, 5 deletions
diff --git a/contrib/libs/curl/lib/http2.c b/contrib/libs/curl/lib/http2.c index f6364d0e02..3a70528e4a 100644 --- a/contrib/libs/curl/lib/http2.c +++ b/contrib/libs/curl/lib/http2.c @@ -1277,6 +1277,27 @@ void Curl_http2_done(struct Curl_easy *data, bool premature) } } +static int client_new(struct connectdata *conn, + nghttp2_session_callbacks *callbacks) +{ +#if NGHTTP2_VERSION_NUM < 0x013200 + /* before 1.50.0 */ + return nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn); +#else + nghttp2_option *o; + int rc = nghttp2_option_new(&o); + if(rc) + return rc; + /* turn off RFC 9113 leading and trailing white spaces validation against + HTTP field value. */ + nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(o, 1); + rc = nghttp2_session_client_new2(&conn->proto.httpc.h2, callbacks, conn, + o); + nghttp2_option_del(o); + return rc; +#endif +} + /* * Initialize nghttp2 for a Curl connection */ @@ -1317,7 +1338,7 @@ static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn) nghttp2_session_callbacks_set_error_callback(callbacks, error_callback); /* The nghttp2 session is not yet setup, do it */ - rc = nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn); + rc = client_new(conn, callbacks); nghttp2_session_callbacks_del(callbacks); diff --git a/contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2.h b/contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2.h index bb8aa1d329..61a14d99eb 100644 --- a/contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2.h +++ b/contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2.h @@ -2753,6 +2753,18 @@ nghttp2_option_set_server_fallback_rfc7540_priorities(nghttp2_option *option, /** * @function * + * This option, if set to nonzero, turns off RFC 9113 leading and + * trailing white spaces validation against HTTP field value. Some + * important fields, such as HTTP/2 pseudo header fields, are + * validated more strictly and this option does not apply to them. + */ +NGHTTP2_EXTERN void +nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation( + nghttp2_option *option, int val); + +/** + * @function + * * Initializes |*session_ptr| for client use. The all members of * |callbacks| are copied to |*session_ptr|. Therefore |*session_ptr| * does not store |callbacks|. The |user_data| is an arbitrary user diff --git a/contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2ver.h b/contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2ver.h index d0a4626ca9..0e503610ba 100644 --- a/contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2ver.h +++ b/contrib/libs/nghttp2/lib/includes/nghttp2/nghttp2ver.h @@ -29,7 +29,7 @@ * @macro * Version number of the nghttp2 library release */ -#define NGHTTP2_VERSION "1.49.0" +#define NGHTTP2_VERSION "1.50.0" /** * @macro @@ -37,6 +37,6 @@ * release. This is a 24 bit number with 8 bits for major number, 8 bits * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203. */ -#define NGHTTP2_VERSION_NUM 0x013100 +#define NGHTTP2_VERSION_NUM 0x013200 #endif /* NGHTTP2VER_H */ diff --git a/contrib/libs/nghttp2/lib/nghttp2_http.c b/contrib/libs/nghttp2/lib/nghttp2_http.c index 71491f0eb5..83e5e6685f 100644 --- a/contrib/libs/nghttp2/lib/nghttp2_http.c +++ b/contrib/libs/nghttp2/lib/nghttp2_http.c @@ -336,6 +336,16 @@ static int check_scheme(const uint8_t *value, size_t len) { return 1; } +static int lws(const uint8_t *s, size_t n) { + size_t i; + for (i = 0; i < n; ++i) { + if (s[i] != ' ' && s[i] != '\t') { + return 0; + } + } + return 1; +} + int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream, nghttp2_frame *frame, nghttp2_hd_nv *nv, int trailer) { @@ -378,6 +388,10 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream, case NGHTTP2_TOKEN_HOST: if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) { rv = nghttp2_check_authority(nv->value->base, nv->value->len); + } else if ( + stream->flags & + NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) { + rv = nghttp2_check_header_value(nv->value->base, nv->value->len); } else { rv = nghttp2_check_header_value_rfc9113(nv->value->base, nv->value->len); } @@ -385,8 +399,24 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream, case NGHTTP2_TOKEN__SCHEME: rv = check_scheme(nv->value->base, nv->value->len); break; + case NGHTTP2_TOKEN__PROTOCOL: + /* Check the value consists of just white spaces, which was done + in check_pseudo_header before + nghttp2_check_header_value_rfc9113 has been introduced. */ + if ((stream->flags & + NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) && + lws(nv->value->base, nv->value->len)) { + rv = 0; + break; + } + /* fall through */ default: - rv = nghttp2_check_header_value_rfc9113(nv->value->base, nv->value->len); + if (stream->flags & + NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) { + rv = nghttp2_check_header_value(nv->value->base, nv->value->len); + } else { + rv = nghttp2_check_header_value_rfc9113(nv->value->base, nv->value->len); + } } if (rv == 0) { diff --git a/contrib/libs/nghttp2/lib/nghttp2_option.c b/contrib/libs/nghttp2/lib/nghttp2_option.c index ffd20322ee..ee0cd0f022 100644 --- a/contrib/libs/nghttp2/lib/nghttp2_option.c +++ b/contrib/libs/nghttp2/lib/nghttp2_option.c @@ -136,3 +136,10 @@ void nghttp2_option_set_server_fallback_rfc7540_priorities( option->opt_set_mask |= NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES; option->server_fallback_rfc7540_priorities = val; } + +void nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation( + nghttp2_option *option, int val) { + option->opt_set_mask |= + NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION; + option->no_rfc9113_leading_and_trailing_ws_validation = val; +} diff --git a/contrib/libs/nghttp2/lib/nghttp2_option.h b/contrib/libs/nghttp2/lib/nghttp2_option.h index 0400d56dfc..b228a0754c 100644 --- a/contrib/libs/nghttp2/lib/nghttp2_option.h +++ b/contrib/libs/nghttp2/lib/nghttp2_option.h @@ -69,6 +69,7 @@ typedef enum { NGHTTP2_OPT_MAX_OUTBOUND_ACK = 1 << 11, NGHTTP2_OPT_MAX_SETTINGS = 1 << 12, NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 13, + NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 14, } nghttp2_option_flag; /** @@ -133,6 +134,10 @@ struct nghttp2_option { */ int server_fallback_rfc7540_priorities; /** + * NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION + */ + int no_rfc9113_leading_and_trailing_ws_validation; + /** * NGHTTP2_OPT_USER_RECV_EXT_TYPES */ uint8_t user_recv_ext_types[32]; diff --git a/contrib/libs/nghttp2/lib/nghttp2_session.c b/contrib/libs/nghttp2/lib/nghttp2_session.c index 134b0efb12..93f3f07cf7 100644 --- a/contrib/libs/nghttp2/lib/nghttp2_session.c +++ b/contrib/libs/nghttp2/lib/nghttp2_session.c @@ -566,6 +566,13 @@ static int session_new(nghttp2_session **session_ptr, (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_SERVER_FALLBACK_RFC7540_PRIORITIES; } + + if ((option->opt_set_mask & + NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) && + option->no_rfc9113_leading_and_trailing_ws_validation) { + (*session_ptr)->opt_flags |= + NGHTTP2_OPTMASK_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION; + } } rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater, @@ -1296,6 +1303,11 @@ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session, mem = &session->mem; stream = nghttp2_session_get_stream_raw(session, stream_id); + if (session->opt_flags & + NGHTTP2_OPTMASK_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) { + flags |= NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION; + } + if (stream) { assert(stream->state == NGHTTP2_STREAM_IDLE); assert((stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) || diff --git a/contrib/libs/nghttp2/lib/nghttp2_session.h b/contrib/libs/nghttp2/lib/nghttp2_session.h index 164b5fd957..34d2d58528 100644 --- a/contrib/libs/nghttp2/lib/nghttp2_session.h +++ b/contrib/libs/nghttp2/lib/nghttp2_session.h @@ -53,7 +53,8 @@ typedef enum { NGHTTP2_OPTMASK_NO_HTTP_MESSAGING = 1 << 2, NGHTTP2_OPTMASK_NO_AUTO_PING_ACK = 1 << 3, NGHTTP2_OPTMASK_NO_CLOSED_STREAMS = 1 << 4, - NGHTTP2_OPTMASK_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 5 + NGHTTP2_OPTMASK_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 5, + NGHTTP2_OPTMASK_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 6, } nghttp2_optmask; /* diff --git a/contrib/libs/nghttp2/lib/nghttp2_stream.h b/contrib/libs/nghttp2/lib/nghttp2_stream.h index 0ec77bf071..7a8e4c6c1d 100644 --- a/contrib/libs/nghttp2/lib/nghttp2_stream.h +++ b/contrib/libs/nghttp2/lib/nghttp2_stream.h @@ -96,6 +96,9 @@ typedef enum { NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES = 0x10, /* Ignore client RFC 9218 priority signal. */ NGHTTP2_STREAM_FLAG_IGNORE_CLIENT_PRIORITIES = 0x20, + /* Indicates that RFC 9113 leading and trailing white spaces + validation against a field value is not performed. */ + NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 0x40, } nghttp2_stream_flag; /* HTTP related flags to enforce HTTP semantics */ |