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