1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ssl/common_name_mismatch_handler.h"
7 #include "base/callback_helpers.h"
8 #include "base/logging.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "chrome/browser/ssl/ssl_error_classification.h"
11 #include "net/base/load_flags.h"
12 #include "net/http/http_response_headers.h"
13 #include "net/http/http_util.h"
14 #include "net/url_request/url_request_status.h"
16 CommonNameMismatchHandler::CommonNameMismatchHandler(
17 const GURL
& request_url
,
18 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
)
19 : request_url_(request_url
), request_context_(request_context
) {}
21 CommonNameMismatchHandler::~CommonNameMismatchHandler() {}
24 CommonNameMismatchHandler::TestingState
25 CommonNameMismatchHandler::testing_state_
= NOT_TESTING
;
27 void CommonNameMismatchHandler::CheckSuggestedUrl(
29 const CheckUrlCallback
& callback
) {
30 // Should be used only in tests.
31 if (testing_state_
== IGNORE_REQUESTS_FOR_TESTING
)
34 DCHECK(CalledOnValidThread());
35 DCHECK(!IsCheckingSuggestedUrl());
36 DCHECK(check_url_callback_
.is_null());
38 check_url_callback_
= callback
;
40 url_fetcher_
= net::URLFetcher::Create(url
, net::URLFetcher::HEAD
, this);
41 url_fetcher_
->SetAutomaticallyRetryOn5xx(false);
42 url_fetcher_
->SetRequestContext(request_context_
.get());
44 // Can't safely use net::LOAD_DISABLE_CERT_REVOCATION_CHECKING here,
45 // since then the connection may be reused without checking the cert.
46 url_fetcher_
->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES
|
47 net::LOAD_DO_NOT_SEND_COOKIES
|
48 net::LOAD_DO_NOT_SEND_AUTH_DATA
);
49 url_fetcher_
->Start();
53 bool CommonNameMismatchHandler::GetSuggestedUrl(
54 const GURL
& request_url
,
55 const std::vector
<std::string
>& dns_names
,
56 GURL
* suggested_url
) {
57 std::string host_name
= request_url
.host();
58 std::string www_mismatch_hostname
;
59 if (!SSLErrorClassification::GetWWWSubDomainMatch(host_name
, dns_names
,
60 &www_mismatch_hostname
)) {
63 // The full URL should be pinged, not just the new hostname. So, get the
64 // |suggested_url| with the |request_url|'s hostname replaced with
65 // new hostname. Keep resource path, query params the same.
66 GURL::Replacements replacements
;
67 replacements
.SetHostStr(www_mismatch_hostname
);
68 *suggested_url
= request_url
.ReplaceComponents(replacements
);
72 void CommonNameMismatchHandler::Cancel() {
74 check_url_callback_
.Reset();
77 void CommonNameMismatchHandler::OnURLFetchComplete(
78 const net::URLFetcher
* source
) {
79 DCHECK(CalledOnValidThread());
80 DCHECK(IsCheckingSuggestedUrl());
81 DCHECK_EQ(url_fetcher_
.get(), source
);
82 DCHECK(!check_url_callback_
.is_null());
83 DCHECK(!url_fetcher_
.get()->GetStatus().is_io_pending());
85 SuggestedUrlCheckResult result
= SUGGESTED_URL_NOT_AVAILABLE
;
86 // Save a copy of |suggested_url| so it can be used after |url_fetcher_|
88 const GURL suggested_url
= url_fetcher_
->GetOriginalURL();
89 const GURL
& landing_url
= url_fetcher_
->GetURL();
91 // Make sure the |landing_url| is a HTTPS page and returns a proper response
93 if (url_fetcher_
.get()->GetResponseCode() == 200 &&
94 landing_url
.SchemeIsCryptographic() &&
95 landing_url
.host() != request_url_
.host()) {
96 result
= SUGGESTED_URL_AVAILABLE
;
99 base::ResetAndReturn(&check_url_callback_
).Run(result
, suggested_url
);
102 bool CommonNameMismatchHandler::IsCheckingSuggestedUrl() const {