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 |