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

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

Issue 8762007: Implement a whitelist for code-signing certificates. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address review comments Created 9 years 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 <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
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
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
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
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
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
OLDNEW
« no previous file with comments | « chrome/browser/safe_browsing/download_protection_service.cc ('k') | chrome/browser/safe_browsing/safe_browsing_service.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698