| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |