Chromium Code Reviews| 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_nss.h" | 5 #include "net/ssl/client_cert_store_nss.h" |
| 6 | 6 |
| 7 #include <nss.h> | 7 #include <nss.h> |
| 8 #include <ssl.h> | 8 #include <ssl.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| 11 #include <memory> | 11 #include <memory> |
| 12 #include <utility> | 12 #include <utility> |
| 13 #include <vector> | |
| 13 | 14 |
| 14 #include "base/bind.h" | 15 #include "base/bind.h" |
| 15 #include "base/bind_helpers.h" | 16 #include "base/bind_helpers.h" |
| 16 #include "base/location.h" | 17 #include "base/location.h" |
| 17 #include "base/logging.h" | 18 #include "base/logging.h" |
| 18 #include "base/strings/string_piece.h" | 19 #include "base/strings/string_piece.h" |
| 19 #include "base/threading/worker_pool.h" | 20 #include "base/threading/worker_pool.h" |
| 20 #include "crypto/nss_crypto_module_delegate.h" | 21 #include "crypto/nss_crypto_module_delegate.h" |
| 22 #include "net/cert/scoped_nss_types.h" | |
| 21 #include "net/cert/x509_util.h" | 23 #include "net/cert/x509_util.h" |
| 22 #include "net/ssl/ssl_cert_request_info.h" | 24 #include "net/ssl/ssl_cert_request_info.h" |
| 25 #include "net/third_party/nss/ssl/cmpcert.h" | |
| 23 | 26 |
| 24 namespace net { | 27 namespace net { |
| 25 | 28 |
| 26 ClientCertStoreNSS::ClientCertStoreNSS( | 29 ClientCertStoreNSS::ClientCertStoreNSS( |
| 27 const PasswordDelegateFactory& password_delegate_factory) | 30 const PasswordDelegateFactory& password_delegate_factory) |
| 28 : password_delegate_factory_(password_delegate_factory) {} | 31 : password_delegate_factory_(password_delegate_factory) {} |
| 29 | 32 |
| 30 ClientCertStoreNSS::~ClientCertStoreNSS() {} | 33 ClientCertStoreNSS::~ClientCertStoreNSS() {} |
| 31 | 34 |
| 32 void ClientCertStoreNSS::GetClientCerts(const SSLCertRequestInfo& request, | 35 void ClientCertStoreNSS::GetClientCerts(const SSLCertRequestInfo& request, |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 56 | 59 |
| 57 // static | 60 // static |
| 58 void ClientCertStoreNSS::FilterCertsOnWorkerThread( | 61 void ClientCertStoreNSS::FilterCertsOnWorkerThread( |
| 59 const CertificateList& certs, | 62 const CertificateList& certs, |
| 60 const SSLCertRequestInfo& request, | 63 const SSLCertRequestInfo& request, |
| 61 CertificateList* filtered_certs) { | 64 CertificateList* filtered_certs) { |
| 62 DCHECK(filtered_certs); | 65 DCHECK(filtered_certs); |
| 63 | 66 |
| 64 filtered_certs->clear(); | 67 filtered_certs->clear(); |
| 65 | 68 |
| 66 // Create a "fake" CERTDistNames structure. No public API exists to create | |
| 67 // one from a list of issuers. | |
| 68 CERTDistNames ca_names; | |
| 69 ca_names.arena = NULL; | |
| 70 ca_names.nnames = 0; | |
| 71 ca_names.names = NULL; | |
| 72 ca_names.head = NULL; | |
| 73 | |
| 74 std::vector<SECItem> ca_names_items(request.cert_authorities.size()); | |
| 75 for (size_t i = 0; i < request.cert_authorities.size(); ++i) { | |
| 76 const std::string& authority = request.cert_authorities[i]; | |
| 77 ca_names_items[i].type = siBuffer; | |
| 78 ca_names_items[i].data = | |
| 79 reinterpret_cast<unsigned char*>(const_cast<char*>(authority.data())); | |
| 80 ca_names_items[i].len = static_cast<unsigned int>(authority.size()); | |
| 81 } | |
| 82 ca_names.nnames = static_cast<int>(ca_names_items.size()); | |
| 83 if (!ca_names_items.empty()) | |
| 84 ca_names.names = &ca_names_items[0]; | |
| 85 | |
| 86 size_t num_raw = 0; | 69 size_t num_raw = 0; |
| 87 for (const auto& cert : certs) { | 70 for (const auto& cert : certs) { |
| 88 ++num_raw; | 71 ++num_raw; |
| 89 X509Certificate::OSCertHandle handle = cert->os_cert_handle(); | 72 X509Certificate::OSCertHandle handle = cert->os_cert_handle(); |
| 90 | 73 |
| 91 // Only offer unexpired certificates. | 74 // Only offer unexpired certificates. |
| 92 if (CERT_CheckCertValidTimes(handle, PR_Now(), PR_TRUE) != | 75 if (CERT_CheckCertValidTimes(handle, PR_Now(), PR_TRUE) != |
| 93 secCertTimeValid) { | 76 secCertTimeValid) { |
| 94 DVLOG(2) << "skipped expired cert: " | 77 DVLOG(2) << "skipped expired cert: " |
| 95 << base::StringPiece(handle->nickname); | 78 << base::StringPiece(handle->nickname); |
| 96 continue; | 79 continue; |
| 97 } | 80 } |
| 98 | 81 |
| 99 // Check if the certificate issuer is allowed by the server. | 82 std::vector<ScopedCERTCertificate> chain; |
| 100 if (!request.cert_authorities.empty() && | 83 if (!MatchClientCertificateIssuers(handle, request.cert_authorities, |
| 101 NSS_CmpCertChainWCANames(handle, &ca_names) != SECSuccess) { | 84 &chain)) { |
| 102 DVLOG(2) << "skipped non-matching cert: " | 85 DVLOG(2) << "skipped non-matching cert: " |
| 103 << base::StringPiece(handle->nickname); | 86 << base::StringPiece(handle->nickname); |
| 104 continue; | 87 continue; |
| 105 } | 88 } |
| 106 | 89 |
| 107 DVLOG(2) << "matched cert: " << base::StringPiece(handle->nickname); | 90 DVLOG(2) << "matched cert: " << base::StringPiece(handle->nickname); |
| 108 filtered_certs->push_back(cert); | 91 |
| 92 std::vector<base::StringPiece> der_chain; | |
| 93 for (const auto& chain_cert : chain) { | |
| 94 der_chain.push_back(base::StringPiece( | |
| 95 reinterpret_cast<const char*>(chain_cert->derCert.data), | |
| 96 chain_cert->derCert.len)); | |
| 97 } | |
| 98 | |
| 99 scoped_refptr<X509Certificate> full_cert = | |
| 100 X509Certificate::CreateFromDERCertChain(der_chain); | |
| 101 if (!full_cert.get()) { | |
| 102 DVLOG(2) << "could not decode chain: " | |
| 103 << base::StringPiece(handle->nickname); | |
| 104 continue; | |
| 105 } | |
|
Ryan Sleevi
2016/07/29 00:37:44
Why do you indirect through the DER, when we've go
davidben
2016/07/29 15:14:11
You know, the for loop is actually much much less
| |
| 106 | |
| 107 filtered_certs->push_back(full_cert); | |
| 109 } | 108 } |
| 110 DVLOG(2) << "num_raw:" << num_raw | 109 DVLOG(2) << "num_raw:" << num_raw |
| 111 << " num_filtered:" << filtered_certs->size(); | 110 << " num_filtered:" << filtered_certs->size(); |
| 112 | 111 |
| 113 std::sort(filtered_certs->begin(), filtered_certs->end(), | 112 std::sort(filtered_certs->begin(), filtered_certs->end(), |
| 114 x509_util::ClientCertSorter()); | 113 x509_util::ClientCertSorter()); |
| 115 } | 114 } |
| 116 | 115 |
| 117 void ClientCertStoreNSS::GetAndFilterCertsOnWorkerThread( | 116 void ClientCertStoreNSS::GetAndFilterCertsOnWorkerThread( |
| 118 std::unique_ptr<crypto::CryptoModuleBlockingPasswordDelegate> | 117 std::unique_ptr<crypto::CryptoModuleBlockingPasswordDelegate> |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 138 } | 137 } |
| 139 for (CERTCertListNode* node = CERT_LIST_HEAD(found_certs); | 138 for (CERTCertListNode* node = CERT_LIST_HEAD(found_certs); |
| 140 !CERT_LIST_END(node, found_certs); node = CERT_LIST_NEXT(node)) { | 139 !CERT_LIST_END(node, found_certs); node = CERT_LIST_NEXT(node)) { |
| 141 certs->push_back(X509Certificate::CreateFromHandle( | 140 certs->push_back(X509Certificate::CreateFromHandle( |
| 142 node->cert, X509Certificate::OSCertHandles())); | 141 node->cert, X509Certificate::OSCertHandles())); |
| 143 } | 142 } |
| 144 CERT_DestroyCertList(found_certs); | 143 CERT_DestroyCertList(found_certs); |
| 145 } | 144 } |
| 146 | 145 |
| 147 } // namespace net | 146 } // namespace net |
| OLD | NEW |