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