]> git.saurik.com Git - apple/securityd.git/blob - src/tokendatabase.cpp
securityd-30544.tar.gz
[apple/securityd.git] / src / tokendatabase.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 //
26 // tokendatabase - software database container implementation.
27 //
28 #include "tokendatabase.h"
29 #include "tokenkey.h"
30 #include "tokenaccess.h"
31 #include "process.h"
32 #include "server.h"
33 #include "localkey.h" // to retrieve local raw keys
34 #include <security_cdsa_client/wrapkey.h>
35
36
37 //
38 // Construct a TokenDbCommon
39 //
40 TokenDbCommon::TokenDbCommon(Session &ssn, Token &tk, const char *name)
41 : DbCommon(ssn), mDbName(name ? name : ""), mResetLevel(0)
42 {
43 secdebug("tokendb", "creating tokendbcommon %p: with token %p", this, &tk);
44 parent(tk);
45 }
46
47 TokenDbCommon::~TokenDbCommon()
48 {
49 secdebug("tokendb", "destroying tokendbcommon %p", this);
50 token().removeCommon(*this); // unregister from Token
51 }
52
53 Token &TokenDbCommon::token() const
54 {
55 return parent<Token>();
56 }
57
58 const std::string &TokenDbCommon::dbName() const
59 {
60 return token().printName();
61 }
62
63
64 //
65 // A TokenDbCommon holds per-session adornments for the ACL machine
66 //
67 Adornable &TokenDbCommon::store()
68 {
69 StLock<Mutex> _(*this);
70
71 // if this is the first one, hook for lifetime
72 if (mAdornments.empty()) {
73 session().addReference(*this); // hold and slave to SSN lifetime
74 token().addCommon(*this); // register with Token
75 }
76
77 // return our (now active) adornments
78 return mAdornments;
79 }
80
81 void TokenDbCommon::resetAcls()
82 {
83 StLock<Mutex> _(*this);
84 if (!mAdornments.empty()) {
85 mAdornments.clearAdornments(); // clear ACL state
86 session().removeReference(*this); // unhook from SSN
87 }
88 token().removeCommon(*this); // unregister from Token
89 }
90
91
92 //
93 // Process (our part of) a "lock all" request.
94 // Smartcard tokens interpret a "lock" as a forced card reset, transmitted
95 // to tokend as an authenticate request.
96 // @@@ Virtual reset for multi-session tokens. Right now, we're using the sledge hammer.
97 //
98 void TokenDbCommon::lockProcessing()
99 {
100 Access access(token());
101 access().authenticate(CSSM_DB_ACCESS_RESET, NULL);
102 }
103
104 //
105 // Construct a TokenDatabase given subservice information.
106 // We are currently ignoring the 'name' argument.
107 //
108 TokenDatabase::TokenDatabase(uint32 ssid, Process &proc,
109 const char *name, const AccessCredentials *cred)
110 : Database(proc)
111 {
112 // locate Token object
113 RefPointer<Token> token = Token::find(ssid);
114
115 Session &session = process().session();
116 StLock<Mutex> _(session);
117 if (TokenDbCommon *dbcom = session.findFirst<TokenDbCommon, uint32>(&TokenDbCommon::subservice, ssid)) {
118 parent(*dbcom);
119 secdebug("tokendb", "open tokendb %p(%ld) at known common %p",
120 this, subservice(), dbcom);
121 } else {
122 // DbCommon not present; make a new one
123 parent(*new TokenDbCommon(proc.session(), *token, name));
124 secdebug("tokendb", "open tokendb %p(%ld) with new common %p",
125 this, subservice(), &common());
126 }
127 mOpenCreds = copy(cred, Allocator::standard());
128 proc.addReference(*this);
129 }
130
131 TokenDatabase::~TokenDatabase()
132 {
133 Allocator::standard().free(mOpenCreds);
134 }
135
136
137 //
138 // Basic Database virtual implementations
139 //
140 TokenDbCommon &TokenDatabase::common() const
141 {
142 return parent<TokenDbCommon>();
143 }
144
145 TokenDaemon &TokenDatabase::tokend()
146 {
147 return common().token().tokend();
148 }
149
150 const char *TokenDatabase::dbName() const
151 {
152 return common().dbName().c_str();
153 }
154
155 bool TokenDatabase::transient() const
156 {
157 //@@@ let tokend decide? Are there any secure transient keystores?
158 return false;
159 }
160
161
162 SecurityServerAcl &TokenDatabase::acl()
163 {
164 return token();
165 }
166
167 bool TokenDatabase::isLocked() const
168 {
169 Access access(token());
170 return access().isLocked();
171 }
172
173
174 //
175 // TokenDatabases implement the dbName-setting function.
176 // This sets the print name of the token, which is persistently
177 // stored in the token cache. So this is a de-facto rename of
178 // the token, at least on this system.
179 //
180 void TokenDatabase::dbName(const char *name)
181 {
182 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
183 }
184
185
186 //
187 // Given a key handle and CssmKey returned from tokend, create a Key representing
188 // it. This takes care of raw returns by turning them into keys of the process's
189 // local transient store.
190 //
191 RefPointer<Key> TokenDatabase::makeKey(KeyHandle hKey, const CssmKey *key,
192 const AclEntryPrototype *owner)
193 {
194 switch (key->blobType()) {
195 case CSSM_KEYBLOB_REFERENCE:
196 return new TokenKey(*this, hKey, key->header());
197 case CSSM_KEYBLOB_RAW:
198 return process().makeTemporaryKey(*key, 0, owner);
199 default:
200 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); // bad key return from tokend
201 }
202 //@@@ Server::releaseWhenDone(key);
203 }
204
205
206 //
207 // Adjust key attributes for newly created keys
208 //
209 static CSSM_KEYATTR_FLAGS modattrs(CSSM_KEYATTR_FLAGS attrs)
210 {
211 static const CSSM_KEYATTR_FLAGS CSSM_KEYATTR_RETURN_FLAGS = 0xff000000;
212 switch (attrs & CSSM_KEYATTR_RETURN_FLAGS) {
213 case CSSM_KEYATTR_RETURN_REF:
214 case CSSM_KEYATTR_RETURN_DATA:
215 break; // as requested
216 case CSSM_KEYATTR_RETURN_NONE:
217 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK);
218 case CSSM_KEYATTR_RETURN_DEFAULT:
219 if (attrs & CSSM_KEYATTR_PERMANENT)
220 attrs |= CSSM_KEYATTR_RETURN_REF;
221 else
222 attrs |= CSSM_KEYATTR_RETURN_DATA;
223 break;
224 }
225 return attrs;
226 }
227
228
229 //
230 // TokenDatabases support remote secret validation by sending a secret
231 // (aka passphrase et al) to tokend for processing.
232 //
233 bool TokenDatabase::validateSecret(const AclSubject *subject, const AccessCredentials *cred)
234 {
235 secdebug("tokendb", "%p attempting remote validation", this);
236 try {
237 Access access(token());
238 // @@@ Use cached mode
239 access().authenticate(CSSM_DB_ACCESS_READ, cred);
240 secdebug("tokendb", "%p remote validation successful", this);
241 return true;
242 }
243 catch (...) {
244 secdebug("tokendb", "%p remote validation failed", this);
245 // return false;
246 throw; // try not to mask error
247 }
248 }
249
250
251 //
252 // Key inquiries
253 //
254 void TokenDatabase::queryKeySizeInBits(Key &key, CssmKeySize &result)
255 {
256 Access access(token());
257 TRY
258 GUARD
259 access().queryKeySizeInBits(myKey(key).tokenHandle(), result);
260 DONE
261 }
262
263
264 //
265 // Signatures and MACs
266 //
267 void TokenDatabase::generateSignature(const Context &context, Key &key,
268 CSSM_ALGORITHMS signOnlyAlgorithm, const CssmData &data, CssmData &signature)
269 {
270 Access access(token(), key);
271 TRY
272 key.validate(CSSM_ACL_AUTHORIZATION_SIGN, context);
273 GUARD
274 access().generateSignature(context, myKey(key).tokenHandle(), data, signature, signOnlyAlgorithm);
275 DONE
276 }
277
278
279 void TokenDatabase::verifySignature(const Context &context, Key &key,
280 CSSM_ALGORITHMS verifyOnlyAlgorithm, const CssmData &data, const CssmData &signature)
281 {
282 Access access(token(), key);
283 TRY
284 GUARD
285 access().verifySignature(context, myKey(key).tokenHandle(), data, signature, verifyOnlyAlgorithm);
286 DONE
287 }
288
289 void TokenDatabase::generateMac(const Context &context, Key &key,
290 const CssmData &data, CssmData &mac)
291 {
292 Access access(token());
293 TRY
294 key.validate(CSSM_ACL_AUTHORIZATION_MAC, context);
295 GUARD
296 access().generateMac(context, myKey(key).tokenHandle(), data, mac);
297 DONE
298 }
299
300 void TokenDatabase::verifyMac(const Context &context, Key &key,
301 const CssmData &data, const CssmData &mac)
302 {
303 Access access(token());
304 TRY
305 key.validate(CSSM_ACL_AUTHORIZATION_MAC, context);
306 GUARD
307 access().verifyMac(context, myKey(key).tokenHandle(), data, mac);
308 DONE
309 }
310
311
312 //
313 // Encryption/decryption
314 //
315 void TokenDatabase::encrypt(const Context &context, Key &key,
316 const CssmData &clear, CssmData &cipher)
317 {
318 Access access(token());
319 TRY
320 key.validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context);
321 GUARD
322 access().encrypt(context, myKey(key).tokenHandle(), clear, cipher);
323 DONE
324 }
325
326
327 void TokenDatabase::decrypt(const Context &context, Key &key,
328 const CssmData &cipher, CssmData &clear)
329 {
330 Access access(token());
331 TRY
332 key.validate(CSSM_ACL_AUTHORIZATION_DECRYPT, context);
333 GUARD
334 access().decrypt(context, myKey(key).tokenHandle(), cipher, clear);
335 DONE
336 }
337
338
339 //
340 // Key generation and derivation.
341 // Currently, we consider symmetric key generation to be fast, but
342 // asymmetric key generation to be (potentially) slow.
343 //
344 void TokenDatabase::generateKey(const Context &context,
345 const AccessCredentials *cred, const AclEntryPrototype *owner,
346 CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, RefPointer<Key> &newKey)
347 {
348 Access access(token());
349 TRY
350 GUARD
351 KeyHandle hKey;
352 CssmKey *result;
353 access().generateKey(context, cred, owner, usage, modattrs(attrs), hKey, result);
354 newKey = makeKey(hKey, result, owner);
355 DONE
356 }
357
358 void TokenDatabase::generateKey(const Context &context,
359 const AccessCredentials *cred, const AclEntryPrototype *owner,
360 CSSM_KEYUSE pubUsage, CSSM_KEYATTR_FLAGS pubAttrs,
361 CSSM_KEYUSE privUsage, CSSM_KEYATTR_FLAGS privAttrs,
362 RefPointer<Key> &publicKey, RefPointer<Key> &privateKey)
363 {
364 Access access(token());
365 TRY
366 GUARD
367 KeyHandle hPrivate, hPublic;
368 CssmKey *privKey, *pubKey;
369 access().generateKey(context, cred, owner,
370 pubUsage, modattrs(pubAttrs), privUsage, modattrs(privAttrs),
371 hPublic, pubKey, hPrivate, privKey);
372 publicKey = makeKey(hPublic, pubKey, owner);
373 privateKey = makeKey(hPrivate, privKey, owner);
374 DONE
375 }
376
377
378 //
379 // Key wrapping and unwrapping.
380 // Note that the key argument (the key in the context) is optional because of the special
381 // case of "cleartext" (null algorithm) wrapping for import/export.
382 //
383 void TokenDatabase::wrapKey(const Context &context, const AccessCredentials *cred,
384 Key *wrappingKey, Key &subjectKey,
385 const CssmData &descriptiveData, CssmKey &wrappedKey)
386 {
387 Access access(token());
388 InputKey cWrappingKey(wrappingKey);
389 InputKey cSubjectKey(subjectKey);
390 TRY
391 subjectKey.validate(context.algorithm() == CSSM_ALGID_NONE ?
392 CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR : CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED,
393 cred);
394 if (wrappingKey)
395 wrappingKey->validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context);
396 GUARD
397 CssmKey *rWrappedKey;
398 access().wrapKey(context, cred,
399 cWrappingKey, cWrappingKey, cSubjectKey, cSubjectKey,
400 descriptiveData, rWrappedKey);
401 wrappedKey = *rWrappedKey;
402 //@@@ ownership of wrappedKey.keyData() ??
403 DONE
404 }
405
406 void TokenDatabase::unwrapKey(const Context &context,
407 const AccessCredentials *cred, const AclEntryPrototype *owner,
408 Key *wrappingKey, Key *publicKey, CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs,
409 const CssmKey wrappedKey, RefPointer<Key> &unwrappedKey, CssmData &descriptiveData)
410 {
411 Access access(token());
412 InputKey cWrappingKey(wrappingKey);
413 InputKey cPublicKey(publicKey);
414 TRY
415 if (wrappingKey)
416 wrappingKey->validate(CSSM_ACL_AUTHORIZATION_DECRYPT, context);
417 // we are not checking access on the public key, if any
418 GUARD
419 KeyHandle hKey;
420 CssmKey *result;
421 access().unwrapKey(context, cred, owner,
422 cWrappingKey, cWrappingKey, cPublicKey, cPublicKey,
423 wrappedKey, usage, modattrs(attrs), descriptiveData, hKey, result);
424 unwrappedKey = makeKey(hKey, result, owner);
425 DONE
426 }
427
428
429 //
430 // Key derivation
431 //
432 void TokenDatabase::deriveKey(const Context &context, Key *sourceKey,
433 const AccessCredentials *cred, const AclEntryPrototype *owner,
434 CssmData *param, CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, RefPointer<Key> &derivedKey)
435 {
436 Access access(token());
437 InputKey cSourceKey(sourceKey);
438 TRY
439 if (sourceKey)
440 sourceKey->validate(CSSM_ACL_AUTHORIZATION_DERIVE, cred);
441 GUARD
442 KeyHandle hKey;
443 CssmKey *result;
444 CssmData params = param ? *param : CssmData();
445 access().deriveKey(noDb, context,
446 cSourceKey, cSourceKey,
447 usage, modattrs(attrs), params, cred, owner,
448 hKey, result);
449 if (param) {
450 *param = params;
451 //@@@ leak? what's the rule here?
452 }
453 derivedKey = makeKey(hKey, result, owner);
454 DONE
455 }
456
457
458 //
459 // Miscellaneous CSSM functions
460 //
461 void TokenDatabase::getOutputSize(const Context &context, Key &key,
462 uint32 inputSize, bool encrypt, uint32 &result)
463 {
464 Access access(token());
465 TRY
466 GUARD
467 access().getOutputSize(context, myKey(key).tokenHandle(), inputSize, encrypt, result);
468 DONE
469 }
470
471
472 //
473 // (Re-)Authenticate the database.
474 // We use dbAuthenticate as the catch-all "do something about authentication" call.
475 //
476 void TokenDatabase::authenticate(CSSM_DB_ACCESS_TYPE mode, const AccessCredentials *cred)
477 {
478 Access access(token());
479 TRY
480 GUARD
481 if (mode != CSSM_DB_ACCESS_RESET && cred) {
482 secdebug("tokendb", "%p authenticate calling validate", this);
483 int pin;
484 if (sscanf(cred->EntryTag, "PIN%d", &pin) == 1)
485 return validate(CSSM_ACL_AUTHORIZATION_PREAUTH(pin), cred);
486 }
487
488 access().authenticate(mode, cred);
489 switch (mode) {
490 case CSSM_DB_ACCESS_RESET:
491 // this mode is known to trigger "lockdown" (i.e. reset)
492 common().resetAcls();
493 break;
494 default:
495 {
496 // no idea what that did to the token;
497 // But let's remember the new creds for our own sake.
498 AccessCredentials *newCred = copy(cred, Allocator::standard());
499 Allocator::standard().free(mOpenCreds);
500 mOpenCreds = newCred;
501 break;
502 }
503 }
504 DONE
505 }
506
507 //
508 // Data access interface.
509 //
510 // Note that the attribute vectors are passed between our two IPC interfaces
511 // as relocated but contiguous memory blocks (to avoid an extra copy). This means
512 // you can read them at will, but can't change them in transit unless you're
513 // willing to repack them right here.
514 //
515 void TokenDatabase::findFirst(const CssmQuery &query,
516 CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength,
517 CssmData *data, RefPointer<Key> &key,
518 RefPointer<Database::Search> &rSearch, RefPointer<Database::Record> &rRecord,
519 CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength)
520 {
521 Access access(token());
522 RefPointer<Search> search = new Search(*this);
523 RefPointer<Record> record = new Record(*this);
524 TRY
525 KeyHandle hKey = noKey;
526 validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds());
527 GUARD
528 record->tokenHandle() = access().Tokend::ClientSession::findFirst(query,
529 inAttributes, inAttributesLength, search->tokenHandle(), NULL, hKey,
530 outAttributes, outAttributesLength);
531 if (!record->tokenHandle()) { // no match (but no other error)
532 rRecord = NULL; // return null record
533 return;
534 }
535 if (data) {
536 if (!hKey)
537 record->validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds());
538 CssmDbRecordAttributeData *noAttributes;
539 mach_msg_type_number_t noAttributesLength;
540 access().Tokend::ClientSession::findRecordHandle(record->tokenHandle(),
541 NULL, 0, data, hKey, noAttributes, noAttributesLength);
542 if (hKey) { // tokend returned a key reference & data
543 CssmKey &keyForm = *data->interpretedAs<CssmKey>(CSSMERR_CSP_INVALID_KEY);
544 key = new TokenKey(*this, hKey, keyForm.header());
545 }
546 }
547 rSearch = search->commit();
548 rRecord = record->commit();
549 DONE
550 }
551
552 void TokenDatabase::findNext(Database::Search *rSearch,
553 CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength,
554 CssmData *data, RefPointer<Key> &key, RefPointer<Database::Record> &rRecord,
555 CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength)
556 {
557 Access access(token());
558 RefPointer<Record> record = new Record(*this);
559 Search *search = safe_cast<Search *>(rSearch);
560 TRY
561 KeyHandle hKey = noKey;
562 validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds());
563 GUARD
564 record->tokenHandle() = access().Tokend::ClientSession::findNext(
565 search->tokenHandle(), inAttributes, inAttributesLength,
566 NULL, hKey, outAttributes, outAttributesLength);
567 if (!record->tokenHandle()) { // no more matches
568 releaseSearch(*search); // release search handle (consumed by EOD)
569 rRecord = NULL; // return null record
570 return;
571 }
572 if (data) {
573 if (!hKey)
574 record->validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds());
575 CssmDbRecordAttributeData *noAttributes;
576 mach_msg_type_number_t noAttributesLength;
577 access().Tokend::ClientSession::findRecordHandle(record->tokenHandle(),
578 NULL, 0, data, hKey, noAttributes, noAttributesLength);
579 if (hKey) { // tokend returned a key reference & data
580 CssmKey &keyForm = *data->interpretedAs<CssmKey>(CSSMERR_CSP_INVALID_KEY);
581 key = new TokenKey(*this, hKey, keyForm.header());
582 }
583 }
584 rRecord = record->commit();
585 DONE
586 }
587
588 void TokenDatabase::findRecordHandle(Database::Record *rRecord,
589 CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength,
590 CssmData *data, RefPointer<Key> &key,
591 CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength)
592 {
593 Access access(token());
594 Record *record = safe_cast<Record *>(rRecord);
595 access.add(*record);
596 TRY
597 KeyHandle hKey = noKey;
598 validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds());
599 if (data)
600 record->validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds());
601 GUARD
602 access().Tokend::ClientSession::findRecordHandle(record->tokenHandle(),
603 inAttributes, inAttributesLength, data, hKey, outAttributes, outAttributesLength);
604 rRecord = record;
605 if (hKey != noKey && data) { // tokend returned a key reference & data
606 CssmKey &keyForm = *data->interpretedAs<CssmKey>(CSSMERR_CSP_INVALID_KEY);
607 key = new TokenKey(*this, hKey, keyForm.header());
608 }
609 DONE
610 }
611
612 void TokenDatabase::insertRecord(CSSM_DB_RECORDTYPE recordType,
613 const CssmDbRecordAttributeData *attributes, mach_msg_type_number_t attributesLength,
614 const CssmData &data, RefPointer<Database::Record> &rRecord)
615 {
616 Access access(token());
617 RefPointer<Record> record = new Record(*this);
618 access.add(*record);
619 TRY
620 validate(CSSM_ACL_AUTHORIZATION_DB_INSERT, openCreds());
621 GUARD
622 access().Tokend::ClientSession::insertRecord(recordType,
623 attributes, attributesLength, data, record->tokenHandle());
624 rRecord = record;
625 DONE
626 }
627
628 void TokenDatabase::modifyRecord(CSSM_DB_RECORDTYPE recordType, Record *rRecord,
629 const CssmDbRecordAttributeData *attributes, mach_msg_type_number_t attributesLength,
630 const CssmData *data, CSSM_DB_MODIFY_MODE modifyMode)
631 {
632 Access access(token());
633 Record *record = safe_cast<Record *>(rRecord);
634 access.add(*record);
635 TRY
636 validate(CSSM_ACL_AUTHORIZATION_DB_MODIFY, openCreds());
637 record->validate(CSSM_ACL_AUTHORIZATION_DB_MODIFY, openCreds());
638 GUARD
639 access().Tokend::ClientSession::modifyRecord(recordType,
640 record->tokenHandle(), attributes, attributesLength, data, modifyMode);
641 DONE
642 }
643
644 void TokenDatabase::deleteRecord(Database::Record *rRecord)
645 {
646 Access access(token(), *this);
647 Record *record = safe_cast<Record *>(rRecord);
648 access.add(*record);
649 TRY
650 validate(CSSM_ACL_AUTHORIZATION_DB_DELETE, openCreds());
651 record->validate(CSSM_ACL_AUTHORIZATION_DB_DELETE, openCreds());
652 GUARD
653 access().Tokend::ClientSession::deleteRecord(record->tokenHandle());
654 DONE
655 }
656
657
658 //
659 // Record/Search object handling
660 //
661 TokenDatabase::Search::~Search()
662 {
663 if (mHandle)
664 try {
665 database().token().tokend().Tokend::ClientSession::releaseSearch(mHandle);
666 } catch (...) {
667 secdebug("tokendb", "%p release search handle %ld threw (ignored)",
668 this, mHandle);
669 }
670 }
671
672 TokenDatabase::Record::~Record()
673 {
674 if (mHandle)
675 try {
676 database().token().tokend().Tokend::ClientSession::releaseRecord(mHandle);
677 } catch (...) {
678 secdebug("tokendb", "%p release record handle %ld threw (ignored)",
679 this, mHandle);
680 }
681 }
682
683
684 //
685 // TokenAcl personality of Record
686 //
687 AclKind TokenDatabase::Record::aclKind() const
688 {
689 return objectAcl;
690 }
691
692 Token &TokenDatabase::Record::token()
693 {
694 return safer_cast<TokenDatabase &>(database()).token();
695 }
696
697 GenericHandle TokenDatabase::Record::tokenHandle() const
698 {
699 return Handler::tokenHandle();
700 }
701
702
703 //
704 // Local utility classes
705 //
706 void TokenDatabase::InputKey::setup(Key *key)
707 {
708 if (TokenKey *myKey = dynamic_cast<TokenKey *>(key)) {
709 // one of ours
710 mKeyHandle = myKey->tokenHandle();
711 mKeyPtr = NULL;
712 } else if (LocalKey *hisKey = dynamic_cast<LocalKey *>(key)) {
713 // a local key - turn into raw form
714 CssmClient::WrapKey wrap(Server::csp(), CSSM_ALGID_NONE);
715 wrap(hisKey->cssmKey(), mKey);
716 mKeyHandle = noKey;
717 mKeyPtr = &mKey;
718 } else {
719 // no key at all
720 mKeyHandle = noKey;
721 mKeyPtr = NULL;
722 }
723 }
724
725
726 TokenDatabase::InputKey::~InputKey()
727 {
728 if (mKeyPtr) {
729 //@@@ Server::csp().freeKey(mKey) ??
730 Server::csp()->allocator().free(mKey.keyData());
731 }
732 }