]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/lib/SecStaticCode.cpp
Security-57337.20.44.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 );
124
125 if (errors)
126 flags |= kSecCSFullReport; // internal-use flag
127
128 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(staticCodeRef);
129 code->setValidationFlags(flags);
130 const SecRequirement *req = SecRequirement::optional(requirementRef);
131 DTRACK(CODESIGN_EVAL_STATIC, code, (char*)code->mainExecutablePath().c_str());
132 code->staticValidate(flags, req);
133
134 END_CSAPI_ERRORS
135 #else
136 #warning resolve before enabling SECTRUST_OSX: <rdar://21328880>
137 OSStatus result = errSecSuccess;
138 const char *func = "SecStaticCodeCheckValidity";
139 CFErrorRef localErrors = NULL;
140 if (!errors) { errors = &localErrors; }
141 try {
142 checkFlags(flags,
143 kSecCSReportProgress
144 | kSecCSCheckAllArchitectures
145 | kSecCSDoNotValidateExecutable
146 | kSecCSDoNotValidateResources
147 | kSecCSConsiderExpiration
148 | kSecCSEnforceRevocationChecks
149 | kSecCSNoNetworkAccess
150 | kSecCSCheckNestedCode
151 | kSecCSStrictValidate
152 | kSecCSCheckGatekeeperArchitectures
153 );
154
155 if (errors)
156 flags |= kSecCSFullReport; // internal-use flag
157
158 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(staticCodeRef);
159 code->setValidationFlags(flags);
160 const SecRequirement *req = SecRequirement::optional(requirementRef);
161 DTRACK(CODESIGN_EVAL_STATIC, code, (char*)code->mainExecutablePath().c_str());
162 code->staticValidate(flags, req);
163 }
164 catch (...) {
165 // the actual error being thrown is not being caught by any of the
166 // type-specific blocks contained in the END_CSAPI_ERRORS macro,
167 // so we only have the catch-all block here for now.
168 result = errSecCSInternalError;
169 }
170
171 if (errors && *errors) {
172 CFShow(errors);
173 CFRelease(errors);
174 *errors = NULL;
175 }
176 if (result == errSecCSInternalError) {
177 #if !NDEBUG
178 Security::Syslog::error("WARNING: %s ignored error %d", func, (int)result);
179 #endif
180 result = errSecSuccess;
181 }
182 return result;
183
184 #endif
185 }
186
187
188 //
189 // ====================================================================================
190 //
191 // The following API functions are called SecCode* but accept both SecCodeRef and
192 // SecStaticCodeRef arguments, operating on the implied SecStaticCodeRef as appropriate.
193 // Hence they're here, rather than in SecCode.cpp.
194 //
195
196
197 //
198 // Retrieve location information for an StaticCode.
199 //
200 OSStatus SecCodeCopyPath(SecStaticCodeRef staticCodeRef, SecCSFlags flags, CFURLRef *path)
201 {
202 BEGIN_CSAPI
203
204 checkFlags(flags);
205 SecPointer<SecStaticCode> staticCode = SecStaticCode::requiredStatic(staticCodeRef);
206 CodeSigning::Required(path) = staticCode->copyCanonicalPath();
207
208 END_CSAPI
209 }
210
211
212 //
213 // Fetch or make up a designated requirement
214 //
215 OSStatus SecCodeCopyDesignatedRequirement(SecStaticCodeRef staticCodeRef, SecCSFlags flags,
216 SecRequirementRef *requirementRef)
217 {
218 BEGIN_CSAPI
219
220 checkFlags(flags);
221 const Requirement *req =
222 SecStaticCode::requiredStatic(staticCodeRef)->designatedRequirement();
223 CodeSigning::Required(requirementRef) = (new SecRequirement(req))->handle();
224
225 END_CSAPI
226 }
227
228
229 //
230 // Fetch a particular internal requirement, if present
231 //
232 OSStatus SecCodeCopyInternalRequirement(SecStaticCodeRef staticCodeRef, SecRequirementType type,
233 SecCSFlags flags, SecRequirementRef *requirementRef)
234 {
235 BEGIN_CSAPI
236
237 checkFlags(flags);
238 const Requirement *req =
239 SecStaticCode::requiredStatic(staticCodeRef)->internalRequirement(type);
240 CodeSigning::Required(requirementRef) = req ? (new SecRequirement(req))->handle() : NULL;
241
242 END_CSAPI
243 }
244
245
246 //
247 // Record for future use a detached code signature.
248 //
249 OSStatus SecCodeSetDetachedSignature(SecStaticCodeRef codeRef, CFDataRef signature,
250 SecCSFlags flags)
251 {
252 BEGIN_CSAPI
253
254 checkFlags(flags);
255 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(codeRef);
256
257 code->detachedSignature(signature); // ... and pass it to the code
258 code->resetValidity();
259
260 END_CSAPI
261 }
262
263
264 //
265 // Attach a code signature to a kernel memory mapping for page-in validation.
266 //
267 OSStatus SecCodeMapMemory(SecStaticCodeRef codeRef, SecCSFlags flags)
268 {
269 BEGIN_CSAPI
270
271 checkFlags(flags);
272 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(codeRef);
273 if (const CodeDirectory *cd = code->codeDirectory(false)) {
274 fsignatures args = { code->diskRep()->signingBase(), (void *)cd, cd->length() };
275 UnixError::check(::fcntl(code->diskRep()->fd(), F_ADDSIGS, &args));
276 } else
277 MacOSError::throwMe(errSecCSUnsigned);
278
279 END_CSAPI
280 }
281
282
283 //
284 // Attach a callback block to a code object
285 //
286 OSStatus SecStaticCodeSetCallback(SecStaticCodeRef codeRef, SecCSFlags flags, SecCodeCallback *old, SecCodeCallback monitor)
287 {
288 BEGIN_CSAPI
289
290 checkFlags(flags);
291 SecStaticCode *code = SecStaticCode::requiredStatic(codeRef);
292 if (old)
293 *old = code->monitor();
294 code->setMonitor(monitor);
295
296 END_CSAPI
297 }
298
299
300 OSStatus SecStaticCodeSetValidationConditions(SecStaticCodeRef codeRef, CFDictionaryRef conditions)
301 {
302 BEGIN_CSAPI
303
304 checkFlags(0);
305 SecStaticCode *code = SecStaticCode::requiredStatic(codeRef);
306 code->setValidationModifiers(conditions);
307
308 END_CSAPI
309 }
310
311
312 //
313 // Set cancellation flag on a static code object.
314 //
315 OSStatus SecStaticCodeCancelValidation(SecStaticCodeRef codeRef, SecCSFlags flags)
316 {
317 BEGIN_CSAPI
318
319 checkFlags(0);
320 SecStaticCode *code = SecStaticCode::requiredStatic(codeRef);
321 code->cancelValidation();
322
323 END_CSAPI
324 }