1/*
2 *  Copyright (c) 2004 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#include "transit.h"
24
25
26namespace Security {
27namespace Tokend {
28
29
30//
31// Relocation support
32//
33void relocate(Context &context, void *base, Context::Attr *attrs, uint32 attrSize)
34{
35	ReconstituteWalker relocator(attrs, base);
36	context.ContextAttributes = attrs;	// fix context->attr vector link
37	for (uint32 n = 0; n < context.attributesInUse(); n++)
38		walk(relocator, context[n]);
39}
40
41
42//
43// Data search and retrieval interface
44//
45DataRetrieval::DataRetrieval(CssmDbRecordAttributeData *inAttributes, bool getData)
46{
47	this->attributes = inAttributes;
48	this->data = getData ? &mData : NULL;
49	this->record = CSSM_INVALID_HANDLE;
50	this->keyhandle = CSSM_INVALID_HANDLE;
51}
52
53
54DataRetrieval::~DataRetrieval()
55{
56}
57
58
59void DataRetrieval::returnData(KeyHandle &hKey, RecordHandle &hRecord,
60	void *&outData, mach_msg_type_number_t &outDataLength,
61	CssmDbRecordAttributeData *&outAttributes, mach_msg_type_number_t &outAttributesLength,
62	CssmDbRecordAttributeData *&outAttributesBase)
63{
64	Copier<CssmDbRecordAttributeData> outCopy(CssmDbRecordAttributeData::overlay(this->attributes));
65	outAttributesLength = outCopy.length();
66	outAttributes = outAttributesBase = outCopy.keep();
67	if (this->data) {
68		outData = this->data->Data;
69		outDataLength = this->data->Length;
70	} else {
71		outData = NULL;
72		outDataLength = 0;
73	}
74
75	/*
76		"record" and "keyhandle" below come from the underlying TOKEND_RETURN_DATA,
77		and are native-sized quantities. These need to be converted to a client
78		handle (32 bit)
79	 */
80
81	hKey = (this->keyhandle)?TokendHandleObject::make(this->keyhandle)->ipcHandle():0;
82	hRecord = (this->record)?TokendHandleObject::make(this->record)->ipcHandle():0;
83
84	server->freeRetrievedData(this);
85	//@@@ deferred-release outAttributes == Copier
86}
87
88/*
89	Cheat sheet
90
91	CSSM_HANDLE
92		- native size, 64 bit or 32 bit
93		- passed along to Tokend e.g. Tokend::Token::_findRecordHandle
94		- passed e.g. as CALL(findNext, ...)
95
96	RecordHandle & SearchHandle
97		- always 32 bit
98		- returned to callers through SecurityTokend interface
99*/
100
101TokendHandleObject::TokendHandleObject(CSSM_HANDLE cssmh) : mTokendHandle(cssmh)
102{
103    thmstate().add(ipcHandle(), this);
104}
105
106TokendHandleObject::~TokendHandleObject()
107{
108    thmstate().erase(ipcHandle());
109}
110
111
112ModuleNexus<TokendHandleObject::TokendHandleMapState> TokendHandleObject::thmstate;
113
114TokendHandleObject::TokendHandleMapState::TokendHandleMapState()
115{
116}
117
118// static factory method
119TokendHandleObject *TokendHandleObject::make(CSSM_HANDLE cssmh)
120{
121	// This will create a new TokendHandleObject, add it to the map, and return
122	// the value of the newly created object
123	if (!cssmh)
124		CssmError::throwMe(CSSMERR_CSSM_INVALID_ADDIN_HANDLE);
125	return new TokendHandleObject(cssmh);
126}
127
128// static method
129CSSM_HANDLE TokendHandleObject::findTDHandle(TokendHandleObject::TransitHandle thdl)
130{
131	/*
132		Find a handle that we can pass along to tokend. We do this so that Tokend
133		can return different errors for different calls -- even if we don't find
134		it in our map, we will still call out to Tokend. It might be better to
135		use a distinctive non-zero value for the bad handle for tracking
136	*/
137	const CSSM_HANDLE knownBadHandle = 0;	// for now
138
139	if (!thdl)
140		return knownBadHandle;
141
142	TokendHandleMap::const_iterator it = thmstate().find(thdl);
143	return (it == thmstate().end()) ? knownBadHandle : it->second->tokendHandle();
144}
145
146void TokendHandleObject::TokendHandleMapState::add(TransitHandle thdl, TokendHandleObject *tho)
147{
148	StLock<Mutex> _(*this);
149	thmstate().insert(thmstate().end(), make_pair(thdl,tho));
150}
151
152void TokendHandleObject::TokendHandleMapState::erase(TransitHandle thdl)
153{
154	StLock<Mutex> _(*this);
155	// @@@  check cssmh, don't erase if not valid
156	TokendHandleMap::erase(thdl);
157}
158
159}	// namespace Tokend
160}	// namespace Security
161
162