/* * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ // // SecCode - API frame for SecCode objects. // // Note that some SecCode* functions take SecStaticCodeRef arguments in order to // accept either static or dynamic code references, operating on the respective // StaticCode. Those functions are in SecStaticCode.cpp, not here, despite their name. // #include "cs.h" #include "Code.h" #include "cskernel.h" #include using namespace CodeSigning; // // CFError user info keys // const CFStringRef kSecCFErrorArchitecture = CFSTR("SecCSArchitecture"); const CFStringRef kSecCFErrorPattern = CFSTR("SecCSPattern"); const CFStringRef kSecCFErrorResourceSeal = CFSTR("SecCSResourceSeal"); const CFStringRef kSecCFErrorResourceAdded = CFSTR("SecCSResourceAdded"); const CFStringRef kSecCFErrorResourceAltered = CFSTR("SecCSResourceAltered"); const CFStringRef kSecCFErrorResourceMissing = CFSTR("SecCSResourceMissing"); const CFStringRef kSecCFErrorInfoPlist = CFSTR("SecCSInfoPlist"); const CFStringRef kSecCFErrorGuestAttributes = CFSTR("SecCSGuestAttributes"); const CFStringRef kSecCFErrorRequirementSyntax = CFSTR("SecRequirementSyntax"); const CFStringRef kSecCFErrorPath = CFSTR("SecComponentPath"); // // CF-standard type code functions // CFTypeID SecCodeGetTypeID(void) { BEGIN_CSAPI return gCFObjects().Code.typeID; END_CSAPI1(_kCFRuntimeNotATypeID) } // // Get a reference to the calling code. // OSStatus SecCodeCopySelf(SecCSFlags flags, SecCodeRef *selfRef) { BEGIN_CSAPI checkFlags(flags); CFRef attributes = makeCFMutableDictionary(1, kSecGuestAttributePid, CFTempNumber(getpid()).get()); CodeSigning::Required(selfRef) = SecCode::autoLocateGuest(attributes, flags)->handle(false); END_CSAPI } // // Get the dynamic status of a code. // OSStatus SecCodeGetStatus(SecCodeRef codeRef, SecCSFlags flags, SecCodeStatus *status) { BEGIN_CSAPI checkFlags(flags); CodeSigning::Required(status) = SecCode::required(codeRef)->status(); END_CSAPI } // // Change the dynamic status of a code // OSStatus SecCodeSetStatus(SecCodeRef codeRef, SecCodeStatusOperation operation, CFDictionaryRef arguments, SecCSFlags flags) { BEGIN_CSAPI checkFlags(flags); SecCode::required(codeRef)->status(operation, arguments); END_CSAPI } // // Get the StaticCode for an Code // OSStatus SecCodeCopyStaticCode(SecCodeRef codeRef, SecCSFlags flags, SecStaticCodeRef *staticCodeRef) { BEGIN_CSAPI checkFlags(flags, kSecCSUseAllArchitectures); SecPointer staticCode = SecCode::required(codeRef)->staticCode(); if (flags & kSecCSUseAllArchitectures) if (Universal* macho = staticCode->diskRep()->mainExecutableImage()) // Mach-O main executable if (macho->narrowed()) { // create a new StaticCode comprising the whole fat file RefPointer rep = DiskRep::bestGuess(staticCode->diskRep()->mainExecutablePath()); staticCode = new SecStaticCode(rep); } CodeSigning::Required(staticCodeRef) = staticCode ? staticCode->handle() : NULL; END_CSAPI } // // Get the host for an Code // OSStatus SecCodeCopyHost(SecCodeRef guestRef, SecCSFlags flags, SecCodeRef *hostRef) { BEGIN_CSAPI checkFlags(flags); SecPointer host = SecCode::required(guestRef)->host(); CodeSigning::Required(hostRef) = host ? host->handle() : NULL; END_CSAPI } // // Find a guest by attribute(s) // const CFStringRef kSecGuestAttributeCanonical = CFSTR("canonical"); const CFStringRef kSecGuestAttributeHash = CFSTR("codedirectory-hash"); const CFStringRef kSecGuestAttributeMachPort = CFSTR("mach-port"); const CFStringRef kSecGuestAttributePid = CFSTR("pid"); const CFStringRef kSecGuestAttributeDynamicCode = CFSTR("dynamicCode"); const CFStringRef kSecGuestAttributeDynamicCodeInfoPlist = CFSTR("dynamicCodeInfoPlist"); const CFStringRef kSecGuestAttributeArchitecture = CFSTR("architecture"); const CFStringRef kSecGuestAttributeSubarchitecture = CFSTR("subarchitecture"); OSStatus SecCodeCopyGuestWithAttributes(SecCodeRef hostRef, CFDictionaryRef attributes, SecCSFlags flags, SecCodeRef *guestRef) { BEGIN_CSAPI checkFlags(flags); if (hostRef) { if (SecCode *guest = SecCode::required(hostRef)->locateGuest(attributes)) CodeSigning::Required(guestRef) = guest->handle(false); else return errSecCSNoSuchCode; } else CodeSigning::Required(guestRef) = SecCode::autoLocateGuest(attributes, flags)->handle(false); END_CSAPI } // // Shorthand for getting the SecCodeRef for a UNIX process // OSStatus SecCodeCreateWithPID(pid_t pid, SecCSFlags flags, SecCodeRef *processRef) { BEGIN_CSAPI checkFlags(flags); if (SecCode *guest = KernelCode::active()->locateGuest(CFTemp("{%O=%d}", kSecGuestAttributePid, pid))) CodeSigning::Required(processRef) = guest->handle(false); else return errSecCSNoSuchCode; END_CSAPI } // // Check validity of an Code // OSStatus SecCodeCheckValidity(SecCodeRef codeRef, SecCSFlags flags, SecRequirementRef requirementRef) { return SecCodeCheckValidityWithErrors(codeRef, flags, requirementRef, NULL); } OSStatus SecCodeCheckValidityWithErrors(SecCodeRef codeRef, SecCSFlags flags, SecRequirementRef requirementRef, CFErrorRef *errors) { BEGIN_CSAPI checkFlags(flags, kSecCSConsiderExpiration | kSecCSEnforceRevocationChecks); SecPointer code = SecCode::required(codeRef); code->checkValidity(flags); if (const SecRequirement *req = SecRequirement::optional(requirementRef)) code->staticCode()->validateRequirement(req->requirement(), errSecCSReqFailed); END_CSAPI_ERRORS } // // Collect suitably laundered information about the code signature of a SecStaticCode // and return it as a CFDictionary. // // This API contracts to return a few pieces of information even for unsigned // code. This means that a SecStaticCodeRef is usable as a basic indentifier // (i.e. handle) for any code out there. // const CFStringRef kSecCodeInfoCertificates = CFSTR("certificates"); const CFStringRef kSecCodeInfoChangedFiles = CFSTR("changed-files"); const CFStringRef kSecCodeInfoCMS = CFSTR("cms"); const CFStringRef kSecCodeInfoDesignatedRequirement = CFSTR("designated-requirement"); const CFStringRef kSecCodeInfoEntitlements = CFSTR("entitlements"); const CFStringRef kSecCodeInfoEntitlementsDict = CFSTR("entitlements-dict"); const CFStringRef kSecCodeInfoFlags = CFSTR("flags"); const CFStringRef kSecCodeInfoFormat = CFSTR("format"); const CFStringRef kSecCodeInfoDigestAlgorithm = CFSTR("digest-algorithm"); const CFStringRef kSecCodeInfoIdentifier = CFSTR("identifier"); const CFStringRef kSecCodeInfoImplicitDesignatedRequirement = CFSTR("implicit-requirement"); const CFStringRef kSecCodeInfoMainExecutable = CFSTR("main-executable"); const CFStringRef kSecCodeInfoPList = CFSTR("info-plist"); const CFStringRef kSecCodeInfoRequirements = CFSTR("requirements"); const CFStringRef kSecCodeInfoRequirementData = CFSTR("requirement-data"); const CFStringRef kSecCodeInfoSource = CFSTR("source"); const CFStringRef kSecCodeInfoStatus = CFSTR("status"); const CFStringRef kSecCodeInfoTeamIdentifier = CFSTR("teamid"); const CFStringRef kSecCodeInfoTime = CFSTR("signing-time"); const CFStringRef kSecCodeInfoTimestamp = CFSTR("signing-timestamp"); const CFStringRef kSecCodeInfoTrust = CFSTR("trust"); const CFStringRef kSecCodeInfoUnique = CFSTR("unique"); const CFStringRef kSecCodeInfoCodeDirectory = CFSTR("CodeDirectory"); const CFStringRef kSecCodeInfoCodeOffset = CFSTR("CodeOffset"); const CFStringRef kSecCodeInfoResourceDirectory = CFSTR("ResourceDirectory"); OSStatus SecCodeCopySigningInformation(SecStaticCodeRef codeRef, SecCSFlags flags, CFDictionaryRef *infoRef) { BEGIN_CSAPI checkFlags(flags, kSecCSInternalInformation | kSecCSSigningInformation | kSecCSRequirementInformation | kSecCSDynamicInformation | kSecCSContentInformation); SecPointer code = SecStaticCode::requiredStatic(codeRef); CFRef info = code->signingInformation(flags); if (flags & kSecCSDynamicInformation) if (SecPointer dcode = SecStaticCode::optionalDynamic(codeRef)) info.take(cfmake("{+%O,%O=%u}", info.get(), kSecCodeInfoStatus, dcode->status())); CodeSigning::Required(infoRef) = info.yield(); END_CSAPI }