-
Notifications
You must be signed in to change notification settings - Fork 5.3k
http/1.1 codec: Rejects requests w/ invalid HTTP header values #7306
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0e55b36
aabe8ea
42f264b
5f50baa
1515e9e
e3d03fe
ab06539
b9015ef
e073771
dad83f1
a989177
73f0d7d
c2cb387
52bb48c
ba0bc86
393a161
88b3d22
0718d58
16bcc99
65c35df
ce5982b
2873206
c0126ea
2b3bb2c
8cd3776
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -174,6 +174,8 @@ class ConnectionImpl : public virtual Connection, protected Logger::Loggable<Log | |
| protected: | ||
| ConnectionImpl(Network::Connection& connection, http_parser_type type, | ||
| uint32_t max_request_headers_kb); | ||
| ConnectionImpl(Network::Connection& connection, http_parser_type type, | ||
| uint32_t max_request_headers_kb, bool strict_header_validation); | ||
|
|
||
| bool resetStreamCalled() { return reset_stream_called_; } | ||
|
|
||
|
|
@@ -282,6 +284,8 @@ class ConnectionImpl : public virtual Connection, protected Logger::Loggable<Log | |
| char* reserved_current_{}; | ||
| Protocol protocol_{Protocol::Http11}; | ||
| const uint32_t max_headers_kb_; | ||
|
|
||
| bool strict_header_validation_; | ||
| }; | ||
|
|
||
| /** | ||
|
|
@@ -292,6 +296,10 @@ class ServerConnectionImpl : public ServerConnection, public ConnectionImpl { | |
| ServerConnectionImpl(Network::Connection& connection, ServerConnectionCallbacks& callbacks, | ||
| Http1Settings settings, uint32_t max_request_headers_kb); | ||
|
|
||
| ServerConnectionImpl(Network::Connection& connection, ServerConnectionCallbacks& callbacks, | ||
|
||
| Http1Settings settings, uint32_t max_request_headers_kb, | ||
| bool strict_header_validation); | ||
|
|
||
| virtual bool supports_http_10() override { return codec_settings_.accept_http_10_; } | ||
|
|
||
| private: | ||
|
|
@@ -342,6 +350,9 @@ class ClientConnectionImpl : public ClientConnection, public ConnectionImpl { | |
| public: | ||
| ClientConnectionImpl(Network::Connection& connection, ConnectionCallbacks& callbacks); | ||
|
|
||
| ClientConnectionImpl(Network::Connection& connection, ConnectionCallbacks& callbacks, | ||
| bool strict_header_validation); | ||
|
|
||
| // Http::ClientConnection | ||
| StreamEncoder& newStream(StreamDecoder& response_decoder) override; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,7 @@ | |
| #include "common/http/header_map_impl.h" | ||
| #include "common/network/address_impl.h" | ||
| #include "common/router/router.h" | ||
| #include "common/runtime/runtime_impl.h" | ||
| #include "common/upstream/host_utility.h" | ||
|
|
||
| // TODO(dio): Remove dependency to extension health checkers when redis_health_check is removed. | ||
|
|
@@ -335,8 +336,10 @@ Http::CodecClient::Type HttpHealthCheckerImpl::codecClientType(bool use_http2) { | |
|
|
||
| Http::CodecClient* | ||
| ProdHttpHealthCheckerImpl::createCodecClient(Upstream::Host::CreateConnectionData& data) { | ||
|
||
| const bool strict_header_validation = | ||
| Runtime::runtimeFeatureEnabled("envoy.reloadable_features.strict_header_validation"); | ||
| return new Http::CodecClientProd(codec_client_type_, std::move(data.connection_), | ||
| data.host_description_, dispatcher_); | ||
| data.host_description_, dispatcher_, strict_header_validation); | ||
| } | ||
|
|
||
| TcpHealthCheckMatcher::MatchSegments TcpHealthCheckMatcher::loadProtoBytes( | ||
|
|
@@ -744,7 +747,7 @@ Http::CodecClientPtr | |
| ProdGrpcHealthCheckerImpl::createCodecClient(Upstream::Host::CreateConnectionData& data) { | ||
| return std::make_unique<Http::CodecClientProd>(Http::CodecClient::Type::HTTP2, | ||
| std::move(data.connection_), | ||
| data.host_description_, dispatcher_); | ||
| data.host_description_, dispatcher_, false); | ||
| } | ||
|
|
||
| std::ostream& operator<<(std::ostream& out, HealthState state) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to not just remove the old constructor and default validate_header_values to false?
Though now that I think about it, I think we'd be better off only having the new constructor and not having a default value. If we force all callers to pick a boolean we won't miss any code sites using the new code path.
It will probably mean tweaking a bunch of unit tests (you can set them all true) but hopefully you can search and replace there
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main reason I hadn't done that was the pervasiveness of the change: it involves a bunch of find/replace that really blew up the diff for the PR. (Due to the fact that it involves changing
ServerConnectionImpl,ClientConnectionImpl,CodecClient/CodecClientProd,ConnectionManagerConfig, and associated mocks, unit tests, and call sites.If you think that much code churn is warranted though, I can certainly do that, and make all the callers default to
false(and default the unit test callers totrue). I know originally we had talked about an overloaded constructor like the one included here, which didn't lead to nearly as much churn.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's actually a fair point about code churn given we'd want to go back to the single argument once we flip this to true and deprecate.
Do you feel confident from grepping around that you have all the call sites under source/...? If not, how about a hacked local version with a RELEASE_ASSERT in the old constructors to make sure we didn't miss any, and we'll call it a day?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I added
RELEASE_ASSERT(false, "");to the{Client,Server}ConnectionImplconstructors and ran Envoy to perform the steps outlined in the PR description (in the "testing" section). Worked great.