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_mac.h" | 5 #include "net/ssl/client_cert_store_mac.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> |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 | 42 |
43 // Create an SSL policy ref configured for client cert evaluation. | 43 // Create an SSL policy ref configured for client cert evaluation. |
44 SecPolicyRef ssl_policy; | 44 SecPolicyRef ssl_policy; |
45 OSStatus result = x509_util::CreateSSLClientPolicy(&ssl_policy); | 45 OSStatus result = x509_util::CreateSSLClientPolicy(&ssl_policy); |
46 if (result) | 46 if (result) |
47 return result; | 47 return result; |
48 ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy); | 48 ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy); |
49 | 49 |
50 // Create a SecTrustRef. | 50 // Create a SecTrustRef. |
51 ScopedCFTypeRef<CFArrayRef> input_certs(CFArrayCreate( | 51 ScopedCFTypeRef<CFArrayRef> input_certs(CFArrayCreate( |
52 NULL, const_cast<const void**>(reinterpret_cast<void**>(&cert_handle)), | 52 NULL, |
53 1, &kCFTypeArrayCallBacks)); | 53 const_cast<const void**>(reinterpret_cast<void**>(&cert_handle)), |
| 54 1, |
| 55 &kCFTypeArrayCallBacks)); |
54 SecTrustRef trust_ref = NULL; | 56 SecTrustRef trust_ref = NULL; |
55 { | 57 { |
56 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | 58 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); |
57 result = SecTrustCreateWithCertificates(input_certs, ssl_policy, | 59 result = |
58 &trust_ref); | 60 SecTrustCreateWithCertificates(input_certs, ssl_policy, &trust_ref); |
59 } | 61 } |
60 if (result) | 62 if (result) |
61 return result; | 63 return result; |
62 ScopedCFTypeRef<SecTrustRef> trust(trust_ref); | 64 ScopedCFTypeRef<SecTrustRef> trust(trust_ref); |
63 | 65 |
64 // Evaluate trust, which creates the cert chain. | 66 // Evaluate trust, which creates the cert chain. |
65 SecTrustResultType status; | 67 SecTrustResultType status; |
66 CSSM_TP_APPLE_EVIDENCE_INFO* status_chain; | 68 CSSM_TP_APPLE_EVIDENCE_INFO* status_chain; |
67 { | 69 { |
68 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | 70 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); |
(...skipping 23 matching lines...) Expand all Loading... |
92 if (result) { | 94 if (result) { |
93 OSSTATUS_LOG(ERROR, result) << "CopyCertChain error"; | 95 OSSTATUS_LOG(ERROR, result) << "CopyCertChain error"; |
94 return false; | 96 return false; |
95 } | 97 } |
96 | 98 |
97 if (!cert_chain) | 99 if (!cert_chain) |
98 return false; | 100 return false; |
99 | 101 |
100 X509Certificate::OSCertHandles intermediates; | 102 X509Certificate::OSCertHandles intermediates; |
101 for (CFIndex i = 1, chain_count = CFArrayGetCount(cert_chain); | 103 for (CFIndex i = 1, chain_count = CFArrayGetCount(cert_chain); |
102 i < chain_count; ++i) { | 104 i < chain_count; |
| 105 ++i) { |
103 SecCertificateRef cert = reinterpret_cast<SecCertificateRef>( | 106 SecCertificateRef cert = reinterpret_cast<SecCertificateRef>( |
104 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i))); | 107 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i))); |
105 intermediates.push_back(cert); | 108 intermediates.push_back(cert); |
106 } | 109 } |
107 | 110 |
108 scoped_refptr<X509Certificate> new_cert(X509Certificate::CreateFromHandle( | 111 scoped_refptr<X509Certificate> new_cert( |
109 cert_handle, intermediates)); | 112 X509Certificate::CreateFromHandle(cert_handle, intermediates)); |
110 CFRelease(cert_chain); // Also frees |intermediates|. | 113 CFRelease(cert_chain); // Also frees |intermediates|. |
111 | 114 |
112 if (!new_cert->IsIssuedByEncoded(valid_issuers)) | 115 if (!new_cert->IsIssuedByEncoded(valid_issuers)) |
113 return false; | 116 return false; |
114 | 117 |
115 cert->swap(new_cert); | 118 cert->swap(new_cert); |
116 return true; | 119 return true; |
117 } | 120 } |
118 | 121 |
119 // Examines the certificates in |preferred_cert| and |regular_certs| to find | 122 // Examines the certificates in |preferred_cert| and |regular_certs| to find |
120 // all certificates that match the client certificate request in |request|, | 123 // all certificates that match the client certificate request in |request|, |
121 // storing the matching certificates in |selected_certs|. | 124 // storing the matching certificates in |selected_certs|. |
122 // If |query_keychain| is true, Keychain Services will be queried to construct | 125 // If |query_keychain| is true, Keychain Services will be queried to construct |
123 // full certificate chains. If it is false, only the the certificates and their | 126 // full certificate chains. If it is false, only the the certificates and their |
124 // intermediates (available via X509Certificate::GetIntermediateCertificates()) | 127 // intermediates (available via X509Certificate::GetIntermediateCertificates()) |
125 // will be considered. | 128 // will be considered. |
126 void GetClientCertsImpl(const scoped_refptr<X509Certificate>& preferred_cert, | 129 void GetClientCertsImpl(const scoped_refptr<X509Certificate>& preferred_cert, |
127 const CertificateList& regular_certs, | 130 const CertificateList& regular_certs, |
128 const SSLCertRequestInfo& request, | 131 const SSLCertRequestInfo& request, |
129 bool query_keychain, | 132 bool query_keychain, |
130 CertificateList* selected_certs) { | 133 CertificateList* selected_certs) { |
131 CertificateList preliminary_list; | 134 CertificateList preliminary_list; |
132 if (preferred_cert.get()) | 135 if (preferred_cert.get()) |
133 preliminary_list.push_back(preferred_cert); | 136 preliminary_list.push_back(preferred_cert); |
134 preliminary_list.insert(preliminary_list.end(), regular_certs.begin(), | 137 preliminary_list.insert( |
135 regular_certs.end()); | 138 preliminary_list.end(), regular_certs.begin(), regular_certs.end()); |
136 | 139 |
137 selected_certs->clear(); | 140 selected_certs->clear(); |
138 for (size_t i = 0; i < preliminary_list.size(); ++i) { | 141 for (size_t i = 0; i < preliminary_list.size(); ++i) { |
139 scoped_refptr<X509Certificate>& cert = preliminary_list[i]; | 142 scoped_refptr<X509Certificate>& cert = preliminary_list[i]; |
140 if (cert->HasExpired() || !cert->SupportsSSLClientAuth()) | 143 if (cert->HasExpired() || !cert->SupportsSSLClientAuth()) |
141 continue; | 144 continue; |
142 | 145 |
143 // Skip duplicates (a cert may be in multiple keychains). | 146 // Skip duplicates (a cert may be in multiple keychains). |
144 const SHA1HashValue& fingerprint = cert->fingerprint(); | 147 const SHA1HashValue& fingerprint = cert->fingerprint(); |
145 size_t pos; | 148 size_t pos; |
(...skipping 19 matching lines...) Expand all Loading... |
165 CertificateList::iterator sort_end = selected_certs->end(); | 168 CertificateList::iterator sort_end = selected_certs->end(); |
166 if (preferred_cert.get() && sort_begin != sort_end && | 169 if (preferred_cert.get() && sort_begin != sort_end && |
167 sort_begin->get() == preferred_cert.get()) { | 170 sort_begin->get() == preferred_cert.get()) { |
168 ++sort_begin; | 171 ++sort_begin; |
169 } | 172 } |
170 sort(sort_begin, sort_end, x509_util::ClientCertSorter()); | 173 sort(sort_begin, sort_end, x509_util::ClientCertSorter()); |
171 } | 174 } |
172 | 175 |
173 } // namespace | 176 } // namespace |
174 | 177 |
175 ClientCertStoreMac::ClientCertStoreMac() {} | 178 ClientCertStoreMac::ClientCertStoreMac() { |
| 179 } |
176 | 180 |
177 ClientCertStoreMac::~ClientCertStoreMac() {} | 181 ClientCertStoreMac::~ClientCertStoreMac() { |
| 182 } |
178 | 183 |
179 void ClientCertStoreMac::GetClientCerts(const SSLCertRequestInfo& request, | 184 void ClientCertStoreMac::GetClientCerts(const SSLCertRequestInfo& request, |
180 CertificateList* selected_certs, | 185 CertificateList* selected_certs, |
181 const base::Closure& callback) { | 186 const base::Closure& callback) { |
182 std::string server_domain = request.host_and_port.host(); | 187 std::string server_domain = request.host_and_port.host(); |
183 | 188 |
184 ScopedCFTypeRef<SecIdentityRef> preferred_identity; | 189 ScopedCFTypeRef<SecIdentityRef> preferred_identity; |
185 if (!server_domain.empty()) { | 190 if (!server_domain.empty()) { |
186 // See if there's an identity preference for this domain: | 191 // See if there's an identity preference for this domain: |
187 ScopedCFTypeRef<CFStringRef> domain_str( | 192 ScopedCFTypeRef<CFStringRef> domain_str( |
188 base::SysUTF8ToCFStringRef("https://" + server_domain)); | 193 base::SysUTF8ToCFStringRef("https://" + server_domain)); |
189 SecIdentityRef identity = NULL; | 194 SecIdentityRef identity = NULL; |
190 // While SecIdentityCopyPreferences appears to take a list of CA issuers | 195 // While SecIdentityCopyPreferences appears to take a list of CA issuers |
191 // to restrict the identity search to, within Security.framework the | 196 // to restrict the identity search to, within Security.framework the |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 if (err) | 229 if (err) |
225 break; | 230 break; |
226 ScopedCFTypeRef<SecIdentityRef> scoped_identity(identity); | 231 ScopedCFTypeRef<SecIdentityRef> scoped_identity(identity); |
227 | 232 |
228 SecCertificateRef cert_handle; | 233 SecCertificateRef cert_handle; |
229 err = SecIdentityCopyCertificate(identity, &cert_handle); | 234 err = SecIdentityCopyCertificate(identity, &cert_handle); |
230 if (err != noErr) | 235 if (err != noErr) |
231 continue; | 236 continue; |
232 ScopedCFTypeRef<SecCertificateRef> scoped_cert_handle(cert_handle); | 237 ScopedCFTypeRef<SecCertificateRef> scoped_cert_handle(cert_handle); |
233 | 238 |
234 scoped_refptr<X509Certificate> cert( | 239 scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromHandle( |
235 X509Certificate::CreateFromHandle(cert_handle, | 240 cert_handle, X509Certificate::OSCertHandles())); |
236 X509Certificate::OSCertHandles())); | |
237 | 241 |
238 if (preferred_identity && CFEqual(preferred_identity, identity)) { | 242 if (preferred_identity && CFEqual(preferred_identity, identity)) { |
239 // Only one certificate should match. | 243 // Only one certificate should match. |
240 DCHECK(!preferred_cert.get()); | 244 DCHECK(!preferred_cert.get()); |
241 preferred_cert = cert; | 245 preferred_cert = cert; |
242 } else { | 246 } else { |
243 regular_certs.push_back(cert); | 247 regular_certs.push_back(cert); |
244 } | 248 } |
245 } | 249 } |
246 | 250 |
247 if (err != errSecItemNotFound) { | 251 if (err != errSecItemNotFound) { |
248 OSSTATUS_LOG(ERROR, err) << "SecIdentitySearch error"; | 252 OSSTATUS_LOG(ERROR, err) << "SecIdentitySearch error"; |
249 selected_certs->clear(); | 253 selected_certs->clear(); |
250 callback.Run(); | 254 callback.Run(); |
251 return; | 255 return; |
252 } | 256 } |
253 | 257 |
254 GetClientCertsImpl(preferred_cert, regular_certs, request, true, | 258 GetClientCertsImpl( |
255 selected_certs); | 259 preferred_cert, regular_certs, request, true, selected_certs); |
256 callback.Run(); | 260 callback.Run(); |
257 } | 261 } |
258 | 262 |
259 bool ClientCertStoreMac::SelectClientCertsForTesting( | 263 bool ClientCertStoreMac::SelectClientCertsForTesting( |
260 const CertificateList& input_certs, | 264 const CertificateList& input_certs, |
261 const SSLCertRequestInfo& request, | 265 const SSLCertRequestInfo& request, |
262 CertificateList* selected_certs) { | 266 CertificateList* selected_certs) { |
263 GetClientCertsImpl(NULL, input_certs, request, false, selected_certs); | 267 GetClientCertsImpl(NULL, input_certs, request, false, selected_certs); |
264 return true; | 268 return true; |
265 } | 269 } |
266 | 270 |
267 bool ClientCertStoreMac::SelectClientCertsGivenPreferredForTesting( | 271 bool ClientCertStoreMac::SelectClientCertsGivenPreferredForTesting( |
268 const scoped_refptr<X509Certificate>& preferred_cert, | 272 const scoped_refptr<X509Certificate>& preferred_cert, |
269 const CertificateList& regular_certs, | 273 const CertificateList& regular_certs, |
270 const SSLCertRequestInfo& request, | 274 const SSLCertRequestInfo& request, |
271 CertificateList* selected_certs) { | 275 CertificateList* selected_certs) { |
272 GetClientCertsImpl( | 276 GetClientCertsImpl( |
273 preferred_cert, regular_certs, request, false, selected_certs); | 277 preferred_cert, regular_certs, request, false, selected_certs); |
274 return true; | 278 return true; |
275 } | 279 } |
276 | 280 |
277 } // namespace net | 281 } // namespace net |
OLD | NEW |