2 * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <Security/SecACL.h>
25 #include <security_keychain/ACL.h>
26 #include <security_keychain/Access.h>
27 #include <security_keychain/SecAccessPriv.h>
29 #include <os/activity.h>
31 #include "SecBridge.h"
33 #include "LegacyAPICounts.h"
37 @function GetACLAuthorizationTagFromString
38 @abstract Get the CSSM ACL item from the CFString
39 @param aclStr The String name of the ACL
40 @result The CSSM ACL value
42 sint32
GetACLAuthorizationTagFromString(CFStringRef aclStr
);
44 CFStringRef
GetAuthStringFromACLAuthorizationTag(sint32 tag
);
49 static void setApplications(ACL
*acl
, CFArrayRef applicationList
);
56 return gTypes().ACL
.typeID
;
58 END_SECAPI1(_kCFRuntimeNotATypeID
)
64 OSStatus
SecACLCreateFromSimpleContents(SecAccessRef accessRef
,
65 CFArrayRef applicationList
,
66 CFStringRef description
, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR
*promptSelector
,
70 os_activity_t activity
= os_activity_create("SecACLCreateFromSimpleContents", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
71 os_activity_scope(activity
);
73 SecPointer
<Access
> access
= Access::required(accessRef
);
74 SecPointer
<ACL
> acl
= new ACL(cfString(description
), *promptSelector
);
75 if (applicationList
) {
76 // application-list + prompt
77 acl
->form(ACL::appListForm
);
78 setApplications(acl
, applicationList
);
81 acl
->form(ACL::allowAllForm
);
83 access
->add(acl
.get());
84 Required(newAcl
) = acl
->handle();
88 OSStatus
SecACLCreateWithSimpleContents(SecAccessRef access
,
89 CFArrayRef applicationList
,
90 CFStringRef description
,
91 SecKeychainPromptSelector promptSelector
,
95 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector
;
96 cdsaPromptSelector
.version
= CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION
;
97 cdsaPromptSelector
.flags
= promptSelector
;
98 return SecACLCreateFromSimpleContents(access
, applicationList
, description
, &cdsaPromptSelector
, newAcl
);
104 OSStatus
SecACLRemove(SecACLRef aclRef
)
107 os_activity_t activity
= os_activity_create("SecACLRemove", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
108 os_activity_scope(activity
);
109 os_release(activity
);
110 ACL::required(aclRef
)->remove();
115 static SecTrustedApplicationRef
116 convert(const SecPointer
<TrustedApplication
> &trustedApplication
)
118 return *trustedApplication
;
123 OSStatus
SecACLCopySimpleContents(SecACLRef aclRef
,
124 CFArrayRef
*applicationList
,
125 CFStringRef
*promptDescription
, CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR
*promptSelector
)
128 SecPointer
<ACL
> acl
= ACL::required(aclRef
);
129 switch (acl
->form()) {
130 case ACL::allowAllForm
:
131 Required(applicationList
) = NULL
;
132 Required(promptDescription
) =
133 acl
->promptDescription().empty() ? NULL
134 : makeCFString(acl
->promptDescription());
135 Required(promptSelector
) = acl
->promptSelector();
137 case ACL::appListForm
:
138 Required(applicationList
) =
139 makeCFArrayFrom(convert
, acl
->applications());
140 Required(promptDescription
) = makeCFString(acl
->promptDescription());
141 Required(promptSelector
) = acl
->promptSelector();
143 case ACL::integrityForm
:
144 Required(applicationList
) = NULL
;
145 Required(promptDescription
) = makeCFString(acl
->integrity().toHex());
147 // We don't have a prompt selector. Nullify.
148 Required(promptSelector
).version
= CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION
;
149 Required(promptSelector
).flags
= 0;
152 return errSecACLNotSimple
; // custom or unknown
157 OSStatus
SecACLCopyContents(SecACLRef acl
,
158 CFArrayRef
*applicationList
,
159 CFStringRef
*description
,
160 SecKeychainPromptSelector
*promptSelector
)
163 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector
;
164 memset(&cdsaPromptSelector
, 0, sizeof(cdsaPromptSelector
));
165 OSStatus err
= errSecSuccess
;
167 err
= SecACLCopySimpleContents(acl
, applicationList
, description
, &cdsaPromptSelector
);
168 *promptSelector
= cdsaPromptSelector
.flags
;
172 OSStatus
SecACLSetSimpleContents(SecACLRef aclRef
,
173 CFArrayRef applicationList
,
174 CFStringRef description
, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR
*promptSelector
)
177 os_activity_t activity
= os_activity_create("SecACLSetSimpleContents", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
178 os_activity_scope(activity
);
179 os_release(activity
);
180 SecPointer
<ACL
> acl
= ACL::required(aclRef
);
181 if(acl
->form() == ACL::integrityForm
) {
182 // If this is an integrity ACL, route the (unhexified) promptDescription into the right place
183 string hex
= cfString(description
);
184 if(hex
.length() %2
== 0) {
185 // might be a valid hex string, try to set
186 CssmAutoData
data(Allocator::standard());
187 data
.malloc(hex
.length() / 2);
188 data
.get().fromHex(hex
.c_str());
189 acl
->setIntegrity(data
);
192 // Otherwise, put it in the promptDescription where it belongs
193 acl
->promptDescription() = description
? cfString(description
) : "";
195 acl
->promptSelector() = promptSelector
? *promptSelector
: ACL::defaultSelector
;
196 if(acl
->form() != ACL::integrityForm
) {
197 if (applicationList
) {
198 // application-list + prompt
199 acl
->form(ACL::appListForm
);
200 setApplications(acl
, applicationList
);
203 acl
->form(ACL::allowAllForm
);
210 OSStatus
SecACLSetContents(SecACLRef acl
,
211 CFArrayRef applicationList
,
212 CFStringRef description
,
213 SecKeychainPromptSelector promptSelector
)
216 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector
;
217 cdsaPromptSelector
.version
= CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION
;
218 cdsaPromptSelector
.flags
= promptSelector
;
219 return SecACLSetSimpleContents(acl
, applicationList
, description
, &cdsaPromptSelector
);
223 // Stuff a CFArray-of-SecTrustedApplications into an ACL object
225 static void setApplications(ACL
*acl
, CFArrayRef applicationList
)
227 ACL::ApplicationList
&appList
= acl
->applications();
229 //@@@ should really use STL iterator overlay on CFArray. By hand...
230 CFIndex count
= CFArrayGetCount(applicationList
);
231 for (CFIndex n
= 0; n
< count
; n
++)
232 appList
.push_back(TrustedApplication::required(
233 SecTrustedApplicationRef(CFArrayGetValueAtIndex(applicationList
, n
))));
238 // Set and get the authorization tags of an ACL entry
240 OSStatus
SecACLGetAuthorizations(SecACLRef acl
,
241 CSSM_ACL_AUTHORIZATION_TAG
*tags
, uint32
*tagCount
)
244 AclAuthorizationSet auths
= ACL::required(acl
)->authorizations();
245 if (Required(tagCount
) < auths
.size()) { // overflow
246 *tagCount
= (uint32
)auths
.size(); // report size required
247 CssmError::throwMe(errSecParam
);
249 *tagCount
= (uint32
)auths
.size();
250 copy(auths
.begin(), auths
.end(), tags
);
254 CFArrayRef
SecACLCopyAuthorizations(SecACLRef acl
)
257 CFArrayRef result
= NULL
;
263 AclAuthorizationSet auths
= ACL::required(acl
)->authorizations();
264 uint32 numAuths
= (uint32
)auths
.size();
266 CSSM_ACL_AUTHORIZATION_TAG
* tags
= new CSSM_ACL_AUTHORIZATION_TAG
[numAuths
];
268 for (i
= 0; i
< numAuths
; ++i
)
273 OSStatus err
= SecACLGetAuthorizations(acl
, tags
, &numAuths
);
274 if (errSecSuccess
!= err
)
280 CFTypeRef
* strings
= new CFTypeRef
[numAuths
];
281 for (i
= 0; i
< numAuths
; ++i
)
286 for (size_t iCnt
= 0; iCnt
< numAuths
; iCnt
++)
288 strings
[iCnt
] = (CFTypeRef
)GetAuthStringFromACLAuthorizationTag(tags
[iCnt
]);
291 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)strings
, numAuths
, &kCFTypeArrayCallBacks
);
300 OSStatus
SecACLSetAuthorizations(SecACLRef aclRef
,
301 CSSM_ACL_AUTHORIZATION_TAG
*tags
, uint32 tagCount
)
304 os_activity_t activity
= os_activity_create("SecACLSetAuthorizations", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
305 os_activity_scope(activity
);
306 os_release(activity
);
307 SecPointer
<ACL
> acl
= ACL::required(aclRef
);
308 if (acl
->isOwner()) // can't change rights of the owner ACL
309 MacOSError::throwMe(errSecInvalidOwnerEdit
);
310 AclAuthorizationSet
&auths
= acl
->authorizations();
312 copy(tags
, tags
+ tagCount
, insert_iterator
<AclAuthorizationSet
>(auths
, auths
.begin()));
317 OSStatus
SecACLUpdateAuthorizations(SecACLRef acl
, CFArrayRef authorizations
)
320 if (NULL
== acl
|| NULL
== authorizations
)
324 uint32 tagCount
= (uint32
)CFArrayGetCount(authorizations
);
326 size_t tagSize
= (tagCount
* sizeof(CSSM_ACL_AUTHORIZATION_TAG
));
328 CSSM_ACL_AUTHORIZATION_TAG
* tags
= (CSSM_ACL_AUTHORIZATION_TAG
*)malloc(tagSize
);
329 memset(tags
, 0, tagSize
);
330 for (uint32 iCnt
= 0; iCnt
< tagCount
; iCnt
++)
332 tags
[iCnt
] = GetACLAuthorizationTagFromString((CFStringRef
)CFArrayGetValueAtIndex(authorizations
, iCnt
));
335 OSStatus result
= SecACLSetAuthorizations(acl
, tags
, tagCount
);