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