2 * Copyright (c) 2000-2008,2013 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 // tokendatabase - software database container implementation.
28 #include "tokendatabase.h"
30 #include "tokenaccess.h"
33 #include "localkey.h" // to retrieve local raw keys
34 #include <security_cdsa_client/wrapkey.h>
38 // Construct a TokenDbCommon
40 TokenDbCommon::TokenDbCommon(Session
&ssn
, Token
&tk
, const char *name
)
41 : DbCommon(ssn
), mDbName(name
? name
: ""), mHasAclState(false)
43 secinfo("tokendb", "creating tokendbcommon %p: with token %p", this, &tk
);
47 TokenDbCommon::~TokenDbCommon()
49 secinfo("tokendb", "destroying tokendbcommon %p", this);
50 token().removeCommon(*this); // unregister from Token
53 Token
&TokenDbCommon::token() const
55 return parent
<Token
>();
58 std::string
TokenDbCommon::dbName() const
60 return token().printName();
65 // A TokenDbCommon holds per-session adornments for the ACL machine
67 Adornable
&TokenDbCommon::store()
69 StLock
<Mutex
> _(*this);
71 // if this is the first one, hook for lifetime
73 session().addReference(*this); // hold and slave to SSN lifetime
74 token().addCommon(*this); // register with Token
78 // return our (now active) adornments
82 void TokenDbCommon::resetAcls()
84 StLock
<Mutex
> _(*this);
86 clearAdornments(); // clear ACL state
87 session().removeReference(*this); // unhook from SSN
90 token().removeCommon(*this); // unregister from Token
95 // Send out a "keychain" notification for this database
97 void TokenDbCommon::notify(NotificationEvent event
)
99 DbCommon::notify(event
, DLDbIdentifier(dbName().c_str(), gGuidAppleSdCSPDL
,
100 subservice(), CSSM_SERVICE_DL
| CSSM_SERVICE_CSP
));
105 // Process (our part of) a "lock all" request.
106 // Smartcard tokens interpret a "lock" as a forced card reset, transmitted
107 // to tokend as an authenticate request.
108 // @@@ Virtual reset for multi-session tokens. Right now, we're using the sledge hammer.
110 void TokenDbCommon::lockProcessing()
112 Access
access(token());
113 access().authenticate(CSSM_DB_ACCESS_RESET
, NULL
);
117 // Construct a TokenDatabase given subservice information.
118 // We are currently ignoring the 'name' argument.
120 TokenDatabase::TokenDatabase(uint32 ssid
, Process
&proc
,
121 const char *name
, const AccessCredentials
*cred
)
124 // locate Token object
125 RefPointer
<Token
> token
= Token::find(ssid
);
127 Session
&session
= process().session();
128 StLock
<Mutex
> _(session
);
129 if (TokenDbCommon
*dbcom
= session
.findFirst
<TokenDbCommon
, uint32
>(&TokenDbCommon::subservice
, ssid
)) {
131 secinfo("tokendb", "open tokendb %p(%d) at known common %p",
132 this, subservice(), dbcom
);
134 // DbCommon not present; make a new one
135 parent(*new TokenDbCommon(proc
.session(), *token
, name
));
136 secinfo("tokendb", "open tokendb %p(%d) with new common %p",
137 this, subservice(), &common());
139 mOpenCreds
= copy(cred
, Allocator::standard());
140 proc
.addReference(*this);
143 TokenDatabase::~TokenDatabase()
145 Allocator::standard().free(mOpenCreds
);
150 // Basic Database virtual implementations
152 TokenDbCommon
&TokenDatabase::common() const
154 return parent
<TokenDbCommon
>();
157 TokenDaemon
&TokenDatabase::tokend()
159 return common().token().tokend();
162 const char *TokenDatabase::dbName() const
164 //store dbName to ensure that will live outside function scope
165 mDbName
= common().dbName();
166 return mDbName
.c_str();
169 bool TokenDatabase::transient() const
171 //@@@ let tokend decide? Are there any secure transient keystores?
177 // Our ObjectAcl resides in the Token object.
179 SecurityServerAcl
&TokenDatabase::acl()
186 // We post-process the status version of getAcl to account for virtual (per-session)
189 void TokenDatabase::getAcl(const char *tag
, uint32
&count
, AclEntryInfo
*&acls
)
191 AclSource::getAcl(tag
, count
, acls
);
193 for (unsigned n
= 0; n
< count
; n
++) {
194 AclEntryPrototype
&proto
= acls
[n
];
195 uint32_t pin
= pinFromAclTag(proto
.tag(), "?");
196 if (pin
) { // pin state response
197 secinfo("tokendb", "%p updating PIN%d state response", this, pin
);
198 TypedList
&subject
= proto
.subject();
199 // subject == { CSSM_WORID_PIN, pin-number, status [, count ] } # all numbers
200 if (subject
.length() > 2
201 && subject
[0].is(CSSM_LIST_ELEMENT_WORDID
)
202 && subject
[0] == CSSM_WORDID_PIN
203 && subject
[1].is(CSSM_LIST_ELEMENT_WORDID
)
204 && subject
[2].is(CSSM_LIST_ELEMENT_WORDID
)) {
205 uint32_t pin
= subject
[1];
206 #pragma clang diagnostic push
207 #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"
208 // This is likely a bug, but we're trapped by CDSA types
209 if (!common().attachment
<PreAuthorizationAcls::AclState
>((void *) pin
).accepted
) {
210 #pragma clang diagnostic pop
211 // we are not pre-authorized in this session
212 secinfo("tokendb", "%p session state forces PIN%d reporting unauthorized", this, pin
);
213 uint32 status
= subject
[2];
214 status
&= ~CSSM_ACL_PREAUTH_TRACKING_AUTHORIZED
; // clear authorized bit
217 if (subject
.length() > 3 && subject
[3].is(CSSM_LIST_ELEMENT_WORDID
))
218 secinfo("tokendb", "%p PIN%d count=%d", this, pin
, subject
[3].word());
227 bool TokenDatabase::isLocked()
229 Access
access(token());
231 bool lockState
= pinState(1);
232 // bool lockState = access().isLocked();
234 secinfo("tokendb", "returning isLocked=%d", lockState
);
238 bool TokenDatabase::pinState(uint32 pin
, int *pinCount
/* = NULL */)
242 this->getAcl("PIN1?", count
, acls
);
243 bool locked
= true; // preset locked
245 *pinCount
= -1; // preset unknown
248 secinfo("tokendb", "PIN%d query returned no entries", pin
);
251 secinfo("tokendb", "PIN%d query returned multiple entries", pin
);
255 TypedList
&subject
= acls
[0].proto().subject();
256 if (subject
.length() > 2
257 && subject
[0].is(CSSM_LIST_ELEMENT_WORDID
)
258 && subject
[0] == CSSM_WORDID_PIN
259 && subject
[1].is(CSSM_LIST_ELEMENT_WORDID
)
260 && subject
[2].is(CSSM_LIST_ELEMENT_WORDID
)) {
261 uint32 status
= subject
[2];
262 locked
= !(status
& CSSM_ACL_PREAUTH_TRACKING_AUTHORIZED
);
263 if (pinCount
&& locked
&& subject
.length() > 3 && subject
[3].is(CSSM_LIST_ELEMENT_WORDID
))
264 *pinCount
= subject
[3];
270 // release memory allocated by getAcl
271 ChunkFreeWalker free
;
272 for (uint32 n
= 0; n
< count
; n
++)
274 Allocator::standard().free(acls
);
282 // TokenDatabases implement the dbName-setting function.
283 // This sets the print name of the token, which is persistently
284 // stored in the token cache. So this is a de-facto rename of
285 // the token, at least on this system.
287 void TokenDatabase::dbName(const char *name
)
289 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
);
294 // Given a key handle and CssmKey returned from tokend, create a Key representing
295 // it. This takes care of raw returns by turning them into keys of the process's
296 // local transient store.
298 RefPointer
<Key
> TokenDatabase::makeKey(KeyHandle hKey
, const CssmKey
*key
,
299 uint32 moreAttributes
, const AclEntryPrototype
*owner
)
301 switch (key
->blobType()) {
302 case CSSM_KEYBLOB_REFERENCE
:
303 return new TokenKey(*this, hKey
, key
->header());
304 case CSSM_KEYBLOB_RAW
:
305 return process().makeTemporaryKey(*key
, moreAttributes
, owner
);
307 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
); // bad key return from tokend
309 //@@@ Server::releaseWhenDone(key);
314 // Adjust key attributes for newly created keys
316 static CSSM_KEYATTR_FLAGS
modattrs(CSSM_KEYATTR_FLAGS attrs
)
318 static const CSSM_KEYATTR_FLAGS CSSM_KEYATTR_RETURN_FLAGS
= 0xff000000;
319 switch (attrs
& CSSM_KEYATTR_RETURN_FLAGS
) {
320 case CSSM_KEYATTR_RETURN_REF
:
321 case CSSM_KEYATTR_RETURN_DATA
:
322 break; // as requested
323 case CSSM_KEYATTR_RETURN_NONE
:
324 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEYATTR_MASK
);
325 case CSSM_KEYATTR_RETURN_DEFAULT
:
326 if (attrs
& CSSM_KEYATTR_PERMANENT
)
327 attrs
|= CSSM_KEYATTR_RETURN_REF
;
329 attrs
|= CSSM_KEYATTR_RETURN_DATA
;
337 // TokenDatabases support remote secret validation by sending a secret
338 // (aka passphrase et al) to tokend for processing.
340 bool TokenDatabase::validateSecret(const AclSubject
*subject
, const AccessCredentials
*cred
)
342 secinfo("tokendb", "%p attempting remote validation", this);
344 Access
access(token());
345 // @@@ Use cached mode
346 access().authenticate(CSSM_DB_ACCESS_READ
, cred
);
347 secinfo("tokendb", "%p remote validation successful", this);
351 secinfo("tokendb", "%p remote validation failed", this);
353 throw; // try not to mask error
361 void TokenDatabase::queryKeySizeInBits(Key
&key
, CssmKeySize
&result
)
363 Access
access(token());
366 access().queryKeySizeInBits(myKey(key
).tokenHandle(), result
);
372 // Signatures and MACs
374 void TokenDatabase::generateSignature(const Context
&context
, Key
&key
,
375 CSSM_ALGORITHMS signOnlyAlgorithm
, const CssmData
&data
, CssmData
&signature
)
377 Access
access(token(), key
);
379 key
.validate(CSSM_ACL_AUTHORIZATION_SIGN
, context
);
381 access().generateSignature(context
, myKey(key
).tokenHandle(), data
, signature
, signOnlyAlgorithm
);
386 void TokenDatabase::verifySignature(const Context
&context
, Key
&key
,
387 CSSM_ALGORITHMS verifyOnlyAlgorithm
, const CssmData
&data
, const CssmData
&signature
)
389 Access
access(token(), key
);
392 access().verifySignature(context
, myKey(key
).tokenHandle(), data
, signature
, verifyOnlyAlgorithm
);
396 void TokenDatabase::generateMac(const Context
&context
, Key
&key
,
397 const CssmData
&data
, CssmData
&mac
)
399 Access
access(token());
401 key
.validate(CSSM_ACL_AUTHORIZATION_MAC
, context
);
403 access().generateMac(context
, myKey(key
).tokenHandle(), data
, mac
);
407 void TokenDatabase::verifyMac(const Context
&context
, Key
&key
,
408 const CssmData
&data
, const CssmData
&mac
)
410 Access
access(token());
412 key
.validate(CSSM_ACL_AUTHORIZATION_MAC
, context
);
414 access().verifyMac(context
, myKey(key
).tokenHandle(), data
, mac
);
420 // Encryption/decryption
422 void TokenDatabase::encrypt(const Context
&context
, Key
&key
,
423 const CssmData
&clear
, CssmData
&cipher
)
425 Access
access(token());
427 key
.validate(CSSM_ACL_AUTHORIZATION_ENCRYPT
, context
);
429 access().encrypt(context
, myKey(key
).tokenHandle(), clear
, cipher
);
434 void TokenDatabase::decrypt(const Context
&context
, Key
&key
,
435 const CssmData
&cipher
, CssmData
&clear
)
437 Access
access(token());
439 key
.validate(CSSM_ACL_AUTHORIZATION_DECRYPT
, context
);
441 access().decrypt(context
, myKey(key
).tokenHandle(), cipher
, clear
);
447 // Key generation and derivation.
448 // Currently, we consider symmetric key generation to be fast, but
449 // asymmetric key generation to be (potentially) slow.
451 void TokenDatabase::generateKey(const Context
&context
,
452 const AccessCredentials
*cred
, const AclEntryPrototype
*owner
,
453 CSSM_KEYUSE usage
, CSSM_KEYATTR_FLAGS attrs
, RefPointer
<Key
> &newKey
)
455 Access
access(token());
460 access().generateKey(context
, cred
, owner
, usage
, modattrs(attrs
), hKey
, result
);
461 newKey
= makeKey(hKey
, result
, 0, owner
);
465 void TokenDatabase::generateKey(const Context
&context
,
466 const AccessCredentials
*cred
, const AclEntryPrototype
*owner
,
467 CSSM_KEYUSE pubUsage
, CSSM_KEYATTR_FLAGS pubAttrs
,
468 CSSM_KEYUSE privUsage
, CSSM_KEYATTR_FLAGS privAttrs
,
469 RefPointer
<Key
> &publicKey
, RefPointer
<Key
> &privateKey
)
471 Access
access(token());
474 KeyHandle hPrivate
, hPublic
;
475 CssmKey
*privKey
, *pubKey
;
476 access().generateKey(context
, cred
, owner
,
477 pubUsage
, modattrs(pubAttrs
), privUsage
, modattrs(privAttrs
),
478 hPublic
, pubKey
, hPrivate
, privKey
);
479 publicKey
= makeKey(hPublic
, pubKey
, 0, owner
);
480 privateKey
= makeKey(hPrivate
, privKey
, 0, owner
);
486 // Key wrapping and unwrapping.
487 // Note that the key argument (the key in the context) is optional because of the special
488 // case of "cleartext" (null algorithm) wrapping for import/export.
490 void TokenDatabase::wrapKey(const Context
&context
, const AccessCredentials
*cred
,
491 Key
*wrappingKey
, Key
&subjectKey
,
492 const CssmData
&descriptiveData
, CssmKey
&wrappedKey
)
494 Access
access(token());
495 InputKey
cWrappingKey(wrappingKey
);
496 InputKey
cSubjectKey(subjectKey
);
498 subjectKey
.validate(context
.algorithm() == CSSM_ALGID_NONE
?
499 CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR
: CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED
,
502 wrappingKey
->validate(CSSM_ACL_AUTHORIZATION_ENCRYPT
, context
);
504 CssmKey
*rWrappedKey
;
505 access().wrapKey(context
, cred
,
506 cWrappingKey
, cWrappingKey
, cSubjectKey
, cSubjectKey
,
507 descriptiveData
, rWrappedKey
);
508 wrappedKey
= *rWrappedKey
;
509 //@@@ ownership of wrappedKey.keyData() ??
513 void TokenDatabase::unwrapKey(const Context
&context
,
514 const AccessCredentials
*cred
, const AclEntryPrototype
*owner
,
515 Key
*wrappingKey
, Key
*publicKey
, CSSM_KEYUSE usage
, CSSM_KEYATTR_FLAGS attrs
,
516 const CssmKey wrappedKey
, RefPointer
<Key
> &unwrappedKey
, CssmData
&descriptiveData
)
518 Access
access(token());
519 InputKey
cWrappingKey(wrappingKey
);
520 InputKey
cPublicKey(publicKey
);
523 wrappingKey
->validate(CSSM_ACL_AUTHORIZATION_DECRYPT
, context
);
524 // we are not checking access on the public key, if any
528 access().unwrapKey(context
, cred
, owner
,
529 cWrappingKey
, cWrappingKey
, cPublicKey
, cPublicKey
,
530 wrappedKey
, usage
, modattrs(attrs
), descriptiveData
, hKey
, result
);
531 unwrappedKey
= makeKey(hKey
, result
, modattrs(attrs
) & LocalKey::managedAttributes
, owner
);
539 void TokenDatabase::deriveKey(const Context
&context
, Key
*sourceKey
,
540 const AccessCredentials
*cred
, const AclEntryPrototype
*owner
,
541 CssmData
*param
, CSSM_KEYUSE usage
, CSSM_KEYATTR_FLAGS attrs
, RefPointer
<Key
> &derivedKey
)
543 Access
access(token());
544 InputKey
cSourceKey(sourceKey
);
547 sourceKey
->validate(CSSM_ACL_AUTHORIZATION_DERIVE
, cred
);
551 CssmData params
= param
? *param
: CssmData();
552 access().deriveKey(noDb
, context
,
553 cSourceKey
, cSourceKey
,
554 usage
, modattrs(attrs
), params
, cred
, owner
,
558 //@@@ leak? what's the rule here?
560 derivedKey
= makeKey(hKey
, result
, 0, owner
);
566 // Miscellaneous CSSM functions
568 void TokenDatabase::getOutputSize(const Context
&context
, Key
&key
,
569 uint32 inputSize
, bool encrypt
, uint32
&result
)
571 Access
access(token());
574 access().getOutputSize(context
, myKey(key
).tokenHandle(), inputSize
, encrypt
, result
);
580 // (Re-)Authenticate the database.
581 // We use dbAuthenticate as the catch-all "do something about authentication" call.
583 void TokenDatabase::authenticate(CSSM_DB_ACCESS_TYPE mode
, const AccessCredentials
*cred
)
585 Access
access(token());
588 if (mode
!= CSSM_DB_ACCESS_RESET
&& cred
) {
589 secinfo("tokendb", "%p authenticate calling validate", this);
590 if (unsigned pin
= pinFromAclTag(cred
->EntryTag
)) {
591 validate(CSSM_ACL_AUTHORIZATION_PREAUTH(pin
), cred
);
592 notify(kNotificationEventUnlocked
);
597 access().authenticate(mode
, cred
);
599 case CSSM_DB_ACCESS_RESET
:
600 // this mode is known to trigger "lockdown" (i.e. reset)
601 common().resetAcls();
602 notify(kNotificationEventLocked
);
606 // no idea what that did to the token;
607 // But let's remember the new creds for our own sake.
608 AccessCredentials
*newCred
= copy(cred
, Allocator::standard());
609 Allocator::standard().free(mOpenCreds
);
610 mOpenCreds
= newCred
;
618 // Data access interface.
620 // Note that the attribute vectors are passed between our two IPC interfaces
621 // as relocated but contiguous memory blocks (to avoid an extra copy). This means
622 // you can read them at will, but can't change them in transit unless you're
623 // willing to repack them right here.
625 void TokenDatabase::findFirst(const CssmQuery
&query
,
626 CssmDbRecordAttributeData
*inAttributes
, mach_msg_type_number_t inAttributesLength
,
627 CssmData
*data
, RefPointer
<Key
> &key
,
628 RefPointer
<Database::Search
> &rSearch
, RefPointer
<Database::Record
> &rRecord
,
629 CssmDbRecordAttributeData
* &outAttributes
, mach_msg_type_number_t
&outAttributesLength
)
631 Access
access(token());
632 RefPointer
<Search
> search
= new Search(*this);
633 RefPointer
<Record
> record
= new Record(*this);
635 KeyHandle hKey
= noKey
;
636 validate(CSSM_ACL_AUTHORIZATION_DB_READ
, openCreds());
638 record
->tokenHandle() = access().Tokend::ClientSession::findFirst(query
,
639 inAttributes
, inAttributesLength
, search
->tokenHandle(), NULL
, hKey
,
640 outAttributes
, outAttributesLength
);
641 if (!record
->tokenHandle()) { // no match (but no other error)
642 rRecord
= NULL
; // return null record
647 record
->validate(CSSM_ACL_AUTHORIZATION_DB_READ
, openCreds());
648 CssmDbRecordAttributeData
*noAttributes
;
649 mach_msg_type_number_t noAttributesLength
;
650 access().Tokend::ClientSession::findRecordHandle(record
->tokenHandle(),
651 NULL
, 0, data
, hKey
, noAttributes
, noAttributesLength
);
652 if (hKey
) { // tokend returned a key reference & data
653 CssmKey
&keyForm
= *data
->interpretedAs
<CssmKey
>(CSSMERR_CSP_INVALID_KEY
);
654 key
= new TokenKey(*this, hKey
, keyForm
.header());
657 rSearch
= search
->commit();
658 rRecord
= record
->commit();
662 void TokenDatabase::findNext(Database::Search
*rSearch
,
663 CssmDbRecordAttributeData
*inAttributes
, mach_msg_type_number_t inAttributesLength
,
664 CssmData
*data
, RefPointer
<Key
> &key
, RefPointer
<Database::Record
> &rRecord
,
665 CssmDbRecordAttributeData
* &outAttributes
, mach_msg_type_number_t
&outAttributesLength
)
667 Access
access(token());
668 RefPointer
<Record
> record
= new Record(*this);
669 Search
*search
= safe_cast
<Search
*>(rSearch
);
671 KeyHandle hKey
= noKey
;
672 validate(CSSM_ACL_AUTHORIZATION_DB_READ
, openCreds());
674 record
->tokenHandle() = access().Tokend::ClientSession::findNext(
675 search
->tokenHandle(), inAttributes
, inAttributesLength
,
676 NULL
, hKey
, outAttributes
, outAttributesLength
);
677 if (!record
->tokenHandle()) { // no more matches
678 releaseSearch(*search
); // release search handle (consumed by EOD)
679 rRecord
= NULL
; // return null record
684 record
->validate(CSSM_ACL_AUTHORIZATION_DB_READ
, openCreds());
685 CssmDbRecordAttributeData
*noAttributes
;
686 mach_msg_type_number_t noAttributesLength
;
687 access().Tokend::ClientSession::findRecordHandle(record
->tokenHandle(),
688 NULL
, 0, data
, hKey
, noAttributes
, noAttributesLength
);
689 if (hKey
) { // tokend returned a key reference & data
690 CssmKey
&keyForm
= *data
->interpretedAs
<CssmKey
>(CSSMERR_CSP_INVALID_KEY
);
691 key
= new TokenKey(*this, hKey
, keyForm
.header());
694 rRecord
= record
->commit();
698 void TokenDatabase::findRecordHandle(Database::Record
*rRecord
,
699 CssmDbRecordAttributeData
*inAttributes
, mach_msg_type_number_t inAttributesLength
,
700 CssmData
*data
, RefPointer
<Key
> &key
,
701 CssmDbRecordAttributeData
* &outAttributes
, mach_msg_type_number_t
&outAttributesLength
)
703 Access
access(token());
704 Record
*record
= safe_cast
<Record
*>(rRecord
);
707 KeyHandle hKey
= noKey
;
708 validate(CSSM_ACL_AUTHORIZATION_DB_READ
, openCreds());
710 record
->validate(CSSM_ACL_AUTHORIZATION_DB_READ
, openCreds());
712 access().Tokend::ClientSession::findRecordHandle(record
->tokenHandle(),
713 inAttributes
, inAttributesLength
, data
, hKey
, outAttributes
, outAttributesLength
);
714 if (hKey
!= noKey
&& data
) { // tokend returned a key reference & data
715 CssmKey
&keyForm
= *data
->interpretedAs
<CssmKey
>(CSSMERR_CSP_INVALID_KEY
);
716 key
= new TokenKey(*this, hKey
, keyForm
.header());
721 void TokenDatabase::tokenInsertRecord(CSSM_DB_RECORDTYPE recordType
,
722 const CssmDbRecordAttributeData
*attributes
, mach_msg_type_number_t attributesLength
,
723 const CssmData
&data
, RefPointer
<Database::Record
> &rRecord
)
725 Access
access(token());
726 RefPointer
<Record
> record
= new Record(*this);
729 validate(CSSM_ACL_AUTHORIZATION_DB_INSERT
, openCreds());
731 access().Tokend::ClientSession::insertRecord(recordType
,
732 attributes
, attributesLength
, data
, record
->tokenHandle());
737 void TokenDatabase::modifyRecord(CSSM_DB_RECORDTYPE recordType
, Database::Record
*rRecord
,
738 const CssmDbRecordAttributeData
*attributes
, mach_msg_type_number_t attributesLength
,
739 const CssmData
*data
, CSSM_DB_MODIFY_MODE modifyMode
)
741 Access
access(token());
742 TokenDatabase::Record
*record
= safe_cast
<TokenDatabase::Record
*>(rRecord
);
745 validate(CSSM_ACL_AUTHORIZATION_DB_MODIFY
, openCreds());
746 record
->validate(CSSM_ACL_AUTHORIZATION_DB_MODIFY
, openCreds());
748 access().Tokend::ClientSession::modifyRecord(recordType
,
749 record
->tokenHandle(), attributes
, attributesLength
, data
, modifyMode
);
753 void TokenDatabase::deleteRecord(Database::Record
*rRecord
)
755 Access
access(token(), *this);
756 Record
*record
= safe_cast
<Record
*>(rRecord
);
759 validate(CSSM_ACL_AUTHORIZATION_DB_DELETE
, openCreds());
760 record
->validate(CSSM_ACL_AUTHORIZATION_DB_DELETE
, openCreds());
762 access().Tokend::ClientSession::deleteRecord(record
->tokenHandle());
768 // Record/Search object handling
770 TokenDatabase::Search::~Search()
774 database().token().tokend().Tokend::ClientSession::releaseSearch(mHandle
);
776 secinfo("tokendb", "%p release search handle %u threw (ignored)",
781 TokenDatabase::Record::~Record()
785 database().token().tokend().Tokend::ClientSession::releaseRecord(mHandle
);
787 secinfo("tokendb", "%p release record handle %u threw (ignored)",
794 // TokenAcl personality of Record
796 AclKind
TokenDatabase::Record::aclKind() const
801 Token
&TokenDatabase::Record::token()
803 return safer_cast
<TokenDatabase
&>(database()).token();
806 GenericHandle
TokenDatabase::Record::tokenHandle() const
808 return Handler::tokenHandle();
813 // Local utility classes
815 void TokenDatabase::InputKey::setup(Key
*key
)
817 if (TokenKey
*myKey
= dynamic_cast<TokenKey
*>(key
)) {
819 mKeyHandle
= myKey
->tokenHandle();
821 } else if (LocalKey
*hisKey
= dynamic_cast<LocalKey
*>(key
)) {
822 // a local key - turn into raw form
823 CssmClient::WrapKey
wrap(Server::csp(), CSSM_ALGID_NONE
);
824 wrap(hisKey
->cssmKey(), mKey
);
835 TokenDatabase::InputKey::~InputKey()
838 //@@@ Server::csp().freeKey(mKey) ??
839 Server::csp()->allocator().free(mKey
.keyData());