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