Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 | |
| 43 } // namespace | 46 } // namespace |
| 44 | 47 |
| 45 struct LogProofFetcher::FetchState { | 48 struct LogProofFetcher::FetchState { |
| 46 FetchState(const std::string& log_id, | 49 FetchState(const std::string& log_id, |
| 47 const SignedTreeHeadFetchedCallback& fetched_callback, | 50 LogRequestType request_type, |
| 51 const SignedTreeHeadFetchedCallback& sth_fetch_callback, | |
| 52 const ConsistencyProofFetchedCallback& proof_fetch_callback, | |
| 48 const FetchFailedCallback& failed_callback); | 53 const FetchFailedCallback& failed_callback); |
| 49 ~FetchState(); | 54 ~FetchState(); |
| 50 | 55 |
| 51 std::string log_id; | 56 std::string log_id; |
| 52 SignedTreeHeadFetchedCallback fetched_callback; | 57 LogRequestType request_type; |
| 58 SignedTreeHeadFetchedCallback sth_fetch_callback; | |
| 59 ConsistencyProofFetchedCallback proof_fetch_callback; | |
| 53 FetchFailedCallback failed_callback; | 60 FetchFailedCallback failed_callback; |
| 54 scoped_refptr<net::IOBufferWithSize> response_buffer; | 61 scoped_refptr<net::IOBufferWithSize> response_buffer; |
| 55 std::string assembled_response; | 62 std::string assembled_response; |
| 56 }; | 63 }; |
| 57 | 64 |
| 58 LogProofFetcher::FetchState::FetchState( | 65 LogProofFetcher::FetchState::FetchState( |
| 59 const std::string& log_id, | 66 const std::string& log_id, |
| 60 const SignedTreeHeadFetchedCallback& fetched_callback, | 67 LogRequestType request_type, |
| 68 const SignedTreeHeadFetchedCallback& sth_fetch_callback, | |
| 69 const ConsistencyProofFetchedCallback& proof_fetch_callback, | |
| 61 const FetchFailedCallback& failed_callback) | 70 const FetchFailedCallback& failed_callback) |
| 62 : log_id(log_id), | 71 : log_id(log_id), |
| 63 fetched_callback(fetched_callback), | 72 request_type(request_type), |
| 73 sth_fetch_callback(sth_fetch_callback), | |
| 74 proof_fetch_callback(proof_fetch_callback), | |
| 64 failed_callback(failed_callback), | 75 failed_callback(failed_callback), |
| 65 response_buffer(new net::IOBufferWithSize(kMaxLogResponseSizeInBytes)) {} | 76 response_buffer(new net::IOBufferWithSize(kMaxLogResponseSizeInBytes)) { |
| 77 DCHECK(!(sth_fetch_callback.is_null() && proof_fetch_callback.is_null())); | |
| 78 } | |
| 66 | 79 |
| 67 LogProofFetcher::FetchState::~FetchState() {} | 80 LogProofFetcher::FetchState::~FetchState() {} |
| 68 | 81 |
| 69 LogProofFetcher::LogProofFetcher(net::URLRequestContext* request_context) | 82 LogProofFetcher::LogProofFetcher(net::URLRequestContext* request_context) |
| 70 : request_context_(request_context), weak_factory_(this) { | 83 : request_context_(request_context), weak_factory_(this) { |
| 71 DCHECK(request_context); | 84 DCHECK(request_context); |
| 72 } | 85 } |
| 73 | 86 |
| 74 LogProofFetcher::~LogProofFetcher() { | 87 LogProofFetcher::~LogProofFetcher() { |
| 75 STLDeleteContainerPairPointers(inflight_requests_.begin(), | 88 STLDeleteContainerPairPointers(inflight_requests_.begin(), |
| 76 inflight_requests_.end()); | 89 inflight_requests_.end()); |
| 77 } | 90 } |
| 78 | 91 |
| 79 void LogProofFetcher::FetchSignedTreeHead( | 92 void LogProofFetcher::FetchSignedTreeHead( |
| 80 const GURL& base_log_url, | 93 const GURL& base_log_url, |
| 81 const std::string& log_id, | 94 const std::string& log_id, |
| 82 const SignedTreeHeadFetchedCallback& fetched_callback, | 95 const SignedTreeHeadFetchedCallback& fetched_callback, |
| 83 const FetchFailedCallback& failed_callback) { | 96 const FetchFailedCallback& failed_callback) { |
|
mmenke
2015/11/18 19:25:15
Suggest putting everything in this method except t
Eran Messeri
2015/11/24 22:53:38
Done. I note that the use of two callbacks is a sm
mmenke
2015/11/25 17:40:28
Could also make a single callback that takes a val
Eran Messeri
2015/11/26 22:07:12
Should be fixed now that I've switched to using a
| |
| 84 DCHECK(base_log_url.SchemeIsHTTPOrHTTPS()); | 97 DCHECK(base_log_url.SchemeIsHTTPOrHTTPS()); |
| 85 GURL fetch_url(base_log_url.Resolve("ct/v1/get-sth")); | 98 GURL fetch_url(base_log_url.Resolve("ct/v1/get-sth")); |
| 86 scoped_ptr<net::URLRequest> request = | 99 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 | 100 |
| 92 FetchState* fetch_state = | 101 FetchState* fetch_state = |
| 93 new FetchState(log_id, fetched_callback, failed_callback); | 102 new FetchState(log_id, LogRequestType::SIGNED_TREE_HEAD, fetched_callback, |
| 103 ConsistencyProofFetchedCallback(), failed_callback); | |
| 94 request->Start(); | 104 request->Start(); |
| 95 inflight_requests_.insert(std::make_pair(request.release(), fetch_state)); | 105 inflight_requests_.insert(std::make_pair(request, fetch_state)); |
| 106 } | |
| 107 | |
| 108 void LogProofFetcher::FetchConsistencyProof( | |
| 109 const GURL& base_log_url, | |
| 110 const std::string& log_id, | |
| 111 size_t old_tree_size, | |
| 112 size_t new_tree_size, | |
| 113 const ConsistencyProofFetchedCallback& fetched_callback, | |
| 114 const FetchFailedCallback& failed_callback) { | |
| 115 DCHECK(base_log_url.SchemeIsHTTPOrHTTPS()); | |
| 116 | |
| 117 std::string relative = | |
| 118 base::StringPrintf("ct/v1/get-sth-consistency?first=%lu&second=%lu", | |
| 119 static_cast<unsigned long>(old_tree_size), | |
| 120 static_cast<unsigned long>(new_tree_size)); | |
|
mmenke
2015/11/18 19:25:15
include format_macros.h and use PRIuS to use print
Eran Messeri
2015/11/24 22:53:38
Done. These are size_t - they indicate size of a M
| |
| 121 GURL fetch_url = base_log_url.Resolve(relative); | |
| 122 | |
| 123 net::URLRequest* request = CreateRequest(fetch_url); | |
| 124 | |
| 125 FetchState* fetch_state = new FetchState( | |
| 126 log_id, LogRequestType::CONSISTENCY_PROOF, | |
| 127 SignedTreeHeadFetchedCallback(), fetched_callback, failed_callback); | |
| 128 request->Start(); | |
| 129 inflight_requests_.insert(std::make_pair(request, fetch_state)); | |
| 96 } | 130 } |
| 97 | 131 |
| 98 void LogProofFetcher::OnResponseStarted(net::URLRequest* request) { | 132 void LogProofFetcher::OnResponseStarted(net::URLRequest* request) { |
| 99 net::URLRequestStatus status(request->status()); | 133 net::URLRequestStatus status(request->status()); |
| 100 DCHECK(inflight_requests_.count(request)); | 134 DCHECK(inflight_requests_.count(request)); |
| 101 FetchState* fetch_state = inflight_requests_.find(request)->second; | 135 FetchState* fetch_state = inflight_requests_.find(request)->second; |
| 102 | 136 |
| 103 if (!status.is_success() || request->GetResponseCode() != net::HTTP_OK) { | 137 if (!status.is_success() || request->GetResponseCode() != net::HTTP_OK) { |
| 104 int net_error = net::OK; | 138 int net_error = net::OK; |
| 105 int http_response_code = request->GetResponseCode(); | 139 int http_response_code = request->GetResponseCode(); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 } | 212 } |
| 179 } | 213 } |
| 180 | 214 |
| 181 void LogProofFetcher::RequestComplete(net::URLRequest* request) { | 215 void LogProofFetcher::RequestComplete(net::URLRequest* request) { |
| 182 DCHECK(inflight_requests_.count(request)); | 216 DCHECK(inflight_requests_.count(request)); |
| 183 | 217 |
| 184 FetchState* fetch_state = inflight_requests_.find(request)->second; | 218 FetchState* fetch_state = inflight_requests_.find(request)->second; |
| 185 | 219 |
| 186 // Get rid of the buffer as it really isn't necessary. | 220 // Get rid of the buffer as it really isn't necessary. |
| 187 fetch_state->response_buffer = nullptr; | 221 fetch_state->response_buffer = nullptr; |
| 188 safe_json::SafeJsonParser::Parse( | 222 if (fetch_state->request_type == LogRequestType::SIGNED_TREE_HEAD) { |
| 189 fetch_state->assembled_response, | 223 safe_json::SafeJsonParser::Parse( |
| 190 base::Bind(&LogProofFetcher::OnSTHJsonParseSuccess, | 224 fetch_state->assembled_response, |
| 191 weak_factory_.GetWeakPtr(), request), | 225 base::Bind(&LogProofFetcher::OnSTHJsonParseSuccess, |
| 192 base::Bind(&LogProofFetcher::OnSTHJsonParseError, | 226 weak_factory_.GetWeakPtr(), request), |
| 193 weak_factory_.GetWeakPtr(), request)); | 227 base::Bind(&LogProofFetcher::OnSTHJsonParseError, |
| 228 weak_factory_.GetWeakPtr(), request)); | |
| 229 } else if (fetch_state->request_type == LogRequestType::CONSISTENCY_PROOF) { | |
| 230 safe_json::SafeJsonParser::Parse( | |
| 231 fetch_state->assembled_response, | |
| 232 base::Bind(&LogProofFetcher::OnConsistencyProofJsonParseSuccess, | |
| 233 weak_factory_.GetWeakPtr(), request), | |
| 234 base::Bind(&LogProofFetcher::OnConsistencyProofJsonParseError, | |
| 235 weak_factory_.GetWeakPtr(), request)); | |
| 236 } else { | |
| 237 NOTREACHED(); | |
| 238 } | |
| 194 } | 239 } |
| 195 | 240 |
| 196 void LogProofFetcher::CleanupRequest(net::URLRequest* request) { | 241 void LogProofFetcher::CleanupRequest(net::URLRequest* request) { |
| 197 DVLOG(1) << "Cleaning up request to " << request->original_url(); | 242 DVLOG(1) << "Cleaning up request to " << request->original_url(); |
| 198 auto it = inflight_requests_.find(request); | 243 auto it = inflight_requests_.find(request); |
| 199 DCHECK(it != inflight_requests_.end()); | 244 DCHECK(it != inflight_requests_.end()); |
| 200 auto next_it = it; | 245 auto next_it = it; |
| 201 std::advance(next_it, 1); | 246 std::advance(next_it, 1); |
| 202 | 247 |
| 203 // Delete FetchState and URLRequest, then the entry from inflight_requests_. | 248 // Delete FetchState and URLRequest, then the entry from inflight_requests_. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 217 CleanupRequest(request); | 262 CleanupRequest(request); |
| 218 } | 263 } |
| 219 | 264 |
| 220 void LogProofFetcher::OnSTHJsonParseSuccess( | 265 void LogProofFetcher::OnSTHJsonParseSuccess( |
| 221 net::URLRequest* request, | 266 net::URLRequest* request, |
| 222 scoped_ptr<base::Value> parsed_json) { | 267 scoped_ptr<base::Value> parsed_json) { |
| 223 DCHECK(inflight_requests_.count(request)); | 268 DCHECK(inflight_requests_.count(request)); |
| 224 | 269 |
| 225 FetchState* fetch_state = inflight_requests_.find(request)->second; | 270 FetchState* fetch_state = inflight_requests_.find(request)->second; |
| 226 net::ct::SignedTreeHead signed_tree_head; | 271 net::ct::SignedTreeHead signed_tree_head; |
| 227 if (net::ct::FillSignedTreeHead(*parsed_json.get(), &signed_tree_head)) { | 272 if (net::ct::FillSignedTreeHead(*parsed_json.get(), &signed_tree_head)) { |
|
mmenke
2015/11/18 19:25:15
nit: While you're here, .get() isn't needed.
Eran Messeri
2015/11/24 22:53:38
Done.
| |
| 228 fetch_state->fetched_callback.Run(fetch_state->log_id, signed_tree_head); | 273 DCHECK(!(fetch_state->sth_fetch_callback.is_null())); |
|
mmenke
2015/11/18 19:25:15
This DCHECK makes much more sense in FetchSignedTr
Eran Messeri
2015/11/24 22:53:38
Good point - DCHECK made much earlier on, removed
| |
| 274 fetch_state->sth_fetch_callback.Run(fetch_state->log_id, signed_tree_head); | |
| 229 } else { | 275 } else { |
| 230 fetch_state->failed_callback.Run(fetch_state->log_id, | 276 fetch_state->failed_callback.Run(fetch_state->log_id, |
| 231 net::ERR_CT_STH_INCOMPLETE, net::HTTP_OK); | 277 net::ERR_CT_STH_INCOMPLETE, net::HTTP_OK); |
| 232 } | 278 } |
| 233 | 279 |
| 234 CleanupRequest(request); | 280 CleanupRequest(request); |
| 235 } | 281 } |
| 236 | 282 |
| 237 void LogProofFetcher::OnSTHJsonParseError(net::URLRequest* request, | 283 void LogProofFetcher::OnSTHJsonParseError(net::URLRequest* request, |
| 238 const std::string& error) { | 284 const std::string& error) { |
| 239 InvokeFailureCallback(request, net::ERR_CT_STH_PARSING_FAILED, net::HTTP_OK); | 285 InvokeFailureCallback(request, net::ERR_CT_STH_PARSING_FAILED, net::HTTP_OK); |
| 240 } | 286 } |
| 241 | 287 |
| 288 void LogProofFetcher::OnConsistencyProofJsonParseSuccess( | |
| 289 net::URLRequest* request, | |
| 290 scoped_ptr<base::Value> parsed_json) { | |
| 291 DCHECK(inflight_requests_.count(request)); | |
| 292 FetchState* fetch_state = inflight_requests_.find(request)->second; | |
| 293 std::vector<std::string> consistency_proof; | |
| 294 if (net::ct::FillConsistencyProof(*parsed_json.get(), &consistency_proof)) { | |
|
mmenke
2015/11/18 19:25:15
See comment in OnSTHJsonParseSuccess.
Eran Messeri
2015/11/24 22:53:38
Done.
| |
| 295 DCHECK(!(fetch_state->proof_fetch_callback.is_null())); | |
|
mmenke
2015/11/18 19:25:15
See comment in OnSTHJsonParseSuccess.
Eran Messeri
2015/11/24 22:53:38
Done (removed unnecessary DCHECKs here as they are
| |
| 296 fetch_state->proof_fetch_callback.Run(fetch_state->log_id, | |
| 297 consistency_proof); | |
| 298 } else { | |
| 299 fetch_state->failed_callback.Run( | |
| 300 fetch_state->log_id, net::ERR_CT_CONSISTENCY_PROOF_PARSING_FAILED, | |
| 301 net::HTTP_OK); | |
| 302 } | |
| 303 | |
| 304 CleanupRequest(request); | |
| 305 } | |
| 306 | |
| 307 void LogProofFetcher::OnConsistencyProofJsonParseError( | |
| 308 net::URLRequest* request, | |
| 309 const std::string& error) { | |
| 310 InvokeFailureCallback(request, net::ERR_CT_CONSISTENCY_PROOF_PARSING_FAILED, | |
| 311 net::HTTP_OK); | |
| 312 } | |
| 313 | |
| 314 net::URLRequest* LogProofFetcher::CreateRequest(const GURL& url) { | |
| 315 scoped_ptr<net::URLRequest> request = | |
| 316 request_context_->CreateRequest(url, net::DEFAULT_PRIORITY, this); | |
| 317 request->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | |
| 318 net::LOAD_DO_NOT_SAVE_COOKIES | | |
| 319 net::LOAD_DO_NOT_SEND_AUTH_DATA); | |
| 320 return request.release(); | |
| 321 } | |
| 322 | |
| 242 } // namespace certificate_transparency | 323 } // namespace certificate_transparency |
| OLD | NEW |