1/* 2 * Copyright (c) 2006-2007 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// SecStaticCode - API frame for SecStaticCode objects 26// 27#include "cs.h" 28#include "StaticCode.h" 29#include <security_utilities/cfmunge.h> 30#include <fcntl.h> 31#include <dirent.h> 32 33using namespace CodeSigning; 34 35 36// 37// CF-standard type code function 38// 39CFTypeID SecStaticCodeGetTypeID(void) 40{ 41 BEGIN_CSAPI 42 return gCFObjects().StaticCode.typeID; 43 END_CSAPI1(_kCFRuntimeNotATypeID) 44} 45 46 47// 48// Create an StaticCode directly from disk path. 49// 50OSStatus SecStaticCodeCreateWithPath(CFURLRef path, SecCSFlags flags, SecStaticCodeRef *staticCodeRef) 51{ 52 BEGIN_CSAPI 53 54 checkFlags(flags); 55 CodeSigning::Required(staticCodeRef) = (new SecStaticCode(DiskRep::bestGuess(cfString(path).c_str())))->handle(); 56 57 END_CSAPI 58} 59 60const CFStringRef kSecCodeAttributeArchitecture = CFSTR("architecture"); 61const CFStringRef kSecCodeAttributeSubarchitecture =CFSTR("subarchitecture"); 62const CFStringRef kSecCodeAttributeBundleVersion = CFSTR("bundleversion"); 63const CFStringRef kSecCodeAttributeUniversalFileOffset = CFSTR("UniversalFileOffset"); 64 65OSStatus SecStaticCodeCreateWithPathAndAttributes(CFURLRef path, SecCSFlags flags, CFDictionaryRef attributes, 66 SecStaticCodeRef *staticCodeRef) 67{ 68 BEGIN_CSAPI 69 70 checkFlags(flags); 71 DiskRep::Context ctx; 72 std::string version; // holds memory placed into ctx 73 if (attributes) { 74 std::string archName; 75 int archNumber, subarchNumber, offset; 76 if (cfscan(attributes, "{%O=%d}", kSecCodeAttributeUniversalFileOffset, &offset)) { 77 ctx.offset = offset; 78 } else if (cfscan(attributes, "{%O=%s}", kSecCodeAttributeArchitecture, &archName)) { 79 ctx.arch = Architecture(archName.c_str()); 80 } else if (cfscan(attributes, "{%O=%d,%O=%d}", 81 kSecCodeAttributeArchitecture, &archNumber, kSecCodeAttributeSubarchitecture, &subarchNumber)) 82 ctx.arch = Architecture(archNumber, subarchNumber); 83 else if (cfscan(attributes, "{%O=%d}", kSecCodeAttributeArchitecture, &archNumber)) 84 ctx.arch = Architecture(archNumber); 85 if (cfscan(attributes, "{%O=%s}", kSecCodeAttributeBundleVersion, &version)) 86 ctx.version = version.c_str(); 87 } 88 89 CodeSigning::Required(staticCodeRef) = (new SecStaticCode(DiskRep::bestGuess(cfString(path).c_str(), &ctx)))->handle(); 90 91 END_CSAPI 92} 93 94 95// 96// Check static validity of a StaticCode 97// 98OSStatus SecStaticCodeCheckValidity(SecStaticCodeRef staticCodeRef, SecCSFlags flags, 99 SecRequirementRef requirementRef) 100{ 101 return SecStaticCodeCheckValidityWithErrors(staticCodeRef, flags, requirementRef, NULL); 102} 103 104OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, SecCSFlags flags, 105 SecRequirementRef requirementRef, CFErrorRef *errors) 106{ 107 BEGIN_CSAPI 108 109 checkFlags(flags, 110 kSecCSCheckAllArchitectures 111 | kSecCSDoNotValidateExecutable 112 | kSecCSDoNotValidateResources 113 | kSecCSConsiderExpiration 114 | kSecCSEnforceRevocationChecks 115 | kSecCSCheckNestedCode 116 | kSecCSStrictValidate); 117 118 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(staticCodeRef); 119 const SecRequirement *req = SecRequirement::optional(requirementRef); 120 DTRACK(CODESIGN_EVAL_STATIC, code, (char*)code->mainExecutablePath().c_str()); 121 code->staticValidate(flags, req); 122 123 END_CSAPI_ERRORS 124} 125 126 127// 128// ==================================================================================== 129// 130// The following API functions are called SecCode* but accept both SecCodeRef and 131// SecStaticCodeRef arguments, operating on the implied SecStaticCodeRef as appropriate. 132// Hence they're here, rather than in SecCode.cpp. 133// 134 135 136// 137// Retrieve location information for an StaticCode. 138// 139OSStatus SecCodeCopyPath(SecStaticCodeRef staticCodeRef, SecCSFlags flags, CFURLRef *path) 140{ 141 BEGIN_CSAPI 142 143 checkFlags(flags); 144 SecPointer<SecStaticCode> staticCode = SecStaticCode::requiredStatic(staticCodeRef); 145 CodeSigning::Required(path) = staticCode->copyCanonicalPath(); 146 147 END_CSAPI 148} 149 150 151// 152// Fetch or make up a designated requirement 153// 154OSStatus SecCodeCopyDesignatedRequirement(SecStaticCodeRef staticCodeRef, SecCSFlags flags, 155 SecRequirementRef *requirementRef) 156{ 157 BEGIN_CSAPI 158 159 checkFlags(flags); 160 const Requirement *req = 161 SecStaticCode::requiredStatic(staticCodeRef)->designatedRequirement(); 162 CodeSigning::Required(requirementRef) = (new SecRequirement(req))->handle(); 163 164 END_CSAPI 165} 166 167 168// 169// Fetch a particular internal requirement, if present 170// 171OSStatus SecCodeCopyInternalRequirement(SecStaticCodeRef staticCodeRef, SecRequirementType type, 172 SecCSFlags flags, SecRequirementRef *requirementRef) 173{ 174 BEGIN_CSAPI 175 176 checkFlags(flags); 177 const Requirement *req = 178 SecStaticCode::requiredStatic(staticCodeRef)->internalRequirement(type); 179 CodeSigning::Required(requirementRef) = req ? (new SecRequirement(req))->handle() : NULL; 180 181 END_CSAPI 182} 183 184 185// 186// Record for future use a detached code signature. 187// 188OSStatus SecCodeSetDetachedSignature(SecStaticCodeRef codeRef, CFDataRef signature, 189 SecCSFlags flags) 190{ 191 BEGIN_CSAPI 192 193 checkFlags(flags); 194 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(codeRef); 195 196 code->detachedSignature(signature); // ... and pass it to the code 197 code->resetValidity(); 198 199 END_CSAPI 200} 201 202 203// 204// Attach a code signature to a kernel memory mapping for page-in validation. 205// 206OSStatus SecCodeMapMemory(SecStaticCodeRef codeRef, SecCSFlags flags) 207{ 208 BEGIN_CSAPI 209 210 checkFlags(flags); 211 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(codeRef); 212 if (const CodeDirectory *cd = code->codeDirectory(false)) { 213 fsignatures args = { code->diskRep()->signingBase(), (void *)cd, cd->length() }; 214 UnixError::check(::fcntl(code->diskRep()->fd(), F_ADDSIGS, &args)); 215 } else 216 MacOSError::throwMe(errSecCSUnsigned); 217 218 END_CSAPI 219} 220 221 222// 223// Attach a callback block to a code object 224// 225OSStatus SecStaticCodeSetCallback(SecStaticCodeRef codeRef, SecCSFlags flags, SecCodeCallback *old, SecCodeCallback monitor) 226{ 227 BEGIN_CSAPI 228 229 checkFlags(flags); 230 SecStaticCode *code = SecStaticCode::requiredStatic(codeRef); 231 if (old) 232 *old = code->monitor(); 233 code->setMonitor(monitor); 234 235 END_CSAPI 236} 237 238 239OSStatus SecStaticCodeSetValidationConditions(SecStaticCodeRef codeRef, CFDictionaryRef conditions) 240{ 241 BEGIN_CSAPI 242 243 checkFlags(0); 244 SecStaticCode *code = SecStaticCode::requiredStatic(codeRef); 245 code->setValidationModifiers(conditions); 246 247 END_CSAPI 248} 249