]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/lib/SecACL.cpp
Security-58286.1.32.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / lib / SecACL.cpp
1 /*
2 * Copyright (c) 2002-2004,2011-2014 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 #include <Security/SecACL.h>
25 #include <security_keychain/ACL.h>
26 #include <security_keychain/Access.h>
27 #include <security_keychain/SecAccessPriv.h>
28
29 #include <os/activity.h>
30
31 #include "SecBridge.h"
32
33 // Forward reference
34 /*!
35 @function GetACLAuthorizationTagFromString
36 @abstract Get the CSSM ACL item from the CFString
37 @param aclStr The String name of the ACL
38 @result The CSSM ACL value
39 */
40 sint32 GetACLAuthorizationTagFromString(CFStringRef aclStr);
41
42 CFStringRef GetAuthStringFromACLAuthorizationTag(sint32 tag);
43
44 //
45 // Local functions
46 //
47 static void setApplications(ACL *acl, CFArrayRef applicationList);
48
49 CFTypeID
50 SecACLGetTypeID(void)
51 {
52 BEGIN_SECAPI
53 os_activity_t activity = os_activity_create("SecACLGetTypeID", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
54 os_activity_scope(activity);
55 os_release(activity);
56
57 return gTypes().ACL.typeID;
58
59 END_SECAPI1(_kCFRuntimeNotATypeID)
60 }
61
62
63 /*!
64 */
65 OSStatus SecACLCreateFromSimpleContents(SecAccessRef accessRef,
66 CFArrayRef applicationList,
67 CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector,
68 SecACLRef *newAcl)
69 {
70 BEGIN_SECAPI
71 os_activity_t activity = os_activity_create("SecACLCreateFromSimpleContents", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
72 os_activity_scope(activity);
73 os_release(activity);
74 SecPointer<Access> access = Access::required(accessRef);
75 SecPointer<ACL> acl = new ACL(cfString(description), *promptSelector);
76 if (applicationList) {
77 // application-list + prompt
78 acl->form(ACL::appListForm);
79 setApplications(acl, applicationList);
80 } else {
81 // allow-any
82 acl->form(ACL::allowAllForm);
83 }
84 access->add(acl.get());
85 Required(newAcl) = acl->handle();
86 END_SECAPI
87 }
88
89 OSStatus SecACLCreateWithSimpleContents(SecAccessRef access,
90 CFArrayRef applicationList,
91 CFStringRef description,
92 SecKeychainPromptSelector promptSelector,
93 SecACLRef *newAcl)
94 {
95 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector;
96 cdsaPromptSelector.version = CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION;
97 cdsaPromptSelector.flags = promptSelector;
98 return SecACLCreateFromSimpleContents(access, applicationList, description, &cdsaPromptSelector, newAcl);
99 }
100
101
102 /*!
103 */
104 OSStatus SecACLRemove(SecACLRef aclRef)
105 {
106 BEGIN_SECAPI
107 os_activity_t activity = os_activity_create("SecACLRemove", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
108 os_activity_scope(activity);
109 os_release(activity);
110 ACL::required(aclRef)->remove();
111 END_SECAPI
112 }
113
114
115 static SecTrustedApplicationRef
116 convert(const SecPointer<TrustedApplication> &trustedApplication)
117 {
118 return *trustedApplication;
119 }
120
121 /*!
122 */
123 OSStatus SecACLCopySimpleContents(SecACLRef aclRef,
124 CFArrayRef *applicationList,
125 CFStringRef *promptDescription, CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector)
126 {
127 BEGIN_SECAPI
128 SecPointer<ACL> acl = ACL::required(aclRef);
129 switch (acl->form()) {
130 case ACL::allowAllForm:
131 Required(applicationList) = NULL;
132 Required(promptDescription) =
133 acl->promptDescription().empty() ? NULL
134 : makeCFString(acl->promptDescription());
135 Required(promptSelector) = acl->promptSelector();
136 break;
137 case ACL::appListForm:
138 Required(applicationList) =
139 makeCFArrayFrom(convert, acl->applications());
140 Required(promptDescription) = makeCFString(acl->promptDescription());
141 Required(promptSelector) = acl->promptSelector();
142 break;
143 case ACL::integrityForm:
144 Required(applicationList) = NULL;
145 Required(promptDescription) = makeCFString(acl->integrity().toHex());
146
147 // We don't have a prompt selector. Nullify.
148 Required(promptSelector).version = CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION;
149 Required(promptSelector).flags = 0;
150 break;
151 default:
152 return errSecACLNotSimple; // custom or unknown
153 }
154 END_SECAPI
155 }
156
157 OSStatus SecACLCopyContents(SecACLRef acl,
158 CFArrayRef *applicationList,
159 CFStringRef *description,
160 SecKeychainPromptSelector *promptSelector)
161 {
162 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector;
163 memset(&cdsaPromptSelector, 0, sizeof(cdsaPromptSelector));
164 OSStatus err = errSecSuccess;
165
166 err = SecACLCopySimpleContents(acl, applicationList, description, &cdsaPromptSelector);
167 *promptSelector = cdsaPromptSelector.flags;
168 return err;
169 }
170
171 OSStatus SecACLSetSimpleContents(SecACLRef aclRef,
172 CFArrayRef applicationList,
173 CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector)
174 {
175 BEGIN_SECAPI
176 os_activity_t activity = os_activity_create("SecACLSetSimpleContents", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
177 os_activity_scope(activity);
178 os_release(activity);
179 SecPointer<ACL> acl = ACL::required(aclRef);
180 if(acl->form() == ACL::integrityForm) {
181 // If this is an integrity ACL, route the (unhexified) promptDescription into the right place
182 string hex = cfString(description);
183 if(hex.length() %2 == 0) {
184 // might be a valid hex string, try to set
185 CssmAutoData data(Allocator::standard());
186 data.malloc(hex.length() / 2);
187 data.get().fromHex(hex.c_str());
188 acl->setIntegrity(data);
189 }
190 } else {
191 // Otherwise, put it in the promptDescription where it belongs
192 acl->promptDescription() = description ? cfString(description) : "";
193 }
194 acl->promptSelector() = promptSelector ? *promptSelector : ACL::defaultSelector;
195 if(acl->form() != ACL::integrityForm) {
196 if (applicationList) {
197 // application-list + prompt
198 acl->form(ACL::appListForm);
199 setApplications(acl, applicationList);
200 } else {
201 // allow-any
202 acl->form(ACL::allowAllForm);
203 }
204 }
205 acl->modify();
206 END_SECAPI
207 }
208
209 OSStatus SecACLSetContents(SecACLRef acl,
210 CFArrayRef applicationList,
211 CFStringRef description,
212 SecKeychainPromptSelector promptSelector)
213 {
214 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector;
215 cdsaPromptSelector.version = CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION;
216 cdsaPromptSelector.flags = promptSelector;
217 return SecACLSetSimpleContents(acl, applicationList, description, &cdsaPromptSelector);
218 }
219
220 //
221 // Stuff a CFArray-of-SecTrustedApplications into an ACL object
222 //
223 static void setApplications(ACL *acl, CFArrayRef applicationList)
224 {
225 ACL::ApplicationList &appList = acl->applications();
226 appList.clear();
227 //@@@ should really use STL iterator overlay on CFArray. By hand...
228 CFIndex count = CFArrayGetCount(applicationList);
229 for (CFIndex n = 0; n < count; n++)
230 appList.push_back(TrustedApplication::required(
231 SecTrustedApplicationRef(CFArrayGetValueAtIndex(applicationList, n))));
232 }
233
234
235 //
236 // Set and get the authorization tags of an ACL entry
237 //
238 OSStatus SecACLGetAuthorizations(SecACLRef acl,
239 CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 *tagCount)
240 {
241 BEGIN_SECAPI
242 AclAuthorizationSet auths = ACL::required(acl)->authorizations();
243 if (Required(tagCount) < auths.size()) { // overflow
244 *tagCount = (uint32)auths.size(); // report size required
245 CssmError::throwMe(errSecParam);
246 }
247 *tagCount = (uint32)auths.size();
248 copy(auths.begin(), auths.end(), tags);
249 END_SECAPI
250 }
251
252 CFArrayRef SecACLCopyAuthorizations(SecACLRef acl)
253 {
254 CFArrayRef result = NULL;
255 if (NULL == acl)
256 {
257 return result;
258 }
259
260 AclAuthorizationSet auths = ACL::required(acl)->authorizations();
261 uint32 numAuths = (uint32)auths.size();
262
263 CSSM_ACL_AUTHORIZATION_TAG* tags = new CSSM_ACL_AUTHORIZATION_TAG[numAuths];
264 int i;
265 for (i = 0; i < numAuths; ++i)
266 {
267 tags[i] = NULL;
268 }
269
270 OSStatus err = SecACLGetAuthorizations(acl, tags, &numAuths);
271 if (errSecSuccess != err)
272 {
273
274 return result;
275 }
276
277 CFTypeRef* strings = new CFTypeRef[numAuths];
278 for (i = 0; i < numAuths; ++i)
279 {
280 strings[i] = NULL;
281 }
282
283 for (size_t iCnt = 0; iCnt < numAuths; iCnt++)
284 {
285 strings[iCnt] = (CFTypeRef)GetAuthStringFromACLAuthorizationTag(tags[iCnt]);
286 }
287
288 result = CFArrayCreate(kCFAllocatorDefault, (const void **)strings, numAuths, &kCFTypeArrayCallBacks);
289
290 delete[] strings;
291 delete[] tags;
292
293 return result;
294
295 }
296
297 OSStatus SecACLSetAuthorizations(SecACLRef aclRef,
298 CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 tagCount)
299 {
300 BEGIN_SECAPI
301 os_activity_t activity = os_activity_create("SecACLSetAuthorizations", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
302 os_activity_scope(activity);
303 os_release(activity);
304 SecPointer<ACL> acl = ACL::required(aclRef);
305 if (acl->isOwner()) // can't change rights of the owner ACL
306 MacOSError::throwMe(errSecInvalidOwnerEdit);
307 AclAuthorizationSet &auths = acl->authorizations();
308 auths.clear();
309 copy(tags, tags + tagCount, insert_iterator<AclAuthorizationSet>(auths, auths.begin()));
310 acl->modify();
311 END_SECAPI
312 }
313
314 OSStatus SecACLUpdateAuthorizations(SecACLRef acl, CFArrayRef authorizations)
315 {
316 if (NULL == acl || NULL == authorizations)
317 {
318 return errSecParam;
319 }
320 uint32 tagCount = (uint32)CFArrayGetCount(authorizations);
321
322 size_t tagSize = (tagCount * sizeof(CSSM_ACL_AUTHORIZATION_TAG));
323
324 CSSM_ACL_AUTHORIZATION_TAG* tags = (CSSM_ACL_AUTHORIZATION_TAG*)malloc(tagSize);
325 memset(tags, 0, tagSize);
326 for (uint32 iCnt = 0; iCnt < tagCount; iCnt++)
327 {
328 tags[iCnt] = GetACLAuthorizationTagFromString((CFStringRef)CFArrayGetValueAtIndex(authorizations, iCnt));
329 }
330
331 OSStatus result = SecACLSetAuthorizations(acl, tags, tagCount);
332 free(tags);
333 return result;
334 }