]> git.saurik.com Git - apple/security.git/blob - libsecurity_codesigning/lib/SecCode.cpp
cd91d81349c0bd4707325739da0a1f03310fa64c
[apple/security.git] / libsecurity_codesigning / lib / SecCode.cpp
1 /*
2 * Copyright (c) 2006-2010 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
36 using namespace CodeSigning;
37
38
39 //
40 // CFError user info keys
41 //
42 const CFStringRef kSecCFErrorArchitecture = CFSTR("SecCSArchitecture");
43 const CFStringRef kSecCFErrorPattern = CFSTR("SecCSPattern");
44 const CFStringRef kSecCFErrorResourceSeal = CFSTR("SecCSResourceSeal");
45 const CFStringRef kSecCFErrorResourceAdded = CFSTR("SecCSResourceAdded");
46 const CFStringRef kSecCFErrorResourceAltered = CFSTR("SecCSResourceAltered");
47 const CFStringRef kSecCFErrorResourceMissing = CFSTR("SecCSResourceMissing");
48 const CFStringRef kSecCFErrorInfoPlist = CFSTR("SecCSInfoPlist");
49 const CFStringRef kSecCFErrorGuestAttributes = CFSTR("SecCSGuestAttributes");
50 const CFStringRef kSecCFErrorRequirementSyntax = CFSTR("SecRequirementSyntax");
51 const CFStringRef kSecCFErrorPath = CFSTR("SecComponentPath");
52
53
54 //
55 // CF-standard type code functions
56 //
57 CFTypeID SecCodeGetTypeID(void)
58 {
59 BEGIN_CSAPI
60 return gCFObjects().Code.typeID;
61 END_CSAPI1(_kCFRuntimeNotATypeID)
62 }
63
64
65 //
66 // Get a reference to the calling code.
67 //
68 OSStatus SecCodeCopySelf(SecCSFlags flags, SecCodeRef *selfRef)
69 {
70 BEGIN_CSAPI
71
72 checkFlags(flags);
73 CFRef<CFMutableDictionaryRef> attributes = makeCFMutableDictionary(1,
74 kSecGuestAttributePid, CFTempNumber(getpid()).get());
75 CodeSigning::Required(selfRef) = SecCode::autoLocateGuest(attributes, flags)->handle(false);
76
77 END_CSAPI
78 }
79
80
81 //
82 // Get the dynamic status of a code.
83 //
84 OSStatus SecCodeGetStatus(SecCodeRef codeRef, SecCSFlags flags, SecCodeStatus *status)
85 {
86 BEGIN_CSAPI
87
88 checkFlags(flags);
89 CodeSigning::Required(status) = SecCode::required(codeRef)->status();
90
91 END_CSAPI
92 }
93
94
95 //
96 // Change the dynamic status of a code
97 //
98 OSStatus SecCodeSetStatus(SecCodeRef codeRef, SecCodeStatusOperation operation,
99 CFDictionaryRef arguments, SecCSFlags flags)
100 {
101 BEGIN_CSAPI
102
103 checkFlags(flags);
104 SecCode::required(codeRef)->status(operation, arguments);
105
106 END_CSAPI
107 }
108
109
110 //
111 // Get the StaticCode for an Code
112 //
113 OSStatus SecCodeCopyStaticCode(SecCodeRef codeRef, SecCSFlags flags, SecStaticCodeRef *staticCodeRef)
114 {
115 BEGIN_CSAPI
116
117 checkFlags(flags, kSecCSUseAllArchitectures);
118 SecPointer<SecStaticCode> staticCode = SecCode::required(codeRef)->staticCode();
119 if (flags & kSecCSUseAllArchitectures)
120 if (Universal* macho = staticCode->diskRep()->mainExecutableImage()) // Mach-O main executable
121 if (macho->narrowed()) {
122 // create a new StaticCode comprising the whole fat file
123 RefPointer<DiskRep> rep = DiskRep::bestGuess(staticCode->diskRep()->mainExecutablePath());
124 staticCode = new SecStaticCode(rep);
125 }
126 CodeSigning::Required(staticCodeRef) = staticCode ? staticCode->handle() : NULL;
127
128 END_CSAPI
129 }
130
131
132 //
133 // Get the host for an Code
134 //
135 OSStatus SecCodeCopyHost(SecCodeRef guestRef, SecCSFlags flags, SecCodeRef *hostRef)
136 {
137 BEGIN_CSAPI
138
139 checkFlags(flags);
140 SecPointer<SecCode> host = SecCode::required(guestRef)->host();
141 CodeSigning::Required(hostRef) = host ? host->handle() : NULL;
142
143 END_CSAPI
144 }
145
146
147 //
148 // Find a guest by attribute(s)
149 //
150 const CFStringRef kSecGuestAttributeCanonical = CFSTR("canonical");
151 const CFStringRef kSecGuestAttributeHash = CFSTR("codedirectory-hash");
152 const CFStringRef kSecGuestAttributeMachPort = CFSTR("mach-port");
153 const CFStringRef kSecGuestAttributePid = CFSTR("pid");
154 const CFStringRef kSecGuestAttributeDynamicCode = CFSTR("dynamicCode");
155 const CFStringRef kSecGuestAttributeDynamicCodeInfoPlist = CFSTR("dynamicCodeInfoPlist");
156 const CFStringRef kSecGuestAttributeArchitecture = CFSTR("architecture");
157 const CFStringRef kSecGuestAttributeSubarchitecture = CFSTR("subarchitecture");
158
159 OSStatus SecCodeCopyGuestWithAttributes(SecCodeRef hostRef,
160 CFDictionaryRef attributes, SecCSFlags flags, SecCodeRef *guestRef)
161 {
162 BEGIN_CSAPI
163
164 checkFlags(flags);
165 if (hostRef) {
166 if (SecCode *guest = SecCode::required(hostRef)->locateGuest(attributes))
167 CodeSigning::Required(guestRef) = guest->handle(false);
168 else
169 return errSecCSNoSuchCode;
170 } else
171 CodeSigning::Required(guestRef) = SecCode::autoLocateGuest(attributes, flags)->handle(false);
172
173 END_CSAPI
174 }
175
176
177 //
178 // Shorthand for getting the SecCodeRef for a UNIX process
179 //
180 OSStatus SecCodeCreateWithPID(pid_t pid, SecCSFlags flags, SecCodeRef *processRef)
181 {
182 BEGIN_CSAPI
183
184 checkFlags(flags);
185 if (SecCode *guest = KernelCode::active()->locateGuest(CFTemp<CFDictionaryRef>("{%O=%d}", kSecGuestAttributePid, pid)))
186 CodeSigning::Required(processRef) = guest->handle(false);
187 else
188 return errSecCSNoSuchCode;
189
190 END_CSAPI
191 }
192
193
194 //
195 // Check validity of an Code
196 //
197 OSStatus SecCodeCheckValidity(SecCodeRef codeRef, SecCSFlags flags,
198 SecRequirementRef requirementRef)
199 {
200 return SecCodeCheckValidityWithErrors(codeRef, flags, requirementRef, NULL);
201 }
202
203 OSStatus SecCodeCheckValidityWithErrors(SecCodeRef codeRef, SecCSFlags flags,
204 SecRequirementRef requirementRef, CFErrorRef *errors)
205 {
206 BEGIN_CSAPI
207
208 checkFlags(flags,
209 kSecCSConsiderExpiration
210 | kSecCSEnforceRevocationChecks);
211 SecPointer<SecCode> code = SecCode::required(codeRef);
212 code->checkValidity(flags);
213 if (const SecRequirement *req = SecRequirement::optional(requirementRef))
214 code->staticCode()->validateRequirement(req->requirement(), errSecCSReqFailed);
215
216 END_CSAPI_ERRORS
217 }
218
219
220 //
221 // Collect suitably laundered information about the code signature of a SecStaticCode
222 // and return it as a CFDictionary.
223 //
224 // This API contracts to return a few pieces of information even for unsigned
225 // code. This means that a SecStaticCodeRef is usable as a basic indentifier
226 // (i.e. handle) for any code out there.
227 //
228 const CFStringRef kSecCodeInfoCertificates = CFSTR("certificates");
229 const CFStringRef kSecCodeInfoChangedFiles = CFSTR("changed-files");
230 const CFStringRef kSecCodeInfoCMS = CFSTR("cms");
231 const CFStringRef kSecCodeInfoDesignatedRequirement = CFSTR("designated-requirement");
232 const CFStringRef kSecCodeInfoEntitlements = CFSTR("entitlements");
233 const CFStringRef kSecCodeInfoEntitlementsDict = CFSTR("entitlements-dict");
234 const CFStringRef kSecCodeInfoFlags = CFSTR("flags");
235 const CFStringRef kSecCodeInfoFormat = CFSTR("format");
236 const CFStringRef kSecCodeInfoDigestAlgorithm = CFSTR("digest-algorithm");
237 const CFStringRef kSecCodeInfoIdentifier = CFSTR("identifier");
238 const CFStringRef kSecCodeInfoImplicitDesignatedRequirement = CFSTR("implicit-requirement");
239 const CFStringRef kSecCodeInfoMainExecutable = CFSTR("main-executable");
240 const CFStringRef kSecCodeInfoPList = CFSTR("info-plist");
241 const CFStringRef kSecCodeInfoRequirements = CFSTR("requirements");
242 const CFStringRef kSecCodeInfoRequirementData = CFSTR("requirement-data");
243 const CFStringRef kSecCodeInfoSource = CFSTR("source");
244 const CFStringRef kSecCodeInfoStatus = CFSTR("status");
245 const CFStringRef kSecCodeInfoTime = CFSTR("signing-time");
246 const CFStringRef kSecCodeInfoTimestamp = CFSTR("signing-timestamp");
247 const CFStringRef kSecCodeInfoTrust = CFSTR("trust");
248 const CFStringRef kSecCodeInfoUnique = CFSTR("unique");
249
250 const CFStringRef kSecCodeInfoCodeDirectory = CFSTR("CodeDirectory");
251 const CFStringRef kSecCodeInfoCodeOffset = CFSTR("CodeOffset");
252 const CFStringRef kSecCodeInfoResourceDirectory = CFSTR("ResourceDirectory");
253
254
255 OSStatus SecCodeCopySigningInformation(SecStaticCodeRef codeRef, SecCSFlags flags,
256 CFDictionaryRef *infoRef)
257 {
258 BEGIN_CSAPI
259
260 checkFlags(flags,
261 kSecCSInternalInformation
262 | kSecCSSigningInformation
263 | kSecCSRequirementInformation
264 | kSecCSDynamicInformation
265 | kSecCSContentInformation);
266
267 SecPointer<SecStaticCode> code = SecStaticCode::requiredStatic(codeRef);
268 CFRef<CFDictionaryRef> info = code->signingInformation(flags);
269
270 if (flags & kSecCSDynamicInformation)
271 if (SecPointer<SecCode> dcode = SecStaticCode::optionalDynamic(codeRef))
272 info.take(cfmake<CFDictionaryRef>("{+%O,%O=%u}", info.get(), kSecCodeInfoStatus, dcode->status()));
273
274 CodeSigning::Required(infoRef) = info.yield();
275
276 END_CSAPI
277 }