]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/lib/SecACL.cpp
Security-57337.40.85.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 "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(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 makeCFArrayFrom(convert, acl->applications());
129 Required(promptDescription) = makeCFString(acl->promptDescription());
130 Required(promptSelector) = acl->promptSelector();
131 break;
132 case ACL::integrityForm:
133 Required(applicationList) = NULL;
134 Required(promptDescription) = makeCFString(acl->integrity().toHex());
135
136 // We don't have a prompt selector. Nullify.
137 Required(promptSelector).version = CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION;
138 Required(promptSelector).flags = 0;
139 break;
140 default:
141 return errSecACLNotSimple; // custom or unknown
142 }
143 END_SECAPI
144 }
145
146 OSStatus SecACLCopyContents(SecACLRef acl,
147 CFArrayRef *applicationList,
148 CFStringRef *description,
149 SecKeychainPromptSelector *promptSelector)
150 {
151 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector;
152 memset(&cdsaPromptSelector, 0, sizeof(cdsaPromptSelector));
153 OSStatus err = errSecSuccess;
154
155 err = SecACLCopySimpleContents(acl, applicationList, description, &cdsaPromptSelector);
156 *promptSelector = cdsaPromptSelector.flags;
157 return err;
158 }
159
160 OSStatus SecACLSetSimpleContents(SecACLRef aclRef,
161 CFArrayRef applicationList,
162 CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector)
163 {
164 BEGIN_SECAPI
165 SecPointer<ACL> acl = ACL::required(aclRef);
166 if(acl->form() == ACL::integrityForm) {
167 // If this is an integrity ACL, route the (unhexified) promptDescription into the right place
168 string hex = cfString(description);
169 if(hex.length() %2 == 0) {
170 // might be a valid hex string, try to set
171 CssmAutoData data(Allocator::standard());
172 data.malloc(hex.length() / 2);
173 data.get().fromHex(hex.c_str());
174 acl->setIntegrity(data);
175 }
176 } else {
177 // Otherwise, put it in the promptDescription where it belongs
178 acl->promptDescription() = description ? cfString(description) : "";
179 }
180 acl->promptSelector() = promptSelector ? *promptSelector : ACL::defaultSelector;
181 if(acl->form() != ACL::integrityForm) {
182 if (applicationList) {
183 // application-list + prompt
184 acl->form(ACL::appListForm);
185 setApplications(acl, applicationList);
186 } else {
187 // allow-any
188 acl->form(ACL::allowAllForm);
189 }
190 }
191 acl->modify();
192 END_SECAPI
193 }
194
195 OSStatus SecACLSetContents(SecACLRef acl,
196 CFArrayRef applicationList,
197 CFStringRef description,
198 SecKeychainPromptSelector promptSelector)
199 {
200 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector;
201 cdsaPromptSelector.version = CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION;
202 cdsaPromptSelector.flags = promptSelector;
203 return SecACLSetSimpleContents(acl, applicationList, description, &cdsaPromptSelector);
204 }
205
206 //
207 // Stuff a CFArray-of-SecTrustedApplications into an ACL object
208 //
209 static void setApplications(ACL *acl, CFArrayRef applicationList)
210 {
211 ACL::ApplicationList &appList = acl->applications();
212 appList.clear();
213 //@@@ should really use STL iterator overlay on CFArray. By hand...
214 CFIndex count = CFArrayGetCount(applicationList);
215 for (CFIndex n = 0; n < count; n++)
216 appList.push_back(TrustedApplication::required(
217 SecTrustedApplicationRef(CFArrayGetValueAtIndex(applicationList, n))));
218 }
219
220
221 //
222 // Set and get the authorization tags of an ACL entry
223 //
224 OSStatus SecACLGetAuthorizations(SecACLRef acl,
225 CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 *tagCount)
226 {
227 BEGIN_SECAPI
228 AclAuthorizationSet auths = ACL::required(acl)->authorizations();
229 if (Required(tagCount) < auths.size()) { // overflow
230 *tagCount = (uint32)auths.size(); // report size required
231 CssmError::throwMe(errSecParam);
232 }
233 *tagCount = (uint32)auths.size();
234 copy(auths.begin(), auths.end(), tags);
235 END_SECAPI
236 }
237
238 CFArrayRef SecACLCopyAuthorizations(SecACLRef acl)
239 {
240 CFArrayRef result = NULL;
241 if (NULL == acl)
242 {
243 return result;
244 }
245
246 AclAuthorizationSet auths = ACL::required(acl)->authorizations();
247 uint32 numAuths = (uint32)auths.size();
248
249 CSSM_ACL_AUTHORIZATION_TAG* tags = new CSSM_ACL_AUTHORIZATION_TAG[numAuths];
250 int i;
251 for (i = 0; i < numAuths; ++i)
252 {
253 tags[i] = NULL;
254 }
255
256 OSStatus err = SecACLGetAuthorizations(acl, tags, &numAuths);
257 if (errSecSuccess != err)
258 {
259
260 return result;
261 }
262
263 CFTypeRef* strings = new CFTypeRef[numAuths];
264 for (i = 0; i < numAuths; ++i)
265 {
266 strings[i] = NULL;
267 }
268
269 for (size_t iCnt = 0; iCnt < numAuths; iCnt++)
270 {
271 strings[iCnt] = (CFTypeRef)GetAuthStringFromACLAuthorizationTag(tags[iCnt]);
272 }
273
274 result = CFArrayCreate(kCFAllocatorDefault, (const void **)strings, numAuths, &kCFTypeArrayCallBacks);
275
276 delete[] strings;
277 delete[] tags;
278
279 return result;
280
281 }
282
283 OSStatus SecACLSetAuthorizations(SecACLRef aclRef,
284 CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 tagCount)
285 {
286 BEGIN_SECAPI
287 SecPointer<ACL> acl = ACL::required(aclRef);
288 if (acl->isOwner()) // can't change rights of the owner ACL
289 MacOSError::throwMe(errSecInvalidOwnerEdit);
290 AclAuthorizationSet &auths = acl->authorizations();
291 auths.clear();
292 copy(tags, tags + tagCount, insert_iterator<AclAuthorizationSet>(auths, auths.begin()));
293 acl->modify();
294 END_SECAPI
295 }
296
297 OSStatus SecACLUpdateAuthorizations(SecACLRef acl, CFArrayRef authorizations)
298 {
299 if (NULL == acl || NULL == authorizations)
300 {
301 return errSecParam;
302 }
303 uint32 tagCount = (uint32)CFArrayGetCount(authorizations);
304
305 size_t tagSize = (tagCount * sizeof(CSSM_ACL_AUTHORIZATION_TAG));
306
307 CSSM_ACL_AUTHORIZATION_TAG* tags = (CSSM_ACL_AUTHORIZATION_TAG*)malloc(tagSize);
308 memset(tags, 0, tagSize);
309 for (uint32 iCnt = 0; iCnt < tagCount; iCnt++)
310 {
311 tags[iCnt] = GetACLAuthorizationTagFromString((CFStringRef)CFArrayGetValueAtIndex(authorizations, iCnt));
312 }
313
314 OSStatus result = SecACLSetAuthorizations(acl, tags, tagCount);
315 free(tags);
316 return result;
317 }