1/* 2 * Copyright (c) 2002-2004,2011-2014 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#include <Security/SecTrustedApplicationPriv.h> 25#include <security_keychain/TrustedApplication.h> 26#include <security_keychain/Certificate.h> 27#include <securityd_client/ssclient.h> // for code equivalence SPIs 28 29#include "SecBridge.h" 30 31 32 33#pragma clang diagnostic push 34#pragma clang diagnostic ignored "-Wunused-function" 35static inline CssmData cfData(CFDataRef data) 36{ 37 return CssmData(const_cast<UInt8 *>(CFDataGetBytePtr(data)), 38 CFDataGetLength(data)); 39} 40#pragma clang diagnostic pop 41 42 43CFTypeID 44SecTrustedApplicationGetTypeID(void) 45{ 46 BEGIN_SECAPI 47 48 return gTypes().TrustedApplication.typeID; 49 50 END_SECAPI1(_kCFRuntimeNotATypeID) 51} 52 53 54OSStatus 55SecTrustedApplicationCreateFromPath(const char *path, SecTrustedApplicationRef *appRef) 56{ 57 BEGIN_SECAPI 58 SecPointer<TrustedApplication> app = 59 path ? new TrustedApplication(path) : new TrustedApplication; 60 Required(appRef) = app->handle(); 61 END_SECAPI 62} 63 64OSStatus SecTrustedApplicationCopyData(SecTrustedApplicationRef appRef, 65 CFDataRef *dataRef) 66{ 67 BEGIN_SECAPI 68 const char *path = TrustedApplication::required(appRef)->path(); 69 Required(dataRef) = CFDataCreate(NULL, (const UInt8 *)path, strlen(path) + 1); 70 END_SECAPI 71} 72 73OSStatus SecTrustedApplicationSetData(SecTrustedApplicationRef appRef, 74 CFDataRef dataRef) 75{ 76 BEGIN_SECAPI 77 if (!dataRef) 78 return errSecParam; 79 TrustedApplication::required(appRef)->data(dataRef); 80 END_SECAPI 81} 82 83 84OSStatus 85SecTrustedApplicationValidateWithPath(SecTrustedApplicationRef appRef, const char *path) 86{ 87 BEGIN_SECAPI 88 TrustedApplication &app = *TrustedApplication::required(appRef); 89 if (!app.verifyToDisk(path)) 90 return CSSMERR_CSP_VERIFY_FAILED; 91 END_SECAPI 92} 93 94 95// 96// Convert from/to external data representation 97// 98OSStatus SecTrustedApplicationCopyExternalRepresentation( 99 SecTrustedApplicationRef appRef, 100 CFDataRef *externalRef) 101{ 102 BEGIN_SECAPI 103 TrustedApplication &app = *TrustedApplication::required(appRef); 104 Required(externalRef) = app.externalForm(); 105 END_SECAPI 106} 107 108OSStatus SecTrustedApplicationCreateWithExternalRepresentation( 109 CFDataRef externalRef, 110 SecTrustedApplicationRef *appRef) 111{ 112 BEGIN_SECAPI 113 Required(appRef) = (new TrustedApplication(externalRef))->handle(); 114 END_SECAPI 115} 116 117 118OSStatus 119SecTrustedApplicationMakeEquivalent(SecTrustedApplicationRef oldRef, 120 SecTrustedApplicationRef newRef, UInt32 flags) 121{ 122 BEGIN_SECAPI 123 if (flags & ~kSecApplicationValidFlags) 124 return errSecParam; 125 SecurityServer::ClientSession ss(Allocator::standard(), Allocator::standard()); 126 TrustedApplication *oldApp = TrustedApplication::required(oldRef); 127 TrustedApplication *newApp = TrustedApplication::required(newRef); 128 ss.addCodeEquivalence(oldApp->legacyHash(), newApp->legacyHash(), oldApp->path(), 129 flags & kSecApplicationFlagSystemwide); 130 END_SECAPI 131} 132 133OSStatus 134SecTrustedApplicationRemoveEquivalence(SecTrustedApplicationRef appRef, UInt32 flags) 135{ 136 BEGIN_SECAPI 137 if (flags & ~kSecApplicationValidFlags) 138 return errSecParam; 139 SecurityServer::ClientSession ss(Allocator::standard(), Allocator::standard()); 140 TrustedApplication *app = TrustedApplication::required(appRef); 141 ss.removeCodeEquivalence(app->legacyHash(), app->path(), 142 flags & kSecApplicationFlagSystemwide); 143 END_SECAPI 144} 145 146 147/* 148 * Check to see if an application at a given path is a candidate for 149 * pre-emptive code equivalency establishment 150 */ 151OSStatus 152SecTrustedApplicationIsUpdateCandidate(const char *installroot, const char *path) 153{ 154 BEGIN_SECAPI 155 156 // strip installroot 157 if (installroot) { 158 size_t rootlen = strlen(installroot); 159 if (!strncmp(installroot, path, rootlen)) 160 path += rootlen - 1; // keep the slash 161 } 162 163 // look up in database 164 static ModuleNexus<PathDatabase> paths; 165 static ModuleNexus<RecursiveMutex> mutex; 166 StLock<Mutex>_(mutex()); 167 168 if (!paths()[path]) 169 return CSSMERR_DL_RECORD_NOT_FOUND; // whatever 170 END_SECAPI 171} 172 173 174/* 175 * Point the system at another system root for equivalence use. 176 * This is for system update installers (only)! 177 */ 178OSStatus 179SecTrustedApplicationUseAlternateSystem(const char *systemRoot) 180{ 181 BEGIN_SECAPI 182 Required(systemRoot); 183 SecurityServer::ClientSession ss(Allocator::standard(), Allocator::standard()); 184 ss.setAlternateSystemRoot(systemRoot); 185 END_SECAPI 186} 187 188 189/* 190 * Gateway between traditional SecTrustedApplicationRefs and the Code Signing 191 * subsystem. Invisible to the naked eye, as of 10.5 (Leopard), these reference 192 * may contain Cod e Signing Requirement objects (SecRequirementRefs). For backward 193 * compatibility, these are handled implicitly at the SecAccess/SecACL layer. 194 * However, Those Who Know can bridge the gap for additional functionality. 195 */ 196OSStatus SecTrustedApplicationCreateFromRequirement(const char *description, 197 SecRequirementRef requirement, SecTrustedApplicationRef *appRef) 198{ 199 BEGIN_SECAPI 200 if (description == NULL) 201 description = "csreq://"; // default to "generic requirement" 202 SecPointer<TrustedApplication> app = new TrustedApplication(description, requirement); 203 Required(appRef) = app->handle(); 204 END_SECAPI 205} 206 207OSStatus SecTrustedApplicationCopyRequirement(SecTrustedApplicationRef appRef, 208 SecRequirementRef *requirement) 209{ 210 BEGIN_SECAPI 211 Required(requirement) = TrustedApplication::required(appRef)->requirement(); 212 if (*requirement) 213 CFRetain(*requirement); 214 END_SECAPI 215} 216 217 218/* 219 * Create an application group reference. 220 */ 221OSStatus SecTrustedApplicationCreateApplicationGroup(const char *groupName, 222 SecCertificateRef anchor, SecTrustedApplicationRef *appRef) 223{ 224 BEGIN_SECAPI 225 226 CFRef<SecRequirementRef> req; 227 MacOSError::check(SecRequirementCreateGroup(CFTempString(groupName), anchor, 228 kSecCSDefaultFlags, &req.aref())); 229 string description = string("group://") + groupName; 230 if (anchor) { 231 Certificate *cert = Certificate::required(anchor); 232 const CssmData &hash = cert->publicKeyHash(); 233 description = description + "?cert=" + cfString(cert->commonName()) 234 + "&hash=" + hash.toHex(); 235 } 236 SecPointer<TrustedApplication> app = new TrustedApplication(description, req); 237 Required(appRef) = app->handle(); 238 239 END_SECAPI 240} 241