| 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 | 
|---|