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