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 "SecBridge.h"
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
38 sint32
GetACLAuthorizationTagFromString(CFStringRef aclStr
);
40 CFStringRef
GetAuthStringFromACLAuthorizationTag(sint32 tag
);
45 static void setApplications(ACL
*acl
, CFArrayRef applicationList
);
52 return gTypes().ACL
.typeID
;
54 END_SECAPI1(_kCFRuntimeNotATypeID
)
60 OSStatus
SecACLCreateFromSimpleContents(SecAccessRef accessRef
,
61 CFArrayRef applicationList
,
62 CFStringRef description
, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR
*promptSelector
,
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
);
74 acl
->form(ACL::allowAllForm
);
76 access
->add(acl
.get());
77 Required(newAcl
) = acl
->handle();
81 OSStatus
SecACLCreateWithSimpleContents(SecAccessRef access
,
82 CFArrayRef applicationList
,
83 CFStringRef description
,
84 SecKeychainPromptSelector promptSelector
,
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
);
96 OSStatus
SecACLRemove(SecACLRef aclRef
)
99 ACL::required(aclRef
)->remove();
104 static SecTrustedApplicationRef
105 convert(const SecPointer
<TrustedApplication
> &trustedApplication
)
107 return *trustedApplication
;
112 OSStatus
SecACLCopySimpleContents(SecACLRef aclRef
,
113 CFArrayRef
*applicationList
,
114 CFStringRef
*promptDescription
, CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR
*promptSelector
)
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();
126 case ACL::appListForm
:
127 Required(applicationList
) =
128 makeCFArray(convert
, acl
->applications());
129 Required(promptDescription
) = makeCFString(acl
->promptDescription());
130 Required(promptSelector
) = acl
->promptSelector();
133 return errSecACLNotSimple
; // custom or unknown
138 OSStatus
SecACLCopyContents(SecACLRef acl
,
139 CFArrayRef
*applicationList
,
140 CFStringRef
*description
,
141 SecKeychainPromptSelector
*promptSelector
)
143 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector
;
144 memset(&cdsaPromptSelector
, 0, sizeof(cdsaPromptSelector
));
145 OSStatus err
= errSecSuccess
;
147 err
= SecACLCopySimpleContents(acl
, applicationList
, description
, &cdsaPromptSelector
);
148 *promptSelector
= cdsaPromptSelector
.flags
;
152 OSStatus
SecACLSetSimpleContents(SecACLRef aclRef
,
153 CFArrayRef applicationList
,
154 CFStringRef description
, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR
*promptSelector
)
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
);
166 acl
->form(ACL::allowAllForm
);
172 OSStatus
SecACLSetContents(SecACLRef acl
,
173 CFArrayRef applicationList
,
174 CFStringRef description
,
175 SecKeychainPromptSelector promptSelector
)
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
);
184 // Stuff a CFArray-of-SecTrustedApplications into an ACL object
186 static void setApplications(ACL
*acl
, CFArrayRef applicationList
)
188 ACL::ApplicationList
&appList
= acl
->applications();
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
))));
199 // Set and get the authorization tags of an ACL entry
201 OSStatus
SecACLGetAuthorizations(SecACLRef acl
,
202 CSSM_ACL_AUTHORIZATION_TAG
*tags
, uint32
*tagCount
)
205 AclAuthorizationSet auths
= ACL::required(acl
)->authorizations();
206 if (Required(tagCount
) < auths
.size()) { // overflow
207 *tagCount
= (uint32
)auths
.size(); // report size required
208 CssmError::throwMe(errSecParam
);
210 *tagCount
= (uint32
)auths
.size();
211 copy(auths
.begin(), auths
.end(), tags
);
215 CFArrayRef
SecACLCopyAuthorizations(SecACLRef acl
)
217 CFArrayRef result
= NULL
;
223 AclAuthorizationSet auths
= ACL::required(acl
)->authorizations();
224 uint32 numAuths
= (uint32
)auths
.size();
226 CSSM_ACL_AUTHORIZATION_TAG
* tags
= new CSSM_ACL_AUTHORIZATION_TAG
[numAuths
];
228 for (i
= 0; i
< numAuths
; ++i
)
233 OSStatus err
= SecACLGetAuthorizations(acl
, tags
, &numAuths
);
234 if (errSecSuccess
!= err
)
240 CFTypeRef
* strings
= new CFTypeRef
[numAuths
];
241 for (i
= 0; i
< numAuths
; ++i
)
246 for (size_t iCnt
= 0; iCnt
< numAuths
; iCnt
++)
248 strings
[iCnt
] = (CFTypeRef
)GetAuthStringFromACLAuthorizationTag(tags
[iCnt
]);
251 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)strings
, numAuths
, NULL
);
260 OSStatus
SecACLSetAuthorizations(SecACLRef aclRef
,
261 CSSM_ACL_AUTHORIZATION_TAG
*tags
, uint32 tagCount
)
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();
269 copy(tags
, tags
+ tagCount
, insert_iterator
<AclAuthorizationSet
>(auths
, auths
.begin()));
274 OSStatus
SecACLUpdateAuthorizations(SecACLRef acl
, CFArrayRef authorizations
)
276 if (NULL
== acl
|| NULL
== authorizations
)
280 uint32 tagCount
= (uint32
)CFArrayGetCount(authorizations
);
282 size_t tagSize
= (tagCount
* sizeof(CSSM_ACL_AUTHORIZATION_TAG
));
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
++)
288 tags
[iCnt
] = GetACLAuthorizationTagFromString((CFStringRef
)CFArrayGetValueAtIndex(authorizations
, iCnt
));
291 OSStatus result
= SecACLSetAuthorizations(acl
, tags
, tagCount
);