Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / net / cert / nss_cert_database_chromeos_unittest.cc
1 // Copyright 2013 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.
4
5 #include "net/cert/nss_cert_database_chromeos.h"
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/run_loop.h"
11 #include "crypto/nss_util.h"
12 #include "crypto/nss_util_internal.h"
13 #include "net/base/test_data_directory.h"
14 #include "net/cert/cert_database.h"
15 #include "net/test/cert_test_util.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace net {
19
20 namespace {
21
22 bool IsCertInCertificateList(const X509Certificate* cert,
23                              const CertificateList& cert_list) {
24   for (CertificateList::const_iterator it = cert_list.begin();
25        it != cert_list.end();
26        ++it) {
27     if (X509Certificate::IsSameOSCert((*it)->os_cert_handle(),
28                                       cert->os_cert_handle()))
29       return true;
30   }
31   return false;
32 }
33
34 void SwapCertLists(CertificateList* destination,
35                    scoped_ptr<CertificateList> source) {
36   ASSERT_TRUE(destination);
37   ASSERT_TRUE(source);
38
39   destination->swap(*source);
40 }
41
42 }  // namespace
43
44 class NSSCertDatabaseChromeOSTest : public testing::Test,
45                                     public CertDatabase::Observer {
46  public:
47   NSSCertDatabaseChromeOSTest()
48       : observer_added_(false), user_1_("user1"), user_2_("user2") {}
49
50   virtual void SetUp() OVERRIDE {
51     // Initialize nss_util slots.
52     ASSERT_TRUE(user_1_.constructed_successfully());
53     ASSERT_TRUE(user_2_.constructed_successfully());
54     user_1_.FinishInit();
55     user_2_.FinishInit();
56
57     // Create NSSCertDatabaseChromeOS for each user.
58     db_1_.reset(new NSSCertDatabaseChromeOS(
59         crypto::GetPublicSlotForChromeOSUser(user_1_.username_hash()),
60         crypto::GetPrivateSlotForChromeOSUser(
61             user_1_.username_hash(),
62             base::Callback<void(crypto::ScopedPK11Slot)>())));
63     db_1_->SetSlowTaskRunnerForTest(base::MessageLoopProxy::current());
64     db_2_.reset(new NSSCertDatabaseChromeOS(
65         crypto::GetPublicSlotForChromeOSUser(user_2_.username_hash()),
66         crypto::GetPrivateSlotForChromeOSUser(
67             user_2_.username_hash(),
68             base::Callback<void(crypto::ScopedPK11Slot)>())));
69     db_2_->SetSlowTaskRunnerForTest(base::MessageLoopProxy::current());
70
71     // Add observer to CertDatabase for checking that notifications from
72     // NSSCertDatabaseChromeOS are proxied to the CertDatabase.
73     CertDatabase::GetInstance()->AddObserver(this);
74     observer_added_ = true;
75   }
76
77   virtual void TearDown() OVERRIDE {
78     if (observer_added_)
79       CertDatabase::GetInstance()->RemoveObserver(this);
80   }
81
82   // CertDatabase::Observer:
83   virtual void OnCertAdded(const X509Certificate* cert) OVERRIDE {
84     added_.push_back(cert ? cert->os_cert_handle() : NULL);
85   }
86
87   virtual void OnCertRemoved(const X509Certificate* cert) OVERRIDE {}
88
89   virtual void OnCACertChanged(const X509Certificate* cert) OVERRIDE {
90     added_ca_.push_back(cert ? cert->os_cert_handle() : NULL);
91   }
92
93  protected:
94   bool observer_added_;
95   // Certificates that were passed to the CertDatabase observers.
96   std::vector<CERTCertificate*> added_ca_;
97   std::vector<CERTCertificate*> added_;
98
99   crypto::ScopedTestNSSChromeOSUser user_1_;
100   crypto::ScopedTestNSSChromeOSUser user_2_;
101   scoped_ptr<NSSCertDatabaseChromeOS> db_1_;
102   scoped_ptr<NSSCertDatabaseChromeOS> db_2_;
103 };
104
105 // Test that ListModules() on each user includes that user's NSS software slot,
106 // and does not include the software slot of the other user. (Does not check the
107 // private slot, since it is the same as the public slot in tests.)
108 TEST_F(NSSCertDatabaseChromeOSTest, ListModules) {
109   CryptoModuleList modules_1;
110   CryptoModuleList modules_2;
111
112   db_1_->ListModules(&modules_1, false /* need_rw */);
113   db_2_->ListModules(&modules_2, false /* need_rw */);
114
115   bool found_1 = false;
116   for (CryptoModuleList::iterator it = modules_1.begin(); it != modules_1.end();
117        ++it) {
118     EXPECT_NE(db_2_->GetPublicSlot().get(), (*it)->os_module_handle());
119     if ((*it)->os_module_handle() == db_1_->GetPublicSlot().get())
120       found_1 = true;
121   }
122   EXPECT_TRUE(found_1);
123
124   bool found_2 = false;
125   for (CryptoModuleList::iterator it = modules_2.begin(); it != modules_2.end();
126        ++it) {
127     EXPECT_NE(db_1_->GetPublicSlot().get(), (*it)->os_module_handle());
128     if ((*it)->os_module_handle() == db_2_->GetPublicSlot().get())
129       found_2 = true;
130   }
131   EXPECT_TRUE(found_2);
132 }
133
134 // Test that ImportCACerts imports the cert to the correct slot, and that
135 // ListCerts includes the added cert for the correct user, and does not include
136 // it for the other user.
137 TEST_F(NSSCertDatabaseChromeOSTest, ImportCACerts) {
138   // Load test certs from disk.
139   CertificateList certs_1 =
140       CreateCertificateListFromFile(GetTestCertsDirectory(),
141                                     "root_ca_cert.pem",
142                                     X509Certificate::FORMAT_AUTO);
143   ASSERT_EQ(1U, certs_1.size());
144
145   CertificateList certs_2 =
146       CreateCertificateListFromFile(GetTestCertsDirectory(),
147                                     "2048-rsa-root.pem",
148                                     X509Certificate::FORMAT_AUTO);
149   ASSERT_EQ(1U, certs_2.size());
150
151   // Import one cert for each user.
152   NSSCertDatabase::ImportCertFailureList failed;
153   EXPECT_TRUE(
154       db_1_->ImportCACerts(certs_1, NSSCertDatabase::TRUSTED_SSL, &failed));
155   EXPECT_EQ(0U, failed.size());
156   failed.clear();
157   EXPECT_TRUE(
158       db_2_->ImportCACerts(certs_2, NSSCertDatabase::TRUSTED_SSL, &failed));
159   EXPECT_EQ(0U, failed.size());
160
161   // Get cert list for each user.
162   CertificateList user_1_certlist;
163   CertificateList user_2_certlist;
164   db_1_->ListCertsSync(&user_1_certlist);
165   db_2_->ListCertsSync(&user_2_certlist);
166
167   // Check that the imported certs only shows up in the list for the user that
168   // imported them.
169   EXPECT_TRUE(IsCertInCertificateList(certs_1[0], user_1_certlist));
170   EXPECT_FALSE(IsCertInCertificateList(certs_1[0], user_2_certlist));
171
172   EXPECT_TRUE(IsCertInCertificateList(certs_2[0], user_2_certlist));
173   EXPECT_FALSE(IsCertInCertificateList(certs_2[0], user_1_certlist));
174
175   // Run the message loop so the observer notifications get processed.
176   base::RunLoop().RunUntilIdle();
177   // Should have gotten two OnCACertChanged notifications.
178   ASSERT_EQ(2U, added_ca_.size());
179   // TODO(mattm): make NSSCertDatabase actually pass the cert to the callback,
180   // and enable these checks:
181   // EXPECT_EQ(certs_1[0]->os_cert_handle(), added_ca_[0]);
182   // EXPECT_EQ(certs_2[0]->os_cert_handle(), added_ca_[1]);
183   EXPECT_EQ(0U, added_.size());
184
185   // Tests that the new certs are loaded by async ListCerts method.
186   CertificateList user_1_certlist_async;
187   CertificateList user_2_certlist_async;
188   db_1_->ListCerts(
189       base::Bind(&SwapCertLists, base::Unretained(&user_1_certlist_async)));
190   db_2_->ListCerts(
191       base::Bind(&SwapCertLists, base::Unretained(&user_2_certlist_async)));
192
193   base::RunLoop().RunUntilIdle();
194
195   EXPECT_TRUE(IsCertInCertificateList(certs_1[0], user_1_certlist_async));
196   EXPECT_FALSE(IsCertInCertificateList(certs_1[0], user_2_certlist_async));
197
198   EXPECT_TRUE(IsCertInCertificateList(certs_2[0], user_2_certlist_async));
199   EXPECT_FALSE(IsCertInCertificateList(certs_2[0], user_1_certlist_async));
200 }
201
202 // Test that ImportServerCerts imports the cert to the correct slot, and that
203 // ListCerts includes the added cert for the correct user, and does not include
204 // it for the other user.
205 TEST_F(NSSCertDatabaseChromeOSTest, ImportServerCert) {
206   // Load test certs from disk.
207   CertificateList certs_1 = CreateCertificateListFromFile(
208       GetTestCertsDirectory(), "ok_cert.pem", X509Certificate::FORMAT_AUTO);
209   ASSERT_EQ(1U, certs_1.size());
210
211   CertificateList certs_2 =
212       CreateCertificateListFromFile(GetTestCertsDirectory(),
213                                     "2048-rsa-ee-by-2048-rsa-intermediate.pem",
214                                     X509Certificate::FORMAT_AUTO);
215   ASSERT_EQ(1U, certs_2.size());
216
217   // Import one cert for each user.
218   NSSCertDatabase::ImportCertFailureList failed;
219   EXPECT_TRUE(
220       db_1_->ImportServerCert(certs_1, NSSCertDatabase::TRUSTED_SSL, &failed));
221   EXPECT_EQ(0U, failed.size());
222   failed.clear();
223   EXPECT_TRUE(
224       db_2_->ImportServerCert(certs_2, NSSCertDatabase::TRUSTED_SSL, &failed));
225   EXPECT_EQ(0U, failed.size());
226
227   // Get cert list for each user.
228   CertificateList user_1_certlist;
229   CertificateList user_2_certlist;
230   db_1_->ListCertsSync(&user_1_certlist);
231   db_2_->ListCertsSync(&user_2_certlist);
232
233   // Check that the imported certs only shows up in the list for the user that
234   // imported them.
235   EXPECT_TRUE(IsCertInCertificateList(certs_1[0], user_1_certlist));
236   EXPECT_FALSE(IsCertInCertificateList(certs_1[0], user_2_certlist));
237
238   EXPECT_TRUE(IsCertInCertificateList(certs_2[0], user_2_certlist));
239   EXPECT_FALSE(IsCertInCertificateList(certs_2[0], user_1_certlist));
240
241   // Run the message loop so the observer notifications get processed.
242   base::RunLoop().RunUntilIdle();
243   // TODO(mattm): ImportServerCert doesn't actually cause any observers to
244   // fire. Is that correct?
245   EXPECT_EQ(0U, added_ca_.size());
246   EXPECT_EQ(0U, added_.size());
247
248   // Tests that the new certs are loaded by async ListCerts method.
249   CertificateList user_1_certlist_async;
250   CertificateList user_2_certlist_async;
251   db_1_->ListCerts(
252       base::Bind(&SwapCertLists, base::Unretained(&user_1_certlist_async)));
253   db_2_->ListCerts(
254       base::Bind(&SwapCertLists, base::Unretained(&user_2_certlist_async)));
255
256   base::RunLoop().RunUntilIdle();
257
258   EXPECT_TRUE(IsCertInCertificateList(certs_1[0], user_1_certlist_async));
259   EXPECT_FALSE(IsCertInCertificateList(certs_1[0], user_2_certlist_async));
260
261   EXPECT_TRUE(IsCertInCertificateList(certs_2[0], user_2_certlist_async));
262   EXPECT_FALSE(IsCertInCertificateList(certs_2[0], user_1_certlist_async));
263 }
264
265 // Tests that There is no crash if the database is deleted while ListCerts
266 // is being processed on the worker pool.
267 TEST_F(NSSCertDatabaseChromeOSTest, NoCrashIfShutdownBeforeDoneOnWorkerPool) {
268   CertificateList certlist;
269   db_1_->ListCerts(base::Bind(&SwapCertLists, base::Unretained(&certlist)));
270   EXPECT_EQ(0U, certlist.size());
271
272   db_1_.reset();
273
274   base::RunLoop().RunUntilIdle();
275
276   EXPECT_LT(0U, certlist.size());
277 }
278
279 }  // namespace net