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 "net/base/origin_bound_cert_service.h" | 5 #include "net/base/origin_bound_cert_service.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/scoped_ptr.h" |
11 #include "crypto/rsa_private_key.h" | 11 #include "crypto/rsa_private_key.h" |
12 #include "net/base/default_origin_bound_cert_store.h" | 12 #include "net/base/default_origin_bound_cert_store.h" |
13 #include "net/base/net_errors.h" | |
14 #include "net/base/test_completion_callback.h" | |
13 #include "net/base/x509_certificate.h" | 15 #include "net/base/x509_certificate.h" |
14 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
15 | 17 |
16 namespace net { | 18 namespace net { |
17 | 19 |
20 class OriginBoundCertServiceTest : public testing::Test { | |
21 }; | |
22 | |
23 class ExplodingCallback : public CallbackRunner<Tuple1<int> > { | |
24 public: | |
25 virtual void RunWithParams(const Tuple1<int>& params) { | |
26 FAIL(); | |
27 } | |
28 }; | |
29 | |
18 // See http://crbug.com/91512 - implement OpenSSL version of CreateSelfSigned. | 30 // See http://crbug.com/91512 - implement OpenSSL version of CreateSelfSigned. |
19 #if !defined(USE_OPENSSL) | 31 #if !defined(USE_OPENSSL) |
20 | 32 |
21 TEST(OriginBoundCertServiceTest, DuplicateCertTest) { | 33 TEST_F(OriginBoundCertServiceTest, CacheHit) { |
22 scoped_refptr<OriginBoundCertService> service( | 34 scoped_ptr<OriginBoundCertService> service( |
23 new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL))); | 35 new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL))); |
24 std::string origin1("https://encrypted.google.com/"); | 36 std::string origin("https://encrypted.google.com:443"); |
25 std::string origin2("https://www.verisign.com/"); | |
26 | 37 |
27 // The store should start out empty and should increment appropriately. | 38 int error; |
28 std::string private_key_info_1a, der_cert_1a; | 39 TestCompletionCallback callback; |
29 EXPECT_EQ(0, service->GetCertCount()); | 40 OriginBoundCertService::RequestHandle request_handle; |
30 EXPECT_TRUE(service->GetOriginBoundCert( | |
31 origin1, &private_key_info_1a, &der_cert_1a)); | |
32 EXPECT_EQ(1, service->GetCertCount()); | |
33 | 41 |
34 // We should get the same cert and key for the same origin. | 42 // Asynchronous completion. |
35 std::string private_key_info_1b, der_cert_1b; | 43 std::string private_key_info1, der_cert1; |
36 EXPECT_TRUE(service->GetOriginBoundCert( | 44 EXPECT_EQ(0, service->get_cert_count()); |
37 origin1, &private_key_info_1b, &der_cert_1b)); | 45 error = service->GetOriginBoundCert( |
38 EXPECT_EQ(1, service->GetCertCount()); | 46 origin, &private_key_info1, &der_cert1, &callback, &request_handle); |
39 EXPECT_EQ(private_key_info_1a, private_key_info_1b); | 47 EXPECT_EQ(ERR_IO_PENDING, error); |
40 EXPECT_EQ(der_cert_1a, der_cert_1b); | 48 EXPECT_TRUE(request_handle != NULL); |
49 error = callback.WaitForResult(); | |
50 EXPECT_EQ(OK, error); | |
51 EXPECT_EQ(1, service->get_cert_count()); | |
52 EXPECT_FALSE(private_key_info1.empty()); | |
53 EXPECT_FALSE(der_cert1.empty()); | |
41 | 54 |
42 // We should get a different cert and key for different origins. | 55 // Synchronous completion. |
43 std::string private_key_info_2, der_cert_2; | 56 std::string private_key_info2, der_cert2; |
44 EXPECT_TRUE(service->GetOriginBoundCert( | 57 error = service->GetOriginBoundCert( |
45 origin2, &private_key_info_2, &der_cert_2)); | 58 origin, &private_key_info2, &der_cert2, &callback, &request_handle); |
46 EXPECT_EQ(2, service->GetCertCount()); | 59 EXPECT_TRUE(request_handle == NULL); |
47 EXPECT_NE(private_key_info_1a, private_key_info_2); | 60 EXPECT_EQ(OK, error); |
48 EXPECT_NE(der_cert_1a, der_cert_2); | 61 EXPECT_EQ(1, service->get_cert_count()); |
62 | |
63 EXPECT_EQ(private_key_info1, private_key_info2); | |
64 EXPECT_EQ(der_cert1, der_cert2); | |
65 | |
66 EXPECT_EQ(2u, service->requests()); | |
67 EXPECT_EQ(1u, service->cache_hits()); | |
68 EXPECT_EQ(0u, service->inflight_joins()); | |
49 } | 69 } |
50 | 70 |
51 TEST(OriginBoundCertServiceTest, ExtractValuesFromBytes) { | 71 TEST_F(OriginBoundCertServiceTest, StoreCerts) { |
52 scoped_refptr<OriginBoundCertService> service( | 72 scoped_ptr<OriginBoundCertService> service( |
53 new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL))); | 73 new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL))); |
54 std::string origin("https://encrypted.google.com/"); | 74 int error; |
75 TestCompletionCallback callback; | |
76 OriginBoundCertService::RequestHandle request_handle; | |
77 | |
78 std::string origin1("https://encrypted.google.com:443"); | |
wtc
2011/08/09 00:43:34
Is the explicit :433 port required in an origin?
rkn
2011/08/09 03:25:38
I don't believe so.
| |
79 std::string private_key_info1, der_cert1; | |
80 EXPECT_EQ(0, service->get_cert_count()); | |
81 error = service->GetOriginBoundCert( | |
82 origin1, &private_key_info1, &der_cert1, &callback, &request_handle); | |
83 EXPECT_EQ(ERR_IO_PENDING, error); | |
84 EXPECT_TRUE(request_handle != NULL); | |
85 error = callback.WaitForResult(); | |
86 EXPECT_EQ(OK, error); | |
87 EXPECT_EQ(1, service->get_cert_count()); | |
88 | |
89 std::string origin2("https://www.verisign.com:443"); | |
90 std::string private_key_info2, der_cert2; | |
91 error = service->GetOriginBoundCert( | |
92 origin2, &private_key_info2, &der_cert2, &callback, &request_handle); | |
93 EXPECT_EQ(ERR_IO_PENDING, error); | |
94 EXPECT_TRUE(request_handle != NULL); | |
95 error = callback.WaitForResult(); | |
96 EXPECT_EQ(OK, error); | |
97 EXPECT_EQ(2, service->get_cert_count()); | |
98 | |
99 std::string origin3("https://www.twitter.com:443"); | |
100 std::string private_key_info3, der_cert3; | |
101 error = service->GetOriginBoundCert( | |
102 origin3, &private_key_info3, &der_cert3, &callback, &request_handle); | |
103 EXPECT_EQ(ERR_IO_PENDING, error); | |
104 EXPECT_TRUE(request_handle != NULL); | |
105 error = callback.WaitForResult(); | |
106 EXPECT_EQ(OK, error); | |
107 EXPECT_EQ(3, service->get_cert_count()); | |
108 | |
109 EXPECT_NE(private_key_info1, private_key_info2); | |
110 EXPECT_NE(der_cert1, der_cert2); | |
111 EXPECT_NE(private_key_info1, private_key_info3); | |
112 EXPECT_NE(der_cert1, der_cert3); | |
113 EXPECT_NE(private_key_info2, private_key_info3); | |
114 EXPECT_NE(der_cert2, der_cert3); | |
115 } | |
116 | |
117 // Tests an inflight join. | |
118 TEST_F(OriginBoundCertServiceTest, InflightJoin) { | |
119 scoped_ptr<OriginBoundCertService> service( | |
120 new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL))); | |
121 std::string origin("https://encrypted.google.com:443"); | |
122 int error; | |
123 | |
124 std::string private_key_info1, der_cert1; | |
125 TestCompletionCallback callback1; | |
126 OriginBoundCertService::RequestHandle request_handle1; | |
127 | |
128 std::string private_key_info2, der_cert2; | |
129 TestCompletionCallback callback2; | |
130 OriginBoundCertService::RequestHandle request_handle2; | |
131 | |
132 error = service->GetOriginBoundCert( | |
133 origin, &private_key_info1, &der_cert1, &callback1, &request_handle1); | |
134 EXPECT_EQ(ERR_IO_PENDING, error); | |
135 EXPECT_TRUE(request_handle1 != NULL); | |
136 error = service->GetOriginBoundCert( | |
137 origin, &private_key_info2, &der_cert2, &callback2, &request_handle2); | |
138 EXPECT_EQ(ERR_IO_PENDING, error); | |
139 EXPECT_TRUE(request_handle2 != NULL); | |
140 | |
141 error = callback1.WaitForResult(); | |
142 EXPECT_EQ(OK, error); | |
143 error = callback2.WaitForResult(); | |
144 EXPECT_EQ(OK, error); | |
145 | |
146 EXPECT_EQ(2u, service->requests()); | |
147 EXPECT_EQ(0u, service->cache_hits()); | |
148 EXPECT_EQ(1u, service->inflight_joins()); | |
149 } | |
150 | |
151 TEST_F(OriginBoundCertServiceTest, ExtractValuesFromBytes) { | |
152 scoped_ptr<OriginBoundCertService> service( | |
153 new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL))); | |
154 std::string origin("https://encrypted.google.com:443"); | |
55 std::string private_key_info, der_cert; | 155 std::string private_key_info, der_cert; |
56 EXPECT_TRUE(service->GetOriginBoundCert( | 156 int error; |
57 origin, &private_key_info, &der_cert)); | 157 TestCompletionCallback callback; |
158 OriginBoundCertService::RequestHandle request_handle; | |
159 | |
160 error = service->GetOriginBoundCert( | |
161 origin, &private_key_info, &der_cert, &callback, &request_handle); | |
162 EXPECT_EQ(ERR_IO_PENDING, error); | |
163 EXPECT_TRUE(request_handle != NULL); | |
164 error = callback.WaitForResult(); | |
165 EXPECT_EQ(OK, error); | |
166 | |
167 // Check that we can retrieve the key from the bytes. | |
58 std::vector<uint8> key_vec(private_key_info.begin(), private_key_info.end()); | 168 std::vector<uint8> key_vec(private_key_info.begin(), private_key_info.end()); |
59 | |
60 // Check that we can retrieve the key pair from the bytes. | |
61 scoped_ptr<crypto::RSAPrivateKey> private_key( | 169 scoped_ptr<crypto::RSAPrivateKey> private_key( |
62 crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_vec)); | 170 crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_vec)); |
63 EXPECT_TRUE(private_key != NULL); | 171 EXPECT_TRUE(private_key != NULL); |
64 | 172 |
65 // Check that we can retrieve the cert from the bytes. | 173 // Check that we can retrieve the cert from the bytes. |
66 scoped_refptr<X509Certificate> x509cert( | 174 scoped_refptr<X509Certificate> x509cert( |
67 X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size())); | 175 X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size())); |
68 EXPECT_TRUE(x509cert != NULL); | 176 EXPECT_TRUE(x509cert != NULL); |
69 } | 177 } |
70 | 178 |
179 // Tests that the callback of a canceled request is never made. | |
180 TEST_F(OriginBoundCertServiceTest, CancelRequest) { | |
181 scoped_ptr<OriginBoundCertService> service( | |
182 new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL))); | |
183 std::string origin("https://encrypted.google.com:443"); | |
184 std::string private_key_info, der_cert; | |
185 int error; | |
186 ExplodingCallback exploding_callback; | |
187 OriginBoundCertService::RequestHandle request_handle; | |
188 | |
189 error = service->GetOriginBoundCert(origin, | |
190 &private_key_info, | |
191 &der_cert, | |
192 &exploding_callback, | |
193 &request_handle); | |
194 EXPECT_EQ(ERR_IO_PENDING, error); | |
195 EXPECT_TRUE(request_handle != NULL); | |
196 service->CancelRequest(request_handle); | |
197 | |
198 // Issue a few more requests to the worker pool and wait for their | |
199 // completion, so that the task of the canceled request (which runs on a | |
200 // worker thread) is likely to complete by the end of this test. | |
201 TestCompletionCallback callback; | |
202 for (int i = 0; i < 5; ++i) { | |
203 error = service->GetOriginBoundCert( | |
204 std::string(1, (char) ('a' + i)), | |
wtc
2011/08/09 00:43:34
Should we construct more realistic origins?
| |
205 &private_key_info, | |
206 &der_cert, | |
207 &callback, | |
208 &request_handle); | |
wtc
2011/08/09 00:43:34
Align the function arguments.
| |
209 EXPECT_EQ(ERR_IO_PENDING, error); | |
210 EXPECT_TRUE(request_handle != NULL); | |
211 error = callback.WaitForResult(); | |
212 } | |
213 } | |
214 | |
71 #endif // !defined(USE_OPENSSL) | 215 #endif // !defined(USE_OPENSSL) |
72 | 216 |
73 } // namespace net | 217 } // namespace net |
OLD | NEW |