]> git.saurik.com Git - apple/securityd.git/blob - src/tokendatabase.cpp
securityd-27887.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 const std::string &TokenDbCommon::dbName() const
52 {
53 return token().printName();
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 }
237 catch (...) {
238 secdebug("tokendb", "%p remote validation failed", this);
239 // return false;
240 throw; // try not to mask error
241 }
242 }
243
244
245 //
246 // Key inquiries
247 //
248 void TokenDatabase::queryKeySizeInBits(Key &key, CssmKeySize &result)
249 {
250 Access access(token());
251 TRY
252 GUARD
253 access().queryKeySizeInBits(myKey(key).tokenHandle(), result);
254 DONE
255 }
256
257
258 //
259 // Signatures and MACs
260 //
261 void TokenDatabase::generateSignature(const Context &context, Key &key,
262 CSSM_ALGORITHMS signOnlyAlgorithm, const CssmData &data, CssmData &signature)
263 {
264 Access access(token(), key);
265 TRY
266 key.validate(CSSM_ACL_AUTHORIZATION_SIGN, context);
267 GUARD
268 access().generateSignature(context, myKey(key).tokenHandle(), data, signature, signOnlyAlgorithm);
269 DONE
270 }
271
272
273 void TokenDatabase::verifySignature(const Context &context, Key &key,
274 CSSM_ALGORITHMS verifyOnlyAlgorithm, const CssmData &data, const CssmData &signature)
275 {
276 Access access(token(), key);
277 TRY
278 GUARD
279 access().verifySignature(context, myKey(key).tokenHandle(), data, signature, verifyOnlyAlgorithm);
280 DONE
281 }
282
283 void TokenDatabase::generateMac(const Context &context, Key &key,
284 const CssmData &data, CssmData &mac)
285 {
286 Access access(token());
287 TRY
288 key.validate(CSSM_ACL_AUTHORIZATION_MAC, context);
289 GUARD
290 access().generateMac(context, myKey(key).tokenHandle(), data, mac);
291 DONE
292 }
293
294 void TokenDatabase::verifyMac(const Context &context, Key &key,
295 const CssmData &data, const CssmData &mac)
296 {
297 Access access(token());
298 TRY
299 key.validate(CSSM_ACL_AUTHORIZATION_MAC, context);
300 GUARD
301 access().verifyMac(context, myKey(key).tokenHandle(), data, mac);
302 DONE
303 }
304
305
306 //
307 // Encryption/decryption
308 //
309 void TokenDatabase::encrypt(const Context &context, Key &key,
310 const CssmData &clear, CssmData &cipher)
311 {
312 Access access(token());
313 TRY
314 key.validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context);
315 GUARD
316 access().encrypt(context, myKey(key).tokenHandle(), clear, cipher);
317 DONE
318 }
319
320
321 void TokenDatabase::decrypt(const Context &context, Key &key,
322 const CssmData &cipher, CssmData &clear)
323 {
324 Access access(token());
325 TRY
326 key.validate(CSSM_ACL_AUTHORIZATION_DECRYPT, context);
327 GUARD
328 access().decrypt(context, myKey(key).tokenHandle(), cipher, clear);
329 DONE
330 }
331
332
333 //
334 // Key generation and derivation.
335 // Currently, we consider symmetric key generation to be fast, but
336 // asymmetric key generation to be (potentially) slow.
337 //
338 void TokenDatabase::generateKey(const Context &context,
339 const AccessCredentials *cred, const AclEntryPrototype *owner,
340 CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, RefPointer<Key> &newKey)
341 {
342 Access access(token());
343 TRY
344 GUARD
345 KeyHandle hKey;
346 CssmKey *result;
347 access().generateKey(context, cred, owner, usage, modattrs(attrs), hKey, result);
348 newKey = makeKey(hKey, result, owner);
349 DONE
350 }
351
352 void TokenDatabase::generateKey(const Context &context,
353 const AccessCredentials *cred, const AclEntryPrototype *owner,
354 CSSM_KEYUSE pubUsage, CSSM_KEYATTR_FLAGS pubAttrs,
355 CSSM_KEYUSE privUsage, CSSM_KEYATTR_FLAGS privAttrs,
356 RefPointer<Key> &publicKey, RefPointer<Key> &privateKey)
357 {
358 Access access(token());
359 TRY
360 GUARD
361 KeyHandle hPrivate, hPublic;
362 CssmKey *privKey, *pubKey;
363 access().generateKey(context, cred, owner,
364 pubUsage, modattrs(pubAttrs), privUsage, modattrs(privAttrs),
365 hPublic, pubKey, hPrivate, privKey);
366 publicKey = makeKey(hPublic, pubKey, owner);
367 privateKey = makeKey(hPrivate, privKey, owner);
368 DONE
369 }
370
371
372 //
373 // Key wrapping and unwrapping.
374 // Note that the key argument (the key in the context) is optional because of the special
375 // case of "cleartext" (null algorithm) wrapping for import/export.
376 //
377 void TokenDatabase::wrapKey(const Context &context, const AccessCredentials *cred,
378 Key *wrappingKey, Key &subjectKey,
379 const CssmData &descriptiveData, CssmKey &wrappedKey)
380 {
381 Access access(token());
382 InputKey cWrappingKey(wrappingKey);
383 InputKey cSubjectKey(subjectKey);
384 TRY
385 subjectKey.validate(context.algorithm() == CSSM_ALGID_NONE ?
386 CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR : CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED,
387 cred);
388 if (wrappingKey)
389 wrappingKey->validate(CSSM_ACL_AUTHORIZATION_ENCRYPT, context);
390 GUARD
391 CssmKey *rWrappedKey;
392 access().wrapKey(context, cred,
393 cWrappingKey, cWrappingKey, cSubjectKey, cSubjectKey,
394 descriptiveData, rWrappedKey);
395 wrappedKey = *rWrappedKey;
396 //@@@ ownership of wrappedKey.keyData() ??
397 DONE
398 }
399
400 void TokenDatabase::unwrapKey(const Context &context,
401 const AccessCredentials *cred, const AclEntryPrototype *owner,
402 Key *wrappingKey, Key *publicKey, CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs,
403 const CssmKey wrappedKey, RefPointer<Key> &unwrappedKey, CssmData &descriptiveData)
404 {
405 Access access(token());
406 InputKey cWrappingKey(wrappingKey);
407 InputKey cPublicKey(publicKey);
408 TRY
409 if (wrappingKey)
410 wrappingKey->validate(CSSM_ACL_AUTHORIZATION_DECRYPT, context);
411 // we are not checking access on the public key, if any
412 GUARD
413 KeyHandle hKey;
414 CssmKey *result;
415 access().unwrapKey(context, cred, owner,
416 cWrappingKey, cWrappingKey, cPublicKey, cPublicKey,
417 wrappedKey, usage, modattrs(attrs), descriptiveData, hKey, result);
418 unwrappedKey = makeKey(hKey, result, owner);
419 DONE
420 }
421
422
423 //
424 // Key derivation
425 //
426 void TokenDatabase::deriveKey(const Context &context, Key *sourceKey,
427 const AccessCredentials *cred, const AclEntryPrototype *owner,
428 CssmData *param, CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, RefPointer<Key> &derivedKey)
429 {
430 Access access(token());
431 InputKey cSourceKey(sourceKey);
432 TRY
433 if (sourceKey)
434 sourceKey->validate(CSSM_ACL_AUTHORIZATION_DERIVE, cred);
435 GUARD
436 KeyHandle hKey;
437 CssmKey *result;
438 CssmData params = param ? *param : CssmData();
439 access().deriveKey(noDb, context,
440 cSourceKey, cSourceKey,
441 usage, modattrs(attrs), params, cred, owner,
442 hKey, result);
443 if (param) {
444 *param = params;
445 //@@@ leak? what's the rule here?
446 }
447 derivedKey = makeKey(hKey, result, owner);
448 DONE
449 }
450
451
452 //
453 // Miscellaneous CSSM functions
454 //
455 void TokenDatabase::getOutputSize(const Context &context, Key &key,
456 uint32 inputSize, bool encrypt, uint32 &result)
457 {
458 Access access(token());
459 TRY
460 GUARD
461 access().getOutputSize(context, myKey(key).tokenHandle(), inputSize, encrypt, result);
462 DONE
463 }
464
465
466 //
467 // (Re-)Authenticate the database.
468 // We use dbAuthenticate as the catch-all "do something about authentication" call.
469 //
470 void TokenDatabase::authenticate(CSSM_DB_ACCESS_TYPE mode, const AccessCredentials *cred)
471 {
472 Access access(token());
473 TRY
474 GUARD
475 if (mode != CSSM_DB_ACCESS_RESET && cred) {
476 secdebug("tokendb", "%p authenticate calling validate", this);
477 int pin;
478 if (sscanf(cred->EntryTag, "PIN%d", &pin) == 1)
479 return validate(CSSM_ACL_AUTHORIZATION_PREAUTH(pin), cred);
480 }
481
482 access().authenticate(mode, cred);
483 switch (mode) {
484 case CSSM_DB_ACCESS_RESET:
485 // this mode is known to trigger "lockdown" (i.e. reset)
486 common().resetAcls();
487 break;
488 default:
489 {
490 // no idea what that did to the token;
491 // But let's remember the new creds for our own sake.
492 AccessCredentials *newCred = copy(cred, Allocator::standard());
493 Allocator::standard().free(mOpenCreds);
494 mOpenCreds = newCred;
495 break;
496 }
497 }
498 DONE
499 }
500
501 //
502 // Data access interface.
503 //
504 // Note that the attribute vectors are passed between our two IPC interfaces
505 // as relocated but contiguous memory blocks (to avoid an extra copy). This means
506 // you can read them at will, but can't change them in transit unless you're
507 // willing to repack them right here.
508 //
509 void TokenDatabase::findFirst(const CssmQuery &query,
510 CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength,
511 CssmData *data, RefPointer<Key> &key,
512 RefPointer<Database::Search> &rSearch, RefPointer<Database::Record> &rRecord,
513 CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength)
514 {
515 Access access(token());
516 RefPointer<Search> search = new Search(*this);
517 RefPointer<Record> record = new Record(*this);
518 TRY
519 KeyHandle hKey = noKey;
520 validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds());
521 GUARD
522 record->tokenHandle() = access().Tokend::ClientSession::findFirst(query,
523 inAttributes, inAttributesLength, search->tokenHandle(), NULL, hKey,
524 outAttributes, outAttributesLength);
525 if (!record->tokenHandle()) { // no match (but no other error)
526 rRecord = NULL; // return null record
527 return;
528 }
529 if (data) {
530 if (!hKey)
531 record->validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds());
532 CssmDbRecordAttributeData *noAttributes;
533 mach_msg_type_number_t noAttributesLength;
534 access().Tokend::ClientSession::findRecordHandle(record->tokenHandle(),
535 NULL, 0, data, hKey, noAttributes, noAttributesLength);
536 if (hKey) { // tokend returned a key reference & data
537 CssmKey &keyForm = *data->interpretedAs<CssmKey>(CSSMERR_CSP_INVALID_KEY);
538 key = new TokenKey(*this, hKey, keyForm.header());
539 }
540 }
541 rSearch = search->commit();
542 rRecord = record->commit();
543 DONE
544 }
545
546 void TokenDatabase::findNext(Database::Search *rSearch,
547 CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength,
548 CssmData *data, RefPointer<Key> &key, RefPointer<Database::Record> &rRecord,
549 CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength)
550 {
551 Access access(token());
552 RefPointer<Record> record = new Record(*this);
553 Search *search = safe_cast<Search *>(rSearch);
554 TRY
555 KeyHandle hKey = noKey;
556 validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds());
557 GUARD
558 record->tokenHandle() = access().Tokend::ClientSession::findNext(
559 search->tokenHandle(), inAttributes, inAttributesLength,
560 NULL, hKey, outAttributes, outAttributesLength);
561 if (!record->tokenHandle()) { // no more matches
562 releaseSearch(*search); // release search handle (consumed by EOD)
563 rRecord = NULL; // return null record
564 return;
565 }
566 if (data) {
567 if (!hKey)
568 record->validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds());
569 CssmDbRecordAttributeData *noAttributes;
570 mach_msg_type_number_t noAttributesLength;
571 access().Tokend::ClientSession::findRecordHandle(record->tokenHandle(),
572 NULL, 0, data, hKey, noAttributes, noAttributesLength);
573 if (hKey) { // tokend returned a key reference & data
574 CssmKey &keyForm = *data->interpretedAs<CssmKey>(CSSMERR_CSP_INVALID_KEY);
575 key = new TokenKey(*this, hKey, keyForm.header());
576 }
577 }
578 rRecord = record->commit();
579 DONE
580 }
581
582 void TokenDatabase::findRecordHandle(Database::Record *rRecord,
583 CssmDbRecordAttributeData *inAttributes, mach_msg_type_number_t inAttributesLength,
584 CssmData *data, RefPointer<Key> &key,
585 CssmDbRecordAttributeData * &outAttributes, mach_msg_type_number_t &outAttributesLength)
586 {
587 Access access(token());
588 Record *record = safe_cast<Record *>(rRecord);
589 access.add(*record);
590 TRY
591 KeyHandle hKey = noKey;
592 validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds());
593 if (data)
594 record->validate(CSSM_ACL_AUTHORIZATION_DB_READ, openCreds());
595 GUARD
596 access().Tokend::ClientSession::findRecordHandle(record->tokenHandle(),
597 inAttributes, inAttributesLength, data, hKey, outAttributes, outAttributesLength);
598 rRecord = record;
599 if (hKey != noKey && data) { // tokend returned a key reference & data
600 CssmKey &keyForm = *data->interpretedAs<CssmKey>(CSSMERR_CSP_INVALID_KEY);
601 key = new TokenKey(*this, hKey, keyForm.header());
602 }
603 DONE
604 }
605
606 void TokenDatabase::insertRecord(CSSM_DB_RECORDTYPE recordType,
607 const CssmDbRecordAttributeData *attributes, mach_msg_type_number_t attributesLength,
608 const CssmData &data, RefPointer<Database::Record> &rRecord)
609 {
610 Access access(token());
611 RefPointer<Record> record = new Record(*this);
612 access.add(*record);
613 TRY
614 validate(CSSM_ACL_AUTHORIZATION_DB_INSERT, openCreds());
615 GUARD
616 access().Tokend::ClientSession::insertRecord(recordType,
617 attributes, attributesLength, data, record->tokenHandle());
618 rRecord = record;
619 DONE
620 }
621
622 void TokenDatabase::modifyRecord(CSSM_DB_RECORDTYPE recordType, Record *rRecord,
623 const CssmDbRecordAttributeData *attributes, mach_msg_type_number_t attributesLength,
624 const CssmData *data, CSSM_DB_MODIFY_MODE modifyMode)
625 {
626 Access access(token());
627 Record *record = safe_cast<Record *>(rRecord);
628 access.add(*record);
629 TRY
630 validate(CSSM_ACL_AUTHORIZATION_DB_MODIFY, openCreds());
631 record->validate(CSSM_ACL_AUTHORIZATION_DB_MODIFY, openCreds());
632 GUARD
633 access().Tokend::ClientSession::modifyRecord(recordType,
634 record->tokenHandle(), attributes, attributesLength, data, modifyMode);
635 DONE
636 }
637
638 void TokenDatabase::deleteRecord(Database::Record *rRecord)
639 {
640 Access access(token(), *this);
641 Record *record = safe_cast<Record *>(rRecord);
642 access.add(*record);
643 TRY
644 validate(CSSM_ACL_AUTHORIZATION_DB_DELETE, openCreds());
645 record->validate(CSSM_ACL_AUTHORIZATION_DB_DELETE, openCreds());
646 GUARD
647 access().Tokend::ClientSession::deleteRecord(record->tokenHandle());
648 DONE
649 }
650
651
652 //
653 // Record/Search object handling
654 //
655 TokenDatabase::Search::~Search()
656 {
657 if (mHandle)
658 try {
659 database().token().tokend().Tokend::ClientSession::releaseSearch(mHandle);
660 } catch (...) {
661 secdebug("tokendb", "%p release search handle %ld threw (ignored)",
662 this, mHandle);
663 }
664 }
665
666 TokenDatabase::Record::~Record()
667 {
668 if (mHandle)
669 try {
670 database().token().tokend().Tokend::ClientSession::releaseRecord(mHandle);
671 } catch (...) {
672 secdebug("tokendb", "%p release record handle %ld threw (ignored)",
673 this, mHandle);
674 }
675 }
676
677
678 //
679 // TokenAcl personality of Record
680 //
681 AclKind TokenDatabase::Record::aclKind() const
682 {
683 return objectAcl;
684 }
685
686 Token &TokenDatabase::Record::token()
687 {
688 return safer_cast<TokenDatabase &>(database()).token();
689 }
690
691 GenericHandle TokenDatabase::Record::tokenHandle() const
692 {
693 return Handler::tokenHandle();
694 }
695
696
697 //
698 // Local utility classes
699 //
700 void TokenDatabase::InputKey::setup(Key *key)
701 {
702 if (TokenKey *myKey = dynamic_cast<TokenKey *>(key)) {
703 // one of ours
704 mKeyHandle = myKey->tokenHandle();
705 mKeyPtr = NULL;
706 } else if (LocalKey *hisKey = dynamic_cast<LocalKey *>(key)) {
707 // a local key - turn into raw form
708 CssmClient::WrapKey wrap(Server::csp(), CSSM_ALGID_NONE);
709 wrap(hisKey->cssmKey(), mKey);
710 mKeyHandle = noKey;
711 mKeyPtr = &mKey;
712 } else {
713 // no key at all
714 mKeyHandle = noKey;
715 mKeyPtr = NULL;
716 }
717 }
718
719
720 TokenDatabase::InputKey::~InputKey()
721 {
722 if (mKeyPtr) {
723 //@@@ Server::csp().freeKey(mKey) ??
724 Server::csp()->allocator().free(mKey.keyData());
725 }
726 }