• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <cstdint>
6 #include <vector>
7 
8 #include "base/big_endian.h"
9 #include "base/functional/bind.h"
10 #include "base/memory/raw_ptr.h"
11 #include "base/memory/scoped_refptr.h"
12 #include "base/strings/strcat.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_piece.h"
15 #include "base/test/scoped_feature_list.h"
16 #include "net/base/features.h"
17 #include "net/base/network_change_notifier.h"
18 #include "net/base/privacy_mode.h"
19 #include "net/base/proxy_server.h"
20 #include "net/dns/context_host_resolver.h"
21 #include "net/dns/dns_client.h"
22 #include "net/dns/dns_config.h"
23 #include "net/dns/dns_query.h"
24 #include "net/dns/dns_test_util.h"
25 #include "net/dns/dns_transaction.h"
26 #include "net/dns/host_resolver.h"
27 #include "net/dns/host_resolver_manager.h"
28 #include "net/dns/host_resolver_proc.h"
29 #include "net/dns/public/dns_config_overrides.h"
30 #include "net/dns/public/dns_over_https_config.h"
31 #include "net/dns/public/secure_dns_mode.h"
32 #include "net/dns/public/secure_dns_policy.h"
33 #include "net/dns/public/util.h"
34 #include "net/http/http_stream_factory_test_util.h"
35 #include "net/log/net_log.h"
36 #include "net/socket/transport_client_socket_pool.h"
37 #include "net/ssl/ssl_config_service.h"
38 #include "net/ssl/test_ssl_config_service.h"
39 #include "net/test/embedded_test_server/embedded_test_server.h"
40 #include "net/test/embedded_test_server/http_request.h"
41 #include "net/test/embedded_test_server/http_response.h"
42 #include "net/test/gtest_util.h"
43 #include "net/test/ssl_test_util.h"
44 #include "net/test/test_doh_server.h"
45 #include "net/test/test_with_task_environment.h"
46 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
47 #include "net/url_request/url_request.h"
48 #include "net/url_request/url_request_context.h"
49 #include "net/url_request/url_request_context_builder.h"
50 #include "net/url_request/url_request_test_util.h"
51 #include "testing/gtest/include/gtest/gtest.h"
52 #include "testing/platform_test.h"
53 #include "third_party/boringssl/src/include/openssl/ssl.h"
54 #include "url/scheme_host_port.h"
55 #include "url/url_constants.h"
56 
57 namespace net {
58 namespace {
59 
60 using net::test::IsError;
61 using net::test::IsOk;
62 
63 const char kDohHostname[] = "doh-server.example";
64 const char kHostname[] = "bar.example.com";
65 const char kTestBody[] = "<html><body>TEST RESPONSE</body></html>";
66 
67 class TestHostResolverProc : public HostResolverProc {
68  public:
TestHostResolverProc()69   TestHostResolverProc() : HostResolverProc(nullptr) {}
70 
Resolve(const std::string & hostname,AddressFamily address_family,HostResolverFlags host_resolver_flags,AddressList * addrlist,int * os_error)71   int Resolve(const std::string& hostname,
72               AddressFamily address_family,
73               HostResolverFlags host_resolver_flags,
74               AddressList* addrlist,
75               int* os_error) override {
76     insecure_queries_served_++;
77     *addrlist = AddressList::CreateFromIPAddress(IPAddress(127, 0, 0, 1), 0);
78     return OK;
79   }
80 
insecure_queries_served()81   uint32_t insecure_queries_served() { return insecure_queries_served_; }
82 
83  private:
84   ~TestHostResolverProc() override = default;
85   uint32_t insecure_queries_served_ = 0;
86 };
87 
88 // Runs and waits for the DoH probe to complete in automatic mode. The resolver
89 // must have a single DoH server, and the DoH server must serve addresses for
90 // `kDohProbeHostname`.
91 class DohProber : public NetworkChangeNotifier::DNSObserver {
92  public:
DohProber(ContextHostResolver * resolver)93   explicit DohProber(ContextHostResolver* resolver) : resolver_(resolver) {}
94 
ProbeAndWaitForCompletion()95   void ProbeAndWaitForCompletion() {
96     std::unique_ptr<HostResolver::ProbeRequest> probe_request =
97         resolver_->CreateDohProbeRequest();
98     EXPECT_THAT(probe_request->Start(), IsError(ERR_IO_PENDING));
99     if (NumAvailableDohServers() == 0) {
100       NetworkChangeNotifier::AddDNSObserver(this);
101       loop_.Run();
102       NetworkChangeNotifier::RemoveDNSObserver(this);
103     }
104     EXPECT_GT(NumAvailableDohServers(), 0u);
105   }
106 
OnDNSChanged()107   void OnDNSChanged() override {
108     if (NumAvailableDohServers() > 0) {
109       loop_.Quit();
110     }
111   }
112 
113  private:
NumAvailableDohServers()114   size_t NumAvailableDohServers() {
115     ResolveContext* context = resolver_->resolve_context_for_testing();
116     return context->NumAvailableDohServers(
117         context->current_session_for_testing());
118   }
119 
120   raw_ptr<ContextHostResolver> resolver_;
121   base::RunLoop loop_;
122 };
123 
124 // A test fixture that creates a DoH server with a `URLRequestContext`
125 // configured to use it.
126 class DnsOverHttpsIntegrationTest : public TestWithTaskEnvironment {
127  public:
DnsOverHttpsIntegrationTest()128   DnsOverHttpsIntegrationTest()
129       : host_resolver_proc_(base::MakeRefCounted<TestHostResolverProc>()) {
130     doh_server_.SetHostname(kDohHostname);
131     EXPECT_TRUE(doh_server_.Start());
132 
133     // In `kAutomatic` mode, DoH support depends on a probe for
134     // `kDohProbeHostname`.
135     doh_server_.AddAddressRecord(kDohProbeHostname, IPAddress::IPv4Localhost());
136 
137     ResetContext();
138   }
139 
context()140   URLRequestContext* context() { return request_context_.get(); }
141 
ResetContext(SecureDnsMode mode=SecureDnsMode::kSecure)142   void ResetContext(SecureDnsMode mode = SecureDnsMode::kSecure) {
143     // TODO(crbug.com/1252155): Simplify this.
144     HostResolver::ManagerOptions manager_options;
145     // Without a DnsConfig, HostResolverManager will not use DoH, even in
146     // kSecure mode. See https://crbug.com/1251715. However,
147     // DnsClient::BuildEffectiveConfig special-cases overrides that override
148     // everything, so that gets around it. Ideally, we would instead mock out a
149     // system DnsConfig via the usual pathway.
150     manager_options.dns_config_overrides =
151         DnsConfigOverrides::CreateOverridingEverythingWithDefaults();
152     manager_options.dns_config_overrides.secure_dns_mode = mode;
153     manager_options.dns_config_overrides.dns_over_https_config =
154         *DnsOverHttpsConfig::FromString(doh_server_.GetPostOnlyTemplate());
155     manager_options.dns_config_overrides.use_local_ipv6 = true;
156     auto resolver = HostResolver::CreateStandaloneContextResolver(
157         /*net_log=*/nullptr, manager_options);
158 
159     // Configure `resolver_` to use `host_resolver_proc_` to resolve
160     // `doh_server_` itself. Additionally, without an explicit HostResolverProc,
161     // HostResolverManager::HaveTestProcOverride disables the built-in DNS
162     // client.
163     auto* resolver_raw = resolver.get();
164     resolver->SetHostResolverSystemParamsForTest(
165         HostResolverSystemTask::Params(host_resolver_proc_, 1));
166 
167     auto context_builder = CreateTestURLRequestContextBuilder();
168     context_builder->set_host_resolver(std::move(resolver));
169     auto ssl_config_service =
170         std::make_unique<TestSSLConfigService>(SSLContextConfig());
171     ssl_config_service_ = ssl_config_service.get();
172     context_builder->set_ssl_config_service(std::move(ssl_config_service));
173     request_context_ = context_builder->Build();
174 
175     if (mode == SecureDnsMode::kAutomatic) {
176       DohProber prober(resolver_raw);
177       prober.ProbeAndWaitForCompletion();
178     }
179   }
180 
AddHostWithEch(const url::SchemeHostPort & host,const IPAddress & address,base::span<const uint8_t> ech_config_list)181   void AddHostWithEch(const url::SchemeHostPort& host,
182                       const IPAddress& address,
183                       base::span<const uint8_t> ech_config_list) {
184     doh_server_.AddAddressRecord(host.host(), address);
185     doh_server_.AddRecord(BuildTestHttpsServiceRecord(
186         dns_util::GetNameForHttpsQuery(host),
187         /*priority=*/1, /*service_name=*/host.host(),
188         {BuildTestHttpsServiceEchConfigParam(ech_config_list)}));
189   }
190 
191  protected:
192   TestDohServer doh_server_;
193   scoped_refptr<net::TestHostResolverProc> host_resolver_proc_;
194   std::unique_ptr<URLRequestContext> request_context_;
195   raw_ptr<TestSSLConfigService> ssl_config_service_;
196 };
197 
198 // A convenience wrapper over `DnsOverHttpsIntegrationTest` that also starts an
199 // HTTPS server.
200 class HttpsWithDnsOverHttpsTest : public DnsOverHttpsIntegrationTest {
201  public:
HttpsWithDnsOverHttpsTest()202   HttpsWithDnsOverHttpsTest() {
203     EmbeddedTestServer::ServerCertificateConfig cert_config;
204     cert_config.dns_names = {kHostname};
205     https_server_.SetSSLConfig(cert_config);
206     https_server_.RegisterRequestHandler(
207         base::BindRepeating(&HttpsWithDnsOverHttpsTest::HandleDefaultRequest,
208                             base::Unretained(this)));
209     EXPECT_TRUE(https_server_.Start());
210 
211     doh_server_.AddAddressRecord(kHostname, IPAddress(127, 0, 0, 1));
212   }
213 
HandleDefaultRequest(const test_server::HttpRequest & request)214   std::unique_ptr<test_server::HttpResponse> HandleDefaultRequest(
215       const test_server::HttpRequest& request) {
216     auto http_response = std::make_unique<test_server::BasicHttpResponse>();
217     test_https_requests_served_++;
218     http_response->set_content(kTestBody);
219     http_response->set_content_type("text/html");
220     return std::move(http_response);
221   }
222 
223  protected:
224   EmbeddedTestServer https_server_{EmbeddedTestServer::Type::TYPE_HTTPS};
225   uint32_t test_https_requests_served_ = 0;
226 };
227 
228 class TestHttpDelegate : public HttpStreamRequest::Delegate {
229  public:
TestHttpDelegate(base::RunLoop * loop)230   explicit TestHttpDelegate(base::RunLoop* loop) : loop_(loop) {}
231   ~TestHttpDelegate() override = default;
OnStreamReady(const SSLConfig & used_ssl_config,const ProxyInfo & used_proxy_info,std::unique_ptr<HttpStream> stream)232   void OnStreamReady(const SSLConfig& used_ssl_config,
233                      const ProxyInfo& used_proxy_info,
234                      std::unique_ptr<HttpStream> stream) override {
235     stream->Close(false);
236     loop_->Quit();
237   }
238 
OnWebSocketHandshakeStreamReady(const SSLConfig & used_ssl_config,const ProxyInfo & used_proxy_info,std::unique_ptr<WebSocketHandshakeStreamBase> stream)239   void OnWebSocketHandshakeStreamReady(
240       const SSLConfig& used_ssl_config,
241       const ProxyInfo& used_proxy_info,
242       std::unique_ptr<WebSocketHandshakeStreamBase> stream) override {}
243 
OnBidirectionalStreamImplReady(const SSLConfig & used_ssl_config,const ProxyInfo & used_proxy_info,std::unique_ptr<BidirectionalStreamImpl> stream)244   void OnBidirectionalStreamImplReady(
245       const SSLConfig& used_ssl_config,
246       const ProxyInfo& used_proxy_info,
247       std::unique_ptr<BidirectionalStreamImpl> stream) override {}
248 
OnStreamFailed(int status,const NetErrorDetails & net_error_details,const SSLConfig & used_ssl_config,const ProxyInfo & used_proxy_info,ResolveErrorInfo resolve_eror_info)249   void OnStreamFailed(int status,
250                       const NetErrorDetails& net_error_details,
251                       const SSLConfig& used_ssl_config,
252                       const ProxyInfo& used_proxy_info,
253                       ResolveErrorInfo resolve_eror_info) override {}
254 
OnCertificateError(int status,const SSLConfig & used_ssl_config,const SSLInfo & ssl_info)255   void OnCertificateError(int status,
256                           const SSLConfig& used_ssl_config,
257                           const SSLInfo& ssl_info) override {}
258 
OnNeedsProxyAuth(const HttpResponseInfo & proxy_response,const SSLConfig & used_ssl_config,const ProxyInfo & used_proxy_info,HttpAuthController * auth_controller)259   void OnNeedsProxyAuth(const HttpResponseInfo& proxy_response,
260                         const SSLConfig& used_ssl_config,
261                         const ProxyInfo& used_proxy_info,
262                         HttpAuthController* auth_controller) override {}
263 
OnNeedsClientAuth(const SSLConfig & used_ssl_config,SSLCertRequestInfo * cert_info)264   void OnNeedsClientAuth(const SSLConfig& used_ssl_config,
265                          SSLCertRequestInfo* cert_info) override {}
266 
OnQuicBroken()267   void OnQuicBroken() override {}
268 
269  private:
270   raw_ptr<base::RunLoop> loop_;
271 };
272 
273 // This test sets up a request which will reenter the connection pools by
274 // triggering a DNS over HTTPS request. It also sets up an idle socket
275 // which was a precondition for the crash we saw in  https://crbug.com/830917.
TEST_F(HttpsWithDnsOverHttpsTest,EndToEnd)276 TEST_F(HttpsWithDnsOverHttpsTest, EndToEnd) {
277   // Create and start http server.
278   EmbeddedTestServer http_server(EmbeddedTestServer::Type::TYPE_HTTP);
279   http_server.RegisterRequestHandler(
280       base::BindRepeating(&HttpsWithDnsOverHttpsTest::HandleDefaultRequest,
281                           base::Unretained(this)));
282   EXPECT_TRUE(http_server.Start());
283 
284   // Set up an idle socket.
285   HttpTransactionFactory* transaction_factory =
286       request_context_->http_transaction_factory();
287   HttpStreamFactory::JobFactory default_job_factory;
288   HttpNetworkSession* network_session = transaction_factory->GetSession();
289   base::RunLoop loop;
290   TestHttpDelegate request_delegate(&loop);
291 
292   HttpStreamFactory* factory = network_session->http_stream_factory();
293   HttpRequestInfo request_info;
294   request_info.method = "GET";
295   request_info.url = http_server.GetURL("localhost", "/preconnect");
296 
297   std::unique_ptr<HttpStreamRequest> request(factory->RequestStream(
298       request_info, DEFAULT_PRIORITY, SSLConfig(), &request_delegate, false,
299       false, NetLogWithSource()));
300   loop.Run();
301 
302   ClientSocketPool::GroupId group_id(
303       url::SchemeHostPort(request_info.url), PrivacyMode::PRIVACY_MODE_DISABLED,
304       NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
305   EXPECT_EQ(network_session
306                 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
307                                 ProxyChain::Direct())
308                 ->IdleSocketCountInGroup(group_id),
309             1u);
310 
311   // The domain "localhost" is resolved locally, so no DNS lookups should have
312   // occurred.
313   EXPECT_EQ(doh_server_.QueriesServed(), 0);
314   EXPECT_EQ(host_resolver_proc_->insecure_queries_served(), 0u);
315   // A stream was established, but no HTTPS request has been made yet.
316   EXPECT_EQ(test_https_requests_served_, 0u);
317 
318   // Make a request that will trigger a DoH query as well.
319   TestDelegate d;
320   GURL main_url = https_server_.GetURL(kHostname, "/test");
321   std::unique_ptr<URLRequest> req(context()->CreateRequest(
322       main_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
323   req->Start();
324   base::RunLoop().Run();
325   EXPECT_TRUE(https_server_.ShutdownAndWaitUntilComplete());
326   EXPECT_TRUE(http_server.ShutdownAndWaitUntilComplete());
327   EXPECT_TRUE(doh_server_.ShutdownAndWaitUntilComplete());
328 
329   // There should be three DoH lookups for kHostname (A, AAAA, and HTTPS).
330   EXPECT_EQ(doh_server_.QueriesServed(), 3);
331   // The requests to the DoH server are pooled, so there should only be one
332   // insecure lookup for the DoH server hostname.
333   EXPECT_EQ(host_resolver_proc_->insecure_queries_served(), 1u);
334   // There should be one non-DoH HTTPS request for the connection to kHostname.
335   EXPECT_EQ(test_https_requests_served_, 1u);
336 
337   EXPECT_TRUE(d.response_completed());
338   EXPECT_EQ(d.request_status(), 0);
339   EXPECT_EQ(d.data_received(), kTestBody);
340 }
341 
TEST_F(HttpsWithDnsOverHttpsTest,EndToEndFail)342 TEST_F(HttpsWithDnsOverHttpsTest, EndToEndFail) {
343   // Fail all DoH requests.
344   doh_server_.SetFailRequests(true);
345 
346   // Make a request that will trigger a DoH query.
347   TestDelegate d;
348   GURL main_url = https_server_.GetURL(kHostname, "/test");
349   std::unique_ptr<URLRequest> req(context()->CreateRequest(
350       main_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
351   req->Start();
352   base::RunLoop().Run();
353   EXPECT_TRUE(https_server_.ShutdownAndWaitUntilComplete());
354   EXPECT_TRUE(doh_server_.ShutdownAndWaitUntilComplete());
355 
356   // No HTTPS connection to the test server will be attempted due to the
357   // host resolution error.
358   EXPECT_EQ(test_https_requests_served_, 0u);
359 
360   EXPECT_TRUE(d.response_completed());
361   EXPECT_EQ(d.request_status(), net::ERR_NAME_NOT_RESOLVED);
362 
363   const auto& resolve_error_info = req->response_info().resolve_error_info;
364   EXPECT_TRUE(resolve_error_info.is_secure_network_error);
365   EXPECT_EQ(resolve_error_info.error, net::ERR_DNS_MALFORMED_RESPONSE);
366 }
367 
368 // An end-to-end test of the HTTPS upgrade behavior.
TEST_F(HttpsWithDnsOverHttpsTest,HttpsUpgrade)369 TEST_F(HttpsWithDnsOverHttpsTest, HttpsUpgrade) {
370   base::test::ScopedFeatureList features;
371   features.InitAndEnableFeatureWithParameters(
372       features::kUseDnsHttpsSvcb,
373       {// Disable timeouts.
374        {"UseDnsHttpsSvcbSecureExtraTimeMax", "0"},
375        {"UseDnsHttpsSvcbSecureExtraTimePercent", "0"},
376        {"UseDnsHttpsSvcbSecureExtraTimeMin", "0"}});
377   ResetContext();
378 
379   GURL https_url = https_server_.GetURL(kHostname, "/test");
380   EXPECT_TRUE(https_url.SchemeIs(url::kHttpsScheme));
381   GURL::Replacements replacements;
382   replacements.SetSchemeStr(url::kHttpScheme);
383   GURL http_url = https_url.ReplaceComponents(replacements);
384 
385   // `service_name` is `kHostname` rather than "." because "." specifies the
386   // query name. For non-defaults ports, the query name uses port prefix naming
387   // and does not match the A/AAAA records.
388   doh_server_.AddRecord(BuildTestHttpsServiceRecord(
389       dns_util::GetNameForHttpsQuery(url::SchemeHostPort(https_url)),
390       /*priority=*/1, /*service_name=*/kHostname, /*params=*/{}));
391 
392   for (auto mode : {SecureDnsMode::kSecure, SecureDnsMode::kAutomatic}) {
393     SCOPED_TRACE(kSecureDnsModes.at(mode));
394     ResetContext(mode);
395 
396     // Fetch the http URL.
397     TestDelegate d;
398     std::unique_ptr<URLRequest> req(context()->CreateRequest(
399         http_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
400     req->Start();
401     base::RunLoop().Run();
402     ASSERT_THAT(d.request_status(), IsOk());
403 
404     // The request should have been redirected to https.
405     EXPECT_EQ(d.received_redirect_count(), 1);
406     EXPECT_EQ(req->url(), https_url);
407 
408     EXPECT_TRUE(d.response_completed());
409     EXPECT_EQ(d.request_status(), 0);
410     EXPECT_EQ(d.data_received(), kTestBody);
411   }
412 }
413 
414 // An end-to-end test for requesting a domain with a basic HTTPS record. Expect
415 // this to exercise connection logic for extra HostResolver results with
416 // metadata.
TEST_F(HttpsWithDnsOverHttpsTest,HttpsMetadata)417 TEST_F(HttpsWithDnsOverHttpsTest, HttpsMetadata) {
418   base::test::ScopedFeatureList features;
419   features.InitAndEnableFeatureWithParameters(
420       features::kUseDnsHttpsSvcb,
421       {// Disable timeouts.
422        {"UseDnsHttpsSvcbSecureExtraTimeMax", "0"},
423        {"UseDnsHttpsSvcbSecureExtraTimePercent", "0"},
424        {"UseDnsHttpsSvcbSecureExtraTimeMin", "0"}});
425   ResetContext();
426 
427   GURL main_url = https_server_.GetURL(kHostname, "/test");
428   EXPECT_TRUE(main_url.SchemeIs(url::kHttpsScheme));
429 
430   doh_server_.AddRecord(BuildTestHttpsServiceRecord(
431       dns_util::GetNameForHttpsQuery(url::SchemeHostPort(main_url)),
432       /*priority=*/1, /*service_name=*/kHostname, /*params=*/{}));
433 
434   // Fetch the http URL.
435   TestDelegate d;
436 
437   std::unique_ptr<URLRequest> req(context()->CreateRequest(
438       main_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
439   req->Start();
440   base::RunLoop().Run();
441   ASSERT_THAT(d.request_status(), IsOk());
442 
443   // There should be three DoH lookups for kHostname (A, AAAA, and HTTPS).
444   EXPECT_EQ(doh_server_.QueriesServed(), 3);
445 
446   EXPECT_TRUE(d.response_completed());
447   EXPECT_EQ(d.request_status(), 0);
448   EXPECT_EQ(d.data_received(), kTestBody);
449 }
450 
TEST_F(DnsOverHttpsIntegrationTest,EncryptedClientHello)451 TEST_F(DnsOverHttpsIntegrationTest, EncryptedClientHello) {
452   // Configure a test server that speaks ECH.
453   static constexpr char kRealName[] = "secret.example";
454   static constexpr char kPublicName[] = "public.example";
455   EmbeddedTestServer::ServerCertificateConfig server_cert_config;
456   server_cert_config.dns_names = {kRealName};
457 
458   SSLServerConfig ssl_server_config;
459   std::vector<uint8_t> ech_config_list;
460   ssl_server_config.ech_keys =
461       MakeTestEchKeys(kPublicName, /*max_name_len=*/128, &ech_config_list);
462   ASSERT_TRUE(ssl_server_config.ech_keys);
463 
464   EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
465   test_server.SetSSLConfig(server_cert_config, ssl_server_config);
466   RegisterDefaultHandlers(&test_server);
467   ASSERT_TRUE(test_server.Start());
468 
469   AddressList addr;
470   ASSERT_TRUE(test_server.GetAddressList(&addr));
471   GURL url = test_server.GetURL(kRealName, "/defaultresponse");
472   AddHostWithEch(url::SchemeHostPort(url), addr.front().address(),
473                  ech_config_list);
474 
475   for (bool feature_enabled : {true, false}) {
476     SCOPED_TRACE(feature_enabled);
477     base::test::ScopedFeatureList features;
478     if (feature_enabled) {
479       features.InitWithFeaturesAndParameters(
480           /*enabled_features=*/{{features::kUseDnsHttpsSvcb,
481                                  {// Disable timeouts.
482                                   {"UseDnsHttpsSvcbSecureExtraTimeMax", "0"},
483                                   {"UseDnsHttpsSvcbSecureExtraTimePercent",
484                                    "0"},
485                                   {"UseDnsHttpsSvcbSecureExtraTimeMin", "0"}}},
486                                 {features::kEncryptedClientHello, {}}},
487           /*disabled_features=*/{});
488     } else {
489       features.InitWithFeaturesAndParameters(
490           /*enabled_features=*/{{features::kUseDnsHttpsSvcb,
491                                  {// Disable timeouts.
492                                   {"UseDnsHttpsSvcbSecureExtraTimeMax", "0"},
493                                   {"UseDnsHttpsSvcbSecureExtraTimePercent",
494                                    "0"},
495                                   {"UseDnsHttpsSvcbSecureExtraTimeMin", "0"}}}},
496           /*disabled_features=*/{features::kEncryptedClientHello});
497     }
498 
499     for (bool config_enabled : {true, false}) {
500       SCOPED_TRACE(config_enabled);
501       bool ech_enabled = feature_enabled && config_enabled;
502 
503       // Create a new `URLRequestContext`, to ensure there are no cached
504       // sockets, etc., from the previous loop iteration.
505       ResetContext();
506 
507       SSLContextConfig config;
508       config.ech_enabled = config_enabled;
509       ssl_config_service_->UpdateSSLConfigAndNotify(config);
510 
511       TestDelegate d;
512       std::unique_ptr<URLRequest> r = context()->CreateRequest(
513           url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS);
514       r->Start();
515       EXPECT_TRUE(r->is_pending());
516 
517       d.RunUntilComplete();
518 
519       EXPECT_THAT(d.request_status(), IsOk());
520       EXPECT_EQ(1, d.response_started_count());
521       EXPECT_FALSE(d.received_data_before_response());
522       EXPECT_NE(0, d.bytes_received());
523       EXPECT_EQ(ech_enabled, r->ssl_info().encrypted_client_hello);
524     }
525   }
526 }
527 
528 // Test that, if the DNS returns a stale ECHConfigList (or other key mismatch),
529 // the client can recover and connect to the server, provided the server can
530 // handshake as the public name.
TEST_F(DnsOverHttpsIntegrationTest,EncryptedClientHelloStaleKey)531 TEST_F(DnsOverHttpsIntegrationTest, EncryptedClientHelloStaleKey) {
532   base::test::ScopedFeatureList features;
533   features.InitWithFeaturesAndParameters(
534       /*enabled_features=*/{{features::kEncryptedClientHello, {}},
535                             {features::kUseDnsHttpsSvcb,
536                              {// Disable timeouts.
537                               {"UseDnsHttpsSvcbSecureExtraTimeMax", "0"},
538                               {"UseDnsHttpsSvcbSecureExtraTimePercent", "0"},
539                               {"UseDnsHttpsSvcbSecureExtraTimeMin", "0"}}}},
540       /*disabled_features=*/{});
541   ResetContext();
542 
543   static constexpr char kRealNameStale[] = "secret1.example";
544   static constexpr char kRealNameWrongPublicName[] = "secret2.example";
545   static constexpr char kPublicName[] = "public.example";
546   static constexpr char kWrongPublicName[] = "wrong-public.example";
547 
548   std::vector<uint8_t> ech_config_list, ech_config_list_stale,
549       ech_config_list_wrong_public_name;
550   bssl::UniquePtr<SSL_ECH_KEYS> ech_keys =
551       MakeTestEchKeys(kPublicName, /*max_name_len=*/128, &ech_config_list);
552   ASSERT_TRUE(ech_keys);
553   ASSERT_TRUE(MakeTestEchKeys(kPublicName, /*max_name_len=*/128,
554                               &ech_config_list_stale));
555   ASSERT_TRUE(MakeTestEchKeys(kWrongPublicName, /*max_name_len=*/128,
556                               &ech_config_list_wrong_public_name));
557 
558   // Configure an ECH-supporting server that can speak for all names except
559   // `kWrongPublicName`.
560   EmbeddedTestServer::ServerCertificateConfig server_cert_config;
561   server_cert_config.dns_names = {kRealNameStale, kRealNameWrongPublicName,
562                                   kPublicName};
563   SSLServerConfig ssl_server_config;
564   ssl_server_config.ech_keys = std::move(ech_keys);
565   EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
566   test_server.SetSSLConfig(server_cert_config, ssl_server_config);
567   RegisterDefaultHandlers(&test_server);
568   ASSERT_TRUE(test_server.Start());
569 
570   AddressList addr;
571   ASSERT_TRUE(test_server.GetAddressList(&addr));
572   GURL url_stale = test_server.GetURL(kRealNameStale, "/defaultresponse");
573   GURL url_wrong_public_name =
574       test_server.GetURL(kRealNameWrongPublicName, "/defaultresponse");
575   AddHostWithEch(url::SchemeHostPort(url_stale), addr.front().address(),
576                  ech_config_list_stale);
577   AddHostWithEch(url::SchemeHostPort(url_wrong_public_name),
578                  addr.front().address(), ech_config_list_wrong_public_name);
579 
580   // Connecting to `url_stale` should succeed. Although the server will not
581   // decrypt the ClientHello, it can handshake as `kPublicName` and provide new
582   // keys for the client to use.
583   {
584     TestDelegate d;
585     std::unique_ptr<URLRequest> r = context()->CreateRequest(
586         url_stale, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS);
587     r->Start();
588     EXPECT_TRUE(r->is_pending());
589 
590     d.RunUntilComplete();
591 
592     EXPECT_THAT(d.request_status(), IsOk());
593     EXPECT_EQ(1, d.response_started_count());
594     EXPECT_FALSE(d.received_data_before_response());
595     EXPECT_NE(0, d.bytes_received());
596     EXPECT_TRUE(r->ssl_info().encrypted_client_hello);
597   }
598 
599   // Connecting to `url_wrong_public_name` should fail. The server can neither
600   // decrypt the ClientHello, nor handshake as `kWrongPublicName`.
601   {
602     TestDelegate d;
603     std::unique_ptr<URLRequest> r =
604         context()->CreateRequest(url_wrong_public_name, DEFAULT_PRIORITY, &d,
605                                  TRAFFIC_ANNOTATION_FOR_TESTS);
606     r->Start();
607     EXPECT_TRUE(r->is_pending());
608 
609     d.RunUntilComplete();
610 
611     EXPECT_THAT(d.request_status(),
612                 IsError(ERR_ECH_FALLBACK_CERTIFICATE_INVALID));
613   }
614 }
615 
TEST_F(DnsOverHttpsIntegrationTest,EncryptedClientHelloFallback)616 TEST_F(DnsOverHttpsIntegrationTest, EncryptedClientHelloFallback) {
617   base::test::ScopedFeatureList features;
618   features.InitWithFeaturesAndParameters(
619       /*enabled_features=*/{{features::kEncryptedClientHello, {}},
620                             {features::kUseDnsHttpsSvcb,
621                              {// Disable timeouts.
622                               {"UseDnsHttpsSvcbSecureExtraTimeMax", "0"},
623                               {"UseDnsHttpsSvcbSecureExtraTimePercent", "0"},
624                               {"UseDnsHttpsSvcbSecureExtraTimeMin", "0"}}}},
625       /*disabled_features=*/{});
626   ResetContext();
627 
628   static constexpr char kRealNameStale[] = "secret1.example";
629   static constexpr char kRealNameWrongPublicName[] = "secret2.example";
630   static constexpr char kPublicName[] = "public.example";
631   static constexpr char kWrongPublicName[] = "wrong-public.example";
632 
633   std::vector<uint8_t> ech_config_list_stale, ech_config_list_wrong_public_name;
634   ASSERT_TRUE(MakeTestEchKeys(kPublicName, /*max_name_len=*/128,
635                               &ech_config_list_stale));
636   ASSERT_TRUE(MakeTestEchKeys(kWrongPublicName, /*max_name_len=*/128,
637                               &ech_config_list_wrong_public_name));
638 
639   // Configure a server, without ECH, that can speak for all names except
640   // `kWrongPublicName`.
641   EmbeddedTestServer::ServerCertificateConfig server_cert_config;
642   server_cert_config.dns_names = {kRealNameStale, kRealNameWrongPublicName,
643                                   kPublicName};
644   EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
645   test_server.SetSSLConfig(server_cert_config);
646   RegisterDefaultHandlers(&test_server);
647   ASSERT_TRUE(test_server.Start());
648 
649   AddressList addr;
650   ASSERT_TRUE(test_server.GetAddressList(&addr));
651   GURL url_stale = test_server.GetURL(kRealNameStale, "/defaultresponse");
652   GURL url_wrong_public_name =
653       test_server.GetURL(kRealNameWrongPublicName, "/defaultresponse");
654   AddHostWithEch(url::SchemeHostPort(url_stale), addr.front().address(),
655                  ech_config_list_stale);
656   AddHostWithEch(url::SchemeHostPort(url_wrong_public_name),
657                  addr.front().address(), ech_config_list_wrong_public_name);
658 
659   // Connecting to `url_stale` should succeed. Although the server will not
660   // decrypt the ClientHello, it can handshake as `kPublicName` and trigger an
661   // authenticated fallback.
662   {
663     TestDelegate d;
664     std::unique_ptr<URLRequest> r = context()->CreateRequest(
665         url_stale, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS);
666     r->Start();
667     EXPECT_TRUE(r->is_pending());
668     d.RunUntilComplete();
669     EXPECT_THAT(d.request_status(), IsOk());
670     EXPECT_EQ(1, d.response_started_count());
671     EXPECT_FALSE(d.received_data_before_response());
672     EXPECT_NE(0, d.bytes_received());
673     EXPECT_FALSE(r->ssl_info().encrypted_client_hello);
674   }
675 
676   // Connecting to `url_wrong_public_name` should fail. The server can neither
677   // decrypt the ClientHello, nor handshake as `kWrongPublicName`.
678   {
679     TestDelegate d;
680     std::unique_ptr<URLRequest> r =
681         context()->CreateRequest(url_wrong_public_name, DEFAULT_PRIORITY, &d,
682                                  TRAFFIC_ANNOTATION_FOR_TESTS);
683     r->Start();
684     EXPECT_TRUE(r->is_pending());
685     d.RunUntilComplete();
686     EXPECT_THAT(d.request_status(),
687                 IsError(ERR_ECH_FALLBACK_CERTIFICATE_INVALID));
688   }
689 }
690 
TEST_F(DnsOverHttpsIntegrationTest,EncryptedClientHelloFallbackTLS12)691 TEST_F(DnsOverHttpsIntegrationTest, EncryptedClientHelloFallbackTLS12) {
692   base::test::ScopedFeatureList features;
693   features.InitWithFeaturesAndParameters(
694       /*enabled_features=*/{{features::kEncryptedClientHello, {}},
695                             {features::kUseDnsHttpsSvcb,
696                              {// Disable timeouts.
697                               {"UseDnsHttpsSvcbSecureExtraTimeMax", "0"},
698                               {"UseDnsHttpsSvcbSecureExtraTimePercent", "0"},
699                               {"UseDnsHttpsSvcbSecureExtraTimeMin", "0"}}}},
700       /*disabled_features=*/{});
701   ResetContext();
702 
703   static constexpr char kRealNameStale[] = "secret1.example";
704   static constexpr char kRealNameWrongPublicName[] = "secret2.example";
705   static constexpr char kPublicName[] = "public.example";
706   static constexpr char kWrongPublicName[] = "wrong-public.example";
707 
708   std::vector<uint8_t> ech_config_list_stale, ech_config_list_wrong_public_name;
709   ASSERT_TRUE(MakeTestEchKeys(kPublicName, /*max_name_len=*/128,
710                               &ech_config_list_stale));
711   ASSERT_TRUE(MakeTestEchKeys(kWrongPublicName, /*max_name_len=*/128,
712                               &ech_config_list_wrong_public_name));
713 
714   // Configure a server, without ECH or TLS 1.3, that can speak for all names
715   // except `kWrongPublicName`.
716   EmbeddedTestServer::ServerCertificateConfig server_cert_config;
717   server_cert_config.dns_names = {kRealNameStale, kRealNameWrongPublicName,
718                                   kPublicName};
719   SSLServerConfig ssl_server_config;
720   ssl_server_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
721   EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTPS);
722   test_server.SetSSLConfig(server_cert_config, ssl_server_config);
723   RegisterDefaultHandlers(&test_server);
724   ASSERT_TRUE(test_server.Start());
725 
726   AddressList addr;
727   ASSERT_TRUE(test_server.GetAddressList(&addr));
728   GURL url_stale = test_server.GetURL(kRealNameStale, "/defaultresponse");
729   GURL url_wrong_public_name =
730       test_server.GetURL(kRealNameWrongPublicName, "/defaultresponse");
731   AddHostWithEch(url::SchemeHostPort(url_stale), addr.front().address(),
732                  ech_config_list_stale);
733   AddHostWithEch(url::SchemeHostPort(url_wrong_public_name),
734                  addr.front().address(), ech_config_list_wrong_public_name);
735 
736   // Connecting to `url_stale` should succeed. Although the server will not
737   // decrypt the ClientHello, it can handshake as `kPublicName` and trigger an
738   // authenticated fallback.
739   {
740     TestDelegate d;
741     std::unique_ptr<URLRequest> r = context()->CreateRequest(
742         url_stale, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS);
743     r->Start();
744     EXPECT_TRUE(r->is_pending());
745     d.RunUntilComplete();
746     EXPECT_THAT(d.request_status(), IsOk());
747     EXPECT_EQ(1, d.response_started_count());
748     EXPECT_FALSE(d.received_data_before_response());
749     EXPECT_NE(0, d.bytes_received());
750     EXPECT_FALSE(r->ssl_info().encrypted_client_hello);
751   }
752 
753   // Connecting to `url_wrong_public_name` should fail. The server can neither
754   // decrypt the ClientHello, nor handshake as `kWrongPublicName`.
755   {
756     TestDelegate d;
757     std::unique_ptr<URLRequest> r =
758         context()->CreateRequest(url_wrong_public_name, DEFAULT_PRIORITY, &d,
759                                  TRAFFIC_ANNOTATION_FOR_TESTS);
760     r->Start();
761     EXPECT_TRUE(r->is_pending());
762     d.RunUntilComplete();
763     EXPECT_THAT(d.request_status(),
764                 IsError(ERR_ECH_FALLBACK_CERTIFICATE_INVALID));
765   }
766 }
767 
768 }  // namespace
769 }  // namespace net
770