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 kSecCFErrorInfoPlist 
=                        CFSTR("SecCSInfoPlist"); 
  50 const CFStringRef kSecCFErrorGuestAttributes 
=  CFSTR("SecCSGuestAttributes"); 
  51 const CFStringRef kSecCFErrorRequirementSyntax 
= CFSTR("SecRequirementSyntax"); 
  52 const CFStringRef kSecCFErrorPath 
=                             CFSTR("SecComponentPath"); 
  56 // CF-standard type code functions 
  58 CFTypeID 
SecCodeGetTypeID(void) 
  61         return gCFObjects().Code
.typeID
; 
  62     END_CSAPI1(_kCFRuntimeNotATypeID
) 
  67 // Get a reference to the calling code. 
  69 OSStatus 
SecCodeCopySelf(SecCSFlags flags
, SecCodeRef 
*selfRef
) 
  74         CFRef
<CFMutableDictionaryRef
> attributes 
= makeCFMutableDictionary(1, 
  75                 kSecGuestAttributePid
, CFTempNumber(getpid()).get()); 
  76         CodeSigning::Required(selfRef
) = SecCode::autoLocateGuest(attributes
, flags
)->handle(false); 
  83 // Get the dynamic status of a code. 
  85 OSStatus 
SecCodeGetStatus(SecCodeRef codeRef
, SecCSFlags flags
, SecCodeStatus 
*status
) 
  90         CodeSigning::Required(status
) = SecCode::required(codeRef
)->status(); 
  97 // Change the dynamic status of a code 
  99 OSStatus 
SecCodeSetStatus(SecCodeRef codeRef
, SecCodeStatusOperation operation
, 
 100         CFDictionaryRef arguments
, SecCSFlags flags
) 
 105         SecCode::required(codeRef
)->status(operation
, arguments
); 
 112 // Get the StaticCode for an Code 
 114 OSStatus 
SecCodeCopyStaticCode(SecCodeRef codeRef
, SecCSFlags flags
, SecStaticCodeRef 
*staticCodeRef
) 
 118         checkFlags(flags
, kSecCSUseAllArchitectures
); 
 119         SecPointer
<SecStaticCode
> staticCode 
= SecCode::required(codeRef
)->staticCode(); 
 120         if (flags 
& kSecCSUseAllArchitectures
) 
 121                 if (Universal
* macho 
= staticCode
->diskRep()->mainExecutableImage())    // Mach-O main executable 
 122                         if (macho
->narrowed()) { 
 123                                 // create a new StaticCode comprising the whole fat file 
 124                                 RefPointer
<DiskRep
> rep 
= DiskRep::bestGuess(staticCode
->diskRep()->mainExecutablePath()); 
 125                                 staticCode 
= new SecStaticCode(rep
); 
 127         CodeSigning::Required(staticCodeRef
) = staticCode 
? staticCode
->handle() : NULL
; 
 134 // Get the host for an Code 
 136 OSStatus 
SecCodeCopyHost(SecCodeRef guestRef
, SecCSFlags flags
, SecCodeRef 
*hostRef
) 
 141         SecPointer
<SecCode
> host 
= SecCode::required(guestRef
)->host(); 
 142         CodeSigning::Required(hostRef
) = host 
? host
->handle() : NULL
; 
 149 // Find a guest by attribute(s) 
 151 const CFStringRef kSecGuestAttributeCanonical 
=         CFSTR("canonical"); 
 152 const CFStringRef kSecGuestAttributeHash 
=                      CFSTR("codedirectory-hash"); 
 153 const CFStringRef kSecGuestAttributeMachPort 
=          CFSTR("mach-port"); 
 154 const CFStringRef kSecGuestAttributePid 
=                       CFSTR("pid"); 
 155 const CFStringRef kSecGuestAttributeDynamicCode 
=               CFSTR("dynamicCode"); 
 156 const CFStringRef kSecGuestAttributeDynamicCodeInfoPlist 
=               CFSTR("dynamicCodeInfoPlist"); 
 157 const CFStringRef kSecGuestAttributeArchitecture 
=      CFSTR("architecture"); 
 158 const CFStringRef kSecGuestAttributeSubarchitecture 
= CFSTR("subarchitecture"); 
 160 OSStatus 
SecCodeCopyGuestWithAttributes(SecCodeRef hostRef
, 
 161         CFDictionaryRef attributes
,     SecCSFlags flags
, SecCodeRef 
*guestRef
) 
 167                 if (SecCode 
*guest 
= SecCode::required(hostRef
)->locateGuest(attributes
)) 
 168                         CodeSigning::Required(guestRef
) = guest
->handle(false); 
 170                         return errSecCSNoSuchCode
; 
 172                 CodeSigning::Required(guestRef
) = SecCode::autoLocateGuest(attributes
, flags
)->handle(false); 
 179 // Shorthand for getting the SecCodeRef for a UNIX process 
 181 OSStatus 
SecCodeCreateWithPID(pid_t pid
, SecCSFlags flags
, SecCodeRef 
*processRef
) 
 186         if (SecCode 
*guest 
= KernelCode::active()->locateGuest(CFTemp
<CFDictionaryRef
>("{%O=%d}", kSecGuestAttributePid
, pid
))) 
 187                 CodeSigning::Required(processRef
) = guest
->handle(false); 
 189                 return errSecCSNoSuchCode
; 
 196 // Check validity of an Code 
 198 OSStatus 
SecCodeCheckValidity(SecCodeRef codeRef
, SecCSFlags flags
, 
 199         SecRequirementRef requirementRef
) 
 201         return SecCodeCheckValidityWithErrors(codeRef
, flags
, requirementRef
, NULL
); 
 204 OSStatus 
SecCodeCheckValidityWithErrors(SecCodeRef codeRef
, SecCSFlags flags
, 
 205         SecRequirementRef requirementRef
, CFErrorRef 
*errors
) 
 211                   kSecCSConsiderExpiration
 
 212                 | kSecCSStrictValidate
 
 213                 | kSecCSEnforceRevocationChecks
); 
 214         SecPointer
<SecCode
> code 
= SecCode::required(codeRef
); 
 215         code
->checkValidity(flags
); 
 216         if (const SecRequirement 
*req 
= SecRequirement::optional(requirementRef
)) 
 217                 code
->staticCode()->validateRequirement(req
->requirement(), errSecCSReqFailed
); 
 221 #warning resolve before enabling SECTRUST_OSX: <rdar://21328880> 
 222         OSStatus result 
= errSecSuccess
; 
 223         const char *func 
= "SecCodeCheckValidity"; 
 224         CFErrorRef localErrors 
= NULL
; 
 225         if (!errors
) { errors 
= &localErrors
; } 
 228                                 kSecCSConsiderExpiration
 
 229                                 | kSecCSEnforceRevocationChecks
); 
 230                 SecPointer
<SecCode
> code 
= SecCode::required(codeRef
); 
 231                 code
->checkValidity(flags
); 
 232                 if (const SecRequirement 
*req 
= SecRequirement::optional(requirementRef
)) 
 233                         code
->staticCode()->validateRequirement(req
->requirement(), errSecCSReqFailed
); 
 236                 // the actual error being thrown is not being caught by any of the 
 237                 // type-specific blocks contained in the END_CSAPI_ERRORS macro, 
 238                 // so we only have the catch-all block here for now. 
 239                 result 
= errSecCSInternalError
; 
 242         if (errors 
&& *errors
) { 
 247         if (result 
== errSecCSInternalError
) { 
 249                 Security::Syslog::error("WARNING: %s ignored error %d", func
, (int)result
); 
 251                 result 
= errSecSuccess
; 
 259 // Collect suitably laundered information about the code signature of a SecStaticCode 
 260 // and return it as a CFDictionary. 
 262 // This API contracts to return a few pieces of information even for unsigned 
 263 // code. This means that a SecStaticCodeRef is usable as a basic indentifier 
 264 // (i.e. handle) for any code out there. 
 266 const CFStringRef kSecCodeInfoCertificates 
=    CFSTR("certificates"); 
 267 const CFStringRef kSecCodeInfoChangedFiles 
=    CFSTR("changed-files"); 
 268 const CFStringRef kSecCodeInfoCMS 
=                             CFSTR("cms"); 
 269 const CFStringRef kSecCodeInfoDesignatedRequirement 
= CFSTR("designated-requirement"); 
 270 const CFStringRef kSecCodeInfoEntitlements 
=    CFSTR("entitlements"); 
 271 const CFStringRef kSecCodeInfoEntitlementsDict 
=        CFSTR("entitlements-dict"); 
 272 const CFStringRef kSecCodeInfoFlags 
=                   CFSTR("flags"); 
 273 const CFStringRef kSecCodeInfoFormat 
=                  CFSTR("format"); 
 274 const CFStringRef kSecCodeInfoDigestAlgorithm 
= CFSTR("digest-algorithm"); 
 275 const CFStringRef kSecCodeInfoDigestAlgorithms 
= CFSTR("digest-algorithms"); 
 276 const CFStringRef kSecCodeInfoPlatformIdentifier 
= CFSTR("platform-identifier"); 
 277 const CFStringRef kSecCodeInfoIdentifier 
=              CFSTR("identifier"); 
 278 const CFStringRef kSecCodeInfoImplicitDesignatedRequirement 
= CFSTR("implicit-requirement"); 
 279 const CFStringRef kSecCodeInfoMainExecutable 
=  CFSTR("main-executable"); 
 280 const CFStringRef kSecCodeInfoPList 
=                   CFSTR("info-plist"); 
 281 const CFStringRef kSecCodeInfoRequirements 
=    CFSTR("requirements"); 
 282 const CFStringRef kSecCodeInfoRequirementData 
= CFSTR("requirement-data"); 
 283 const CFStringRef kSecCodeInfoSource 
=                  CFSTR("source"); 
 284 const CFStringRef kSecCodeInfoStatus 
=                  CFSTR("status"); 
 285 const CFStringRef kSecCodeInfoTeamIdentifier 
=  CFSTR("teamid"); 
 286 const CFStringRef kSecCodeInfoTime 
=                    CFSTR("signing-time"); 
 287 const CFStringRef kSecCodeInfoTimestamp 
=               CFSTR("signing-timestamp"); 
 288 const CFStringRef kSecCodeInfoTrust 
=                   CFSTR("trust"); 
 289 const CFStringRef kSecCodeInfoUnique 
=                  CFSTR("unique"); 
 290 const CFStringRef kSecCodeInfoCdHashes 
=        CFSTR("cdhashes"); 
 293 const CFStringRef kSecCodeInfoCodeDirectory 
=   CFSTR("CodeDirectory"); 
 294 const CFStringRef kSecCodeInfoCodeOffset 
=              CFSTR("CodeOffset"); 
 295 const CFStringRef kSecCodeInfoResourceDirectory 
= CFSTR("ResourceDirectory"); 
 298 OSStatus 
SecCodeCopySigningInformation(SecStaticCodeRef codeRef
, SecCSFlags flags
, 
 299         CFDictionaryRef 
*infoRef
) 
 304                   kSecCSInternalInformation
 
 305                 | kSecCSSigningInformation
 
 306                 | kSecCSRequirementInformation
 
 307                 | kSecCSDynamicInformation
 
 308                 | kSecCSContentInformation
); 
 310         SecPointer
<SecStaticCode
> code 
= SecStaticCode::requiredStatic(codeRef
); 
 311         CFRef
<CFDictionaryRef
> info 
= code
->signingInformation(flags
); 
 313         if (flags 
& kSecCSDynamicInformation
) 
 314                 if (SecPointer
<SecCode
> dcode 
= SecStaticCode::optionalDynamic(codeRef
)) 
 315                         info
.take(cfmake
<CFDictionaryRef
>("{+%O,%O=%u}", info
.get(), kSecCodeInfoStatus
, dcode
->status())); 
 317         CodeSigning::Required(infoRef
) = info
.yield();