OLD | NEW |
---|---|
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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
60 public content::URLFetcherDelegate { | 60 public content::URLFetcherDelegate { |
61 public: | 61 public: |
62 CheckClientDownloadRequest(const DownloadInfo& info, | 62 CheckClientDownloadRequest(const DownloadInfo& info, |
63 const CheckDownloadCallback& callback, | 63 const CheckDownloadCallback& callback, |
64 DownloadProtectionService* service, | 64 DownloadProtectionService* service, |
65 SafeBrowsingService* sb_service) | 65 SafeBrowsingService* sb_service) |
66 : info_(info), | 66 : info_(info), |
67 callback_(callback), | 67 callback_(callback), |
68 service_(service), | 68 service_(service), |
69 sb_service_(sb_service), | 69 sb_service_(sb_service), |
70 pingback_enabled_(service_->enabled()) { | 70 pingback_enabled_(service_->enabled()), |
71 is_signed_(false) { | |
71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 72 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
72 } | 73 } |
73 | 74 |
74 void Start() { | 75 void Start() { |
75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
76 // TODO(noelutz): implement some cache to make sure we don't issue the same | 77 // TODO(noelutz): implement some cache to make sure we don't issue the same |
77 // request over and over again if a user downloads the same binary multiple | 78 // request over and over again if a user downloads the same binary multiple |
78 // times. | 79 // times. |
79 if (info_.download_url_chain.empty()) { | 80 if (info_.download_url_chain.empty()) { |
80 RecordStats(REASON_INVALID_URL); | 81 RecordStats(REASON_INVALID_URL); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
155 private: | 156 private: |
156 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; | 157 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; |
157 friend class DeleteTask<CheckClientDownloadRequest>; | 158 friend class DeleteTask<CheckClientDownloadRequest>; |
158 | 159 |
159 virtual ~CheckClientDownloadRequest() { | 160 virtual ~CheckClientDownloadRequest() { |
160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
161 } | 162 } |
162 | 163 |
163 void ExtractFileFeatures() { | 164 void ExtractFileFeatures() { |
164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
165 bool is_signed; | |
166 if (safe_browsing::signature_util::IsSigned(info_.local_file)) { | 166 if (safe_browsing::signature_util::IsSigned(info_.local_file)) { |
167 VLOG(2) << "Downloaded a signed binary: " << info_.local_file.value(); | 167 VLOG(2) << "Downloaded a signed binary: " << info_.local_file.value(); |
168 is_signed = true; | 168 is_signed_ = true; |
169 } else { | 169 } else { |
170 VLOG(2) << "Downloaded an unsigned binary: " << info_.local_file.value(); | 170 VLOG(2) << "Downloaded an unsigned binary: " << info_.local_file.value(); |
171 is_signed = false; | 171 is_signed_ = false; |
172 } | 172 } |
173 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.SignedBinaryDownload", is_signed); | 173 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.SignedBinaryDownload", is_signed_); |
174 | 174 |
175 // TODO(noelutz): DownloadInfo should also contain the IP address of every | 175 // TODO(noelutz): DownloadInfo should also contain the IP address of every |
176 // URL in the redirect chain. We also should check whether the download | 176 // URL in the redirect chain. We also should check whether the download |
177 // URL is hosted on the internal network. | 177 // URL is hosted on the internal network. |
178 BrowserThread::PostTask( | 178 BrowserThread::PostTask( |
179 BrowserThread::IO, | 179 BrowserThread::IO, |
180 FROM_HERE, | 180 FROM_HERE, |
181 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this)); | 181 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this)); |
182 } | 182 } |
183 | 183 |
184 void CheckWhitelists() { | 184 void CheckWhitelists() { |
185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
186 DownloadCheckResultReason reason = REASON_MAX; | 186 DownloadCheckResultReason reason = REASON_MAX; |
187 if (!pingback_enabled_ || !sb_service_.get()) { | 187 if (!sb_service_.get()) { |
188 reason = REASON_SB_DISABLED; | 188 reason = REASON_SB_DISABLED; |
189 } else { | 189 } else { |
190 for (size_t i = 0; i < info_.download_url_chain.size(); ++i) { | 190 for (size_t i = 0; i < info_.download_url_chain.size(); ++i) { |
191 const GURL& url = info_.download_url_chain[i]; | 191 const GURL& url = info_.download_url_chain[i]; |
192 if (url.is_valid() && sb_service_->MatchDownloadWhitelistUrl(url)) { | 192 if (url.is_valid() && sb_service_->MatchDownloadWhitelistUrl(url)) { |
193 reason = REASON_WHITELISTED_URL; | 193 reason = REASON_WHITELISTED_URL; |
194 break; | 194 break; |
195 } | 195 } |
196 } | 196 } |
197 if (info_.referrer_url.is_valid() && | 197 if (info_.referrer_url.is_valid() && reason == REASON_MAX && |
198 sb_service_->MatchDownloadWhitelistUrl(info_.referrer_url)) { | 198 sb_service_->MatchDownloadWhitelistUrl(info_.referrer_url)) { |
199 reason = REASON_WHITELISTED_REFERRER; | 199 reason = REASON_WHITELISTED_REFERRER; |
200 } | 200 } |
201 if (reason != REASON_MAX || is_signed_) { | |
202 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.SignedOrWhitelistedDownload", | |
Brian Ryner
2011/10/28 23:00:59
Should this be UMA_HISTOGRAM_COUNTS given how you'
noelutz
2011/10/28 23:11:24
Done.
| |
203 1); | |
204 } | |
201 } | 205 } |
202 if (reason != REASON_MAX) { | 206 if (reason != REASON_MAX) { |
203 RecordStats(reason); | 207 RecordStats(reason); |
204 PostFinishTask(SAFE); | 208 PostFinishTask(SAFE); |
205 return; | 209 } else if (!pingback_enabled_) { |
210 RecordStats(REASON_SB_DISABLED); | |
211 PostFinishTask(SAFE); | |
212 } else { | |
213 // TODO(noelutz): check signature and CA against whitelist. | |
214 | |
215 // The URLFetcher is owned by the UI thread, so post a message to | |
216 // start the pingback. | |
217 BrowserThread::PostTask( | |
218 BrowserThread::UI, | |
219 FROM_HERE, | |
220 base::Bind(&CheckClientDownloadRequest::SendRequest, this)); | |
206 } | 221 } |
207 | |
208 // TODO(noelutz): check signature and CA against whitelist. | |
209 | |
210 // The URLFetcher is owned by the UI thread, so post a message to | |
211 // start the pingback. | |
212 BrowserThread::PostTask( | |
213 BrowserThread::UI, | |
214 FROM_HERE, | |
215 base::Bind(&CheckClientDownloadRequest::SendRequest, this)); | |
216 } | 222 } |
217 | 223 |
218 void SendRequest() { | 224 void SendRequest() { |
219 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
220 | 226 |
221 // This is our last chance to check whether the request has been canceled | 227 // This is our last chance to check whether the request has been canceled |
222 // before sending it. | 228 // before sending it. |
223 if (!service_) { | 229 if (!service_) { |
230 RecordStats(REASON_REQUEST_CANCELED); | |
224 FinishRequest(SAFE); | 231 FinishRequest(SAFE); |
225 return; | 232 return; |
226 } | 233 } |
227 | 234 |
228 ClientDownloadRequest request; | 235 ClientDownloadRequest request; |
229 request.set_url(info_.download_url_chain.back().spec()); | 236 request.set_url(info_.download_url_chain.back().spec()); |
230 request.mutable_digests()->set_sha256(info_.sha256_hash); | 237 request.mutable_digests()->set_sha256(info_.sha256_hash); |
231 request.set_length(info_.total_bytes); | 238 request.set_length(info_.total_bytes); |
232 for (size_t i = 0; i < info_.download_url_chain.size(); ++i) { | 239 for (size_t i = 0; i < info_.download_url_chain.size(); ++i) { |
233 ClientDownloadRequest::Resource* resource = request.add_resources(); | 240 ClientDownloadRequest::Resource* resource = request.add_resources(); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
282 UMA_HISTOGRAM_ENUMERATION("SBClientDownload.CheckDownloadStats", | 289 UMA_HISTOGRAM_ENUMERATION("SBClientDownload.CheckDownloadStats", |
283 reason, | 290 reason, |
284 REASON_MAX); | 291 REASON_MAX); |
285 } | 292 } |
286 | 293 |
287 DownloadInfo info_; | 294 DownloadInfo info_; |
288 CheckDownloadCallback callback_; | 295 CheckDownloadCallback callback_; |
289 // Will be NULL if the request has been canceled. | 296 // Will be NULL if the request has been canceled. |
290 DownloadProtectionService* service_; | 297 DownloadProtectionService* service_; |
291 scoped_refptr<SafeBrowsingService> sb_service_; | 298 scoped_refptr<SafeBrowsingService> sb_service_; |
292 bool pingback_enabled_; | 299 const bool pingback_enabled_; |
300 bool is_signed_; | |
293 scoped_ptr<content::URLFetcher> fetcher_; | 301 scoped_ptr<content::URLFetcher> fetcher_; |
294 | 302 |
295 DISALLOW_COPY_AND_ASSIGN(CheckClientDownloadRequest); | 303 DISALLOW_COPY_AND_ASSIGN(CheckClientDownloadRequest); |
296 }; | 304 }; |
297 | 305 |
298 DownloadProtectionService::DownloadProtectionService( | 306 DownloadProtectionService::DownloadProtectionService( |
299 SafeBrowsingService* sb_service, | 307 SafeBrowsingService* sb_service, |
300 net::URLRequestContextGetter* request_context_getter) | 308 net::URLRequestContextGetter* request_context_getter) |
301 : sb_service_(sb_service), | 309 : sb_service_(sb_service), |
302 request_context_getter_(request_context_getter), | 310 request_context_getter_(request_context_getter), |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
340 void DownloadProtectionService::RequestFinished( | 348 void DownloadProtectionService::RequestFinished( |
341 CheckClientDownloadRequest* request) { | 349 CheckClientDownloadRequest* request) { |
342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 350 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
343 std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = | 351 std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = |
344 download_requests_.find(request); | 352 download_requests_.find(request); |
345 DCHECK(it != download_requests_.end()); | 353 DCHECK(it != download_requests_.end()); |
346 download_requests_.erase(*it); | 354 download_requests_.erase(*it); |
347 } | 355 } |
348 | 356 |
349 } // namespace safe_browsing | 357 } // namespace safe_browsing |
OLD | NEW |