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"
35 @function GetACLAuthorizationTagFromString
36 @abstract Get the CSSM ACL item from the CFString
37 @param aclStr The String name of the ACL
38 @result The CSSM ACL value
40 sint32
GetACLAuthorizationTagFromString(CFStringRef aclStr
);
42 CFStringRef
GetAuthStringFromACLAuthorizationTag(sint32 tag
);
47 static void setApplications(ACL
*acl
, CFArrayRef applicationList
);
54 return gTypes().ACL
.typeID
;
56 END_SECAPI1(_kCFRuntimeNotATypeID
)
62 OSStatus
SecACLCreateFromSimpleContents(SecAccessRef accessRef
,
63 CFArrayRef applicationList
,
64 CFStringRef description
, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR
*promptSelector
,
68 os_activity_t activity
= os_activity_create("SecACLCreateFromSimpleContents", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
69 os_activity_scope(activity
);
71 SecPointer
<Access
> access
= Access::required(accessRef
);
72 SecPointer
<ACL
> acl
= new ACL(cfString(description
), *promptSelector
);
73 if (applicationList
) {
74 // application-list + prompt
75 acl
->form(ACL::appListForm
);
76 setApplications(acl
, applicationList
);
79 acl
->form(ACL::allowAllForm
);
81 access
->add(acl
.get());
82 Required(newAcl
) = acl
->handle();
86 OSStatus
SecACLCreateWithSimpleContents(SecAccessRef access
,
87 CFArrayRef applicationList
,
88 CFStringRef description
,
89 SecKeychainPromptSelector promptSelector
,
92 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector
;
93 cdsaPromptSelector
.version
= CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION
;
94 cdsaPromptSelector
.flags
= promptSelector
;
95 return SecACLCreateFromSimpleContents(access
, applicationList
, description
, &cdsaPromptSelector
, newAcl
);
101 OSStatus
SecACLRemove(SecACLRef aclRef
)
104 os_activity_t activity
= os_activity_create("SecACLRemove", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
105 os_activity_scope(activity
);
106 os_release(activity
);
107 ACL::required(aclRef
)->remove();
112 static SecTrustedApplicationRef
113 convert(const SecPointer
<TrustedApplication
> &trustedApplication
)
115 return *trustedApplication
;
120 OSStatus
SecACLCopySimpleContents(SecACLRef aclRef
,
121 CFArrayRef
*applicationList
,
122 CFStringRef
*promptDescription
, CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR
*promptSelector
)
125 SecPointer
<ACL
> acl
= ACL::required(aclRef
);
126 switch (acl
->form()) {
127 case ACL::allowAllForm
:
128 Required(applicationList
) = NULL
;
129 Required(promptDescription
) =
130 acl
->promptDescription().empty() ? NULL
131 : makeCFString(acl
->promptDescription());
132 Required(promptSelector
) = acl
->promptSelector();
134 case ACL::appListForm
:
135 Required(applicationList
) =
136 makeCFArrayFrom(convert
, acl
->applications());
137 Required(promptDescription
) = makeCFString(acl
->promptDescription());
138 Required(promptSelector
) = acl
->promptSelector();
140 case ACL::integrityForm
:
141 Required(applicationList
) = NULL
;
142 Required(promptDescription
) = makeCFString(acl
->integrity().toHex());
144 // We don't have a prompt selector. Nullify.
145 Required(promptSelector
).version
= CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION
;
146 Required(promptSelector
).flags
= 0;
149 return errSecACLNotSimple
; // custom or unknown
154 OSStatus
SecACLCopyContents(SecACLRef acl
,
155 CFArrayRef
*applicationList
,
156 CFStringRef
*description
,
157 SecKeychainPromptSelector
*promptSelector
)
159 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector
;
160 memset(&cdsaPromptSelector
, 0, sizeof(cdsaPromptSelector
));
161 OSStatus err
= errSecSuccess
;
163 err
= SecACLCopySimpleContents(acl
, applicationList
, description
, &cdsaPromptSelector
);
164 *promptSelector
= cdsaPromptSelector
.flags
;
168 OSStatus
SecACLSetSimpleContents(SecACLRef aclRef
,
169 CFArrayRef applicationList
,
170 CFStringRef description
, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR
*promptSelector
)
173 os_activity_t activity
= os_activity_create("SecACLSetSimpleContents", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
174 os_activity_scope(activity
);
175 os_release(activity
);
176 SecPointer
<ACL
> acl
= ACL::required(aclRef
);
177 if(acl
->form() == ACL::integrityForm
) {
178 // If this is an integrity ACL, route the (unhexified) promptDescription into the right place
179 string hex
= cfString(description
);
180 if(hex
.length() %2
== 0) {
181 // might be a valid hex string, try to set
182 CssmAutoData
data(Allocator::standard());
183 data
.malloc(hex
.length() / 2);
184 data
.get().fromHex(hex
.c_str());
185 acl
->setIntegrity(data
);
188 // Otherwise, put it in the promptDescription where it belongs
189 acl
->promptDescription() = description
? cfString(description
) : "";
191 acl
->promptSelector() = promptSelector
? *promptSelector
: ACL::defaultSelector
;
192 if(acl
->form() != ACL::integrityForm
) {
193 if (applicationList
) {
194 // application-list + prompt
195 acl
->form(ACL::appListForm
);
196 setApplications(acl
, applicationList
);
199 acl
->form(ACL::allowAllForm
);
206 OSStatus
SecACLSetContents(SecACLRef acl
,
207 CFArrayRef applicationList
,
208 CFStringRef description
,
209 SecKeychainPromptSelector promptSelector
)
211 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector
;
212 cdsaPromptSelector
.version
= CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION
;
213 cdsaPromptSelector
.flags
= promptSelector
;
214 return SecACLSetSimpleContents(acl
, applicationList
, description
, &cdsaPromptSelector
);
218 // Stuff a CFArray-of-SecTrustedApplications into an ACL object
220 static void setApplications(ACL
*acl
, CFArrayRef applicationList
)
222 ACL::ApplicationList
&appList
= acl
->applications();
224 //@@@ should really use STL iterator overlay on CFArray. By hand...
225 CFIndex count
= CFArrayGetCount(applicationList
);
226 for (CFIndex n
= 0; n
< count
; n
++)
227 appList
.push_back(TrustedApplication::required(
228 SecTrustedApplicationRef(CFArrayGetValueAtIndex(applicationList
, n
))));
233 // Set and get the authorization tags of an ACL entry
235 OSStatus
SecACLGetAuthorizations(SecACLRef acl
,
236 CSSM_ACL_AUTHORIZATION_TAG
*tags
, uint32
*tagCount
)
239 AclAuthorizationSet auths
= ACL::required(acl
)->authorizations();
240 if (Required(tagCount
) < auths
.size()) { // overflow
241 *tagCount
= (uint32
)auths
.size(); // report size required
242 CssmError::throwMe(errSecParam
);
244 *tagCount
= (uint32
)auths
.size();
245 copy(auths
.begin(), auths
.end(), tags
);
249 CFArrayRef
SecACLCopyAuthorizations(SecACLRef acl
)
251 CFArrayRef result
= NULL
;
257 AclAuthorizationSet auths
= ACL::required(acl
)->authorizations();
258 uint32 numAuths
= (uint32
)auths
.size();
260 CSSM_ACL_AUTHORIZATION_TAG
* tags
= new CSSM_ACL_AUTHORIZATION_TAG
[numAuths
];
262 for (i
= 0; i
< numAuths
; ++i
)
267 OSStatus err
= SecACLGetAuthorizations(acl
, tags
, &numAuths
);
268 if (errSecSuccess
!= err
)
274 CFTypeRef
* strings
= new CFTypeRef
[numAuths
];
275 for (i
= 0; i
< numAuths
; ++i
)
280 for (size_t iCnt
= 0; iCnt
< numAuths
; iCnt
++)
282 strings
[iCnt
] = (CFTypeRef
)GetAuthStringFromACLAuthorizationTag(tags
[iCnt
]);
285 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)strings
, numAuths
, &kCFTypeArrayCallBacks
);
294 OSStatus
SecACLSetAuthorizations(SecACLRef aclRef
,
295 CSSM_ACL_AUTHORIZATION_TAG
*tags
, uint32 tagCount
)
298 os_activity_t activity
= os_activity_create("SecACLSetAuthorizations", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
299 os_activity_scope(activity
);
300 os_release(activity
);
301 SecPointer
<ACL
> acl
= ACL::required(aclRef
);
302 if (acl
->isOwner()) // can't change rights of the owner ACL
303 MacOSError::throwMe(errSecInvalidOwnerEdit
);
304 AclAuthorizationSet
&auths
= acl
->authorizations();
306 copy(tags
, tags
+ tagCount
, insert_iterator
<AclAuthorizationSet
>(auths
, auths
.begin()));
311 OSStatus
SecACLUpdateAuthorizations(SecACLRef acl
, CFArrayRef authorizations
)
313 if (NULL
== acl
|| NULL
== authorizations
)
317 uint32 tagCount
= (uint32
)CFArrayGetCount(authorizations
);
319 size_t tagSize
= (tagCount
* sizeof(CSSM_ACL_AUTHORIZATION_TAG
));
321 CSSM_ACL_AUTHORIZATION_TAG
* tags
= (CSSM_ACL_AUTHORIZATION_TAG
*)malloc(tagSize
);
322 memset(tags
, 0, tagSize
);
323 for (uint32 iCnt
= 0; iCnt
< tagCount
; iCnt
++)
325 tags
[iCnt
] = GetACLAuthorizationTagFromString((CFStringRef
)CFArrayGetValueAtIndex(authorizations
, iCnt
));
328 OSStatus result
= SecACLSetAuthorizations(acl
, tags
, tagCount
);