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