Chromium Code Reviews| 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 | |
|
bulach
2010/11/17 17:17:30
append ,
| |
| 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::SetAnchorCertificates(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 temporary_roots_.reset(CFArrayCreateMutable(kCFAllocatorDefault, 0, | |
| 130 &kCertArrayCallbacks)); | |
| 131 } | |
| 132 | |
| 133 TestRootCerts::~TestRootCerts() { | |
| 134 } | |
| 135 | |
| 136 } // namespace net | |
| OLD | NEW |