]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_codesigning/lib/SecStaticCode.cpp
Security-58286.240.4.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / SecStaticCode.cpp
CommitLineData
b1ab9ed8 1/*
5c19dc3a
A
2 * Copyright (c) 2006-2007,2011-2015 Apple Inc. All Rights Reserved.
3 *
b1ab9ed8 4 * @APPLE_LICENSE_HEADER_START@
5c19dc3a 5 *
b1ab9ed8
A
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.
5c19dc3a 12 *
b1ab9ed8
A
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.
5c19dc3a 20 *
b1ab9ed8
A
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>
5c19dc3a 30#include <security_utilities/logging.h>
b1ab9ed8
A
31#include <fcntl.h>
32#include <dirent.h>
33
34using namespace CodeSigning;
35
36
37//
38// CF-standard type code function
39//
40CFTypeID 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//
51OSStatus SecStaticCodeCreateWithPath(CFURLRef path, SecCSFlags flags, SecStaticCodeRef *staticCodeRef)
52{
53 BEGIN_CSAPI
5c19dc3a 54
79b9da22
A
55 checkFlags(flags, kSecCSForceOnlineNotarizationCheck);
56 CodeSigning::Required(staticCodeRef) = (new SecStaticCode(DiskRep::bestGuess(cfString(path).c_str()), flags))->handle();
b1ab9ed8
A
57
58 END_CSAPI
59}
60
61const CFStringRef kSecCodeAttributeArchitecture = CFSTR("architecture");
62const CFStringRef kSecCodeAttributeSubarchitecture =CFSTR("subarchitecture");
63const CFStringRef kSecCodeAttributeBundleVersion = CFSTR("bundleversion");
427c49bc 64const CFStringRef kSecCodeAttributeUniversalFileOffset = CFSTR("UniversalFileOffset");
b1ab9ed8
A
65
66OSStatus SecStaticCodeCreateWithPathAndAttributes(CFURLRef path, SecCSFlags flags, CFDictionaryRef attributes,
67 SecStaticCodeRef *staticCodeRef)
68{
69 BEGIN_CSAPI
5c19dc3a 70
79b9da22 71 checkFlags(flags, kSecCSForceOnlineNotarizationCheck);
b1ab9ed8
A
72 DiskRep::Context ctx;
73 std::string version; // holds memory placed into ctx
74 if (attributes) {
75 std::string archName;
427c49bc
A
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)) {
b1ab9ed8
A
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 }
d8f41ccd 89
79b9da22 90 CodeSigning::Required(staticCodeRef) = (new SecStaticCode(DiskRep::bestGuess(cfString(path).c_str(), &ctx), flags))->handle();
b1ab9ed8
A
91
92 END_CSAPI
93}
94
95
96//
97// Check static validity of a StaticCode
98//
b1ab9ed8
A
99OSStatus SecStaticCodeCheckValidity(SecStaticCodeRef staticCodeRef, SecCSFlags flags,
100 SecRequirementRef requirementRef)
101{
102 return SecStaticCodeCheckValidityWithErrors(staticCodeRef, flags, requirementRef, NULL);
103}
104
105OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, SecCSFlags flags,
106 SecRequirementRef requirementRef, CFErrorRef *errors)
107{
108 BEGIN_CSAPI
5c19dc3a 109
b1ab9ed8 110 checkFlags(flags,
d8f41ccd
A
111 kSecCSReportProgress
112 | kSecCSCheckAllArchitectures
b1ab9ed8
A
113 | kSecCSDoNotValidateExecutable
114 | kSecCSDoNotValidateResources
115 | kSecCSConsiderExpiration
fa7225c8 116 | kSecCSEnforceRevocationChecks
d8f41ccd 117 | kSecCSNoNetworkAccess
80e23899 118 | kSecCSCheckNestedCode
d87e1158 119 | kSecCSStrictValidate
fa7225c8 120 | kSecCSRestrictSidebandData
d87e1158 121 | kSecCSCheckGatekeeperArchitectures
5c19dc3a 122 | kSecCSRestrictSymlinks
e3d460c9 123 | kSecCSRestrictToAppLike
866f8763 124 | kSecCSUseSoftwareSigningCert
90dc47c2 125 | kSecCSValidatePEH
7512f6be 126 | kSecCSSingleThreaded
d87e1158 127 );
5c19dc3a 128
d8f41ccd
A
129 if (errors)
130 flags |= kSecCSFullReport; // internal-use flag
b1ab9ed8
A
131
132 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(staticCodeRef);
d8f41ccd 133 code->setValidationFlags(flags);
b1ab9ed8
A
134 const SecRequirement *req = SecRequirement::optional(requirementRef);
135 DTRACK(CODESIGN_EVAL_STATIC, code, (char*)code->mainExecutablePath().c_str());
427c49bc 136 code->staticValidate(flags, req);
b1ab9ed8 137
866f8763
A
138#if TARGET_OS_IPHONE
139 // Everything checked out correctly but we need to make sure that when
140 // we validated the code directory, we trusted the signer. We defer this
141 // until now because the caller may still trust the signer via a
142 // provisioning profile so if we prematurely throw an error when validating
143 // the directory, we potentially skip resource validation even though the
144 // caller will go on to trust the signature
145 // <rdar://problem/6075501> Applications that are validated against a provisioning profile do not have their resources checked
146 if (code->trustedSigningCertChain() == false) {
147 return CSError::cfError(errors, errSecCSSignatureUntrusted);
148 }
149#endif
150
151
b1ab9ed8
A
152 END_CSAPI_ERRORS
153}
154
155
156//
157// ====================================================================================
158//
159// The following API functions are called SecCode* but accept both SecCodeRef and
160// SecStaticCodeRef arguments, operating on the implied SecStaticCodeRef as appropriate.
161// Hence they're here, rather than in SecCode.cpp.
162//
163
164
165//
166// Retrieve location information for an StaticCode.
167//
168OSStatus SecCodeCopyPath(SecStaticCodeRef staticCodeRef, SecCSFlags flags, CFURLRef *path)
169{
170 BEGIN_CSAPI
5c19dc3a 171
b1ab9ed8
A
172 checkFlags(flags);
173 SecPointer<SecStaticCode> staticCode = SecStaticCode::requiredStatic(staticCodeRef);
80e23899 174 CodeSigning::Required(path) = staticCode->copyCanonicalPath();
b1ab9ed8
A
175
176 END_CSAPI
177}
178
179
180//
181// Fetch or make up a designated requirement
182//
183OSStatus SecCodeCopyDesignatedRequirement(SecStaticCodeRef staticCodeRef, SecCSFlags flags,
184 SecRequirementRef *requirementRef)
185{
186 BEGIN_CSAPI
5c19dc3a 187
b1ab9ed8
A
188 checkFlags(flags);
189 const Requirement *req =
190 SecStaticCode::requiredStatic(staticCodeRef)->designatedRequirement();
191 CodeSigning::Required(requirementRef) = (new SecRequirement(req))->handle();
192
193 END_CSAPI
194}
195
196
197//
198// Fetch a particular internal requirement, if present
199//
200OSStatus SecCodeCopyInternalRequirement(SecStaticCodeRef staticCodeRef, SecRequirementType type,
201 SecCSFlags flags, SecRequirementRef *requirementRef)
202{
203 BEGIN_CSAPI
5c19dc3a 204
b1ab9ed8
A
205 checkFlags(flags);
206 const Requirement *req =
207 SecStaticCode::requiredStatic(staticCodeRef)->internalRequirement(type);
208 CodeSigning::Required(requirementRef) = req ? (new SecRequirement(req))->handle() : NULL;
209
210 END_CSAPI
211}
212
213
214//
215// Record for future use a detached code signature.
216//
217OSStatus SecCodeSetDetachedSignature(SecStaticCodeRef codeRef, CFDataRef signature,
218 SecCSFlags flags)
219{
220 BEGIN_CSAPI
5c19dc3a 221
b1ab9ed8
A
222 checkFlags(flags);
223 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(codeRef);
224
b1ab9ed8
A
225 code->detachedSignature(signature); // ... and pass it to the code
226 code->resetValidity();
227
228 END_CSAPI
229}
230
231
232//
233// Attach a code signature to a kernel memory mapping for page-in validation.
234//
235OSStatus SecCodeMapMemory(SecStaticCodeRef codeRef, SecCSFlags flags)
236{
237 BEGIN_CSAPI
d8f41ccd 238
b1ab9ed8
A
239 checkFlags(flags);
240 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(codeRef);
241 if (const CodeDirectory *cd = code->codeDirectory(false)) {
79b9da22
A
242 if (code->isDetached()) {
243 // Detached signatures need to attach their code directory from memory.
244 fsignatures args = { static_cast<off_t>(code->diskRep()->signingBase()), (void *)cd, cd->length() };
245 UnixError::check(::fcntl(code->diskRep()->fd(), F_ADDSIGS, &args));
246 } else {
247 // All other signatures can simply point to the signature in the main executable.
248 Universal *execImage = code->diskRep()->mainExecutableImage();
249 if (execImage == NULL) {
250 MacOSError::throwMe(errSecCSNoMainExecutable);
251 }
252
253 auto_ptr<MachO> arch(execImage->architecture());
254 if (arch.get() == NULL) {
255 MacOSError::throwMe(errSecCSNoMainExecutable);
256 }
257
258 size_t signatureOffset = arch->signingOffset();
259 size_t signatureLength = arch->signingLength();
260 if (signatureOffset == 0) {
261 MacOSError::throwMe(errSecCSUnsigned);
262 }
263
264 fsignatures args = {
265 static_cast<off_t>(code->diskRep()->signingBase()),
266 (void *)signatureOffset,
267 signatureLength,
268 };
269 UnixError::check(::fcntl(code->diskRep()->fd(), F_ADDFILESIGS, &args));
270 }
271 } else {
b1ab9ed8 272 MacOSError::throwMe(errSecCSUnsigned);
79b9da22 273 }
b1ab9ed8
A
274
275 END_CSAPI
276}
427c49bc
A
277
278
279//
280// Attach a callback block to a code object
281//
282OSStatus SecStaticCodeSetCallback(SecStaticCodeRef codeRef, SecCSFlags flags, SecCodeCallback *old, SecCodeCallback monitor)
283{
284 BEGIN_CSAPI
285
286 checkFlags(flags);
287 SecStaticCode *code = SecStaticCode::requiredStatic(codeRef);
288 if (old)
289 *old = code->monitor();
290 code->setMonitor(monitor);
291
292 END_CSAPI
293}
80e23899
A
294
295
296OSStatus SecStaticCodeSetValidationConditions(SecStaticCodeRef codeRef, CFDictionaryRef conditions)
297{
298 BEGIN_CSAPI
5c19dc3a 299
80e23899
A
300 checkFlags(0);
301 SecStaticCode *code = SecStaticCode::requiredStatic(codeRef);
302 code->setValidationModifiers(conditions);
5c19dc3a 303
80e23899
A
304 END_CSAPI
305}
d8f41ccd
A
306
307
308//
309// Set cancellation flag on a static code object.
310//
311OSStatus SecStaticCodeCancelValidation(SecStaticCodeRef codeRef, SecCSFlags flags)
312{
313 BEGIN_CSAPI
5c19dc3a 314
d8f41ccd
A
315 checkFlags(0);
316 SecStaticCode *code = SecStaticCode::requiredStatic(codeRef);
317 code->cancelValidation();
5c19dc3a 318
d8f41ccd
A
319 END_CSAPI
320}
fa7225c8
A
321
322
323//
324// Retrieve a component object for a special slot directly.
325//
326CFDataRef SecCodeCopyComponent(SecCodeRef codeRef, int slot, CFDataRef hash)
327{
328 BEGIN_CSAPI
329
330 SecStaticCode* code = SecStaticCode::requiredStatic(codeRef);
331 return code->copyComponent(slot, hash);
332
333 END_CSAPI1(NULL)
334}
335
336
337//
338// Validate a single plain file's resource seal against a memory copy.
339// This will fail for any other file type (symlink, directory, nested code, etc. etc.)
340//
341OSStatus SecCodeValidateFileResource(SecStaticCodeRef codeRef, CFStringRef relativePath, CFDataRef fileData, SecCSFlags flags)
342{
343 BEGIN_CSAPI
344
345 checkFlags(0);
346 if (fileData == NULL)
347 MacOSError::throwMe(errSecCSObjectRequired);
348 SecStaticCode *code = SecStaticCode::requiredStatic(codeRef);
349 code->validatePlainMemoryResource(cfString(relativePath), fileData, flags);
350
351 END_CSAPI
352
353}