1/*
2 * Copyright (c) 2000-2008 Apple 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// transition - SecurityServer client library transition code.
27//
28// These are the functions that implement CssmClient methods in terms of
29// MIG IPC client calls, plus their supporting machinery.
30//
31// WARNING! HERE BE DRAGONS!
32// This code involves moderately arcane magic including (but not limited to)
33// dancing macros paired off with self-maintaining stack objects. Don't take
34// anything for granted! Be very afraid of ALL-CAPS names. Your best bet is
35// probably to stick with the existing patterns.
36//
37// Dragons, the sequel.  You just don't go killing of that kind of prose, so
38// we'll continue the saga here with a bit of an update.  In transitioning
39// into securityd there are a couple of steps.  The current setup is there
40// to allow Security.framework to have 32 and 64 bit clients and either
41// big or little endian.  Data is packaged up as hand-generated XDR, which
42// means it's also in network byte-order.
43//
44// CSSM_HANDLEs have remained longs in the 64 bit transition to keep the
45// optimization option open to allow cssm modules to hand back pointers as
46// handles.  Since we don't identify the client, handles across ipc will
47// remain 32 bit.  Handles you see here are passed out by securityd, and
48// are clipped and expanded in this layer (high bits always zero).
49//
50#include "sstransit.h"
51#include <security_cdsa_client/cspclient.h>
52
53#include <securityd_client/xdr_auth.h>
54#include <securityd_client/xdr_cssm.h>
55#include <securityd_client/xdr_dldb.h>
56
57namespace Security {
58namespace SecurityServer {
59
60using MachPlusPlus::check;
61using MachPlusPlus::VMGuard;
62
63//
64// Common database interface
65//
66void ClientSession::authenticateDb(DbHandle db, CSSM_DB_ACCESS_TYPE type,
67	const AccessCredentials *cred)
68{
69	// XXX/cs Leave it up to DatabaseAccessCredentials to rewrite it for now
70    DatabaseAccessCredentials creds(cred, internalAllocator);
71	CopyIn copy(creds.value(), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS));
72	IPC(ucsp_client_authenticateDb(UCSP_ARGS, db, type, copy.data(), copy.length()));
73}
74
75
76void ClientSession::releaseDb(DbHandle db)
77{
78	IPC(ucsp_client_releaseDb(UCSP_ARGS, db));
79}
80
81
82//
83// External database interface
84//
85DbHandle ClientSession::openToken(uint32 ssid, const AccessCredentials *cred,
86	const char *name)
87{
88	DbHandle db;
89	DatabaseAccessCredentials creds(cred, internalAllocator);
90	CopyIn copycreds(creds.value(), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS));
91
92	IPC(ucsp_client_openToken(UCSP_ARGS, ssid, name ? name : "", copycreds.data(), copycreds.length(), &db));
93
94	return db;
95}
96
97
98RecordHandle ClientSession::insertRecord(DbHandle db,
99						  CSSM_DB_RECORDTYPE recordType,
100						  const CssmDbRecordAttributeData *attributes,
101						  const CssmData *data)
102{
103	RecordHandle record;
104	CopyIn db_record_attr_data(attributes, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA));
105
106	IPC(ucsp_client_insertRecord(UCSP_ARGS, db, recordType, db_record_attr_data.data(), (mach_msg_type_number_t)db_record_attr_data.length(), OPTIONALDATA(data), &record));
107
108	return record;
109}
110
111
112void ClientSession::deleteRecord(DbHandle db, RecordHandle record)
113{
114	IPC(ucsp_client_deleteRecord(UCSP_ARGS, db, record));
115}
116
117
118void ClientSession::modifyRecord(DbHandle db, RecordHandle &record,
119				  CSSM_DB_RECORDTYPE recordType,
120				  const CssmDbRecordAttributeData *attributes,
121				  const CssmData *data,
122				  CSSM_DB_MODIFY_MODE modifyMode)
123{
124	CopyIn db_record_attr_data(attributes, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA));
125
126	IPC(ucsp_client_modifyRecord(UCSP_ARGS, db, &record, recordType, db_record_attr_data.data(), (mach_msg_type_number_t)db_record_attr_data.length(),
127        data != NULL, OPTIONALDATA(data), modifyMode));
128}
129
130static
131void copy_back_attribute_return_data(CssmDbRecordAttributeData *dest_attrs, CssmDbRecordAttributeData *source_attrs, Allocator &returnAllocator)
132{
133	assert(dest_attrs->size() == source_attrs->size());
134	// global (per-record) fields
135	dest_attrs->recordType(source_attrs->recordType());
136	dest_attrs->semanticInformation(source_attrs->semanticInformation());
137
138	// transfer data values (but not infos, which we keep in the original vector)
139	for (uint32 n = 0; n < dest_attrs->size(); n++)
140		dest_attrs->at(n).copyValues(source_attrs->at(n), returnAllocator);
141}
142
143RecordHandle ClientSession::findFirst(DbHandle db,
144							  const CssmQuery &inQuery,
145							  SearchHandle &hSearch,
146							  CssmDbRecordAttributeData *attributes,
147							  CssmData *data, KeyHandle &hKey)
148{
149	CopyIn query(&inQuery, reinterpret_cast<xdrproc_t>(xdr_CSSM_QUERY));
150	CopyIn in_attr(attributes, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA));
151	void *out_attr_data = NULL, *out_data = NULL;
152	mach_msg_size_t out_attr_length = 0, out_data_length = 0;
153	RecordHandle ipcHRecord = 0;
154
155	IPC(ucsp_client_findFirst(UCSP_ARGS, db,
156		query.data(), query.length(), in_attr.data(), in_attr.length(),
157		&out_attr_data, &out_attr_length, (data != NULL), &out_data, &out_data_length,
158		&hKey, &hSearch, &ipcHRecord));
159
160	if (ipcHRecord != 0)
161	{
162		CopyOut out_attrs(out_attr_data, out_attr_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR), true);
163		copy_back_attribute_return_data(attributes, reinterpret_cast<CssmDbRecordAttributeData*>(out_attrs.data()), returnAllocator);
164	}
165
166	// decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data)
167	CopyOut possible_key_in_data(out_data, out_data_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR), true, data);
168
169	return ipcHRecord;
170}
171
172
173RecordHandle ClientSession::findNext(SearchHandle hSearch,
174							 CssmDbRecordAttributeData *attributes,
175							 CssmData *data, KeyHandle &hKey)
176{
177	CopyIn in_attr(attributes, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA));
178	void *out_attr_data = NULL, *out_data = NULL;
179	mach_msg_size_t out_attr_length = 0, out_data_length = 0;
180	//DataOutput out_data(data, returnAllocator);
181	RecordHandle ipcHRecord = 0;
182
183	IPC(ucsp_client_findNext(UCSP_ARGS, hSearch,
184		in_attr.data(), in_attr.length(), &out_attr_data, &out_attr_length,
185		(data != NULL), &out_data, &out_data_length, &hKey, &ipcHRecord));
186
187	if (ipcHRecord != 0)
188	{
189		CopyOut out_attrs(out_attr_data, out_attr_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR), true);
190		copy_back_attribute_return_data(attributes, reinterpret_cast<CssmDbRecordAttributeData*>(out_attrs.data()), returnAllocator);
191	}
192
193	// decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data)
194	CopyOut possible_key_in_data(out_data, out_data_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR), true, data);
195
196	return ipcHRecord;
197}
198
199
200void ClientSession::findRecordHandle(RecordHandle hRecord,
201								   CssmDbRecordAttributeData *attributes,
202								   CssmData *data, KeyHandle &hKey)
203{
204	CopyIn in_attr(attributes, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA));
205	void *out_attr_data = NULL, *out_data = NULL;
206	mach_msg_size_t out_attr_length = 0, out_data_length = 0;
207	IPC(ucsp_client_findRecordHandle(UCSP_ARGS, hRecord,
208		in_attr.data(), in_attr.length(), &out_attr_data, &out_attr_length,
209		data != NULL, &out_data, &out_data_length, &hKey));
210
211	if (hRecord != 0)
212	{
213		CopyOut out_attrs(out_attr_data, out_attr_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR), true);
214		copy_back_attribute_return_data(attributes, reinterpret_cast<CssmDbRecordAttributeData*>(out_attrs.data()), returnAllocator);
215	}
216
217	// decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data)
218	CopyOut possible_key_in_data(out_data, out_data_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR), true, data);
219}
220
221
222void ClientSession::releaseSearch(SearchHandle searchHandle)
223{
224	IPC(ucsp_client_releaseSearch(UCSP_ARGS, searchHandle));
225}
226
227
228void ClientSession::releaseRecord(RecordHandle record)
229{
230	IPC(ucsp_client_releaseRecord(UCSP_ARGS, record));
231}
232
233void ClientSession::getDbName(DbHandle db, string &name)
234{
235	char result[PATH_MAX];
236
237	IPC(ucsp_client_getDbName(UCSP_ARGS, db, result));
238
239	name = result;
240}
241
242void ClientSession::setDbName(DbHandle db, const string &name)
243{
244	IPC(ucsp_client_setDbName(UCSP_ARGS, db, name.c_str()));
245}
246
247
248//
249// Internal database management
250//
251DbHandle ClientSession::createDb(const DLDbIdentifier &dbId,
252    const AccessCredentials *cred, const AclEntryInput *owner,
253    const DBParameters &params)
254{
255	DatabaseAccessCredentials creds(cred, internalAllocator);
256	CopyIn copycreds(creds.value(), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS));
257	CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE));
258	// XXX/64 make xdr routines translate directly between dldbident and flat rep
259    DataWalkers::DLDbFlatIdentifier ident(dbId);
260	CopyIn id(&ident, reinterpret_cast<xdrproc_t>(xdr_DLDbFlatIdentifier));
261	DbHandle db;
262
263	IPC(ucsp_client_createDb(UCSP_ARGS, &db, id.data(), id.length(), copycreds.data(), copycreds.length(), proto.data(), proto.length(), params));
264
265	return db;
266}
267
268DbHandle ClientSession::recodeDbForSync(DbHandle dbToClone,
269									   DbHandle srcDb)
270{
271	DbHandle newDb;
272
273	IPC(ucsp_client_recodeDbForSync(UCSP_ARGS, dbToClone, srcDb, &newDb));
274
275	return newDb;
276}
277
278DbHandle ClientSession::authenticateDbsForSync(const CssmData &dbHandleArray,
279											   const CssmData &agentData)
280{
281	DbHandle newDb;
282
283	IPC(ucsp_client_authenticateDbsForSync(UCSP_ARGS, DATA(dbHandleArray), DATA(agentData), &newDb));
284
285	return newDb;
286}
287
288void ClientSession::commitDbForSync(DbHandle srcDb, DbHandle cloneDb,
289                                    CssmData &blob, Allocator &alloc)
290{
291    DataOutput outBlob(blob, alloc);
292    IPC(ucsp_client_commitDbForSync(UCSP_ARGS, srcDb, cloneDb, DATA_OUT(outBlob)));
293}
294
295DbHandle ClientSession::decodeDb(const DLDbIdentifier &dbId,
296    const AccessCredentials *cred, const CssmData &blob)
297{
298	// XXX/64 fold into one translation
299	DatabaseAccessCredentials credentials(cred, internalAllocator);
300	CopyIn creds(credentials.value(), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS));
301	// XXX/64 fold into one translation
302    DataWalkers::DLDbFlatIdentifier ident(dbId);
303	CopyIn id(&ident, reinterpret_cast<xdrproc_t>(xdr_DLDbFlatIdentifier));
304	DbHandle db;
305
306	IPC(ucsp_client_decodeDb(UCSP_ARGS, &db, id.data(), id.length(), creds.data(), creds.length(), DATA(blob)));
307
308	return db;
309}
310
311void ClientSession::encodeDb(DbHandle db, CssmData &blob, Allocator &alloc)
312{
313	DataOutput outBlob(blob, alloc);
314	IPC(ucsp_client_encodeDb(UCSP_ARGS, db, DATA_OUT(outBlob)));
315}
316
317void ClientSession::setDbParameters(DbHandle db, const DBParameters &params)
318{
319	IPC(ucsp_client_setDbParameters(UCSP_ARGS, db, params));
320}
321
322void ClientSession::getDbParameters(DbHandle db, DBParameters &params)
323{
324	IPC(ucsp_client_getDbParameters(UCSP_ARGS, db, &params));
325}
326
327void ClientSession::changePassphrase(DbHandle db, const AccessCredentials *cred)
328{
329	CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS));
330    IPC(ucsp_client_changePassphrase(UCSP_ARGS, db, creds.data(), creds.length()));
331}
332
333
334void ClientSession::lock(DbHandle db)
335{
336	IPC(ucsp_client_authenticateDb(UCSP_ARGS, db, CSSM_DB_ACCESS_RESET, NULL, 0));
337//@@@VIRTUAL	IPC(ucsp_client_lockDb(UCSP_ARGS, db));
338}
339
340void ClientSession::lockAll (bool forSleep)
341{
342	IPC(ucsp_client_lockAll (UCSP_ARGS, forSleep));
343}
344
345void ClientSession::unlock(DbHandle db)
346{
347	IPC(ucsp_client_unlockDb(UCSP_ARGS, db));
348}
349
350void ClientSession::unlock(DbHandle db, const CssmData &passphrase)
351{
352	IPC(ucsp_client_unlockDbWithPassphrase(UCSP_ARGS, db, DATA(passphrase)));
353}
354
355void ClientSession::stashDb(DbHandle db)
356{
357    IPC(ucsp_client_stashDb(UCSP_ARGS, db));
358}
359
360void ClientSession::stashDbCheck(DbHandle db)
361{
362    IPC(ucsp_client_stashDbCheck(UCSP_ARGS, db));
363}
364
365bool ClientSession::isLocked(DbHandle db)
366{
367    boolean_t locked;
368	IPC(ucsp_client_isLocked(UCSP_ARGS, db, &locked));
369    return locked;
370}
371
372void ClientSession::verifyKeyStorePassphrase(uint32_t retries)
373{
374    IPC(ucsp_client_verifyKeyStorePassphrase(UCSP_ARGS, retries));
375}
376
377void ClientSession::resetKeyStorePassphrase(const CssmData &passphrase)
378{
379    IPC(ucsp_client_resetKeyStorePassphrase(UCSP_ARGS, DATA(passphrase)));
380}
381
382void ClientSession::changeKeyStorePassphrase()
383{
384    IPC(ucsp_client_changeKeyStorePassphrase(UCSP_ARGS));
385}
386
387//
388// Key control
389//
390void ClientSession::encodeKey(KeyHandle key, CssmData &blob,
391    KeyUID *uid, Allocator &alloc)
392{
393	// Not really used as output
394	DataOutput oBlob(blob, alloc);
395    void *uidp;
396    mach_msg_type_number_t uidLength;
397
398	IPC(ucsp_client_encodeKey(UCSP_ARGS, key, oBlob.data(), oBlob.length(),
399        (uid != NULL), &uidp, &uidLength));
400
401    // return key uid if requested
402    if (uid) {
403        assert(uidLength == sizeof(KeyUID));
404        memcpy(uid, uidp, sizeof(KeyUID));
405    }
406}
407
408KeyHandle ClientSession::decodeKey(DbHandle db, const CssmData &blob, CssmKey::Header &header)
409{
410	KeyHandle key;
411	void *keyHeaderData;
412	mach_msg_type_number_t keyHeaderDataLength;
413
414	IPC(ucsp_client_decodeKey(UCSP_ARGS, &key, &keyHeaderData, &keyHeaderDataLength, db, blob.data(), (mach_msg_type_number_t)blob.length()));
415
416	CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true);
417	header = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedKeyHeaderXDR.data()));
418
419	return key;
420}
421
422// keychain synchronization
423void ClientSession::recodeKey(DbHandle oldDb, KeyHandle key, DbHandle newDb,
424	CssmData &blob)
425{
426	DataOutput outBlob(blob, returnAllocator);
427	IPC(ucsp_client_recodeKey(UCSP_ARGS, oldDb, key, newDb, DATA_OUT(outBlob)));
428}
429
430void ClientSession::releaseKey(KeyHandle key)
431{
432	IPC(ucsp_client_releaseKey(UCSP_ARGS, key));
433}
434
435
436CssmKeySize ClientSession::queryKeySizeInBits(KeyHandle key)
437{
438    CssmKeySize length;
439    IPC(ucsp_client_queryKeySizeInBits(UCSP_ARGS, key, &length));
440    return length;
441}
442
443
444uint32 ClientSession::getOutputSize(const Context &context, KeyHandle key,
445    uint32 inputSize, bool encrypt)
446{
447	CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT));
448    uint32 outputSize;
449
450    IPC(ucsp_client_getOutputSize(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, inputSize, encrypt, &outputSize));
451    return outputSize;
452}
453
454
455//
456// Random number generation.
457// This interfaces to the secure RNG inside the SecurityServer; it does not access
458// a PRNG in its CSP. If you need a reproducible PRNG, attach a local CSP and use it.
459// Note that this function does not allocate a buffer; it always fills the buffer provided.
460//
461void ClientSession::generateRandom(const Security::Context &context, CssmData &data, Allocator &alloc)
462{
463	CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT));
464	DataOutput result(data, alloc);
465
466	IPC(ucsp_client_generateRandom(UCSP_ARGS, 0, ctxcopy.data(), ctxcopy.length(), DATA_OUT(result)));
467}
468
469
470//
471// Signatures and MACs
472//
473void ClientSession::generateSignature(const Context &context, KeyHandle key,
474	const CssmData &data, CssmData &signature, Allocator &alloc, CSSM_ALGORITHMS signOnlyAlgorithm)
475{
476	CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT));
477	DataOutput sig(signature, alloc);
478
479	IPCKEY(ucsp_client_generateSignature(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, signOnlyAlgorithm,
480		DATA(data), DATA_OUT(sig)),
481		   key, CSSM_ACL_AUTHORIZATION_SIGN);
482}
483
484void ClientSession::verifySignature(const Context &context, KeyHandle key,
485	const CssmData &data, const CssmData &signature, CSSM_ALGORITHMS verifyOnlyAlgorithm)
486{
487	CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT));
488
489	IPC(ucsp_client_verifySignature(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, verifyOnlyAlgorithm, DATA(data), DATA(signature)));
490}
491
492
493void ClientSession::generateMac(const Context &context, KeyHandle key,
494	const CssmData &data, CssmData &signature, Allocator &alloc)
495{
496	CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT));
497	DataOutput sig(signature, alloc);
498
499	IPCKEY(ucsp_client_generateMac(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, DATA(data), DATA_OUT(sig)),
500		key, CSSM_ACL_AUTHORIZATION_MAC);
501}
502
503void ClientSession::verifyMac(const Context &context, KeyHandle key,
504	const CssmData &data, const CssmData &signature)
505{
506	CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT));
507
508	IPCKEY(ucsp_client_verifyMac(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key,
509		DATA(data), DATA(signature)),
510		key, CSSM_ACL_AUTHORIZATION_MAC);
511}
512
513
514//
515// Encryption/Decryption
516//
517
518void ClientSession::encrypt(const Context &context, KeyHandle key,
519	const CssmData &clear, CssmData &cipher, Allocator &alloc)
520{
521	CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT));
522	DataOutput cipherOut(cipher, alloc);
523	IPCKEY(ucsp_client_encrypt(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, DATA(clear), DATA_OUT(cipherOut)),
524		key, CSSM_ACL_AUTHORIZATION_ENCRYPT);
525}
526
527void ClientSession::decrypt(const Context &context, KeyHandle key,
528	const CssmData &cipher, CssmData &clear, Allocator &alloc)
529{
530	CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT));
531	DataOutput clearOut(clear, alloc);
532
533	IPCKEY(ucsp_client_decrypt(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, DATA(cipher), DATA_OUT(clearOut)),
534		key, CSSM_ACL_AUTHORIZATION_DECRYPT);
535}
536
537
538//
539// Key generation
540//
541void ClientSession::generateKey(DbHandle db, const Context &context, uint32 keyUsage, uint32 keyAttr,
542    const AccessCredentials *cred, const AclEntryInput *owner,
543    KeyHandle &newKey, CssmKey::Header &newHeader)
544{
545	CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT));
546	CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS));
547	CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE));
548	void *keyHeaderData;
549	mach_msg_type_number_t keyHeaderDataLength;
550
551	IPC(ucsp_client_generateKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(),
552		creds.data(), creds.length(), proto.data(), proto.length(),
553		keyUsage, keyAttr, &newKey, &keyHeaderData, &keyHeaderDataLength));
554
555	CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true);
556	newHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedKeyHeaderXDR.data()));
557}
558
559void ClientSession::generateKey(DbHandle db, const Context &context,
560    uint32 pubKeyUsage, uint32 pubKeyAttr,
561    uint32 privKeyUsage, uint32 privKeyAttr,
562    const AccessCredentials *cred, const AclEntryInput *owner,
563    KeyHandle &pubKey, CssmKey::Header &pubHeader,
564    KeyHandle &privKey, CssmKey::Header &privHeader)
565{
566	CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT));
567	CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS));
568	CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE));
569	void *pubKeyHeaderData, *privKeyHeaderData;
570	mach_msg_type_number_t pubKeyHeaderDataLength, privKeyHeaderDataLength;
571
572	IPC(ucsp_client_generateKeyPair(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(),
573		creds.data(), creds.length(), proto.data(), proto.length(),
574		pubKeyUsage, pubKeyAttr, privKeyUsage, privKeyAttr,
575		&pubKey, &pubKeyHeaderData, &pubKeyHeaderDataLength,
576		&privKey, &privKeyHeaderData, &privKeyHeaderDataLength));
577
578	CopyOut wrappedPubKeyHeaderXDR(pubKeyHeaderData, pubKeyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true);
579	pubHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedPubKeyHeaderXDR.data()));
580	CopyOut wrappedPrivKeyHeaderXDR(privKeyHeaderData, privKeyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true);
581	privHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedPrivKeyHeaderXDR.data()));
582
583}
584
585
586//
587// Key derivation
588// This is a bit strained; the incoming 'param' value may have structure,
589// and we use a synthetic CssmDeriveData structure (with ad-hoc walker) to
590// handle that. Param also is input/output, which is always a pain (not to mention
591// ill-defined by the CDSA standard).
592//
593// If you're here because an algorithm of yours requires structured parameter
594// input, go to security_cdsa_utilities/cssmwalkers.h and add a case to the
595// CssmDeriveData walker.
596//
597void ClientSession::deriveKey(DbHandle db, const Context &context, KeyHandle baseKey,
598    CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, CssmData &param,
599    const AccessCredentials *cred, const AclEntryInput *owner,
600    KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &allocator)
601{
602		CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT));
603		CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS));
604		CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE));
605		CSSM_DERIVE_DATA inParamForm = { context.algorithm(), param };
606		CopyIn inParam(&inParamForm, reinterpret_cast<xdrproc_t>(xdr_CSSM_DERIVE_DATA));
607
608		try
609		{
610			DataOutput paramOutput(param, allocator);
611			void *keyHeaderData;
612			mach_msg_type_number_t keyHeaderDataLength;
613
614			IPCKEY(ucsp_client_deriveKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), baseKey,
615				creds.data(), creds.length(), proto.data(), proto.length(),
616				inParam.data(), inParam.length(), DATA_OUT(paramOutput),
617				usage, attrs, &newKey, &keyHeaderData, &keyHeaderDataLength),
618				baseKey, CSSM_ACL_AUTHORIZATION_DERIVE);
619
620			CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true);
621			newHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedKeyHeaderXDR.data()));
622		}
623		catch (CssmError& e)
624		{
625			// filter out errors for CSSM_ALGID_PKCS5_PBKDF2
626			if (context.algorithm() != CSSM_ALGID_PKCS5_PBKDF2 && e.error != CSSMERR_CSP_OUTPUT_LENGTH_ERROR)
627			{
628				throw;
629			}
630		}
631}
632
633
634//
635// Digest generation
636//
637void ClientSession::getKeyDigest(KeyHandle key, CssmData &digest, Allocator &allocator)
638{
639	DataOutput dig(digest, allocator);
640	IPC(ucsp_client_getKeyDigest(UCSP_ARGS, key, DATA_OUT(dig)));
641}
642
643
644//
645// Key wrapping and unwrapping
646//
647void ClientSession::wrapKey(const Context &context, KeyHandle wrappingKey,
648    KeyHandle keyToBeWrapped, const AccessCredentials *cred,
649	const CssmData *descriptiveData, CssmWrappedKey &wrappedKey, Allocator &alloc)
650{
651	CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT));
652	CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS));
653	void *keyData;
654	mach_msg_type_number_t keyDataLength;
655
656	IPCKEY(ucsp_client_wrapKey(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), wrappingKey,
657		creds.data(), creds.length(),
658		keyToBeWrapped, OPTIONALDATA(descriptiveData),
659		&keyData, &keyDataLength),
660		keyToBeWrapped,
661		context.algorithm() == CSSM_ALGID_NONE
662			? CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR : CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED);
663
664	CopyOut wrappedKeyXDR(keyData, keyDataLength + sizeof(CSSM_KEY), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEY_PTR), true);
665	CssmWrappedKey *wrappedKeyIPC = reinterpret_cast<CssmWrappedKey*>(wrappedKeyXDR.data());
666	wrappedKey.header() = wrappedKeyIPC->header();
667	wrappedKey.keyData() = CssmData(alloc.malloc(wrappedKeyIPC->keyData().length()), wrappedKeyIPC->keyData().length());
668	memcpy(wrappedKey.keyData().data(), wrappedKeyIPC->keyData(), wrappedKeyIPC->keyData().length());
669}
670
671void ClientSession::unwrapKey(DbHandle db, const Context &context, KeyHandle key,
672    KeyHandle publicKey, const CssmWrappedKey &wrappedKey,
673	uint32 usage, uint32 attr,
674	const AccessCredentials *cred, const AclEntryInput *acl,
675	CssmData &descriptiveData,
676    KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &alloc)
677{
678	CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT));
679	DataOutput descriptor(descriptiveData, alloc);
680	CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS));
681	CopyIn proto(acl ? &acl->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE));
682	CopyIn wrappedKeyXDR(&wrappedKey, reinterpret_cast<xdrproc_t>(xdr_CSSM_KEY));
683	void *keyHeaderData;
684	mach_msg_type_number_t keyHeaderDataLength;
685
686	IPCKEY(ucsp_client_unwrapKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), key,
687		creds.data(), creds.length(), proto.data(), proto.length(),
688		publicKey, wrappedKeyXDR.data(), wrappedKeyXDR.length(), usage, attr, DATA_OUT(descriptor),
689        &newKey, &keyHeaderData, &keyHeaderDataLength),
690		key, CSSM_ACL_AUTHORIZATION_DECRYPT);
691
692	CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true);
693	newHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedKeyHeaderXDR.data()));
694}
695
696
697//
698// ACL management
699//
700void ClientSession::getAcl(AclKind kind, GenericHandle key, const char *tag,
701	uint32 &infoCount, AclEntryInfo * &infoArray, Allocator &alloc)
702{
703	uint32 count;
704	void* info; mach_msg_type_number_t infoLength;
705	IPC(ucsp_client_getAcl(UCSP_ARGS, kind, key,
706		(tag != NULL), tag ? tag : "",
707		&count, &info, &infoLength));
708
709	CSSM_ACL_ENTRY_INFO_ARRAY_PTR aclsArray;
710	if (!::copyout_chunked(info, infoLength, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_INFO_ARRAY_PTR), reinterpret_cast<void**>(&aclsArray)))
711			CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR);
712
713	infoCount = aclsArray->count;
714	infoArray = reinterpret_cast<AclEntryInfo*>(aclsArray->acls);
715    free(aclsArray);
716}
717
718void ClientSession::changeAcl(AclKind kind, GenericHandle key, const AccessCredentials &cred,
719	const AclEdit &edit)
720{
721	CopyIn creds(&cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS));
722	//@@@ ignoring callback
723	CopyIn newEntry(edit.newEntry(), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_INPUT));
724
725	IPCKEY(ucsp_client_changeAcl(UCSP_ARGS, kind, key, creds.data(), creds.length(),
726		edit.mode(), toIPCHandle(edit.handle()), newEntry.data(), newEntry.length()),
727		key, CSSM_ACL_AUTHORIZATION_CHANGE_ACL);
728}
729
730void ClientSession::getOwner(AclKind kind, GenericHandle key, AclOwnerPrototype &owner,
731    Allocator &alloc)
732{
733	void* proto; mach_msg_type_number_t protoLength;
734	IPC(ucsp_client_getOwner(UCSP_ARGS, kind, key, &proto, &protoLength));
735
736    CSSM_ACL_OWNER_PROTOTYPE_PTR tmpOwner;
737	if (!::copyout_chunked(proto, protoLength, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_OWNER_PROTOTYPE_PTR), reinterpret_cast<void **>(&tmpOwner)))
738		CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR);
739    owner = *static_cast<AclOwnerPrototypePtr>(tmpOwner);
740    free(tmpOwner);
741}
742
743void ClientSession::changeOwner(AclKind kind, GenericHandle key,
744	const AccessCredentials &cred, const AclOwnerPrototype &proto)
745{
746	CopyIn creds(&cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS));
747	CopyIn protos(&proto, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_OWNER_PROTOTYPE));
748	IPCKEY(ucsp_client_setOwner(UCSP_ARGS, kind, key, creds.data(), creds.length(), protos.data(), protos.length()),
749		key, CSSM_ACL_AUTHORIZATION_CHANGE_OWNER);
750}
751
752
753void ClientSession::getKeyAcl(DbHandle db, const char *tag,
754	uint32 &count, AclEntryInfo * &info, Allocator &alloc)
755{ getAcl(keyAcl, db, tag, count, info, alloc); }
756
757void ClientSession::changeKeyAcl(DbHandle db, const AccessCredentials &cred,
758	const AclEdit &edit)
759{ changeAcl(keyAcl, db, cred, edit); }
760
761void ClientSession::getKeyOwner(DbHandle db, AclOwnerPrototype &owner, Allocator &alloc)
762{ getOwner(keyAcl, db, owner, alloc); }
763
764void ClientSession::changeKeyOwner(DbHandle db, const AccessCredentials &cred,
765	const AclOwnerPrototype &edit)
766{ changeOwner(keyAcl, db, cred, edit); }
767
768void ClientSession::getDbAcl(DbHandle db, const char *tag,
769	uint32 &count, AclEntryInfo * &info, Allocator &alloc)
770{ getAcl(dbAcl, db, tag, count, info, alloc); }
771
772void ClientSession::changeDbAcl(DbHandle db, const AccessCredentials &cred,
773	const AclEdit &edit)
774{ changeAcl(dbAcl, db, cred, edit); }
775
776void ClientSession::getDbOwner(DbHandle db, AclOwnerPrototype &owner, Allocator &alloc)
777{ getOwner(dbAcl, db, owner, alloc); }
778
779void ClientSession::changeDbOwner(DbHandle db, const AccessCredentials &cred,
780	const AclOwnerPrototype &edit)
781{ changeOwner(dbAcl, db, cred, edit); }
782
783
784//
785// Database key management
786//
787void ClientSession::extractMasterKey(DbHandle db, const Context &context, DbHandle sourceDb,
788	uint32 keyUsage, uint32 keyAttr,
789	const AccessCredentials *cred, const AclEntryInput *owner,
790	KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &alloc)
791{
792	CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT));
793	CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS));
794	CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE));
795	void *keyHeaderData;
796	mach_msg_type_number_t keyHeaderDataLength;
797
798	IPC(ucsp_client_extractMasterKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), sourceDb,
799		creds.data(), creds.length(), proto.data(), proto.length(),
800		keyUsage, keyAttr, &newKey, &keyHeaderData, &keyHeaderDataLength));
801
802	CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true);
803	newHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedKeyHeaderXDR.data()));
804}
805
806
807//
808// Authorization subsystem entry
809//
810void ClientSession::authCreate(const AuthorizationItemSet *rights,
811	const AuthorizationItemSet *environment, AuthorizationFlags flags,
812	AuthorizationBlob &result)
813{
814	void *rightSet = NULL; mach_msg_size_t rightSet_size = 0;
815	void *environ = NULL; mach_msg_size_t environ_size = 0;
816
817	if ((rights &&
818		!copyin_AuthorizationItemSet(rights, &rightSet, &rightSet_size)) ||
819		(environment &&
820		!copyin_AuthorizationItemSet(environment, &environ, &environ_size)))
821			CssmError::throwMe(errAuthorizationInternal);
822
823	activate();
824	IPCSTART(ucsp_client_authorizationCreate(UCSP_ARGS,
825		rightSet, rightSet_size,
826		flags,
827		environ, environ_size,
828		&result));
829
830	free(rightSet);
831	free(environ);
832
833	if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION)
834	  CssmError::throwMe(errAuthorizationInteractionNotAllowed);
835	IPCEND_CHECK;
836}
837
838void ClientSession::authRelease(const AuthorizationBlob &auth,
839	AuthorizationFlags flags)
840{
841	activate();
842	IPCSTART(ucsp_client_authorizationRelease(UCSP_ARGS, auth, flags));
843	if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION)
844	  CssmError::throwMe(errAuthorizationInteractionNotAllowed);
845	IPCEND_CHECK;
846}
847
848void ClientSession::authCopyRights(const AuthorizationBlob &auth,
849	const AuthorizationItemSet *rights, const AuthorizationItemSet *environment,
850	AuthorizationFlags flags,
851	AuthorizationItemSet **grantedRights)
852{
853	void *rightSet = NULL; mach_msg_size_t rightSet_size = 0;
854	void *environ = NULL; mach_msg_size_t environ_size = 0;
855	void *result = NULL; mach_msg_type_number_t resultLength = 0;
856
857	if ((rights && !copyin_AuthorizationItemSet(rights, &rightSet, &rightSet_size)) ||
858		(environment && !copyin_AuthorizationItemSet(environment, &environ, &environ_size)))
859          CssmError::throwMe(errAuthorizationInternal); // allocation error probably
860
861	activate();
862	IPCSTART(ucsp_client_authorizationCopyRights(UCSP_ARGS,
863		auth,
864		rightSet, rightSet_size,
865		flags | (grantedRights ? 0 : kAuthorizationFlagNoData),
866		environ, environ_size,
867		&result, &resultLength));
868
869	free(rightSet);
870	free(environ);
871
872	// XXX/cs return error when copyout returns false
873	if (rcode == CSSM_OK && grantedRights)
874		copyout_AuthorizationItemSet(result, resultLength, grantedRights);
875
876	if (result)
877		mig_deallocate(reinterpret_cast<vm_address_t>(result), resultLength);
878	if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION)
879	  CssmError::throwMe(errAuthorizationInteractionNotAllowed);
880	IPCEND_CHECK;
881}
882
883void ClientSession::authCopyInfo(const AuthorizationBlob &auth,
884	const char *tag,
885	AuthorizationItemSet * &info)
886{
887    if (tag == NULL)
888        tag = "";
889    else if (tag[0] == '\0')
890        MacOSError::throwMe(errAuthorizationInvalidTag);
891
892	activate();
893	void *result; mach_msg_type_number_t resultLength;
894	IPCSTART(ucsp_client_authorizationCopyInfo(UCSP_ARGS, auth, tag, &result, &resultLength));
895
896	// XXX/cs return error when copyout returns false
897	if (rcode == CSSM_OK)
898		copyout_AuthorizationItemSet(result, resultLength, &info);
899
900	if (result)
901		mig_deallocate(reinterpret_cast<vm_address_t>(result), resultLength);
902
903	if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION)
904	  CssmError::throwMe(errAuthorizationInteractionNotAllowed);
905	IPCEND_CHECK;
906}
907
908void ClientSession::authExternalize(const AuthorizationBlob &auth,
909	AuthorizationExternalForm &extForm)
910{
911	activate();
912	IPCSTART(ucsp_client_authorizationExternalize(UCSP_ARGS, auth, &extForm));
913	if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION)
914	  CssmError::throwMe(errAuthorizationInteractionNotAllowed);
915	IPCEND_CHECK;
916}
917
918void ClientSession::authInternalize(const AuthorizationExternalForm &extForm,
919	AuthorizationBlob &auth)
920{
921	activate();
922	IPCSTART(ucsp_client_authorizationInternalize(UCSP_ARGS, extForm, &auth));
923	if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION)
924	  CssmError::throwMe(errAuthorizationInteractionNotAllowed);
925	IPCEND_CHECK;
926}
927
928
929//
930// Push user preferences from an app in user space to securityd
931//
932void ClientSession::setSessionUserPrefs(SecuritySessionId sessionId, uint32_t userPreferencesLength, const void *userPreferences)
933{
934	IPC(ucsp_client_setSessionUserPrefs(UCSP_ARGS, sessionId, const_cast<void *>(userPreferences), userPreferencesLength));
935}
936
937
938void ClientSession::postNotification(NotificationDomain domain, NotificationEvent event, const CssmData &data)
939{
940	uint32 seq = ++mGlobal().thread().notifySeq;
941#if !defined(NDEBUG)
942	if (getenv("NOTIFYJITTER")) {
943		// artificially reverse odd/even sequences to test securityd's jitter buffer
944		seq += 2 * (seq % 2) - 1;
945		secdebug("notify", "POSTING FAKE SEQUENCE %d NOTIFICATION", seq);
946	}
947#endif //NDEBUG
948	secdebug("notify", "posting domain 0x%x event %d sequence %d",
949		domain, event, seq);
950	IPC(ucsp_client_postNotification(UCSP_ARGS, domain, event, DATA(data), seq));
951}
952
953//
954// authorizationdbGet/Set/Remove
955//
956void ClientSession::authorizationdbGet(const AuthorizationString rightname, CssmData &rightDefinition, Allocator &alloc)
957{
958	DataOutput definition(rightDefinition, alloc);
959	activate();
960	IPCSTART(ucsp_client_authorizationdbGet(UCSP_ARGS, rightname, DATA_OUT(definition)));
961	if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION)
962	  CssmError::throwMe(errAuthorizationInteractionNotAllowed);
963	IPCEND_CHECK;
964}
965
966void ClientSession::authorizationdbSet(const AuthorizationBlob &auth, const AuthorizationString rightname, uint32_t rightDefinitionLength, const void *rightDefinition)
967{
968	// @@@ DATA_IN in transition.cpp is not const void *
969	activate();
970	IPCSTART(ucsp_client_authorizationdbSet(UCSP_ARGS, auth, rightname, const_cast<void *>(rightDefinition), rightDefinitionLength));
971	if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION)
972	  CssmError::throwMe(errAuthorizationInteractionNotAllowed);
973	IPCEND_CHECK;
974}
975
976void ClientSession::authorizationdbRemove(const AuthorizationBlob &auth, const AuthorizationString rightname)
977{
978	activate();
979	IPCSTART(ucsp_client_authorizationdbRemove(UCSP_ARGS, auth, rightname));
980	if (rcode == CSSMERR_CSSM_NO_USER_INTERACTION)
981	  CssmError::throwMe(errAuthorizationInteractionNotAllowed);
982	IPCEND_CHECK;
983}
984
985
986//
987// Miscellaneous administrative calls
988//
989void ClientSession::addCodeEquivalence(const CssmData &oldHash, const CssmData &newHash,
990	const char *name, bool forSystem /* = false */)
991{
992	IPC(ucsp_client_addCodeEquivalence(UCSP_ARGS, DATA(oldHash), DATA(newHash),
993		name, forSystem));
994}
995
996void ClientSession::removeCodeEquivalence(const CssmData &hash, const char *name, bool forSystem /* = false */)
997{
998	IPC(ucsp_client_removeCodeEquivalence(UCSP_ARGS, DATA(hash), name, forSystem));
999}
1000
1001void ClientSession::setAlternateSystemRoot(const char *path)
1002{
1003	IPC(ucsp_client_setAlternateSystemRoot(UCSP_ARGS, path));
1004}
1005
1006
1007//
1008// Code Signing related
1009//
1010void ClientSession::registerHosting(mach_port_t hostingPort, SecCSFlags flags)
1011{
1012	IPC(ucsp_client_registerHosting(UCSP_ARGS, hostingPort, flags));
1013}
1014
1015mach_port_t ClientSession::hostingPort(pid_t pid)
1016{
1017	mach_port_t result;
1018	IPC(ucsp_client_hostingPort(UCSP_ARGS, pid, &result));
1019	return result;
1020}
1021
1022SecGuestRef ClientSession::createGuest(SecGuestRef host,
1023		uint32_t status, const char *path, const CssmData &cdhash, const CssmData &attributes, SecCSFlags flags)
1024{
1025	SecGuestRef newGuest;
1026	IPC(ucsp_client_createGuest(UCSP_ARGS, host, status, path, DATA(cdhash), DATA(attributes), flags, &newGuest));
1027	if (flags & kSecCSDedicatedHost) {
1028		secdebug("ssclient", "setting dedicated guest to 0x%x (was 0x%x)",
1029			mDedicatedGuest, newGuest);
1030		mDedicatedGuest = newGuest;
1031	}
1032	return newGuest;
1033}
1034
1035void ClientSession::setGuestStatus(SecGuestRef guest, uint32 status, const CssmData &attributes)
1036{
1037	IPC(ucsp_client_setGuestStatus(UCSP_ARGS, guest, status, DATA(attributes)));
1038}
1039
1040void ClientSession::removeGuest(SecGuestRef host, SecGuestRef guest)
1041{
1042	IPC(ucsp_client_removeGuest(UCSP_ARGS, host, guest));
1043}
1044
1045void ClientSession::selectGuest(SecGuestRef newGuest)
1046{
1047	if (mDedicatedGuest) {
1048		secdebug("ssclient", "ignoring selectGuest(0x%x) because dedicated guest=0x%x",
1049			newGuest, mDedicatedGuest);
1050	} else {
1051		secdebug("ssclient", "switching to guest 0x%x", newGuest);
1052		mGlobal().thread().currentGuest = newGuest;
1053	}
1054}
1055
1056SecGuestRef ClientSession::selectedGuest() const
1057{
1058	if (mDedicatedGuest)
1059		return mDedicatedGuest;
1060	else
1061		return mGlobal().thread().currentGuest;
1062}
1063
1064
1065} // end namespace SecurityServer
1066} // end namespace Security
1067