]> git.saurik.com Git - apple/security.git/blame - Security/libsecurity_keychain/lib/SecACL.cpp
Security-57031.30.12.tar.gz
[apple/security.git] / Security / libsecurity_keychain / lib / SecACL.cpp
CommitLineData
b1ab9ed8 1/*
d8f41ccd 2 * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved.
b1ab9ed8
A
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*/
38sint32 GetACLAuthorizationTagFromString(CFStringRef aclStr);
39
40CFStringRef GetAuthStringFromACLAuthorizationTag(sint32 tag);
41
42//
43// Local functions
44//
45static void setApplications(ACL *acl, CFArrayRef applicationList);
46
47CFTypeID
48SecACLGetTypeID(void)
49{
50 BEGIN_SECAPI
51
52 return gTypes().ACL.typeID;
53
54 END_SECAPI1(_kCFRuntimeNotATypeID)
55}
56
57
58/*!
59 */
60OSStatus 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
81OSStatus 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 */
96OSStatus SecACLRemove(SecACLRef aclRef)
97{
98 BEGIN_SECAPI
99 ACL::required(aclRef)->remove();
100 END_SECAPI
101}
102
103
104static SecTrustedApplicationRef
105convert(const SecPointer<TrustedApplication> &trustedApplication)
106{
107 return *trustedApplication;
108}
109
110/*!
111 */
112OSStatus 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
138OSStatus 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));
427c49bc 145 OSStatus err = errSecSuccess;
b1ab9ed8
A
146
147 err = SecACLCopySimpleContents(acl, applicationList, description, &cdsaPromptSelector);
148 *promptSelector = cdsaPromptSelector.flags;
149 return err;
150}
151
152OSStatus 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
172OSStatus 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//
186static 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//
201OSStatus 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
427c49bc
A
207 *tagCount = (uint32)auths.size(); // report size required
208 CssmError::throwMe(errSecParam);
b1ab9ed8 209 }
427c49bc 210 *tagCount = (uint32)auths.size();
b1ab9ed8
A
211 copy(auths.begin(), auths.end(), tags);
212 END_SECAPI
213}
214
215CFArrayRef 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();
427c49bc 224 uint32 numAuths = (uint32)auths.size();
b1ab9ed8
A
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);
427c49bc 234 if (errSecSuccess != err)
b1ab9ed8
A
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
260OSStatus 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
274OSStatus SecACLUpdateAuthorizations(SecACLRef acl, CFArrayRef authorizations)
275{
276 if (NULL == acl || NULL == authorizations)
277 {
427c49bc 278 return errSecParam;
b1ab9ed8 279 }
427c49bc 280 uint32 tagCount = (uint32)CFArrayGetCount(authorizations);
b1ab9ed8
A
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}