]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/lib/SecCode.cpp
Security-59306.61.1.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / SecCode.cpp
1 /*
2 * Copyright (c) 2006-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 // SecCode - API frame for SecCode objects.
26 //
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.
30 //
31 #include "cs.h"
32 #include "Code.h"
33 #include "cskernel.h"
34 #include <security_utilities/cfmunge.h>
35 #include <security_utilities/logging.h>
36
37 using namespace CodeSigning;
38
39
40 //
41 // CFError user info keys
42 //
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 kSecCFErrorResourceSideband = CFSTR("SecCSResourceHasSidebandData");
50 const CFStringRef kSecCFErrorInfoPlist = CFSTR("SecCSInfoPlist");
51 const CFStringRef kSecCFErrorGuestAttributes = CFSTR("SecCSGuestAttributes");
52 const CFStringRef kSecCFErrorRequirementSyntax = CFSTR("SecRequirementSyntax");
53 const CFStringRef kSecCFErrorPath = CFSTR("SecComponentPath");
54
55
56 //
57 // CF-standard type code functions
58 //
59 CFTypeID SecCodeGetTypeID(void)
60 {
61 BEGIN_CSAPI
62 return gCFObjects().Code.typeID;
63 END_CSAPI1(_kCFRuntimeNotATypeID)
64 }
65
66
67 //
68 // Get a reference to the calling code.
69 //
70 OSStatus SecCodeCopySelf(SecCSFlags flags, SecCodeRef *selfRef)
71 {
72 BEGIN_CSAPI
73
74 checkFlags(flags);
75 CFRef<CFMutableDictionaryRef> attributes = makeCFMutableDictionary(1,
76 kSecGuestAttributePid, CFTempNumber(getpid()).get());
77 CodeSigning::Required(selfRef) = SecCode::autoLocateGuest(attributes, flags)->handle(false);
78
79 END_CSAPI
80 }
81
82
83 //
84 // Get the dynamic status of a code.
85 //
86 OSStatus SecCodeGetStatus(SecCodeRef codeRef, SecCSFlags flags, SecCodeStatus *status)
87 {
88 BEGIN_CSAPI
89
90 checkFlags(flags);
91 CodeSigning::Required(status) = SecCode::required(codeRef)->status();
92
93 END_CSAPI
94 }
95
96
97 //
98 // Change the dynamic status of a code
99 //
100 OSStatus SecCodeSetStatus(SecCodeRef codeRef, SecCodeStatusOperation operation,
101 CFDictionaryRef arguments, SecCSFlags flags)
102 {
103 BEGIN_CSAPI
104
105 checkFlags(flags);
106 SecCode::required(codeRef)->status(operation, arguments);
107
108 END_CSAPI
109 }
110
111
112 //
113 // Get the StaticCode for an Code
114 //
115 OSStatus SecCodeCopyStaticCode(SecCodeRef codeRef, SecCSFlags flags, SecStaticCodeRef *staticCodeRef)
116 {
117 BEGIN_CSAPI
118
119 checkFlags(flags, kSecCSUseAllArchitectures);
120 SecPointer<SecStaticCode> staticCode = SecCode::required(codeRef)->staticCode();
121 if (flags & kSecCSUseAllArchitectures)
122 if (Universal* macho = staticCode->diskRep()->mainExecutableImage()) // Mach-O main executable
123 if (macho->narrowed()) {
124 // create a new StaticCode comprising the whole fat file
125 RefPointer<DiskRep> rep = DiskRep::bestGuess(staticCode->diskRep()->mainExecutablePath());
126 staticCode = new SecStaticCode(rep);
127 }
128 CodeSigning::Required(staticCodeRef) = staticCode ? staticCode->handle() : NULL;
129
130 END_CSAPI
131 }
132
133
134 //
135 // Get the host for an Code
136 //
137 OSStatus SecCodeCopyHost(SecCodeRef guestRef, SecCSFlags flags, SecCodeRef *hostRef)
138 {
139 BEGIN_CSAPI
140
141 checkFlags(flags);
142 SecPointer<SecCode> host = SecCode::required(guestRef)->host();
143 CodeSigning::Required(hostRef) = host ? host->handle() : NULL;
144
145 END_CSAPI
146 }
147
148
149 //
150 // Find a guest by attribute(s)
151 //
152 const CFStringRef kSecGuestAttributeCanonical = CFSTR("canonical");
153 const CFStringRef kSecGuestAttributeHash = CFSTR("codedirectory-hash");
154 const CFStringRef kSecGuestAttributeMachPort = CFSTR("mach-port");
155 const CFStringRef kSecGuestAttributePid = CFSTR("pid");
156 const CFStringRef kSecGuestAttributeAudit = CFSTR("audit");
157 const CFStringRef kSecGuestAttributeDynamicCode = CFSTR("dynamicCode");
158 const CFStringRef kSecGuestAttributeDynamicCodeInfoPlist = CFSTR("dynamicCodeInfoPlist");
159 const CFStringRef kSecGuestAttributeArchitecture = CFSTR("architecture");
160 const CFStringRef kSecGuestAttributeSubarchitecture = CFSTR("subarchitecture");
161
162 #if TARGET_OS_OSX
163 OSStatus SecCodeCopyGuestWithAttributes(SecCodeRef hostRef,
164 CFDictionaryRef attributes, SecCSFlags flags, SecCodeRef *guestRef)
165 {
166 BEGIN_CSAPI
167
168 checkFlags(flags);
169 if (hostRef) {
170 if (SecCode *guest = SecCode::required(hostRef)->locateGuest(attributes))
171 CodeSigning::Required(guestRef) = guest->handle(false);
172 else
173 return errSecCSNoSuchCode;
174 } else
175 CodeSigning::Required(guestRef) = SecCode::autoLocateGuest(attributes, flags)->handle(false);
176
177 END_CSAPI
178 }
179
180
181 //
182 // Deprecated since 10.6, DO NOT USE. This can be raced.
183 // Use SecCodeCreateWithAuditToken instead.
184 //
185 OSStatus SecCodeCreateWithPID(pid_t pid, SecCSFlags flags, SecCodeRef *processRef)
186 {
187 BEGIN_CSAPI
188
189 checkFlags(flags);
190 if (SecCode *guest = KernelCode::active()->locateGuest(CFTemp<CFDictionaryRef>("{%O=%d}", kSecGuestAttributePid, pid)))
191 CodeSigning::Required(processRef) = guest->handle(false);
192 else
193 return errSecCSNoSuchCode;
194
195 END_CSAPI
196 }
197
198 //
199 // Shorthand for getting the SecCodeRef for a UNIX process
200 //
201 OSStatus SecCodeCreateWithAuditToken(const audit_token_t *audit,
202 SecCSFlags flags, SecCodeRef *processRef)
203 {
204 BEGIN_CSAPI
205
206 checkFlags(flags);
207 CFRef<CFDataRef> auditData = makeCFData(audit, sizeof(audit_token_t));
208 if (SecCode *guest = KernelCode::active()->locateGuest(CFTemp<CFDictionaryRef>("{%O=%O}", kSecGuestAttributeAudit, auditData.get()))) {
209 CodeSigning::Required(processRef) = guest->handle(false);
210 } else {
211 return errSecCSNoSuchCode;
212 }
213
214 END_CSAPI
215 }
216 #endif // TARGET_OS_OSX
217
218
219 //
220 // Check validity of an Code
221 //
222 OSStatus SecCodeCheckValidity(SecCodeRef codeRef, SecCSFlags flags,
223 SecRequirementRef requirementRef)
224 {
225 return SecCodeCheckValidityWithErrors(codeRef, flags, requirementRef, NULL);
226 }
227
228 OSStatus SecCodeCheckValidityWithErrors(SecCodeRef codeRef, SecCSFlags flags,
229 SecRequirementRef requirementRef, CFErrorRef *errors)
230 {
231 BEGIN_CSAPI
232
233 checkFlags(flags,
234 kSecCSConsiderExpiration
235 | kSecCSStrictValidate
236 | kSecCSStrictValidateStructure
237 | kSecCSRestrictSidebandData
238 | kSecCSEnforceRevocationChecks
239 );
240 SecPointer<SecCode> code = SecCode::required(codeRef);
241 code->checkValidity(flags);
242 if (const SecRequirement *req = SecRequirement::optional(requirementRef))
243 code->staticCode()->validateRequirement(req->requirement(), errSecCSReqFailed);
244
245 END_CSAPI_ERRORS
246 }
247
248
249 //
250 // Collect suitably laundered information about the code signature of a SecStaticCode
251 // and return it as a CFDictionary.
252 //
253 // This API contracts to return a few pieces of information even for unsigned
254 // code. This means that a SecStaticCodeRef is usable as a basic indentifier
255 // (i.e. handle) for any code out there.
256 //
257 const CFStringRef kSecCodeInfoCertificates = CFSTR("certificates");
258 const CFStringRef kSecCodeInfoChangedFiles = CFSTR("changed-files");
259 const CFStringRef kSecCodeInfoCMS = CFSTR("cms");
260 const CFStringRef kSecCodeInfoDesignatedRequirement = CFSTR("designated-requirement");
261 const CFStringRef kSecCodeInfoEntitlements = CFSTR("entitlements");
262 const CFStringRef kSecCodeInfoEntitlementsDict = CFSTR("entitlements-dict");
263 const CFStringRef kSecCodeInfoFlags = CFSTR("flags");
264 const CFStringRef kSecCodeInfoFormat = CFSTR("format");
265 const CFStringRef kSecCodeInfoDigestAlgorithm = CFSTR("digest-algorithm");
266 const CFStringRef kSecCodeInfoDigestAlgorithms = CFSTR("digest-algorithms");
267 const CFStringRef kSecCodeInfoPlatformIdentifier = CFSTR("platform-identifier");
268 const CFStringRef kSecCodeInfoIdentifier = CFSTR("identifier");
269 const CFStringRef kSecCodeInfoImplicitDesignatedRequirement = CFSTR("implicit-requirement");
270 const CFStringRef kSecCodeInfoMainExecutable = CFSTR("main-executable");
271 const CFStringRef kSecCodeInfoPList = CFSTR("info-plist");
272 const CFStringRef kSecCodeInfoRequirements = CFSTR("requirements");
273 const CFStringRef kSecCodeInfoRequirementData = CFSTR("requirement-data");
274 const CFStringRef kSecCodeInfoSource = CFSTR("source");
275 const CFStringRef kSecCodeInfoStatus = CFSTR("status");
276 const CFStringRef kSecCodeInfoTeamIdentifier = CFSTR("teamid");
277 const CFStringRef kSecCodeInfoTime = CFSTR("signing-time");
278 const CFStringRef kSecCodeInfoTimestamp = CFSTR("signing-timestamp");
279 const CFStringRef kSecCodeInfoTrust = CFSTR("trust");
280 const CFStringRef kSecCodeInfoUnique = CFSTR("unique");
281 const CFStringRef kSecCodeInfoCdHashes = CFSTR("cdhashes");
282 const CFStringRef kSecCodeInfoCdHashesFull = CFSTR("cdhashes-full");
283 const CFStringRef kSecCodeInfoRuntimeVersion = CFSTR("runtime-version");
284
285 const CFStringRef kSecCodeInfoCodeDirectory = CFSTR("CodeDirectory");
286 const CFStringRef kSecCodeInfoCodeOffset = CFSTR("CodeOffset");
287 const CFStringRef kSecCodeInfoDiskRepInfo = CFSTR("DiskRepInfo");
288 const CFStringRef kSecCodeInfoResourceDirectory = CFSTR("ResourceDirectory");
289 const CFStringRef kSecCodeInfoNotarizationDate = CFSTR("NotarizationDate");
290 const CFStringRef kSecCodeInfoCMSDigestHashType = CFSTR("CMSDigestHashType");
291 const CFStringRef kSecCodeInfoCMSDigest = CFSTR("CMSDigest");
292
293 /* DiskInfoRepInfo types */
294 const CFStringRef kSecCodeInfoDiskRepVersionPlatform = CFSTR("VersionPlatform");
295 const CFStringRef kSecCodeInfoDiskRepVersionMin = CFSTR("VersionMin");
296 const CFStringRef kSecCodeInfoDiskRepVersionSDK = CFSTR("VersionSDK");
297 const CFStringRef kSecCodeInfoDiskRepNoLibraryValidation = CFSTR("NoLibraryValidation");
298
299
300 OSStatus SecCodeCopySigningInformation(SecStaticCodeRef codeRef, SecCSFlags flags,
301 CFDictionaryRef *infoRef)
302 {
303 BEGIN_CSAPI
304
305 checkFlags(flags,
306 kSecCSInternalInformation
307 | kSecCSSigningInformation
308 | kSecCSRequirementInformation
309 | kSecCSDynamicInformation
310 | kSecCSContentInformation
311 | kSecCSSkipResourceDirectory
312 | kSecCSCalculateCMSDigest);
313
314 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(codeRef);
315 CFRef<CFDictionaryRef> info = code->signingInformation(flags);
316
317 if (flags & kSecCSDynamicInformation)
318 if (SecPointer<SecCode> dcode = SecStaticCode::optionalDynamic(codeRef))
319 info.take(cfmake<CFDictionaryRef>("{+%O,%O=%u}", info.get(), kSecCodeInfoStatus, dcode->status()));
320
321 CodeSigning::Required(infoRef) = info.yield();
322
323 END_CSAPI
324 }