]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/lib/SecStaticCode.cpp
Security-57337.60.2.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / SecStaticCode.cpp
1 /*
2 * Copyright (c) 2006-2007,2011-2015 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 <security_utilities/logging.h>
31 #include <fcntl.h>
32 #include <dirent.h>
33
34 using namespace CodeSigning;
35
36
37 //
38 // CF-standard type code function
39 //
40 CFTypeID SecStaticCodeGetTypeID(void)
41 {
42 BEGIN_CSAPI
43 return gCFObjects().StaticCode.typeID;
44 END_CSAPI1(_kCFRuntimeNotATypeID)
45 }
46
47
48 //
49 // Create an StaticCode directly from disk path.
50 //
51 OSStatus SecStaticCodeCreateWithPath(CFURLRef path, SecCSFlags flags, SecStaticCodeRef *staticCodeRef)
52 {
53 BEGIN_CSAPI
54
55 checkFlags(flags);
56 CodeSigning::Required(staticCodeRef) = (new SecStaticCode(DiskRep::bestGuess(cfString(path).c_str())))->handle();
57
58 END_CSAPI
59 }
60
61 const CFStringRef kSecCodeAttributeArchitecture = CFSTR("architecture");
62 const CFStringRef kSecCodeAttributeSubarchitecture =CFSTR("subarchitecture");
63 const CFStringRef kSecCodeAttributeBundleVersion = CFSTR("bundleversion");
64 const CFStringRef kSecCodeAttributeUniversalFileOffset = CFSTR("UniversalFileOffset");
65
66 OSStatus SecStaticCodeCreateWithPathAndAttributes(CFURLRef path, SecCSFlags flags, CFDictionaryRef attributes,
67 SecStaticCodeRef *staticCodeRef)
68 {
69 BEGIN_CSAPI
70
71 checkFlags(flags);
72 DiskRep::Context ctx;
73 std::string version; // holds memory placed into ctx
74 if (attributes) {
75 std::string archName;
76 int archNumber, subarchNumber, offset;
77 if (cfscan(attributes, "{%O=%d}", kSecCodeAttributeUniversalFileOffset, &offset)) {
78 ctx.offset = offset;
79 } else if (cfscan(attributes, "{%O=%s}", kSecCodeAttributeArchitecture, &archName)) {
80 ctx.arch = Architecture(archName.c_str());
81 } else if (cfscan(attributes, "{%O=%d,%O=%d}",
82 kSecCodeAttributeArchitecture, &archNumber, kSecCodeAttributeSubarchitecture, &subarchNumber))
83 ctx.arch = Architecture(archNumber, subarchNumber);
84 else if (cfscan(attributes, "{%O=%d}", kSecCodeAttributeArchitecture, &archNumber))
85 ctx.arch = Architecture(archNumber);
86 if (cfscan(attributes, "{%O=%s}", kSecCodeAttributeBundleVersion, &version))
87 ctx.version = version.c_str();
88 }
89
90 CodeSigning::Required(staticCodeRef) = (new SecStaticCode(DiskRep::bestGuess(cfString(path).c_str(), &ctx)))->handle();
91
92 END_CSAPI
93 }
94
95
96 //
97 // Check static validity of a StaticCode
98 //
99 OSStatus SecStaticCodeCheckValidity(SecStaticCodeRef staticCodeRef, SecCSFlags flags,
100 SecRequirementRef requirementRef)
101 {
102 return SecStaticCodeCheckValidityWithErrors(staticCodeRef, flags, requirementRef, NULL);
103 }
104
105 OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, SecCSFlags flags,
106 SecRequirementRef requirementRef, CFErrorRef *errors)
107 {
108 #if !SECTRUST_OSX
109 BEGIN_CSAPI
110
111 checkFlags(flags,
112 kSecCSReportProgress
113 | kSecCSCheckAllArchitectures
114 | kSecCSDoNotValidateExecutable
115 | kSecCSDoNotValidateResources
116 | kSecCSConsiderExpiration
117 | kSecCSEnforceRevocationChecks
118 | kSecCSNoNetworkAccess
119 | kSecCSCheckNestedCode
120 | kSecCSStrictValidate
121 | kSecCSCheckGatekeeperArchitectures
122 | kSecCSRestrictSymlinks
123 | kSecCSRestrictToAppLike
124 );
125
126 if (errors)
127 flags |= kSecCSFullReport; // internal-use flag
128
129 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(staticCodeRef);
130 code->setValidationFlags(flags);
131 const SecRequirement *req = SecRequirement::optional(requirementRef);
132 DTRACK(CODESIGN_EVAL_STATIC, code, (char*)code->mainExecutablePath().c_str());
133 code->staticValidate(flags, req);
134
135 END_CSAPI_ERRORS
136 #else
137 #warning resolve before enabling SECTRUST_OSX: <rdar://21328880>
138 OSStatus result = errSecSuccess;
139 const char *func = "SecStaticCodeCheckValidity";
140 CFErrorRef localErrors = NULL;
141 if (!errors) { errors = &localErrors; }
142 try {
143 checkFlags(flags,
144 kSecCSReportProgress
145 | kSecCSCheckAllArchitectures
146 | kSecCSDoNotValidateExecutable
147 | kSecCSDoNotValidateResources
148 | kSecCSConsiderExpiration
149 | kSecCSEnforceRevocationChecks
150 | kSecCSNoNetworkAccess
151 | kSecCSCheckNestedCode
152 | kSecCSStrictValidate
153 | kSecCSCheckGatekeeperArchitectures
154 );
155
156 if (errors)
157 flags |= kSecCSFullReport; // internal-use flag
158
159 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(staticCodeRef);
160 code->setValidationFlags(flags);
161 const SecRequirement *req = SecRequirement::optional(requirementRef);
162 DTRACK(CODESIGN_EVAL_STATIC, code, (char*)code->mainExecutablePath().c_str());
163 code->staticValidate(flags, req);
164 }
165 catch (...) {
166 // the actual error being thrown is not being caught by any of the
167 // type-specific blocks contained in the END_CSAPI_ERRORS macro,
168 // so we only have the catch-all block here for now.
169 result = errSecCSInternalError;
170 }
171
172 if (errors && *errors) {
173 CFShow(errors);
174 CFRelease(errors);
175 *errors = NULL;
176 }
177 if (result == errSecCSInternalError) {
178 #if !NDEBUG
179 Security::Syslog::error("WARNING: %s ignored error %d", func, (int)result);
180 #endif
181 result = errSecSuccess;
182 }
183 return result;
184
185 #endif
186 }
187
188
189 //
190 // ====================================================================================
191 //
192 // The following API functions are called SecCode* but accept both SecCodeRef and
193 // SecStaticCodeRef arguments, operating on the implied SecStaticCodeRef as appropriate.
194 // Hence they're here, rather than in SecCode.cpp.
195 //
196
197
198 //
199 // Retrieve location information for an StaticCode.
200 //
201 OSStatus SecCodeCopyPath(SecStaticCodeRef staticCodeRef, SecCSFlags flags, CFURLRef *path)
202 {
203 BEGIN_CSAPI
204
205 checkFlags(flags);
206 SecPointer<SecStaticCode> staticCode = SecStaticCode::requiredStatic(staticCodeRef);
207 CodeSigning::Required(path) = staticCode->copyCanonicalPath();
208
209 END_CSAPI
210 }
211
212
213 //
214 // Fetch or make up a designated requirement
215 //
216 OSStatus SecCodeCopyDesignatedRequirement(SecStaticCodeRef staticCodeRef, SecCSFlags flags,
217 SecRequirementRef *requirementRef)
218 {
219 BEGIN_CSAPI
220
221 checkFlags(flags);
222 const Requirement *req =
223 SecStaticCode::requiredStatic(staticCodeRef)->designatedRequirement();
224 CodeSigning::Required(requirementRef) = (new SecRequirement(req))->handle();
225
226 END_CSAPI
227 }
228
229
230 //
231 // Fetch a particular internal requirement, if present
232 //
233 OSStatus SecCodeCopyInternalRequirement(SecStaticCodeRef staticCodeRef, SecRequirementType type,
234 SecCSFlags flags, SecRequirementRef *requirementRef)
235 {
236 BEGIN_CSAPI
237
238 checkFlags(flags);
239 const Requirement *req =
240 SecStaticCode::requiredStatic(staticCodeRef)->internalRequirement(type);
241 CodeSigning::Required(requirementRef) = req ? (new SecRequirement(req))->handle() : NULL;
242
243 END_CSAPI
244 }
245
246
247 //
248 // Record for future use a detached code signature.
249 //
250 OSStatus SecCodeSetDetachedSignature(SecStaticCodeRef codeRef, CFDataRef signature,
251 SecCSFlags flags)
252 {
253 BEGIN_CSAPI
254
255 checkFlags(flags);
256 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(codeRef);
257
258 code->detachedSignature(signature); // ... and pass it to the code
259 code->resetValidity();
260
261 END_CSAPI
262 }
263
264
265 //
266 // Attach a code signature to a kernel memory mapping for page-in validation.
267 //
268 OSStatus SecCodeMapMemory(SecStaticCodeRef codeRef, SecCSFlags flags)
269 {
270 BEGIN_CSAPI
271
272 checkFlags(flags);
273 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(codeRef);
274 if (const CodeDirectory *cd = code->codeDirectory(false)) {
275 fsignatures args = { code->diskRep()->signingBase(), (void *)cd, cd->length() };
276 UnixError::check(::fcntl(code->diskRep()->fd(), F_ADDSIGS, &args));
277 } else
278 MacOSError::throwMe(errSecCSUnsigned);
279
280 END_CSAPI
281 }
282
283
284 //
285 // Attach a callback block to a code object
286 //
287 OSStatus SecStaticCodeSetCallback(SecStaticCodeRef codeRef, SecCSFlags flags, SecCodeCallback *old, SecCodeCallback monitor)
288 {
289 BEGIN_CSAPI
290
291 checkFlags(flags);
292 SecStaticCode *code = SecStaticCode::requiredStatic(codeRef);
293 if (old)
294 *old = code->monitor();
295 code->setMonitor(monitor);
296
297 END_CSAPI
298 }
299
300
301 OSStatus SecStaticCodeSetValidationConditions(SecStaticCodeRef codeRef, CFDictionaryRef conditions)
302 {
303 BEGIN_CSAPI
304
305 checkFlags(0);
306 SecStaticCode *code = SecStaticCode::requiredStatic(codeRef);
307 code->setValidationModifiers(conditions);
308
309 END_CSAPI
310 }
311
312
313 //
314 // Set cancellation flag on a static code object.
315 //
316 OSStatus SecStaticCodeCancelValidation(SecStaticCodeRef codeRef, SecCSFlags flags)
317 {
318 BEGIN_CSAPI
319
320 checkFlags(0);
321 SecStaticCode *code = SecStaticCode::requiredStatic(codeRef);
322 code->cancelValidation();
323
324 END_CSAPI
325 }