2 * Copyright (c) 2000-2001,2007,2011 Apple Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
22 #include <security_cdsa_client/cssmclient.h>
23 #include <security_cdsa_client/aclclient.h>
24 #include <security_cdsa_client/keychainacl.h>
25 #include <security_cdsa_utilities/cssmwalkers.h>
26 #include <security_cdsa_utilities/cssmdata.h>
30 namespace CssmClient
{
32 static inline void check(CSSM_RETURN rc
)
34 ObjectImpl::check(rc
);
39 // AclBearer methods (trivial)
41 AclBearer::~AclBearer()
46 // Variant forms of AclBearer implemented in terms of its canonical virtual methods
48 void AclBearer::addAcl(const AclEntryInput
&input
, const CSSM_ACCESS_CREDENTIALS
*cred
)
50 changeAcl(AclEdit(input
), cred
);
53 void AclBearer::changeAcl(CSSM_ACL_HANDLE handle
, const AclEntryInput
&input
,
54 const CSSM_ACCESS_CREDENTIALS
*cred
)
56 changeAcl(AclEdit(handle
, input
), cred
);
59 void AclBearer::deleteAcl(CSSM_ACL_HANDLE handle
, const CSSM_ACCESS_CREDENTIALS
*cred
)
61 changeAcl(AclEdit(handle
), cred
);
64 void AclBearer::deleteAcl(const char *tag
, const CSSM_ACCESS_CREDENTIALS
*cred
)
66 AutoAclEntryInfoList entries
;
68 for (uint32 n
= 0; n
< entries
.count(); n
++)
69 deleteAcl(entries
[n
].handle(), cred
);
74 // KeyAclBearer implementation
76 void KeyAclBearer::getAcl(AutoAclEntryInfoList
&aclInfos
, const char *selectionTag
) const
78 aclInfos
.allocator(allocator
);
79 check(CSSM_GetKeyAcl(csp
, &key
, reinterpret_cast<const CSSM_STRING
*>(selectionTag
), aclInfos
, aclInfos
));
82 void KeyAclBearer::changeAcl(const CSSM_ACL_EDIT
&aclEdit
, const CSSM_ACCESS_CREDENTIALS
*cred
)
84 check(CSSM_ChangeKeyAcl(csp
, AccessCredentials::needed(cred
), &aclEdit
, &key
));
87 void KeyAclBearer::getOwner(AutoAclOwnerPrototype
&owner
) const
89 owner
.allocator(allocator
);
90 check(CSSM_GetKeyOwner(csp
, &key
, owner
));
93 void KeyAclBearer::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE
&newOwner
,
94 const CSSM_ACCESS_CREDENTIALS
*cred
)
96 check(CSSM_ChangeKeyOwner(csp
, AccessCredentials::needed(cred
), &key
, &newOwner
));
101 // A single global structure containing pseudo-static data
107 AutoCredentials nullCred
;
108 AutoCredentials promptCred
;
109 AutoCredentials unlockCred
;
110 AutoCredentials cancelCred
;
111 AutoCredentials promptedPINCred
;
112 AutoCredentials promptedPINItemCred
;
114 AclOwnerPrototype anyOwner
;
119 ModuleNexus
<Statics
> statics
;
124 // Make pseudo-statics.
125 // Note: This is an eternal object. It is not currently destroyed
126 // if the containing code is unloaded.
129 : alloc(Allocator::standard()),
131 promptCred(alloc
, 3),
132 unlockCred(alloc
, 1),
133 cancelCred(alloc
, 1),
134 promptedPINCred(alloc
, 1),
135 promptedPINItemCred(alloc
, 1),
136 anyOwner(TypedList(alloc
, CSSM_ACL_SUBJECT_TYPE_ANY
)),
137 anyAcl(AclEntryPrototype(TypedList(alloc
, CSSM_ACL_SUBJECT_TYPE_ANY
), 1))
139 // nullCred: nothing at all
141 // an empty THRESHOLD sample to match threshold subjects with "free" subjects
142 nullCred
.sample(0) = TypedList(alloc
, CSSM_SAMPLE_TYPE_THRESHOLD
);
144 // promptCred: a credential permitting user prompt confirmations
146 // a KEYCHAIN_PROMPT sample, both by itself and in a THRESHOLD
147 // a PROMPTED_PASSWORD sample
148 promptCred
.sample(0) = TypedList(alloc
, CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT
);
149 promptCred
.sample(1) = TypedList(alloc
, CSSM_SAMPLE_TYPE_THRESHOLD
,
150 new(alloc
) ListElement(TypedList(alloc
, CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT
)));
151 promptCred
.sample(2) = TypedList(alloc
, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD
,
152 new(alloc
) ListElement(alloc
, CssmData()));
155 unlockCred
.sample(0) = TypedList(alloc
, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK
,
156 new(alloc
) ListElement(CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT
));
158 cancelCred
.sample(0) = TypedList(alloc
, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK
,
159 new(alloc
) ListElement(CSSM_WORDID_CANCELED
));
164 promptedPINCred.tag("PIN1");
166 here to avoid triggering code in TokenDatabase::getAcl in securityd that
167 would always show a PIN unlock dialog. This credential is used for an
168 unlock of the database, i.e. a dbauthenticate call to unlock the card.
170 promptedPINCred
.sample(0) = TypedList(alloc
, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD
,
171 new(alloc
) ListElement(alloc
, CssmData()));
174 This credential is used for items like non-repudiation keys that always
175 require an explicit entry of the PIN. We set this so that Token::authenticate
176 will recognize the number of the PIN we need to unlock.
178 promptedPINItemCred
.tag("PIN1");
179 promptedPINItemCred
.sample(0) = TypedList(alloc
, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD
,
180 new(alloc
) ListElement(alloc
, CssmData()));
185 // Make and break AclFactories
187 AclFactory::AclFactory()
190 AclFactory::~AclFactory()
195 // Return basic pseudo-static values
197 const AccessCredentials
*AclFactory::nullCred() const
198 { return &statics().nullCred
; }
200 const AccessCredentials
*AclFactory::promptCred() const
201 { return &statics().promptCred
; }
203 const AccessCredentials
*AclFactory::unlockCred() const
204 { return &statics().unlockCred
; }
207 const AccessCredentials
*AclFactory::cancelCred() const
208 { return &statics().cancelCred
; }
210 const AccessCredentials
*AclFactory::promptedPINCred() const
211 { return &statics().promptedPINCred
; }
213 const AccessCredentials
*AclFactory::promptedPINItemCred() const
214 { return &statics().promptedPINItemCred
; }
218 // Manage the (pseudo) credentials used to explicitly provide a passphrase to a keychain.
219 // Use the eternal unlockCred() for normal (protected prompt) unlocking.
221 AclFactory::KeychainCredentials::~KeychainCredentials ()
223 DataWalkers::chunkFree(mCredentials
, allocator
);
226 AclFactory::PassphraseUnlockCredentials::PassphraseUnlockCredentials (const CssmData
& password
,
227 Allocator
& allocator
) : KeychainCredentials(allocator
)
229 mCredentials
->sample(0) = TypedList(allocator
, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK
,
230 new (allocator
) ListElement (CSSM_SAMPLE_TYPE_PASSWORD
),
231 new (allocator
) ListElement (CssmAutoData(allocator
, password
).release()));
236 // Manage the (pseudo) credentials used to explicitly change a keychain's passphrase
238 AclFactory::PasswordChangeCredentials::PasswordChangeCredentials (const CssmData
& password
,
239 Allocator
& allocator
) : KeychainCredentials(allocator
)
241 mCredentials
->sample(0) = TypedList(allocator
, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK
,
242 new (allocator
) ListElement (CSSM_SAMPLE_TYPE_PASSWORD
),
243 new (allocator
) ListElement (CssmAutoData(allocator
, password
).release()));
248 // Wide open ("ANY") CSSM forms for owner and ACL entry
250 const AclOwnerPrototype
&AclFactory::anyOwner() const
251 { return statics().anyOwner
; }
253 const AclEntryInfo
&AclFactory::anyAcl() const
254 { return statics().anyAcl
; }
258 // Create an ANY style AclEntryInput.
259 // This can be used to explicitly request wide-open authorization on a new CSSM object.
261 AclFactory::AnyResourceContext::AnyResourceContext(const CSSM_ACCESS_CREDENTIALS
*cred
)
262 : mAny(CSSM_ACL_SUBJECT_TYPE_ANY
), mTag(CSSM_ACL_AUTHORIZATION_ANY
)
264 // set up an ANY/EVERYTHING AclEntryInput
265 input().proto().subject() += &mAny
;
266 AuthorizationGroup
&authGroup
= input().proto().authorization();
267 authGroup
.NumberOfAuthTags
= 1;
268 authGroup
.AuthTags
= &mTag
;
270 // install the cred (not copied)
278 AclFactory::Subject::Subject(Allocator
&alloc
, CSSM_ACL_SUBJECT_TYPE type
)
279 : TypedList(alloc
, type
)
283 AclFactory::PWSubject::PWSubject(Allocator
&alloc
)
284 : Subject(alloc
, CSSM_ACL_SUBJECT_TYPE_PASSWORD
)
287 AclFactory::PWSubject::PWSubject(Allocator
&alloc
, const CssmData
&secret
)
288 : Subject(alloc
, CSSM_ACL_SUBJECT_TYPE_PASSWORD
)
290 append(new(alloc
) ListElement(alloc
, secret
));
293 AclFactory::PromptPWSubject::PromptPWSubject(Allocator
&alloc
, const CssmData
&prompt
)
294 : Subject(alloc
, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD
)
296 append(new(alloc
) ListElement(alloc
, prompt
));
299 AclFactory::PromptPWSubject::PromptPWSubject(Allocator
&alloc
, const CssmData
&prompt
, const CssmData
&secret
)
300 : Subject(alloc
, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD
)
302 append(new(alloc
) ListElement(alloc
, prompt
));
303 append(new(alloc
) ListElement(alloc
, secret
));
306 AclFactory::ProtectedPWSubject::ProtectedPWSubject(Allocator
&alloc
)
307 : Subject(alloc
, CSSM_ACL_SUBJECT_TYPE_PROTECTED_PASSWORD
)
310 AclFactory::PinSubject::PinSubject(Allocator
&alloc
, uint32 slot
)
311 : Subject(alloc
, CSSM_ACL_SUBJECT_TYPE_PREAUTH
)
313 append(new(alloc
) ListElement(CSSM_ACL_AUTHORIZATION_PREAUTH(slot
)));
316 AclFactory::PinSourceSubject::PinSourceSubject(Allocator
&alloc
, const TypedList
&form
)
317 : Subject(alloc
, CSSM_ACL_SUBJECT_TYPE_PREAUTH_SOURCE
)
319 append(new(alloc
) ListElement(form
));
323 } // end namespace CssmClient
324 } // end namespace Security