Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(245)

Side by Side Diff: net/ssl/client_cert_store_mac.cc

Issue 2411023002: *WIP* Mac Unittest for client cert selection with intermediate certs
Patch Set: rebase Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/data/ssl/scripts/generate-keychain.sh ('k') | net/ssl/client_cert_store_mac_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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>
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/callback.h"
17 #include "base/logging.h" 17 #include "base/logging.h"
18 #include "base/mac/mac_logging.h" 18 #include "base/mac/mac_logging.h"
19 #include "base/mac/scoped_cftyperef.h" 19 #include "base/mac/scoped_cftyperef.h"
20 #include "base/strings/sys_string_conversions.h" 20 #include "base/strings/sys_string_conversions.h"
21 #include "base/synchronization/lock.h" 21 #include "base/synchronization/lock.h"
22 #include "crypto/mac_security_services_lock.h" 22 #include "crypto/mac_security_services_lock.h"
23 #include "net/base/host_port_pair.h" 23 #include "net/base/host_port_pair.h"
24 #include "net/cert/test_keychain_search_list_mac.h"
24 #include "net/cert/x509_util.h" 25 #include "net/cert/x509_util.h"
25 #include "net/cert/x509_util_mac.h" 26 #include "net/cert/x509_util_mac.h"
26 27
27 using base::ScopedCFTypeRef; 28 using base::ScopedCFTypeRef;
28 29
29 namespace net { 30 namespace net {
30 31
31 // CSSM functions are deprecated as of OSX 10.7, but have no replacement. 32 // CSSM functions are deprecated as of OSX 10.7, but have no replacement.
32 // https://bugs.chromium.org/p/chromium/issues/detail?id=590914#c1 33 // https://bugs.chromium.org/p/chromium/issues/detail?id=590914#c1
33 #pragma clang diagnostic push 34 #pragma clang diagnostic push
(...skipping 25 matching lines...) Expand all
59 SecTrustRef trust_ref = NULL; 60 SecTrustRef trust_ref = NULL;
60 { 61 {
61 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); 62 base::AutoLock lock(crypto::GetMacSecurityServicesLock());
62 result = SecTrustCreateWithCertificates(input_certs, ssl_policy, 63 result = SecTrustCreateWithCertificates(input_certs, ssl_policy,
63 &trust_ref); 64 &trust_ref);
64 } 65 }
65 if (result) 66 if (result)
66 return result; 67 return result;
67 ScopedCFTypeRef<SecTrustRef> trust(trust_ref); 68 ScopedCFTypeRef<SecTrustRef> trust(trust_ref);
68 69
70 ScopedCFTypeRef<CFArrayRef> scoped_alternate_keychain_search_list;
71 // XXX use TestKeychainSearchList
72 if (TestKeychainSearchList::HasInstance()) {
73 OSStatus status = TestKeychainSearchList::GetInstance()->CopySearchList(
74 &scoped_alternate_keychain_search_list);
75 if (status)
76 return status;
77
78 {
79 base::AutoLock lock(crypto::GetMacSecurityServicesLock());
80 status = SecTrustSetKeychains(trust, scoped_alternate_keychain_search_list .get());
81 }
82 if (status)
83 return status;
84 }
85
69 // Evaluate trust, which creates the cert chain. 86 // Evaluate trust, which creates the cert chain.
70 SecTrustResultType status; 87 SecTrustResultType status;
71 CSSM_TP_APPLE_EVIDENCE_INFO* status_chain; 88 CSSM_TP_APPLE_EVIDENCE_INFO* status_chain;
72 { 89 {
73 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); 90 base::AutoLock lock(crypto::GetMacSecurityServicesLock());
74 result = SecTrustEvaluate(trust, &status); 91 result = SecTrustEvaluate(trust, &status);
75 } 92 }
76 if (result) 93 if (result) {
94 OSSTATUS_LOG(ERROR, result) << "SecTrustEvaluate error";
77 return result; 95 return result;
96 }
97 LOG(WARNING) << "SecTrustEvaluate status=" << status;
78 { 98 {
79 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); 99 base::AutoLock lock(crypto::GetMacSecurityServicesLock());
80 result = SecTrustGetResult(trust, &status, out_cert_chain, &status_chain); 100 result = SecTrustGetResult(trust, &status, out_cert_chain, &status_chain);
81 } 101 }
102 if (result) {
103 OSSTATUS_LOG(ERROR, result) << "SecTrustGetResult error";
104 }
105 LOG(WARNING) << "SecTrustGetResult status=" << status;
82 return result; 106 return result;
83 } 107 }
84 108
85 // Returns true if |*cert| is issued by an authority in |valid_issuers| 109 // Returns true if |*cert| is issued by an authority in |valid_issuers|
86 // according to Keychain Services, rather than using |cert|'s intermediate 110 // according to Keychain Services, rather than using |cert|'s intermediate
87 // certificates. If it is, |*cert| is updated to point to the completed 111 // certificates. If it is, |*cert| is updated to point to the completed
88 // certificate 112 // certificate
89 bool IsIssuedByInKeychain(const std::vector<std::string>& valid_issuers, 113 bool IsIssuedByInKeychain(const std::vector<std::string>& valid_issuers,
90 scoped_refptr<X509Certificate>* cert) { 114 scoped_refptr<X509Certificate>* cert) {
91 DCHECK(cert); 115 DCHECK(cert);
92 DCHECK(cert->get()); 116 DCHECK(cert->get());
93 117
118 LOG(WARNING) << "IsIssuedByInKeychain " << (*cert)->subject().GetDisplayName();
94 X509Certificate::OSCertHandle cert_handle = (*cert)->os_cert_handle(); 119 X509Certificate::OSCertHandle cert_handle = (*cert)->os_cert_handle();
95 CFArrayRef cert_chain = NULL; 120 CFArrayRef cert_chain = NULL;
96 OSStatus result = CopyCertChain(cert_handle, &cert_chain); 121 OSStatus result = CopyCertChain(cert_handle, &cert_chain);
97 if (result) { 122 if (result) {
98 OSSTATUS_LOG(ERROR, result) << "CopyCertChain error"; 123 OSSTATUS_LOG(ERROR, result) << "CopyCertChain error";
99 return false; 124 return false;
100 } 125 }
101 126
102 if (!cert_chain) 127 if (!cert_chain)
103 return false; 128 return false;
129
130 LOG(WARNING) << "chain size: " << CFArrayGetCount(cert_chain);
104 131
105 X509Certificate::OSCertHandles intermediates; 132 X509Certificate::OSCertHandles intermediates;
106 for (CFIndex i = 1, chain_count = CFArrayGetCount(cert_chain); 133 for (CFIndex i = 1, chain_count = CFArrayGetCount(cert_chain);
107 i < chain_count; ++i) { 134 i < chain_count; ++i) {
108 SecCertificateRef cert = reinterpret_cast<SecCertificateRef>( 135 SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(
109 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i))); 136 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i)));
110 intermediates.push_back(cert); 137 intermediates.push_back(cert);
111 } 138 }
112 139
113 scoped_refptr<X509Certificate> new_cert(X509Certificate::CreateFromHandle( 140 scoped_refptr<X509Certificate> new_cert(X509Certificate::CreateFromHandle(
114 cert_handle, intermediates)); 141 cert_handle, intermediates));
115 CFRelease(cert_chain); // Also frees |intermediates|. 142 CFRelease(cert_chain); // Also frees |intermediates|.
116 143
117 if (!new_cert->IsIssuedByEncoded(valid_issuers)) 144 if (!new_cert->IsIssuedByEncoded(valid_issuers)) {
145 LOG(WARNING) << "no.";
118 return false; 146 return false;
147 }
119 148
149 LOG(WARNING) << "yes.";
120 cert->swap(new_cert); 150 cert->swap(new_cert);
121 return true; 151 return true;
122 } 152 }
123 153
124 // Examines the certificates in |preferred_cert| and |regular_certs| to find 154 // Examines the certificates in |preferred_cert| and |regular_certs| to find
125 // all certificates that match the client certificate request in |request|, 155 // all certificates that match the client certificate request in |request|,
126 // storing the matching certificates in |selected_certs|. 156 // storing the matching certificates in |selected_certs|.
127 // If |query_keychain| is true, Keychain Services will be queried to construct 157 // If |query_keychain| is true, Keychain Services will be queried to construct
128 // full certificate chains. If it is false, only the the certificates and their 158 // full certificate chains. If it is false, only the the certificates and their
129 // intermediates (available via X509Certificate::GetIntermediateCertificates()) 159 // intermediates (available via X509Certificate::GetIntermediateCertificates())
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); 231 base::AutoLock lock(crypto::GetMacSecurityServicesLock());
202 if (SecIdentityCopyPreference(domain_str, 0, NULL, &identity) == noErr) 232 if (SecIdentityCopyPreference(domain_str, 0, NULL, &identity) == noErr)
203 preferred_identity.reset(identity); 233 preferred_identity.reset(identity);
204 } 234 }
205 } 235 }
206 236
207 // Now enumerate the identities in the available keychains. 237 // Now enumerate the identities in the available keychains.
208 scoped_refptr<X509Certificate> preferred_cert = NULL; 238 scoped_refptr<X509Certificate> preferred_cert = NULL;
209 CertificateList regular_certs; 239 CertificateList regular_certs;
210 240
241 ScopedCFTypeRef<CFMutableDictionaryRef> query(
242 CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks,
243 &kCFTypeDictionaryValueCallBacks));
244
245 CFDictionarySetValue(query, kSecClass, kSecClassIdentity);
246 CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue);
247 CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll);
248
249 ScopedCFTypeRef<CFArrayRef> scoped_alternate_keychain_search_list;
250 if (TestKeychainSearchList::HasInstance()) {
251 OSStatus status = TestKeychainSearchList::GetInstance()->CopySearchList(
252 &scoped_alternate_keychain_search_list);
253 if (status) {
254 OSSTATUS_LOG(ERROR, status) << "TestKeychainSearchList::CopySearchList err or";
255 selected_certs->clear();
256 callback.Run();
257 return;
258 }
259 CFDictionarySetValue(query, kSecMatchSearchList, scoped_alternate_keychain_s earch_list.get());
260 }
261
262 CFArrayRef matching_items;
263 OSStatus err;
264 {
265 base::AutoLock lock(crypto::GetMacSecurityServicesLock());
266 err = SecItemCopyMatching(query, (CFTypeRef*)&matching_items);
267 }
268 if (err) {
269 OSSTATUS_LOG(ERROR, err) << "SecItemCopyMatching error";
270 selected_certs->clear();
271 callback.Run();
272 return;
273 }
274 ScopedCFTypeRef<CFArrayRef> scoped_matching_items(matching_items);
275
276 for (CFIndex i = 0, item_count = CFArrayGetCount(matching_items);
277 i < item_count; ++i) {
278 SecIdentityRef identity = reinterpret_cast<SecIdentityRef>(
279 const_cast<void*>(CFArrayGetValueAtIndex(matching_items, i)));
280 SecCertificateRef cert_handle;
281 err = SecIdentityCopyCertificate(identity, &cert_handle);
282 if (err != noErr)
283 continue;
284 ScopedCFTypeRef<SecCertificateRef> scoped_cert_handle(cert_handle);
285
286 scoped_refptr<X509Certificate> cert(
287 X509Certificate::CreateFromHandle(cert_handle,
288 X509Certificate::OSCertHandles()));
289
290 if (preferred_identity && CFEqual(preferred_identity, identity)) {
291 // Only one certificate should match.
292 DCHECK(!preferred_cert.get());
293 preferred_cert = cert;
294 } else {
295 regular_certs.push_back(cert);
296 }
297 }
298 LOG(WARNING) << "have preferred=" << !!preferred_cert << " regular_certs.size=" << regular_certs.size();
299
300 #if 0
211 SecIdentitySearchRef search = NULL; 301 SecIdentitySearchRef search = NULL;
212 OSStatus err; 302 OSStatus err;
213 { 303 {
214 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); 304 base::AutoLock lock(crypto::GetMacSecurityServicesLock());
215 err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search); 305 err = SecIdentitySearchCreate(scoped_alternate_keychain_search_list,
306 CSSM_KEYUSE_SIGN, &search);
216 } 307 }
217 if (err) { 308 if (err) {
218 selected_certs->clear(); 309 selected_certs->clear();
219 callback.Run(); 310 callback.Run();
220 return; 311 return;
221 } 312 }
222 ScopedCFTypeRef<SecIdentitySearchRef> scoped_search(search); 313 ScopedCFTypeRef<SecIdentitySearchRef> scoped_search(search);
223 while (!err) { 314 while (!err) {
224 SecIdentityRef identity = NULL; 315 SecIdentityRef identity = NULL;
225 { 316 {
(...skipping 22 matching lines...) Expand all
248 regular_certs.push_back(cert); 339 regular_certs.push_back(cert);
249 } 340 }
250 } 341 }
251 342
252 if (err != errSecItemNotFound) { 343 if (err != errSecItemNotFound) {
253 OSSTATUS_LOG(ERROR, err) << "SecIdentitySearch error"; 344 OSSTATUS_LOG(ERROR, err) << "SecIdentitySearch error";
254 selected_certs->clear(); 345 selected_certs->clear();
255 callback.Run(); 346 callback.Run();
256 return; 347 return;
257 } 348 }
349 #endif
258 350
259 GetClientCertsImpl(preferred_cert, regular_certs, request, true, 351 GetClientCertsImpl(preferred_cert, regular_certs, request, true,
260 selected_certs); 352 selected_certs);
261 callback.Run(); 353 callback.Run();
262 } 354 }
263 355
264 bool ClientCertStoreMac::SelectClientCertsForTesting( 356 bool ClientCertStoreMac::SelectClientCertsForTesting(
265 const CertificateList& input_certs, 357 const CertificateList& input_certs,
266 const SSLCertRequestInfo& request, 358 const SSLCertRequestInfo& request,
267 CertificateList* selected_certs) { 359 CertificateList* selected_certs) {
268 GetClientCertsImpl(NULL, input_certs, request, false, selected_certs); 360 GetClientCertsImpl(NULL, input_certs, request, false, selected_certs);
269 return true; 361 return true;
270 } 362 }
271 363
272 bool ClientCertStoreMac::SelectClientCertsGivenPreferredForTesting( 364 bool ClientCertStoreMac::SelectClientCertsGivenPreferredForTesting(
273 const scoped_refptr<X509Certificate>& preferred_cert, 365 const scoped_refptr<X509Certificate>& preferred_cert,
274 const CertificateList& regular_certs, 366 const CertificateList& regular_certs,
275 const SSLCertRequestInfo& request, 367 const SSLCertRequestInfo& request,
276 CertificateList* selected_certs) { 368 CertificateList* selected_certs) {
277 GetClientCertsImpl( 369 GetClientCertsImpl(
278 preferred_cert, regular_certs, request, false, selected_certs); 370 preferred_cert, regular_certs, request, false, selected_certs);
279 return true; 371 return true;
280 } 372 }
281 373
282 #pragma clang diagnostic pop // "-Wdeprecated-declarations" 374 #pragma clang diagnostic pop // "-Wdeprecated-declarations"
283 375
284 } // namespace net 376 } // namespace net
OLDNEW
« no previous file with comments | « net/data/ssl/scripts/generate-keychain.sh ('k') | net/ssl/client_cert_store_mac_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698