OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_impl.h" | 5 #include "net/ssl/client_cert_store_impl.h" |
6 | 6 |
7 #include <CommonCrypto/CommonDigest.h> | 7 #include <CommonCrypto/CommonDigest.h> |
8 #include <CoreFoundation/CFArray.h> | 8 #include <CoreFoundation/CFArray.h> |
9 #include <CoreServices/CoreServices.h> | 9 #include <CoreServices/CoreServices.h> |
10 #include <Security/SecBase.h> | 10 #include <Security/SecBase.h> |
11 #include <Security/Security.h> | 11 #include <Security/Security.h> |
12 | 12 |
13 #include <algorithm> | 13 #include <algorithm> |
14 #include <string> | 14 #include <string> |
15 | 15 |
| 16 #include "base/callback.h" |
16 #include "base/logging.h" | 17 #include "base/logging.h" |
17 #include "base/mac/mac_logging.h" | 18 #include "base/mac/mac_logging.h" |
18 #include "base/mac/scoped_cftyperef.h" | 19 #include "base/mac/scoped_cftyperef.h" |
19 #include "base/strings/sys_string_conversions.h" | 20 #include "base/strings/sys_string_conversions.h" |
20 #include "base/synchronization/lock.h" | 21 #include "base/synchronization/lock.h" |
21 #include "crypto/mac_security_services_lock.h" | 22 #include "crypto/mac_security_services_lock.h" |
22 #include "net/base/host_port_pair.h" | 23 #include "net/base/host_port_pair.h" |
23 #include "net/cert/x509_util.h" | 24 #include "net/cert/x509_util.h" |
24 #include "net/cert/x509_util_mac.h" | 25 #include "net/cert/x509_util_mac.h" |
25 | 26 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 return true; | 116 return true; |
116 } | 117 } |
117 | 118 |
118 // Examines the certificates in |preferred_cert| and |regular_certs| to find | 119 // Examines the certificates in |preferred_cert| and |regular_certs| to find |
119 // all certificates that match the client certificate request in |request|, | 120 // all certificates that match the client certificate request in |request|, |
120 // storing the matching certificates in |selected_certs|. | 121 // storing the matching certificates in |selected_certs|. |
121 // If |query_keychain| is true, Keychain Services will be queried to construct | 122 // If |query_keychain| is true, Keychain Services will be queried to construct |
122 // full certificate chains. If it is false, only the the certificates and their | 123 // full certificate chains. If it is false, only the the certificates and their |
123 // intermediates (available via X509Certificate::GetIntermediateCertificates()) | 124 // intermediates (available via X509Certificate::GetIntermediateCertificates()) |
124 // will be considered. | 125 // will be considered. |
125 bool GetClientCertsImpl(const scoped_refptr<X509Certificate>& preferred_cert, | 126 void GetClientCertsImpl(const scoped_refptr<X509Certificate>& preferred_cert, |
126 const CertificateList& regular_certs, | 127 const CertificateList& regular_certs, |
127 const SSLCertRequestInfo& request, | 128 const SSLCertRequestInfo& request, |
128 bool query_keychain, | 129 bool query_keychain, |
129 CertificateList* selected_certs) { | 130 CertificateList* selected_certs) { |
130 CertificateList preliminary_list; | 131 CertificateList preliminary_list; |
131 if (preferred_cert.get()) | 132 if (preferred_cert.get()) |
132 preliminary_list.push_back(preferred_cert); | 133 preliminary_list.push_back(preferred_cert); |
133 preliminary_list.insert(preliminary_list.end(), regular_certs.begin(), | 134 preliminary_list.insert(preliminary_list.end(), regular_certs.begin(), |
134 regular_certs.end()); | 135 regular_certs.end()); |
135 | 136 |
(...skipping 24 matching lines...) Expand all Loading... |
160 | 161 |
161 // Preferred cert should appear first in the ui, so exclude it from the | 162 // Preferred cert should appear first in the ui, so exclude it from the |
162 // sorting. | 163 // sorting. |
163 CertificateList::iterator sort_begin = selected_certs->begin(); | 164 CertificateList::iterator sort_begin = selected_certs->begin(); |
164 CertificateList::iterator sort_end = selected_certs->end(); | 165 CertificateList::iterator sort_end = selected_certs->end(); |
165 if (preferred_cert.get() && sort_begin != sort_end && | 166 if (preferred_cert.get() && sort_begin != sort_end && |
166 sort_begin->get() == preferred_cert.get()) { | 167 sort_begin->get() == preferred_cert.get()) { |
167 ++sort_begin; | 168 ++sort_begin; |
168 } | 169 } |
169 sort(sort_begin, sort_end, x509_util::ClientCertSorter()); | 170 sort(sort_begin, sort_end, x509_util::ClientCertSorter()); |
170 return true; | |
171 } | 171 } |
172 | 172 |
173 } // namespace | 173 } // namespace |
174 | 174 |
175 bool ClientCertStoreImpl::GetClientCerts(const SSLCertRequestInfo& request, | 175 void ClientCertStoreImpl::GetClientCerts(const SSLCertRequestInfo& request, |
176 CertificateList* selected_certs) { | 176 CertificateList* selected_certs, |
| 177 const base::Closure& callback) { |
177 std::string server_domain = | 178 std::string server_domain = |
178 HostPortPair::FromString(request.host_and_port).host(); | 179 HostPortPair::FromString(request.host_and_port).host(); |
179 | 180 |
180 ScopedCFTypeRef<SecIdentityRef> preferred_identity; | 181 ScopedCFTypeRef<SecIdentityRef> preferred_identity; |
181 if (!server_domain.empty()) { | 182 if (!server_domain.empty()) { |
182 // See if there's an identity preference for this domain: | 183 // See if there's an identity preference for this domain: |
183 ScopedCFTypeRef<CFStringRef> domain_str( | 184 ScopedCFTypeRef<CFStringRef> domain_str( |
184 base::SysUTF8ToCFStringRef("https://" + server_domain)); | 185 base::SysUTF8ToCFStringRef("https://" + server_domain)); |
185 SecIdentityRef identity = NULL; | 186 SecIdentityRef identity = NULL; |
186 // While SecIdentityCopyPreferences appears to take a list of CA issuers | 187 // While SecIdentityCopyPreferences appears to take a list of CA issuers |
(...skipping 11 matching lines...) Expand all Loading... |
198 // Now enumerate the identities in the available keychains. | 199 // Now enumerate the identities in the available keychains. |
199 scoped_refptr<X509Certificate> preferred_cert = NULL; | 200 scoped_refptr<X509Certificate> preferred_cert = NULL; |
200 CertificateList regular_certs; | 201 CertificateList regular_certs; |
201 | 202 |
202 SecIdentitySearchRef search = NULL; | 203 SecIdentitySearchRef search = NULL; |
203 OSStatus err; | 204 OSStatus err; |
204 { | 205 { |
205 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | 206 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); |
206 err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search); | 207 err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search); |
207 } | 208 } |
208 if (err) | 209 if (err) { |
209 return false; | 210 selected_certs->clear(); |
| 211 callback.Run(); |
| 212 return; |
| 213 } |
210 ScopedCFTypeRef<SecIdentitySearchRef> scoped_search(search); | 214 ScopedCFTypeRef<SecIdentitySearchRef> scoped_search(search); |
211 while (!err) { | 215 while (!err) { |
212 SecIdentityRef identity = NULL; | 216 SecIdentityRef identity = NULL; |
213 { | 217 { |
214 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | 218 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); |
215 err = SecIdentitySearchCopyNext(search, &identity); | 219 err = SecIdentitySearchCopyNext(search, &identity); |
216 } | 220 } |
217 if (err) | 221 if (err) |
218 break; | 222 break; |
219 ScopedCFTypeRef<SecIdentityRef> scoped_identity(identity); | 223 ScopedCFTypeRef<SecIdentityRef> scoped_identity(identity); |
(...skipping 12 matching lines...) Expand all Loading... |
232 // Only one certificate should match. | 236 // Only one certificate should match. |
233 DCHECK(!preferred_cert.get()); | 237 DCHECK(!preferred_cert.get()); |
234 preferred_cert = cert; | 238 preferred_cert = cert; |
235 } else { | 239 } else { |
236 regular_certs.push_back(cert); | 240 regular_certs.push_back(cert); |
237 } | 241 } |
238 } | 242 } |
239 | 243 |
240 if (err != errSecItemNotFound) { | 244 if (err != errSecItemNotFound) { |
241 OSSTATUS_LOG(ERROR, err) << "SecIdentitySearch error"; | 245 OSSTATUS_LOG(ERROR, err) << "SecIdentitySearch error"; |
242 return false; | 246 selected_certs->clear(); |
| 247 callback.Run(); |
| 248 return; |
243 } | 249 } |
244 | 250 |
245 return GetClientCertsImpl(preferred_cert, regular_certs, request, true, | 251 GetClientCertsImpl(preferred_cert, regular_certs, request, true, |
246 selected_certs); | 252 selected_certs); |
| 253 callback.Run(); |
247 } | 254 } |
248 | 255 |
249 bool ClientCertStoreImpl::SelectClientCertsForTesting( | 256 bool ClientCertStoreImpl::SelectClientCertsForTesting( |
250 const CertificateList& input_certs, | 257 const CertificateList& input_certs, |
251 const SSLCertRequestInfo& request, | 258 const SSLCertRequestInfo& request, |
252 CertificateList* selected_certs) { | 259 CertificateList* selected_certs) { |
253 return GetClientCertsImpl(NULL, input_certs, request, false, | 260 GetClientCertsImpl(NULL, input_certs, request, false, selected_certs); |
254 selected_certs); | 261 return true; |
255 } | 262 } |
256 | 263 |
257 #if !defined(OS_IOS) | 264 #if !defined(OS_IOS) |
258 bool ClientCertStoreImpl::SelectClientCertsGivenPreferredForTesting( | 265 bool ClientCertStoreImpl::SelectClientCertsGivenPreferredForTesting( |
259 const scoped_refptr<X509Certificate>& preferred_cert, | 266 const scoped_refptr<X509Certificate>& preferred_cert, |
260 const CertificateList& regular_certs, | 267 const CertificateList& regular_certs, |
261 const SSLCertRequestInfo& request, | 268 const SSLCertRequestInfo& request, |
262 CertificateList* selected_certs) { | 269 CertificateList* selected_certs) { |
263 return GetClientCertsImpl(preferred_cert, regular_certs, request, false, | 270 GetClientCertsImpl( |
264 selected_certs); | 271 preferred_cert, regular_certs, request, false, selected_certs); |
| 272 return true; |
265 } | 273 } |
266 #endif | 274 #endif |
267 | 275 |
268 } // namespace net | 276 } // namespace net |
OLD | NEW |