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