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

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: Address Noe and Matt's comments 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 = signature_info_.has_certificate_contents();
225 if (is_signed) {
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;
225 } else { 227 } else {
226 VLOG(2) << "Downloaded an unsigned binary: " << info_.local_file.value(); 228 VLOG(2) << "Downloaded an unsigned binary: " << info_.local_file.value();
227 is_signed_ = false;
228 } 229 }
229 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.SignedBinaryDownload", is_signed_); 230 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.SignedBinaryDownload", is_signed);
230 231
231 // TODO(noelutz): DownloadInfo should also contain the IP address of every 232 // TODO(noelutz): DownloadInfo should also contain the IP address of every
232 // URL in the redirect chain. We also should check whether the download 233 // URL in the redirect chain. We also should check whether the download
233 // URL is hosted on the internal network. 234 // URL is hosted on the internal network.
234 BrowserThread::PostTask( 235 BrowserThread::PostTask(
235 BrowserThread::IO, 236 BrowserThread::IO,
236 FROM_HERE, 237 FROM_HERE,
237 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this)); 238 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this));
238 } 239 }
239 240
240 void CheckWhitelists() { 241 void CheckWhitelists() {
241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 242 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
242 DownloadCheckResultReason reason = REASON_MAX; 243 DownloadCheckResultReason reason = REASON_MAX;
243 if (!sb_service_.get()) { 244 if (!sb_service_.get()) {
244 reason = REASON_SB_DISABLED; 245 reason = REASON_SB_DISABLED;
245 } else { 246 } else {
246 for (size_t i = 0; i < info_.download_url_chain.size(); ++i) { 247 for (size_t i = 0; i < info_.download_url_chain.size(); ++i) {
247 const GURL& url = info_.download_url_chain[i]; 248 const GURL& url = info_.download_url_chain[i];
248 if (url.is_valid() && sb_service_->MatchDownloadWhitelistUrl(url)) { 249 if (url.is_valid() && sb_service_->MatchDownloadWhitelistUrl(url)) {
249 reason = REASON_WHITELISTED_URL; 250 reason = REASON_WHITELISTED_URL;
250 break; 251 break;
251 } 252 }
252 } 253 }
253 if (info_.referrer_url.is_valid() && reason == REASON_MAX && 254 if (info_.referrer_url.is_valid() && reason == REASON_MAX &&
254 sb_service_->MatchDownloadWhitelistUrl(info_.referrer_url)) { 255 sb_service_->MatchDownloadWhitelistUrl(info_.referrer_url)) {
255 reason = REASON_WHITELISTED_REFERRER; 256 reason = REASON_WHITELISTED_REFERRER;
256 } 257 }
257 if (reason != REASON_MAX || is_signed_) { 258 if (reason != REASON_MAX || signature_info_.has_certificate_contents()) {
258 UMA_HISTOGRAM_COUNTS("SBClientDownload.SignedOrWhitelistedDownload", 1); 259 UMA_HISTOGRAM_COUNTS("SBClientDownload.SignedOrWhitelistedDownload", 1);
259 } 260 }
260 } 261 }
261 if (reason != REASON_MAX) { 262 if (reason != REASON_MAX) {
262 RecordStats(reason); 263 RecordStats(reason);
263 PostFinishTask(SAFE); 264 PostFinishTask(SAFE);
264 } else if (!pingback_enabled_) { 265 } else if (!pingback_enabled_) {
265 RecordStats(REASON_SB_DISABLED); 266 RecordStats(REASON_SB_DISABLED);
266 PostFinishTask(SAFE); 267 PostFinishTask(SAFE);
267 } else { 268 } else {
(...skipping 29 matching lines...) Expand all
297 if (i == info_.download_url_chain.size() - 1) { 298 if (i == info_.download_url_chain.size() - 1) {
298 // The last URL in the chain is the download URL. 299 // The last URL in the chain is the download URL.
299 resource->set_type(ClientDownloadRequest::DOWNLOAD_URL); 300 resource->set_type(ClientDownloadRequest::DOWNLOAD_URL);
300 resource->set_referrer(info_.referrer_url.spec()); 301 resource->set_referrer(info_.referrer_url.spec());
301 } else { 302 } else {
302 resource->set_type(ClientDownloadRequest::DOWNLOAD_REDIRECT); 303 resource->set_type(ClientDownloadRequest::DOWNLOAD_REDIRECT);
303 } 304 }
304 // TODO(noelutz): fill out the remote IP addresses. 305 // TODO(noelutz): fill out the remote IP addresses.
305 } 306 }
306 request.set_user_initiated(info_.user_initiated); 307 request.set_user_initiated(info_.user_initiated);
308 request.mutable_signature()->CopyFrom(signature_info_);
307 std::string request_data; 309 std::string request_data;
308 if (!request.SerializeToString(&request_data)) { 310 if (!request.SerializeToString(&request_data)) {
309 RecordStats(REASON_INVALID_REQUEST_PROTO); 311 RecordStats(REASON_INVALID_REQUEST_PROTO);
310 FinishRequest(SAFE); 312 FinishRequest(SAFE);
311 return; 313 return;
312 } 314 }
313 315
314 VLOG(2) << "Sending a request for URL: " 316 VLOG(2) << "Sending a request for URL: "
315 << info_.download_url_chain.back(); 317 << info_.download_url_chain.back();
316 fetcher_.reset(content::URLFetcher::Create(0 /* ID used for testing */, 318 fetcher_.reset(content::URLFetcher::Create(0 /* ID used for testing */,
(...skipping 23 matching lines...) Expand all
340 } 342 }
341 } 343 }
342 344
343 void RecordStats(DownloadCheckResultReason reason) { 345 void RecordStats(DownloadCheckResultReason reason) {
344 UMA_HISTOGRAM_ENUMERATION("SBClientDownload.CheckDownloadStats", 346 UMA_HISTOGRAM_ENUMERATION("SBClientDownload.CheckDownloadStats",
345 reason, 347 reason,
346 REASON_MAX); 348 REASON_MAX);
347 } 349 }
348 350
349 DownloadInfo info_; 351 DownloadInfo info_;
352 ClientDownloadRequest_SignatureInfo signature_info_;
350 CheckDownloadCallback callback_; 353 CheckDownloadCallback callback_;
351 // Will be NULL if the request has been canceled. 354 // Will be NULL if the request has been canceled.
352 DownloadProtectionService* service_; 355 DownloadProtectionService* service_;
356 scoped_refptr<SignatureUtil> signature_util_;
353 scoped_refptr<SafeBrowsingService> sb_service_; 357 scoped_refptr<SafeBrowsingService> sb_service_;
354 const bool pingback_enabled_; 358 const bool pingback_enabled_;
355 bool is_signed_;
356 scoped_ptr<content::URLFetcher> fetcher_; 359 scoped_ptr<content::URLFetcher> fetcher_;
357 360
358 DISALLOW_COPY_AND_ASSIGN(CheckClientDownloadRequest); 361 DISALLOW_COPY_AND_ASSIGN(CheckClientDownloadRequest);
359 }; 362 };
360 363
361 DownloadProtectionService::DownloadProtectionService( 364 DownloadProtectionService::DownloadProtectionService(
362 SafeBrowsingService* sb_service, 365 SafeBrowsingService* sb_service,
363 net::URLRequestContextGetter* request_context_getter) 366 net::URLRequestContextGetter* request_context_getter)
364 : sb_service_(sb_service), 367 : sb_service_(sb_service),
365 request_context_getter_(request_context_getter), 368 request_context_getter_(request_context_getter),
366 enabled_(false) {} 369 enabled_(false),
370 signature_util_(new SignatureUtil()) {}
367 371
368 DownloadProtectionService::~DownloadProtectionService() { 372 DownloadProtectionService::~DownloadProtectionService() {
369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
370 CancelPendingRequests(); 374 CancelPendingRequests();
371 } 375 }
372 376
373 void DownloadProtectionService::SetEnabled(bool enabled) { 377 void DownloadProtectionService::SetEnabled(bool enabled) {
374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 378 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
375 if (enabled == enabled_) { 379 if (enabled == enabled_) {
376 return; 380 return;
377 } 381 }
378 enabled_ = enabled; 382 enabled_ = enabled;
379 if (!enabled_) { 383 if (!enabled_) {
380 CancelPendingRequests(); 384 CancelPendingRequests();
381 } 385 }
382 } 386 }
383 387
384 void DownloadProtectionService::CheckClientDownload( 388 void DownloadProtectionService::CheckClientDownload(
385 const DownloadProtectionService::DownloadInfo& info, 389 const DownloadProtectionService::DownloadInfo& info,
386 const CheckDownloadCallback& callback) { 390 const CheckDownloadCallback& callback) {
387 scoped_refptr<CheckClientDownloadRequest> request( 391 scoped_refptr<CheckClientDownloadRequest> request(
388 new CheckClientDownloadRequest(info, callback, this, sb_service_)); 392 new CheckClientDownloadRequest(info, callback, this,
393 sb_service_, signature_util_.get()));
389 download_requests_.insert(request); 394 download_requests_.insert(request);
390 request->Start(); 395 request->Start();
391 } 396 }
392 397
393 void DownloadProtectionService::CancelPendingRequests() { 398 void DownloadProtectionService::CancelPendingRequests() {
394 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 399 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
395 for (std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = 400 for (std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it =
396 download_requests_.begin(); 401 download_requests_.begin();
397 it != download_requests_.end(); ++it) { 402 it != download_requests_.end(); ++it) {
398 (*it)->Cancel(); 403 (*it)->Cancel();
399 } 404 }
400 download_requests_.clear(); 405 download_requests_.clear();
401 } 406 }
402 407
403 void DownloadProtectionService::RequestFinished( 408 void DownloadProtectionService::RequestFinished(
404 CheckClientDownloadRequest* request) { 409 CheckClientDownloadRequest* request) {
405 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 410 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
406 std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = 411 std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it =
407 download_requests_.find(request); 412 download_requests_.find(request);
408 DCHECK(it != download_requests_.end()); 413 DCHECK(it != download_requests_.end());
409 download_requests_.erase(*it); 414 download_requests_.erase(*it);
410 } 415 }
411 416
412 } // namespace safe_browsing 417 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698