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

Side by Side Diff: components/certificate_transparency/log_proof_fetcher.cc

Issue 1405293009: Certificate Transparency: Fetching consistency proofs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Post merge with master 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 2015 The Chromium Authors. All rights reserved. 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 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/certificate_transparency/log_proof_fetcher.h" 5 #include "components/certificate_transparency/log_proof_fetcher.h"
6 6
7 #include <iterator> 7 #include <iterator>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/ref_counted.h" 10 #include "base/memory/ref_counted.h"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "base/strings/stringprintf.h"
12 #include "base/values.h" 13 #include "base/values.h"
13 #include "components/safe_json/safe_json_parser.h" 14 #include "components/safe_json/safe_json_parser.h"
14 #include "net/base/io_buffer.h" 15 #include "net/base/io_buffer.h"
15 #include "net/base/load_flags.h" 16 #include "net/base/load_flags.h"
16 #include "net/base/net_errors.h" 17 #include "net/base/net_errors.h"
17 #include "net/base/request_priority.h" 18 #include "net/base/request_priority.h"
18 #include "net/cert/ct_log_response_parser.h" 19 #include "net/cert/ct_log_response_parser.h"
19 #include "net/cert/signed_tree_head.h" 20 #include "net/cert/signed_tree_head.h"
20 #include "net/http/http_status_code.h" 21 #include "net/http/http_status_code.h"
21 #include "net/url_request/url_request_context.h" 22 #include "net/url_request/url_request_context.h"
(...skipping 11 matching lines...) Expand all
33 case net::URLRequestStatus::CANCELED: 34 case net::URLRequestStatus::CANCELED:
34 return net::ERR_ABORTED; 35 return net::ERR_ABORTED;
35 case net::URLRequestStatus::FAILED: 36 case net::URLRequestStatus::FAILED:
36 return status.error(); 37 return status.error();
37 default: 38 default:
38 NOTREACHED(); 39 NOTREACHED();
39 return net::ERR_FAILED; 40 return net::ERR_FAILED;
40 } 41 }
41 } 42 }
42 43
44 enum LogRequestType { SIGNED_TREE_HEAD, CONSISTENCY_PROOF };
45
46 template <typename T>
47 size_t InsertCallbackToMap(std::map<size_t, T>* callbacks_map, T callback) {
48 size_t callback_id = callbacks_map->size();
49 while (callbacks_map->find(callback_id) != callbacks_map->end())
50 ++callback_id;
51
52 callbacks_map->insert(std::make_pair(callback_id, callback));
53 return callback_id;
54 }
55
56 template <typename T>
57 T FindCallback(const std::map<size_t, T>& callbacks_map, size_t callback_id) {
58 auto callback_position = callbacks_map.find(callback_id);
59 CHECK(callback_position != callbacks_map.end());
60 return callback_position->second;
61 }
62
43 } // namespace 63 } // namespace
44 64
45 struct LogProofFetcher::FetchState { 65 struct LogProofFetcher::FetchState {
46 FetchState(const std::string& log_id, 66 FetchState(const std::string& log_id,
47 const SignedTreeHeadFetchedCallback& fetched_callback, 67 LogRequestType request_type,
68 size_t callback_id,
48 const FetchFailedCallback& failed_callback); 69 const FetchFailedCallback& failed_callback);
49 ~FetchState(); 70 ~FetchState();
50 71
51 std::string log_id; 72 std::string log_id;
52 SignedTreeHeadFetchedCallback fetched_callback; 73 LogRequestType request_type;
74 size_t callback_id;
53 FetchFailedCallback failed_callback; 75 FetchFailedCallback failed_callback;
svaldez 2015/11/12 20:11:03 Can't you just add: SignedTreeHeadFetchedCallback
Eran Messeri 2015/11/16 13:39:46 Done - it does simplify the design.
54 scoped_refptr<net::IOBufferWithSize> response_buffer; 76 scoped_refptr<net::IOBufferWithSize> response_buffer;
55 std::string assembled_response; 77 std::string assembled_response;
56 }; 78 };
57 79
58 LogProofFetcher::FetchState::FetchState( 80 LogProofFetcher::FetchState::FetchState(
59 const std::string& log_id, 81 const std::string& log_id,
60 const SignedTreeHeadFetchedCallback& fetched_callback, 82 LogRequestType request_type,
83 size_t callback_id,
61 const FetchFailedCallback& failed_callback) 84 const FetchFailedCallback& failed_callback)
62 : log_id(log_id), 85 : log_id(log_id),
63 fetched_callback(fetched_callback), 86 request_type(request_type),
87 callback_id(callback_id),
64 failed_callback(failed_callback), 88 failed_callback(failed_callback),
65 response_buffer(new net::IOBufferWithSize(kMaxLogResponseSizeInBytes)) {} 89 response_buffer(new net::IOBufferWithSize(kMaxLogResponseSizeInBytes)) {}
66 90
67 LogProofFetcher::FetchState::~FetchState() {} 91 LogProofFetcher::FetchState::~FetchState() {}
68 92
69 LogProofFetcher::LogProofFetcher(net::URLRequestContext* request_context) 93 LogProofFetcher::LogProofFetcher(net::URLRequestContext* request_context)
70 : request_context_(request_context), weak_factory_(this) { 94 : request_context_(request_context), weak_factory_(this) {
71 DCHECK(request_context); 95 DCHECK(request_context);
72 } 96 }
73 97
74 LogProofFetcher::~LogProofFetcher() { 98 LogProofFetcher::~LogProofFetcher() {
75 STLDeleteContainerPairPointers(inflight_requests_.begin(), 99 STLDeleteContainerPairPointers(inflight_requests_.begin(),
76 inflight_requests_.end()); 100 inflight_requests_.end());
77 } 101 }
78 102
79 void LogProofFetcher::FetchSignedTreeHead( 103 void LogProofFetcher::FetchSignedTreeHead(
80 const GURL& base_log_url, 104 const GURL& base_log_url,
81 const std::string& log_id, 105 const std::string& log_id,
82 const SignedTreeHeadFetchedCallback& fetched_callback, 106 const SignedTreeHeadFetchedCallback& fetched_callback,
83 const FetchFailedCallback& failed_callback) { 107 const FetchFailedCallback& failed_callback) {
84 DCHECK(base_log_url.SchemeIsHTTPOrHTTPS()); 108 DCHECK(base_log_url.SchemeIsHTTPOrHTTPS());
85 GURL fetch_url(base_log_url.Resolve("ct/v1/get-sth")); 109 GURL fetch_url(base_log_url.Resolve("ct/v1/get-sth"));
86 scoped_ptr<net::URLRequest> request = 110 net::URLRequest* request = CreateRequest(fetch_url);
87 request_context_->CreateRequest(fetch_url, net::DEFAULT_PRIORITY, this);
88 request->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
89 net::LOAD_DO_NOT_SAVE_COOKIES |
90 net::LOAD_DO_NOT_SEND_AUTH_DATA);
91 111
92 FetchState* fetch_state = 112 size_t callback_id =
93 new FetchState(log_id, fetched_callback, failed_callback); 113 InsertCallbackToMap(&sth_fetch_callbacks_, fetched_callback);
114 FetchState* fetch_state = new FetchState(
115 log_id, LogRequestType::SIGNED_TREE_HEAD, callback_id, failed_callback);
94 request->Start(); 116 request->Start();
95 inflight_requests_.insert(std::make_pair(request.release(), fetch_state)); 117 inflight_requests_.insert(std::make_pair(request, fetch_state));
118 }
119
120 void LogProofFetcher::FetchConsistencyProof(
121 const GURL& base_log_url,
122 const std::string& log_id,
123 size_t old_tree_size,
124 size_t new_tree_size,
125 const ConsistencyProofFetchedCallback& fetched_callback,
126 const FetchFailedCallback& failed_callback) {
127 DCHECK(base_log_url.SchemeIsHTTPOrHTTPS());
128 std::string query =
129 base::StringPrintf("first=%lu&second=%lu", old_tree_size, new_tree_size);
130 GURL::Replacements replacements;
131 replacements.SetQueryStr(query);
132 GURL fetch_url = base_log_url.Resolve("ct/v1/get-sth-consistency")
133 .ReplaceComponents(replacements);
svaldez 2015/11/12 20:11:03 Can't you just do: std::string relative = StringP
Eran Messeri 2015/11/16 13:39:46 Done.
134
135 net::URLRequest* request = CreateRequest(fetch_url);
136
137 size_t callback_id =
138 InsertCallbackToMap(&consistency_fetch_callbacks_, fetched_callback);
139 FetchState* fetch_state = new FetchState(
140 log_id, LogRequestType::CONSISTENCY_PROOF, callback_id, failed_callback);
141 request->Start();
142 inflight_requests_.insert(std::make_pair(request, fetch_state));
96 } 143 }
97 144
98 void LogProofFetcher::OnResponseStarted(net::URLRequest* request) { 145 void LogProofFetcher::OnResponseStarted(net::URLRequest* request) {
99 net::URLRequestStatus status(request->status()); 146 net::URLRequestStatus status(request->status());
100 DCHECK(inflight_requests_.count(request)); 147 DCHECK(inflight_requests_.count(request));
101 FetchState* fetch_state = inflight_requests_.find(request)->second; 148 FetchState* fetch_state = inflight_requests_.find(request)->second;
102 149
103 if (!status.is_success() || request->GetResponseCode() != net::HTTP_OK) { 150 if (!status.is_success() || request->GetResponseCode() != net::HTTP_OK) {
104 int net_error = net::OK; 151 int net_error = net::OK;
105 int http_response_code = request->GetResponseCode(); 152 int http_response_code = request->GetResponseCode();
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 } 225 }
179 } 226 }
180 227
181 void LogProofFetcher::RequestComplete(net::URLRequest* request) { 228 void LogProofFetcher::RequestComplete(net::URLRequest* request) {
182 DCHECK(inflight_requests_.count(request)); 229 DCHECK(inflight_requests_.count(request));
183 230
184 FetchState* fetch_state = inflight_requests_.find(request)->second; 231 FetchState* fetch_state = inflight_requests_.find(request)->second;
185 232
186 // Get rid of the buffer as it really isn't necessary. 233 // Get rid of the buffer as it really isn't necessary.
187 fetch_state->response_buffer = nullptr; 234 fetch_state->response_buffer = nullptr;
188 safe_json::SafeJsonParser::Parse( 235 if (fetch_state->request_type == LogRequestType::SIGNED_TREE_HEAD) {
189 fetch_state->assembled_response, 236 safe_json::SafeJsonParser::Parse(
190 base::Bind(&LogProofFetcher::OnSTHJsonParseSuccess, 237 fetch_state->assembled_response,
191 weak_factory_.GetWeakPtr(), request), 238 base::Bind(&LogProofFetcher::OnSTHJsonParseSuccess,
192 base::Bind(&LogProofFetcher::OnSTHJsonParseError, 239 weak_factory_.GetWeakPtr(), request),
193 weak_factory_.GetWeakPtr(), request)); 240 base::Bind(&LogProofFetcher::OnSTHJsonParseError,
241 weak_factory_.GetWeakPtr(), request));
242 } else if (fetch_state->request_type == LogRequestType::CONSISTENCY_PROOF) {
243 safe_json::SafeJsonParser::Parse(
244 fetch_state->assembled_response,
245 base::Bind(&LogProofFetcher::OnConsistencyProofJsonParseSuccess,
246 weak_factory_.GetWeakPtr(), request),
247 base::Bind(&LogProofFetcher::OnConsistencyProofJsonParseError,
248 weak_factory_.GetWeakPtr(), request));
249 } else {
250 NOTREACHED();
251 }
194 } 252 }
195 253
196 void LogProofFetcher::CleanupRequest(net::URLRequest* request) { 254 void LogProofFetcher::CleanupRequest(net::URLRequest* request) {
197 DVLOG(1) << "Cleaning up request to " << request->original_url(); 255 DVLOG(1) << "Cleaning up request to " << request->original_url();
198 auto it = inflight_requests_.find(request); 256 auto it = inflight_requests_.find(request);
199 DCHECK(it != inflight_requests_.end()); 257 DCHECK(it != inflight_requests_.end());
258
259 LogRequestType request_type = it->second->request_type;
260 size_t callback_id = it->second->callback_id;
261 if (request_type == SIGNED_TREE_HEAD) {
262 sth_fetch_callbacks_.erase(callback_id);
263 } else if (request_type == CONSISTENCY_PROOF) {
264 consistency_fetch_callbacks_.erase(callback_id);
265 }
200 auto next_it = it; 266 auto next_it = it;
201 std::advance(next_it, 1); 267 std::advance(next_it, 1);
202 268
203 // Delete FetchState and URLRequest, then the entry from inflight_requests_. 269 // Delete FetchState and URLRequest, then the entry from inflight_requests_.
204 STLDeleteContainerPairPointers(it, next_it); 270 STLDeleteContainerPairPointers(it, next_it);
205 inflight_requests_.erase(it); 271 inflight_requests_.erase(it);
206 } 272 }
207 273
208 void LogProofFetcher::InvokeFailureCallback(net::URLRequest* request, 274 void LogProofFetcher::InvokeFailureCallback(net::URLRequest* request,
209 int net_error, 275 int net_error,
210 int http_response_code) { 276 int http_response_code) {
211 DCHECK(inflight_requests_.count(request)); 277 DCHECK(inflight_requests_.count(request));
212 auto it = inflight_requests_.find(request); 278 auto it = inflight_requests_.find(request);
213 FetchState* fetch_state = it->second; 279 FetchState* fetch_state = it->second;
214 280
215 fetch_state->failed_callback.Run(fetch_state->log_id, net_error, 281 fetch_state->failed_callback.Run(fetch_state->log_id, net_error,
216 http_response_code); 282 http_response_code);
217 CleanupRequest(request); 283 CleanupRequest(request);
218 } 284 }
219 285
220 void LogProofFetcher::OnSTHJsonParseSuccess( 286 void LogProofFetcher::OnSTHJsonParseSuccess(
221 net::URLRequest* request, 287 net::URLRequest* request,
222 scoped_ptr<base::Value> parsed_json) { 288 scoped_ptr<base::Value> parsed_json) {
223 DCHECK(inflight_requests_.count(request)); 289 DCHECK(inflight_requests_.count(request));
224 290
225 FetchState* fetch_state = inflight_requests_.find(request)->second; 291 FetchState* fetch_state = inflight_requests_.find(request)->second;
226 net::ct::SignedTreeHead signed_tree_head; 292 net::ct::SignedTreeHead signed_tree_head;
227 if (net::ct::FillSignedTreeHead(*parsed_json.get(), &signed_tree_head)) { 293 if (net::ct::FillSignedTreeHead(*parsed_json.get(), &signed_tree_head)) {
228 fetch_state->fetched_callback.Run(fetch_state->log_id, signed_tree_head); 294 SignedTreeHeadFetchedCallback fetched_callback =
295 FindCallback(sth_fetch_callbacks_, fetch_state->callback_id);
296 fetched_callback.Run(fetch_state->log_id, signed_tree_head);
229 } else { 297 } else {
230 fetch_state->failed_callback.Run(fetch_state->log_id, 298 fetch_state->failed_callback.Run(fetch_state->log_id,
231 net::ERR_CT_STH_INCOMPLETE, net::HTTP_OK); 299 net::ERR_CT_STH_INCOMPLETE, net::HTTP_OK);
232 } 300 }
233 301
234 CleanupRequest(request); 302 CleanupRequest(request);
235 } 303 }
236 304
237 void LogProofFetcher::OnSTHJsonParseError(net::URLRequest* request, 305 void LogProofFetcher::OnSTHJsonParseError(net::URLRequest* request,
238 const std::string& error) { 306 const std::string& error) {
239 InvokeFailureCallback(request, net::ERR_CT_STH_PARSING_FAILED, net::HTTP_OK); 307 InvokeFailureCallback(request, net::ERR_CT_STH_PARSING_FAILED, net::HTTP_OK);
240 } 308 }
241 309
310 void LogProofFetcher::OnConsistencyProofJsonParseSuccess(
311 net::URLRequest* request,
312 scoped_ptr<base::Value> parsed_json) {
313 DCHECK(inflight_requests_.count(request));
314 FetchState* fetch_state = inflight_requests_.find(request)->second;
315 std::vector<std::string> consistency_proof;
316 if (net::ct::FillConsistencyProof(*parsed_json.get(), &consistency_proof)) {
317 ConsistencyProofFetchedCallback fetched_callback =
318 FindCallback(consistency_fetch_callbacks_, fetch_state->callback_id);
319 fetched_callback.Run(fetch_state->log_id, consistency_proof);
320 } else {
321 fetch_state->failed_callback.Run(
322 fetch_state->log_id, net::ERR_CT_CONSISTENCY_PROOF_PARSING_FAILED,
323 net::HTTP_OK);
324 }
325
326 CleanupRequest(request);
327 }
328
329 void LogProofFetcher::OnConsistencyProofJsonParseError(
330 net::URLRequest* request,
331 const std::string& error) {
332 InvokeFailureCallback(request, net::ERR_CT_CONSISTENCY_PROOF_PARSING_FAILED,
333 net::HTTP_OK);
334 }
335
336 net::URLRequest* LogProofFetcher::CreateRequest(const GURL& url) {
337 scoped_ptr<net::URLRequest> request =
338 request_context_->CreateRequest(url, net::DEFAULT_PRIORITY, this);
339 request->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
340 net::LOAD_DO_NOT_SAVE_COOKIES |
341 net::LOAD_DO_NOT_SEND_AUTH_DATA);
342 return request.release();
343 }
344
242 } // namespace certificate_transparency 345 } // namespace certificate_transparency
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698