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 |