121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Copyright (c) 2010 The Chromium Authors. All rights reserved. 221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Use of this source code is governed by a BSD-style license that can be 321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// found in the LICENSE file. 421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/base/test_root_certs.h" 621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <Security/Security.h> 821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/logging.h" 1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/mac/scoped_cftyperef.h" 1121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/base/x509_certificate.h" 1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace net { 1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace { 1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#if !defined(MAC_OS_X_VERSION_10_6) || \ 1821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Declared in <Security/SecBase.h> of the 10.6 SDK. 2021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenenum { 2121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen errSecUnimplemented = -4, 2221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}; 2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif 2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 2521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsentypedef OSStatus (*SecTrustSetAnchorCertificatesOnlyFuncPtr)(SecTrustRef, 2621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Boolean); 2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 2821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenBoolean OurSecCertificateEqual(const void* value1, const void* value2) { 2921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (CFGetTypeID(value1) != SecCertificateGetTypeID() || 3021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CFGetTypeID(value2) != SecCertificateGetTypeID()) 3121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return CFEqual(value1, value2); 3221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return X509Certificate::IsSameOSCert( 3321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen reinterpret_cast<SecCertificateRef>(const_cast<void*>(value1)), 3421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen reinterpret_cast<SecCertificateRef>(const_cast<void*>(value2))); 3521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 3621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 3721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst void* RetainWrapper(CFAllocatorRef unused, const void* value) { 3821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return CFRetain(value); 3921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 4021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ReleaseWrapper(CFAllocatorRef unused, const void* value) { 4221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CFRelease(value); 4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 4421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 4521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// CFEqual prior to 10.6 only performed pointer checks on SecCertificateRefs, 4621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// rather than checking if they were the same (logical) certificate, so a 4721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// custom structure is used for the array callbacks. 4821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst CFArrayCallBacks kCertArrayCallbacks = { 4921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 0, // version 5021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen RetainWrapper, 5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ReleaseWrapper, 5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CFCopyDescription, 5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen OurSecCertificateEqual, 5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}; 5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} // namespace 5721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 5821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool TestRootCerts::Add(X509Certificate* certificate) { 5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (CFArrayContainsValue(temporary_roots_, 6021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CFRangeMake(0, CFArrayGetCount(temporary_roots_)), 6121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen certificate->os_cert_handle())) 6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return true; 6321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CFArrayAppendValue(temporary_roots_, certificate->os_cert_handle()); 6421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return true; 6521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 6621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 6721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid TestRootCerts::Clear() { 6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CFArrayRemoveAllValues(temporary_roots_); 6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 7021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 7121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool TestRootCerts::IsEmpty() const { 7221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return CFArrayGetCount(temporary_roots_) == 0; 7321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenOSStatus TestRootCerts::FixupSecTrustRef(SecTrustRef trust_ref) const { 7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (IsEmpty()) 7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return noErr; 7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 7921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CFBundleRef bundle = 8021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security")); 8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SecTrustSetAnchorCertificatesOnlyFuncPtr set_anchor_certificates_only = NULL; 8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (bundle) { 8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen set_anchor_certificates_only = 8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen reinterpret_cast<SecTrustSetAnchorCertificatesOnlyFuncPtr>( 8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CFBundleGetFunctionPointerForName(bundle, 8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CFSTR("SecTrustSetAnchorCertificatesOnly"))); 8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 8921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen OSStatus status = noErr; 9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (set_anchor_certificates_only) { 9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // OS X 10.6 includes a function where the system trusts can be 9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // preserved while appending application trusts. This is preferable, 9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // because it preserves any user trust settings (explicit distrust), 9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // which the naive copy in 10.5 does not. Unfortunately, though the 9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // function pointer may be available, it is not always implemented. If it 9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // returns errSecUnimplemented, fall through to the 10.5 behaviour. 9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen status = SecTrustSetAnchorCertificates(trust_ref, temporary_roots_); 9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (status) 9921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return status; 10021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen status = set_anchor_certificates_only(trust_ref, false); 10121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (status != errSecUnimplemented) 10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return status; 10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Restore the original settings before falling back. 10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen status = SecTrustSetAnchorCertificates(trust_ref, NULL); 10621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (status) 10721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return status; 10821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // On 10.5, the system certificates have to be copied and merged into 11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // the application trusts, and may override any user trust settings. 11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CFArrayRef system_roots = NULL; 11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen status = SecTrustCopyAnchorCertificates(&system_roots); 11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (status) 11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return status; 11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::mac::ScopedCFTypeRef<CFArrayRef> scoped_system_roots(system_roots); 11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::mac::ScopedCFTypeRef<CFMutableArrayRef> scoped_roots( 11921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, 12021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen scoped_system_roots)); 12121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(scoped_roots.get()); 12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CFArrayAppendArray(scoped_roots, temporary_roots_, 12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CFRangeMake(0, CFArrayGetCount(temporary_roots_))); 12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return SecTrustSetAnchorCertificates(trust_ref, scoped_roots); 12621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 12721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 12821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenTestRootCerts::~TestRootCerts() {} 12921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 13021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid TestRootCerts::Init() { 13121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen temporary_roots_.reset(CFArrayCreateMutable(kCFAllocatorDefault, 0, 13221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen &kCertArrayCallbacks)); 13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 13421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 13521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} // namespace net 136