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

Side by Side Diff: net/base/x509_certificate_mac.cc

Issue 2944008: Refactor X509Certificate caching to cache the OS handle, rather than the X509Certificate (Closed)
Patch Set: Rebase to trunk after splitting out 4645001 Created 9 years, 11 months 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
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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/base/x509_certificate.h" 5 #include "net/base/x509_certificate.h"
6 6
7 #include <CommonCrypto/CommonDigest.h> 7 #include <CommonCrypto/CommonDigest.h>
8 #include <Security/Security.h> 8 #include <Security/Security.h>
9 #include <time.h> 9 #include <time.h>
10 10
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const { 402 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const {
403 dns_names->clear(); 403 dns_names->clear();
404 404
405 GetCertGeneralNamesForOID(cert_handle_, CSSMOID_SubjectAltName, GNT_DNSName, 405 GetCertGeneralNamesForOID(cert_handle_, CSSMOID_SubjectAltName, GNT_DNSName,
406 dns_names); 406 dns_names);
407 407
408 if (dns_names->empty()) 408 if (dns_names->empty())
409 dns_names->push_back(subject_.common_name); 409 dns_names->push_back(subject_.common_name);
410 } 410 }
411 411
412 X509Certificate::OSCertListHandle
413 X509Certificate::CreateOSCertListHandle() const {
414 CFMutableArrayRef cert_list =
415 CFArrayCreateMutable(kCFAllocatorDefault, 0,
416 &kCFTypeArrayCallBacks);
417 if (!cert_list)
418 return NULL;
419
420 CFArrayAppendValue(cert_list, cert_handle_);
421 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) {
422 CFArrayAppendValue(cert_list, intermediate_ca_certs_[i]);
423 }
424
425 return cert_list;
426 }
427
412 int X509Certificate::Verify(const std::string& hostname, int flags, 428 int X509Certificate::Verify(const std::string& hostname, int flags,
413 CertVerifyResult* verify_result) const { 429 CertVerifyResult* verify_result) const {
414 verify_result->Reset(); 430 verify_result->Reset();
415 431
416 // Create an SSL SecPolicyRef, and configure it to perform hostname 432 // Create an SSL SecPolicyRef, and configure it to perform hostname
417 // validation. The hostname check does 99% of what we want, with the 433 // validation. The hostname check does 99% of what we want, with the
418 // exception of dotted IPv4 addreses, which we handle ourselves below. 434 // exception of dotted IPv4 addreses, which we handle ourselves below.
419 CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options = { 435 CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options = {
420 CSSM_APPLE_TP_SSL_OPTS_VERSION, 436 CSSM_APPLE_TP_SSL_OPTS_VERSION,
421 hostname.size(), 437 hostname.size(),
422 hostname.data(), 438 hostname.data(),
423 0 439 0
424 }; 440 };
425 SecPolicyRef ssl_policy; 441 SecPolicyRef ssl_policy;
426 OSStatus status = CreatePolicy(&CSSMOID_APPLE_TP_SSL, 442 OSStatus status = CreatePolicy(&CSSMOID_APPLE_TP_SSL,
427 &tp_ssl_options, 443 &tp_ssl_options,
428 sizeof(tp_ssl_options), 444 sizeof(tp_ssl_options),
429 &ssl_policy); 445 &ssl_policy);
430 if (status) 446 if (status)
431 return NetErrorFromOSStatus(status); 447 return NetErrorFromOSStatus(status);
432 ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy); 448 ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy);
433 449
434 // Create and configure a SecTrustRef, which takes our certificate(s) 450 // Create and configure a SecTrustRef, which takes our certificate(s)
435 // and our SSL SecPolicyRef. SecTrustCreateWithCertificates() takes an 451 // and our SSL SecPolicyRef. SecTrustCreateWithCertificates() takes an
436 // array of certificates, the first of which is the certificate we're 452 // array of certificates, the first of which is the certificate we're
437 // verifying, and the subsequent (optional) certificates are used for 453 // verifying, and the subsequent (optional) certificates are used for
438 // chain building. 454 // chain building.
439 CFMutableArrayRef cert_array = CFArrayCreateMutable(kCFAllocatorDefault, 0, 455 ScopedCFTypeRef<CFArrayRef> cert_array(CreateOSCertListHandle());
440 &kCFTypeArrayCallBacks);
441 if (!cert_array)
442 return ERR_OUT_OF_MEMORY;
443 ScopedCFTypeRef<CFArrayRef> scoped_cert_array(cert_array);
444 CFArrayAppendValue(cert_array, cert_handle_);
445 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i)
446 CFArrayAppendValue(cert_array, intermediate_ca_certs_[i]);
447 456
448 // From here on, only one thread can be active at a time. We have had a number 457 // From here on, only one thread can be active at a time. We have had a number
449 // of sporadic crashes in the SecTrustEvaluate call below, way down inside 458 // of sporadic crashes in the SecTrustEvaluate call below, way down inside
450 // Apple's cert code, which we suspect are caused by a thread-safety issue. 459 // Apple's cert code, which we suspect are caused by a thread-safety issue.
451 // So as a speculative fix allow only one thread to use SecTrust on this cert. 460 // So as a speculative fix allow only one thread to use SecTrust on this cert.
452 AutoLock lock(verification_lock_); 461 AutoLock lock(verification_lock_);
453 462
454 SecTrustRef trust_ref = NULL; 463 SecTrustRef trust_ref = NULL;
455 status = SecTrustCreateWithCertificates(cert_array, ssl_policy, &trust_ref); 464 status = SecTrustCreateWithCertificates(cert_array, ssl_policy, &trust_ref);
456 if (status) 465 if (status)
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 return NULL; 723 return NULL;
715 return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); 724 return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle)));
716 } 725 }
717 726
718 // static 727 // static
719 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { 728 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
720 CFRelease(cert_handle); 729 CFRelease(cert_handle);
721 } 730 }
722 731
723 // static 732 // static
733 void X509Certificate::FreeOSCertListHandle(OSCertListHandle identity) {
734 CFRelease(identity);
735 }
736
737 // static
724 SHA1Fingerprint X509Certificate::CalculateFingerprint( 738 SHA1Fingerprint X509Certificate::CalculateFingerprint(
725 OSCertHandle cert) { 739 OSCertHandle cert) {
726 SHA1Fingerprint sha1; 740 SHA1Fingerprint sha1;
727 memset(sha1.data, 0, sizeof(sha1.data)); 741 memset(sha1.data, 0, sizeof(sha1.data));
728 742
729 CSSM_DATA cert_data; 743 CSSM_DATA cert_data;
730 OSStatus status = SecCertificateGetData(cert, &cert_data); 744 OSStatus status = SecCertificateGetData(cert, &cert_data);
731 if (status) 745 if (status)
732 return sha1; 746 return sha1;
733 747
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
812 return false; 826 return false;
813 ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain); 827 ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain);
814 828
815 // Check all the certs in the chain for a match. 829 // Check all the certs in the chain for a match.
816 int n = CFArrayGetCount(cert_chain); 830 int n = CFArrayGetCount(cert_chain);
817 for (int i = 0; i < n; ++i) { 831 for (int i = 0; i < n; ++i) {
818 SecCertificateRef cert_handle = reinterpret_cast<SecCertificateRef>( 832 SecCertificateRef cert_handle = reinterpret_cast<SecCertificateRef>(
819 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i))); 833 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i)));
820 scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromHandle( 834 scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromHandle(
821 cert_handle, 835 cert_handle,
822 X509Certificate::SOURCE_LONE_CERT_IMPORT,
823 X509Certificate::OSCertHandles())); 836 X509Certificate::OSCertHandles()));
824 for (unsigned j = 0; j < valid_issuers.size(); j++) { 837 for (unsigned j = 0; j < valid_issuers.size(); j++) {
825 if (cert->issuer().Matches(valid_issuers[j])) 838 if (cert->issuer().Matches(valid_issuers[j]))
826 return true; 839 return true;
827 } 840 }
828 } 841 }
829 return false; 842 return false;
830 } 843 }
831 844
832 // static 845 // static
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
874 break; 887 break;
875 ScopedCFTypeRef<SecIdentityRef> scoped_identity(identity); 888 ScopedCFTypeRef<SecIdentityRef> scoped_identity(identity);
876 889
877 SecCertificateRef cert_handle; 890 SecCertificateRef cert_handle;
878 err = SecIdentityCopyCertificate(identity, &cert_handle); 891 err = SecIdentityCopyCertificate(identity, &cert_handle);
879 if (err != noErr) 892 if (err != noErr)
880 continue; 893 continue;
881 ScopedCFTypeRef<SecCertificateRef> scoped_cert_handle(cert_handle); 894 ScopedCFTypeRef<SecCertificateRef> scoped_cert_handle(cert_handle);
882 895
883 scoped_refptr<X509Certificate> cert( 896 scoped_refptr<X509Certificate> cert(
884 CreateFromHandle(cert_handle, SOURCE_LONE_CERT_IMPORT, 897 CreateFromHandle(cert_handle, OSCertHandles()));
885 OSCertHandles()));
886 if (cert->HasExpired() || !cert->SupportsSSLClientAuth()) 898 if (cert->HasExpired() || !cert->SupportsSSLClientAuth())
887 continue; 899 continue;
888 900
889 // Skip duplicates (a cert may be in multiple keychains). 901 // Skip duplicates (a cert may be in multiple keychains).
890 const SHA1Fingerprint& fingerprint = cert->fingerprint(); 902 const SHA1Fingerprint& fingerprint = cert->fingerprint();
891 unsigned i; 903 unsigned i;
892 for (i = 0; i < certs->size(); ++i) { 904 for (i = 0; i < certs->size(); ++i) {
893 if ((*certs)[i]->fingerprint().Equals(fingerprint)) 905 if ((*certs)[i]->fingerprint().Equals(fingerprint))
894 break; 906 break;
895 } 907 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
950 cert_chain, 962 cert_chain,
951 CFRangeMake(1, chain_count - 1)); 963 CFRangeMake(1, chain_count - 1));
952 } 964 }
953 CFRelease(cert_chain); 965 CFRelease(cert_chain);
954 } 966 }
955 967
956 return chain.release(); 968 return chain.release();
957 } 969 }
958 970
959 } // namespace net 971 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698