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