]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cdsa_client/lib/aclclient.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / libsecurity_cdsa_client / lib / aclclient.cpp
1 /*
2 * Copyright (c) 2000-2001,2007,2011 Apple Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 //
20 // aclclient
21 //
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>
27
28
29 namespace Security {
30 namespace CssmClient {
31
32 static inline void check(CSSM_RETURN rc)
33 {
34 ObjectImpl::check(rc);
35 }
36
37
38 //
39 // AclBearer methods (trivial)
40 //
41 AclBearer::~AclBearer()
42 { }
43
44
45 //
46 // Variant forms of AclBearer implemented in terms of its canonical virtual methods
47 //
48 void AclBearer::addAcl(const AclEntryInput &input, const CSSM_ACCESS_CREDENTIALS *cred)
49 {
50 changeAcl(AclEdit(input), cred);
51 }
52
53 void AclBearer::changeAcl(CSSM_ACL_HANDLE handle, const AclEntryInput &input,
54 const CSSM_ACCESS_CREDENTIALS *cred)
55 {
56 changeAcl(AclEdit(handle, input), cred);
57 }
58
59 void AclBearer::deleteAcl(CSSM_ACL_HANDLE handle, const CSSM_ACCESS_CREDENTIALS *cred)
60 {
61 changeAcl(AclEdit(handle), cred);
62 }
63
64 void AclBearer::deleteAcl(const char *tag, const CSSM_ACCESS_CREDENTIALS *cred)
65 {
66 AutoAclEntryInfoList entries;
67 getAcl(entries, tag);
68 for (uint32 n = 0; n < entries.count(); n++)
69 deleteAcl(entries[n].handle(), cred);
70 }
71
72
73 //
74 // KeyAclBearer implementation
75 //
76 void KeyAclBearer::getAcl(AutoAclEntryInfoList &aclInfos, const char *selectionTag) const
77 {
78 aclInfos.allocator(allocator);
79 check(CSSM_GetKeyAcl(csp, &key, reinterpret_cast<const CSSM_STRING *>(selectionTag), aclInfos, aclInfos));
80 }
81
82 void KeyAclBearer::changeAcl(const CSSM_ACL_EDIT &aclEdit, const CSSM_ACCESS_CREDENTIALS *cred)
83 {
84 check(CSSM_ChangeKeyAcl(csp, AccessCredentials::needed(cred), &aclEdit, &key));
85 }
86
87 void KeyAclBearer::getOwner(AutoAclOwnerPrototype &owner) const
88 {
89 owner.allocator(allocator);
90 check(CSSM_GetKeyOwner(csp, &key, owner));
91 }
92
93 void KeyAclBearer::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner,
94 const CSSM_ACCESS_CREDENTIALS *cred)
95 {
96 check(CSSM_ChangeKeyOwner(csp, AccessCredentials::needed(cred), &key, &newOwner));
97 }
98
99
100 //
101 // A single global structure containing pseudo-static data
102 //
103 struct Statics {
104 Statics();
105 Allocator &alloc;
106
107 AutoCredentials nullCred;
108 AutoCredentials promptCred;
109 AutoCredentials unlockCred;
110 AutoCredentials cancelCred;
111 AutoCredentials promptedPINCred;
112 AutoCredentials promptedPINItemCred;
113
114 AclOwnerPrototype anyOwner;
115 AclEntryInfo anyAcl;
116 };
117
118 namespace {
119 ModuleNexus<Statics> statics;
120 }
121
122
123 //
124 // Make pseudo-statics.
125 // Note: This is an eternal object. It is not currently destroyed
126 // if the containing code is unloaded.
127 //
128 Statics::Statics()
129 : alloc(Allocator::standard()),
130 nullCred(alloc, 1),
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))
138 {
139 // nullCred: nothing at all
140 // contains:
141 // an empty THRESHOLD sample to match threshold subjects with "free" subjects
142 nullCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_THRESHOLD);
143
144 // promptCred: a credential permitting user prompt confirmations
145 // contains:
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()));
153
154 // unlockCred: ???
155 unlockCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK,
156 new(alloc) ListElement(CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT));
157
158 cancelCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK,
159 new(alloc) ListElement(CSSM_WORDID_CANCELED));
160
161 /*
162 We don't set this:
163
164 promptedPINCred.tag("PIN1");
165
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.
169 */
170 promptedPINCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD,
171 new(alloc) ListElement(alloc, CssmData()));
172
173 /*
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.
177 */
178 promptedPINItemCred.tag("PIN1");
179 promptedPINItemCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD,
180 new(alloc) ListElement(alloc, CssmData()));
181 }
182
183
184 //
185 // Make and break AclFactories
186 //
187 AclFactory::AclFactory()
188 { }
189
190 AclFactory::~AclFactory()
191 { }
192
193
194 //
195 // Return basic pseudo-static values
196 //
197 const AccessCredentials *AclFactory::nullCred() const
198 { return &statics().nullCred; }
199
200 const AccessCredentials *AclFactory::promptCred() const
201 { return &statics().promptCred; }
202
203 const AccessCredentials *AclFactory::unlockCred() const
204 { return &statics().unlockCred; }
205
206
207 const AccessCredentials *AclFactory::cancelCred() const
208 { return &statics().cancelCred; }
209
210 const AccessCredentials *AclFactory::promptedPINCred() const
211 { return &statics().promptedPINCred; }
212
213 const AccessCredentials *AclFactory::promptedPINItemCred() const
214 { return &statics().promptedPINItemCred; }
215
216
217 //
218 // Manage the (pseudo) credentials used to explicitly provide a passphrase to a keychain.
219 // Use the eternal unlockCred() for normal (protected prompt) unlocking.
220 //
221 AclFactory::KeychainCredentials::~KeychainCredentials ()
222 {
223 DataWalkers::chunkFree(mCredentials, allocator);
224 }
225
226 AclFactory::PassphraseUnlockCredentials::PassphraseUnlockCredentials (const CssmData& password,
227 Allocator& allocator) : KeychainCredentials(allocator)
228 {
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()));
232 }
233
234
235 //
236 // Manage the (pseudo) credentials used to explicitly change a keychain's passphrase
237 //
238 AclFactory::PasswordChangeCredentials::PasswordChangeCredentials (const CssmData& password,
239 Allocator& allocator) : KeychainCredentials(allocator)
240 {
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()));
244 }
245
246
247 //
248 // Wide open ("ANY") CSSM forms for owner and ACL entry
249 //
250 const AclOwnerPrototype &AclFactory::anyOwner() const
251 { return statics().anyOwner; }
252
253 const AclEntryInfo &AclFactory::anyAcl() const
254 { return statics().anyAcl; }
255
256
257 //
258 // Create an ANY style AclEntryInput.
259 // This can be used to explicitly request wide-open authorization on a new CSSM object.
260 //
261 AclFactory::AnyResourceContext::AnyResourceContext(const CSSM_ACCESS_CREDENTIALS *cred)
262 : mAny(CSSM_ACL_SUBJECT_TYPE_ANY), mTag(CSSM_ACL_AUTHORIZATION_ANY)
263 {
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;
269
270 // install the cred (not copied)
271 credentials(cred);
272 }
273
274
275 //
276 // CSSM ACL makers
277 //
278 AclFactory::Subject::Subject(Allocator &alloc, CSSM_ACL_SUBJECT_TYPE type)
279 : TypedList(alloc, type)
280 { }
281
282
283 AclFactory::PWSubject::PWSubject(Allocator &alloc)
284 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD)
285 { }
286
287 AclFactory::PWSubject::PWSubject(Allocator &alloc, const CssmData &secret)
288 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD)
289 {
290 append(new(alloc) ListElement(alloc, secret));
291 }
292
293 AclFactory::PromptPWSubject::PromptPWSubject(Allocator &alloc, const CssmData &prompt)
294 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD)
295 {
296 append(new(alloc) ListElement(alloc, prompt));
297 }
298
299 AclFactory::PromptPWSubject::PromptPWSubject(Allocator &alloc, const CssmData &prompt, const CssmData &secret)
300 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD)
301 {
302 append(new(alloc) ListElement(alloc, prompt));
303 append(new(alloc) ListElement(alloc, secret));
304 }
305
306 AclFactory::ProtectedPWSubject::ProtectedPWSubject(Allocator &alloc)
307 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PROTECTED_PASSWORD)
308 { }
309
310 AclFactory::PinSubject::PinSubject(Allocator &alloc, uint32 slot)
311 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PREAUTH)
312 {
313 append(new(alloc) ListElement(CSSM_ACL_AUTHORIZATION_PREAUTH(slot)));
314 }
315
316 AclFactory::PinSourceSubject::PinSourceSubject(Allocator &alloc, const TypedList &form)
317 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PREAUTH_SOURCE)
318 {
319 append(new(alloc) ListElement(form));
320 }
321
322
323 } // end namespace CssmClient
324 } // end namespace Security