]> git.saurik.com Git - apple/securityd.git/blob - src/transition.cpp
securityd-36975.tar.gz
[apple/securityd.git] / src / transition.cpp
1 /*
2 * Copyright (c) 2000-2009 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 - securityd IPC-to-class-methods transition layer
27 //
28 // This file contains all server-side MIG implementations for the main
29 // securityd protocol ("ucsp"). It dispatches them into the vast object
30 // conspiracy that is securityd, anchored in the Server object.
31 //
32 #include <securityd_client/ss_types.h>
33 #include <securityd_client/ucsp.h>
34 #include "server.h"
35 #include "session.h"
36 #include "agentquery.h"
37 #include "database.h"
38 #include "kcdatabase.h"
39 #include "tokendatabase.h"
40 #include "kckey.h"
41 #include "child.h"
42 #include <syslog.h>
43 #include <mach/mach_error.h>
44 #include <securityd_client/xdr_cssm.h>
45 #include <securityd_client/xdr_auth.h>
46 #include <securityd_client/xdr_dldb.h>
47 #include <security_utilities/logging.h>
48
49 #include <CoreFoundation/CFDictionary.h>
50 #include <CoreFoundation/CFPropertyList.h>
51
52 //
53 // Bracket Macros
54 //
55 #define UCSP_ARGS mach_port_t servicePort, mach_port_t replyPort, \
56 audit_token_t auditToken, CSSM_RETURN *rcode
57
58 #define BEGIN_IPCN *rcode = CSSM_OK; try {
59 #define BEGIN_IPC(name) BEGIN_IPCN RefPointer<Connection> connRef(&Server::connection(replyPort, auditToken)); \
60 Connection &connection __attribute__((unused)) = *connRef; \
61 if (SECURITYD_REQUEST_ENTRY_ENABLED()) { \
62 const char * volatile s = #name; volatile char __attribute__((unused)) pagein = s[0]; \
63 SECURITYD_REQUEST_ENTRY((char *)s, &connection, &connection.process()); \
64 }
65 #define END_IPC(base) END_IPCN(base) Server::requestComplete(*rcode); return KERN_SUCCESS;
66 #define END_IPCN(base) SECURITYD_REQUEST_RETURN(*rcode); \
67 } \
68 catch (const CommonError &err) { *rcode = CssmError::cssmError(err, CSSM_ ## base ## _BASE_ERROR); } \
69 catch (const std::bad_alloc &) { *rcode = CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \
70 catch (Connection *conn) { *rcode = 0; } \
71 catch (...) { *rcode = CssmError::merge(CSSM_ERRCODE_INTERNAL_ERROR, CSSM_ ## base ## _BASE_ERROR); }
72
73 #define BEGIN_IPCS try {
74 #define END_IPCS(more) } catch (...) { } \
75 mach_port_deallocate(mach_task_self(), serverPort); more; return KERN_SUCCESS;
76
77 #define DATA_IN(base) void *base, mach_msg_type_number_t base##Length
78 #define DATA_OUT(base) void **base, mach_msg_type_number_t *base##Length
79 #define DATA(base) CssmData(base, base##Length)
80
81 #define SSBLOB(Type, name) makeBlob<Type>(DATA(name))
82
83 using LowLevelMemoryUtilities::increment;
84 using LowLevelMemoryUtilities::difference;
85
86 class CopyOutAccessCredentials : public CopyOut {
87 public:
88 CopyOutAccessCredentials(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_ACCESS_CREDENTIALS), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS_PTR)) { }
89 operator AccessCredentials *() { return static_cast<AccessCredentials *>(reinterpret_cast<CSSM_ACCESS_CREDENTIALS_PTR>(data())); }
90 };
91
92
93 class CopyOutEntryAcl : public CopyOut {
94 public:
95 CopyOutEntryAcl(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_ACL_ENTRY_PROTOTYPE), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE_PTR)) { }
96 operator AclEntryPrototype *() { return static_cast<AclEntryPrototype *>(reinterpret_cast<CSSM_ACL_ENTRY_PROTOTYPE_PTR>(data())); }
97 };
98
99 class CopyOutOwnerAcl : public CopyOut {
100 public:
101 CopyOutOwnerAcl(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_ACL_OWNER_PROTOTYPE), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_OWNER_PROTOTYPE_PTR)) { }
102 operator AclOwnerPrototype *() { return static_cast<AclOwnerPrototype *>(reinterpret_cast<CSSM_ACL_OWNER_PROTOTYPE_PTR>(data())); }
103 };
104
105 class CopyOutAclEntryInput : public CopyOut {
106 public:
107 CopyOutAclEntryInput(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_ACL_ENTRY_INPUT), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_INPUT_PTR)) { }
108 operator AclEntryInput *() { return static_cast<AclEntryInput *>(reinterpret_cast<CSSM_ACL_ENTRY_INPUT_PTR>(data())); }
109 };
110
111
112 class CopyOutDeriveData : public CopyOut {
113 public:
114 CopyOutDeriveData(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_DERIVE_DATA), reinterpret_cast<xdrproc_t>(xdr_CSSM_DERIVE_DATA_PTR)) { }
115 CSSM_DERIVE_DATA * derive_data() { return reinterpret_cast<CSSM_DERIVE_DATA *>(data()); }
116 CSSM_DATA &cssm_data() { return derive_data()->baseData; }
117 CSSM_ALGORITHMS algorithm() { return derive_data()->algorithm; }
118 };
119
120
121 class CopyOutContext : public CopyOut {
122 public:
123 CopyOutContext(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_CONTEXT), reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT_PTR)) { }
124 operator Context *() { return static_cast<Context *>(reinterpret_cast<CSSM_CONTEXT_PTR>(data())); }
125 Context &context() { return *static_cast<Context *>(reinterpret_cast<CSSM_CONTEXT_PTR>(data())); }
126 };
127
128 class CopyOutKey : public CopyOut {
129 public:
130 CopyOutKey(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_KEY), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEY_PTR)) { }
131 operator CssmKey *() { return static_cast<CssmKey *>(reinterpret_cast<CSSM_KEY_PTR>(data())); }
132 CssmKey &key() { return *static_cast<CssmKey *>(reinterpret_cast<CSSM_KEY_PTR>(data())); }
133 };
134
135 class CopyOutDbRecordAttributes : public CopyOut {
136 public:
137 CopyOutDbRecordAttributes(void *copy, size_t size) : CopyOut(copy, size + sizeof(CSSM_DB_RECORD_ATTRIBUTE_DATA), reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR)) { }
138 CssmDbRecordAttributeData *attribute_data() { return static_cast<CssmDbRecordAttributeData *>(reinterpret_cast<CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR>(data())); }
139 };
140
141 class CopyOutQuery : public CopyOut {
142 public:
143 CopyOutQuery(void *copy, size_t size) : CopyOut(copy, size, reinterpret_cast<xdrproc_t>(xdr_CSSM_QUERY_PTR)) { }
144 operator CssmQuery *() { return static_cast<CssmQuery *>(reinterpret_cast<CSSM_QUERY_PTR>(data())); }
145 };
146
147 //
148 // Take a DATA type RPC argument purportedly representing a Blob of some kind,
149 // turn it into a Blob, and fail properly if it's not kosher.
150 //
151 template <class BlobType>
152 const BlobType *makeBlob(const CssmData &blobData, CSSM_RETURN error = CSSM_ERRCODE_INVALID_DATA)
153 {
154 if (!blobData.data() || blobData.length() < sizeof(BlobType))
155 CssmError::throwMe(error);
156 const BlobType *blob = static_cast<const BlobType *>(blobData.data());
157 if (blob->totalLength != blobData.length())
158 CssmError::throwMe(error);
159 return blob;
160 }
161
162 //
163 // An OutputData object will take memory allocated within securityd,
164 // hand it to the MIG return-output parameters, and schedule it to be released
165 // after the MIG reply has been sent. It will also get rid of it in case of
166 // error.
167 //
168 class OutputData : public CssmData {
169 public:
170 OutputData(void **outP, mach_msg_type_number_t *outLength)
171 : mData(*outP), mLength(*outLength) { }
172 ~OutputData()
173 { mData = data(); mLength = length(); Server::releaseWhenDone(mData); }
174
175 void operator = (const CssmData &source)
176 { CssmData::operator = (source); }
177
178 private:
179 void * &mData;
180 mach_msg_type_number_t &mLength;
181 };
182
183 //
184 // Choose a Database from a choice of two sources, giving preference
185 // to persistent stores and to earlier sources.
186 //
187 Database *pickDb(Database *db1, Database *db2);
188
189 static inline Database *dbOf(Key *key) { return key ? &key->database() : NULL; }
190
191 inline Database *pickDb(Key *k1, Key *k2) { return pickDb(dbOf(k1), dbOf(k2)); }
192 inline Database *pickDb(Database *db1, Key *k2) { return pickDb(db1, dbOf(k2)); }
193 inline Database *pickDb(Key *k1, Database *db2) { return pickDb(dbOf(k1), db2); }
194
195 //
196 // Choose a Database from a choice of two sources, giving preference
197 // to persistent stores and to earlier sources.
198 //
199 Database *pickDb(Database *db1, Database *db2)
200 {
201 // persistent db1 always wins
202 if (db1 && !db1->transient())
203 return db1;
204
205 // persistent db2 is next choice
206 if (db2 && !db2->transient())
207 return db2;
208
209 // pick any existing transient database
210 if (db1)
211 return db1;
212 if (db2)
213 return db2;
214
215 // none at all. use the canonical transient store
216 return Server::optionalDatabase(noDb);
217 }
218
219 //
220 // Setup/Teardown functions.
221 //
222 kern_return_t ucsp_server_setup(UCSP_ARGS, mach_port_t taskPort, ClientSetupInfo info, const char *identity)
223 {
224 BEGIN_IPCN
225 SECURITYD_REQUEST_ENTRY((char*)"setup", NULL, NULL);
226 Server::active().setupConnection(Server::connectNewProcess, servicePort, replyPort,
227 taskPort, auditToken, &info, identity);
228 END_IPCN(CSSM)
229 if (*rcode)
230 Syslog::notice("setup(%s) failed rcode=%d", identity ? identity : "<NULL>", *rcode);
231 return KERN_SUCCESS;
232 }
233
234 kern_return_t ucsp_server_setupNew(UCSP_ARGS, mach_port_t taskPort,
235 ClientSetupInfo info, const char *identity,
236 mach_port_t *newServicePort)
237 {
238 BEGIN_IPCN
239 SECURITYD_REQUEST_ENTRY((char*)"setupNew", NULL, NULL);
240 try {
241 RefPointer<Session> session = new DynamicSession(taskPort);
242 Server::active().setupConnection(Server::connectNewSession, session->servicePort(), replyPort,
243 taskPort, auditToken, &info, identity);
244 *newServicePort = session->servicePort();
245 } catch (const MachPlusPlus::Error &err) {
246 switch (err.error) {
247 case BOOTSTRAP_SERVICE_ACTIVE:
248 MacOSError::throwMe(errSessionAuthorizationDenied); // translate
249 default:
250 throw;
251 }
252 }
253 END_IPCN(CSSM)
254 if (*rcode)
255 Syslog::notice("setupNew(%s) failed rcode=%d", identity ? identity : "<NULL>", *rcode);
256 return KERN_SUCCESS;
257 }
258
259 kern_return_t ucsp_server_setupThread(UCSP_ARGS, mach_port_t taskPort)
260 {
261 SECURITYD_REQUEST_ENTRY((char*)"setupThread", NULL, NULL);
262 BEGIN_IPCN
263 Server::active().setupConnection(Server::connectNewThread, servicePort, replyPort,
264 taskPort, auditToken);
265 END_IPCN(CSSM)
266 if (*rcode)
267 Syslog::notice("setupThread failed rcode=%d", *rcode);
268 return KERN_SUCCESS;
269 }
270
271
272 kern_return_t ucsp_server_teardown(UCSP_ARGS)
273 {
274 BEGIN_IPCN
275 SECURITYD_REQUEST_ENTRY((char*)"teardown", NULL, NULL);
276 Server::active().endConnection(replyPort);
277 END_IPCN(CSSM)
278 return KERN_SUCCESS;
279 }
280
281 kern_return_t ucsp_server_verifyPrivileged(UCSP_ARGS)
282 {
283 BEGIN_IPCN
284 SECURITYD_REQUEST_ENTRY((char*)"verifyPrivileged", NULL, NULL);
285 // doing nothing (we just want securityd's audit credentials returned)
286 END_IPCN(CSSM)
287 return KERN_SUCCESS;
288 }
289
290 //
291 // Common database operations
292 //
293 kern_return_t ucsp_server_authenticateDb(UCSP_ARGS, DbHandle db,
294 CSSM_DB_ACCESS_TYPE accessType, DATA_IN(cred))
295 {
296 BEGIN_IPC(authenticateDb)
297 secdebug("dl", "authenticateDb");
298 CopyOutAccessCredentials creds(cred, credLength);
299 // ignoring accessType
300 Server::database(db)->authenticate(accessType, creds);
301 END_IPC(DL)
302 }
303
304 kern_return_t ucsp_server_releaseDb(UCSP_ARGS, DbHandle db)
305 {
306 BEGIN_IPC(releaseDb)
307 connection.process().kill(*Server::database(db));
308 END_IPC(DL)
309 }
310
311
312 kern_return_t ucsp_server_getDbName(UCSP_ARGS, DbHandle db, char name[PATH_MAX])
313 {
314 BEGIN_IPC(getDbName)
315 string result = Server::database(db)->dbName();
316 assert(result.length() < PATH_MAX);
317 memcpy(name, result.c_str(), result.length() + 1);
318 END_IPC(DL)
319 }
320
321 kern_return_t ucsp_server_setDbName(UCSP_ARGS, DbHandle db, const char *name)
322 {
323 BEGIN_IPC(setDbName)
324 Server::database(db)->dbName(name);
325 END_IPC(DL)
326 }
327
328
329 //
330 // External database interface
331 //
332 kern_return_t ucsp_server_openToken(UCSP_ARGS, uint32 ssid, FilePath name,
333 DATA_IN(accessCredentials), DbHandle *db)
334 {
335 BEGIN_IPC(openToken)
336 CopyOutAccessCredentials creds(accessCredentials, accessCredentialsLength);
337 *db = (new TokenDatabase(ssid, connection.process(), name, creds))->handle();
338 END_IPC(DL)
339 }
340
341 kern_return_t ucsp_server_findFirst(UCSP_ARGS, DbHandle db,
342 DATA_IN(inQuery), DATA_IN(inAttributes), DATA_OUT(outAttributes),
343 boolean_t getData, DATA_OUT(data),
344 KeyHandle *hKey, SearchHandle *hSearch, IPCRecordHandle *hRecord)
345 {
346 BEGIN_IPC(findFirst)
347 CopyOutQuery query(inQuery, inQueryLength);
348 CopyOutDbRecordAttributes attrs(inAttributes, inAttributesLength);
349
350 RefPointer<Database::Search> search;
351 RefPointer<Database::Record> record;
352 RefPointer<Key> key;
353 CssmData outData;
354 CssmDbRecordAttributeData *outAttrs = NULL; mach_msg_type_number_t outAttrsLength;
355 Server::database(db)->findFirst(*query,
356 attrs.attribute_data(), attrs.length(),
357 getData ? &outData : NULL, key, search, record, outAttrs, outAttrsLength);
358
359 // handle nothing-found case without exceptions
360 if (!record) {
361 *hRecord = noRecord;
362 *hSearch = noSearch;
363 *hKey = noKey;
364 } else {
365 // return handles
366 *hRecord = record->handle();
367 *hSearch = search->handle();
368 *hKey = key ? key->handle() : noKey;
369
370 if (outAttrsLength && outAttrs) {
371 Server::releaseWhenDone(outAttrs); // exception proof it against next line
372 if (!copyin(outAttrs, reinterpret_cast<xdrproc_t> (xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA), outAttributes, outAttributesLength))
373 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR);
374 Server::releaseWhenDone(*outAttributes);
375 }
376
377 // return data (temporary fix)
378 if (getData) {
379 Server::releaseWhenDone(outData.data());
380 xdrproc_t encode_proc = reinterpret_cast<xdrproc_t>(xdr_CSSM_NO_KEY_IN_DATA);
381 if (key)
382 encode_proc = reinterpret_cast<xdrproc_t>(xdr_CSSM_KEY_IN_DATA);
383 if (!copyin(&outData, encode_proc, data, dataLength))
384 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR);
385 Server::releaseWhenDone(*data);
386 }
387 }
388 END_IPC(DL)
389 }
390
391
392 kern_return_t ucsp_server_findNext(UCSP_ARGS, SearchHandle hSearch,
393 DATA_IN(inAttributes),
394 DATA_OUT(outAttributes),
395 boolean_t getData, DATA_OUT(data), KeyHandle *hKey,
396 IPCRecordHandle *hRecord)
397 {
398 BEGIN_IPC(findNext)
399 CopyOutDbRecordAttributes attrs(inAttributes, inAttributesLength);
400 RefPointer<Database::Search> search =
401 Server::find<Database::Search>(hSearch, CSSMERR_DL_INVALID_RESULTS_HANDLE);
402 RefPointer<Database::Record> record;
403 RefPointer<Key> key;
404 CssmData outData;
405 CssmDbRecordAttributeData *outAttrs = NULL; mach_msg_type_number_t outAttrsLength;
406 search->database().findNext(search, attrs.attribute_data(), attrs.length(),
407 getData ? &outData : NULL, key, record, outAttrs, outAttrsLength);
408
409 // handle nothing-found case without exceptions
410 if (!record) {
411 *hRecord = noRecord;
412 *hKey = noKey;
413 } else {
414 // return handles
415 *hRecord = record->handle();
416 *hKey = key ? key->handle() : noKey;
417
418 if (outAttrsLength && outAttrs) {
419 secdebug("attrmem", "Found attrs: %p of length: %d", outAttrs, outAttrsLength);
420 Server::releaseWhenDone(outAttrs); // exception proof it against next line
421 if (!copyin(outAttrs, reinterpret_cast<xdrproc_t> (xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA), outAttributes, outAttributesLength))
422 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR);
423 secdebug("attrmem", "Copied attrs: %p of length: %d", *outAttributes, *outAttributesLength);
424 Server::releaseWhenDone(*outAttributes);
425 }
426
427 // return data (temporary fix)
428 if (getData) {
429 Server::releaseWhenDone(outData.data());
430 xdrproc_t encode_proc = reinterpret_cast<xdrproc_t>(xdr_CSSM_NO_KEY_IN_DATA);
431 if (key)
432 encode_proc = reinterpret_cast<xdrproc_t>(xdr_CSSM_KEY_IN_DATA);
433 if (!copyin(&outData, encode_proc, data, dataLength))
434 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR);
435 Server::releaseWhenDone(*data);
436 }
437 }
438 END_IPC(DL)
439 }
440
441 kern_return_t ucsp_server_findRecordHandle(UCSP_ARGS, IPCRecordHandle hRecord,
442 DATA_IN(inAttributes), DATA_OUT(outAttributes),
443 boolean_t getData, DATA_OUT(data), KeyHandle *hKey)
444 {
445 BEGIN_IPC(findRecordHandle)
446 CopyOutDbRecordAttributes attrs(inAttributes, inAttributesLength);
447 RefPointer<Database::Record> record =
448 Server::find<Database::Record>(hRecord, CSSMERR_DL_INVALID_RECORD_UID);
449 RefPointer<Key> key;
450 CssmData outData;
451 CssmDbRecordAttributeData *outAttrs; mach_msg_type_number_t outAttrsLength;
452 record->database().findRecordHandle(record, attrs.attribute_data(), attrs.length(),
453 getData ? &outData : NULL, key, outAttrs, outAttrsLength);
454
455 // return handles
456 *hKey = key ? key->handle() : noKey;
457
458 if (outAttrsLength && outAttrs) {
459 Server::releaseWhenDone(outAttrs); // exception proof it against next line
460 if (!copyin(outAttrs, reinterpret_cast<xdrproc_t> (xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA), outAttributes, outAttributesLength))
461 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR);
462 Server::releaseWhenDone(*outAttributes);
463 }
464
465 // return data (temporary fix)
466 if (getData) {
467 /*
468 We can't release this with the usual allocator (which calls free(), since
469 it was VM allocated. Part of the fix for:
470 <rdar://problem/6738709> securityd leaks VM memory during certain smartcard operations
471 will be to call Server::releaseWhenDone below with a new vm allocator param
472 */
473 Server::releaseWhenDone(outData.data());
474 xdrproc_t encode_proc = reinterpret_cast<xdrproc_t>(xdr_CSSM_NO_KEY_IN_DATA);
475 if (key)
476 encode_proc = reinterpret_cast<xdrproc_t>(xdr_CSSM_KEY_IN_DATA);
477 if (!copyin(&outData, encode_proc, data, dataLength))
478 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR);
479 Server::releaseWhenDone(*data);
480 }
481 END_IPC(DL)
482 }
483
484 kern_return_t ucsp_server_insertRecord(UCSP_ARGS, DbHandle db, CSSM_DB_RECORDTYPE recordType,
485 DATA_IN(inAttributes), DATA_IN(data), IPCRecordHandle *record)
486 {
487 BEGIN_IPC(insertRecord)
488 RecordHandle recordHandle;
489 CopyOutDbRecordAttributes attrs(inAttributes, inAttributesLength);
490 Server::database(db)->insertRecord(recordType, attrs.attribute_data(), attrs.length(),
491 DATA(data), recordHandle);
492 *record = recordHandle;
493 END_IPC(DL)
494 }
495
496 kern_return_t ucsp_server_modifyRecord(UCSP_ARGS, DbHandle db, IPCRecordHandle *hRecord,
497 CSSM_DB_RECORDTYPE recordType, DATA_IN(attributes),
498 boolean_t setData, DATA_IN(data), CSSM_DB_MODIFY_MODE modifyMode)
499 {
500 BEGIN_IPC(modifyRecord)
501 CopyOutDbRecordAttributes attrs(attributes, attributesLength);
502 CssmData newData(DATA(data));
503 RefPointer<Database::Record> record =
504 Server::find<Database::Record>(*hRecord, CSSMERR_DL_INVALID_RECORD_UID);
505 Server::database(db)->modifyRecord(recordType, record, attrs.attribute_data(), attrs.length(),
506 setData ? &newData : NULL, modifyMode);
507 // note that the record handle presented to the client never changes here
508 // (we could, but have no reason to - our record handles are just always up to date)
509 END_IPC(DL)
510 }
511
512 kern_return_t ucsp_server_deleteRecord(UCSP_ARGS, DbHandle db, IPCRecordHandle hRecord)
513 {
514 BEGIN_IPC(deleteRecord)
515 Server::database(db)->deleteRecord(
516 Server::find<Database::Record>(hRecord, CSSMERR_DL_INVALID_RECORD_UID));
517 END_IPC(DL)
518 }
519
520 kern_return_t ucsp_server_releaseSearch(UCSP_ARGS, SearchHandle hSearch)
521 {
522 BEGIN_IPC(releaseSearch)
523 RefPointer<Database::Search> search = Server::find<Database::Search>(hSearch, 0);
524 search->database().releaseSearch(*search);
525 END_IPC(DL)
526 }
527
528 kern_return_t ucsp_server_releaseRecord(UCSP_ARGS, IPCRecordHandle hRecord)
529 {
530 BEGIN_IPC(releaseRecord)
531 RefPointer<Database::Record> record = Server::find<Database::Record>(hRecord, 0);
532 record->database().releaseRecord(*record);
533 END_IPC(DL)
534 }
535
536
537 //
538 // Internal database management
539 //
540 kern_return_t ucsp_server_createDb(UCSP_ARGS, DbHandle *db,
541 DATA_IN(ident), DATA_IN(cred), DATA_IN(owner),
542 DBParameters params)
543 {
544 BEGIN_IPC(createDb)
545 CopyOutAccessCredentials creds(cred, credLength);
546 CopyOutEntryAcl owneracl(owner, ownerLength);
547 CopyOut flatident(ident, identLength, reinterpret_cast<xdrproc_t>(xdr_DLDbFlatIdentifierRef));
548 *db = (new KeychainDatabase(*reinterpret_cast<DLDbFlatIdentifier*>(flatident.data()), params, connection.process(), creds, owneracl))->handle();
549 END_IPC(DL)
550 }
551
552 kern_return_t ucsp_server_recodeDbForSync(UCSP_ARGS, DbHandle dbToClone,
553 DbHandle srcDb, DbHandle *newDb)
554 {
555 BEGIN_IPC(recodeDbForSync)
556 RefPointer<KeychainDatabase> srcKC = Server::keychain(srcDb);
557 *newDb = (new KeychainDatabase(*srcKC, connection.process(), dbToClone))->handle();
558 END_IPC(DL)
559 }
560
561 kern_return_t ucsp_server_authenticateDbsForSync(UCSP_ARGS, DATA_IN(dbHandleArray),
562 DATA_IN(agentData), DbHandle* authenticatedDBHandle)
563 {
564 BEGIN_IPC(authenticateDbsForSync)
565 QueryDBBlobSecret query;
566 query.inferHints(connection.process());
567 query.addHint(AGENT_HINT_KCSYNC_DICT, agentData, agentDataLength);
568 CSSM_DATA dbData = DATA(dbHandleArray);
569 uint8 ipcDbHandleArrayCount = *(dbData.Data);
570 DbHandle *ipcDbHandleArray = (DbHandle *)Allocator::standard().malloc(ipcDbHandleArrayCount * sizeof(DbHandle));
571 if ( ipcDbHandleArray == 0 )
572 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR);
573 DbHandle *currIPCDbHandleArrayPtr = ipcDbHandleArray;
574 DbHandle *dbHandleArrayPtr = (DbHandle *)(dbData.Data+1);
575 int index;
576 for (index=0; index < ipcDbHandleArrayCount; index++)
577 {
578 *currIPCDbHandleArrayPtr = *dbHandleArrayPtr;
579 Server::keychain(*currIPCDbHandleArrayPtr)->lockDb(); // lock this db if it was unlocked in the past (user could have deleted the kc, resetLogin, etc.)
580 currIPCDbHandleArrayPtr++;
581 dbHandleArrayPtr++;
582 }
583 Server::releaseWhenDone(ipcDbHandleArray);
584 if (query(ipcDbHandleArray, ipcDbHandleArrayCount, authenticatedDBHandle) != SecurityAgent::noReason)
585 CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED);
586 END_IPC(DL)
587 }
588
589 kern_return_t ucsp_server_commitDbForSync(UCSP_ARGS, DbHandle srcDb,
590 DbHandle cloneDb, DATA_OUT(blob))
591 {
592 BEGIN_IPC(commitDbForSync)
593 RefPointer<KeychainDatabase> srcKC = Server::keychain(srcDb);
594 RefPointer<KeychainDatabase> cloneKC = Server::keychain(cloneDb);
595 srcKC->commitSecretsForSync(*cloneKC);
596
597 // re-encode blob for convenience
598 if (blob && blobLength) {
599 DbBlob *dbBlob = srcKC->blob();
600 *blob = dbBlob;
601 *blobLength = dbBlob->length();
602 } else {
603 secdebug("kcrecode", "No blob can be returned to client");
604 }
605 END_IPC(DL)
606 }
607
608 kern_return_t ucsp_server_decodeDb(UCSP_ARGS, DbHandle *db,
609 DATA_IN(ident), DATA_IN(cred), DATA_IN(blob))
610 {
611 BEGIN_IPC(decodeDb)
612 CopyOutAccessCredentials creds(cred, credLength);
613 CopyOut flatident(ident, identLength, reinterpret_cast<xdrproc_t>(xdr_DLDbFlatIdentifierRef));
614 DLDbFlatIdentifier* flatID = (DLDbFlatIdentifier*) flatident.data();
615 DLDbIdentifier id = *flatID; // invokes a casting operator
616
617 *db = (new KeychainDatabase(id, SSBLOB(DbBlob, blob),
618 connection.process(), creds))->handle();
619 END_IPC(DL)
620 }
621
622 kern_return_t ucsp_server_encodeDb(UCSP_ARGS, DbHandle db, DATA_OUT(blob))
623 {
624 BEGIN_IPC(encodeDb)
625 DbBlob *dbBlob = Server::keychain(db)->blob(); // memory owned by database
626 *blob = dbBlob;
627 *blobLength = dbBlob->length();
628 END_IPC(DL)
629 }
630
631 kern_return_t ucsp_server_setDbParameters(UCSP_ARGS, DbHandle db, DBParameters params)
632 {
633 BEGIN_IPC(setDbParameters)
634 Server::keychain(db)->setParameters(params);
635 END_IPC(DL)
636 }
637
638 kern_return_t ucsp_server_getDbParameters(UCSP_ARGS, DbHandle db, DBParameters *params)
639 {
640 BEGIN_IPC(getDbParameters)
641 Server::keychain(db)->getParameters(*params);
642 END_IPC(DL)
643 }
644
645 kern_return_t ucsp_server_changePassphrase(UCSP_ARGS, DbHandle db,
646 DATA_IN(cred))
647 {
648 BEGIN_IPC(changePassphrase)
649 CopyOutAccessCredentials creds(cred, credLength);
650 Server::keychain(db)->changePassphrase(creds);
651 END_IPC(DL)
652 }
653
654 kern_return_t ucsp_server_lockAll (UCSP_ARGS, boolean_t)
655 {
656 BEGIN_IPC(lockAll)
657 connection.session().processLockAll();
658 END_IPC(DL)
659 }
660
661 kern_return_t ucsp_server_unlockDb(UCSP_ARGS, DbHandle db)
662 {
663 BEGIN_IPC(unlockDb)
664 Server::keychain(db)->unlockDb();
665 END_IPC(DL)
666 }
667
668 kern_return_t ucsp_server_unlockDbWithPassphrase(UCSP_ARGS, DbHandle db, DATA_IN(passphrase))
669 {
670 BEGIN_IPC(unlockDbWithPassphrase)
671 Server::keychain(db)->unlockDb(DATA(passphrase));
672 END_IPC(DL)
673 }
674
675 kern_return_t ucsp_server_isLocked(UCSP_ARGS, DbHandle db, boolean_t *locked)
676 {
677 BEGIN_IPC(isLocked)
678 *locked = Server::database(db)->isLocked();
679 END_IPC(DL)
680 }
681
682
683 //
684 // Key management
685 //
686 kern_return_t ucsp_server_encodeKey(UCSP_ARGS, KeyHandle keyh, DATA_OUT(blob),
687 boolean_t wantUid, DATA_OUT(uid))
688 {
689 BEGIN_IPC(encodeKey)
690 RefPointer<Key> gKey = Server::key(keyh);
691 if (KeychainKey *key = dynamic_cast<KeychainKey *>(gKey.get())) {
692 KeyBlob *keyBlob = key->blob(); // still owned by key
693 *blob = keyBlob;
694 *blobLength = keyBlob->length();
695 if (wantUid) { // uid generation is not implemented
696 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
697 } else {
698 *uidLength = 0; // do not return this
699 }
700 } else { // not a KeychainKey
701 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE);
702 }
703 END_IPC(CSP)
704 }
705
706 kern_return_t ucsp_server_decodeKey(UCSP_ARGS, KeyHandle *keyh, DATA_OUT(keyHeader),
707 DbHandle db, DATA_IN(blob))
708 {
709 BEGIN_IPC(decodeKey)
710 RefPointer<Key> key = new KeychainKey(*Server::keychain(db), SSBLOB(KeyBlob, blob));
711 CssmKey::Header header;
712 key->returnKey(*keyh, header);
713 if (!copyin(&header, reinterpret_cast<xdrproc_t> (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength))
714 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR);
715 Server::releaseWhenDone(*keyHeader);
716 END_IPC(CSP)
717 }
718
719 // keychain synchronization
720 kern_return_t ucsp_server_recodeKey(UCSP_ARGS, DbHandle oldDb, KeyHandle keyh,
721 DbHandle newDb, DATA_OUT(newBlob))
722 {
723 BEGIN_IPC(recodeKey)
724 // If the old key is passed in as DATA_IN(oldBlob):
725 // RefPointer<KeychainKey> key = new KeychainKey(*Server::keychain(oldDb), SSBLOB(KeyBlob, oldBlob));
726 RefPointer<Key> key = Server::key(keyh);
727 if (KeychainKey *kckey = dynamic_cast<KeychainKey *>(key.get())) {
728 KeyBlob *blob = Server::keychain(newDb)->recodeKey(*kckey);
729 *newBlob = blob;
730 *newBlobLength = blob->length();
731 Server::releaseWhenDone(*newBlob);
732 // @@@ stop leaking blob
733 } else { // not a KeychainKey
734 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE);
735 }
736 END_IPC(CSP)
737 }
738
739 kern_return_t ucsp_server_releaseKey(UCSP_ARGS, KeyHandle keyh)
740 {
741 BEGIN_IPC(releaseKey)
742 RefPointer<Key> key = Server::key(keyh);
743 key->database().releaseKey(*key);
744 END_IPC(CSP)
745 }
746
747 kern_return_t ucsp_server_queryKeySizeInBits(UCSP_ARGS, KeyHandle keyh, CSSM_KEY_SIZE *length)
748 {
749 BEGIN_IPC(queryKeySizeInBits)
750 RefPointer<Key> key = Server::key(keyh);
751 key->database().queryKeySizeInBits(*key, CssmKeySize::overlay(*length));
752 END_IPC(CSP)
753 }
754
755 kern_return_t ucsp_server_getOutputSize(UCSP_ARGS, DATA_IN(context), KeyHandle keyh,
756 uint32 inputSize, boolean_t encrypt, uint32 *outputSize)
757 {
758 BEGIN_IPC(getOutputSize)
759 CopyOutContext ctx(context, contextLength);
760 RefPointer<Key> key = Server::key(keyh);
761 key->database().getOutputSize(*ctx, *key, inputSize, encrypt, *outputSize);
762 END_IPC(CSP)
763 }
764
765 kern_return_t ucsp_server_getKeyDigest(UCSP_ARGS, KeyHandle key, DATA_OUT(digest))
766 {
767 BEGIN_IPC(getKeyDigest)
768 CssmData digestData = Server::key(key)->canonicalDigest();
769 *digest = digestData.data();
770 *digestLength = digestData.length();
771 END_IPC(CSP)
772 }
773
774
775 //
776 // Signatures and MACs
777 //
778 kern_return_t ucsp_server_generateSignature(UCSP_ARGS, DATA_IN(context), KeyHandle keyh,
779 CSSM_ALGORITHMS signOnlyAlgorithm, DATA_IN(data), DATA_OUT(signature))
780 {
781 BEGIN_IPC(generateSignature)
782 CopyOutContext ctx(context, contextLength);
783 RefPointer<Key> key = Server::key(keyh);
784 OutputData sigData(signature, signatureLength);
785 key->database().generateSignature(*ctx, *key, signOnlyAlgorithm,
786 DATA(data), sigData);
787 END_IPC(CSP)
788 }
789
790 kern_return_t ucsp_server_verifySignature(UCSP_ARGS, DATA_IN(context), KeyHandle keyh,
791 CSSM_ALGORITHMS verifyOnlyAlgorithm, DATA_IN(data), DATA_IN(signature))
792 {
793 BEGIN_IPC(verifySignature)
794 CopyOutContext ctx(context, contextLength);
795 RefPointer<Key> key = Server::key(keyh);
796 key->database().verifySignature(*ctx, *key, verifyOnlyAlgorithm,
797 DATA(data), DATA(signature));
798 END_IPC(CSP)
799 }
800
801 kern_return_t ucsp_server_generateMac(UCSP_ARGS, DATA_IN(context), KeyHandle keyh,
802 DATA_IN(data), DATA_OUT(mac))
803 {
804 BEGIN_IPC(generateMac)
805 CopyOutContext ctx(context, contextLength);
806 RefPointer<Key> key = Server::key(keyh);
807 OutputData macData(mac, macLength);
808 key->database().generateMac(*ctx, *key, DATA(data), macData);
809 END_IPC(CSP)
810 }
811
812 kern_return_t ucsp_server_verifyMac(UCSP_ARGS, DATA_IN(context), KeyHandle keyh,
813 DATA_IN(data), DATA_IN(mac))
814 {
815 BEGIN_IPC(verifyMac)
816 CopyOutContext ctx(context, contextLength);
817 RefPointer<Key> key = Server::key(keyh);
818 key->database().verifyMac(*ctx, *key, DATA(data), DATA(mac));
819 END_IPC(CSP)
820 }
821
822
823 //
824 // Encryption/Decryption
825 //
826 kern_return_t ucsp_server_encrypt(UCSP_ARGS, DATA_IN(context), KeyHandle keyh,
827 DATA_IN(clear), DATA_OUT(cipher))
828 {
829 BEGIN_IPC(encrypt)
830 CopyOutContext ctx(context, contextLength);
831 RefPointer<Key> key = Server::key(keyh);
832 OutputData cipherOut(cipher, cipherLength);
833 key->database().encrypt(*ctx, *key, DATA(clear), cipherOut);
834 END_IPC(CSP)
835 }
836
837 kern_return_t ucsp_server_decrypt(UCSP_ARGS, DATA_IN(context), KeyHandle keyh,
838 DATA_IN(cipher), DATA_OUT(clear))
839 {
840 BEGIN_IPC(decrypt)
841 CopyOutContext ctx(context, contextLength);
842 RefPointer<Key> key = Server::key(keyh);
843 OutputData clearOut(clear, clearLength);
844 key->database().decrypt(*ctx, *key, DATA(cipher), clearOut);
845 END_IPC(CSP)
846 }
847
848
849 //
850 // Key generation
851 //
852 kern_return_t ucsp_server_generateKey(UCSP_ARGS, DbHandle db, DATA_IN(context),
853 DATA_IN(cred), DATA_IN(owner),
854 uint32 usage, uint32 attrs, KeyHandle *newKey, DATA_OUT(keyHeader))
855 {
856 BEGIN_IPC(generateKey)
857 CopyOutContext ctx(context, contextLength);
858 CopyOutAccessCredentials creds(cred, credLength);
859
860 CopyOutEntryAcl owneracl(owner, ownerLength);
861 //@@@ preliminary interpretation - will get "type handle"
862 RefPointer<Database> database =
863 Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT);
864 RefPointer<Key> key;
865 database->generateKey(*ctx, creds, owneracl, usage, attrs, key);
866 CssmKey::Header newHeader;
867 key->returnKey(*newKey, newHeader);
868
869 if (!copyin(&newHeader, reinterpret_cast<xdrproc_t> (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength))
870 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR);
871 Server::releaseWhenDone(*keyHeader);
872 END_IPC(CSP)
873 }
874
875 kern_return_t ucsp_server_generateKeyPair(UCSP_ARGS, DbHandle db, DATA_IN(context),
876 DATA_IN(cred), DATA_IN(owner),
877 uint32 pubUsage, uint32 pubAttrs, uint32 privUsage, uint32 privAttrs,
878 KeyHandle *pubKey, DATA_OUT(pubHeader), KeyHandle *privKey, DATA_OUT(privHeader))
879 {
880 BEGIN_IPC(generateKeyPair)
881 CopyOutContext ctx(context, contextLength);
882 CopyOutAccessCredentials creds(cred, credLength);
883 CopyOutEntryAcl owneracl(owner, ownerLength);
884 RefPointer<Database> database =
885 Server::optionalDatabase(db, (privAttrs | pubAttrs) & CSSM_KEYATTR_PERMANENT);
886 RefPointer<Key> pub, priv;
887 database->generateKey(*ctx, creds, owneracl,
888 pubUsage, pubAttrs, privUsage, privAttrs, pub, priv);
889 CssmKey::Header tmpPubHeader, tmpPrivHeader;
890
891 pub->returnKey(*pubKey, tmpPubHeader);
892 if (!copyin(&tmpPubHeader, reinterpret_cast<xdrproc_t> (xdr_CSSM_KEYHEADER), pubHeader, pubHeaderLength))
893 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR);
894 Server::releaseWhenDone(*pubHeader);
895
896 priv->returnKey(*privKey, tmpPrivHeader);
897 if (!copyin(&tmpPrivHeader, reinterpret_cast<xdrproc_t> (xdr_CSSM_KEYHEADER), privHeader, privHeaderLength))
898 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR);
899 Server::releaseWhenDone(*privHeader);
900
901 END_IPC(CSP)
902 }
903
904
905 //
906 // Key wrapping and unwrapping
907 //
908 kern_return_t ucsp_server_wrapKey(UCSP_ARGS, DATA_IN(context), KeyHandle hWrappingKey,
909 DATA_IN(cred), KeyHandle hKeyToBeWrapped,
910 DATA_IN(descriptiveData), DATA_OUT(wrappedKeyData))
911 {
912 BEGIN_IPC(wrapKey)
913 CssmKey wrappedKey;
914 CopyOutContext ctx(context, contextLength);
915 CopyOutAccessCredentials creds(cred, credLength);
916 RefPointer<Key> subjectKey = Server::key(hKeyToBeWrapped);
917 RefPointer<Key> wrappingKey = Server::optionalKey(hWrappingKey);
918 if ((ctx.context().algorithm() == CSSM_ALGID_NONE && subjectKey->attribute(CSSM_KEYATTR_SENSITIVE))
919 || !subjectKey->attribute(CSSM_KEYATTR_EXTRACTABLE))
920 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK);
921 pickDb(subjectKey, wrappingKey)->wrapKey(*ctx, creds, wrappingKey, *subjectKey, DATA(descriptiveData), wrappedKey);
922 Server::releaseWhenDone(wrappedKey.keyData().data());
923
924 if (!copyin(&wrappedKey, reinterpret_cast<xdrproc_t> (xdr_CSSM_KEY), wrappedKeyData, wrappedKeyDataLength))
925 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR);
926
927 Server::releaseWhenDone(*wrappedKeyData);
928 END_IPC(CSP)
929 }
930
931 kern_return_t ucsp_server_unwrapKey(UCSP_ARGS, DbHandle db, DATA_IN(context),
932 KeyHandle hWrappingKey, DATA_IN(cred), DATA_IN(owner),
933 KeyHandle hPublicKey, DATA_IN(wrappedKeyData),
934 CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, DATA_OUT(descriptiveData),
935 KeyHandle *newKey, DATA_OUT(keyHeader)/*CssmKey::Header *newHeader*/)
936 {
937 BEGIN_IPC(unwrapKey)
938 CopyOutContext ctx(context, contextLength);
939 CopyOutKey wrappedKey(wrappedKeyData, wrappedKeyDataLength);
940 CopyOutAccessCredentials creds(cred, credLength);
941 CopyOutEntryAcl owneracl(owner, ownerLength);
942 OutputData descriptiveDatas(descriptiveData, descriptiveDataLength);
943 RefPointer<Key> wrappingKey = Server::optionalKey(hWrappingKey);
944 RefPointer<Key> unwrappedKey;
945 pickDb(Server::optionalDatabase(db), wrappingKey)->unwrapKey(*ctx, creds, owneracl,
946 wrappingKey, Server::optionalKey(hPublicKey),
947 usage, attrs, wrappedKey.key(), unwrappedKey, descriptiveDatas);
948
949 CssmKey::Header newHeader;
950 unwrappedKey->returnKey(*newKey, newHeader);
951 if (!copyin(&newHeader, reinterpret_cast<xdrproc_t> (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength))
952 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR);
953 Server::releaseWhenDone(*keyHeader);
954
955 END_IPC(CSP)
956 }
957
958
959 //
960 // Key derivation.
961 //
962 // Note that the "param" argument can have structure. The walker for the
963 // (artificial) POD CssmDeriveData handles those that are known; if you add
964 // an algorithm with structured param, you need to add a case there.
965 //
966 kern_return_t ucsp_server_deriveKey(UCSP_ARGS, DbHandle db, DATA_IN(context), KeyHandle hKey,
967 DATA_IN(cred), DATA_IN(owner),
968 DATA_IN(paramInput), DATA_OUT(paramOutput),
969 uint32 usage, uint32 attrs, KeyHandle *newKey, DATA_OUT(keyHeader))
970 {
971 BEGIN_IPC(deriveKey)
972 CopyOutContext ctx(context, contextLength);
973 CopyOutAccessCredentials creds(cred, credLength);
974 CopyOutEntryAcl owneracl(owner, ownerLength);
975 CopyOutDeriveData deriveParam(paramInput, paramInputLength);
976 if (deriveParam.algorithm() != ctx.context().algorithm())
977 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); // client layer fault
978
979 RefPointer<Database> database =
980 Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT);
981 RefPointer<Key> key = Server::optionalKey(hKey);
982 CSSM_DATA param = deriveParam.cssm_data();
983 RefPointer<Key> derivedKey;
984 pickDb(Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT),
985 key)->deriveKey(*ctx, key, creds, owneracl, static_cast<CssmData*>(&param), usage, attrs, derivedKey);
986
987 CssmKey::Header newHeader;
988 derivedKey->returnKey(*newKey, newHeader);
989
990 if (!copyin(&newHeader, reinterpret_cast<xdrproc_t> (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength))
991 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR);
992 Server::releaseWhenDone(*keyHeader);
993
994 if (param.Length) {
995 if (!param.Data) // CSP screwed up
996 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
997 OutputData(paramOutput, paramOutputLength) = CssmAutoData(Server::csp().allocator(), param).release();
998 }
999 END_IPC(CSP)
1000 }
1001
1002
1003 //
1004 // Random generation
1005 //
1006 kern_return_t ucsp_server_generateRandom(UCSP_ARGS, uint32 ssid, DATA_IN(context), DATA_OUT(data))
1007 {
1008 BEGIN_IPC(generateRandom)
1009 CopyOutContext ctx(context, contextLength);
1010 if (ssid)
1011 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
1012
1013 // default version (use /dev/random)
1014 Allocator &allocator = Allocator::standard(Allocator::sensitive);
1015 if (size_t bytes = ctx.context().getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE)) {
1016 void *buffer = allocator.malloc(bytes);
1017 Server::active().random(buffer, bytes);
1018 *data = buffer;
1019 *dataLength = bytes;
1020 Server::releaseWhenDone(allocator, buffer);
1021 }
1022 END_IPC(CSP)
1023 }
1024
1025
1026 //
1027 // ACL management.
1028 // Watch out for the memory-management tap-dance.
1029 //
1030 kern_return_t ucsp_server_getOwner(UCSP_ARGS, AclKind kind, KeyHandle key,
1031 DATA_OUT(ownerOut))
1032 {
1033 BEGIN_IPC(getOwner)
1034 AclOwnerPrototype owner;
1035 Server::aclBearer(kind, key).getOwner(owner); // allocates memory in owner
1036 void *owners_data; u_int owners_length;
1037 if (!::copyin(&owner, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_OWNER_PROTOTYPE), &owners_data, &owners_length))
1038 CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR);
1039
1040 { ChunkFreeWalker free; walk(free, owner); } // release chunked original
1041 Server::releaseWhenDone(owners_data); // throw flat copy out when done
1042 *ownerOut = owners_data;
1043 *ownerOutLength = owners_length;
1044 END_IPC(CSP)
1045 }
1046
1047 kern_return_t ucsp_server_setOwner(UCSP_ARGS, AclKind kind, KeyHandle key,
1048 DATA_IN(cred), DATA_IN(owner))
1049 {
1050 BEGIN_IPC(setOwner)
1051 CopyOutAccessCredentials creds(cred, credLength);
1052 CopyOutOwnerAcl owneracl(owner, ownerLength);
1053 Server::aclBearer(kind, key).changeOwner(*owneracl, creds);
1054 END_IPC(CSP)
1055 }
1056
1057 kern_return_t ucsp_server_getAcl(UCSP_ARGS, AclKind kind, KeyHandle key,
1058 boolean_t haveTag, const char *tag,
1059 uint32 *countp, DATA_OUT(acls))
1060 {
1061 BEGIN_IPC(getAcl)
1062 uint32 count;
1063 AclEntryInfo *aclList;
1064 Server::aclBearer(kind, key).getAcl(haveTag ? tag : NULL, count, aclList);
1065
1066 CSSM_ACL_ENTRY_INFO_ARRAY aclsArray = { count, aclList };
1067 void *acls_data; u_int acls_length;
1068 if (!::copyin(&aclsArray, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_INFO_ARRAY), &acls_data, &acls_length))
1069 CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR);
1070
1071 { // release the chunked memory originals
1072 ChunkFreeWalker free;
1073 for (uint32 n = 0; n < count; n++)
1074 walk(free, aclList[n]);
1075
1076 // release the memory allocated for the list itself when we are done
1077 Allocator::standard().free (aclList);
1078 }
1079
1080
1081 *countp = count; // XXX/cs count becomes part of the blob
1082 *aclsLength = acls_length;
1083 *acls = acls_data;
1084 Server::releaseWhenDone(acls_data);
1085 END_IPC(CSP)
1086 }
1087
1088 kern_return_t ucsp_server_changeAcl(UCSP_ARGS, AclKind kind, KeyHandle key,
1089 DATA_IN(cred), CSSM_ACL_EDIT_MODE mode, GenericHandle handle,
1090 DATA_IN(acl))
1091 {
1092 BEGIN_IPC(changeAcl)
1093 CopyOutAccessCredentials creds(cred, credLength);
1094 CopyOutAclEntryInput entryacl(acl, aclLength);
1095
1096 Server::aclBearer(kind, key).changeAcl(AclEdit(mode, handle, entryacl), creds);
1097 END_IPC(CSP)
1098 }
1099
1100
1101 //
1102 // Login/Logout
1103 //
1104 kern_return_t ucsp_server_login(UCSP_ARGS, DATA_IN(cred), DATA_IN(name))
1105 {
1106 BEGIN_IPC(login)
1107 CopyOutAccessCredentials creds(cred, credLength);
1108 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
1109 END_IPC(CSP)
1110 }
1111
1112 kern_return_t ucsp_server_logout(UCSP_ARGS)
1113 {
1114 BEGIN_IPC(logout)
1115 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
1116 END_IPC(CSP)
1117 }
1118
1119
1120 //
1121 // Miscellaneous CSP-related calls
1122 //
1123 kern_return_t ucsp_server_getStatistics(UCSP_ARGS, uint32 ssid, CSSM_CSP_OPERATIONAL_STATISTICS *statistics)
1124 {
1125 BEGIN_IPC(getStatistics)
1126 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
1127 END_IPC(CSP)
1128 }
1129
1130 kern_return_t ucsp_server_getTime(UCSP_ARGS, uint32 ssid, CSSM_ALGORITHMS algorithm, DATA_OUT(data))
1131 {
1132 BEGIN_IPC(getTime)
1133 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
1134 END_IPC(CSP)
1135 }
1136
1137 kern_return_t ucsp_server_getCounter(UCSP_ARGS, uint32 ssid, DATA_OUT(data))
1138 {
1139 BEGIN_IPC(getCounter)
1140 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
1141 END_IPC(CSP)
1142 }
1143
1144 kern_return_t ucsp_server_selfVerify(UCSP_ARGS, uint32 ssid)
1145 {
1146 BEGIN_IPC(selfVerify)
1147 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
1148 END_IPC(CSP)
1149 }
1150
1151
1152 //
1153 // Passthrough calls (separate for CSP and DL passthroughs)
1154 //
1155 kern_return_t ucsp_server_cspPassThrough(UCSP_ARGS, uint32 ssid, uint32 id, DATA_IN(context),
1156 KeyHandle hKey, DATA_IN(inData), DATA_OUT(outData))
1157 {
1158 BEGIN_IPC(cspPassThrough)
1159 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
1160 END_IPC(CSP)
1161 }
1162
1163 kern_return_t ucsp_server_dlPassThrough(UCSP_ARGS, uint32 ssid, uint32 id,
1164 DATA_IN(inData), DATA_OUT(outData))
1165 {
1166 BEGIN_IPC(dlPassThrough)
1167 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
1168 END_IPC(DL)
1169 }
1170
1171
1172 //
1173 // Database key management.
1174 // ExtractMasterKey looks vaguely like a key derivation operation, and is in fact
1175 // presented by the CSPDL's CSSM layer as such.
1176 //
1177 kern_return_t ucsp_server_extractMasterKey(UCSP_ARGS, DbHandle db, DATA_IN(context), DbHandle sourceDb,
1178 DATA_IN(cred), DATA_IN(owner),
1179 uint32 usage, uint32 attrs, KeyHandle *newKey, DATA_OUT(keyHeader))
1180 {
1181 BEGIN_IPC(extractMasterKey)
1182 CopyOutAccessCredentials creds(cred, credLength);
1183 CopyOutEntryAcl owneracl(owner, ownerLength);
1184 CopyOutContext ctx(context, contextLength);
1185 RefPointer<KeychainDatabase> keychain = Server::keychain(sourceDb);
1186 RefPointer<Key> masterKey = keychain->extractMasterKey(
1187 *Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT),
1188 creds, owneracl, usage, attrs);
1189 CssmKey::Header header;
1190 masterKey->returnKey(*newKey, header);
1191 if (!copyin(&header, reinterpret_cast<xdrproc_t> (xdr_CSSM_KEYHEADER), keyHeader, keyHeaderLength))
1192 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR);
1193 Server::releaseWhenDone(*keyHeader);
1194 END_IPC(CSP)
1195 }
1196
1197
1198 //
1199 // Authorization subsystem support
1200 //
1201 kern_return_t ucsp_server_authorizationCreate(UCSP_ARGS,
1202 void *inRights, mach_msg_type_number_t inRightsLength,
1203 uint32 flags,
1204 void *inEnvironment, mach_msg_type_number_t inEnvironmentLength,
1205 AuthorizationBlob *authorization)
1206 {
1207 BEGIN_IPC(authorizationCreate)
1208 AuthorizationItemSet *authrights = NULL, *authenvironment = NULL;
1209
1210 if (inRights && !copyout_AuthorizationItemSet(inRights, inRightsLength, &authrights))
1211 {
1212 Syslog::alert("ucsp_server_authorizationCreate(): error converting 'rights' input");
1213 CssmError::throwMe(errAuthorizationInternal); // allocation error probably
1214 }
1215
1216 if (inEnvironment && !copyout_AuthorizationItemSet(inEnvironment, inEnvironmentLength, &authenvironment))
1217 {
1218 free(authrights);
1219 Syslog::alert("ucsp_server_authorizationCreate(): error converting 'environment' input");
1220 CssmError::throwMe(errAuthorizationInternal); // allocation error probably
1221 }
1222
1223 Authorization::AuthItemSet rights(authrights), environment(authenvironment);
1224
1225 *rcode = connection.process().session().authCreate(rights, environment,
1226 flags, *authorization, auditToken);
1227
1228 // @@@ safe-guard against code throw()ing in here
1229
1230 if (authrights)
1231 free(authrights);
1232
1233 if (authenvironment)
1234 free(authenvironment);
1235
1236 END_IPC(CSSM)
1237 }
1238
1239 kern_return_t ucsp_server_authorizationRelease(UCSP_ARGS,
1240 AuthorizationBlob authorization, uint32 flags)
1241 {
1242 BEGIN_IPC(authorizationRelease)
1243 connection.process().session().authFree(authorization, flags);
1244 END_IPC(CSSM)
1245 }
1246
1247 kern_return_t ucsp_server_authorizationCopyRights(UCSP_ARGS,
1248 AuthorizationBlob authorization,
1249 void *inRights, mach_msg_type_number_t inRightsLength,
1250 uint32 flags,
1251 void *inEnvironment, mach_msg_type_number_t inEnvironmentLength,
1252 void **result, mach_msg_type_number_t *resultLength)
1253 {
1254 BEGIN_IPC(authorizationCopyRights)
1255 AuthorizationItemSet *authrights = NULL, *authenvironment = NULL;
1256
1257 if (inRights && !copyout_AuthorizationItemSet(inRights, inRightsLength, &authrights))
1258 {
1259 Syslog::alert("ucsp_server_authorizationCopyRights(): error converting 'rights' input");
1260 CssmError::throwMe(errAuthorizationInternal); // allocation error probably
1261 }
1262 if (inEnvironment && !copyout_AuthorizationItemSet(inEnvironment, inEnvironmentLength, &authenvironment))
1263 {
1264 free(authrights);
1265 Syslog::alert("ucsp_server_authorizationCopyRights(): error converting 'environment' input");
1266 CssmError::throwMe(errAuthorizationInternal); // allocation error probably
1267 }
1268
1269 Authorization::AuthItemSet rights(authrights), environment(authenvironment), grantedRights;
1270 *rcode = Session::authGetRights(authorization, rights, environment, flags, grantedRights);
1271
1272 // @@@ safe-guard against code throw()ing in here
1273
1274 if (authrights)
1275 free(authrights);
1276
1277 if (authenvironment)
1278 free(authenvironment);
1279
1280 if (result && resultLength)
1281 {
1282 AuthorizationItemSet *copyout = grantedRights.copy();
1283 if (!copyin_AuthorizationItemSet(copyout, result, resultLength))
1284 {
1285 free(copyout);
1286 Syslog::alert("ucsp_server_authorizationCopyRights(): error packaging return information");
1287 CssmError::throwMe(errAuthorizationInternal);
1288 }
1289 free(copyout);
1290 Server::releaseWhenDone(*result);
1291 }
1292 END_IPC(CSSM)
1293 }
1294
1295 kern_return_t ucsp_server_authorizationCopyInfo(UCSP_ARGS,
1296 AuthorizationBlob authorization,
1297 AuthorizationString tag,
1298 void **info, mach_msg_type_number_t *infoLength)
1299 {
1300 BEGIN_IPC(authorizationCopyInfo)
1301 Authorization::AuthItemSet infoSet;
1302 *info = NULL;
1303 *infoLength = 0;
1304 *rcode = connection.process().session().authGetInfo(authorization,
1305 tag[0] ? tag : NULL, infoSet);
1306 if (*rcode == noErr)
1307 {
1308 AuthorizationItemSet *copyout = infoSet.copy();
1309 if (!copyin_AuthorizationItemSet(copyout, info, infoLength))
1310 {
1311 free(copyout);
1312 Syslog::alert("ucsp_server_authorizationCopyInfo(): error packaging return information");
1313 CssmError::throwMe(errAuthorizationInternal);
1314 }
1315 free(copyout);
1316 Server::releaseWhenDone(*info);
1317 }
1318 END_IPC(CSSM)
1319 }
1320
1321 kern_return_t ucsp_server_authorizationExternalize(UCSP_ARGS,
1322 AuthorizationBlob authorization, AuthorizationExternalForm *extForm)
1323 {
1324 BEGIN_IPC(authorizationExternalize)
1325 *rcode = connection.process().session().authExternalize(authorization, *extForm);
1326 END_IPC(CSSM)
1327 }
1328
1329 kern_return_t ucsp_server_authorizationInternalize(UCSP_ARGS,
1330 AuthorizationExternalForm extForm, AuthorizationBlob *authorization)
1331 {
1332 BEGIN_IPC(authorizationInternalize)
1333 *rcode = connection.process().session().authInternalize(extForm, *authorization);
1334 END_IPC(CSSM)
1335 }
1336
1337
1338 //
1339 // Session management subsystem
1340 //
1341 kern_return_t ucsp_server_getSessionInfo(UCSP_ARGS,
1342 SecuritySessionId *sessionId, SessionAttributeBits *attrs)
1343 {
1344 BEGIN_IPC(getSessionInfo)
1345 Session &session = Session::find(*sessionId);
1346 *sessionId = session.handle();
1347 *attrs = session.attributes();
1348 END_IPC(CSSM)
1349 }
1350
1351 kern_return_t ucsp_server_setupSession(UCSP_ARGS,
1352 SessionCreationFlags flags, SessionAttributeBits attrs)
1353 {
1354 BEGIN_IPC(setupSession)
1355 Server::process().session().setupAttributes(flags, attrs);
1356 END_IPC(CSSM)
1357 }
1358
1359 kern_return_t ucsp_server_setSessionDistinguishedUid(UCSP_ARGS,
1360 SecuritySessionId sessionId, uid_t user)
1361 {
1362 BEGIN_IPC(setSessionDistinguishedUid)
1363 Session::find<DynamicSession>(sessionId).originatorUid(user);
1364 END_IPC(CSSM)
1365 }
1366
1367 kern_return_t ucsp_server_getSessionDistinguishedUid(UCSP_ARGS,
1368 SecuritySessionId sessionId, uid_t *user)
1369 {
1370 BEGIN_IPC(getSessionDistinguishedUid)
1371 *user = Session::find(sessionId).originatorUid();
1372 END_IPC(CSSM)
1373 }
1374
1375 kern_return_t ucsp_server_setSessionUserPrefs(UCSP_ARGS, SecuritySessionId sessionId, DATA_IN(userPrefs))
1376 {
1377 BEGIN_IPC(setSessionuserPrefs)
1378 CFRef<CFDataRef> data(CFDataCreate(NULL, (UInt8 *)userPrefs, userPrefsLength));
1379
1380 if (!data)
1381 {
1382 *rcode = errSessionValueNotSet;
1383 return 0;
1384 }
1385
1386 Session::find<DynamicSession>(sessionId).setUserPrefs(data);
1387 *rcode = 0;
1388
1389 END_IPC(CSSM)
1390 }
1391
1392
1393
1394 //
1395 // Notification core subsystem
1396 //
1397
1398 kern_return_t ucsp_server_postNotification(UCSP_ARGS, uint32 domain, uint32 event,
1399 DATA_IN(data), uint32 sequence)
1400 {
1401 BEGIN_IPC(postNotification)
1402 Listener::notify(domain, event, sequence, DATA(data));
1403 END_IPC(CSSM)
1404 }
1405
1406
1407 //
1408 // AuthorizationDB modification
1409 //
1410 kern_return_t ucsp_server_authorizationdbGet(UCSP_ARGS, const char *rightname, DATA_OUT(rightDefinition))
1411 {
1412 BEGIN_IPC(authorizationdbGet)
1413 CFDictionaryRef rightDict;
1414
1415 *rcode = connection.process().session().authorizationdbGet(rightname, &rightDict);
1416
1417 if (!*rcode && rightDict)
1418 {
1419 CFRef<CFDataRef> data(CFPropertyListCreateXMLData (NULL, rightDict));
1420 CFRelease(rightDict);
1421 if (!data)
1422 {
1423 Syslog::alert("ucsp_server_authorizationGet(): unable to make XML version of right definition for '%s'", rightname);
1424 return errAuthorizationInternal;
1425 }
1426
1427 // @@@ copy data to avoid having to do a delayed cfrelease
1428 mach_msg_type_number_t length = CFDataGetLength(data);
1429 void *xmlData = Allocator::standard().malloc(length);
1430 memcpy(xmlData, CFDataGetBytePtr(data), length);
1431 Server::releaseWhenDone(xmlData);
1432
1433 *rightDefinition = xmlData;
1434 *rightDefinitionLength = length;
1435 }
1436 END_IPC(CSSM)
1437 }
1438
1439 kern_return_t ucsp_server_authorizationdbSet(UCSP_ARGS, AuthorizationBlob authorization, const char *rightname, DATA_IN(rightDefinition))
1440 {
1441 BEGIN_IPC(authorizationdbSet)
1442 CFRef<CFDataRef> data(CFDataCreate(NULL, (UInt8 *)rightDefinition, rightDefinitionLength));
1443
1444 if (!data)
1445 {
1446 Syslog::alert("ucsp_server_authorizationSet(): CFDataCreate() error");
1447 return errAuthorizationInternal;
1448 }
1449
1450 CFRef<CFDictionaryRef> rightDefinition(static_cast<CFDictionaryRef>(CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListImmutable, NULL)));
1451
1452 if (!rightDefinition || (CFGetTypeID(rightDefinition) != CFDictionaryGetTypeID()))
1453 {
1454 Syslog::alert("ucsp_server_authorizationSet(): error converting XML right definition for '%s' to property list", rightname);
1455 return errAuthorizationInternal;
1456 }
1457
1458 *rcode = connection.process().session().authorizationdbSet(authorization, rightname, rightDefinition);
1459
1460 END_IPC(CSSM)
1461 }
1462
1463 kern_return_t ucsp_server_authorizationdbRemove(UCSP_ARGS, AuthorizationBlob authorization, const char *rightname)
1464 {
1465 BEGIN_IPC(authorizationdbRemove)
1466 *rcode = connection.process().session().authorizationdbRemove(authorization, rightname);
1467 END_IPC(CSSM)
1468 }
1469
1470
1471 //
1472 // Miscellaneous administrative functions
1473 //
1474 kern_return_t ucsp_server_addCodeEquivalence(UCSP_ARGS, DATA_IN(oldHash), DATA_IN(newHash),
1475 const char *name, boolean_t forSystem)
1476 {
1477 BEGIN_IPC(addCodeEquivalence)
1478 Server::codeSignatures().addLink(DATA(oldHash), DATA(newHash), name, forSystem);
1479 END_IPC(CSSM)
1480 }
1481
1482 kern_return_t ucsp_server_removeCodeEquivalence(UCSP_ARGS, DATA_IN(hash),
1483 const char *name, boolean_t forSystem)
1484 {
1485 BEGIN_IPC(removeCodeEquivalence)
1486 Server::codeSignatures().removeLink(DATA(hash), name, forSystem);
1487 END_IPC(CSSM)
1488 }
1489
1490 kern_return_t ucsp_server_setAlternateSystemRoot(UCSP_ARGS, const char *root)
1491 {
1492 BEGIN_IPC(setAlternateSystemRoot)
1493 #if defined(NDEBUG)
1494 if (connection.process().uid() != 0)
1495 CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED);
1496 #endif //NDEBUG
1497 Server::codeSignatures().open((string(root) + EQUIVALENCEDBPATH).c_str());
1498 END_IPC(CSSM)
1499 }
1500
1501
1502 //
1503 // Child check-in service.
1504 // Note that this isn't using the standard argument pattern.
1505 //
1506 kern_return_t ucsp_server_childCheckIn(mach_port_t serverPort,
1507 mach_port_t servicePort, mach_port_t taskPort)
1508 {
1509 BEGIN_IPCS
1510 ServerChild::checkIn(servicePort, TaskPort(taskPort).pid());
1511 END_IPCS(mach_port_deallocate(mach_task_self(), taskPort))
1512 }
1513
1514
1515 //
1516 // Code Signing Hosting registration.
1517 // Note that the Code Signing Proxy facility (implementing the "cshosting"
1518 // IPC protocol) is elsewhere.
1519 //
1520 kern_return_t ucsp_server_registerHosting(UCSP_ARGS, mach_port_t hostingPort, uint32 flags)
1521 {
1522 BEGIN_IPC(registerHosting)
1523 connection.process().registerCodeSigning(hostingPort, flags);
1524 END_IPC(CSSM)
1525 }
1526
1527 kern_return_t ucsp_server_hostingPort(UCSP_ARGS, pid_t hostPid, mach_port_t *hostingPort)
1528 {
1529 BEGIN_IPC(hostingPort)
1530 if (RefPointer<Process> process = Server::active().findPid(hostPid))
1531 *hostingPort = process->hostingPort();
1532 else
1533 *hostingPort = MACH_PORT_NULL;
1534 secdebug("hosting", "hosting port for for pid=%d is port %d", hostPid, *hostingPort);
1535 END_IPC(CSSM)
1536 }
1537
1538
1539 kern_return_t ucsp_server_setGuest(UCSP_ARGS, SecGuestRef guest, SecCSFlags flags)
1540 {
1541 BEGIN_IPC(setGuest)
1542 connection.guestRef(guest, flags);
1543 END_IPC(CSSM)
1544 }
1545
1546
1547 kern_return_t ucsp_server_createGuest(UCSP_ARGS, SecGuestRef host,
1548 uint32_t status, const char *path, DATA_IN(cdhash), DATA_IN(attributes),
1549 SecCSFlags flags, SecGuestRef *newGuest)
1550 {
1551 BEGIN_IPC(createGuest)
1552 *newGuest = connection.process().createGuest(host, status, path, DATA(cdhash), DATA(attributes), flags);
1553 END_IPC(CSSM)
1554 }
1555
1556 kern_return_t ucsp_server_setGuestStatus(UCSP_ARGS, SecGuestRef guest,
1557 uint32_t status, DATA_IN(attributes))
1558 {
1559 BEGIN_IPC(setGuestStatus)
1560 connection.process().setGuestStatus(guest, status, DATA(attributes));
1561 END_IPC(CSSM)
1562 }
1563
1564 kern_return_t ucsp_server_removeGuest(UCSP_ARGS, SecGuestRef host, SecGuestRef guest)
1565 {
1566 BEGIN_IPC(removeGuest)
1567 connection.process().removeGuest(host, guest);
1568 END_IPC(CSSM)
1569 }
1570
1571 kern_return_t ucsp_server_helpCheckLoad(UCSP_ARGS, const char path[PATH_MAX], uint32_t type)
1572 {
1573 BEGIN_IPC(helpCheckLoad)
1574 END_IPC(CSSM)
1575 }