Chromium Code Reviews| 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 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/pickle.h" | 12 #include "base/pickle.h" |
| 13 #include "base/mac/scoped_cftyperef.h" | 13 #include "base/mac/scoped_cftyperef.h" |
| 14 #include "base/sys_string_conversions.h" | 14 #include "base/sys_string_conversions.h" |
| 15 #include "net/base/cert_status_flags.h" | 15 #include "net/base/cert_status_flags.h" |
| 16 #include "net/base/cert_verify_result.h" | 16 #include "net/base/cert_verify_result.h" |
| 17 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
| 18 #include "net/base/temporary_root_certs.h" | |
| 18 | 19 |
| 19 using base::mac::ScopedCFTypeRef; | 20 using base::mac::ScopedCFTypeRef; |
| 20 using base::Time; | 21 using base::Time; |
| 21 | 22 |
| 22 namespace net { | 23 namespace net { |
| 23 | 24 |
| 24 class MacTrustedCertificates { | |
| 25 public: | |
| 26 // Sets the trusted root certificate used by tests. Call with |cert| set | |
| 27 // to NULL to clear the test certificate. | |
| 28 void SetTestCertificate(X509Certificate* cert) { | |
| 29 AutoLock lock(lock_); | |
| 30 test_certificate_ = cert; | |
| 31 } | |
| 32 | |
| 33 // Returns an array containing the trusted certificates for use with | |
| 34 // SecTrustSetAnchorCertificates(). Returns NULL if the system-supplied | |
| 35 // list of trust anchors is acceptable (that is, there is not test | |
| 36 // certificate available). Ownership follows the Create Rule (caller | |
| 37 // is responsible for calling CFRelease on the non-NULL result). | |
| 38 CFArrayRef CopyTrustedCertificateArray() { | |
| 39 AutoLock lock(lock_); | |
| 40 | |
| 41 if (!test_certificate_) | |
| 42 return NULL; | |
| 43 | |
| 44 // Failure to copy the anchor certificates or add the test certificate | |
| 45 // is non-fatal; SecTrustEvaluate() will use the system anchors instead. | |
| 46 CFArrayRef anchor_array; | |
| 47 OSStatus status = SecTrustCopyAnchorCertificates(&anchor_array); | |
| 48 if (status) | |
| 49 return NULL; | |
| 50 ScopedCFTypeRef<CFArrayRef> scoped_anchor_array(anchor_array); | |
| 51 CFMutableArrayRef merged_array = CFArrayCreateMutableCopy( | |
| 52 kCFAllocatorDefault, 0, anchor_array); | |
| 53 if (!merged_array) | |
| 54 return NULL; | |
| 55 CFArrayAppendValue(merged_array, test_certificate_->os_cert_handle()); | |
| 56 | |
| 57 return merged_array; | |
| 58 } | |
| 59 private: | |
| 60 friend struct DefaultSingletonTraits<MacTrustedCertificates>; | |
| 61 | |
| 62 // Obtain an instance of MacTrustedCertificates via the singleton | |
| 63 // interface. | |
| 64 MacTrustedCertificates() : test_certificate_(NULL) { } | |
| 65 | |
| 66 // An X509Certificate object that may be appended to the list of | |
| 67 // system trusted anchors. | |
| 68 scoped_refptr<X509Certificate> test_certificate_; | |
| 69 | |
| 70 // The trusted cache may be accessed from multiple threads. | |
| 71 mutable Lock lock_; | |
| 72 | |
| 73 DISALLOW_COPY_AND_ASSIGN(MacTrustedCertificates); | |
| 74 }; | |
| 75 | |
| 76 void SetMacTestCertificate(X509Certificate* cert) { | |
| 77 Singleton<MacTrustedCertificates>::get()->SetTestCertificate(cert); | |
| 78 } | |
| 79 | |
| 80 namespace { | 25 namespace { |
| 81 | 26 |
| 82 typedef OSStatus (*SecTrustCopyExtendedResultFuncPtr)(SecTrustRef, | 27 typedef OSStatus (*SecTrustCopyExtendedResultFuncPtr)(SecTrustRef, |
| 83 CFDictionaryRef*); | 28 CFDictionaryRef*); |
| 29 typedef OSStatus (*SecTrustSetAnchorCertificatesOnlyFuncPtr)(SecTrustRef, | |
| 30 Boolean); | |
| 84 | 31 |
| 85 int NetErrorFromOSStatus(OSStatus status) { | 32 int NetErrorFromOSStatus(OSStatus status) { |
| 86 switch (status) { | 33 switch (status) { |
| 87 case noErr: | 34 case noErr: |
| 88 return OK; | 35 return OK; |
| 89 case errSecNotAvailable: | 36 case errSecNotAvailable: |
| 90 case errSecNoCertificateModule: | 37 case errSecNoCertificateModule: |
| 91 case errSecNoPolicyModule: | 38 case errSecNoPolicyModule: |
| 92 return ERR_NOT_IMPLEMENTED; | 39 return ERR_NOT_IMPLEMENTED; |
| 93 case errSecAuthFailed: | 40 case errSecAuthFailed: |
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 535 // Apple's cert code, which we suspect are caused by a thread-safety issue. | 482 // Apple's cert code, which we suspect are caused by a thread-safety issue. |
| 536 // So as a speculative fix allow only one thread to use SecTrust on this cert. | 483 // So as a speculative fix allow only one thread to use SecTrust on this cert. |
| 537 AutoLock lock(verification_lock_); | 484 AutoLock lock(verification_lock_); |
| 538 | 485 |
| 539 SecTrustRef trust_ref = NULL; | 486 SecTrustRef trust_ref = NULL; |
| 540 status = SecTrustCreateWithCertificates(cert_array, ssl_policy, &trust_ref); | 487 status = SecTrustCreateWithCertificates(cert_array, ssl_policy, &trust_ref); |
| 541 if (status) | 488 if (status) |
| 542 return NetErrorFromOSStatus(status); | 489 return NetErrorFromOSStatus(status); |
| 543 ScopedCFTypeRef<SecTrustRef> scoped_trust_ref(trust_ref); | 490 ScopedCFTypeRef<SecTrustRef> scoped_trust_ref(trust_ref); |
| 544 | 491 |
| 545 // Set the trusted anchor certificates for the SecTrustRef by merging the | 492 TemporaryRootCerts* root_certs = TemporaryRootCerts::GetInstance(); |
| 546 // system trust anchors and the test root certificate. | 493 if (!root_certs->IsEmpty()) { |
| 547 CFArrayRef anchor_array = | 494 CFBundleRef bundle = |
| 548 Singleton<MacTrustedCertificates>::get()->CopyTrustedCertificateArray(); | 495 CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security")); |
| 549 ScopedCFTypeRef<CFArrayRef> scoped_anchor_array(anchor_array); | 496 SecTrustSetAnchorCertificatesOnlyFuncPtr set_anchor_certificates_only = |
| 550 if (anchor_array) { | 497 NULL; |
| 551 status = SecTrustSetAnchorCertificates(trust_ref, anchor_array); | 498 if (bundle) |
| 552 if (status) | 499 set_anchor_certificates_only = |
| 553 return NetErrorFromOSStatus(status); | 500 reinterpret_cast<SecTrustSetAnchorCertificatesOnlyFuncPtr>( |
| 501 CFBundleGetFunctionPointerForName(bundle, | |
| 502 CFSTR("SecTrustSetAnchorCertificatesOnly"))); | |
| 503 | |
| 504 if (set_anchor_certificates_only) { | |
| 505 // OS X 10.6 includes a function where the system trusts can be | |
| 506 // preserved while appending application trusts. This is preferable, | |
| 507 // because it preserves any user trust settings (explicit distrust), | |
| 508 // which the naive copy of 10.5 does not. | |
| 509 status = SecTrustSetAnchorCertificates(trust_ref, | |
| 510 root_certs->temporary_roots()); | |
| 511 if (status) | |
| 512 return NetErrorFromOSStatus(status); | |
| 513 status = set_anchor_certificates_only(trust_ref, false); | |
| 514 } else { | |
| 515 // On 10.5, the system certificates have to be copied and merged into | |
| 516 // the application trusts. | |
| 517 CFArrayRef system_trusts = NULL; | |
| 518 status = SecTrustCopyAnchorCertificates(&system_trusts); | |
| 519 if (status) | |
| 520 return NetErrorFromOSStatus(status); | |
| 521 | |
| 522 ScopedCFTypeRef<CFArrayRef> scoped_system_trusts(system_trusts); | |
| 523 ScopedCFTypeRef<CFMutableArrayRef> scoped_trusts( | |
| 524 CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, | |
| 525 scoped_system_trusts)); | |
| 526 if (!scoped_trusts) | |
| 527 return ERR_FAILED; | |
| 528 | |
| 529 CFArrayAppendArray( | |
| 530 scoped_trusts, root_certs->temporary_roots(), | |
| 531 CFRangeMake(0, CFArrayGetCount(root_certs->temporary_roots()))); | |
| 532 status = SecTrustSetAnchorCertificates(trust_ref, scoped_trusts); | |
| 533 if (status) | |
| 534 return NetErrorFromOSStatus(status); | |
| 535 } | |
|
bulach
2010/11/09 16:21:09
could we move 494-534 to something like
status T
| |
| 554 } | 536 } |
| 555 | 537 |
| 556 if (flags & VERIFY_REV_CHECKING_ENABLED) { | 538 if (flags & VERIFY_REV_CHECKING_ENABLED) { |
| 557 // When called with VERIFY_REV_CHECKING_ENABLED, we ask SecTrustEvaluate() | 539 // When called with VERIFY_REV_CHECKING_ENABLED, we ask SecTrustEvaluate() |
| 558 // to apply OCSP and CRL checking, but we're still subject to the global | 540 // to apply OCSP and CRL checking, but we're still subject to the global |
| 559 // settings, which are configured in the Keychain Access application (in | 541 // settings, which are configured in the Keychain Access application (in |
| 560 // the Certificates tab of the Preferences dialog). If the user has | 542 // the Certificates tab of the Preferences dialog). If the user has |
| 561 // revocation disabled (which is the default), then we will get | 543 // revocation disabled (which is the default), then we will get |
| 562 // kSecTrustResultRecoverableTrustFailure back from SecTrustEvaluate() | 544 // kSecTrustResultRecoverableTrustFailure back from SecTrustEvaluate() |
| 563 // with one of a number of sub error codes indicating that revocation | 545 // with one of a number of sub error codes indicating that revocation |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1004 } | 986 } |
| 1005 CFRelease(cert_chain); | 987 CFRelease(cert_chain); |
| 1006 } | 988 } |
| 1007 exit: | 989 exit: |
| 1008 if (result) | 990 if (result) |
| 1009 LOG(ERROR) << "CreateIdentityCertificateChain error " << result; | 991 LOG(ERROR) << "CreateIdentityCertificateChain error " << result; |
| 1010 return chain.release(); | 992 return chain.release(); |
| 1011 } | 993 } |
| 1012 | 994 |
| 1013 } // namespace net | 995 } // namespace net |
| OLD | NEW |