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