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
);
53 os_activity_t activity
= os_activity_create("SecACLGetTypeID", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
54 os_activity_scope(activity
);
57 return gTypes().ACL
.typeID
;
59 END_SECAPI1(_kCFRuntimeNotATypeID
)
65 OSStatus
SecACLCreateFromSimpleContents(SecAccessRef accessRef
,
66 CFArrayRef applicationList
,
67 CFStringRef description
, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR
*promptSelector
,
71 os_activity_t activity
= os_activity_create("SecACLCreateFromSimpleContents", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
72 os_activity_scope(activity
);
74 SecPointer
<Access
> access
= Access::required(accessRef
);
75 SecPointer
<ACL
> acl
= new ACL(cfString(description
), *promptSelector
);
76 if (applicationList
) {
77 // application-list + prompt
78 acl
->form(ACL::appListForm
);
79 setApplications(acl
, applicationList
);
82 acl
->form(ACL::allowAllForm
);
84 access
->add(acl
.get());
85 Required(newAcl
) = acl
->handle();
89 OSStatus
SecACLCreateWithSimpleContents(SecAccessRef access
,
90 CFArrayRef applicationList
,
91 CFStringRef description
,
92 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
)
162 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector
;
163 memset(&cdsaPromptSelector
, 0, sizeof(cdsaPromptSelector
));
164 OSStatus err
= errSecSuccess
;
166 err
= SecACLCopySimpleContents(acl
, applicationList
, description
, &cdsaPromptSelector
);
167 *promptSelector
= cdsaPromptSelector
.flags
;
171 OSStatus
SecACLSetSimpleContents(SecACLRef aclRef
,
172 CFArrayRef applicationList
,
173 CFStringRef description
, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR
*promptSelector
)
176 os_activity_t activity
= os_activity_create("SecACLSetSimpleContents", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
177 os_activity_scope(activity
);
178 os_release(activity
);
179 SecPointer
<ACL
> acl
= ACL::required(aclRef
);
180 if(acl
->form() == ACL::integrityForm
) {
181 // If this is an integrity ACL, route the (unhexified) promptDescription into the right place
182 string hex
= cfString(description
);
183 if(hex
.length() %2
== 0) {
184 // might be a valid hex string, try to set
185 CssmAutoData
data(Allocator::standard());
186 data
.malloc(hex
.length() / 2);
187 data
.get().fromHex(hex
.c_str());
188 acl
->setIntegrity(data
);
191 // Otherwise, put it in the promptDescription where it belongs
192 acl
->promptDescription() = description
? cfString(description
) : "";
194 acl
->promptSelector() = promptSelector
? *promptSelector
: ACL::defaultSelector
;
195 if(acl
->form() != ACL::integrityForm
) {
196 if (applicationList
) {
197 // application-list + prompt
198 acl
->form(ACL::appListForm
);
199 setApplications(acl
, applicationList
);
202 acl
->form(ACL::allowAllForm
);
209 OSStatus
SecACLSetContents(SecACLRef acl
,
210 CFArrayRef applicationList
,
211 CFStringRef description
,
212 SecKeychainPromptSelector promptSelector
)
214 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector
;
215 cdsaPromptSelector
.version
= CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION
;
216 cdsaPromptSelector
.flags
= promptSelector
;
217 return SecACLSetSimpleContents(acl
, applicationList
, description
, &cdsaPromptSelector
);
221 // Stuff a CFArray-of-SecTrustedApplications into an ACL object
223 static void setApplications(ACL
*acl
, CFArrayRef applicationList
)
225 ACL::ApplicationList
&appList
= acl
->applications();
227 //@@@ should really use STL iterator overlay on CFArray. By hand...
228 CFIndex count
= CFArrayGetCount(applicationList
);
229 for (CFIndex n
= 0; n
< count
; n
++)
230 appList
.push_back(TrustedApplication::required(
231 SecTrustedApplicationRef(CFArrayGetValueAtIndex(applicationList
, n
))));
236 // Set and get the authorization tags of an ACL entry
238 OSStatus
SecACLGetAuthorizations(SecACLRef acl
,
239 CSSM_ACL_AUTHORIZATION_TAG
*tags
, uint32
*tagCount
)
242 AclAuthorizationSet auths
= ACL::required(acl
)->authorizations();
243 if (Required(tagCount
) < auths
.size()) { // overflow
244 *tagCount
= (uint32
)auths
.size(); // report size required
245 CssmError::throwMe(errSecParam
);
247 *tagCount
= (uint32
)auths
.size();
248 copy(auths
.begin(), auths
.end(), tags
);
252 CFArrayRef
SecACLCopyAuthorizations(SecACLRef acl
)
254 CFArrayRef result
= NULL
;
260 AclAuthorizationSet auths
= ACL::required(acl
)->authorizations();
261 uint32 numAuths
= (uint32
)auths
.size();
263 CSSM_ACL_AUTHORIZATION_TAG
* tags
= new CSSM_ACL_AUTHORIZATION_TAG
[numAuths
];
265 for (i
= 0; i
< numAuths
; ++i
)
270 OSStatus err
= SecACLGetAuthorizations(acl
, tags
, &numAuths
);
271 if (errSecSuccess
!= err
)
277 CFTypeRef
* strings
= new CFTypeRef
[numAuths
];
278 for (i
= 0; i
< numAuths
; ++i
)
283 for (size_t iCnt
= 0; iCnt
< numAuths
; iCnt
++)
285 strings
[iCnt
] = (CFTypeRef
)GetAuthStringFromACLAuthorizationTag(tags
[iCnt
]);
288 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)strings
, numAuths
, &kCFTypeArrayCallBacks
);
297 OSStatus
SecACLSetAuthorizations(SecACLRef aclRef
,
298 CSSM_ACL_AUTHORIZATION_TAG
*tags
, uint32 tagCount
)
301 os_activity_t activity
= os_activity_create("SecACLSetAuthorizations", OS_ACTIVITY_CURRENT
, OS_ACTIVITY_FLAG_IF_NONE_PRESENT
);
302 os_activity_scope(activity
);
303 os_release(activity
);
304 SecPointer
<ACL
> acl
= ACL::required(aclRef
);
305 if (acl
->isOwner()) // can't change rights of the owner ACL
306 MacOSError::throwMe(errSecInvalidOwnerEdit
);
307 AclAuthorizationSet
&auths
= acl
->authorizations();
309 copy(tags
, tags
+ tagCount
, insert_iterator
<AclAuthorizationSet
>(auths
, auths
.begin()));
314 OSStatus
SecACLUpdateAuthorizations(SecACLRef acl
, CFArrayRef authorizations
)
316 if (NULL
== acl
|| NULL
== authorizations
)
320 uint32 tagCount
= (uint32
)CFArrayGetCount(authorizations
);
322 size_t tagSize
= (tagCount
* sizeof(CSSM_ACL_AUTHORIZATION_TAG
));
324 CSSM_ACL_AUTHORIZATION_TAG
* tags
= (CSSM_ACL_AUTHORIZATION_TAG
*)malloc(tagSize
);
325 memset(tags
, 0, tagSize
);
326 for (uint32 iCnt
= 0; iCnt
< tagCount
; iCnt
++)
328 tags
[iCnt
] = GetACLAuthorizationTagFromString((CFStringRef
)CFArrayGetValueAtIndex(authorizations
, iCnt
));
331 OSStatus result
= SecACLSetAuthorizations(acl
, tags
, tagCount
);