Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / ssl / client_cert_store_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/ssl/client_cert_store_chromeos.h"
6
7 #include <string>
8
9 #include "base/callback.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h"
12 #include "crypto/rsa_private_key.h"
13 #include "crypto/scoped_test_nss_db.h"
14 #include "net/base/test_data_directory.h"
15 #include "net/cert/x509_certificate.h"
16 #include "net/ssl/client_cert_store_unittest-inl.h"
17 #include "net/test/cert_test_util.h"
18
19 namespace net {
20
21 namespace {
22
23 class TestCertFilter : public net::ClientCertStoreChromeOS::CertFilter {
24  public:
25   explicit TestCertFilter(bool init_finished)
26       : init_finished_(init_finished), init_called_(false) {}
27
28   ~TestCertFilter() override {}
29
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_;
62 };
63
64 }  // namespace
65
66 // Define a delegate to be used for instantiating the parameterized test set
67 // ClientCertStoreTest.
68 class ClientCertStoreChromeOSTestDelegate {
69  public:
70   ClientCertStoreChromeOSTestDelegate()
71       : store_(
72             make_scoped_ptr(new TestCertFilter(true /* init synchronously */)),
73             ClientCertStoreChromeOS::PasswordDelegateFactory()) {
74     // Defer futher initialization and checks to SelectClientCerts, because the
75     // constructor doesn't allow us to return an initialization result. Could be
76     // cleaned up by adding an Init() function.
77   }
78
79   // Called by the ClientCertStoreTest tests.
80   // |inpurt_certs| contains certificates to select from. Because
81   // ClientCertStoreChromeOS filters also for the right slot, we have to import
82   // the certs at first.
83   // Since the certs are imported, the store can be tested by using its public
84   // interface (GetClientCerts), which will read the certs from NSS.
85   bool SelectClientCerts(const CertificateList& input_certs,
86                          const SSLCertRequestInfo& cert_request_info,
87                          CertificateList* selected_certs) {
88     if (!test_db_.is_open()) {
89       LOG(ERROR) << "NSS DB could not be constructed.";
90       return false;
91     }
92
93     // Only user certs are considered for the cert request, which means that the
94     // private key must be known to NSS. Import all private keys for certs that
95     // are used througout the test.
96     if (!ImportSensitiveKeyFromFile(
97             GetTestCertsDirectory(), "client_1.pk8", test_db_.slot()) ||
98         !ImportSensitiveKeyFromFile(
99             GetTestCertsDirectory(), "client_2.pk8", test_db_.slot())) {
100       return false;
101     }
102
103     for (CertificateList::const_iterator it = input_certs.begin();
104          it != input_certs.end();
105          ++it) {
106       if (!ImportClientCertToSlot(*it, test_db_.slot()))
107         return false;
108     }
109     base::RunLoop run_loop;
110     store_.GetClientCerts(
111         cert_request_info, selected_certs, run_loop.QuitClosure());
112     run_loop.Run();
113     return true;
114   }
115
116  private:
117   crypto::ScopedTestNSSDB test_db_;
118   ClientCertStoreChromeOS store_;
119 };
120
121 // ClientCertStoreChromeOS derives from ClientCertStoreNSS and delegates the
122 // filtering by issuer to that base class.
123 // To verify that this delegation is functional, run the same filtering tests as
124 // for the other implementations. These tests are defined in
125 // client_cert_store_unittest-inl.h and are instantiated for each platform.
126 INSTANTIATE_TYPED_TEST_CASE_P(ClientCertStoreTestChromeOS,
127                               ClientCertStoreTest,
128                               ClientCertStoreChromeOSTestDelegate);
129
130 class ClientCertStoreChromeOSTest : public ::testing::Test {
131  public:
132   scoped_refptr<X509Certificate> ImportCertToSlot(
133       const std::string& cert_filename,
134       const std::string& key_filename,
135       PK11SlotInfo* slot) {
136     return ImportClientCertAndKeyFromFile(
137         GetTestCertsDirectory(), cert_filename, key_filename, slot);
138   }
139 };
140
141 // Ensure that cert requests, that are started before the filter is initialized,
142 // will wait for the initialization and succeed afterwards.
143 TEST_F(ClientCertStoreChromeOSTest, RequestWaitsForNSSInitAndSucceeds) {
144   crypto::ScopedTestNSSDB test_db;
145   ASSERT_TRUE(test_db.is_open());
146
147   TestCertFilter* cert_filter =
148       new TestCertFilter(false /* init asynchronously */);
149   ClientCertStoreChromeOS store(
150       make_scoped_ptr(cert_filter),
151       ClientCertStoreChromeOS::PasswordDelegateFactory());
152
153   scoped_refptr<X509Certificate> cert_1(
154       ImportCertToSlot("client_1.pem", "client_1.pk8", test_db.slot()));
155   ASSERT_TRUE(cert_1.get());
156
157   // Request any client certificate, which is expected to match client_1.
158   scoped_refptr<SSLCertRequestInfo> request_all(new SSLCertRequestInfo());
159
160   base::RunLoop run_loop;
161   store.GetClientCerts(
162       *request_all, &request_all->client_certs, run_loop.QuitClosure());
163
164   {
165     base::RunLoop run_loop_inner;
166     run_loop_inner.RunUntilIdle();
167     // GetClientCerts should wait for the initialization of the filter to
168     // finish.
169     ASSERT_EQ(0u, request_all->client_certs.size());
170     EXPECT_TRUE(cert_filter->init_called());
171   }
172   cert_filter->FinishInit();
173   run_loop.Run();
174
175   ASSERT_EQ(1u, request_all->client_certs.size());
176 }
177
178 // Ensure that cert requests, that are started after the filter was initialized,
179 // will succeed.
180 TEST_F(ClientCertStoreChromeOSTest, RequestsAfterNSSInitSucceed) {
181   crypto::ScopedTestNSSDB test_db;
182   ASSERT_TRUE(test_db.is_open());
183
184   ClientCertStoreChromeOS store(
185       make_scoped_ptr(new TestCertFilter(true /* init synchronously */)),
186       ClientCertStoreChromeOS::PasswordDelegateFactory());
187
188   scoped_refptr<X509Certificate> cert_1(
189       ImportCertToSlot("client_1.pem", "client_1.pk8", test_db.slot()));
190   ASSERT_TRUE(cert_1.get());
191
192   scoped_refptr<SSLCertRequestInfo> request_all(new SSLCertRequestInfo());
193
194   base::RunLoop run_loop;
195   store.GetClientCerts(
196       *request_all, &request_all->client_certs, run_loop.QuitClosure());
197   run_loop.Run();
198
199   ASSERT_EQ(1u, request_all->client_certs.size());
200 }
201
202 TEST_F(ClientCertStoreChromeOSTest, Filter) {
203   crypto::ScopedTestNSSDB test_db;
204   ASSERT_TRUE(test_db.is_open());
205
206   TestCertFilter* cert_filter =
207       new TestCertFilter(true /* init synchronously */);
208   ClientCertStoreChromeOS store(
209       make_scoped_ptr(cert_filter),
210       ClientCertStoreChromeOS::PasswordDelegateFactory());
211
212   scoped_refptr<X509Certificate> cert_1(
213       ImportCertToSlot("client_1.pem", "client_1.pk8", test_db.slot()));
214   ASSERT_TRUE(cert_1.get());
215   scoped_refptr<X509Certificate> cert_2(
216       ImportCertToSlot("client_2.pem", "client_2.pk8", test_db.slot()));
217   ASSERT_TRUE(cert_2.get());
218
219   scoped_refptr<SSLCertRequestInfo> request_all(new SSLCertRequestInfo());
220
221   {
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();
227
228     ASSERT_EQ(1u, selected_certs.size());
229     EXPECT_TRUE(cert_1->Equals(selected_certs[0].get()));
230   }
231
232   {
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();
238
239     ASSERT_EQ(1u, selected_certs.size());
240     EXPECT_TRUE(cert_2->Equals(selected_certs[0].get()));
241   }
242 }
243
244 }  // namespace net