]>
Commit | Line | Data |
---|---|---|
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 | */ | |
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)); | |
427c49bc | 145 | OSStatus err = errSecSuccess; |
b1ab9ed8 A |
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 | |
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 | ||
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(); | |
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 | ||
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 | { | |
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 | } |