OLD | NEW |
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_win.h" | 5 #include "net/ssl/client_cert_store_win.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #define SECURITY_WIN32 // Needs to be defined before including security.h | 10 #define SECURITY_WIN32 // Needs to be defined before including security.h |
11 #include <windows.h> | 11 #include <windows.h> |
12 #include <security.h> | 12 #include <security.h> |
13 | 13 |
14 #include "base/bind.h" | 14 #include "base/bind.h" |
15 #include "base/bind_helpers.h" | 15 #include "base/bind_helpers.h" |
16 #include "base/callback.h" | 16 #include "base/callback.h" |
17 #include "base/logging.h" | 17 #include "base/logging.h" |
18 #include "base/memory/ptr_util.h" | 18 #include "base/memory/ptr_util.h" |
| 19 #include "base/numerics/safe_conversions.h" |
19 #include "base/task_runner_util.h" | 20 #include "base/task_runner_util.h" |
20 #include "base/threading/thread_task_runner_handle.h" | 21 #include "base/threading/thread_task_runner_handle.h" |
21 #include "crypto/wincrypt_shim.h" | 22 #include "crypto/wincrypt_shim.h" |
22 #include "net/cert/x509_util.h" | 23 #include "net/cert/x509_util.h" |
| 24 #include "net/cert/x509_util_win.h" |
23 #include "net/ssl/ssl_platform_key_win.h" | 25 #include "net/ssl/ssl_platform_key_win.h" |
24 #include "net/ssl/ssl_private_key.h" | 26 #include "net/ssl/ssl_private_key.h" |
25 | 27 |
26 namespace net { | 28 namespace net { |
27 | 29 |
28 namespace { | 30 namespace { |
29 | 31 |
30 class ClientCertIdentityWin : public ClientCertIdentity { | 32 class ClientCertIdentityWin : public ClientCertIdentity { |
31 public: | 33 public: |
32 // Takes ownership of |cert_context|. | 34 // Takes ownership of |cert_context|. |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 PCCERT_CONTEXT cert_context2 = NULL; | 155 PCCERT_CONTEXT cert_context2 = NULL; |
154 BOOL ok = CertAddCertificateContextToStore(NULL, cert_context, | 156 BOOL ok = CertAddCertificateContextToStore(NULL, cert_context, |
155 CERT_STORE_ADD_USE_EXISTING, | 157 CERT_STORE_ADD_USE_EXISTING, |
156 &cert_context2); | 158 &cert_context2); |
157 if (!ok) { | 159 if (!ok) { |
158 NOTREACHED(); | 160 NOTREACHED(); |
159 continue; | 161 continue; |
160 } | 162 } |
161 | 163 |
162 // Grab the intermediates, if any. | 164 // Grab the intermediates, if any. |
163 X509Certificate::OSCertHandles intermediates; | 165 std::vector<PCCERT_CONTEXT> intermediates; |
164 for (DWORD i = 1; i < chain_context->rgpChain[0]->cElement; ++i) { | 166 for (DWORD i = 1; i < chain_context->rgpChain[0]->cElement; ++i) { |
165 PCCERT_CONTEXT chain_intermediate = | 167 PCCERT_CONTEXT chain_intermediate = |
166 chain_context->rgpChain[0]->rgpElement[i]->pCertContext; | 168 chain_context->rgpChain[0]->rgpElement[i]->pCertContext; |
167 PCCERT_CONTEXT copied_intermediate = NULL; | 169 PCCERT_CONTEXT copied_intermediate = NULL; |
168 ok = CertAddCertificateContextToStore(NULL, chain_intermediate, | 170 ok = CertAddCertificateContextToStore(NULL, chain_intermediate, |
169 CERT_STORE_ADD_USE_EXISTING, | 171 CERT_STORE_ADD_USE_EXISTING, |
170 &copied_intermediate); | 172 &copied_intermediate); |
171 if (ok) | 173 if (ok) |
172 intermediates.push_back(copied_intermediate); | 174 intermediates.push_back(copied_intermediate); |
173 } | 175 } |
174 | 176 |
175 // Drop the self-signed root, if any. Match Internet Explorer in not sending | 177 // Drop the self-signed root, if any. Match Internet Explorer in not sending |
176 // it. Although the root's signature is irrelevant for authentication, some | 178 // it. Although the root's signature is irrelevant for authentication, some |
177 // servers reject chains if the root is explicitly sent and has a weak | 179 // servers reject chains if the root is explicitly sent and has a weak |
178 // signature algorithm. See https://crbug.com/607264. | 180 // signature algorithm. See https://crbug.com/607264. |
179 // | 181 // |
180 // The leaf or a intermediate may also have a weak signature algorithm but, | 182 // The leaf or a intermediate may also have a weak signature algorithm but, |
181 // in that case, assume it is a configuration error. | 183 // in that case, assume it is a configuration error. |
182 if (!intermediates.empty() && | 184 if (!intermediates.empty() && |
183 X509Certificate::IsSelfSigned(intermediates.back())) { | 185 x509_util::IsSelfSigned(intermediates.back())) { |
184 CertFreeCertificateContext(intermediates.back()); | 186 CertFreeCertificateContext(intermediates.back()); |
185 intermediates.pop_back(); | 187 intermediates.pop_back(); |
186 } | 188 } |
187 | 189 |
| 190 // TODO(mattm): The following comment is only true when not using |
| 191 // USE_BYTE_CERTS. Remove it once the non-byte-certs code is also removed. |
188 // TODO(svaldez): cert currently wraps cert_context2 which may be backed | 192 // TODO(svaldez): cert currently wraps cert_context2 which may be backed |
189 // by a smartcard with threading difficulties. Instead, create a fresh | 193 // by a smartcard with threading difficulties. Instead, create a fresh |
190 // X509Certificate with CreateFromBytes and route cert_context2 into the | 194 // X509Certificate with CreateFromBytes and route cert_context2 into the |
191 // SSLPrivateKey. Probably changing CertificateList to be a | 195 // SSLPrivateKey. Probably changing CertificateList to be a |
192 // pair<X509Certificate, SSLPrivateKeyCallback>. | 196 // pair<X509Certificate, SSLPrivateKeyCallback>. |
193 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( | 197 scoped_refptr<X509Certificate> cert = |
194 cert_context2, intermediates); | 198 x509_util::CreateX509CertificateFromCertContexts(cert_context2, |
| 199 intermediates); |
195 if (cert) { | 200 if (cert) { |
196 selected_identities->push_back(base::MakeUnique<ClientCertIdentityWin>( | 201 selected_identities->push_back(base::MakeUnique<ClientCertIdentityWin>( |
197 std::move(cert), | 202 std::move(cert), |
198 cert_context2, // Takes ownership of |cert_context2|. | 203 cert_context2, // Takes ownership of |cert_context2|. |
199 current_thread)); // The key must be acquired on the same thread, as | 204 current_thread)); // The key must be acquired on the same thread, as |
200 // the PCCERT_CONTEXT may not be thread safe. | 205 // the PCCERT_CONTEXT may not be thread safe. |
201 } | 206 } |
202 for (size_t i = 0; i < intermediates.size(); ++i) | 207 for (size_t i = 0; i < intermediates.size(); ++i) |
203 CertFreeCertificateContext(intermediates[i]); | 208 CertFreeCertificateContext(intermediates[i]); |
204 } | 209 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 ClientCertIdentityList* selected_identities) { | 257 ClientCertIdentityList* selected_identities) { |
253 ScopedHCERTSTORE test_store(CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, | 258 ScopedHCERTSTORE test_store(CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, |
254 NULL)); | 259 NULL)); |
255 if (!test_store) | 260 if (!test_store) |
256 return false; | 261 return false; |
257 | 262 |
258 // Add available certificates to the test store. | 263 // Add available certificates to the test store. |
259 for (size_t i = 0; i < input_certs.size(); ++i) { | 264 for (size_t i = 0; i < input_certs.size(); ++i) { |
260 // Add the certificate to the test store. | 265 // Add the certificate to the test store. |
261 PCCERT_CONTEXT cert = NULL; | 266 PCCERT_CONTEXT cert = NULL; |
262 if (!CertAddCertificateContextToStore(test_store, | 267 std::string der_cert; |
263 input_certs[i]->os_cert_handle(), | 268 X509Certificate::GetDEREncoded(input_certs[i]->os_cert_handle(), &der_cert); |
264 CERT_STORE_ADD_NEW, &cert)) { | 269 if (!CertAddEncodedCertificateToStore( |
| 270 test_store, X509_ASN_ENCODING, |
| 271 reinterpret_cast<const BYTE*>(der_cert.data()), |
| 272 base::checked_cast<DWORD>(der_cert.size()), CERT_STORE_ADD_NEW, |
| 273 &cert)) { |
265 return false; | 274 return false; |
266 } | 275 } |
| 276 // Hold the reference to the certificate (since we requested a copy). |
| 277 ScopedPCCERT_CONTEXT scoped_cert(cert); |
| 278 |
267 // Add dummy private key data to the certificate - otherwise the certificate | 279 // Add dummy private key data to the certificate - otherwise the certificate |
268 // would be discarded by the filtering routines. | 280 // would be discarded by the filtering routines. |
269 CRYPT_KEY_PROV_INFO private_key_data; | 281 CRYPT_KEY_PROV_INFO private_key_data; |
270 memset(&private_key_data, 0, sizeof(private_key_data)); | 282 memset(&private_key_data, 0, sizeof(private_key_data)); |
271 if (!CertSetCertificateContextProperty(cert, | 283 if (!CertSetCertificateContextProperty(cert, |
272 CERT_KEY_PROV_INFO_PROP_ID, | 284 CERT_KEY_PROV_INFO_PROP_ID, |
273 0, &private_key_data)) { | 285 0, &private_key_data)) { |
274 return false; | 286 return false; |
275 } | 287 } |
276 // Decrement the reference count of the certificate (since we requested a | |
277 // copy). | |
278 if (!CertFreeCertificateContext(cert)) | |
279 return false; | |
280 } | 288 } |
281 | 289 |
282 GetClientCertsImpl(test_store.get(), request, selected_identities); | 290 GetClientCertsImpl(test_store.get(), request, selected_identities); |
283 return true; | 291 return true; |
284 } | 292 } |
285 | 293 |
286 } // namespace net | 294 } // namespace net |
OLD | NEW |