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

Side by Side Diff: net/ssl/client_cert_store_chromeos_unittest.cc

Issue 663583006: Remove nss_util dependency from ClientCertStoreChromeOS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed typo. Created 6 years, 1 month 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
« no previous file with comments | « net/ssl/client_cert_store_chromeos.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 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 "net/ssl/client_cert_store_chromeos.h" 5 #include "net/ssl/client_cert_store_chromeos.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/bind.h"
10 #include "base/callback.h" 9 #include "base/callback.h"
11 #include "base/files/file_util.h" 10 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h" 11 #include "base/run_loop.h"
13 #include "crypto/nss_util_internal.h"
14 #include "crypto/rsa_private_key.h" 12 #include "crypto/rsa_private_key.h"
15 #include "crypto/scoped_test_nss_chromeos_user.h" 13 #include "crypto/scoped_test_nss_db.h"
16 #include "crypto/scoped_test_system_nss_key_slot.h"
17 #include "net/base/test_data_directory.h" 14 #include "net/base/test_data_directory.h"
18 #include "net/cert/x509_certificate.h" 15 #include "net/cert/x509_certificate.h"
19 #include "net/ssl/client_cert_store_unittest-inl.h" 16 #include "net/ssl/client_cert_store_unittest-inl.h"
20 #include "net/test/cert_test_util.h" 17 #include "net/test/cert_test_util.h"
21 18
22 namespace net { 19 namespace net {
23 20
24 namespace { 21 namespace {
25 22
26 enum ReadFromSlot { 23 class TestCertFilter : public net::ClientCertStoreChromeOS::CertFilter {
27 READ_FROM_SLOT_USER, 24 public:
28 READ_FROM_SLOT_SYSTEM 25 explicit TestCertFilter(bool init_finished)
29 }; 26 : init_finished_(init_finished), init_called_(false) {}
30 27
31 enum SystemSlotAvailability { 28 ~TestCertFilter() override {}
32 SYSTEM_SLOT_AVAILABILITY_ENABLED, 29
33 SYSTEM_SLOT_AVAILABILITY_DISABLED 30 bool Init(const base::Closure& callback) override {
31 init_called_ = true;
32 if (init_finished_)
33 return true;
34 pending_callback_ = callback;
35 return false;
36 }
37
38 bool IsCertAllowed(
39 const scoped_refptr<net::X509Certificate>& cert) const override {
40 if (not_allowed_cert_.get() && cert->Equals(not_allowed_cert_.get()))
41 return false;
42 return true;
43 }
44
45 bool init_called() { return init_called_; }
46
47 void FinishInit() {
48 init_finished_ = true;
49 base::MessageLoop::current()->PostTask(FROM_HERE, pending_callback_);
50 pending_callback_.Reset();
51 }
52
53 void SetNotAllowedCert(scoped_refptr<X509Certificate> cert) {
54 not_allowed_cert_ = cert;
55 }
56
57 private:
58 bool init_finished_;
59 bool init_called_;
60 base::Closure pending_callback_;
61 scoped_refptr<X509Certificate> not_allowed_cert_;
34 }; 62 };
35 63
36 } // namespace 64 } // namespace
37 65
38 // Define a delegate to be used for instantiating the parameterized test set 66 // Define a delegate to be used for instantiating the parameterized test set
39 // ClientCertStoreTest. 67 // ClientCertStoreTest.
40 template <ReadFromSlot read_from,
41 SystemSlotAvailability system_slot_availability>
42 class ClientCertStoreChromeOSTestDelegate { 68 class ClientCertStoreChromeOSTestDelegate {
43 public: 69 public:
44 ClientCertStoreChromeOSTestDelegate() 70 ClientCertStoreChromeOSTestDelegate()
45 : user_("scopeduser"), 71 : store_(
46 store_(system_slot_availability == SYSTEM_SLOT_AVAILABILITY_ENABLED, 72 make_scoped_ptr(new TestCertFilter(true /* init synchronously */)),
47 user_.username_hash(), 73 ClientCertStoreChromeOS::PasswordDelegateFactory()) {
48 ClientCertStoreChromeOS::PasswordDelegateFactory()) {
49 // Defer futher initialization and checks to SelectClientCerts, because the 74 // Defer futher initialization and checks to SelectClientCerts, because the
50 // constructor doesn't allow us to return an initialization result. Could be 75 // constructor doesn't allow us to return an initialization result. Could be
51 // cleaned up by adding an Init() function. 76 // cleaned up by adding an Init() function.
52 } 77 }
53 78
54 // Called by the ClientCertStoreTest tests. 79 // Called by the ClientCertStoreTest tests.
55 // |inpurt_certs| contains certificates to select from. Because 80 // |inpurt_certs| contains certificates to select from. Because
56 // ClientCertStoreChromeOS filters also for the right slot, we have to import 81 // ClientCertStoreChromeOS filters also for the right slot, we have to import
57 // the certs at first. 82 // the certs at first.
58 // Since the certs are imported, the store can be tested by using its public 83 // Since the certs are imported, the store can be tested by using its public
59 // interface (GetClientCerts), which will read the certs from NSS. 84 // interface (GetClientCerts), which will read the certs from NSS.
60 bool SelectClientCerts(const CertificateList& input_certs, 85 bool SelectClientCerts(const CertificateList& input_certs,
61 const SSLCertRequestInfo& cert_request_info, 86 const SSLCertRequestInfo& cert_request_info,
62 CertificateList* selected_certs) { 87 CertificateList* selected_certs) {
63 if (!user_.constructed_successfully()) { 88 if (!test_db_.is_open()) {
64 LOG(ERROR) << "Scoped test user DB could not be constructed."; 89 LOG(ERROR) << "NSS DB could not be constructed.";
65 return false;
66 }
67 user_.FinishInit();
68
69 crypto::ScopedPK11Slot slot;
70 switch (read_from) {
71 case READ_FROM_SLOT_USER:
72 slot = crypto::GetPublicSlotForChromeOSUser(user_.username_hash());
73 break;
74 case READ_FROM_SLOT_SYSTEM:
75 slot.reset(PK11_ReferenceSlot(system_db_.slot()));
76 break;
77 default:
78 CHECK(false);
79 }
80 if (!slot) {
81 LOG(ERROR) << "Could not get the NSS key slot";
82 return false; 90 return false;
83 } 91 }
84 92
85 // Only user certs are considered for the cert request, which means that the 93 // Only user certs are considered for the cert request, which means that the
86 // private key must be known to NSS. Import all private keys for certs that 94 // private key must be known to NSS. Import all private keys for certs that
87 // are used througout the test. 95 // are used througout the test.
88 if (!ImportSensitiveKeyFromFile( 96 if (!ImportSensitiveKeyFromFile(
89 GetTestCertsDirectory(), "client_1.pk8", slot.get()) || 97 GetTestCertsDirectory(), "client_1.pk8", test_db_.slot()) ||
90 !ImportSensitiveKeyFromFile( 98 !ImportSensitiveKeyFromFile(
91 GetTestCertsDirectory(), "client_2.pk8", slot.get())) { 99 GetTestCertsDirectory(), "client_2.pk8", test_db_.slot())) {
92 return false; 100 return false;
93 } 101 }
94 102
95 for (CertificateList::const_iterator it = input_certs.begin(); 103 for (CertificateList::const_iterator it = input_certs.begin();
96 it != input_certs.end(); 104 it != input_certs.end();
97 ++it) { 105 ++it) {
98 if (!ImportClientCertToSlot(*it, slot.get())) 106 if (!ImportClientCertToSlot(*it, test_db_.slot()))
99 return false; 107 return false;
100 } 108 }
101 base::RunLoop run_loop; 109 base::RunLoop run_loop;
102 store_.GetClientCerts( 110 store_.GetClientCerts(
103 cert_request_info, selected_certs, run_loop.QuitClosure()); 111 cert_request_info, selected_certs, run_loop.QuitClosure());
104 run_loop.Run(); 112 run_loop.Run();
105 return true; 113 return true;
106 } 114 }
107 115
108 private: 116 private:
109 crypto::ScopedTestNSSChromeOSUser user_; 117 crypto::ScopedTestNSSDB test_db_;
110 crypto::ScopedTestSystemNSSKeySlot system_db_;
111 ClientCertStoreChromeOS store_; 118 ClientCertStoreChromeOS store_;
112 }; 119 };
113 120
114 // ClientCertStoreChromeOS derives from ClientCertStoreNSS and delegates the 121 // ClientCertStoreChromeOS derives from ClientCertStoreNSS and delegates the
115 // filtering by issuer to that base class. 122 // filtering by issuer to that base class.
116 // To verify that this delegation is functional, run the same filtering tests as 123 // To verify that this delegation is functional, run the same filtering tests as
117 // for the other implementations. These tests are defined in 124 // for the other implementations. These tests are defined in
118 // client_cert_store_unittest-inl.h and are instantiated for each platform. 125 // client_cert_store_unittest-inl.h and are instantiated for each platform.
119 126 INSTANTIATE_TYPED_TEST_CASE_P(ClientCertStoreTestChromeOS,
120 // In this case, all requested certs are read from the user's slot and the
121 // system slot is not enabled in the store.
122 typedef ClientCertStoreChromeOSTestDelegate<READ_FROM_SLOT_USER,
123 SYSTEM_SLOT_AVAILABILITY_DISABLED>
124 DelegateReadUserDisableSystem;
125 INSTANTIATE_TYPED_TEST_CASE_P(ChromeOS_ReadUserDisableSystem,
126 ClientCertStoreTest, 127 ClientCertStoreTest,
127 DelegateReadUserDisableSystem); 128 ClientCertStoreChromeOSTestDelegate);
128
129 // In this case, all requested certs are read from the user's slot and the
130 // system slot is enabled in the store.
131 typedef ClientCertStoreChromeOSTestDelegate<READ_FROM_SLOT_USER,
132 SYSTEM_SLOT_AVAILABILITY_ENABLED>
133 DelegateReadUserEnableSystem;
134 INSTANTIATE_TYPED_TEST_CASE_P(ChromeOS_ReadUserEnableSystem,
135 ClientCertStoreTest,
136 DelegateReadUserEnableSystem);
137
138 // In this case, all requested certs are read from the system slot, therefore
139 // the system slot is enabled in the store.
140 typedef ClientCertStoreChromeOSTestDelegate<READ_FROM_SLOT_SYSTEM,
141 SYSTEM_SLOT_AVAILABILITY_ENABLED>
142 DelegateReadSystem;
143 INSTANTIATE_TYPED_TEST_CASE_P(ChromeOS_ReadSystem,
144 ClientCertStoreTest,
145 DelegateReadSystem);
146 129
147 class ClientCertStoreChromeOSTest : public ::testing::Test { 130 class ClientCertStoreChromeOSTest : public ::testing::Test {
148 public: 131 public:
149 scoped_refptr<X509Certificate> ImportCertForUser( 132 scoped_refptr<X509Certificate> ImportCertToSlot(
150 const std::string& username_hash,
151 const std::string& cert_filename, 133 const std::string& cert_filename,
152 const std::string& key_filename) { 134 const std::string& key_filename,
153 crypto::ScopedPK11Slot slot( 135 PK11SlotInfo* slot) {
154 crypto::GetPublicSlotForChromeOSUser(username_hash));
155 if (!slot) {
156 LOG(ERROR) << "No slot for user " << username_hash;
157 return NULL;
158 }
159
160 return ImportClientCertAndKeyFromFile( 136 return ImportClientCertAndKeyFromFile(
161 GetTestCertsDirectory(), cert_filename, key_filename, slot.get()); 137 GetTestCertsDirectory(), cert_filename, key_filename, slot);
162 } 138 }
163
164 }; 139 };
165 140
166 // Ensure that cert requests, that are started before the user's NSS DB is 141 // Ensure that cert requests, that are started before the filter is initialized,
167 // initialized, will wait for the initialization and succeed afterwards. 142 // will wait for the initialization and succeed afterwards.
168 TEST_F(ClientCertStoreChromeOSTest, RequestWaitsForNSSInitAndSucceeds) { 143 TEST_F(ClientCertStoreChromeOSTest, RequestWaitsForNSSInitAndSucceeds) {
169 crypto::ScopedTestNSSChromeOSUser user("scopeduser"); 144 crypto::ScopedTestNSSDB test_db;
170 ASSERT_TRUE(user.constructed_successfully()); 145 ASSERT_TRUE(test_db.is_open());
171 146
172 crypto::ScopedTestSystemNSSKeySlot system_slot; 147 TestCertFilter* cert_filter =
148 new TestCertFilter(false /* init asynchronously */);
149 ClientCertStoreChromeOS store(
150 make_scoped_ptr(cert_filter),
151 ClientCertStoreChromeOS::PasswordDelegateFactory());
173 152
174 ClientCertStoreChromeOS store(
175 true /* use system slot */,
176 user.username_hash(),
177 ClientCertStoreChromeOS::PasswordDelegateFactory());
178 scoped_refptr<X509Certificate> cert_1( 153 scoped_refptr<X509Certificate> cert_1(
179 ImportCertForUser(user.username_hash(), "client_1.pem", "client_1.pk8")); 154 ImportCertToSlot("client_1.pem", "client_1.pk8", test_db.slot()));
180 ASSERT_TRUE(cert_1.get()); 155 ASSERT_TRUE(cert_1.get());
181 156
182 // Request any client certificate, which is expected to match client_1. 157 // Request any client certificate, which is expected to match client_1.
183 scoped_refptr<SSLCertRequestInfo> request_all(new SSLCertRequestInfo()); 158 scoped_refptr<SSLCertRequestInfo> request_all(new SSLCertRequestInfo());
184 159
185 base::RunLoop run_loop; 160 base::RunLoop run_loop;
186 store.GetClientCerts( 161 store.GetClientCerts(
187 *request_all, &request_all->client_certs, run_loop.QuitClosure()); 162 *request_all, &request_all->client_certs, run_loop.QuitClosure());
188 163
189 { 164 {
190 base::RunLoop run_loop_inner; 165 base::RunLoop run_loop_inner;
191 run_loop_inner.RunUntilIdle(); 166 run_loop_inner.RunUntilIdle();
192 // GetClientCerts should wait for the initialization of the user's DB to 167 // GetClientCerts should wait for the initialization of the filter to
193 // finish. 168 // finish.
194 ASSERT_EQ(0u, request_all->client_certs.size()); 169 ASSERT_EQ(0u, request_all->client_certs.size());
170 EXPECT_TRUE(cert_filter->init_called());
195 } 171 }
196 // This should trigger the GetClientCerts operation to finish and to call 172 cert_filter->FinishInit();
197 // back.
198 user.FinishInit();
199
200 run_loop.Run(); 173 run_loop.Run();
201 174
202 ASSERT_EQ(1u, request_all->client_certs.size()); 175 ASSERT_EQ(1u, request_all->client_certs.size());
203 } 176 }
204 177
205 // Ensure that cert requests, that are started after the user's NSS DB was 178 // Ensure that cert requests, that are started after the filter was initialized,
206 // initialized, will succeed. 179 // will succeed.
207 TEST_F(ClientCertStoreChromeOSTest, RequestsAfterNSSInitSucceed) { 180 TEST_F(ClientCertStoreChromeOSTest, RequestsAfterNSSInitSucceed) {
208 crypto::ScopedTestNSSChromeOSUser user("scopeduser"); 181 crypto::ScopedTestNSSDB test_db;
209 ASSERT_TRUE(user.constructed_successfully()); 182 ASSERT_TRUE(test_db.is_open());
210 user.FinishInit();
211
212 crypto::ScopedTestSystemNSSKeySlot system_slot;
213 183
214 ClientCertStoreChromeOS store( 184 ClientCertStoreChromeOS store(
215 true /* use system slot */, 185 make_scoped_ptr(new TestCertFilter(true /* init synchronously */)),
216 user.username_hash(),
217 ClientCertStoreChromeOS::PasswordDelegateFactory()); 186 ClientCertStoreChromeOS::PasswordDelegateFactory());
187
218 scoped_refptr<X509Certificate> cert_1( 188 scoped_refptr<X509Certificate> cert_1(
219 ImportCertForUser(user.username_hash(), "client_1.pem", "client_1.pk8")); 189 ImportCertToSlot("client_1.pem", "client_1.pk8", test_db.slot()));
220 ASSERT_TRUE(cert_1.get()); 190 ASSERT_TRUE(cert_1.get());
221 191
222 scoped_refptr<SSLCertRequestInfo> request_all(new SSLCertRequestInfo()); 192 scoped_refptr<SSLCertRequestInfo> request_all(new SSLCertRequestInfo());
223 193
224 base::RunLoop run_loop; 194 base::RunLoop run_loop;
225 store.GetClientCerts( 195 store.GetClientCerts(
226 *request_all, &request_all->client_certs, run_loop.QuitClosure()); 196 *request_all, &request_all->client_certs, run_loop.QuitClosure());
227 run_loop.Run(); 197 run_loop.Run();
228 198
229 ASSERT_EQ(1u, request_all->client_certs.size()); 199 ASSERT_EQ(1u, request_all->client_certs.size());
230 } 200 }
231 201
232 // This verifies that a request in the context of User1 doesn't see certificates 202 TEST_F(ClientCertStoreChromeOSTest, Filter) {
233 // of User2, and the other way round. We check both directions, to ensure that 203 crypto::ScopedTestNSSDB test_db;
234 // the behavior doesn't depend on initialization order of the DBs, for example. 204 ASSERT_TRUE(test_db.is_open());
235 TEST_F(ClientCertStoreChromeOSTest, RequestDoesCrossReadOtherUserDB) {
236 crypto::ScopedTestNSSChromeOSUser user1("scopeduser1");
237 ASSERT_TRUE(user1.constructed_successfully());
238 crypto::ScopedTestNSSChromeOSUser user2("scopeduser2");
239 ASSERT_TRUE(user2.constructed_successfully());
240 205
241 user1.FinishInit(); 206 TestCertFilter* cert_filter =
242 user2.FinishInit(); 207 new TestCertFilter(true /* init synchronously */);
243 208 ClientCertStoreChromeOS store(
244 crypto::ScopedTestSystemNSSKeySlot system_slot; 209 make_scoped_ptr(cert_filter),
245
246 ClientCertStoreChromeOS store1(
247 true /* use system slot */,
248 user1.username_hash(),
249 ClientCertStoreChromeOS::PasswordDelegateFactory());
250 ClientCertStoreChromeOS store2(
251 true /* use system slot */,
252 user2.username_hash(),
253 ClientCertStoreChromeOS::PasswordDelegateFactory()); 210 ClientCertStoreChromeOS::PasswordDelegateFactory());
254 211
255 scoped_refptr<X509Certificate> cert_1( 212 scoped_refptr<X509Certificate> cert_1(
256 ImportCertForUser(user1.username_hash(), "client_1.pem", "client_1.pk8")); 213 ImportCertToSlot("client_1.pem", "client_1.pk8", test_db.slot()));
257 ASSERT_TRUE(cert_1.get()); 214 ASSERT_TRUE(cert_1.get());
258 scoped_refptr<X509Certificate> cert_2( 215 scoped_refptr<X509Certificate> cert_2(
259 ImportCertForUser(user2.username_hash(), "client_2.pem", "client_2.pk8")); 216 ImportCertToSlot("client_2.pem", "client_2.pk8", test_db.slot()));
260 ASSERT_TRUE(cert_2.get()); 217 ASSERT_TRUE(cert_2.get());
261 218
262 scoped_refptr<SSLCertRequestInfo> request_all(new SSLCertRequestInfo()); 219 scoped_refptr<SSLCertRequestInfo> request_all(new SSLCertRequestInfo());
263 220
264 base::RunLoop run_loop_1; 221 {
265 base::RunLoop run_loop_2; 222 base::RunLoop run_loop;
223 cert_filter->SetNotAllowedCert(cert_2);
224 CertificateList selected_certs;
225 store.GetClientCerts(*request_all, &selected_certs, run_loop.QuitClosure());
226 run_loop.Run();
266 227
267 CertificateList selected_certs1, selected_certs2; 228 ASSERT_EQ(1u, selected_certs.size());
268 store1.GetClientCerts( 229 EXPECT_TRUE(cert_1->Equals(selected_certs[0].get()));
269 *request_all, &selected_certs1, run_loop_1.QuitClosure()); 230 }
270 store2.GetClientCerts(
271 *request_all, &selected_certs2, run_loop_2.QuitClosure());
272 231
273 run_loop_1.Run(); 232 {
274 run_loop_2.Run(); 233 base::RunLoop run_loop;
234 cert_filter->SetNotAllowedCert(cert_1);
235 CertificateList selected_certs;
236 store.GetClientCerts(*request_all, &selected_certs, run_loop.QuitClosure());
237 run_loop.Run();
275 238
276 // store1 should only return certs of user1, namely cert_1. 239 ASSERT_EQ(1u, selected_certs.size());
277 ASSERT_EQ(1u, selected_certs1.size()); 240 EXPECT_TRUE(cert_2->Equals(selected_certs[0].get()));
278 EXPECT_TRUE(cert_1->Equals(selected_certs1[0].get())); 241 }
279
280 // store2 should only return certs of user2, namely cert_2.
281 ASSERT_EQ(1u, selected_certs2.size());
282 EXPECT_TRUE(cert_2->Equals(selected_certs2[0].get()));
283 }
284
285 // This verifies that a request in the context of User1 doesn't see certificates
286 // of the system store if the system store is disabled.
287 TEST_F(ClientCertStoreChromeOSTest, RequestDoesCrossReadSystemDB) {
288 crypto::ScopedTestNSSChromeOSUser user1("scopeduser1");
289 ASSERT_TRUE(user1.constructed_successfully());
290
291 user1.FinishInit();
292
293 crypto::ScopedTestSystemNSSKeySlot system_slot;
294
295 ClientCertStoreChromeOS store(
296 false /* do not use system slot */,
297 user1.username_hash(),
298 ClientCertStoreChromeOS::PasswordDelegateFactory());
299
300 scoped_refptr<X509Certificate> cert_1(
301 ImportCertForUser(user1.username_hash(), "client_1.pem", "client_1.pk8"));
302 ASSERT_TRUE(cert_1.get());
303 scoped_refptr<X509Certificate> cert_2(
304 ImportClientCertAndKeyFromFile(GetTestCertsDirectory(),
305 "client_2.pem",
306 "client_2.pk8",
307 system_slot.slot()));
308 ASSERT_TRUE(cert_2.get());
309
310 scoped_refptr<SSLCertRequestInfo> request_all(new SSLCertRequestInfo());
311
312 base::RunLoop run_loop;
313
314 CertificateList selected_certs;
315 store.GetClientCerts(*request_all, &selected_certs, run_loop.QuitClosure());
316
317 run_loop.Run();
318
319 // store should only return certs of the user, namely cert_1.
320 ASSERT_EQ(1u, selected_certs.size());
321 EXPECT_TRUE(cert_1->Equals(selected_certs[0].get()));
322 } 242 }
323 243
324 } // namespace net 244 } // namespace net
OLDNEW
« no previous file with comments | « net/ssl/client_cert_store_chromeos.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698