]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cdsa_client/lib/aclclient.cpp
Security-58286.31.2.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/keyclient.h>
25 #include <security_cdsa_client/keychainacl.h>
26 #include <security_cdsa_utilities/cssmwalkers.h>
27 #include <security_cdsa_utilities/cssmdata.h>
28 #include <security_cdsa_utilities/cssmendian.h>
29 #include <securityd_client/handletypes.h>
30
31 namespace Security {
32 namespace CssmClient {
33
34 static inline void check(CSSM_RETURN rc)
35 {
36 ObjectImpl::check(rc);
37 }
38
39
40 //
41 // AclBearer methods (trivial)
42 //
43 AclBearer::~AclBearer()
44 { }
45
46
47 //
48 // Variant forms of AclBearer implemented in terms of its canonical virtual methods
49 //
50 void AclBearer::addAcl(const AclEntryInput &input, const CSSM_ACCESS_CREDENTIALS *cred)
51 {
52 changeAcl(AclEdit(input), cred);
53 }
54
55 void AclBearer::changeAcl(CSSM_ACL_HANDLE handle, const AclEntryInput &input,
56 const CSSM_ACCESS_CREDENTIALS *cred)
57 {
58 changeAcl(AclEdit(handle, input), cred);
59 }
60
61 void AclBearer::deleteAcl(CSSM_ACL_HANDLE handle, const CSSM_ACCESS_CREDENTIALS *cred)
62 {
63 changeAcl(AclEdit(handle), cred);
64 }
65
66 void AclBearer::deleteAcl(const char *tag, const CSSM_ACCESS_CREDENTIALS *cred)
67 {
68 AutoAclEntryInfoList entries;
69 getAcl(entries, tag);
70 for (uint32 n = 0; n < entries.count(); n++)
71 deleteAcl(entries[n].handle(), cred);
72 }
73
74
75 //
76 // KeyAclBearer implementation
77 //
78 void KeyAclBearer::getAcl(AutoAclEntryInfoList &aclInfos, const char *selectionTag) const
79 {
80 aclInfos.allocator(allocator);
81 check(CSSM_GetKeyAcl(csp, &key, reinterpret_cast<const CSSM_STRING *>(selectionTag), aclInfos, aclInfos));
82 }
83
84 void KeyAclBearer::changeAcl(const CSSM_ACL_EDIT &aclEdit, const CSSM_ACCESS_CREDENTIALS *cred)
85 {
86 check(CSSM_ChangeKeyAcl(csp, AccessCredentials::needed(cred), &aclEdit, &key));
87 }
88
89 void KeyAclBearer::getOwner(AutoAclOwnerPrototype &owner) const
90 {
91 owner.allocator(allocator);
92 check(CSSM_GetKeyOwner(csp, &key, owner));
93 }
94
95 void KeyAclBearer::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner,
96 const CSSM_ACCESS_CREDENTIALS *cred)
97 {
98 check(CSSM_ChangeKeyOwner(csp, AccessCredentials::needed(cred), &key, &newOwner));
99 }
100
101
102 //
103 // A single global structure containing pseudo-static data
104 //
105 struct Statics {
106 Statics();
107 Allocator &alloc;
108
109 AutoCredentials nullCred;
110 AutoCredentials promptCred;
111 AutoCredentials unlockCred;
112 AutoCredentials cancelCred;
113 AutoCredentials promptedPINCred;
114 AutoCredentials promptedPINItemCred;
115
116 AclOwnerPrototype anyOwner;
117 AclEntryInfo anyAcl;
118 };
119
120 namespace {
121 ModuleNexus<Statics> statics;
122 }
123
124
125 //
126 // Make pseudo-statics.
127 // Note: This is an eternal object. It is not currently destroyed
128 // if the containing code is unloaded.
129 //
130 Statics::Statics()
131 : alloc(Allocator::standard()),
132 nullCred(alloc, 1),
133 promptCred(alloc, 3),
134 unlockCred(alloc, 1),
135 cancelCred(alloc, 1),
136 promptedPINCred(alloc, 1),
137 promptedPINItemCred(alloc, 1),
138 anyOwner(TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_ANY)),
139 anyAcl(AclEntryPrototype(TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_ANY), 1))
140 {
141 // nullCred: nothing at all
142 // contains:
143 // an empty THRESHOLD sample to match threshold subjects with "free" subjects
144 nullCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_THRESHOLD);
145
146 // promptCred: a credential permitting user prompt confirmations
147 // contains:
148 // a KEYCHAIN_PROMPT sample, both by itself and in a THRESHOLD
149 // a PROMPTED_PASSWORD sample
150 promptCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT);
151 promptCred.sample(1) = TypedList(alloc, CSSM_SAMPLE_TYPE_THRESHOLD,
152 new(alloc) ListElement(TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT)));
153 promptCred.sample(2) = TypedList(alloc, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD,
154 new(alloc) ListElement(alloc, CssmData()));
155
156 // unlockCred: ???
157 unlockCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK,
158 new(alloc) ListElement(CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT));
159
160 cancelCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK,
161 new(alloc) ListElement(CSSM_WORDID_CANCELED));
162
163 /*
164 We don't set this:
165
166 promptedPINCred.tag("PIN1");
167
168 here to avoid triggering code in TokenDatabase::getAcl in securityd that
169 would always show a PIN unlock dialog. This credential is used for an
170 unlock of the database, i.e. a dbauthenticate call to unlock the card.
171 */
172 promptedPINCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD,
173 new(alloc) ListElement(alloc, CssmData()));
174
175 /*
176 This credential is used for items like non-repudiation keys that always
177 require an explicit entry of the PIN. We set this so that Token::authenticate
178 will recognize the number of the PIN we need to unlock.
179 */
180 promptedPINItemCred.tag("PIN1");
181 promptedPINItemCred.sample(0) = TypedList(alloc, CSSM_SAMPLE_TYPE_PROMPTED_PASSWORD,
182 new(alloc) ListElement(alloc, CssmData()));
183 }
184
185
186 //
187 // Make and break AclFactories
188 //
189 AclFactory::AclFactory()
190 { }
191
192 AclFactory::~AclFactory()
193 { }
194
195
196 //
197 // Return basic pseudo-static values
198 //
199 const AccessCredentials *AclFactory::nullCred() const
200 { return &statics().nullCred; }
201
202 const AccessCredentials *AclFactory::promptCred() const
203 { return &statics().promptCred; }
204
205 const AccessCredentials *AclFactory::unlockCred() const
206 { return &statics().unlockCred; }
207
208
209 const AccessCredentials *AclFactory::cancelCred() const
210 { return &statics().cancelCred; }
211
212 const AccessCredentials *AclFactory::promptedPINCred() const
213 { return &statics().promptedPINCred; }
214
215 const AccessCredentials *AclFactory::promptedPINItemCred() const
216 { return &statics().promptedPINItemCred; }
217
218
219 //
220 // Manage the (pseudo) credentials used to explicitly provide a passphrase to a keychain.
221 // Use the eternal unlockCred() for normal (protected prompt) unlocking.
222 //
223 AclFactory::KeychainCredentials::~KeychainCredentials ()
224 {
225 DataWalkers::chunkFree(mCredentials, allocator);
226 }
227
228 AclFactory::PassphraseUnlockCredentials::PassphraseUnlockCredentials (const CssmData& password,
229 Allocator& allocator) : KeychainCredentials(allocator)
230 {
231 mCredentials->sample(0) = TypedList(allocator, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK,
232 new (allocator) ListElement (CSSM_SAMPLE_TYPE_PASSWORD),
233 new (allocator) ListElement (CssmAutoData(allocator, password).release()));
234 }
235
236
237 //
238 // Manage the (pseudo) credentials used to explicitly change a keychain's passphrase
239 //
240 AclFactory::PasswordChangeCredentials::PasswordChangeCredentials (const CssmData& password,
241 Allocator& allocator) : KeychainCredentials(allocator)
242 {
243 mCredentials->sample(0) = TypedList(allocator, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK,
244 new (allocator) ListElement (CSSM_SAMPLE_TYPE_PASSWORD),
245 new (allocator) ListElement (CssmAutoData(allocator, password).release()));
246 }
247
248
249 //
250 // Manage the (pseudo) credentials used to explicitly provide a master key to a keychain.
251 //
252 AclFactory::MasterKeyUnlockCredentials::MasterKeyUnlockCredentials (const CssmClient::Key& key,
253 Allocator& allocator) : KeychainCredentials(allocator)
254 {
255 // Flatten out this key into:
256 // { h2ni(CSSM_KEY) : raw data for CSSM_KEY }
257 // which is also (on x86_64):
258 // { h2ni(CSSM_KEYHEADER) : 4 byte align : CSSM_DATA{0:0} : raw data for CSSM_KEY }
259 // (placement of alignment bytes uncertain)
260 //
261 // Data format is for consumption by kcdatabase.cpp:unflattenKey()
262
263 size_t dataLen = sizeof(CSSM_KEY) + key->keyData().length();
264 CssmAutoData flattenedKey(allocator);
265 flattenedKey.malloc(dataLen);
266 memset(flattenedKey, 0, dataLen);
267
268 // The key header must be in network-byte order for some reason
269 CSSM_KEYHEADER header = key->header();
270 Security::h2ni(header);
271 memcpy(flattenedKey, &header, sizeof(CSSM_KEYHEADER));
272 memcpy(((uint8_t*) flattenedKey.data()) + sizeof(CSSM_KEY), key->keyData().data(), key->keyData().length());
273
274 mCredentials->sample(0) = TypedList(allocator, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK,
275 new (allocator) ListElement(CSSM_SAMPLE_TYPE_SYMMETRIC_KEY),
276 new (allocator) ListElement(CssmAutoData(allocator, CssmData::wrap((SecurityServer::KeyHandle) 0)).release()),
277 new (allocator) ListElement(CssmAutoData(allocator, CssmData::wrap(*((const CssmKey*) key))).release()),
278 new (allocator) ListElement(flattenedKey.release()));
279 }
280
281
282
283 //
284 // Wide open ("ANY") CSSM forms for owner and ACL entry
285 //
286 const AclOwnerPrototype &AclFactory::anyOwner() const
287 { return statics().anyOwner; }
288
289 const AclEntryInfo &AclFactory::anyAcl() const
290 { return statics().anyAcl; }
291
292
293 //
294 // Create an ANY style AclEntryInput.
295 // This can be used to explicitly request wide-open authorization on a new CSSM object.
296 //
297 AclFactory::AnyResourceContext::AnyResourceContext(const CSSM_ACCESS_CREDENTIALS *cred)
298 : mAny(CSSM_ACL_SUBJECT_TYPE_ANY), mTag(CSSM_ACL_AUTHORIZATION_ANY)
299 {
300 // set up an ANY/EVERYTHING AclEntryInput
301 input().proto().subject() += &mAny;
302 AuthorizationGroup &authGroup = input().proto().authorization();
303 authGroup.NumberOfAuthTags = 1;
304 authGroup.AuthTags = &mTag;
305
306 // install the cred (not copied)
307 credentials(cred);
308 }
309
310
311 //
312 // CSSM ACL makers
313 //
314 AclFactory::Subject::Subject(Allocator &alloc, CSSM_ACL_SUBJECT_TYPE type)
315 : TypedList(alloc, type)
316 { }
317
318
319 AclFactory::PWSubject::PWSubject(Allocator &alloc)
320 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD)
321 { }
322
323 AclFactory::PWSubject::PWSubject(Allocator &alloc, const CssmData &secret)
324 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD)
325 {
326 append(new(alloc) ListElement(alloc, secret));
327 }
328
329 AclFactory::PromptPWSubject::PromptPWSubject(Allocator &alloc, const CssmData &prompt)
330 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD)
331 {
332 append(new(alloc) ListElement(alloc, prompt));
333 }
334
335 AclFactory::PromptPWSubject::PromptPWSubject(Allocator &alloc, const CssmData &prompt, const CssmData &secret)
336 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PROMPTED_PASSWORD)
337 {
338 append(new(alloc) ListElement(alloc, prompt));
339 append(new(alloc) ListElement(alloc, secret));
340 }
341
342 AclFactory::ProtectedPWSubject::ProtectedPWSubject(Allocator &alloc)
343 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PROTECTED_PASSWORD)
344 { }
345
346 AclFactory::PinSubject::PinSubject(Allocator &alloc, uint32 slot)
347 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PREAUTH)
348 {
349 append(new(alloc) ListElement(CSSM_ACL_AUTHORIZATION_PREAUTH(slot)));
350 }
351
352 AclFactory::PinSourceSubject::PinSourceSubject(Allocator &alloc, const TypedList &form)
353 : Subject(alloc, CSSM_ACL_SUBJECT_TYPE_PREAUTH_SOURCE)
354 {
355 append(new(alloc) ListElement(form));
356 }
357
358
359 } // end namespace CssmClient
360 } // end namespace Security