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