2 * Copyright (c) 2006-2007,2011-2014 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 // SecStaticCode - API frame for SecStaticCode objects
28 #include "StaticCode.h"
29 #include <security_utilities/cfmunge.h>
33 using namespace CodeSigning
;
37 // CF-standard type code function
39 CFTypeID
SecStaticCodeGetTypeID(void)
42 return gCFObjects().StaticCode
.typeID
;
43 END_CSAPI1(_kCFRuntimeNotATypeID
)
48 // Create an StaticCode directly from disk path.
50 OSStatus
SecStaticCodeCreateWithPath(CFURLRef path
, SecCSFlags flags
, SecStaticCodeRef
*staticCodeRef
)
55 CodeSigning::Required(staticCodeRef
) = (new SecStaticCode(DiskRep::bestGuess(cfString(path
).c_str())))->handle();
60 const CFStringRef kSecCodeAttributeArchitecture
= CFSTR("architecture");
61 const CFStringRef kSecCodeAttributeSubarchitecture
=CFSTR("subarchitecture");
62 const CFStringRef kSecCodeAttributeBundleVersion
= CFSTR("bundleversion");
63 const CFStringRef kSecCodeAttributeUniversalFileOffset
= CFSTR("UniversalFileOffset");
65 OSStatus
SecStaticCodeCreateWithPathAndAttributes(CFURLRef path
, SecCSFlags flags
, CFDictionaryRef attributes
,
66 SecStaticCodeRef
*staticCodeRef
)
72 std::string version
; // holds memory placed into ctx
75 int archNumber
, subarchNumber
, offset
;
76 if (cfscan(attributes
, "{%O=%d}", kSecCodeAttributeUniversalFileOffset
, &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();
89 CodeSigning::Required(staticCodeRef
) = (new SecStaticCode(DiskRep::bestGuess(cfString(path
).c_str(), &ctx
)))->handle();
96 // Check static validity of a StaticCode
98 OSStatus
SecStaticCodeCheckValidity(SecStaticCodeRef staticCodeRef
, SecCSFlags flags
,
99 SecRequirementRef requirementRef
)
101 return SecStaticCodeCheckValidityWithErrors(staticCodeRef
, flags
, requirementRef
, NULL
);
104 OSStatus
SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef
, SecCSFlags flags
,
105 SecRequirementRef requirementRef
, CFErrorRef
*errors
)
111 | kSecCSCheckAllArchitectures
112 | kSecCSDoNotValidateExecutable
113 | kSecCSDoNotValidateResources
114 | kSecCSConsiderExpiration
115 | kSecCSEnforceRevocationChecks
116 | kSecCSNoNetworkAccess
117 | kSecCSCheckNestedCode
118 | kSecCSStrictValidate
119 | kSecCSCheckGatekeeperArchitectures
123 flags
|= kSecCSFullReport
; // internal-use flag
125 SecPointer
<SecStaticCode
> code
= SecStaticCode::requiredStatic(staticCodeRef
);
126 code
->setValidationFlags(flags
);
127 const SecRequirement
*req
= SecRequirement::optional(requirementRef
);
128 DTRACK(CODESIGN_EVAL_STATIC
, code
, (char*)code
->mainExecutablePath().c_str());
129 code
->staticValidate(flags
, req
);
136 // ====================================================================================
138 // The following API functions are called SecCode* but accept both SecCodeRef and
139 // SecStaticCodeRef arguments, operating on the implied SecStaticCodeRef as appropriate.
140 // Hence they're here, rather than in SecCode.cpp.
145 // Retrieve location information for an StaticCode.
147 OSStatus
SecCodeCopyPath(SecStaticCodeRef staticCodeRef
, SecCSFlags flags
, CFURLRef
*path
)
152 SecPointer
<SecStaticCode
> staticCode
= SecStaticCode::requiredStatic(staticCodeRef
);
153 CodeSigning::Required(path
) = staticCode
->copyCanonicalPath();
160 // Fetch or make up a designated requirement
162 OSStatus
SecCodeCopyDesignatedRequirement(SecStaticCodeRef staticCodeRef
, SecCSFlags flags
,
163 SecRequirementRef
*requirementRef
)
168 const Requirement
*req
=
169 SecStaticCode::requiredStatic(staticCodeRef
)->designatedRequirement();
170 CodeSigning::Required(requirementRef
) = (new SecRequirement(req
))->handle();
177 // Fetch a particular internal requirement, if present
179 OSStatus
SecCodeCopyInternalRequirement(SecStaticCodeRef staticCodeRef
, SecRequirementType type
,
180 SecCSFlags flags
, SecRequirementRef
*requirementRef
)
185 const Requirement
*req
=
186 SecStaticCode::requiredStatic(staticCodeRef
)->internalRequirement(type
);
187 CodeSigning::Required(requirementRef
) = req
? (new SecRequirement(req
))->handle() : NULL
;
194 // Record for future use a detached code signature.
196 OSStatus
SecCodeSetDetachedSignature(SecStaticCodeRef codeRef
, CFDataRef signature
,
202 SecPointer
<SecStaticCode
> code
= SecStaticCode::requiredStatic(codeRef
);
204 code
->detachedSignature(signature
); // ... and pass it to the code
205 code
->resetValidity();
212 // Attach a code signature to a kernel memory mapping for page-in validation.
214 OSStatus
SecCodeMapMemory(SecStaticCodeRef codeRef
, SecCSFlags flags
)
219 SecPointer
<SecStaticCode
> code
= SecStaticCode::requiredStatic(codeRef
);
220 if (const CodeDirectory
*cd
= code
->codeDirectory(false)) {
221 fsignatures args
= { code
->diskRep()->signingBase(), (void *)cd
, cd
->length() };
222 UnixError::check(::fcntl(code
->diskRep()->fd(), F_ADDSIGS
, &args
));
224 MacOSError::throwMe(errSecCSUnsigned
);
231 // Attach a callback block to a code object
233 OSStatus
SecStaticCodeSetCallback(SecStaticCodeRef codeRef
, SecCSFlags flags
, SecCodeCallback
*old
, SecCodeCallback monitor
)
238 SecStaticCode
*code
= SecStaticCode::requiredStatic(codeRef
);
240 *old
= code
->monitor();
241 code
->setMonitor(monitor
);
247 OSStatus
SecStaticCodeSetValidationConditions(SecStaticCodeRef codeRef
, CFDictionaryRef conditions
)
252 SecStaticCode
*code
= SecStaticCode::requiredStatic(codeRef
);
253 code
->setValidationModifiers(conditions
);
260 // Set cancellation flag on a static code object.
262 OSStatus
SecStaticCodeCancelValidation(SecStaticCodeRef codeRef
, SecCSFlags flags
)
267 SecStaticCode
*code
= SecStaticCode::requiredStatic(codeRef
);
268 code
->cancelValidation();