OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/base/test_root_certs.h" |
| 6 |
| 7 #include <Security/Security.h> |
| 8 |
| 9 #include "base/logging.h" |
| 10 #include "base/mac/scoped_cftyperef.h" |
| 11 #include "net/base/x509_certificate.h" |
| 12 |
| 13 namespace net { |
| 14 |
| 15 namespace { |
| 16 |
| 17 #if !defined(MAC_OS_X_VERSION_10_6) || \ |
| 18 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 |
| 19 // Declared in <Security/SecBase.h> of the 10.6 SDK. |
| 20 enum { |
| 21 errSecUnimplemented = -4, |
| 22 }; |
| 23 #endif |
| 24 |
| 25 typedef OSStatus (*SecTrustSetAnchorCertificatesOnlyFuncPtr)(SecTrustRef, |
| 26 Boolean); |
| 27 |
| 28 Boolean OurSecCertificateEqual(const void* value1, const void* value2) { |
| 29 if (CFGetTypeID(value1) != SecCertificateGetTypeID() || |
| 30 CFGetTypeID(value2) != SecCertificateGetTypeID()) |
| 31 return CFEqual(value1, value2); |
| 32 return X509Certificate::IsSameOSCert( |
| 33 reinterpret_cast<SecCertificateRef>(const_cast<void*>(value1)), |
| 34 reinterpret_cast<SecCertificateRef>(const_cast<void*>(value2))); |
| 35 } |
| 36 |
| 37 const void* RetainWrapper(CFAllocatorRef unused, const void* value) { |
| 38 return CFRetain(value); |
| 39 } |
| 40 |
| 41 void ReleaseWrapper(CFAllocatorRef unused, const void* value) { |
| 42 CFRelease(value); |
| 43 } |
| 44 |
| 45 // CFEqual prior to 10.6 only performed pointer checks on SecCertificateRefs, |
| 46 // rather than checking if they were the same (logical) certificate, so a |
| 47 // custom structure is used for the array callbacks. |
| 48 const CFArrayCallBacks kCertArrayCallbacks = { |
| 49 0, // version |
| 50 RetainWrapper, |
| 51 ReleaseWrapper, |
| 52 CFCopyDescription, |
| 53 OurSecCertificateEqual, |
| 54 }; |
| 55 |
| 56 } // namespace |
| 57 |
| 58 bool TestRootCerts::Add(X509Certificate* certificate) { |
| 59 if (CFArrayContainsValue(temporary_roots_, |
| 60 CFRangeMake(0, CFArrayGetCount(temporary_roots_)), |
| 61 certificate->os_cert_handle())) |
| 62 return true; |
| 63 CFArrayAppendValue(temporary_roots_, certificate->os_cert_handle()); |
| 64 return true; |
| 65 } |
| 66 |
| 67 void TestRootCerts::Clear() { |
| 68 CFArrayRemoveAllValues(temporary_roots_); |
| 69 } |
| 70 |
| 71 bool TestRootCerts::IsEmpty() const { |
| 72 return CFArrayGetCount(temporary_roots_) == 0; |
| 73 } |
| 74 |
| 75 OSStatus TestRootCerts::FixupSecTrustRef(SecTrustRef trust_ref) const { |
| 76 if (IsEmpty()) |
| 77 return noErr; |
| 78 |
| 79 CFBundleRef bundle = |
| 80 CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security")); |
| 81 SecTrustSetAnchorCertificatesOnlyFuncPtr set_anchor_certificates_only = NULL; |
| 82 if (bundle) { |
| 83 set_anchor_certificates_only = |
| 84 reinterpret_cast<SecTrustSetAnchorCertificatesOnlyFuncPtr>( |
| 85 CFBundleGetFunctionPointerForName(bundle, |
| 86 CFSTR("SecTrustSetAnchorCertificatesOnly"))); |
| 87 } |
| 88 |
| 89 OSStatus status = noErr; |
| 90 if (set_anchor_certificates_only) { |
| 91 // OS X 10.6 includes a function where the system trusts can be |
| 92 // preserved while appending application trusts. This is preferable, |
| 93 // because it preserves any user trust settings (explicit distrust), |
| 94 // which the naive copy in 10.5 does not. Unfortunately, though the |
| 95 // function pointer may be available, it is not always implemented. If it |
| 96 // returns errSecUnimplemented, fall through to the 10.5 behaviour. |
| 97 status = SecTrustSetAnchorCertificates(trust_ref, temporary_roots_); |
| 98 if (status) |
| 99 return status; |
| 100 status = set_anchor_certificates_only(trust_ref, false); |
| 101 if (status != errSecUnimplemented) |
| 102 return status; |
| 103 |
| 104 // Restore the original settings before falling back. |
| 105 status = SecTrustSetAnchorCertificates(trust_ref, NULL); |
| 106 if (status) |
| 107 return status; |
| 108 } |
| 109 |
| 110 // On 10.5, the system certificates have to be copied and merged into |
| 111 // the application trusts, and may override any user trust settings. |
| 112 CFArrayRef system_roots = NULL; |
| 113 status = SecTrustCopyAnchorCertificates(&system_roots); |
| 114 if (status) |
| 115 return status; |
| 116 |
| 117 base::mac::ScopedCFTypeRef<CFArrayRef> scoped_system_roots(system_roots); |
| 118 base::mac::ScopedCFTypeRef<CFMutableArrayRef> scoped_roots( |
| 119 CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, |
| 120 scoped_system_roots)); |
| 121 DCHECK(scoped_roots.get()); |
| 122 |
| 123 CFArrayAppendArray(scoped_roots, temporary_roots_, |
| 124 CFRangeMake(0, CFArrayGetCount(temporary_roots_))); |
| 125 return SecTrustSetAnchorCertificates(trust_ref, scoped_roots); |
| 126 } |
| 127 |
| 128 TestRootCerts::~TestRootCerts() {} |
| 129 |
| 130 void TestRootCerts::Init() { |
| 131 temporary_roots_.reset(CFArrayCreateMutable(kCFAllocatorDefault, 0, |
| 132 &kCertArrayCallbacks)); |
| 133 } |
| 134 |
| 135 } // namespace net |
OLD | NEW |