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(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 makeCFArrayFrom(convert
, acl
->applications());
129 Required(promptDescription
) = makeCFString(acl
->promptDescription());
130 Required(promptSelector
) = acl
->promptSelector();
132 case ACL::integrityForm
:
133 Required(applicationList
) = NULL
;
134 Required(promptDescription
) = makeCFString(acl
->integrity().toHex());
136 // We don't have a prompt selector. Nullify.
137 Required(promptSelector
).version
= CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION
;
138 Required(promptSelector
).flags
= 0;
141 return errSecACLNotSimple
; // custom or unknown
146 OSStatus
SecACLCopyContents(SecACLRef acl
,
147 CFArrayRef
*applicationList
,
148 CFStringRef
*description
,
149 SecKeychainPromptSelector
*promptSelector
)
151 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector
;
152 memset(&cdsaPromptSelector
, 0, sizeof(cdsaPromptSelector
));
153 OSStatus err
= errSecSuccess
;
155 err
= SecACLCopySimpleContents(acl
, applicationList
, description
, &cdsaPromptSelector
);
156 *promptSelector
= cdsaPromptSelector
.flags
;
160 OSStatus
SecACLSetSimpleContents(SecACLRef aclRef
,
161 CFArrayRef applicationList
,
162 CFStringRef description
, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR
*promptSelector
)
165 SecPointer
<ACL
> acl
= ACL::required(aclRef
);
166 if(acl
->form() == ACL::integrityForm
) {
167 // If this is an integrity ACL, route the (unhexified) promptDescription into the right place
168 string hex
= cfString(description
);
169 if(hex
.length() %2
== 0) {
170 // might be a valid hex string, try to set
171 CssmAutoData
data(Allocator::standard());
172 data
.malloc(hex
.length() / 2);
173 data
.get().fromHex(hex
.c_str());
174 acl
->setIntegrity(data
);
177 // Otherwise, put it in the promptDescription where it belongs
178 acl
->promptDescription() = description
? cfString(description
) : "";
180 acl
->promptSelector() = promptSelector
? *promptSelector
: ACL::defaultSelector
;
181 if(acl
->form() != ACL::integrityForm
) {
182 if (applicationList
) {
183 // application-list + prompt
184 acl
->form(ACL::appListForm
);
185 setApplications(acl
, applicationList
);
188 acl
->form(ACL::allowAllForm
);
195 OSStatus
SecACLSetContents(SecACLRef acl
,
196 CFArrayRef applicationList
,
197 CFStringRef description
,
198 SecKeychainPromptSelector promptSelector
)
200 CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector
;
201 cdsaPromptSelector
.version
= CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION
;
202 cdsaPromptSelector
.flags
= promptSelector
;
203 return SecACLSetSimpleContents(acl
, applicationList
, description
, &cdsaPromptSelector
);
207 // Stuff a CFArray-of-SecTrustedApplications into an ACL object
209 static void setApplications(ACL
*acl
, CFArrayRef applicationList
)
211 ACL::ApplicationList
&appList
= acl
->applications();
213 //@@@ should really use STL iterator overlay on CFArray. By hand...
214 CFIndex count
= CFArrayGetCount(applicationList
);
215 for (CFIndex n
= 0; n
< count
; n
++)
216 appList
.push_back(TrustedApplication::required(
217 SecTrustedApplicationRef(CFArrayGetValueAtIndex(applicationList
, n
))));
222 // Set and get the authorization tags of an ACL entry
224 OSStatus
SecACLGetAuthorizations(SecACLRef acl
,
225 CSSM_ACL_AUTHORIZATION_TAG
*tags
, uint32
*tagCount
)
228 AclAuthorizationSet auths
= ACL::required(acl
)->authorizations();
229 if (Required(tagCount
) < auths
.size()) { // overflow
230 *tagCount
= (uint32
)auths
.size(); // report size required
231 CssmError::throwMe(errSecParam
);
233 *tagCount
= (uint32
)auths
.size();
234 copy(auths
.begin(), auths
.end(), tags
);
238 CFArrayRef
SecACLCopyAuthorizations(SecACLRef acl
)
240 CFArrayRef result
= NULL
;
246 AclAuthorizationSet auths
= ACL::required(acl
)->authorizations();
247 uint32 numAuths
= (uint32
)auths
.size();
249 CSSM_ACL_AUTHORIZATION_TAG
* tags
= new CSSM_ACL_AUTHORIZATION_TAG
[numAuths
];
251 for (i
= 0; i
< numAuths
; ++i
)
256 OSStatus err
= SecACLGetAuthorizations(acl
, tags
, &numAuths
);
257 if (errSecSuccess
!= err
)
263 CFTypeRef
* strings
= new CFTypeRef
[numAuths
];
264 for (i
= 0; i
< numAuths
; ++i
)
269 for (size_t iCnt
= 0; iCnt
< numAuths
; iCnt
++)
271 strings
[iCnt
] = (CFTypeRef
)GetAuthStringFromACLAuthorizationTag(tags
[iCnt
]);
274 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)strings
, numAuths
, &kCFTypeArrayCallBacks
);
283 OSStatus
SecACLSetAuthorizations(SecACLRef aclRef
,
284 CSSM_ACL_AUTHORIZATION_TAG
*tags
, uint32 tagCount
)
287 SecPointer
<ACL
> acl
= ACL::required(aclRef
);
288 if (acl
->isOwner()) // can't change rights of the owner ACL
289 MacOSError::throwMe(errSecInvalidOwnerEdit
);
290 AclAuthorizationSet
&auths
= acl
->authorizations();
292 copy(tags
, tags
+ tagCount
, insert_iterator
<AclAuthorizationSet
>(auths
, auths
.begin()));
297 OSStatus
SecACLUpdateAuthorizations(SecACLRef acl
, CFArrayRef authorizations
)
299 if (NULL
== acl
|| NULL
== authorizations
)
303 uint32 tagCount
= (uint32
)CFArrayGetCount(authorizations
);
305 size_t tagSize
= (tagCount
* sizeof(CSSM_ACL_AUTHORIZATION_TAG
));
307 CSSM_ACL_AUTHORIZATION_TAG
* tags
= (CSSM_ACL_AUTHORIZATION_TAG
*)malloc(tagSize
);
308 memset(tags
, 0, tagSize
);
309 for (uint32 iCnt
= 0; iCnt
< tagCount
; iCnt
++)
311 tags
[iCnt
] = GetACLAuthorizationTagFromString((CFStringRef
)CFArrayGetValueAtIndex(authorizations
, iCnt
));
314 OSStatus result
= SecACLSetAuthorizations(acl
, tags
, tagCount
);