Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1138)

Side by Side Diff: chrome/browser/local_discovery/privet_http_impl.cc

Issue 1417363004: Verify certificate of Privet v3 device (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/local_discovery/privet_http_impl.h" 5 #include "chrome/browser/local_discovery/privet_http_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/location.h" 11 #include "base/location.h"
12 #include "base/rand_util.h" 12 #include "base/rand_util.h"
13 #include "base/single_thread_task_runner.h" 13 #include "base/single_thread_task_runner.h"
14 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
16 #include "base/thread_task_runner_handle.h" 16 #include "base/thread_task_runner_handle.h"
17 #include "chrome/browser/local_discovery/privet_constants.h" 17 #include "chrome/browser/local_discovery/privet_constants.h"
18 #include "chrome/common/chrome_content_client.h"
18 #include "chrome/common/cloud_print/cloud_print_constants.h" 19 #include "chrome/common/cloud_print/cloud_print_constants.h"
19 #include "net/base/url_util.h" 20 #include "net/base/url_util.h"
21 #include "net/cert/cert_verifier.h"
22 #include "net/cert/cert_verify_result.h"
23 #include "net/url_request/url_request_context.h"
24 #include "net/url_request/url_request_context_builder.h"
20 #include "url/gurl.h" 25 #include "url/gurl.h"
21 26
22 #if defined(ENABLE_PRINT_PREVIEW) 27 #if defined(ENABLE_PRINT_PREVIEW)
23 #include "chrome/browser/local_discovery/pwg_raster_converter.h" 28 #include "chrome/browser/local_discovery/pwg_raster_converter.h"
24 #include "components/cloud_devices/common/printer_description.h" 29 #include "components/cloud_devices/common/printer_description.h"
25 #include "printing/pdf_render_settings.h" 30 #include "printing/pdf_render_settings.h"
26 #include "printing/pwg_raster_settings.h" 31 #include "printing/pwg_raster_settings.h"
27 #include "ui/gfx/text_elider.h" 32 #include "ui/gfx/text_elider.h"
28 #endif // ENABLE_PRINT_PREVIEW 33 #endif // ENABLE_PRINT_PREVIEW
29 34
30 namespace local_discovery { 35 namespace local_discovery {
31 36
32 namespace { 37 namespace {
38
33 const char kUrlPlaceHolder[] = "http://host/"; 39 const char kUrlPlaceHolder[] = "http://host/";
34 const char kPrivetRegisterActionArgName[] = "action"; 40 const char kPrivetRegisterActionArgName[] = "action";
35 const char kPrivetRegisterUserArgName[] = "user"; 41 const char kPrivetRegisterUserArgName[] = "user";
36 42
37 const int kPrivetCancelationTimeoutSeconds = 3; 43 const int kPrivetCancelationTimeoutSeconds = 3;
38 44
39 #if defined(ENABLE_PRINT_PREVIEW) 45 #if defined(ENABLE_PRINT_PREVIEW)
40 const char kPrivetURLKeyUserName[] = "user_name"; 46 const char kPrivetURLKeyUserName[] = "user_name";
41 const char kPrivetURLKeyClientName[] = "client_name"; 47 const char kPrivetURLKeyClientName[] = "client_name";
42 const char kPrivetURLKeyJobname[] = "job_name"; 48 const char kPrivetURLKeyJobname[] = "job_name";
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 const std::string& query_params) { 80 const std::string& query_params) {
75 GURL url(kUrlPlaceHolder); 81 GURL url(kUrlPlaceHolder);
76 GURL::Replacements replacements; 82 GURL::Replacements replacements;
77 replacements.SetPathStr(path); 83 replacements.SetPathStr(path);
78 if (!query_params.empty()) { 84 if (!query_params.empty()) {
79 replacements.SetQueryStr(query_params); 85 replacements.SetQueryStr(query_params);
80 } 86 }
81 return url.ReplaceComponents(replacements); 87 return url.ReplaceComponents(replacements);
82 } 88 }
83 89
90 // Used before we have any certificate fingerprint.
91 class FailingCertVerifier : public net::CertVerifier {
92 public:
93 int Verify(net::X509Certificate* cert,
94 const std::string& hostname,
95 const std::string& ocsp_response,
96 int flags,
97 net::CRLSet* crl_set,
98 net::CertVerifyResult* verify_result,
99 const net::CompletionCallback& callback,
100 scoped_ptr<Request>* out_req,
101 const net::BoundNetLog& net_log) override {
102 verify_result->Reset();
103 verify_result->verified_cert = cert;
104 verify_result->cert_status = net::CERT_STATUS_INVALID;
105 return net::ERR_CERT_INVALID;
106 }
107 };
108
109 // Class verifies certificate by its fingerprint received using different
110 // channel. It's the only know information about device with self-signed
111 // certificate.
112 class FingerprintVerifier : public net::CertVerifier {
113 public:
114 explicit FingerprintVerifier(
115 const net::SHA256HashValue& certificate_fingerprint)
116 : certificate_fingerprint_(certificate_fingerprint) {}
117
118 int Verify(net::X509Certificate* cert,
119 const std::string& hostname,
120 const std::string& ocsp_response,
121 int flags,
122 net::CRLSet* crl_set,
123 net::CertVerifyResult* verify_result,
124 const net::CompletionCallback& callback,
125 scoped_ptr<Request>* out_req,
126 const net::BoundNetLog& net_log) override {
127 // Mark certificate as invalid as we didn't check it.
128 verify_result->Reset();
129 verify_result->verified_cert = cert;
130 verify_result->cert_status = net::CERT_STATUS_INVALID;
131
132 auto fingerprint =
133 net::X509Certificate::CalculateFingerprint256(cert->os_cert_handle());
134
135 return certificate_fingerprint_.Equals(fingerprint) ? net::OK
136 : net::ERR_CERT_INVALID;
137 }
138
139 private:
140 net::SHA256HashValue certificate_fingerprint_;
141
142 DISALLOW_COPY_AND_ASSIGN(FingerprintVerifier);
143 };
144
145 class PrivetContextGetter : public net::URLRequestContextGetter {
146 public:
147 PrivetContextGetter(
148 const scoped_refptr<base::SingleThreadTaskRunner>& net_task_runner,
149 const net::SHA256HashValue& certificate_fingerprint)
150 : verifier_(new FingerprintVerifier(certificate_fingerprint)),
151 net_task_runner_(net_task_runner) {}
152
153 // Don't allow any https without fingerprint. Device with valid certificate
154 // may be different from the one which user is trying to pair.
155 explicit PrivetContextGetter(
156 const scoped_refptr<base::SingleThreadTaskRunner>& net_task_runner)
157 : verifier_(new FailingCertVerifier()),
158 net_task_runner_(net_task_runner) {}
159
160 net::URLRequestContext* GetURLRequestContext() override {
161 if (!context_) {
162 net::URLRequestContextBuilder builder;
163 builder.set_proxy_service(net::ProxyService::CreateDirect());
164 builder.SetSpdyAndQuicEnabled(false, false);
165 builder.DisableHttpCache();
166 builder.SetCertVerifier(verifier_.Pass());
167 builder.set_user_agent(::GetUserAgent());
168 context_ = builder.Build();
169 }
170 return context_.get();
171 }
172
173 scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner()
174 const override {
175 return net_task_runner_;
176 }
177
178 protected:
179 ~PrivetContextGetter() override = default;
mmenke 2015/10/29 16:12:26 BUG: The URLRequestContext must be deleted on the
Vitaly Buka (NO REVIEWS) 2015/10/29 18:37:12 That's not what I see from code: https://code.goog
mmenke 2015/10/29 18:40:18 You're right - I completely forgot about that magi
180
181 private:
182 scoped_ptr<net::CertVerifier> verifier_;
183 scoped_ptr<net::URLRequestContext> context_;
184 scoped_refptr<base::SingleThreadTaskRunner> net_task_runner_;
185
186 DISALLOW_COPY_AND_ASSIGN(PrivetContextGetter);
187 };
188
84 } // namespace 189 } // namespace
85 190
86 PrivetInfoOperationImpl::PrivetInfoOperationImpl( 191 PrivetInfoOperationImpl::PrivetInfoOperationImpl(
87 PrivetHTTPClient* privet_client, 192 PrivetHTTPClient* privet_client,
88 const PrivetJSONOperation::ResultCallback& callback) 193 const PrivetJSONOperation::ResultCallback& callback)
89 : privet_client_(privet_client), callback_(callback) { 194 : privet_client_(privet_client), callback_(callback) {
90 } 195 }
91 196
92 PrivetInfoOperationImpl::~PrivetInfoOperationImpl() { 197 PrivetInfoOperationImpl::~PrivetInfoOperationImpl() {
93 } 198 }
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 int visible_http_code = -1; 277 int visible_http_code = -1;
173 FailureReason reason = FAILURE_NETWORK; 278 FailureReason reason = FAILURE_NETWORK;
174 279
175 if (error == PrivetURLFetcher::RESPONSE_CODE_ERROR) { 280 if (error == PrivetURLFetcher::RESPONSE_CODE_ERROR) {
176 visible_http_code = fetcher->response_code(); 281 visible_http_code = fetcher->response_code();
177 reason = FAILURE_HTTP_ERROR; 282 reason = FAILURE_HTTP_ERROR;
178 } else if (error == PrivetURLFetcher::JSON_PARSE_ERROR) { 283 } else if (error == PrivetURLFetcher::JSON_PARSE_ERROR) {
179 reason = FAILURE_MALFORMED_RESPONSE; 284 reason = FAILURE_MALFORMED_RESPONSE;
180 } else if (error == PrivetURLFetcher::TOKEN_ERROR) { 285 } else if (error == PrivetURLFetcher::TOKEN_ERROR) {
181 reason = FAILURE_TOKEN; 286 reason = FAILURE_TOKEN;
182 } else if (error == PrivetURLFetcher::RETRY_ERROR) { 287 } else if (error == PrivetURLFetcher::UNKNOWN_ERROR) {
183 reason = FAILURE_RETRY; 288 reason = FAILURE_UNKNOWN;
184 } 289 }
185 290
186 delegate_->OnPrivetRegisterError(this, 291 delegate_->OnPrivetRegisterError(this,
187 current_action_, 292 current_action_,
188 reason, 293 reason,
189 visible_http_code, 294 visible_http_code,
190 NULL); 295 NULL);
191 } 296 }
192 297
193 void PrivetRegisterOperationImpl::OnParsedJson( 298 void PrivetRegisterOperationImpl::OnParsedJson(
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 void PrivetLocalPrintOperationImpl::SetPWGRasterConverterForTesting( 789 void PrivetLocalPrintOperationImpl::SetPWGRasterConverterForTesting(
685 scoped_ptr<PWGRasterConverter> pwg_raster_converter) { 790 scoped_ptr<PWGRasterConverter> pwg_raster_converter) {
686 pwg_raster_converter_ = pwg_raster_converter.Pass(); 791 pwg_raster_converter_ = pwg_raster_converter.Pass();
687 } 792 }
688 #endif // ENABLE_PRINT_PREVIEW 793 #endif // ENABLE_PRINT_PREVIEW
689 794
690 PrivetHTTPClientImpl::PrivetHTTPClientImpl( 795 PrivetHTTPClientImpl::PrivetHTTPClientImpl(
691 const std::string& name, 796 const std::string& name,
692 const net::HostPortPair& host_port, 797 const net::HostPortPair& host_port,
693 net::URLRequestContextGetter* request_context) 798 net::URLRequestContextGetter* request_context)
694 : name_(name), request_context_(request_context), host_port_(host_port) {} 799 : PrivetHTTPClientImpl(name,
800 host_port,
801 request_context->GetNetworkTaskRunner()) {}
802
803 PrivetHTTPClientImpl::PrivetHTTPClientImpl(
804 const std::string& name,
805 const net::HostPortPair& host_port,
806 const scoped_refptr<base::SingleThreadTaskRunner>& net_task_runner)
807 : name_(name),
808 context_getter_(new PrivetContextGetter(net_task_runner)),
mmenke 2015/10/29 16:12:26 URLRequestContexts are very heavy weight objects.
Vitaly Buka (NO REVIEWS) 2015/10/29 18:37:12 For PrivetHTTPClient printing functionality this c
809 host_port_(host_port) {}
695 810
696 PrivetHTTPClientImpl::~PrivetHTTPClientImpl() { 811 PrivetHTTPClientImpl::~PrivetHTTPClientImpl() {
697 } 812 }
698 813
699 const std::string& PrivetHTTPClientImpl::GetName() { 814 const std::string& PrivetHTTPClientImpl::GetName() {
700 return name_; 815 return name_;
701 } 816 }
702 817
703 scoped_ptr<PrivetJSONOperation> PrivetHTTPClientImpl::CreateInfoOperation( 818 scoped_ptr<PrivetJSONOperation> PrivetHTTPClientImpl::CreateInfoOperation(
704 const PrivetJSONOperation::ResultCallback& callback) { 819 const PrivetJSONOperation::ResultCallback& callback) {
705 return scoped_ptr<PrivetJSONOperation>( 820 return scoped_ptr<PrivetJSONOperation>(
706 new PrivetInfoOperationImpl(this, callback)); 821 new PrivetInfoOperationImpl(this, callback));
707 } 822 }
708 823
709 scoped_ptr<PrivetURLFetcher> PrivetHTTPClientImpl::CreateURLFetcher( 824 scoped_ptr<PrivetURLFetcher> PrivetHTTPClientImpl::CreateURLFetcher(
710 const GURL& url, 825 const GURL& url,
711 net::URLFetcher::RequestType request_type, 826 net::URLFetcher::RequestType request_type,
712 PrivetURLFetcher::Delegate* delegate) { 827 PrivetURLFetcher::Delegate* delegate) {
713 GURL::Replacements replacements; 828 GURL::Replacements replacements;
714 replacements.SetHostStr(host_port_.host()); 829 replacements.SetHostStr(host_port_.host());
715 std::string port( 830 std::string port = base::UintToString(host_port_.port());
716 base::UintToString(host_port_.port())); // Keep string alive.
717 replacements.SetPortStr(port); 831 replacements.SetPortStr(port);
832 std::string scheme = IsInHttpsMode() ? "https" : "http";
833 replacements.SetSchemeStr(scheme);
718 return scoped_ptr<PrivetURLFetcher>( 834 return scoped_ptr<PrivetURLFetcher>(
719 new PrivetURLFetcher(url.ReplaceComponents(replacements), 835 new PrivetURLFetcher(url.ReplaceComponents(replacements), request_type,
720 request_type, 836 context_getter_, delegate));
721 request_context_.get(),
722 delegate));
723 } 837 }
724 838
725 void PrivetHTTPClientImpl::RefreshPrivetToken( 839 void PrivetHTTPClientImpl::RefreshPrivetToken(
726 const PrivetURLFetcher::TokenCallback& callback) { 840 const PrivetURLFetcher::TokenCallback& callback) {
727 token_callbacks_.push_back(callback); 841 token_callbacks_.push_back(callback);
728 842
729 if (!info_operation_) { 843 if (!info_operation_) {
730 info_operation_ = CreateInfoOperation( 844 info_operation_ = CreateInfoOperation(
731 base::Bind(&PrivetHTTPClientImpl::OnPrivetInfoDone, 845 base::Bind(&PrivetHTTPClientImpl::OnPrivetInfoDone,
732 base::Unretained(this))); 846 base::Unretained(this)));
733 info_operation_->Start(); 847 info_operation_->Start();
734 } 848 }
735 } 849 }
736 850
851 void PrivetHTTPClientImpl::SwitchToHttps(
852 uint16_t port,
853 const net::SHA256HashValue& certificate_fingerprint) {
854 use_https_ = true;
855 host_port_.set_port(port);
856 context_getter_ = new PrivetContextGetter(
857 context_getter_->GetNetworkTaskRunner(), certificate_fingerprint);
858 }
859
860 bool PrivetHTTPClientImpl::IsInHttpsMode() const {
861 return use_https_;
862 }
863
737 void PrivetHTTPClientImpl::OnPrivetInfoDone( 864 void PrivetHTTPClientImpl::OnPrivetInfoDone(
738 const base::DictionaryValue* value) { 865 const base::DictionaryValue* value) {
739 info_operation_.reset(); 866 info_operation_.reset();
740 std::string token; 867 std::string token;
741 868
742 // If this does not succeed, token will be empty, and an empty string 869 // If this does not succeed, token will be empty, and an empty string
743 // is our sentinel value, since empty X-Privet-Tokens are not allowed. 870 // is our sentinel value, since empty X-Privet-Tokens are not allowed.
744 if (value) { 871 if (value) {
745 value->GetString(kPrivetInfoKeyToken, &token); 872 value->GetString(kPrivetInfoKeyToken, &token);
746 } 873 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 PrivetLocalPrintOperation::Delegate* delegate) { 918 PrivetLocalPrintOperation::Delegate* delegate) {
792 #if defined(ENABLE_PRINT_PREVIEW) 919 #if defined(ENABLE_PRINT_PREVIEW)
793 return scoped_ptr<PrivetLocalPrintOperation>( 920 return scoped_ptr<PrivetLocalPrintOperation>(
794 new PrivetLocalPrintOperationImpl(info_client(), delegate)); 921 new PrivetLocalPrintOperationImpl(info_client(), delegate));
795 #else 922 #else
796 return scoped_ptr<PrivetLocalPrintOperation>(); 923 return scoped_ptr<PrivetLocalPrintOperation>();
797 #endif // ENABLE_PRINT_PREVIEW 924 #endif // ENABLE_PRINT_PREVIEW
798 } 925 }
799 926
800 } // namespace local_discovery 927 } // namespace local_discovery
OLDNEW
« no previous file with comments | « chrome/browser/local_discovery/privet_http_impl.h ('k') | chrome/browser/local_discovery/privet_http_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698