1/* 2 * Copyright (c) 2006-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// 25// SecCode - API frame for SecCode objects. 26// 27// Note that some SecCode* functions take SecStaticCodeRef arguments in order to 28// accept either static or dynamic code references, operating on the respective 29// StaticCode. Those functions are in SecStaticCode.cpp, not here, despite their name. 30// 31#include "cs.h" 32#include "Code.h" 33#include "cskernel.h" 34#include <security_utilities/cfmunge.h> 35 36using namespace CodeSigning; 37 38 39// 40// CFError user info keys 41// 42const CFStringRef kSecCFErrorArchitecture = CFSTR("SecCSArchitecture"); 43const CFStringRef kSecCFErrorPattern = CFSTR("SecCSPattern"); 44const CFStringRef kSecCFErrorResourceSeal = CFSTR("SecCSResourceSeal"); 45const CFStringRef kSecCFErrorResourceAdded = CFSTR("SecCSResourceAdded"); 46const CFStringRef kSecCFErrorResourceAltered = CFSTR("SecCSResourceAltered"); 47const CFStringRef kSecCFErrorResourceMissing = CFSTR("SecCSResourceMissing"); 48const CFStringRef kSecCFErrorInfoPlist = CFSTR("SecCSInfoPlist"); 49const CFStringRef kSecCFErrorGuestAttributes = CFSTR("SecCSGuestAttributes"); 50const CFStringRef kSecCFErrorRequirementSyntax = CFSTR("SecRequirementSyntax"); 51const CFStringRef kSecCFErrorPath = CFSTR("SecComponentPath"); 52 53 54// 55// CF-standard type code functions 56// 57CFTypeID SecCodeGetTypeID(void) 58{ 59 BEGIN_CSAPI 60 return gCFObjects().Code.typeID; 61 END_CSAPI1(_kCFRuntimeNotATypeID) 62} 63 64 65// 66// Get a reference to the calling code. 67// 68OSStatus SecCodeCopySelf(SecCSFlags flags, SecCodeRef *selfRef) 69{ 70 BEGIN_CSAPI 71 72 checkFlags(flags); 73 CFRef<CFMutableDictionaryRef> attributes = makeCFMutableDictionary(1, 74 kSecGuestAttributePid, CFTempNumber(getpid()).get()); 75 CodeSigning::Required(selfRef) = SecCode::autoLocateGuest(attributes, flags)->handle(false); 76 77 END_CSAPI 78} 79 80 81// 82// Get the dynamic status of a code. 83// 84OSStatus SecCodeGetStatus(SecCodeRef codeRef, SecCSFlags flags, SecCodeStatus *status) 85{ 86 BEGIN_CSAPI 87 88 checkFlags(flags); 89 CodeSigning::Required(status) = SecCode::required(codeRef)->status(); 90 91 END_CSAPI 92} 93 94 95// 96// Change the dynamic status of a code 97// 98OSStatus SecCodeSetStatus(SecCodeRef codeRef, SecCodeStatusOperation operation, 99 CFDictionaryRef arguments, SecCSFlags flags) 100{ 101 BEGIN_CSAPI 102 103 checkFlags(flags); 104 SecCode::required(codeRef)->status(operation, arguments); 105 106 END_CSAPI 107} 108 109 110// 111// Get the StaticCode for an Code 112// 113OSStatus SecCodeCopyStaticCode(SecCodeRef codeRef, SecCSFlags flags, SecStaticCodeRef *staticCodeRef) 114{ 115 BEGIN_CSAPI 116 117 checkFlags(flags, kSecCSUseAllArchitectures); 118 SecPointer<SecStaticCode> staticCode = SecCode::required(codeRef)->staticCode(); 119 if (flags & kSecCSUseAllArchitectures) 120 if (Universal* macho = staticCode->diskRep()->mainExecutableImage()) // Mach-O main executable 121 if (macho->narrowed()) { 122 // create a new StaticCode comprising the whole fat file 123 RefPointer<DiskRep> rep = DiskRep::bestGuess(staticCode->diskRep()->mainExecutablePath()); 124 staticCode = new SecStaticCode(rep); 125 } 126 CodeSigning::Required(staticCodeRef) = staticCode ? staticCode->handle() : NULL; 127 128 END_CSAPI 129} 130 131 132// 133// Get the host for an Code 134// 135OSStatus SecCodeCopyHost(SecCodeRef guestRef, SecCSFlags flags, SecCodeRef *hostRef) 136{ 137 BEGIN_CSAPI 138 139 checkFlags(flags); 140 SecPointer<SecCode> host = SecCode::required(guestRef)->host(); 141 CodeSigning::Required(hostRef) = host ? host->handle() : NULL; 142 143 END_CSAPI 144} 145 146 147// 148// Find a guest by attribute(s) 149// 150const CFStringRef kSecGuestAttributeCanonical = CFSTR("canonical"); 151const CFStringRef kSecGuestAttributeHash = CFSTR("codedirectory-hash"); 152const CFStringRef kSecGuestAttributeMachPort = CFSTR("mach-port"); 153const CFStringRef kSecGuestAttributePid = CFSTR("pid"); 154const CFStringRef kSecGuestAttributeDynamicCode = CFSTR("dynamicCode"); 155const CFStringRef kSecGuestAttributeDynamicCodeInfoPlist = CFSTR("dynamicCodeInfoPlist"); 156const CFStringRef kSecGuestAttributeArchitecture = CFSTR("architecture"); 157const CFStringRef kSecGuestAttributeSubarchitecture = CFSTR("subarchitecture"); 158 159OSStatus SecCodeCopyGuestWithAttributes(SecCodeRef hostRef, 160 CFDictionaryRef attributes, SecCSFlags flags, SecCodeRef *guestRef) 161{ 162 BEGIN_CSAPI 163 164 checkFlags(flags); 165 if (hostRef) { 166 if (SecCode *guest = SecCode::required(hostRef)->locateGuest(attributes)) 167 CodeSigning::Required(guestRef) = guest->handle(false); 168 else 169 return errSecCSNoSuchCode; 170 } else 171 CodeSigning::Required(guestRef) = SecCode::autoLocateGuest(attributes, flags)->handle(false); 172 173 END_CSAPI 174} 175 176 177// 178// Shorthand for getting the SecCodeRef for a UNIX process 179// 180OSStatus SecCodeCreateWithPID(pid_t pid, SecCSFlags flags, SecCodeRef *processRef) 181{ 182 BEGIN_CSAPI 183 184 checkFlags(flags); 185 if (SecCode *guest = KernelCode::active()->locateGuest(CFTemp<CFDictionaryRef>("{%O=%d}", kSecGuestAttributePid, pid))) 186 CodeSigning::Required(processRef) = guest->handle(false); 187 else 188 return errSecCSNoSuchCode; 189 190 END_CSAPI 191} 192 193 194// 195// Check validity of an Code 196// 197OSStatus SecCodeCheckValidity(SecCodeRef codeRef, SecCSFlags flags, 198 SecRequirementRef requirementRef) 199{ 200 return SecCodeCheckValidityWithErrors(codeRef, flags, requirementRef, NULL); 201} 202 203OSStatus SecCodeCheckValidityWithErrors(SecCodeRef codeRef, SecCSFlags flags, 204 SecRequirementRef requirementRef, CFErrorRef *errors) 205{ 206 BEGIN_CSAPI 207 208 checkFlags(flags, 209 kSecCSConsiderExpiration 210 | kSecCSEnforceRevocationChecks); 211 SecPointer<SecCode> code = SecCode::required(codeRef); 212 code->checkValidity(flags); 213 if (const SecRequirement *req = SecRequirement::optional(requirementRef)) 214 code->staticCode()->validateRequirement(req->requirement(), errSecCSReqFailed); 215 216 END_CSAPI_ERRORS 217} 218 219 220// 221// Collect suitably laundered information about the code signature of a SecStaticCode 222// and return it as a CFDictionary. 223// 224// This API contracts to return a few pieces of information even for unsigned 225// code. This means that a SecStaticCodeRef is usable as a basic indentifier 226// (i.e. handle) for any code out there. 227// 228const CFStringRef kSecCodeInfoCertificates = CFSTR("certificates"); 229const CFStringRef kSecCodeInfoChangedFiles = CFSTR("changed-files"); 230const CFStringRef kSecCodeInfoCMS = CFSTR("cms"); 231const CFStringRef kSecCodeInfoDesignatedRequirement = CFSTR("designated-requirement"); 232const CFStringRef kSecCodeInfoEntitlements = CFSTR("entitlements"); 233const CFStringRef kSecCodeInfoEntitlementsDict = CFSTR("entitlements-dict"); 234const CFStringRef kSecCodeInfoFlags = CFSTR("flags"); 235const CFStringRef kSecCodeInfoFormat = CFSTR("format"); 236const CFStringRef kSecCodeInfoDigestAlgorithm = CFSTR("digest-algorithm"); 237const CFStringRef kSecCodeInfoIdentifier = CFSTR("identifier"); 238const CFStringRef kSecCodeInfoImplicitDesignatedRequirement = CFSTR("implicit-requirement"); 239const CFStringRef kSecCodeInfoMainExecutable = CFSTR("main-executable"); 240const CFStringRef kSecCodeInfoPList = CFSTR("info-plist"); 241const CFStringRef kSecCodeInfoRequirements = CFSTR("requirements"); 242const CFStringRef kSecCodeInfoRequirementData = CFSTR("requirement-data"); 243const CFStringRef kSecCodeInfoSource = CFSTR("source"); 244const CFStringRef kSecCodeInfoStatus = CFSTR("status"); 245const CFStringRef kSecCodeInfoTeamIdentifier = CFSTR("teamid"); 246const CFStringRef kSecCodeInfoTime = CFSTR("signing-time"); 247const CFStringRef kSecCodeInfoTimestamp = CFSTR("signing-timestamp"); 248const CFStringRef kSecCodeInfoTrust = CFSTR("trust"); 249const CFStringRef kSecCodeInfoUnique = CFSTR("unique"); 250 251const CFStringRef kSecCodeInfoCodeDirectory = CFSTR("CodeDirectory"); 252const CFStringRef kSecCodeInfoCodeOffset = CFSTR("CodeOffset"); 253const CFStringRef kSecCodeInfoResourceDirectory = CFSTR("ResourceDirectory"); 254 255 256OSStatus SecCodeCopySigningInformation(SecStaticCodeRef codeRef, SecCSFlags flags, 257 CFDictionaryRef *infoRef) 258{ 259 BEGIN_CSAPI 260 261 checkFlags(flags, 262 kSecCSInternalInformation 263 | kSecCSSigningInformation 264 | kSecCSRequirementInformation 265 | kSecCSDynamicInformation 266 | kSecCSContentInformation); 267 268 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(codeRef); 269 CFRef<CFDictionaryRef> info = code->signingInformation(flags); 270 271 if (flags & kSecCSDynamicInformation) 272 if (SecPointer<SecCode> dcode = SecStaticCode::optionalDynamic(codeRef)) 273 info.take(cfmake<CFDictionaryRef>("{+%O,%O=%u}", info.get(), kSecCodeInfoStatus, dcode->status())); 274 275 CodeSigning::Required(infoRef) = info.yield(); 276 277 END_CSAPI 278} 279