1/* 2 * Copyright (c) 2007-2009 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * SecTrustStore.c - CertificateSource API to a system root certificate store 26 */ 27#include <Security/SecTrustStore.h> 28 29#include <Security/SecCertificateInternal.h> 30#include <Security/SecInternal.h> 31#include <CoreFoundation/CFString.h> 32#include <AssertMacros.h> 33#include "securityd_client.h" 34#include "SecuritydXPC.h" 35#include "SecFramework.h" 36#include <sys/stat.h> 37#include <stdio.h> 38#include <dirent.h> 39#include "SecTrustPriv.h" 40#include <utilities/SecCFError.h> 41#include "utilities/SecDb.h" 42 43static CFStringRef kSecTrustStoreUserName = CFSTR("user"); 44 45SecTrustStoreRef SecTrustStoreForDomain(SecTrustStoreDomain domain) { 46 CFStringRef domainName; 47 if (domain == kSecTrustStoreDomainUser) { 48 domainName = kSecTrustStoreUserName; 49 } else { 50 return NULL; 51 } 52 53 if (gSecurityd) { 54 return gSecurityd->sec_trust_store_for_domain(domainName, NULL); 55 } else { 56 return (SecTrustStoreRef)domainName; 57 } 58} 59 60static bool string_data_to_bool_error(enum SecXPCOperation op, SecTrustStoreRef ts, CFDataRef digest, CFErrorRef *error) 61{ 62 return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { 63 return SecXPCDictionarySetString(message, kSecXPCKeyDomain, (CFStringRef)ts, error) && 64 SecXPCDictionarySetData(message, kSecXPCKeyDigest, digest, error); 65 }, NULL); 66} 67 68static bool string_data_to_bool_bool_error(enum SecXPCOperation op, SecTrustStoreRef ts, CFDataRef digest, bool *result, CFErrorRef *error) 69{ 70 return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { 71 return SecXPCDictionarySetString(message, kSecXPCKeyDomain, (CFStringRef)ts, error) && 72 SecXPCDictionarySetData(message, kSecXPCKeyDigest, digest, error); 73 }, ^bool(xpc_object_t response, CFErrorRef *error) { 74 if (result) 75 *result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); 76 return true; 77 }); 78} 79 80Boolean SecTrustStoreContains(SecTrustStoreRef ts, 81 SecCertificateRef certificate) { 82 CFDataRef digest; 83 bool ok = false; 84 __block bool contains = false; 85 86 require(ts, errOut); 87 require(digest = SecCertificateGetSHA1Digest(certificate), errOut); 88 ok = (SecOSStatusWith(^bool (CFErrorRef *error) { 89 return SECURITYD_XPC(sec_trust_store_contains, string_data_to_bool_bool_error, ts, digest, &contains, error); 90 }) == errSecSuccess); 91 92errOut: 93 return ok && contains; 94} 95 96static bool SecXPCDictionarySetCertificate(xpc_object_t message, const char *key, SecCertificateRef certificate, CFErrorRef *error) { 97 if (certificate) { 98 xpc_dictionary_set_data(message, key, SecCertificateGetBytePtr(certificate), 99 SecCertificateGetLength(certificate)); 100 return true; 101 } 102 return SecError(errSecParam, error, CFSTR("NULL certificate")); 103} 104 105 106static bool string_cert_cftype_to_error(enum SecXPCOperation op, SecTrustStoreRef ts, SecCertificateRef certificate, CFTypeRef trustSettingsDictOrArray, CFErrorRef *error) 107{ 108 return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { 109 bool ok = false; 110 ok = SecXPCDictionarySetString(message, kSecXPCKeyDomain, (CFStringRef)ts, error) && 111 SecXPCDictionarySetCertificate(message, kSecXPCKeyCertificate, certificate, error) && 112 (!trustSettingsDictOrArray || SecXPCDictionarySetPList(message, kSecXPCKeySettings, trustSettingsDictOrArray, error)); 113 return ok; 114 }, NULL); 115} 116 117OSStatus SecTrustStoreSetTrustSettings(SecTrustStoreRef ts, 118 SecCertificateRef certificate, 119 CFTypeRef trustSettingsDictOrArray) { 120 return SecOSStatusWith(^bool (CFErrorRef *error) { 121 return SECURITYD_XPC(sec_trust_store_set_trust_settings, string_cert_cftype_to_error, ts, certificate, trustSettingsDictOrArray, error); 122 }); 123} 124 125OSStatus SecTrustStoreRemoveCertificate(SecTrustStoreRef ts, 126 SecCertificateRef certificate) 127{ 128 CFDataRef digest; 129 OSStatus status = errSecParam; 130 131 require(ts, errOut); 132 require(digest = SecCertificateGetSHA1Digest(certificate), errOut); 133 require(gSecurityd || ts == (SecTrustStoreRef)kSecTrustStoreUserName, errOut); 134 status = SecOSStatusWith(^bool (CFErrorRef *error) { 135 return SECURITYD_XPC(sec_trust_store_remove_certificate, string_data_to_bool_error, ts, digest, error); 136 }); 137 138errOut: 139 return status; 140} 141 142 143static CFIndex GetOTAAssetVersionNumber() 144{ 145 CFIndex result = 0; 146 int version = 0; 147 148 if (errSecSuccess == SecTrustGetOTAPKIAssetVersionNumber(&version)) 149 { 150 result = version; 151 } 152 153 return result; 154} 155 156 157 158OSStatus SecTrustStoreGetSettingsVersionNumber(SecTrustSettingsVersionNumber* p_settings_version_number) 159{ 160 OSStatus status = errSecParam; 161 if (NULL == p_settings_version_number) 162 { 163 return status; 164 } 165 166 CFIndex versionNumber = GetOTAAssetVersionNumber(); 167 *p_settings_version_number = (SecTrustSettingsVersionNumber)versionNumber; 168 169 return errSecSuccess; 170} 171