2  * Copyright (c) 2006-2015 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   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 
  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. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  25 // SecCode - API frame for SecCode objects. 
  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. 
  34 #include <security_utilities/cfmunge.h> 
  35 #include <security_utilities/logging.h> 
  37 using namespace CodeSigning
; 
  41 // CFError user info keys 
  43 const CFStringRef kSecCFErrorArchitecture 
=             CFSTR("SecCSArchitecture"); 
  44 const CFStringRef kSecCFErrorPattern 
=                  CFSTR("SecCSPattern"); 
  45 const CFStringRef kSecCFErrorResourceSeal 
=             CFSTR("SecCSResourceSeal"); 
  46 const CFStringRef kSecCFErrorResourceAdded 
=            CFSTR("SecCSResourceAdded"); 
  47 const CFStringRef kSecCFErrorResourceAltered 
=  CFSTR("SecCSResourceAltered"); 
  48 const CFStringRef kSecCFErrorResourceMissing 
=  CFSTR("SecCSResourceMissing"); 
  49 const CFStringRef kSecCFErrorResourceSideband 
= CFSTR("SecCSResourceHasSidebandData"); 
  50 const CFStringRef kSecCFErrorInfoPlist 
=                        CFSTR("SecCSInfoPlist"); 
  51 const CFStringRef kSecCFErrorGuestAttributes 
=  CFSTR("SecCSGuestAttributes"); 
  52 const CFStringRef kSecCFErrorRequirementSyntax 
= CFSTR("SecRequirementSyntax"); 
  53 const CFStringRef kSecCFErrorPath 
=                             CFSTR("SecComponentPath"); 
  57 // CF-standard type code functions 
  59 CFTypeID 
SecCodeGetTypeID(void) 
  62         return gCFObjects().Code
.typeID
; 
  63     END_CSAPI1(_kCFRuntimeNotATypeID
) 
  68 // Get a reference to the calling code. 
  70 OSStatus 
SecCodeCopySelf(SecCSFlags flags
, SecCodeRef 
*selfRef
) 
  75         CFRef
<CFMutableDictionaryRef
> attributes 
= makeCFMutableDictionary(1, 
  76                 kSecGuestAttributePid
, CFTempNumber(getpid()).get()); 
  77         CodeSigning::Required(selfRef
) = SecCode::autoLocateGuest(attributes
, flags
)->handle(false); 
  84 // Get the dynamic status of a code. 
  86 OSStatus 
SecCodeGetStatus(SecCodeRef codeRef
, SecCSFlags flags
, SecCodeStatus 
*status
) 
  91         CodeSigning::Required(status
) = SecCode::required(codeRef
)->status(); 
  98 // Change the dynamic status of a code 
 100 OSStatus 
SecCodeSetStatus(SecCodeRef codeRef
, SecCodeStatusOperation operation
, 
 101         CFDictionaryRef arguments
, SecCSFlags flags
) 
 106         SecCode::required(codeRef
)->status(operation
, arguments
); 
 113 // Get the StaticCode for an Code 
 115 OSStatus 
SecCodeCopyStaticCode(SecCodeRef codeRef
, SecCSFlags flags
, SecStaticCodeRef 
*staticCodeRef
) 
 119         checkFlags(flags
, kSecCSUseAllArchitectures
); 
 120         SecPointer
<SecStaticCode
> staticCode 
= SecCode::required(codeRef
)->staticCode(); 
 121         if (flags 
& kSecCSUseAllArchitectures
) 
 122                 if (Universal
* macho 
= staticCode
->diskRep()->mainExecutableImage())    // Mach-O main executable 
 123                         if (macho
->narrowed()) { 
 124                                 // create a new StaticCode comprising the whole fat file 
 125                                 RefPointer
<DiskRep
> rep 
= DiskRep::bestGuess(staticCode
->diskRep()->mainExecutablePath()); 
 126                                 staticCode 
= new SecStaticCode(rep
); 
 128         CodeSigning::Required(staticCodeRef
) = staticCode 
? staticCode
->handle() : NULL
; 
 135 // Get the host for an Code 
 137 OSStatus 
SecCodeCopyHost(SecCodeRef guestRef
, SecCSFlags flags
, SecCodeRef 
*hostRef
) 
 142         SecPointer
<SecCode
> host 
= SecCode::required(guestRef
)->host(); 
 143         CodeSigning::Required(hostRef
) = host 
? host
->handle() : NULL
; 
 150 // Find a guest by attribute(s) 
 152 const CFStringRef kSecGuestAttributeCanonical 
=         CFSTR("canonical"); 
 153 const CFStringRef kSecGuestAttributeHash 
=                      CFSTR("codedirectory-hash"); 
 154 const CFStringRef kSecGuestAttributeMachPort 
=          CFSTR("mach-port"); 
 155 const CFStringRef kSecGuestAttributePid 
=                       CFSTR("pid"); 
 156 const CFStringRef kSecGuestAttributeAudit 
=                     CFSTR("audit"); 
 157 const CFStringRef kSecGuestAttributeDynamicCode 
=       CFSTR("dynamicCode"); 
 158 const CFStringRef kSecGuestAttributeDynamicCodeInfoPlist 
= CFSTR("dynamicCodeInfoPlist"); 
 159 const CFStringRef kSecGuestAttributeArchitecture 
=      CFSTR("architecture"); 
 160 const CFStringRef kSecGuestAttributeSubarchitecture 
= CFSTR("subarchitecture"); 
 163 OSStatus 
SecCodeCopyGuestWithAttributes(SecCodeRef hostRef
, 
 164         CFDictionaryRef attributes
,     SecCSFlags flags
, SecCodeRef 
*guestRef
) 
 170                 if (SecCode 
*guest 
= SecCode::required(hostRef
)->locateGuest(attributes
)) 
 171                         CodeSigning::Required(guestRef
) = guest
->handle(false); 
 173                         return errSecCSNoSuchCode
; 
 175                 CodeSigning::Required(guestRef
) = SecCode::autoLocateGuest(attributes
, flags
)->handle(false); 
 182 // Deprecated since 10.6, DO NOT USE. This can be raced. 
 183 // Use SecCodeCreateWithAuditToken instead. 
 185 OSStatus 
SecCodeCreateWithPID(pid_t pid
, SecCSFlags flags
, SecCodeRef 
*processRef
) 
 190         if (SecCode 
*guest 
= KernelCode::active()->locateGuest(CFTemp
<CFDictionaryRef
>("{%O=%d}", kSecGuestAttributePid
, pid
))) 
 191                 CodeSigning::Required(processRef
) = guest
->handle(false); 
 193                 return errSecCSNoSuchCode
; 
 199 // Shorthand for getting the SecCodeRef for a UNIX process 
 201 OSStatus 
SecCodeCreateWithAuditToken(const audit_token_t 
*audit
, 
 202                                                                          SecCSFlags flags
, SecCodeRef 
*processRef
) 
 207         CFRef
<CFDataRef
> auditData 
= makeCFData(audit
, sizeof(audit_token_t
)); 
 208         if (SecCode 
*guest 
= KernelCode::active()->locateGuest(CFTemp
<CFDictionaryRef
>("{%O=%O}", kSecGuestAttributeAudit
, auditData
.get()))) { 
 209                 CodeSigning::Required(processRef
) = guest
->handle(false); 
 211                 return errSecCSNoSuchCode
; 
 216 #endif // TARGET_OS_OSX 
 220 // Check validity of an Code 
 222 OSStatus 
SecCodeCheckValidity(SecCodeRef codeRef
, SecCSFlags flags
, 
 223         SecRequirementRef requirementRef
) 
 225         return SecCodeCheckValidityWithErrors(codeRef
, flags
, requirementRef
, NULL
); 
 228 OSStatus 
SecCodeCheckValidityWithErrors(SecCodeRef codeRef
, SecCSFlags flags
, 
 229         SecRequirementRef requirementRef
, CFErrorRef 
*errors
) 
 234                   kSecCSConsiderExpiration
 
 235                 | kSecCSStrictValidate
 
 236                 | kSecCSStrictValidateStructure
 
 237                 | kSecCSRestrictSidebandData
 
 238                 | kSecCSEnforceRevocationChecks
 
 240         SecPointer
<SecCode
> code 
= SecCode::required(codeRef
); 
 241         code
->checkValidity(flags
); 
 242         if (const SecRequirement 
*req 
= SecRequirement::optional(requirementRef
)) 
 243                 code
->staticCode()->validateRequirement(req
->requirement(), errSecCSReqFailed
); 
 250 // Collect suitably laundered information about the code signature of a SecStaticCode 
 251 // and return it as a CFDictionary. 
 253 // This API contracts to return a few pieces of information even for unsigned 
 254 // code. This means that a SecStaticCodeRef is usable as a basic indentifier 
 255 // (i.e. handle) for any code out there. 
 257 const CFStringRef kSecCodeInfoCertificates 
=    CFSTR("certificates"); 
 258 const CFStringRef kSecCodeInfoChangedFiles 
=    CFSTR("changed-files"); 
 259 const CFStringRef kSecCodeInfoCMS 
=                             CFSTR("cms"); 
 260 const CFStringRef kSecCodeInfoDesignatedRequirement 
= CFSTR("designated-requirement"); 
 261 const CFStringRef kSecCodeInfoEntitlements 
=    CFSTR("entitlements"); 
 262 const CFStringRef kSecCodeInfoEntitlementsDict 
=        CFSTR("entitlements-dict"); 
 263 const CFStringRef kSecCodeInfoFlags 
=                   CFSTR("flags"); 
 264 const CFStringRef kSecCodeInfoFormat 
=                  CFSTR("format"); 
 265 const CFStringRef kSecCodeInfoDigestAlgorithm 
= CFSTR("digest-algorithm"); 
 266 const CFStringRef kSecCodeInfoDigestAlgorithms 
= CFSTR("digest-algorithms"); 
 267 const CFStringRef kSecCodeInfoPlatformIdentifier 
= CFSTR("platform-identifier"); 
 268 const CFStringRef kSecCodeInfoIdentifier 
=              CFSTR("identifier"); 
 269 const CFStringRef kSecCodeInfoImplicitDesignatedRequirement 
= CFSTR("implicit-requirement"); 
 270 const CFStringRef kSecCodeInfoMainExecutable 
=  CFSTR("main-executable"); 
 271 const CFStringRef kSecCodeInfoPList 
=                   CFSTR("info-plist"); 
 272 const CFStringRef kSecCodeInfoRequirements 
=    CFSTR("requirements"); 
 273 const CFStringRef kSecCodeInfoRequirementData 
= CFSTR("requirement-data"); 
 274 const CFStringRef kSecCodeInfoSource 
=                  CFSTR("source"); 
 275 const CFStringRef kSecCodeInfoStatus 
=                  CFSTR("status"); 
 276 const CFStringRef kSecCodeInfoTeamIdentifier 
=  CFSTR("teamid"); 
 277 const CFStringRef kSecCodeInfoTime 
=                    CFSTR("signing-time"); 
 278 const CFStringRef kSecCodeInfoTimestamp 
=               CFSTR("signing-timestamp"); 
 279 const CFStringRef kSecCodeInfoTrust 
=                   CFSTR("trust"); 
 280 const CFStringRef kSecCodeInfoUnique 
=                  CFSTR("unique"); 
 281 const CFStringRef kSecCodeInfoCdHashes 
=        CFSTR("cdhashes"); 
 282 const CFStringRef kSecCodeInfoCdHashesFull 
=    CFSTR("cdhashes-full"); 
 283 const CFStringRef kSecCodeInfoRuntimeVersion 
=  CFSTR("runtime-version"); 
 285 const CFStringRef kSecCodeInfoCodeDirectory 
=   CFSTR("CodeDirectory"); 
 286 const CFStringRef kSecCodeInfoCodeOffset 
=              CFSTR("CodeOffset"); 
 287 const CFStringRef kSecCodeInfoDiskRepInfo 
=     CFSTR("DiskRepInfo"); 
 288 const CFStringRef kSecCodeInfoResourceDirectory 
= CFSTR("ResourceDirectory"); 
 289 const CFStringRef kSecCodeInfoNotarizationDate 
= CFSTR("NotarizationDate"); 
 290 const CFStringRef kSecCodeInfoCMSDigestHashType 
= CFSTR("CMSDigestHashType"); 
 291 const CFStringRef kSecCodeInfoCMSDigest 
=        CFSTR("CMSDigest"); 
 293 /* DiskInfoRepInfo types */ 
 294 const CFStringRef kSecCodeInfoDiskRepVersionPlatform 
=          CFSTR("VersionPlatform"); 
 295 const CFStringRef kSecCodeInfoDiskRepVersionMin 
=               CFSTR("VersionMin"); 
 296 const CFStringRef kSecCodeInfoDiskRepVersionSDK 
=               CFSTR("VersionSDK"); 
 297 const CFStringRef kSecCodeInfoDiskRepNoLibraryValidation 
=      CFSTR("NoLibraryValidation"); 
 300 OSStatus 
SecCodeCopySigningInformation(SecStaticCodeRef codeRef
, SecCSFlags flags
, 
 301         CFDictionaryRef 
*infoRef
) 
 306                   kSecCSInternalInformation
 
 307                 | kSecCSSigningInformation
 
 308                 | kSecCSRequirementInformation
 
 309                 | kSecCSDynamicInformation
 
 310                 | kSecCSContentInformation
 
 311         | kSecCSSkipResourceDirectory
 
 312                 | kSecCSCalculateCMSDigest
); 
 314         SecPointer
<SecStaticCode
> code 
= SecStaticCode::requiredStatic(codeRef
); 
 315         CFRef
<CFDictionaryRef
> info 
= code
->signingInformation(flags
); 
 317         if (flags 
& kSecCSDynamicInformation
) 
 318                 if (SecPointer
<SecCode
> dcode 
= SecStaticCode::optionalDynamic(codeRef
)) 
 319                         info
.take(cfmake
<CFDictionaryRef
>("{+%O,%O=%u}", info
.get(), kSecCodeInfoStatus
, dcode
->status())); 
 321         CodeSigning::Required(infoRef
) = info
.yield();