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/format_macros.h" | |
9 #include "base/logging.h" | 10 #include "base/logging.h" |
10 #include "base/memory/ref_counted.h" | 11 #include "base/memory/ref_counted.h" |
11 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
13 #include "base/strings/stringprintf.h" | |
12 #include "base/values.h" | 14 #include "base/values.h" |
13 #include "components/safe_json/safe_json_parser.h" | 15 #include "components/safe_json/safe_json_parser.h" |
14 #include "net/base/io_buffer.h" | 16 #include "net/base/io_buffer.h" |
15 #include "net/base/load_flags.h" | 17 #include "net/base/load_flags.h" |
16 #include "net/base/net_errors.h" | 18 #include "net/base/net_errors.h" |
17 #include "net/base/request_priority.h" | 19 #include "net/base/request_priority.h" |
18 #include "net/cert/ct_log_response_parser.h" | 20 #include "net/cert/ct_log_response_parser.h" |
19 #include "net/cert/signed_tree_head.h" | 21 #include "net/cert/signed_tree_head.h" |
20 #include "net/http/http_status_code.h" | 22 #include "net/http/http_status_code.h" |
21 #include "net/url_request/url_request_context.h" | 23 #include "net/url_request/url_request_context.h" |
(...skipping 11 matching lines...) Expand all Loading... | |
33 case net::URLRequestStatus::CANCELED: | 35 case net::URLRequestStatus::CANCELED: |
34 return net::ERR_ABORTED; | 36 return net::ERR_ABORTED; |
35 case net::URLRequestStatus::FAILED: | 37 case net::URLRequestStatus::FAILED: |
36 return status.error(); | 38 return status.error(); |
37 default: | 39 default: |
38 NOTREACHED(); | 40 NOTREACHED(); |
39 return net::ERR_FAILED; | 41 return net::ERR_FAILED; |
40 } | 42 } |
41 } | 43 } |
42 | 44 |
45 enum LogRequestType { SIGNED_TREE_HEAD, CONSISTENCY_PROOF }; | |
Ryan Sleevi
2015/11/26 00:50:09
Document
Eran Messeri
2015/11/26 22:07:13
Obsolete.
| |
46 | |
43 } // namespace | 47 } // namespace |
44 | 48 |
45 struct LogProofFetcher::FetchState { | 49 struct LogProofFetcher::FetchState { |
46 FetchState(const std::string& log_id, | 50 FetchState(const std::string& log_id, |
47 const SignedTreeHeadFetchedCallback& fetched_callback, | 51 LogRequestType request_type, |
52 const SignedTreeHeadFetchedCallback& sth_fetch_callback, | |
53 const ConsistencyProofFetchedCallback& proof_fetch_callback, | |
48 const FetchFailedCallback& failed_callback); | 54 const FetchFailedCallback& failed_callback); |
49 ~FetchState(); | 55 ~FetchState(); |
50 | 56 |
51 std::string log_id; | 57 std::string log_id; |
52 SignedTreeHeadFetchedCallback fetched_callback; | 58 LogRequestType request_type; |
59 SignedTreeHeadFetchedCallback sth_fetch_callback; | |
60 ConsistencyProofFetchedCallback proof_fetch_callback; | |
53 FetchFailedCallback failed_callback; | 61 FetchFailedCallback failed_callback; |
54 scoped_refptr<net::IOBufferWithSize> response_buffer; | 62 scoped_refptr<net::IOBufferWithSize> response_buffer; |
55 std::string assembled_response; | 63 std::string assembled_response; |
56 }; | 64 }; |
57 | 65 |
58 LogProofFetcher::FetchState::FetchState( | 66 LogProofFetcher::FetchState::FetchState( |
59 const std::string& log_id, | 67 const std::string& log_id, |
60 const SignedTreeHeadFetchedCallback& fetched_callback, | 68 LogRequestType request_type, |
69 const SignedTreeHeadFetchedCallback& sth_fetch_callback, | |
70 const ConsistencyProofFetchedCallback& proof_fetch_callback, | |
61 const FetchFailedCallback& failed_callback) | 71 const FetchFailedCallback& failed_callback) |
62 : log_id(log_id), | 72 : log_id(log_id), |
63 fetched_callback(fetched_callback), | 73 request_type(request_type), |
74 sth_fetch_callback(sth_fetch_callback), | |
75 proof_fetch_callback(proof_fetch_callback), | |
64 failed_callback(failed_callback), | 76 failed_callback(failed_callback), |
65 response_buffer(new net::IOBufferWithSize(kMaxLogResponseSizeInBytes)) {} | 77 response_buffer(new net::IOBufferWithSize(kMaxLogResponseSizeInBytes)) { |
78 DCHECK(!(sth_fetch_callback.is_null() && proof_fetch_callback.is_null())); | |
Ryan Sleevi
2015/11/26 00:50:09
Past experience has shown mixing state objects lik
Eran Messeri
2015/11/26 22:07:13
Agreed - this is indeed a smell. I've completely c
| |
79 } | |
66 | 80 |
67 LogProofFetcher::FetchState::~FetchState() {} | 81 LogProofFetcher::FetchState::~FetchState() {} |
68 | 82 |
69 LogProofFetcher::LogProofFetcher(net::URLRequestContext* request_context) | 83 LogProofFetcher::LogProofFetcher(net::URLRequestContext* request_context) |
70 : request_context_(request_context), weak_factory_(this) { | 84 : request_context_(request_context), weak_factory_(this) { |
71 DCHECK(request_context); | 85 DCHECK(request_context); |
72 } | 86 } |
73 | 87 |
74 LogProofFetcher::~LogProofFetcher() { | 88 LogProofFetcher::~LogProofFetcher() { |
75 STLDeleteContainerPairPointers(inflight_requests_.begin(), | 89 STLDeleteContainerPairPointers(inflight_requests_.begin(), |
76 inflight_requests_.end()); | 90 inflight_requests_.end()); |
77 } | 91 } |
78 | 92 |
79 void LogProofFetcher::FetchSignedTreeHead( | 93 void LogProofFetcher::FetchSignedTreeHead( |
80 const GURL& base_log_url, | 94 const GURL& base_log_url, |
81 const std::string& log_id, | 95 const std::string& log_id, |
82 const SignedTreeHeadFetchedCallback& fetched_callback, | 96 const SignedTreeHeadFetchedCallback& fetched_callback, |
83 const FetchFailedCallback& failed_callback) { | 97 const FetchFailedCallback& failed_callback) { |
98 GURL fetch_url(base_log_url.Resolve("ct/v1/get-sth")); | |
99 | |
100 FetchFromLog(fetch_url, log_id, fetched_callback, | |
101 ConsistencyProofFetchedCallback(), failed_callback); | |
102 } | |
103 | |
104 void LogProofFetcher::FetchConsistencyProof( | |
105 const GURL& base_log_url, | |
106 const std::string& log_id, | |
107 size_t old_tree_size, | |
Ryan Sleevi
2015/11/26 00:50:09
BUG: I'm fairly sure these should be uint64_t type
Eran Messeri
2015/11/26 22:07:13
Correct, fixed.
| |
108 size_t new_tree_size, | |
109 const ConsistencyProofFetchedCallback& fetched_callback, | |
110 const FetchFailedCallback& failed_callback) { | |
84 DCHECK(base_log_url.SchemeIsHTTPOrHTTPS()); | 111 DCHECK(base_log_url.SchemeIsHTTPOrHTTPS()); |
85 GURL fetch_url(base_log_url.Resolve("ct/v1/get-sth")); | 112 |
113 std::string relative = base::StringPrintf( | |
114 "ct/v1/get-sth-consistency?first=%" PRIuS "&second=%" PRIuS, | |
115 old_tree_size, new_tree_size); | |
116 GURL fetch_url = base_log_url.Resolve(relative); | |
117 | |
118 FetchFromLog(fetch_url, log_id, SignedTreeHeadFetchedCallback(), | |
119 fetched_callback, failed_callback); | |
120 } | |
121 | |
122 void LogProofFetcher::FetchFromLog( | |
123 const GURL& request_url, | |
124 const std::string& log_id, | |
125 const SignedTreeHeadFetchedCallback& sth_fetched_callback, | |
126 const ConsistencyProofFetchedCallback& proof_fetched_callback, | |
127 const FetchFailedCallback& failed_callback) { | |
128 DCHECK(request_url.SchemeIsHTTPOrHTTPS()); | |
129 DCHECK(!failed_callback.is_null()); | |
130 | |
131 LogRequestType request_type; | |
132 if (!sth_fetched_callback.is_null()) { | |
133 request_type = LogRequestType::SIGNED_TREE_HEAD; | |
134 } else { | |
135 DCHECK(!proof_fetched_callback.is_null()); | |
136 request_type = LogRequestType::CONSISTENCY_PROOF; | |
137 } | |
mmenke
2015/11/25 17:40:28
optional: May be cleaner as an argument...Or mayb
Eran Messeri
2015/11/26 22:07:13
Obsolete - see restructuring of the code.
| |
138 | |
86 scoped_ptr<net::URLRequest> request = | 139 scoped_ptr<net::URLRequest> request = |
87 request_context_->CreateRequest(fetch_url, net::DEFAULT_PRIORITY, this); | 140 request_context_->CreateRequest(request_url, net::DEFAULT_PRIORITY, this); |
88 request->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 141 request->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
89 net::LOAD_DO_NOT_SAVE_COOKIES | | 142 net::LOAD_DO_NOT_SAVE_COOKIES | |
90 net::LOAD_DO_NOT_SEND_AUTH_DATA); | 143 net::LOAD_DO_NOT_SEND_AUTH_DATA); |
91 | 144 |
92 FetchState* fetch_state = | 145 FetchState* fetch_state = |
93 new FetchState(log_id, fetched_callback, failed_callback); | 146 new FetchState(log_id, request_type, sth_fetched_callback, |
147 proof_fetched_callback, failed_callback); | |
94 request->Start(); | 148 request->Start(); |
95 inflight_requests_.insert(std::make_pair(request.release(), fetch_state)); | 149 inflight_requests_.insert(std::make_pair(request.release(), fetch_state)); |
96 } | 150 } |
97 | 151 |
98 void LogProofFetcher::OnResponseStarted(net::URLRequest* request) { | 152 void LogProofFetcher::OnResponseStarted(net::URLRequest* request) { |
99 net::URLRequestStatus status(request->status()); | 153 net::URLRequestStatus status(request->status()); |
100 DCHECK(inflight_requests_.count(request)); | 154 DCHECK(inflight_requests_.count(request)); |
101 FetchState* fetch_state = inflight_requests_.find(request)->second; | 155 FetchState* fetch_state = inflight_requests_.find(request)->second; |
102 | 156 |
103 if (!status.is_success() || request->GetResponseCode() != net::HTTP_OK) { | 157 if (!status.is_success() || request->GetResponseCode() != net::HTTP_OK) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
178 } | 232 } |
179 } | 233 } |
180 | 234 |
181 void LogProofFetcher::RequestComplete(net::URLRequest* request) { | 235 void LogProofFetcher::RequestComplete(net::URLRequest* request) { |
182 DCHECK(inflight_requests_.count(request)); | 236 DCHECK(inflight_requests_.count(request)); |
183 | 237 |
184 FetchState* fetch_state = inflight_requests_.find(request)->second; | 238 FetchState* fetch_state = inflight_requests_.find(request)->second; |
185 | 239 |
186 // Get rid of the buffer as it really isn't necessary. | 240 // Get rid of the buffer as it really isn't necessary. |
187 fetch_state->response_buffer = nullptr; | 241 fetch_state->response_buffer = nullptr; |
188 safe_json::SafeJsonParser::Parse( | 242 if (fetch_state->request_type == LogRequestType::SIGNED_TREE_HEAD) { |
189 fetch_state->assembled_response, | 243 safe_json::SafeJsonParser::Parse( |
190 base::Bind(&LogProofFetcher::OnSTHJsonParseSuccess, | 244 fetch_state->assembled_response, |
191 weak_factory_.GetWeakPtr(), request), | 245 base::Bind(&LogProofFetcher::OnSTHJsonParseSuccess, |
192 base::Bind(&LogProofFetcher::OnSTHJsonParseError, | 246 weak_factory_.GetWeakPtr(), request), |
193 weak_factory_.GetWeakPtr(), request)); | 247 base::Bind(&LogProofFetcher::OnSTHJsonParseError, |
248 weak_factory_.GetWeakPtr(), request)); | |
249 } else if (fetch_state->request_type == LogRequestType::CONSISTENCY_PROOF) { | |
250 safe_json::SafeJsonParser::Parse( | |
251 fetch_state->assembled_response, | |
252 base::Bind(&LogProofFetcher::OnConsistencyProofJsonParseSuccess, | |
253 weak_factory_.GetWeakPtr(), request), | |
254 base::Bind(&LogProofFetcher::OnConsistencyProofJsonParseError, | |
255 weak_factory_.GetWeakPtr(), request)); | |
256 } else { | |
257 NOTREACHED(); | |
258 } | |
194 } | 259 } |
195 | 260 |
196 void LogProofFetcher::CleanupRequest(net::URLRequest* request) { | 261 void LogProofFetcher::CleanupRequest(net::URLRequest* request) { |
197 DVLOG(1) << "Cleaning up request to " << request->original_url(); | 262 DVLOG(1) << "Cleaning up request to " << request->original_url(); |
198 auto it = inflight_requests_.find(request); | 263 auto it = inflight_requests_.find(request); |
199 DCHECK(it != inflight_requests_.end()); | 264 DCHECK(it != inflight_requests_.end()); |
200 auto next_it = it; | 265 auto next_it = it; |
201 std::advance(next_it, 1); | 266 std::advance(next_it, 1); |
202 | 267 |
203 // Delete FetchState and URLRequest, then the entry from inflight_requests_. | 268 // Delete FetchState and URLRequest, then the entry from inflight_requests_. |
(...skipping 13 matching lines...) Expand all Loading... | |
217 CleanupRequest(request); | 282 CleanupRequest(request); |
218 } | 283 } |
219 | 284 |
220 void LogProofFetcher::OnSTHJsonParseSuccess( | 285 void LogProofFetcher::OnSTHJsonParseSuccess( |
221 net::URLRequest* request, | 286 net::URLRequest* request, |
222 scoped_ptr<base::Value> parsed_json) { | 287 scoped_ptr<base::Value> parsed_json) { |
223 DCHECK(inflight_requests_.count(request)); | 288 DCHECK(inflight_requests_.count(request)); |
224 | 289 |
225 FetchState* fetch_state = inflight_requests_.find(request)->second; | 290 FetchState* fetch_state = inflight_requests_.find(request)->second; |
226 net::ct::SignedTreeHead signed_tree_head; | 291 net::ct::SignedTreeHead signed_tree_head; |
227 if (net::ct::FillSignedTreeHead(*parsed_json.get(), &signed_tree_head)) { | 292 if (net::ct::FillSignedTreeHead(*parsed_json, &signed_tree_head)) { |
228 fetch_state->fetched_callback.Run(fetch_state->log_id, signed_tree_head); | 293 fetch_state->sth_fetch_callback.Run(fetch_state->log_id, signed_tree_head); |
229 } else { | 294 } else { |
230 fetch_state->failed_callback.Run(fetch_state->log_id, | 295 fetch_state->failed_callback.Run(fetch_state->log_id, |
231 net::ERR_CT_STH_INCOMPLETE, net::HTTP_OK); | 296 net::ERR_CT_STH_INCOMPLETE, net::HTTP_OK); |
232 } | 297 } |
233 | 298 |
234 CleanupRequest(request); | 299 CleanupRequest(request); |
235 } | 300 } |
236 | 301 |
237 void LogProofFetcher::OnSTHJsonParseError(net::URLRequest* request, | 302 void LogProofFetcher::OnSTHJsonParseError(net::URLRequest* request, |
238 const std::string& error) { | 303 const std::string& error) { |
239 InvokeFailureCallback(request, net::ERR_CT_STH_PARSING_FAILED, net::HTTP_OK); | 304 InvokeFailureCallback(request, net::ERR_CT_STH_PARSING_FAILED, net::HTTP_OK); |
240 } | 305 } |
241 | 306 |
307 void LogProofFetcher::OnConsistencyProofJsonParseSuccess( | |
308 net::URLRequest* request, | |
309 scoped_ptr<base::Value> parsed_json) { | |
310 DCHECK(inflight_requests_.count(request)); | |
311 FetchState* fetch_state = inflight_requests_.find(request)->second; | |
312 std::vector<std::string> consistency_proof; | |
313 if (net::ct::FillConsistencyProof(*parsed_json, &consistency_proof)) { | |
314 fetch_state->proof_fetch_callback.Run(fetch_state->log_id, | |
315 consistency_proof); | |
316 } else { | |
317 fetch_state->failed_callback.Run( | |
318 fetch_state->log_id, net::ERR_CT_CONSISTENCY_PROOF_PARSING_FAILED, | |
319 net::HTTP_OK); | |
320 } | |
321 | |
322 CleanupRequest(request); | |
323 } | |
324 | |
325 void LogProofFetcher::OnConsistencyProofJsonParseError( | |
326 net::URLRequest* request, | |
327 const std::string& error) { | |
328 InvokeFailureCallback(request, net::ERR_CT_CONSISTENCY_PROOF_PARSING_FAILED, | |
329 net::HTTP_OK); | |
330 } | |
331 | |
242 } // namespace certificate_transparency | 332 } // namespace certificate_transparency |
OLD | NEW |