]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/lib/SecACL.cpp
Security-59754.41.1.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 #include "LegacyAPICounts.h"
34
35 // Forward reference
36 /*!
37 @function GetACLAuthorizationTagFromString
38 @abstract Get the CSSM ACL item from the CFString
39 @param aclStr The String name of the ACL
40 @result The CSSM ACL value
41 */
42 sint32 GetACLAuthorizationTagFromString(CFStringRef aclStr);
43
44 CFStringRef GetAuthStringFromACLAuthorizationTag(sint32 tag);
45
46 //
47 // Local functions
48 //
49 static void setApplications(ACL *acl, CFArrayRef applicationList);
50
51 CFTypeID
52 SecACLGetTypeID(void)
53 {
54 BEGIN_SECAPI
55
56 return gTypes().ACL.typeID;
57
58 END_SECAPI1(_kCFRuntimeNotATypeID)
59 }
60
61
62 /*!
63 */
64 OSStatus SecACLCreateFromSimpleContents(SecAccessRef accessRef,
65 CFArrayRef applicationList,
66 CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector,
67 SecACLRef *newAcl)
68 {
69 BEGIN_SECAPI
70 os_activity_t activity = os_activity_create("SecACLCreateFromSimpleContents", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
71 os_activity_scope(activity);
72 os_release(activity);
73 SecPointer<Access> access = Access::required(accessRef);
74 SecPointer<ACL> acl = new ACL(cfString(description), *promptSelector);
75 if (applicationList) {
76 // application-list + prompt
77 acl->form(ACL::appListForm);
78 setApplications(acl, applicationList);
79 } else {
80 // allow-any
81 acl->form(ACL::allowAllForm);
82 }
83 access->add(acl.get());
84 Required(newAcl) = acl->handle();
85 END_SECAPI
86 }
87
88 OSStatus SecACLCreateWithSimpleContents(SecAccessRef access,
89 CFArrayRef applicationList,
90 CFStringRef description,
91 SecKeychainPromptSelector promptSelector,
92 SecACLRef *newAcl)
93 {
94 COUNTLEGACYAPI
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 COUNTLEGACYAPI
163 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector;
164 memset(&cdsaPromptSelector, 0, sizeof(cdsaPromptSelector));
165 OSStatus err = errSecSuccess;
166
167 err = SecACLCopySimpleContents(acl, applicationList, description, &cdsaPromptSelector);
168 *promptSelector = cdsaPromptSelector.flags;
169 return err;
170 }
171
172 OSStatus SecACLSetSimpleContents(SecACLRef aclRef,
173 CFArrayRef applicationList,
174 CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector)
175 {
176 BEGIN_SECAPI
177 os_activity_t activity = os_activity_create("SecACLSetSimpleContents", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
178 os_activity_scope(activity);
179 os_release(activity);
180 SecPointer<ACL> acl = ACL::required(aclRef);
181 if(acl->form() == ACL::integrityForm) {
182 // If this is an integrity ACL, route the (unhexified) promptDescription into the right place
183 string hex = cfString(description);
184 if(hex.length() %2 == 0) {
185 // might be a valid hex string, try to set
186 CssmAutoData data(Allocator::standard());
187 data.malloc(hex.length() / 2);
188 data.get().fromHex(hex.c_str());
189 acl->setIntegrity(data);
190 }
191 } else {
192 // Otherwise, put it in the promptDescription where it belongs
193 acl->promptDescription() = description ? cfString(description) : "";
194 }
195 acl->promptSelector() = promptSelector ? *promptSelector : ACL::defaultSelector;
196 if(acl->form() != ACL::integrityForm) {
197 if (applicationList) {
198 // application-list + prompt
199 acl->form(ACL::appListForm);
200 setApplications(acl, applicationList);
201 } else {
202 // allow-any
203 acl->form(ACL::allowAllForm);
204 }
205 }
206 acl->modify();
207 END_SECAPI
208 }
209
210 OSStatus SecACLSetContents(SecACLRef acl,
211 CFArrayRef applicationList,
212 CFStringRef description,
213 SecKeychainPromptSelector promptSelector)
214 {
215 COUNTLEGACYAPI
216 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector;
217 cdsaPromptSelector.version = CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION;
218 cdsaPromptSelector.flags = promptSelector;
219 return SecACLSetSimpleContents(acl, applicationList, description, &cdsaPromptSelector);
220 }
221
222 //
223 // Stuff a CFArray-of-SecTrustedApplications into an ACL object
224 //
225 static void setApplications(ACL *acl, CFArrayRef applicationList)
226 {
227 ACL::ApplicationList &appList = acl->applications();
228 appList.clear();
229 //@@@ should really use STL iterator overlay on CFArray. By hand...
230 CFIndex count = CFArrayGetCount(applicationList);
231 for (CFIndex n = 0; n < count; n++)
232 appList.push_back(TrustedApplication::required(
233 SecTrustedApplicationRef(CFArrayGetValueAtIndex(applicationList, n))));
234 }
235
236
237 //
238 // Set and get the authorization tags of an ACL entry
239 //
240 OSStatus SecACLGetAuthorizations(SecACLRef acl,
241 CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 *tagCount)
242 {
243 BEGIN_SECAPI
244 AclAuthorizationSet auths = ACL::required(acl)->authorizations();
245 if (Required(tagCount) < auths.size()) { // overflow
246 *tagCount = (uint32)auths.size(); // report size required
247 CssmError::throwMe(errSecParam);
248 }
249 *tagCount = (uint32)auths.size();
250 copy(auths.begin(), auths.end(), tags);
251 END_SECAPI
252 }
253
254 CFArrayRef SecACLCopyAuthorizations(SecACLRef acl)
255 {
256 COUNTLEGACYAPI
257 CFArrayRef result = NULL;
258 if (NULL == acl)
259 {
260 return result;
261 }
262
263 AclAuthorizationSet auths = ACL::required(acl)->authorizations();
264 uint32 numAuths = (uint32)auths.size();
265
266 CSSM_ACL_AUTHORIZATION_TAG* tags = new CSSM_ACL_AUTHORIZATION_TAG[numAuths];
267 int i;
268 for (i = 0; i < numAuths; ++i)
269 {
270 tags[i] = NULL;
271 }
272
273 OSStatus err = SecACLGetAuthorizations(acl, tags, &numAuths);
274 if (errSecSuccess != err)
275 {
276
277 return result;
278 }
279
280 CFTypeRef* strings = new CFTypeRef[numAuths];
281 for (i = 0; i < numAuths; ++i)
282 {
283 strings[i] = NULL;
284 }
285
286 for (size_t iCnt = 0; iCnt < numAuths; iCnt++)
287 {
288 strings[iCnt] = (CFTypeRef)GetAuthStringFromACLAuthorizationTag(tags[iCnt]);
289 }
290
291 result = CFArrayCreate(kCFAllocatorDefault, (const void **)strings, numAuths, &kCFTypeArrayCallBacks);
292
293 delete[] strings;
294 delete[] tags;
295
296 return result;
297
298 }
299
300 OSStatus SecACLSetAuthorizations(SecACLRef aclRef,
301 CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 tagCount)
302 {
303 BEGIN_SECAPI
304 os_activity_t activity = os_activity_create("SecACLSetAuthorizations", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
305 os_activity_scope(activity);
306 os_release(activity);
307 SecPointer<ACL> acl = ACL::required(aclRef);
308 if (acl->isOwner()) // can't change rights of the owner ACL
309 MacOSError::throwMe(errSecInvalidOwnerEdit);
310 AclAuthorizationSet &auths = acl->authorizations();
311 auths.clear();
312 copy(tags, tags + tagCount, insert_iterator<AclAuthorizationSet>(auths, auths.begin()));
313 acl->modify();
314 END_SECAPI
315 }
316
317 OSStatus SecACLUpdateAuthorizations(SecACLRef acl, CFArrayRef authorizations)
318 {
319 COUNTLEGACYAPI
320 if (NULL == acl || NULL == authorizations)
321 {
322 return errSecParam;
323 }
324 uint32 tagCount = (uint32)CFArrayGetCount(authorizations);
325
326 size_t tagSize = (tagCount * sizeof(CSSM_ACL_AUTHORIZATION_TAG));
327
328 CSSM_ACL_AUTHORIZATION_TAG* tags = (CSSM_ACL_AUTHORIZATION_TAG*)malloc(tagSize);
329 memset(tags, 0, tagSize);
330 for (uint32 iCnt = 0; iCnt < tagCount; iCnt++)
331 {
332 tags[iCnt] = GetACLAuthorizationTagFromString((CFStringRef)CFArrayGetValueAtIndex(authorizations, iCnt));
333 }
334
335 OSStatus result = SecACLSetAuthorizations(acl, tags, tagCount);
336 free(tags);
337 return result;
338 }