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