1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/safe_browsing/download_protection_service.h"
10 #include "base/base_paths.h"
11 #include "base/bind.h"
12 #include "base/callback.h"
13 #include "base/file_util.h"
14 #include "base/files/file_path.h"
15 #include "base/files/scoped_temp_dir.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/message_loop/message_loop.h"
19 #include "base/path_service.h"
20 #include "base/run_loop.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/threading/sequenced_worker_pool.h"
23 #include "chrome/browser/safe_browsing/database_manager.h"
24 #include "chrome/browser/safe_browsing/download_feedback_service.h"
25 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
26 #include "chrome/browser/safe_browsing/signature_util.h"
27 #include "chrome/common/safe_browsing/csd.pb.h"
28 #include "content/public/test/mock_download_item.h"
29 #include "content/public/test/test_browser_thread_bundle.h"
30 #include "content/public/test/test_utils.h"
31 #include "net/cert/x509_certificate.h"
32 #include "net/http/http_status_code.h"
33 #include "net/url_request/test_url_fetcher_factory.h"
34 #include "net/url_request/url_fetcher_delegate.h"
35 #include "net/url_request/url_request_status.h"
36 #include "testing/gmock/include/gmock/gmock.h"
37 #include "testing/gtest/include/gtest/gtest.h"
38 #include "third_party/zlib/google/zip.h"
41 using ::testing::Assign
;
42 using ::testing::ContainerEq
;
43 using ::testing::DoAll
;
44 using ::testing::ElementsAre
;
45 using ::testing::Mock
;
46 using ::testing::NotNull
;
47 using ::testing::Return
;
48 using ::testing::ReturnRef
;
49 using ::testing::SaveArg
;
50 using ::testing::StrictMock
;
52 using base::MessageLoop
;
53 using content::BrowserThread
;
54 namespace safe_browsing
{
56 // A SafeBrowsingDatabaseManager implementation that returns a fixed result for
58 class MockSafeBrowsingDatabaseManager
: public SafeBrowsingDatabaseManager
{
60 explicit MockSafeBrowsingDatabaseManager(SafeBrowsingService
* service
)
61 : SafeBrowsingDatabaseManager(service
) { }
63 MOCK_METHOD1(MatchDownloadWhitelistUrl
, bool(const GURL
&));
64 MOCK_METHOD1(MatchDownloadWhitelistString
, bool(const std::string
&));
65 MOCK_METHOD2(CheckDownloadUrl
, bool(
66 const std::vector
<GURL
>& url_chain
,
67 SafeBrowsingDatabaseManager::Client
* client
));
70 virtual ~MockSafeBrowsingDatabaseManager() {}
71 DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingDatabaseManager
);
74 class FakeSafeBrowsingService
: public SafeBrowsingService
{
76 FakeSafeBrowsingService() { }
78 // Returned pointer has the same lifespan as the database_manager_ refcounted
80 MockSafeBrowsingDatabaseManager
* mock_database_manager() {
81 return mock_database_manager_
;
85 virtual ~FakeSafeBrowsingService() { }
87 virtual SafeBrowsingDatabaseManager
* CreateDatabaseManager() OVERRIDE
{
88 mock_database_manager_
= new MockSafeBrowsingDatabaseManager(this);
89 return mock_database_manager_
;
93 MockSafeBrowsingDatabaseManager
* mock_database_manager_
;
95 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService
);
98 class MockSignatureUtil
: public SignatureUtil
{
100 MockSignatureUtil() {}
101 MOCK_METHOD2(CheckSignature
, void (const base::FilePath
&,
102 ClientDownloadRequest_SignatureInfo
*));
105 virtual ~MockSignatureUtil() {}
108 DISALLOW_COPY_AND_ASSIGN(MockSignatureUtil
);
112 ACTION_P(SetCertificateContents
, contents
) {
113 arg1
->add_certificate_chain()->add_element()->set_certificate(contents
);
116 ACTION_P(TrustSignature
, certificate_file
) {
117 arg1
->set_trusted(true);
118 // Add a certificate chain. Note that we add the certificate twice so that
119 // it appears as its own issuer.
120 std::string cert_data
;
121 ASSERT_TRUE(base::ReadFileToString(certificate_file
, &cert_data
));
122 ClientDownloadRequest_CertificateChain
* chain
=
123 arg1
->add_certificate_chain();
124 chain
->add_element()->set_certificate(cert_data
);
125 chain
->add_element()->set_certificate(cert_data
);
128 // We can't call OnSafeBrowsingResult directly because SafeBrowsingCheck does
129 // not have any copy constructor which means it can't be stored in a callback
130 // easily. Note: check will be deleted automatically when the callback is
132 void OnSafeBrowsingResult(
133 SafeBrowsingDatabaseManager::SafeBrowsingCheck
* check
) {
134 check
->client
->OnSafeBrowsingResult(*check
);
137 ACTION_P(CheckDownloadUrlDone
, threat_type
) {
138 SafeBrowsingDatabaseManager::SafeBrowsingCheck
* check
=
139 new SafeBrowsingDatabaseManager::SafeBrowsingCheck(
141 std::vector
<SBFullHash
>(),
143 safe_browsing_util::BINURL
,
144 std::vector
<SBThreatType
>(1, SB_THREAT_TYPE_BINARY_MALWARE_URL
));
145 for (size_t i
= 0; i
< check
->url_results
.size(); ++i
)
146 check
->url_results
[i
] = threat_type
;
147 BrowserThread::PostTask(BrowserThread::IO
,
149 base::Bind(&OnSafeBrowsingResult
,
150 base::Owned(check
)));
153 class DownloadProtectionServiceTest
: public testing::Test
{
155 DownloadProtectionServiceTest()
156 : test_browser_thread_bundle_(
157 content::TestBrowserThreadBundle::IO_MAINLOOP
) {
159 virtual void SetUp() {
160 // Start real threads for the IO and File threads so that the DCHECKs
161 // to test that we're on the correct thread work.
162 sb_service_
= new StrictMock
<FakeSafeBrowsingService
>();
163 sb_service_
->Initialize();
164 signature_util_
= new StrictMock
<MockSignatureUtil
>();
165 download_service_
= sb_service_
->download_protection_service();
166 download_service_
->signature_util_
= signature_util_
;
167 download_service_
->SetEnabled(true);
168 base::RunLoop().RunUntilIdle();
171 base::FilePath source_path
;
172 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT
, &source_path
));
173 testdata_path_
= source_path
174 .AppendASCII("chrome")
177 .AppendASCII("safe_browsing")
178 .AppendASCII("download_protection");
181 virtual void TearDown() {
182 sb_service_
->ShutDown();
183 // Flush all of the thread message loops to ensure that there are no
184 // tasks currently running.
185 FlushThreadMessageLoops();
189 bool RequestContainsResource(const ClientDownloadRequest
& request
,
190 ClientDownloadRequest::ResourceType type
,
191 const std::string
& url
,
192 const std::string
& referrer
) {
193 for (int i
= 0; i
< request
.resources_size(); ++i
) {
194 if (request
.resources(i
).url() == url
&&
195 request
.resources(i
).type() == type
&&
196 (referrer
.empty() || request
.resources(i
).referrer() == referrer
)) {
203 // At this point we only set the server IP for the download itself.
204 bool RequestContainsServerIp(const ClientDownloadRequest
& request
,
205 const std::string
& remote_address
) {
206 for (int i
= 0; i
< request
.resources_size(); ++i
) {
207 // We want the last DOWNLOAD_URL in the chain.
208 if (request
.resources(i
).type() == ClientDownloadRequest::DOWNLOAD_URL
&&
209 (i
+ 1 == request
.resources_size() ||
210 request
.resources(i
+ 1).type() !=
211 ClientDownloadRequest::DOWNLOAD_URL
)) {
212 return remote_address
== request
.resources(i
).remote_ip();
218 // Flushes any pending tasks in the message loops of all threads.
219 void FlushThreadMessageLoops() {
220 BrowserThread::GetBlockingPool()->FlushForTesting();
221 FlushMessageLoop(BrowserThread::IO
);
222 base::RunLoop().RunUntilIdle();
225 // Proxy for private method.
226 static void GetCertificateWhitelistStrings(
227 const net::X509Certificate
& certificate
,
228 const net::X509Certificate
& issuer
,
229 std::vector
<std::string
>* whitelist_strings
) {
230 DownloadProtectionService::GetCertificateWhitelistStrings(
231 certificate
, issuer
, whitelist_strings
);
234 // Reads a single PEM-encoded certificate from the testdata directory.
235 // Returns NULL on failure.
236 scoped_refptr
<net::X509Certificate
> ReadTestCertificate(
237 const std::string
& filename
) {
238 std::string cert_data
;
239 if (!base::ReadFileToString(testdata_path_
.AppendASCII(filename
),
243 net::CertificateList certs
=
244 net::X509Certificate::CreateCertificateListFromBytes(
247 net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE
);
248 return certs
.empty() ? NULL
: certs
[0];
252 // Helper functions for FlushThreadMessageLoops.
253 void RunAllPendingAndQuitUI() {
254 base::MessageLoop::current()->RunUntilIdle();
255 BrowserThread::PostTask(
258 base::Bind(&DownloadProtectionServiceTest::QuitMessageLoop
,
259 base::Unretained(this)));
262 void QuitMessageLoop() {
263 base::MessageLoop::current()->Quit();
266 void PostRunMessageLoopTask(BrowserThread::ID thread
) {
267 BrowserThread::PostTask(
270 base::Bind(&DownloadProtectionServiceTest::RunAllPendingAndQuitUI
,
271 base::Unretained(this)));
274 void FlushMessageLoop(BrowserThread::ID thread
) {
275 BrowserThread::PostTask(
278 base::Bind(&DownloadProtectionServiceTest::PostRunMessageLoopTask
,
279 base::Unretained(this), thread
));
280 MessageLoop::current()->Run();
284 void CheckDoneCallback(
285 DownloadProtectionService::DownloadCheckResult result
) {
288 MessageLoop::current()->Quit();
291 void SyncCheckDoneCallback(
292 DownloadProtectionService::DownloadCheckResult result
) {
297 void SendURLFetchComplete(net::TestURLFetcher
* fetcher
) {
298 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
301 testing::AssertionResult
IsResult(
302 DownloadProtectionService::DownloadCheckResult expected
) {
304 return testing::AssertionFailure() << "No result";
306 return result_
== expected
?
307 testing::AssertionSuccess() :
308 testing::AssertionFailure() << "Expected " << expected
<<
313 scoped_refptr
<FakeSafeBrowsingService
> sb_service_
;
314 scoped_refptr
<MockSignatureUtil
> signature_util_
;
315 DownloadProtectionService
* download_service_
;
316 DownloadProtectionService::DownloadCheckResult result_
;
318 content::TestBrowserThreadBundle test_browser_thread_bundle_
;
319 content::InProcessUtilityThreadHelper in_process_utility_thread_helper_
;
320 base::FilePath testdata_path_
;
323 TEST_F(DownloadProtectionServiceTest
, CheckClientDownloadInvalidUrl
) {
324 base::FilePath
a_tmp(FILE_PATH_LITERAL("a.tmp"));
325 base::FilePath
a_exe(FILE_PATH_LITERAL("a.exe"));
326 std::vector
<GURL
> url_chain
;
327 GURL
referrer("http://www.google.com/");
329 content::MockDownloadItem item
;
330 EXPECT_CALL(item
, AddObserver(_
));
331 EXPECT_CALL(item
, RemoveObserver(_
));
332 EXPECT_CALL(item
, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp
));
333 EXPECT_CALL(item
, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe
));
334 EXPECT_CALL(item
, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain
));
335 EXPECT_CALL(item
, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer
));
336 download_service_
->CheckClientDownload(
338 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
339 base::Unretained(this)));
340 MessageLoop::current()->Run();
341 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
342 Mock::VerifyAndClearExpectations(&item
);
344 url_chain
.push_back(GURL("file://www.google.com/"));
345 EXPECT_CALL(item
, AddObserver(_
));
346 EXPECT_CALL(item
, RemoveObserver(_
));
347 EXPECT_CALL(item
, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp
));
348 EXPECT_CALL(item
, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe
));
349 EXPECT_CALL(item
, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain
));
350 EXPECT_CALL(item
, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer
));
351 download_service_
->CheckClientDownload(
353 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
354 base::Unretained(this)));
355 MessageLoop::current()->Run();
356 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
359 TEST_F(DownloadProtectionServiceTest
, CheckClientDownloadWhitelistedUrl
) {
360 // Response to any requests will be DANGEROUS.
361 ClientDownloadResponse response
;
362 response
.set_verdict(ClientDownloadResponse::DANGEROUS
);
363 net::FakeURLFetcherFactory
factory(NULL
);
364 factory
.SetFakeResponse(
365 DownloadProtectionService::GetDownloadRequestUrl(),
366 response
.SerializeAsString(),
367 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
369 std::string hash
= "hash";
370 base::FilePath
a_tmp(FILE_PATH_LITERAL("a.tmp"));
371 base::FilePath
a_exe(FILE_PATH_LITERAL("a.exe"));
372 std::vector
<GURL
> url_chain
;
375 content::MockDownloadItem item
;
376 EXPECT_CALL(item
, AddObserver(_
)).Times(4);
377 EXPECT_CALL(item
, RemoveObserver(_
)).Times(4);
378 EXPECT_CALL(item
, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp
));
379 EXPECT_CALL(item
, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe
));
380 EXPECT_CALL(item
, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain
));
381 EXPECT_CALL(item
, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer
));
382 EXPECT_CALL(item
, GetHash()).WillRepeatedly(ReturnRef(hash
));
383 EXPECT_CALL(item
, GetReceivedBytes()).WillRepeatedly(Return(100));
384 EXPECT_CALL(item
, HasUserGesture()).WillRepeatedly(Return(true));
385 EXPECT_CALL(item
, GetRemoteAddress()).WillRepeatedly(Return(""));
386 EXPECT_CALL(*signature_util_
.get(), CheckSignature(a_tmp
, _
)).Times(4);
388 // We should not get whilelist checks for other URLs than specified below.
389 EXPECT_CALL(*sb_service_
->mock_database_manager(),
390 MatchDownloadWhitelistUrl(_
)).Times(0);
391 EXPECT_CALL(*sb_service_
->mock_database_manager(),
392 MatchDownloadWhitelistUrl(GURL("http://www.evil.com/bla.exe")))
393 .WillRepeatedly(Return(false));
394 EXPECT_CALL(*sb_service_
->mock_database_manager(),
395 MatchDownloadWhitelistUrl(GURL("http://www.google.com/a.exe")))
396 .WillRepeatedly(Return(true));
398 // With no referrer and just the bad url, should be marked DANGEROUS.
399 url_chain
.push_back(GURL("http://www.evil.com/bla.exe"));
400 download_service_
->CheckClientDownload(
402 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
403 base::Unretained(this)));
404 MessageLoop::current()->Run();
406 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS
));
408 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
411 // Check that the referrer is not matched against the whitelist.
412 referrer
= GURL("http://www.google.com/");
413 download_service_
->CheckClientDownload(
415 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
416 base::Unretained(this)));
417 MessageLoop::current()->Run();
419 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS
));
421 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
424 // Redirect from a site shouldn't be checked either.
425 url_chain
.insert(url_chain
.begin(), GURL("http://www.google.com/redirect"));
426 download_service_
->CheckClientDownload(
428 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
429 base::Unretained(this)));
430 MessageLoop::current()->Run();
432 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS
));
434 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
437 // Only if the final url is whitelisted should it be SAFE.
438 url_chain
.push_back(GURL("http://www.google.com/a.exe"));
439 download_service_
->CheckClientDownload(
441 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
442 base::Unretained(this)));
443 MessageLoop::current()->Run();
444 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
447 TEST_F(DownloadProtectionServiceTest
, CheckClientDownloadFetchFailed
) {
448 net::FakeURLFetcherFactory
factory(NULL
);
449 // HTTP request will fail.
450 factory
.SetFakeResponse(
451 DownloadProtectionService::GetDownloadRequestUrl(), std::string(),
452 net::HTTP_INTERNAL_SERVER_ERROR
, net::URLRequestStatus::FAILED
);
454 base::FilePath
a_tmp(FILE_PATH_LITERAL("a.tmp"));
455 base::FilePath
a_exe(FILE_PATH_LITERAL("a.exe"));
456 std::vector
<GURL
> url_chain
;
457 url_chain
.push_back(GURL("http://www.evil.com/a.exe"));
458 GURL
referrer("http://www.google.com/");
459 std::string hash
= "hash";
461 content::MockDownloadItem item
;
462 EXPECT_CALL(item
, AddObserver(_
));
463 EXPECT_CALL(item
, RemoveObserver(_
));
464 EXPECT_CALL(item
, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp
));
465 EXPECT_CALL(item
, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe
));
466 EXPECT_CALL(item
, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain
));
467 EXPECT_CALL(item
, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer
));
468 EXPECT_CALL(item
, GetHash()).WillRepeatedly(ReturnRef(hash
));
469 EXPECT_CALL(item
, GetReceivedBytes()).WillRepeatedly(Return(100));
470 EXPECT_CALL(item
, HasUserGesture()).WillRepeatedly(Return(true));
471 EXPECT_CALL(item
, GetRemoteAddress()).WillRepeatedly(Return(""));
473 EXPECT_CALL(*sb_service_
->mock_database_manager(),
474 MatchDownloadWhitelistUrl(_
))
475 .WillRepeatedly(Return(false));
476 EXPECT_CALL(*signature_util_
.get(), CheckSignature(a_tmp
, _
));
478 download_service_
->CheckClientDownload(
480 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
481 base::Unretained(this)));
482 MessageLoop::current()->Run();
483 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
486 TEST_F(DownloadProtectionServiceTest
, CheckClientDownloadSuccess
) {
487 ClientDownloadResponse response
;
488 response
.set_verdict(ClientDownloadResponse::SAFE
);
489 net::FakeURLFetcherFactory
factory(NULL
);
490 // Empty response means SAFE.
491 factory
.SetFakeResponse(
492 DownloadProtectionService::GetDownloadRequestUrl(),
493 response
.SerializeAsString(),
494 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
496 base::FilePath
a_tmp(FILE_PATH_LITERAL("a.tmp"));
497 base::FilePath
a_exe(FILE_PATH_LITERAL("a.exe"));
498 std::vector
<GURL
> url_chain
;
499 url_chain
.push_back(GURL("http://www.evil.com/a.exe"));
500 GURL
referrer("http://www.google.com/");
501 std::string hash
= "hash";
503 content::MockDownloadItem item
;
504 EXPECT_CALL(item
, AddObserver(_
)).Times(6);
505 EXPECT_CALL(item
, RemoveObserver(_
)).Times(6);
506 EXPECT_CALL(item
, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp
));
507 EXPECT_CALL(item
, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe
));
508 EXPECT_CALL(item
, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain
));
509 EXPECT_CALL(item
, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer
));
510 EXPECT_CALL(item
, GetHash()).WillRepeatedly(ReturnRef(hash
));
511 EXPECT_CALL(item
, GetReceivedBytes()).WillRepeatedly(Return(100));
512 EXPECT_CALL(item
, HasUserGesture()).WillRepeatedly(Return(true));
513 EXPECT_CALL(item
, GetRemoteAddress()).WillRepeatedly(Return(""));
515 EXPECT_CALL(*sb_service_
->mock_database_manager(),
516 MatchDownloadWhitelistUrl(_
))
517 .WillRepeatedly(Return(false));
518 EXPECT_CALL(*signature_util_
.get(), CheckSignature(a_tmp
, _
)).Times(6);
520 download_service_
->CheckClientDownload(
522 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
523 base::Unretained(this)));
524 MessageLoop::current()->Run();
525 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
527 // Invalid response should be safe too.
529 factory
.SetFakeResponse(
530 DownloadProtectionService::GetDownloadRequestUrl(),
531 response
.SerializePartialAsString(),
532 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
534 download_service_
->CheckClientDownload(
536 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
537 base::Unretained(this)));
538 MessageLoop::current()->Run();
539 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
540 std::string feedback_ping
;
541 std::string feedback_response
;
542 EXPECT_FALSE(DownloadFeedbackService::GetPingsForDownloadForTesting(
543 item
, &feedback_ping
, &feedback_response
));
545 // If the response is dangerous the result should also be marked as dangerous.
546 response
.set_verdict(ClientDownloadResponse::DANGEROUS
);
547 factory
.SetFakeResponse(
548 DownloadProtectionService::GetDownloadRequestUrl(),
549 response
.SerializeAsString(),
550 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
552 download_service_
->CheckClientDownload(
554 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
555 base::Unretained(this)));
556 MessageLoop::current()->Run();
557 EXPECT_FALSE(DownloadFeedbackService::GetPingsForDownloadForTesting(
558 item
, &feedback_ping
, &feedback_response
));
560 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS
));
562 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
565 // If the response is uncommon the result should also be marked as uncommon.
566 response
.set_verdict(ClientDownloadResponse::UNCOMMON
);
567 factory
.SetFakeResponse(
568 DownloadProtectionService::GetDownloadRequestUrl(),
569 response
.SerializeAsString(),
570 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
572 download_service_
->CheckClientDownload(
574 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
575 base::Unretained(this)));
576 MessageLoop::current()->Run();
578 EXPECT_TRUE(IsResult(DownloadProtectionService::UNCOMMON
));
579 EXPECT_TRUE(DownloadFeedbackService::GetPingsForDownloadForTesting(
580 item
, &feedback_ping
, &feedback_response
));
581 ClientDownloadRequest decoded_request
;
582 EXPECT_TRUE(decoded_request
.ParseFromString(feedback_ping
));
583 EXPECT_EQ(url_chain
.back().spec(), decoded_request
.url());
584 EXPECT_EQ(response
.SerializeAsString(), feedback_response
);
586 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
589 // If the response is dangerous_host the result should also be marked as
591 response
.set_verdict(ClientDownloadResponse::DANGEROUS_HOST
);
592 factory
.SetFakeResponse(
593 DownloadProtectionService::GetDownloadRequestUrl(),
594 response
.SerializeAsString(),
595 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
597 download_service_
->CheckClientDownload(
599 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
600 base::Unretained(this)));
601 MessageLoop::current()->Run();
603 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS_HOST
));
604 EXPECT_TRUE(DownloadFeedbackService::GetPingsForDownloadForTesting(
605 item
, &feedback_ping
, &feedback_response
));
606 EXPECT_EQ(response
.SerializeAsString(), feedback_response
);
608 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
611 // If the response is POTENTIALLY_UNWANTED the result should also be marked as
612 // POTENTIALLY_UNWANTED.
613 response
.set_verdict(ClientDownloadResponse::POTENTIALLY_UNWANTED
);
614 factory
.SetFakeResponse(
615 DownloadProtectionService::GetDownloadRequestUrl(),
616 response
.SerializeAsString(),
617 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
619 download_service_
->CheckClientDownload(
621 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
622 base::Unretained(this)));
623 MessageLoop::current()->Run();
625 EXPECT_TRUE(IsResult(DownloadProtectionService::POTENTIALLY_UNWANTED
));
627 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
631 TEST_F(DownloadProtectionServiceTest
, CheckClientDownloadHTTPS
) {
632 ClientDownloadResponse response
;
633 response
.set_verdict(ClientDownloadResponse::DANGEROUS
);
634 net::FakeURLFetcherFactory
factory(NULL
);
635 factory
.SetFakeResponse(
636 DownloadProtectionService::GetDownloadRequestUrl(),
637 response
.SerializeAsString(),
638 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
640 base::FilePath
a_tmp(FILE_PATH_LITERAL("a.tmp"));
641 base::FilePath
a_exe(FILE_PATH_LITERAL("a.exe"));
642 std::vector
<GURL
> url_chain
;
643 url_chain
.push_back(GURL("http://www.evil.com/a.exe"));
644 GURL
referrer("http://www.google.com/");
645 std::string hash
= "hash";
647 content::MockDownloadItem item
;
648 EXPECT_CALL(item
, AddObserver(_
)).Times(1);
649 EXPECT_CALL(item
, RemoveObserver(_
)).Times(1);
650 EXPECT_CALL(item
, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp
));
651 EXPECT_CALL(item
, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe
));
652 EXPECT_CALL(item
, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain
));
653 EXPECT_CALL(item
, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer
));
654 EXPECT_CALL(item
, GetHash()).WillRepeatedly(ReturnRef(hash
));
655 EXPECT_CALL(item
, GetReceivedBytes()).WillRepeatedly(Return(100));
656 EXPECT_CALL(item
, HasUserGesture()).WillRepeatedly(Return(true));
657 EXPECT_CALL(item
, GetRemoteAddress()).WillRepeatedly(Return(""));
659 EXPECT_CALL(*sb_service_
->mock_database_manager(),
660 MatchDownloadWhitelistUrl(_
))
661 .WillRepeatedly(Return(false));
662 EXPECT_CALL(*signature_util_
.get(), CheckSignature(a_tmp
, _
)).Times(1);
664 download_service_
->CheckClientDownload(
666 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
667 base::Unretained(this)));
668 MessageLoop::current()->Run();
670 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS
));
672 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
676 TEST_F(DownloadProtectionServiceTest
, CheckClientDownloadZip
) {
677 ClientDownloadResponse response
;
678 response
.set_verdict(ClientDownloadResponse::SAFE
);
679 net::FakeURLFetcherFactory
factory(NULL
);
680 // Empty response means SAFE.
681 factory
.SetFakeResponse(
682 DownloadProtectionService::GetDownloadRequestUrl(),
683 response
.SerializeAsString(),
684 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
686 base::ScopedTempDir download_dir
;
687 ASSERT_TRUE(download_dir
.CreateUniqueTempDir());
689 base::FilePath
a_tmp(download_dir
.path().Append(FILE_PATH_LITERAL("a.tmp")));
690 base::FilePath
a_zip(FILE_PATH_LITERAL("a.zip"));
691 std::vector
<GURL
> url_chain
;
692 url_chain
.push_back(GURL("http://www.evil.com/a.zip"));
693 GURL
referrer("http://www.google.com/");
694 std::string hash
= "hash";
696 content::MockDownloadItem item
;
697 EXPECT_CALL(item
, AddObserver(_
)).Times(3);
698 EXPECT_CALL(item
, RemoveObserver(_
)).Times(3);
699 EXPECT_CALL(item
, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp
));
700 EXPECT_CALL(item
, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_zip
));
701 EXPECT_CALL(item
, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain
));
702 EXPECT_CALL(item
, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer
));
703 EXPECT_CALL(item
, GetHash()).WillRepeatedly(ReturnRef(hash
));
704 EXPECT_CALL(item
, GetReceivedBytes()).WillRepeatedly(Return(100));
705 EXPECT_CALL(item
, HasUserGesture()).WillRepeatedly(Return(true));
706 EXPECT_CALL(item
, GetRemoteAddress()).WillRepeatedly(Return(""));
708 // Write out a zip archive to the temporary file. In this case, it
709 // only contains a text file.
710 base::ScopedTempDir zip_source_dir
;
711 ASSERT_TRUE(zip_source_dir
.CreateUniqueTempDir());
712 std::string file_contents
= "dummy file";
713 ASSERT_EQ(static_cast<int>(file_contents
.size()), file_util::WriteFile(
714 zip_source_dir
.path().Append(FILE_PATH_LITERAL("file.txt")),
715 file_contents
.data(), file_contents
.size()));
716 ASSERT_TRUE(zip::Zip(zip_source_dir
.path(), a_tmp
, false));
718 download_service_
->CheckClientDownload(
720 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
721 base::Unretained(this)));
722 MessageLoop::current()->Run();
723 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
724 Mock::VerifyAndClearExpectations(sb_service_
.get());
725 Mock::VerifyAndClearExpectations(signature_util_
.get());
727 // Now check with an executable in the zip file as well.
728 ASSERT_EQ(static_cast<int>(file_contents
.size()), file_util::WriteFile(
729 zip_source_dir
.path().Append(FILE_PATH_LITERAL("file.exe")),
730 file_contents
.data(), file_contents
.size()));
731 ASSERT_TRUE(zip::Zip(zip_source_dir
.path(), a_tmp
, false));
733 EXPECT_CALL(*sb_service_
->mock_database_manager(),
734 MatchDownloadWhitelistUrl(_
))
735 .WillRepeatedly(Return(false));
737 download_service_
->CheckClientDownload(
739 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
740 base::Unretained(this)));
741 MessageLoop::current()->Run();
742 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
743 Mock::VerifyAndClearExpectations(signature_util_
.get());
745 // If the response is dangerous the result should also be marked as
747 response
.set_verdict(ClientDownloadResponse::DANGEROUS
);
748 factory
.SetFakeResponse(
749 DownloadProtectionService::GetDownloadRequestUrl(),
750 response
.SerializeAsString(),
751 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
753 download_service_
->CheckClientDownload(
755 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
756 base::Unretained(this)));
757 MessageLoop::current()->Run();
759 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS
));
761 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
763 Mock::VerifyAndClearExpectations(signature_util_
.get());
766 TEST_F(DownloadProtectionServiceTest
, CheckClientDownloadCorruptZip
) {
767 base::ScopedTempDir download_dir
;
768 ASSERT_TRUE(download_dir
.CreateUniqueTempDir());
770 base::FilePath
a_tmp(download_dir
.path().Append(FILE_PATH_LITERAL("a.tmp")));
771 base::FilePath
a_zip(FILE_PATH_LITERAL("a.zip"));
772 std::vector
<GURL
> url_chain
;
773 url_chain
.push_back(GURL("http://www.evil.com/a.zip"));
774 GURL
referrer("http://www.google.com/");
775 std::string hash
= "hash";
777 content::MockDownloadItem item
;
778 EXPECT_CALL(item
, AddObserver(_
)).Times(1);
779 EXPECT_CALL(item
, RemoveObserver(_
)).Times(1);
780 EXPECT_CALL(item
, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp
));
781 EXPECT_CALL(item
, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_zip
));
782 EXPECT_CALL(item
, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain
));
783 EXPECT_CALL(item
, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer
));
784 EXPECT_CALL(item
, GetHash()).WillRepeatedly(ReturnRef(hash
));
785 EXPECT_CALL(item
, GetReceivedBytes()).WillRepeatedly(Return(100));
786 EXPECT_CALL(item
, HasUserGesture()).WillRepeatedly(Return(true));
787 EXPECT_CALL(item
, GetRemoteAddress()).WillRepeatedly(Return(""));
789 std::string file_contents
= "corrupt zip file";
790 ASSERT_EQ(static_cast<int>(file_contents
.size()), file_util::WriteFile(
791 a_tmp
, file_contents
.data(), file_contents
.size()));
793 download_service_
->CheckClientDownload(
795 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
796 base::Unretained(this)));
797 MessageLoop::current()->Run();
798 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
799 Mock::VerifyAndClearExpectations(sb_service_
.get());
800 Mock::VerifyAndClearExpectations(signature_util_
.get());
803 TEST_F(DownloadProtectionServiceTest
, CheckClientCrxDownloadSuccess
) {
804 ClientDownloadResponse response
;
805 // Even if the server verdict is dangerous we should return SAFE because
806 // DownloadProtectionService::IsSupportedDownload() will return false
807 // for crx downloads.
808 response
.set_verdict(ClientDownloadResponse::DANGEROUS
);
809 net::FakeURLFetcherFactory
factory(NULL
);
810 // Empty response means SAFE.
811 factory
.SetFakeResponse(
812 DownloadProtectionService::GetDownloadRequestUrl(),
813 response
.SerializeAsString(),
814 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
816 base::FilePath
a_tmp(FILE_PATH_LITERAL("a.tmp"));
817 base::FilePath
a_crx(FILE_PATH_LITERAL("a.crx"));
818 std::vector
<GURL
> url_chain
;
819 url_chain
.push_back(GURL("http://www.evil.com/a.crx"));
820 GURL
referrer("http://www.google.com/");
821 std::string hash
= "hash";
823 content::MockDownloadItem item
;
824 EXPECT_CALL(item
, AddObserver(_
)).Times(1);
825 EXPECT_CALL(item
, RemoveObserver(_
)).Times(1);
826 EXPECT_CALL(item
, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp
));
827 EXPECT_CALL(item
, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_crx
));
828 EXPECT_CALL(item
, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain
));
829 EXPECT_CALL(item
, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer
));
830 EXPECT_CALL(item
, GetHash()).WillRepeatedly(ReturnRef(hash
));
831 EXPECT_CALL(item
, GetReceivedBytes()).WillRepeatedly(Return(100));
832 EXPECT_CALL(item
, HasUserGesture()).WillRepeatedly(Return(true));
833 EXPECT_CALL(item
, GetRemoteAddress()).WillRepeatedly(Return(""));
835 EXPECT_CALL(*sb_service_
->mock_database_manager(),
836 MatchDownloadWhitelistUrl(_
))
837 .WillRepeatedly(Return(false));
838 EXPECT_CALL(*signature_util_
.get(), CheckSignature(a_tmp
, _
)).Times(1);
840 EXPECT_FALSE(download_service_
->IsSupportedDownload(item
, a_crx
));
841 download_service_
->CheckClientDownload(
843 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
844 base::Unretained(this)));
845 MessageLoop::current()->Run();
846 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
849 TEST_F(DownloadProtectionServiceTest
, CheckClientDownloadValidateRequest
) {
850 net::TestURLFetcherFactory factory
;
852 base::FilePath
tmp_path(FILE_PATH_LITERAL("bla.tmp"));
853 base::FilePath
final_path(FILE_PATH_LITERAL("bla.exe"));
854 std::vector
<GURL
> url_chain
;
855 url_chain
.push_back(GURL("http://www.google.com/"));
856 url_chain
.push_back(GURL("http://www.google.com/bla.exe"));
857 GURL
referrer("http://www.google.com/");
858 std::string hash
= "hash";
859 std::string remote_address
= "10.11.12.13";
861 content::MockDownloadItem item
;
862 EXPECT_CALL(item
, AddObserver(_
)).Times(1);
863 EXPECT_CALL(item
, RemoveObserver(_
)).Times(1);
864 EXPECT_CALL(item
, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path
));
865 EXPECT_CALL(item
, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path
));
866 EXPECT_CALL(item
, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain
));
867 EXPECT_CALL(item
, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer
));
868 EXPECT_CALL(item
, GetHash()).WillRepeatedly(ReturnRef(hash
));
869 EXPECT_CALL(item
, GetReceivedBytes()).WillRepeatedly(Return(100));
870 EXPECT_CALL(item
, HasUserGesture()).WillRepeatedly(Return(true));
871 EXPECT_CALL(item
, GetRemoteAddress()).WillRepeatedly(Return(remote_address
));
873 EXPECT_CALL(*sb_service_
->mock_database_manager(),
874 MatchDownloadWhitelistUrl(_
))
875 .WillRepeatedly(Return(false));
876 EXPECT_CALL(*signature_util_
.get(), CheckSignature(tmp_path
, _
))
877 .WillOnce(SetCertificateContents("dummy cert data"));
878 download_service_
->CheckClientDownload(
880 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
881 base::Unretained(this)));
884 // SendRequest is not called. Wait for FinishRequest to call our callback.
885 MessageLoop::current()->Run();
886 net::TestURLFetcher
* fetcher
= factory
.GetFetcherByID(0);
887 EXPECT_EQ(NULL
, fetcher
);
889 // Run the message loop(s) until SendRequest is called.
890 FlushThreadMessageLoops();
891 net::TestURLFetcher
* fetcher
= factory
.GetFetcherByID(0);
892 ASSERT_TRUE(fetcher
);
893 ClientDownloadRequest request
;
894 EXPECT_TRUE(request
.ParseFromString(fetcher
->upload_data()));
895 EXPECT_EQ("http://www.google.com/bla.exe", request
.url());
896 EXPECT_EQ(hash
, request
.digests().sha256());
897 EXPECT_EQ(item
.GetReceivedBytes(), request
.length());
898 EXPECT_EQ(item
.HasUserGesture(), request
.user_initiated());
899 EXPECT_TRUE(RequestContainsServerIp(request
, remote_address
));
900 EXPECT_EQ(2, request
.resources_size());
901 EXPECT_TRUE(RequestContainsResource(request
,
902 ClientDownloadRequest::DOWNLOAD_REDIRECT
,
903 "http://www.google.com/", ""));
904 EXPECT_TRUE(RequestContainsResource(request
,
905 ClientDownloadRequest::DOWNLOAD_URL
,
906 "http://www.google.com/bla.exe",
908 EXPECT_TRUE(request
.has_signature());
909 ASSERT_EQ(1, request
.signature().certificate_chain_size());
910 const ClientDownloadRequest_CertificateChain
& chain
=
911 request
.signature().certificate_chain(0);
912 ASSERT_EQ(1, chain
.element_size());
913 EXPECT_EQ("dummy cert data", chain
.element(0).certificate());
915 // Simulate the request finishing.
916 base::MessageLoop::current()->PostTask(
918 base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete
,
919 base::Unretained(this), fetcher
));
920 MessageLoop::current()->Run();
924 // Similar to above, but with an unsigned binary.
925 TEST_F(DownloadProtectionServiceTest
,
926 CheckClientDownloadValidateRequestNoSignature
) {
927 net::TestURLFetcherFactory factory
;
929 base::FilePath
tmp_path(FILE_PATH_LITERAL("bla.tmp"));
930 base::FilePath
final_path(FILE_PATH_LITERAL("bla.exe"));
931 std::vector
<GURL
> url_chain
;
932 url_chain
.push_back(GURL("http://www.google.com/"));
933 url_chain
.push_back(GURL("ftp://www.google.com/bla.exe"));
934 GURL
referrer("http://www.google.com/");
935 std::string hash
= "hash";
936 std::string remote_address
= "10.11.12.13";
938 content::MockDownloadItem item
;
939 EXPECT_CALL(item
, AddObserver(_
)).Times(1);
940 EXPECT_CALL(item
, RemoveObserver(_
)).Times(1);
941 EXPECT_CALL(item
, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path
));
942 EXPECT_CALL(item
, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path
));
943 EXPECT_CALL(item
, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain
));
944 EXPECT_CALL(item
, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer
));
945 EXPECT_CALL(item
, GetHash()).WillRepeatedly(ReturnRef(hash
));
946 EXPECT_CALL(item
, GetReceivedBytes()).WillRepeatedly(Return(100));
947 EXPECT_CALL(item
, HasUserGesture()).WillRepeatedly(Return(true));
948 EXPECT_CALL(item
, GetRemoteAddress()).WillRepeatedly(Return(remote_address
));
950 EXPECT_CALL(*sb_service_
->mock_database_manager(),
951 MatchDownloadWhitelistUrl(_
))
952 .WillRepeatedly(Return(false));
953 EXPECT_CALL(*signature_util_
.get(), CheckSignature(tmp_path
, _
));
954 download_service_
->CheckClientDownload(
956 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
957 base::Unretained(this)));
960 // SendRequest is not called. Wait for FinishRequest to call our callback.
961 MessageLoop::current()->Run();
962 net::TestURLFetcher
* fetcher
= factory
.GetFetcherByID(0);
963 EXPECT_EQ(NULL
, fetcher
);
965 // Run the message loop(s) until SendRequest is called.
966 FlushThreadMessageLoops();
967 net::TestURLFetcher
* fetcher
= factory
.GetFetcherByID(0);
968 ASSERT_TRUE(fetcher
);
969 ClientDownloadRequest request
;
970 EXPECT_TRUE(request
.ParseFromString(fetcher
->upload_data()));
971 EXPECT_EQ("ftp://www.google.com/bla.exe", request
.url());
972 EXPECT_EQ(hash
, request
.digests().sha256());
973 EXPECT_EQ(item
.GetReceivedBytes(), request
.length());
974 EXPECT_EQ(item
.HasUserGesture(), request
.user_initiated());
975 EXPECT_EQ(2, request
.resources_size());
976 EXPECT_TRUE(RequestContainsResource(request
,
977 ClientDownloadRequest::DOWNLOAD_REDIRECT
,
978 "http://www.google.com/", ""));
979 EXPECT_TRUE(RequestContainsResource(request
,
980 ClientDownloadRequest::DOWNLOAD_URL
,
981 "ftp://www.google.com/bla.exe",
983 EXPECT_TRUE(request
.has_signature());
984 EXPECT_EQ(0, request
.signature().certificate_chain_size());
986 // Simulate the request finishing.
987 base::MessageLoop::current()->PostTask(
989 base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete
,
990 base::Unretained(this), fetcher
));
991 MessageLoop::current()->Run();
995 TEST_F(DownloadProtectionServiceTest
, TestCheckDownloadUrl
) {
996 std::vector
<GURL
> url_chain
;
997 url_chain
.push_back(GURL("http://www.google.com/"));
998 url_chain
.push_back(GURL("http://www.google.com/bla.exe"));
999 GURL
referrer("http://www.google.com/");
1000 std::string hash
= "hash";
1002 content::MockDownloadItem item
;
1003 EXPECT_CALL(item
, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain
));
1004 EXPECT_CALL(item
, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer
));
1005 EXPECT_CALL(item
, GetHash()).WillRepeatedly(ReturnRef(hash
));
1007 // CheckDownloadURL returns immediately which means the client object callback
1008 // will never be called. Nevertheless the callback provided to
1009 // CheckClientDownload must still be called.
1010 EXPECT_CALL(*sb_service_
->mock_database_manager(),
1011 CheckDownloadUrl(ContainerEq(url_chain
), NotNull()))
1012 .WillOnce(Return(true));
1013 download_service_
->CheckDownloadUrl(
1015 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
1016 base::Unretained(this)));
1017 MessageLoop::current()->Run();
1018 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
1019 Mock::VerifyAndClearExpectations(sb_service_
.get());
1021 EXPECT_CALL(*sb_service_
->mock_database_manager(),
1022 CheckDownloadUrl(ContainerEq(url_chain
), NotNull()))
1023 .WillOnce(DoAll(CheckDownloadUrlDone(SB_THREAT_TYPE_SAFE
),
1025 download_service_
->CheckDownloadUrl(
1027 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
1028 base::Unretained(this)));
1029 MessageLoop::current()->Run();
1030 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
1031 Mock::VerifyAndClearExpectations(sb_service_
.get());
1033 EXPECT_CALL(*sb_service_
->mock_database_manager(),
1034 CheckDownloadUrl(ContainerEq(url_chain
), NotNull()))
1036 CheckDownloadUrlDone(SB_THREAT_TYPE_URL_MALWARE
),
1038 download_service_
->CheckDownloadUrl(
1040 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
1041 base::Unretained(this)));
1042 MessageLoop::current()->Run();
1043 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
1044 Mock::VerifyAndClearExpectations(sb_service_
.get());
1046 EXPECT_CALL(*sb_service_
->mock_database_manager(),
1047 CheckDownloadUrl(ContainerEq(url_chain
),
1050 CheckDownloadUrlDone(SB_THREAT_TYPE_BINARY_MALWARE_URL
),
1052 download_service_
->CheckDownloadUrl(
1054 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
1055 base::Unretained(this)));
1056 MessageLoop::current()->Run();
1057 EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS
));
1060 TEST_F(DownloadProtectionServiceTest
, TestDownloadRequestTimeout
) {
1061 net::TestURLFetcherFactory factory
;
1063 std::vector
<GURL
> url_chain
;
1064 url_chain
.push_back(GURL("http://www.evil.com/bla.exe"));
1065 GURL
referrer("http://www.google.com/");
1066 base::FilePath
tmp_path(FILE_PATH_LITERAL("a.tmp"));
1067 base::FilePath
final_path(FILE_PATH_LITERAL("a.exe"));
1068 std::string hash
= "hash";
1070 content::MockDownloadItem item
;
1071 EXPECT_CALL(item
, AddObserver(_
)).Times(1);
1072 EXPECT_CALL(item
, RemoveObserver(_
)).Times(1);
1073 EXPECT_CALL(item
, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path
));
1074 EXPECT_CALL(item
, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path
));
1075 EXPECT_CALL(item
, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain
));
1076 EXPECT_CALL(item
, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer
));
1077 EXPECT_CALL(item
, GetHash()).WillRepeatedly(ReturnRef(hash
));
1078 EXPECT_CALL(item
, GetReceivedBytes()).WillRepeatedly(Return(100));
1079 EXPECT_CALL(item
, HasUserGesture()).WillRepeatedly(Return(true));
1080 EXPECT_CALL(item
, GetRemoteAddress()).WillRepeatedly(Return(""));
1082 EXPECT_CALL(*sb_service_
->mock_database_manager(),
1083 MatchDownloadWhitelistUrl(_
))
1084 .WillRepeatedly(Return(false));
1085 EXPECT_CALL(*signature_util_
.get(), CheckSignature(tmp_path
, _
));
1087 download_service_
->download_request_timeout_ms_
= 10;
1088 download_service_
->CheckClientDownload(
1090 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback
,
1091 base::Unretained(this)));
1093 // The request should time out because the HTTP request hasn't returned
1095 MessageLoop::current()->Run();
1096 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
1099 TEST_F(DownloadProtectionServiceTest
, TestDownloadItemDestroyed
) {
1100 net::TestURLFetcherFactory factory
;
1102 std::vector
<GURL
> url_chain
;
1103 url_chain
.push_back(GURL("http://www.evil.com/bla.exe"));
1104 GURL
referrer("http://www.google.com/");
1105 base::FilePath
tmp_path(FILE_PATH_LITERAL("a.tmp"));
1106 base::FilePath
final_path(FILE_PATH_LITERAL("a.exe"));
1107 std::string hash
= "hash";
1109 content::MockDownloadItem item
;
1110 content::DownloadItem::Observer
* observer
= NULL
;
1111 EXPECT_CALL(item
, AddObserver(_
)).WillOnce(SaveArg
<0>(&observer
));
1112 EXPECT_CALL(item
, RemoveObserver(_
)).WillOnce(Assign(
1113 &observer
, static_cast<content::DownloadItem::Observer
*>(NULL
)));
1114 EXPECT_CALL(item
, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path
));
1115 EXPECT_CALL(item
, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path
));
1116 EXPECT_CALL(item
, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain
));
1117 EXPECT_CALL(item
, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer
));
1118 EXPECT_CALL(item
, GetHash()).WillRepeatedly(ReturnRef(hash
));
1119 EXPECT_CALL(item
, GetReceivedBytes()).WillRepeatedly(Return(100));
1120 EXPECT_CALL(item
, HasUserGesture()).WillRepeatedly(Return(true));
1121 EXPECT_CALL(item
, GetRemoteAddress()).WillRepeatedly(Return(""));
1123 EXPECT_CALL(*sb_service_
->mock_database_manager(),
1124 MatchDownloadWhitelistUrl(_
))
1125 .WillRepeatedly(Return(false));
1126 EXPECT_CALL(*signature_util_
.get(), CheckSignature(tmp_path
, _
));
1128 download_service_
->CheckClientDownload(
1130 base::Bind(&DownloadProtectionServiceTest::SyncCheckDoneCallback
,
1131 base::Unretained(this)));
1133 ASSERT_TRUE(observer
!= NULL
);
1134 observer
->OnDownloadDestroyed(&item
);
1136 EXPECT_TRUE(observer
== NULL
);
1137 EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE
));
1140 TEST_F(DownloadProtectionServiceTest
, GetCertificateWhitelistStrings
) {
1141 // We'll pass this cert in as the "issuer", even though it isn't really
1142 // used to sign the certs below. GetCertificateWhitelistStirngs doesn't care
1144 scoped_refptr
<net::X509Certificate
> issuer_cert(
1145 ReadTestCertificate("issuer.pem"));
1146 ASSERT_TRUE(issuer_cert
.get());
1147 std::string cert_base
= "cert/" + base::HexEncode(
1148 issuer_cert
->fingerprint().data
,
1149 sizeof(issuer_cert
->fingerprint().data
));
1151 scoped_refptr
<net::X509Certificate
> cert(ReadTestCertificate("test_cn.pem"));
1152 ASSERT_TRUE(cert
.get());
1153 std::vector
<std::string
> whitelist_strings
;
1154 GetCertificateWhitelistStrings(
1155 *cert
.get(), *issuer_cert
.get(), &whitelist_strings
);
1156 // This also tests escaping of characters in the certificate attributes.
1157 EXPECT_THAT(whitelist_strings
, ElementsAre(
1158 cert_base
+ "/CN=subject%2F%251"));
1160 cert
= ReadTestCertificate("test_cn_o.pem");
1161 ASSERT_TRUE(cert
.get());
1162 whitelist_strings
.clear();
1163 GetCertificateWhitelistStrings(
1164 *cert
.get(), *issuer_cert
.get(), &whitelist_strings
);
1165 EXPECT_THAT(whitelist_strings
,
1166 ElementsAre(cert_base
+ "/CN=subject",
1167 cert_base
+ "/CN=subject/O=org",
1168 cert_base
+ "/O=org"));
1170 cert
= ReadTestCertificate("test_cn_o_ou.pem");
1171 ASSERT_TRUE(cert
.get());
1172 whitelist_strings
.clear();
1173 GetCertificateWhitelistStrings(
1174 *cert
.get(), *issuer_cert
.get(), &whitelist_strings
);
1175 EXPECT_THAT(whitelist_strings
,
1176 ElementsAre(cert_base
+ "/CN=subject",
1177 cert_base
+ "/CN=subject/O=org",
1178 cert_base
+ "/CN=subject/O=org/OU=unit",
1179 cert_base
+ "/CN=subject/OU=unit",
1180 cert_base
+ "/O=org",
1181 cert_base
+ "/O=org/OU=unit",
1182 cert_base
+ "/OU=unit"));
1184 cert
= ReadTestCertificate("test_cn_ou.pem");
1185 ASSERT_TRUE(cert
.get());
1186 whitelist_strings
.clear();
1187 GetCertificateWhitelistStrings(
1188 *cert
.get(), *issuer_cert
.get(), &whitelist_strings
);
1189 EXPECT_THAT(whitelist_strings
,
1190 ElementsAre(cert_base
+ "/CN=subject",
1191 cert_base
+ "/CN=subject/OU=unit",
1192 cert_base
+ "/OU=unit"));
1194 cert
= ReadTestCertificate("test_o.pem");
1195 ASSERT_TRUE(cert
.get());
1196 whitelist_strings
.clear();
1197 GetCertificateWhitelistStrings(
1198 *cert
.get(), *issuer_cert
.get(), &whitelist_strings
);
1199 EXPECT_THAT(whitelist_strings
, ElementsAre(cert_base
+ "/O=org"));
1201 cert
= ReadTestCertificate("test_o_ou.pem");
1202 ASSERT_TRUE(cert
.get());
1203 whitelist_strings
.clear();
1204 GetCertificateWhitelistStrings(
1205 *cert
.get(), *issuer_cert
.get(), &whitelist_strings
);
1206 EXPECT_THAT(whitelist_strings
,
1207 ElementsAre(cert_base
+ "/O=org",
1208 cert_base
+ "/O=org/OU=unit",
1209 cert_base
+ "/OU=unit"));
1211 cert
= ReadTestCertificate("test_ou.pem");
1212 ASSERT_TRUE(cert
.get());
1213 whitelist_strings
.clear();
1214 GetCertificateWhitelistStrings(
1215 *cert
.get(), *issuer_cert
.get(), &whitelist_strings
);
1216 EXPECT_THAT(whitelist_strings
, ElementsAre(cert_base
+ "/OU=unit"));
1218 cert
= ReadTestCertificate("test_c.pem");
1219 ASSERT_TRUE(cert
.get());
1220 whitelist_strings
.clear();
1221 GetCertificateWhitelistStrings(
1222 *cert
.get(), *issuer_cert
.get(), &whitelist_strings
);
1223 EXPECT_THAT(whitelist_strings
, ElementsAre());
1225 } // namespace safe_browsing