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 |