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

Side by Side Diff: components/update_client/request_sender.cc

Issue 1685323002: Implement CUP signing in UpdateClient. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase and remove duplicated code comment. Created 4 years, 10 months 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "components/update_client/request_sender.h" 5 #include "components/update_client/request_sender.h"
6 6
7 #include "base/base64.h"
7 #include "base/bind.h" 8 #include "base/bind.h"
8 #include "base/bind_helpers.h" 9 #include "base/bind_helpers.h"
9 #include "base/location.h" 10 #include "base/location.h"
10 #include "base/logging.h" 11 #include "base/logging.h"
11 #include "base/single_thread_task_runner.h" 12 #include "base/single_thread_task_runner.h"
13 #include "base/strings/stringprintf.h"
12 #include "base/thread_task_runner_handle.h" 14 #include "base/thread_task_runner_handle.h"
15 #include "components/update_client/client_update_protocol_ecdsa.h"
13 #include "components/update_client/configurator.h" 16 #include "components/update_client/configurator.h"
14 #include "components/update_client/utils.h" 17 #include "components/update_client/utils.h"
18 #include "net/http/http_response_headers.h"
15 #include "net/url_request/url_fetcher.h" 19 #include "net/url_request/url_fetcher.h"
16 20
17 namespace update_client { 21 namespace update_client {
18 22
23 namespace {
24
25 // This is an ECDSA prime256v1 named-curve key.
26 const int kKeyVersion = 5;
27 const char kKeyPubBytesBase64[] =
28 "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEB+Yi+3SdJKCyFJmm+suW3CyXygvVsbDbPnJgoC"
29 "X4GeTtoL8Q/WjPx7CGtXOL1Xjbx0VPPN3DrvqZSL/oXy9hVw==";
30
31 } // namespace
32
33 // This value is chosen not to conflict with network errors defined by
34 // net/base/net_error_list.h. The callers don't have to handle this error in
35 // any meaningful way, but this value may be reported in UMA stats, therefore
36 // avoiding collisions with known network errors is desirable.
37 int RequestSender::kErrorResponseNotTrusted = -10000;
38
19 RequestSender::RequestSender(const scoped_refptr<Configurator>& config) 39 RequestSender::RequestSender(const scoped_refptr<Configurator>& config)
20 : config_(config) {} 40 : config_(config), use_signing_(false) {}
21 41
22 RequestSender::~RequestSender() { 42 RequestSender::~RequestSender() {
23 DCHECK(thread_checker_.CalledOnValidThread()); 43 DCHECK(thread_checker_.CalledOnValidThread());
24 } 44 }
25 45
26 void RequestSender::Send(const std::string& request_string, 46 void RequestSender::Send(bool use_signing,
47 const std::string& request_body,
27 const std::vector<GURL>& urls, 48 const std::vector<GURL>& urls,
28 const RequestSenderCallback& request_sender_callback) { 49 const RequestSenderCallback& request_sender_callback) {
29 DCHECK(thread_checker_.CalledOnValidThread()); 50 DCHECK(thread_checker_.CalledOnValidThread());
30 if (urls.empty()) {
31 base::ThreadTaskRunnerHandle::Get()->PostTask(
32 FROM_HERE, base::Bind(request_sender_callback, nullptr));
33 return;
34 }
35 51
36 request_string_ = request_string; 52 use_signing_ = use_signing;
53 request_body_ = request_body;
37 urls_ = urls; 54 urls_ = urls;
38 request_sender_callback_ = request_sender_callback; 55 request_sender_callback_ = request_sender_callback;
39 56
57 if (urls_.empty()) {
58 return HandleSendError(-1);
59 }
60
40 cur_url_ = urls_.begin(); 61 cur_url_ = urls_.begin();
41 62
63 if (use_signing_) {
64 public_key_ = GetKey(kKeyPubBytesBase64);
65 if (public_key_.empty())
66 return HandleSendError(-1);
67 }
68
42 SendInternal(); 69 SendInternal();
43 } 70 }
44 71
45 void RequestSender::SendInternal() { 72 void RequestSender::SendInternal() {
46 DCHECK(cur_url_ != urls_.end()); 73 DCHECK(cur_url_ != urls_.end());
47 DCHECK(cur_url_->is_valid()); 74 DCHECK(cur_url_->is_valid());
48 DCHECK(thread_checker_.CalledOnValidThread()); 75 DCHECK(thread_checker_.CalledOnValidThread());
49 76
50 url_fetcher_ = SendProtocolRequest(*cur_url_, request_string_, this, 77 GURL url(*cur_url_);
51 config_->RequestContext()); 78
79 if (use_signing_) {
80 DCHECK(!public_key_.empty());
81 signer_ = ClientUpdateProtocolEcdsa::Create(kKeyVersion, public_key_);
82 std::string request_query_string;
83 signer_->SignRequest(request_body_, &request_query_string);
84
85 url = BuildUpdateUrl(url, request_query_string);
86 }
87
88 url_fetcher_ =
89 SendProtocolRequest(url, request_body_, this, config_->RequestContext());
90 if (!url_fetcher_.get())
91 base::ThreadTaskRunnerHandle::Get()->PostTask(
92 FROM_HERE,
93 base::Bind(&RequestSender::SendInternalComplete, base::Unretained(this),
94 -1, std::string(), std::string()));
52 } 95 }
53 96
54 void RequestSender::OnURLFetchComplete(const net::URLFetcher* source) { 97 void RequestSender::SendInternalComplete(int error,
55 DCHECK(thread_checker_.CalledOnValidThread()); 98 const std::string& response_body,
56 if (GetFetchError(*source) == 0) { 99 const std::string& response_etag) {
57 request_sender_callback_.Run(source); 100 if (!error) {
58 return; 101 if (!use_signing_) {
102 base::ThreadTaskRunnerHandle::Get()->PostTask(
103 FROM_HERE, base::Bind(request_sender_callback_, 0, response_body));
104 return;
105 }
106
107 DCHECK(use_signing_);
108 DCHECK(signer_.get());
109 if (signer_->ValidateResponse(response_body, response_etag)) {
110 base::ThreadTaskRunnerHandle::Get()->PostTask(
111 FROM_HERE, base::Bind(request_sender_callback_, 0, response_body));
112 return;
113 }
114
115 error = kErrorResponseNotTrusted;
59 } 116 }
60 117
118 DCHECK(error);
61 if (++cur_url_ != urls_.end() && 119 if (++cur_url_ != urls_.end() &&
62 base::ThreadTaskRunnerHandle::Get()->PostTask( 120 base::ThreadTaskRunnerHandle::Get()->PostTask(
63 FROM_HERE, 121 FROM_HERE,
64 base::Bind(&RequestSender::SendInternal, base::Unretained(this)))) { 122 base::Bind(&RequestSender::SendInternal, base::Unretained(this)))) {
65 return; 123 return;
66 } 124 }
67 125
126 HandleSendError(error);
127 }
128
129 void RequestSender::OnURLFetchComplete(const net::URLFetcher* source) {
130 DCHECK(thread_checker_.CalledOnValidThread());
131 DCHECK(source);
132
133 VLOG(1) << "request completed from url: " << source->GetOriginalURL().spec();
134
135 const int fetch_error(GetFetchError(*source));
136 std::string response_body;
137 CHECK(source->GetResponseAsString(&response_body));
138
68 base::ThreadTaskRunnerHandle::Get()->PostTask( 139 base::ThreadTaskRunnerHandle::Get()->PostTask(
69 FROM_HERE, base::Bind(request_sender_callback_, source)); 140 FROM_HERE,
141 base::Bind(&RequestSender::SendInternalComplete, base::Unretained(this),
142 fetch_error, response_body, GetServerETag(source)));
143 }
144
145 void RequestSender::HandleSendError(int error) {
146 base::ThreadTaskRunnerHandle::Get()->PostTask(
147 FROM_HERE, base::Bind(request_sender_callback_, error, std::string()));
148 }
149
150 std::string RequestSender::GetKey(const char* key_bytes_base64) {
151 std::string result;
152 return base::Base64Decode(std::string(key_bytes_base64), &result)
153 ? result
154 : std::string();
155 }
156
157 GURL RequestSender::BuildUpdateUrl(const GURL& url,
158 const std::string& query_params) {
159 const std::string query_string(
160 url.has_query() ? base::StringPrintf("%s&%s", url.query().c_str(),
161 query_params.c_str())
162 : query_params);
163 GURL::Replacements replacements;
164 replacements.SetQueryStr(query_string);
165
166 return url.ReplaceComponents(replacements);
167 }
168
169 std::string RequestSender::GetServerETag(const net::URLFetcher* source) {
170 const auto response_headers(source->GetResponseHeaders());
171 if (!response_headers)
172 return std::string();
173
174 std::string etag;
175 return response_headers->EnumerateHeader(nullptr, "ETag", &etag)
176 ? etag
177 : std::string();
70 } 178 }
71 179
72 } // namespace update_client 180 } // namespace update_client
OLDNEW
« no previous file with comments | « components/update_client/request_sender.h ('k') | components/update_client/request_sender_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698