]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/lib/SecCode.cpp
Security-58286.51.6.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 // Shorthand for getting the SecCodeRef for a UNIX process
183 //
184 OSStatus SecCodeCreateWithPID(pid_t pid, SecCSFlags flags, SecCodeRef *processRef)
185 {
186 BEGIN_CSAPI
187
188 checkFlags(flags);
189 if (SecCode *guest = KernelCode::active()->locateGuest(CFTemp<CFDictionaryRef>("{%O=%d}", kSecGuestAttributePid, pid)))
190 CodeSigning::Required(processRef) = guest->handle(false);
191 else
192 return errSecCSNoSuchCode;
193
194 END_CSAPI
195 }
196 #endif // TARGET_OS_OSX
197
198
199 //
200 // Check validity of an Code
201 //
202 OSStatus SecCodeCheckValidity(SecCodeRef codeRef, SecCSFlags flags,
203 SecRequirementRef requirementRef)
204 {
205 return SecCodeCheckValidityWithErrors(codeRef, flags, requirementRef, NULL);
206 }
207
208 OSStatus SecCodeCheckValidityWithErrors(SecCodeRef codeRef, SecCSFlags flags,
209 SecRequirementRef requirementRef, CFErrorRef *errors)
210 {
211 BEGIN_CSAPI
212
213 checkFlags(flags,
214 kSecCSConsiderExpiration
215 | kSecCSStrictValidate
216 | kSecCSRestrictSidebandData
217 | kSecCSEnforceRevocationChecks);
218 SecPointer<SecCode> code = SecCode::required(codeRef);
219 code->checkValidity(flags);
220 if (const SecRequirement *req = SecRequirement::optional(requirementRef))
221 code->staticCode()->validateRequirement(req->requirement(), errSecCSReqFailed);
222
223 END_CSAPI_ERRORS
224 }
225
226
227 //
228 // Collect suitably laundered information about the code signature of a SecStaticCode
229 // and return it as a CFDictionary.
230 //
231 // This API contracts to return a few pieces of information even for unsigned
232 // code. This means that a SecStaticCodeRef is usable as a basic indentifier
233 // (i.e. handle) for any code out there.
234 //
235 const CFStringRef kSecCodeInfoCertificates = CFSTR("certificates");
236 const CFStringRef kSecCodeInfoChangedFiles = CFSTR("changed-files");
237 const CFStringRef kSecCodeInfoCMS = CFSTR("cms");
238 const CFStringRef kSecCodeInfoDesignatedRequirement = CFSTR("designated-requirement");
239 const CFStringRef kSecCodeInfoEntitlements = CFSTR("entitlements");
240 const CFStringRef kSecCodeInfoEntitlementsDict = CFSTR("entitlements-dict");
241 const CFStringRef kSecCodeInfoFlags = CFSTR("flags");
242 const CFStringRef kSecCodeInfoFormat = CFSTR("format");
243 const CFStringRef kSecCodeInfoDigestAlgorithm = CFSTR("digest-algorithm");
244 const CFStringRef kSecCodeInfoDigestAlgorithms = CFSTR("digest-algorithms");
245 const CFStringRef kSecCodeInfoPlatformIdentifier = CFSTR("platform-identifier");
246 const CFStringRef kSecCodeInfoIdentifier = CFSTR("identifier");
247 const CFStringRef kSecCodeInfoImplicitDesignatedRequirement = CFSTR("implicit-requirement");
248 const CFStringRef kSecCodeInfoMainExecutable = CFSTR("main-executable");
249 const CFStringRef kSecCodeInfoPList = CFSTR("info-plist");
250 const CFStringRef kSecCodeInfoRequirements = CFSTR("requirements");
251 const CFStringRef kSecCodeInfoRequirementData = CFSTR("requirement-data");
252 const CFStringRef kSecCodeInfoSource = CFSTR("source");
253 const CFStringRef kSecCodeInfoStatus = CFSTR("status");
254 const CFStringRef kSecCodeInfoTeamIdentifier = CFSTR("teamid");
255 const CFStringRef kSecCodeInfoTime = CFSTR("signing-time");
256 const CFStringRef kSecCodeInfoTimestamp = CFSTR("signing-timestamp");
257 const CFStringRef kSecCodeInfoTrust = CFSTR("trust");
258 const CFStringRef kSecCodeInfoUnique = CFSTR("unique");
259 const CFStringRef kSecCodeInfoCdHashes = CFSTR("cdhashes");
260
261
262 const CFStringRef kSecCodeInfoCodeDirectory = CFSTR("CodeDirectory");
263 const CFStringRef kSecCodeInfoCodeOffset = CFSTR("CodeOffset");
264 const CFStringRef kSecCodeInfoDiskRepInfo = CFSTR("DiskRepInfo");
265 const CFStringRef kSecCodeInfoResourceDirectory = CFSTR("ResourceDirectory");
266
267 /* DiskInfoRepInfo types */
268 const CFStringRef kSecCodeInfoDiskRepOSPlatform = CFSTR("OSPlatform");
269 const CFStringRef kSecCodeInfoDiskRepOSVersionMin = CFSTR("OSVersionMin");
270 const CFStringRef kSecCodeInfoDiskRepOSSDKVersion = CFSTR("SDKVersion");
271 const CFStringRef kSecCodeInfoDiskRepNoLibraryValidation = CFSTR("NoLibraryValidation");
272
273
274 OSStatus SecCodeCopySigningInformation(SecStaticCodeRef codeRef, SecCSFlags flags,
275 CFDictionaryRef *infoRef)
276 {
277 BEGIN_CSAPI
278
279 checkFlags(flags,
280 kSecCSInternalInformation
281 | kSecCSSigningInformation
282 | kSecCSRequirementInformation
283 | kSecCSDynamicInformation
284 | kSecCSContentInformation
285 | kSecCSSkipResourceDirectory);
286
287 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(codeRef);
288 CFRef<CFDictionaryRef> info = code->signingInformation(flags);
289
290 if (flags & kSecCSDynamicInformation)
291 if (SecPointer<SecCode> dcode = SecStaticCode::optionalDynamic(codeRef))
292 info.take(cfmake<CFDictionaryRef>("{+%O,%O=%u}", info.get(), kSecCodeInfoStatus, dcode->status()));
293
294 CodeSigning::Required(infoRef) = info.yield();
295
296 END_CSAPI
297 }