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