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.
5 #include "net/cert/test_root_certs.h"
7 #include <Security/Security.h>
9 #include "base/logging.h"
10 #include "base/mac/mac_util.h"
11 #include "base/mac/scoped_cftyperef.h"
12 #include "net/cert/x509_certificate.h"
18 typedef OSStatus (*SecTrustSetAnchorCertificatesOnlyFuncPtr
)(SecTrustRef
,
21 Boolean
OurSecCertificateEqual(const void* value1
, const void* value2
) {
22 if (CFGetTypeID(value1
) != SecCertificateGetTypeID() ||
23 CFGetTypeID(value2
) != SecCertificateGetTypeID())
24 return CFEqual(value1
, value2
);
25 return X509Certificate::IsSameOSCert(
26 reinterpret_cast<SecCertificateRef
>(const_cast<void*>(value1
)),
27 reinterpret_cast<SecCertificateRef
>(const_cast<void*>(value2
)));
30 const void* RetainWrapper(CFAllocatorRef unused
, const void* value
) {
31 return CFRetain(value
);
34 void ReleaseWrapper(CFAllocatorRef unused
, const void* value
) {
38 // CFEqual prior to 10.6 only performed pointer checks on SecCertificateRefs,
39 // rather than checking if they were the same (logical) certificate, so a
40 // custom structure is used for the array callbacks.
41 const CFArrayCallBacks kCertArrayCallbacks
= {
46 OurSecCertificateEqual
,
51 bool TestRootCerts::Add(X509Certificate
* certificate
) {
52 if (CFArrayContainsValue(temporary_roots_
,
53 CFRangeMake(0, CFArrayGetCount(temporary_roots_
)),
54 certificate
->os_cert_handle()))
56 CFArrayAppendValue(temporary_roots_
, certificate
->os_cert_handle());
60 void TestRootCerts::Clear() {
61 CFArrayRemoveAllValues(temporary_roots_
);
64 bool TestRootCerts::IsEmpty() const {
65 return CFArrayGetCount(temporary_roots_
) == 0;
68 OSStatus
TestRootCerts::FixupSecTrustRef(SecTrustRef trust_ref
) const {
72 // Despite SecTrustSetAnchorCertificatesOnly existing in OS X 10.6, and
73 // being documented as available, it is not actually implemented. On 10.7+,
74 // however, it always works.
75 if (base::mac::IsOSLionOrLater()) {
76 OSStatus status
= SecTrustSetAnchorCertificates(trust_ref
,
80 return SecTrustSetAnchorCertificatesOnly(trust_ref
, !allow_system_trust_
);
83 if (!allow_system_trust_
) {
84 // Avoid any copying if system roots are not to be trusted. This acts as
85 // an exclusive list on 10.6, replacing the built-ins.
86 return SecTrustSetAnchorCertificates(trust_ref
, temporary_roots_
);
89 // Otherwise, both system trust and temporary_roots_ must be trusted.
90 // Emulate the functionality of SecTrustSetAnchorCertificatesOnly by
91 // creating a copy of the system roots and merging with temporary_roots_.
92 CFArrayRef system_roots
= NULL
;
93 OSStatus status
= SecTrustCopyAnchorCertificates(&system_roots
);
97 base::ScopedCFTypeRef
<CFArrayRef
> scoped_system_roots(system_roots
);
98 base::ScopedCFTypeRef
<CFMutableArrayRef
> scoped_roots(
99 CFArrayCreateMutableCopy(kCFAllocatorDefault
, 0, scoped_system_roots
));
100 CFArrayAppendArray(scoped_roots
, temporary_roots_
,
101 CFRangeMake(0, CFArrayGetCount(temporary_roots_
)));
102 return SecTrustSetAnchorCertificates(trust_ref
, scoped_roots
);
105 void TestRootCerts::SetAllowSystemTrust(bool allow_system_trust
) {
106 allow_system_trust_
= allow_system_trust
;
109 TestRootCerts::~TestRootCerts() {}
111 void TestRootCerts::Init() {
112 temporary_roots_
.reset(CFArrayCreateMutable(kCFAllocatorDefault
, 0,
113 &kCertArrayCallbacks
));
114 allow_system_trust_
= true;