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