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 <map> | 7 #include <map> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/base_paths.h" | |
10 #include "base/bind.h" | 11 #include "base/bind.h" |
11 #include "base/callback.h" | 12 #include "base/callback.h" |
12 #include "base/file_path.h" | 13 #include "base/file_path.h" |
14 #include "base/file_util.h" | |
13 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
14 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
15 #include "base/message_loop.h" | 17 #include "base/message_loop.h" |
18 #include "base/path_service.h" | |
19 #include "base/string_number_conversions.h" | |
16 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | 20 #include "chrome/browser/safe_browsing/safe_browsing_service.h" |
17 #include "chrome/browser/safe_browsing/signature_util.h" | 21 #include "chrome/browser/safe_browsing/signature_util.h" |
18 #include "chrome/common/safe_browsing/csd.pb.h" | 22 #include "chrome/common/safe_browsing/csd.pb.h" |
19 #include "content/browser/download/download_item.h" | 23 #include "content/browser/download/download_item.h" |
20 #include "content/public/common/url_fetcher_delegate.h" | 24 #include "content/public/common/url_fetcher_delegate.h" |
21 #include "content/test/test_browser_thread.h" | 25 #include "content/test/test_browser_thread.h" |
22 #include "content/test/test_url_fetcher_factory.h" | 26 #include "content/test/test_url_fetcher_factory.h" |
27 #include "crypto/rsa_private_key.h" | |
23 #include "googleurl/src/gurl.h" | 28 #include "googleurl/src/gurl.h" |
29 #include "net/base/x509_certificate.h" | |
24 #include "testing/gmock/include/gmock/gmock.h" | 30 #include "testing/gmock/include/gmock/gmock.h" |
25 #include "testing/gtest/include/gtest/gtest.h" | 31 #include "testing/gtest/include/gtest/gtest.h" |
26 | 32 |
27 using ::testing::ContainerEq; | 33 using ::testing::ContainerEq; |
28 using ::testing::DoAll; | 34 using ::testing::DoAll; |
35 using ::testing::ElementsAre; | |
29 using ::testing::Mock; | 36 using ::testing::Mock; |
30 using ::testing::NotNull; | 37 using ::testing::NotNull; |
31 using ::testing::Return; | 38 using ::testing::Return; |
32 using ::testing::SaveArg; | 39 using ::testing::SaveArg; |
33 using ::testing::StrictMock; | 40 using ::testing::StrictMock; |
34 using ::testing::_; | 41 using ::testing::_; |
35 using content::BrowserThread; | 42 using content::BrowserThread; |
36 | 43 |
37 namespace safe_browsing { | 44 namespace safe_browsing { |
38 namespace { | 45 namespace { |
39 class MockSafeBrowsingService : public SafeBrowsingService { | 46 class MockSafeBrowsingService : public SafeBrowsingService { |
40 public: | 47 public: |
41 MockSafeBrowsingService() {} | 48 MockSafeBrowsingService() {} |
42 virtual ~MockSafeBrowsingService() {} | 49 virtual ~MockSafeBrowsingService() {} |
43 | 50 |
44 MOCK_METHOD1(MatchDownloadWhitelistUrl, bool(const GURL&)); | 51 MOCK_METHOD1(MatchDownloadWhitelistUrl, bool(const GURL&)); |
52 MOCK_METHOD1(MatchDownloadWhitelistString, bool(const std::string&)); | |
45 MOCK_METHOD2(CheckDownloadUrl, bool(const std::vector<GURL>& url_chain, | 53 MOCK_METHOD2(CheckDownloadUrl, bool(const std::vector<GURL>& url_chain, |
46 Client* client)); | 54 Client* client)); |
47 MOCK_METHOD2(CheckDownloadHash, bool(const std::string&, Client* client)); | 55 MOCK_METHOD2(CheckDownloadHash, bool(const std::string&, Client* client)); |
48 | 56 |
49 private: | 57 private: |
50 DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingService); | 58 DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingService); |
51 }; | 59 }; |
52 | 60 |
53 class MockSignatureUtil : public SignatureUtil { | 61 class MockSignatureUtil : public SignatureUtil { |
54 public: | 62 public: |
55 MockSignatureUtil() {} | 63 MockSignatureUtil() {} |
56 virtual ~MockSignatureUtil() {} | 64 virtual ~MockSignatureUtil() {} |
57 MOCK_METHOD2(CheckSignature, | 65 MOCK_METHOD2(CheckSignature, |
58 void(const FilePath&, ClientDownloadRequest_SignatureInfo*)); | 66 void(const FilePath&, ClientDownloadRequest_SignatureInfo*)); |
59 | 67 |
60 private: | 68 private: |
61 DISALLOW_COPY_AND_ASSIGN(MockSignatureUtil); | 69 DISALLOW_COPY_AND_ASSIGN(MockSignatureUtil); |
62 }; | 70 }; |
63 } // namespace | 71 } // namespace |
64 | 72 |
65 ACTION_P(SetCertificateContents, contents) { | 73 ACTION_P(SetCertificateContents, contents) { |
66 arg1->add_certificate_chain()->add_element()->set_certificate(contents); | 74 arg1->add_certificate_chain()->add_element()->set_certificate(contents); |
67 } | 75 } |
68 | 76 |
69 ACTION(TrustSignature) { | 77 ACTION_P(TrustSignature, certificate_file) { |
70 arg1->set_trusted(true); | 78 arg1->set_trusted(true); |
79 // Add a certificate chain. Note that we add the certificate twice so that | |
80 // it appears as its own issuer. | |
81 std::string cert_data; | |
82 ASSERT_TRUE(file_util::ReadFileToString(certificate_file, &cert_data)); | |
83 ClientDownloadRequest_CertificateChain* chain = | |
84 arg1->add_certificate_chain(); | |
85 chain->add_element()->set_certificate(cert_data); | |
86 chain->add_element()->set_certificate(cert_data); | |
71 } | 87 } |
72 | 88 |
73 // We can't call OnSafeBrowsingResult directly because SafeBrowsingCheck does | 89 // We can't call OnSafeBrowsingResult directly because SafeBrowsingCheck does |
74 // not have any copy constructor which means it can't be stored in a callback | 90 // not have any copy constructor which means it can't be stored in a callback |
75 // easily. Note: check will be deleted automatically when the callback is | 91 // easily. Note: check will be deleted automatically when the callback is |
76 // deleted. | 92 // deleted. |
77 void OnSafeBrowsingResult(SafeBrowsingService::SafeBrowsingCheck* check) { | 93 void OnSafeBrowsingResult(SafeBrowsingService::SafeBrowsingCheck* check) { |
78 check->client->OnSafeBrowsingResult(*check); | 94 check->client->OnSafeBrowsingResult(*check); |
79 } | 95 } |
80 | 96 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
115 io_thread_.reset(new content::TestBrowserThread(BrowserThread::IO)); | 131 io_thread_.reset(new content::TestBrowserThread(BrowserThread::IO)); |
116 ASSERT_TRUE(io_thread_->Start()); | 132 ASSERT_TRUE(io_thread_->Start()); |
117 file_thread_.reset(new content::TestBrowserThread(BrowserThread::FILE)); | 133 file_thread_.reset(new content::TestBrowserThread(BrowserThread::FILE)); |
118 ASSERT_TRUE(file_thread_->Start()); | 134 ASSERT_TRUE(file_thread_->Start()); |
119 sb_service_ = new StrictMock<MockSafeBrowsingService>(); | 135 sb_service_ = new StrictMock<MockSafeBrowsingService>(); |
120 signature_util_ = new StrictMock<MockSignatureUtil>(); | 136 signature_util_ = new StrictMock<MockSignatureUtil>(); |
121 download_service_ = sb_service_->download_protection_service(); | 137 download_service_ = sb_service_->download_protection_service(); |
122 download_service_->signature_util_ = signature_util_; | 138 download_service_->signature_util_ = signature_util_; |
123 download_service_->SetEnabled(true); | 139 download_service_->SetEnabled(true); |
124 msg_loop_.RunAllPending(); | 140 msg_loop_.RunAllPending(); |
141 | |
142 FilePath source_path; | |
143 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &source_path)); | |
144 testdata_path_ = source_path | |
145 .AppendASCII("chrome") | |
146 .AppendASCII("test") | |
147 .AppendASCII("data") | |
148 .AppendASCII("safe_browsing") | |
149 .AppendASCII("download_protection"); | |
125 } | 150 } |
126 | 151 |
127 virtual void TearDown() { | 152 virtual void TearDown() { |
128 // Flush all of the thread message loops to ensure that there are no | 153 // Flush all of the thread message loops to ensure that there are no |
129 // tasks currently running. | 154 // tasks currently running. |
130 FlushThreadMessageLoops(); | 155 FlushThreadMessageLoops(); |
131 sb_service_ = NULL; | 156 sb_service_ = NULL; |
132 io_thread_.reset(); | 157 io_thread_.reset(); |
133 file_thread_.reset(); | 158 file_thread_.reset(); |
134 ui_thread_.reset(); | 159 ui_thread_.reset(); |
(...skipping 13 matching lines...) Expand all Loading... | |
148 return false; | 173 return false; |
149 } | 174 } |
150 | 175 |
151 // Flushes any pending tasks in the message loops of all threads. | 176 // Flushes any pending tasks in the message loops of all threads. |
152 void FlushThreadMessageLoops() { | 177 void FlushThreadMessageLoops() { |
153 FlushMessageLoop(BrowserThread::FILE); | 178 FlushMessageLoop(BrowserThread::FILE); |
154 FlushMessageLoop(BrowserThread::IO); | 179 FlushMessageLoop(BrowserThread::IO); |
155 msg_loop_.RunAllPending(); | 180 msg_loop_.RunAllPending(); |
156 } | 181 } |
157 | 182 |
183 // Proxy for private method. | |
184 static void GetCertificateWhitelistStrings( | |
185 const net::X509Certificate& certificate, | |
186 const net::X509Certificate& issuer, | |
187 std::vector<std::string>* whitelist_strings) { | |
188 DownloadProtectionService::GetCertificateWhitelistStrings( | |
189 certificate, issuer, whitelist_strings); | |
190 } | |
191 | |
158 private: | 192 private: |
159 // Helper functions for FlushThreadMessageLoops. | 193 // Helper functions for FlushThreadMessageLoops. |
160 void RunAllPendingAndQuitUI() { | 194 void RunAllPendingAndQuitUI() { |
161 MessageLoop::current()->RunAllPending(); | 195 MessageLoop::current()->RunAllPending(); |
162 BrowserThread::PostTask( | 196 BrowserThread::PostTask( |
163 BrowserThread::UI, | 197 BrowserThread::UI, |
164 FROM_HERE, | 198 FROM_HERE, |
165 base::Bind(&DownloadProtectionServiceTest::QuitMessageLoop, | 199 base::Bind(&DownloadProtectionServiceTest::QuitMessageLoop, |
166 base::Unretained(this))); | 200 base::Unretained(this))); |
167 } | 201 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
205 | 239 |
206 protected: | 240 protected: |
207 scoped_refptr<MockSafeBrowsingService> sb_service_; | 241 scoped_refptr<MockSafeBrowsingService> sb_service_; |
208 scoped_refptr<MockSignatureUtil> signature_util_; | 242 scoped_refptr<MockSignatureUtil> signature_util_; |
209 DownloadProtectionService* download_service_; | 243 DownloadProtectionService* download_service_; |
210 MessageLoop msg_loop_; | 244 MessageLoop msg_loop_; |
211 scoped_ptr<DownloadProtectionService::DownloadCheckResult> result_; | 245 scoped_ptr<DownloadProtectionService::DownloadCheckResult> result_; |
212 scoped_ptr<content::TestBrowserThread> io_thread_; | 246 scoped_ptr<content::TestBrowserThread> io_thread_; |
213 scoped_ptr<content::TestBrowserThread> file_thread_; | 247 scoped_ptr<content::TestBrowserThread> file_thread_; |
214 scoped_ptr<content::TestBrowserThread> ui_thread_; | 248 scoped_ptr<content::TestBrowserThread> ui_thread_; |
249 FilePath testdata_path_; | |
215 }; | 250 }; |
216 | 251 |
217 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadInvalidUrl) { | 252 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadInvalidUrl) { |
218 DownloadProtectionService::DownloadInfo info; | 253 DownloadProtectionService::DownloadInfo info; |
219 download_service_->CheckClientDownload( | 254 download_service_->CheckClientDownload( |
220 info, | 255 info, |
221 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 256 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, |
222 base::Unretained(this))); | 257 base::Unretained(this))); |
223 msg_loop_.Run(); | 258 msg_loop_.Run(); |
224 ExpectResult(DownloadProtectionService::SAFE); | 259 ExpectResult(DownloadProtectionService::SAFE); |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
569 base::Unretained(this))); | 604 base::Unretained(this))); |
570 msg_loop_.Run(); | 605 msg_loop_.Run(); |
571 ExpectResult(DownloadProtectionService::SAFE); | 606 ExpectResult(DownloadProtectionService::SAFE); |
572 Mock::VerifyAndClearExpectations(sb_service_); | 607 Mock::VerifyAndClearExpectations(sb_service_); |
573 | 608 |
574 // If the binary is a trusted executable we will not ping the server but | 609 // If the binary is a trusted executable we will not ping the server but |
575 // we will still lookup the digest list. | 610 // we will still lookup the digest list. |
576 EXPECT_CALL(*sb_service_, MatchDownloadWhitelistUrl(_)) | 611 EXPECT_CALL(*sb_service_, MatchDownloadWhitelistUrl(_)) |
577 .WillRepeatedly(Return(false)); | 612 .WillRepeatedly(Return(false)); |
578 EXPECT_CALL(*signature_util_, CheckSignature(info.local_file, _)) | 613 EXPECT_CALL(*signature_util_, CheckSignature(info.local_file, _)) |
579 .WillOnce(TrustSignature()); | 614 .WillOnce(TrustSignature( |
615 testdata_path_.AppendASCII("signature_util_test.cer"))); | |
616 EXPECT_CALL(*sb_service_, | |
617 MatchDownloadWhitelistString( | |
618 "cert/58AFF702772EB67BDD412571BA40AAC07F0D936C/" | |
619 "CN=Joe's-Software-Emporium")) | |
620 .WillOnce(Return(true)); | |
580 EXPECT_CALL(*sb_service_, | 621 EXPECT_CALL(*sb_service_, |
581 CheckDownloadHash(info.sha256_hash, NotNull())) | 622 CheckDownloadHash(info.sha256_hash, NotNull())) |
582 .WillOnce(DoAll(CheckDownloadHashDone(SafeBrowsingService::SAFE), | 623 .WillOnce(DoAll(CheckDownloadHashDone(SafeBrowsingService::SAFE), |
583 Return(false))); | 624 Return(false))); |
584 download_service_->CheckClientDownload( | 625 download_service_->CheckClientDownload( |
585 info, | 626 info, |
586 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 627 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, |
587 base::Unretained(this))); | 628 base::Unretained(this))); |
588 msg_loop_.Run(); | 629 msg_loop_.Run(); |
589 ExpectResult(DownloadProtectionService::SAFE); | 630 ExpectResult(DownloadProtectionService::SAFE); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
668 download_service_->CheckClientDownload( | 709 download_service_->CheckClientDownload( |
669 info, | 710 info, |
670 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, | 711 base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback, |
671 base::Unretained(this))); | 712 base::Unretained(this))); |
672 | 713 |
673 // The request should time out because the HTTP request hasn't returned | 714 // The request should time out because the HTTP request hasn't returned |
674 // anything yet. | 715 // anything yet. |
675 msg_loop_.Run(); | 716 msg_loop_.Run(); |
676 ExpectResult(DownloadProtectionService::SAFE); | 717 ExpectResult(DownloadProtectionService::SAFE); |
677 } | 718 } |
719 | |
720 TEST_F(DownloadProtectionServiceTest, | |
721 GetCertificateWhitelistStrings_TestCert) { | |
722 std::string cert_data; | |
723 ASSERT_TRUE(file_util::ReadFileToString(testdata_path_.AppendASCII( | |
724 "signature_util_test.cer"), &cert_data)); | |
725 | |
726 scoped_refptr<net::X509Certificate> cert( | |
727 net::X509Certificate::CreateFromBytes(cert_data.data(), | |
728 cert_data.size())); | |
729 ASSERT_TRUE(cert.get()); | |
730 | |
731 std::vector<std::string> whitelist_strings; | |
732 GetCertificateWhitelistStrings(*cert, *cert, &whitelist_strings); | |
733 | |
734 EXPECT_THAT(whitelist_strings, ElementsAre( | |
735 "cert/58AFF702772EB67BDD412571BA40AAC07F0D936C" | |
736 "/CN=Joe's-Software-Emporium")); | |
737 } | |
738 | |
739 // Only some implementations have the ability to generate self-signed certs. | |
740 #if defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX) | |
741 TEST_F(DownloadProtectionServiceTest, | |
742 GetCertificateWhitelistStrings_SelfSigned) { | |
743 scoped_ptr<crypto::RSAPrivateKey> private_key( | |
744 crypto::RSAPrivateKey::Create(1024)); | |
Ryan Sleevi
2011/12/02 03:03:05
Just a drive-by: Over on the net/ side, we've foun
| |
745 // We'll pass this cert in as the "issuer", even though it isn't really | |
746 // used to sign the certs below. GetCertificateWhitelistStirngs doesn't care | |
747 // about this. | |
748 scoped_refptr<net::X509Certificate> issuer_cert = | |
749 net::X509Certificate::CreateSelfSigned( | |
750 private_key.get(), "CN=issuer", 1, base::TimeDelta::FromDays(1)); | |
751 ASSERT_TRUE(issuer_cert.get()); | |
752 std::string cert_base = "cert/" + base::HexEncode( | |
753 issuer_cert->fingerprint().data, | |
754 sizeof(issuer_cert->fingerprint().data)); | |
755 | |
756 scoped_refptr<net::X509Certificate> cert = | |
757 net::X509Certificate::CreateSelfSigned( | |
758 private_key.get(), "CN=subject/%1", 1, base::TimeDelta::FromDays(1)); | |
759 ASSERT_TRUE(cert.get()); | |
760 std::vector<std::string> whitelist_strings; | |
761 GetCertificateWhitelistStrings(*cert, *issuer_cert, &whitelist_strings); | |
762 // This also tests escaping of characters in the certificate attributes. | |
763 EXPECT_THAT(whitelist_strings, ElementsAre( | |
764 cert_base + "/CN=subject%2F%251")); | |
765 | |
766 cert = net::X509Certificate::CreateSelfSigned( | |
767 private_key.get(), "CN=subject,O=org", 1, base::TimeDelta::FromDays(1)); | |
768 ASSERT_TRUE(cert.get()); | |
769 whitelist_strings.clear(); | |
770 GetCertificateWhitelistStrings(*cert, *issuer_cert, &whitelist_strings); | |
771 EXPECT_THAT(whitelist_strings, ElementsAre( | |
772 cert_base + "/CN=subject", | |
773 cert_base + "/CN=subject/O=org", | |
774 cert_base + "/O=org")); | |
775 | |
776 cert = net::X509Certificate::CreateSelfSigned( | |
777 private_key.get(), "CN=subject,O=org,OU=unit", 1, | |
778 base::TimeDelta::FromDays(1)); | |
779 ASSERT_TRUE(cert.get()); | |
780 whitelist_strings.clear(); | |
781 GetCertificateWhitelistStrings(*cert, *issuer_cert, &whitelist_strings); | |
782 EXPECT_THAT(whitelist_strings, ElementsAre( | |
783 cert_base + "/CN=subject", | |
784 cert_base + "/CN=subject/O=org", | |
785 cert_base + "/CN=subject/O=org/OU=unit", | |
786 cert_base + "/CN=subject/OU=unit", | |
787 cert_base + "/O=org", | |
788 cert_base + "/O=org/OU=unit", | |
789 cert_base + "/OU=unit")); | |
790 | |
791 cert = net::X509Certificate::CreateSelfSigned( | |
792 private_key.get(), "CN=subject,OU=unit", 1, | |
793 base::TimeDelta::FromDays(1)); | |
794 ASSERT_TRUE(cert.get()); | |
795 whitelist_strings.clear(); | |
796 GetCertificateWhitelistStrings(*cert, *issuer_cert, &whitelist_strings); | |
797 EXPECT_THAT(whitelist_strings, ElementsAre( | |
798 cert_base + "/CN=subject", | |
799 cert_base + "/CN=subject/OU=unit", | |
800 cert_base + "/OU=unit")); | |
801 | |
802 cert = net::X509Certificate::CreateSelfSigned( | |
803 private_key.get(), "O=org,", 1, base::TimeDelta::FromDays(1)); | |
804 ASSERT_TRUE(cert.get()); | |
805 whitelist_strings.clear(); | |
806 GetCertificateWhitelistStrings(*cert, *issuer_cert, &whitelist_strings); | |
807 EXPECT_THAT(whitelist_strings, ElementsAre(cert_base + "/O=org")); | |
808 | |
809 cert = net::X509Certificate::CreateSelfSigned( | |
810 private_key.get(), "O=org,OU=unit", 1, base::TimeDelta::FromDays(1)); | |
811 ASSERT_TRUE(cert.get()); | |
812 whitelist_strings.clear(); | |
813 GetCertificateWhitelistStrings(*cert, *issuer_cert, &whitelist_strings); | |
814 EXPECT_THAT(whitelist_strings, ElementsAre( | |
815 cert_base + "/O=org", | |
816 cert_base + "/O=org/OU=unit", | |
817 cert_base + "/OU=unit")); | |
818 | |
819 cert = net::X509Certificate::CreateSelfSigned( | |
820 private_key.get(), "OU=unit", 1, base::TimeDelta::FromDays(1)); | |
821 ASSERT_TRUE(cert.get()); | |
822 whitelist_strings.clear(); | |
823 GetCertificateWhitelistStrings(*cert, *issuer_cert, &whitelist_strings); | |
824 EXPECT_THAT(whitelist_strings, ElementsAre(cert_base + "/OU=unit")); | |
825 | |
826 cert = net::X509Certificate::CreateSelfSigned( | |
827 private_key.get(), "C=US", 1, base::TimeDelta::FromDays(1)); | |
828 ASSERT_TRUE(cert.get()); | |
829 whitelist_strings.clear(); | |
830 GetCertificateWhitelistStrings(*cert, *issuer_cert, &whitelist_strings); | |
831 EXPECT_THAT(whitelist_strings, ElementsAre()); | |
832 } | |
833 #endif | |
678 } // namespace safe_browsing | 834 } // namespace safe_browsing |
OLD | NEW |