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 85using LowLevelMemoryUtilities::increment; 86using LowLevelMemoryUtilities::difference; 87 88class CopyOutAccessCredentials : public CopyOut { 89public: 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 95class CopyOutEntryAcl : public CopyOut { 96public: 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 101class CopyOutOwnerAcl : public CopyOut { 102public: 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 107class CopyOutAclEntryInput : public CopyOut { 108public: 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 114class CopyOutDeriveData : public CopyOut { 115public: 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 123class CopyOutContext : public CopyOut { 124public: 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 130class CopyOutKey : public CopyOut { 131public: 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 137class CopyOutDbRecordAttributes : public CopyOut { 138public: 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 143class CopyOutQuery : public CopyOut { 144public: 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// 153template <class BlobType> 154const 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// 170class OutputData : public CssmData { 171public: 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 180private: 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// 189Database *pickDb(Database *db1, Database *db2); 190 191static inline Database *dbOf(Key *key) { return key ? &key->database() : NULL; } 192 193inline Database *pickDb(Key *k1, Key *k2) { return pickDb(dbOf(k1), dbOf(k2)); } 194inline Database *pickDb(Database *db1, Key *k2) { return pickDb(db1, dbOf(k2)); } 195inline 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// 201Database *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// 224kern_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 237kern_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 249kern_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 258kern_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 267kern_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// 280kern_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 291kern_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 299kern_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 308kern_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// 319kern_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 328kern_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 379kern_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 428kern_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 471kern_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 483kern_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 499kern_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 507kern_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 515kern_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// 527kern_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 539kern_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 548kern_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 576kern_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 595kern_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 609kern_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 618kern_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 625kern_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 632kern_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 641kern_return_t ucsp_server_lockAll (UCSP_ARGS, boolean_t) 642{ 643 BEGIN_IPC(lockAll) 644 connection.session().processLockAll(); 645 END_IPC(DL) 646} 647 648kern_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 655static 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 679done: 680 if (code_info) { 681 CFRelease(code_info); 682 } 683 684 if (!entitled) { 685 CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED); 686 } 687} 688 689kern_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 696kern_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 704kern_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 712kern_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 719kern_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 726kern_return_t ucsp_server_changeKeyStorePassphrase(UCSP_ARGS) 727{ 728 BEGIN_IPC(verifyKeyStorePassphrase) 729 connection.process().session().changeKeyStorePassphrase(); 730 END_IPC(DL) 731} 732 733kern_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// 743kern_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 763kern_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 777kern_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 796kern_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 804kern_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 812kern_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 822kern_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// 835kern_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 847kern_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 858kern_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 869kern_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// 883kern_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 894kern_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// 909kern_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 932kern_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// 965kern_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 988kern_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// 1023kern_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*>(¶m), 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// 1063kern_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// 1087kern_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 1104kern_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 1114kern_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 1145kern_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// 1161kern_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 1169kern_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// 1180kern_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 1187kern_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 1194kern_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 1201kern_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// 1212kern_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 1220kern_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// 1234kern_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// 1258kern_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 1296kern_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 1304kern_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 1352kern_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 1378kern_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 1386kern_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// 1398kern_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 1420kern_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// 1432kern_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 1461kern_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 1485kern_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// 1496kern_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 1504kern_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 1512kern_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// 1528kern_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// 1542kern_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 1549kern_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 1561kern_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 1569kern_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 1578kern_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 1586kern_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 1593kern_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} 1598