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

Side by Side Diff: chrome/browser/safe_browsing/download_protection_service.cc

Issue 8459001: Extract the certificate to use in the download protection pingback. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Merge and fix test Created 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/safe_browsing/download_protection_service.h" 5 #include "chrome/browser/safe_browsing/download_protection_service.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 109
110 class DownloadProtectionService::CheckClientDownloadRequest 110 class DownloadProtectionService::CheckClientDownloadRequest
111 : public base::RefCountedThreadSafe< 111 : public base::RefCountedThreadSafe<
112 DownloadProtectionService::CheckClientDownloadRequest, 112 DownloadProtectionService::CheckClientDownloadRequest,
113 BrowserThread::DeleteOnUIThread>, 113 BrowserThread::DeleteOnUIThread>,
114 public content::URLFetcherDelegate { 114 public content::URLFetcherDelegate {
115 public: 115 public:
116 CheckClientDownloadRequest(const DownloadInfo& info, 116 CheckClientDownloadRequest(const DownloadInfo& info,
117 const CheckDownloadCallback& callback, 117 const CheckDownloadCallback& callback,
118 DownloadProtectionService* service, 118 DownloadProtectionService* service,
119 SafeBrowsingService* sb_service) 119 SafeBrowsingService* sb_service,
120 SignatureUtil* signature_util)
120 : info_(info), 121 : info_(info),
121 callback_(callback), 122 callback_(callback),
122 service_(service), 123 service_(service),
124 signature_util_(signature_util),
123 sb_service_(sb_service), 125 sb_service_(sb_service),
124 pingback_enabled_(service_->enabled()), 126 pingback_enabled_(service_->enabled()) {
125 is_signed_(false) {
126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
127 } 128 }
128 129
129 void Start() { 130 void Start() {
130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 131 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
131 // TODO(noelutz): implement some cache to make sure we don't issue the same 132 // TODO(noelutz): implement some cache to make sure we don't issue the same
132 // request over and over again if a user downloads the same binary multiple 133 // request over and over again if a user downloads the same binary multiple
133 // times. 134 // times.
134 if (info_.download_url_chain.empty()) { 135 if (info_.download_url_chain.empty()) {
135 RecordStats(REASON_INVALID_URL); 136 RecordStats(REASON_INVALID_URL);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 private: 213 private:
213 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; 214 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
214 friend class DeleteTask<CheckClientDownloadRequest>; 215 friend class DeleteTask<CheckClientDownloadRequest>;
215 216
216 virtual ~CheckClientDownloadRequest() { 217 virtual ~CheckClientDownloadRequest() {
217 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 218 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
218 } 219 }
219 220
220 void ExtractFileFeatures() { 221 void ExtractFileFeatures() {
221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 222 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
222 if (safe_browsing::signature_util::IsSigned(info_.local_file)) { 223 signature_util_->CheckSignature(info_.local_file, &signature_info_);
224 bool is_signed;
225 if (signature_info_.has_certificate_contents()) {
223 VLOG(2) << "Downloaded a signed binary: " << info_.local_file.value(); 226 VLOG(2) << "Downloaded a signed binary: " << info_.local_file.value();
224 is_signed_ = true; 227 is_signed = true;
225 } else { 228 } else {
226 VLOG(2) << "Downloaded an unsigned binary: " << info_.local_file.value(); 229 VLOG(2) << "Downloaded an unsigned binary: " << info_.local_file.value();
227 is_signed_ = false; 230 is_signed = false;
noelutz 2011/11/04 04:41:11 nit: I guess you don't really need that boolean an
Brian Ryner 2011/11/04 22:20:30 I left it as a convenience, that way we only need
228 } 231 }
229 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.SignedBinaryDownload", is_signed_); 232 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.SignedBinaryDownload", is_signed);
230 233
231 // TODO(noelutz): DownloadInfo should also contain the IP address of every 234 // TODO(noelutz): DownloadInfo should also contain the IP address of every
232 // URL in the redirect chain. We also should check whether the download 235 // URL in the redirect chain. We also should check whether the download
233 // URL is hosted on the internal network. 236 // URL is hosted on the internal network.
234 BrowserThread::PostTask( 237 BrowserThread::PostTask(
235 BrowserThread::IO, 238 BrowserThread::IO,
236 FROM_HERE, 239 FROM_HERE,
237 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this)); 240 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this));
238 } 241 }
239 242
240 void CheckWhitelists() { 243 void CheckWhitelists() {
241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
242 DownloadCheckResultReason reason = REASON_MAX; 245 DownloadCheckResultReason reason = REASON_MAX;
243 if (!sb_service_.get()) { 246 if (!sb_service_.get()) {
244 reason = REASON_SB_DISABLED; 247 reason = REASON_SB_DISABLED;
245 } else { 248 } else {
246 for (size_t i = 0; i < info_.download_url_chain.size(); ++i) { 249 for (size_t i = 0; i < info_.download_url_chain.size(); ++i) {
247 const GURL& url = info_.download_url_chain[i]; 250 const GURL& url = info_.download_url_chain[i];
248 if (url.is_valid() && sb_service_->MatchDownloadWhitelistUrl(url)) { 251 if (url.is_valid() && sb_service_->MatchDownloadWhitelistUrl(url)) {
249 reason = REASON_WHITELISTED_URL; 252 reason = REASON_WHITELISTED_URL;
250 break; 253 break;
251 } 254 }
252 } 255 }
253 if (info_.referrer_url.is_valid() && reason == REASON_MAX && 256 if (info_.referrer_url.is_valid() && reason == REASON_MAX &&
254 sb_service_->MatchDownloadWhitelistUrl(info_.referrer_url)) { 257 sb_service_->MatchDownloadWhitelistUrl(info_.referrer_url)) {
255 reason = REASON_WHITELISTED_REFERRER; 258 reason = REASON_WHITELISTED_REFERRER;
256 } 259 }
257 if (reason != REASON_MAX || is_signed_) { 260 if (reason != REASON_MAX || signature_info_.has_certificate_contents()) {
258 UMA_HISTOGRAM_COUNTS("SBClientDownload.SignedOrWhitelistedDownload", 1); 261 UMA_HISTOGRAM_COUNTS("SBClientDownload.SignedOrWhitelistedDownload", 1);
259 } 262 }
260 } 263 }
261 if (reason != REASON_MAX) { 264 if (reason != REASON_MAX) {
262 RecordStats(reason); 265 RecordStats(reason);
263 PostFinishTask(SAFE); 266 PostFinishTask(SAFE);
264 } else if (!pingback_enabled_) { 267 } else if (!pingback_enabled_) {
265 RecordStats(REASON_SB_DISABLED); 268 RecordStats(REASON_SB_DISABLED);
266 PostFinishTask(SAFE); 269 PostFinishTask(SAFE);
267 } else { 270 } else {
(...skipping 29 matching lines...) Expand all
297 if (i == info_.download_url_chain.size() - 1) { 300 if (i == info_.download_url_chain.size() - 1) {
298 // The last URL in the chain is the download URL. 301 // The last URL in the chain is the download URL.
299 resource->set_type(ClientDownloadRequest::DOWNLOAD_URL); 302 resource->set_type(ClientDownloadRequest::DOWNLOAD_URL);
300 resource->set_referrer(info_.referrer_url.spec()); 303 resource->set_referrer(info_.referrer_url.spec());
301 } else { 304 } else {
302 resource->set_type(ClientDownloadRequest::DOWNLOAD_REDIRECT); 305 resource->set_type(ClientDownloadRequest::DOWNLOAD_REDIRECT);
303 } 306 }
304 // TODO(noelutz): fill out the remote IP addresses. 307 // TODO(noelutz): fill out the remote IP addresses.
305 } 308 }
306 request.set_user_initiated(info_.user_initiated); 309 request.set_user_initiated(info_.user_initiated);
310 request.mutable_signature()->CopyFrom(signature_info_);
307 std::string request_data; 311 std::string request_data;
308 if (!request.SerializeToString(&request_data)) { 312 if (!request.SerializeToString(&request_data)) {
309 RecordStats(REASON_INVALID_REQUEST_PROTO); 313 RecordStats(REASON_INVALID_REQUEST_PROTO);
310 FinishRequest(SAFE); 314 FinishRequest(SAFE);
311 return; 315 return;
312 } 316 }
313 317
314 VLOG(2) << "Sending a request for URL: " 318 VLOG(2) << "Sending a request for URL: "
315 << info_.download_url_chain.back(); 319 << info_.download_url_chain.back();
316 fetcher_.reset(content::URLFetcher::Create(0 /* ID used for testing */, 320 fetcher_.reset(content::URLFetcher::Create(0 /* ID used for testing */,
(...skipping 23 matching lines...) Expand all
340 } 344 }
341 } 345 }
342 346
343 void RecordStats(DownloadCheckResultReason reason) { 347 void RecordStats(DownloadCheckResultReason reason) {
344 UMA_HISTOGRAM_ENUMERATION("SBClientDownload.CheckDownloadStats", 348 UMA_HISTOGRAM_ENUMERATION("SBClientDownload.CheckDownloadStats",
345 reason, 349 reason,
346 REASON_MAX); 350 REASON_MAX);
347 } 351 }
348 352
349 DownloadInfo info_; 353 DownloadInfo info_;
354 ClientDownloadRequest_SignatureInfo signature_info_;
350 CheckDownloadCallback callback_; 355 CheckDownloadCallback callback_;
351 // Will be NULL if the request has been canceled. 356 // Will be NULL if the request has been canceled.
352 DownloadProtectionService* service_; 357 DownloadProtectionService* service_;
358 scoped_refptr<SignatureUtil> signature_util_;
353 scoped_refptr<SafeBrowsingService> sb_service_; 359 scoped_refptr<SafeBrowsingService> sb_service_;
354 const bool pingback_enabled_; 360 const bool pingback_enabled_;
355 bool is_signed_;
356 scoped_ptr<content::URLFetcher> fetcher_; 361 scoped_ptr<content::URLFetcher> fetcher_;
357 362
358 DISALLOW_COPY_AND_ASSIGN(CheckClientDownloadRequest); 363 DISALLOW_COPY_AND_ASSIGN(CheckClientDownloadRequest);
359 }; 364 };
360 365
361 DownloadProtectionService::DownloadProtectionService( 366 DownloadProtectionService::DownloadProtectionService(
362 SafeBrowsingService* sb_service, 367 SafeBrowsingService* sb_service,
363 net::URLRequestContextGetter* request_context_getter) 368 net::URLRequestContextGetter* request_context_getter)
364 : sb_service_(sb_service), 369 : sb_service_(sb_service),
365 request_context_getter_(request_context_getter), 370 request_context_getter_(request_context_getter),
366 enabled_(false) {} 371 enabled_(false),
372 signature_util_(new SignatureUtil()) {}
367 373
368 DownloadProtectionService::~DownloadProtectionService() { 374 DownloadProtectionService::~DownloadProtectionService() {
369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 375 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
370 CancelPendingRequests(); 376 CancelPendingRequests();
371 } 377 }
372 378
373 void DownloadProtectionService::SetEnabled(bool enabled) { 379 void DownloadProtectionService::SetEnabled(bool enabled) {
374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 380 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
375 if (enabled == enabled_) { 381 if (enabled == enabled_) {
376 return; 382 return;
377 } 383 }
378 enabled_ = enabled; 384 enabled_ = enabled;
379 if (!enabled_) { 385 if (!enabled_) {
380 CancelPendingRequests(); 386 CancelPendingRequests();
381 } 387 }
382 } 388 }
383 389
384 void DownloadProtectionService::CheckClientDownload( 390 void DownloadProtectionService::CheckClientDownload(
385 const DownloadProtectionService::DownloadInfo& info, 391 const DownloadProtectionService::DownloadInfo& info,
386 const CheckDownloadCallback& callback) { 392 const CheckDownloadCallback& callback) {
387 scoped_refptr<CheckClientDownloadRequest> request( 393 scoped_refptr<CheckClientDownloadRequest> request(
388 new CheckClientDownloadRequest(info, callback, this, sb_service_)); 394 new CheckClientDownloadRequest(info, callback, this,
395 sb_service_, signature_util_.get()));
389 download_requests_.insert(request); 396 download_requests_.insert(request);
390 request->Start(); 397 request->Start();
391 } 398 }
392 399
393 void DownloadProtectionService::CancelPendingRequests() { 400 void DownloadProtectionService::CancelPendingRequests() {
394 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 401 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
395 for (std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = 402 for (std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it =
396 download_requests_.begin(); 403 download_requests_.begin();
397 it != download_requests_.end(); ++it) { 404 it != download_requests_.end(); ++it) {
398 (*it)->Cancel(); 405 (*it)->Cancel();
399 } 406 }
400 download_requests_.clear(); 407 download_requests_.clear();
401 } 408 }
402 409
403 void DownloadProtectionService::RequestFinished( 410 void DownloadProtectionService::RequestFinished(
404 CheckClientDownloadRequest* request) { 411 CheckClientDownloadRequest* request) {
405 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 412 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
406 std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = 413 std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it =
407 download_requests_.find(request); 414 download_requests_.find(request);
408 DCHECK(it != download_requests_.end()); 415 DCHECK(it != download_requests_.end());
409 download_requests_.erase(*it); 416 download_requests_.erase(*it);
410 } 417 }
411 418
412 } // namespace safe_browsing 419 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698