2  * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   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 
  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. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  26 // transition - securityd IPC-to-class-methods transition layer 
  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. 
  32 #include <securityd_client/ss_types.h> 
  33 #include <securityd_client/ucsp.h> 
  37 #include "kcdatabase.h" 
  38 #include "tokendatabase.h" 
  41 #include <mach/mach_error.h> 
  42 #include <securityd_client/xdr_cssm.h> 
  43 #include <securityd_client/xdr_auth.h> 
  44 #include <securityd_client/xdr_dldb.h> 
  46 #include <CoreFoundation/CFDictionary.h> 
  47 #include <CoreFoundation/CFPropertyList.h> 
  52 #define UCSP_ARGS       mach_port_t servicePort, mach_port_t replyPort, \ 
  53         audit_token_t auditToken, CSSM_RETURN *rcode 
  55 #define BEGIN_IPCN      *rcode = CSSM_OK; try { 
  56 #define BEGIN_IPC       BEGIN_IPCN RefPointer<Connection> connRef(&Server::connection(replyPort)); \ 
  57                 Connection &connection __attribute__((unused)) = *connRef; 
  58 #define END_IPC(base)   END_IPCN(base) Server::requestComplete(*rcode); return KERN_SUCCESS; 
  59 #define END_IPCN(base)  } \ 
  60         catch (const CommonError &err) { *rcode = CssmError::cssmError(err, CSSM_ ## base ## _BASE_ERROR); } \ 
  61         catch (const std::bad_alloc &) { *rcode = CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \ 
  62         catch (Connection *conn) { *rcode = 0; } \ 
  63         catch (...) { *rcode = CssmError::merge(CSSM_ERRCODE_INTERNAL_ERROR, CSSM_ ## base ## _BASE_ERROR); } 
  65 #define BEGIN_IPCS              try { 
  66 #define END_IPCS(more)  } catch (...) { } \ 
  67                                                 mach_port_deallocate(mach_task_self(), serverPort); more; return KERN_SUCCESS; 
  69 #define DATA_IN(base)   void *base, mach_msg_type_number_t base##Length 
  70 #define DATA_OUT(base)  void **base, mach_msg_type_number_t *base##Length 
  71 #define DATA(base)              CssmData(base, base##Length) 
  73 #define SSBLOB(Type, name) makeBlob<Type>(DATA(name)) 
  75 using LowLevelMemoryUtilities::increment
; 
  76 using LowLevelMemoryUtilities::difference
; 
  78 class CopyOutAccessCredentials 
: public CopyOut 
{ 
  80         CopyOutAccessCredentials(void *copy
, size_t size
) : CopyOut(copy
, size 
+ sizeof(CSSM_ACCESS_CREDENTIALS
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACCESS_CREDENTIALS_PTR
)) { } 
  81         operator AccessCredentials 
*() { return static_cast<AccessCredentials 
*>(reinterpret_cast<CSSM_ACCESS_CREDENTIALS_PTR
>(data())); } 
  85 class CopyOutEntryAcl 
: public CopyOut 
{ 
  87         CopyOutEntryAcl(void *copy
, size_t size
) : CopyOut(copy
, size 
+ sizeof(CSSM_ACL_ENTRY_PROTOTYPE
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_PROTOTYPE_PTR
)) { } 
  88         operator AclEntryPrototype 
*() { return static_cast<AclEntryPrototype 
*>(reinterpret_cast<CSSM_ACL_ENTRY_PROTOTYPE_PTR
>(data())); } 
  91 class CopyOutOwnerAcl 
: public CopyOut 
{ 
  93         CopyOutOwnerAcl(void *copy
, size_t size
) : CopyOut(copy
, size 
+ sizeof(CSSM_ACL_OWNER_PROTOTYPE
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_OWNER_PROTOTYPE_PTR
)) { } 
  94         operator AclOwnerPrototype 
*() { return static_cast<AclOwnerPrototype 
*>(reinterpret_cast<CSSM_ACL_OWNER_PROTOTYPE_PTR
>(data())); } 
  97 class CopyOutAclEntryInput 
: public CopyOut 
{ 
  99         CopyOutAclEntryInput(void *copy
, size_t size
) : CopyOut(copy
, size 
+ sizeof(CSSM_ACL_ENTRY_INPUT
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_INPUT_PTR
)) { } 
 100         operator AclEntryInput 
*() { return static_cast<AclEntryInput 
*>(reinterpret_cast<CSSM_ACL_ENTRY_INPUT_PTR
>(data())); } 
 104 class CopyOutDeriveData 
: public CopyOut 
{ 
 106         CopyOutDeriveData(void *copy
, size_t size
) : CopyOut(copy
, size 
+ sizeof(CSSM_DERIVE_DATA
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_DERIVE_DATA_PTR
)) { } 
 107         CSSM_DERIVE_DATA 
* derive_data() { return reinterpret_cast<CSSM_DERIVE_DATA 
*>(data()); } 
 108         CSSM_DATA 
&cssm_data() { return derive_data()->baseData
; } 
 109         CSSM_ALGORITHMS 
algorithm() { return derive_data()->algorithm
; } 
 113 class CopyOutContext 
: public CopyOut 
{ 
 115         CopyOutContext(void *copy
, size_t size
) : CopyOut(copy
, size 
+ sizeof(CSSM_CONTEXT
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_CONTEXT_PTR
)) { } 
 116         operator Context 
*() { return static_cast<Context 
*>(reinterpret_cast<CSSM_CONTEXT_PTR
>(data())); } 
 117         Context 
&context() { return *static_cast<Context 
*>(reinterpret_cast<CSSM_CONTEXT_PTR
>(data())); } 
 120 class CopyOutKey 
: public CopyOut 
{ 
 122         CopyOutKey(void *copy
, size_t size
) : CopyOut(copy
, size 
+ sizeof(CSSM_KEY
), reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEY_PTR
)) { } 
 123         operator CssmKey 
*() { return static_cast<CssmKey 
*>(reinterpret_cast<CSSM_KEY_PTR
>(data())); } 
 124         CssmKey 
&key() { return *static_cast<CssmKey 
*>(reinterpret_cast<CSSM_KEY_PTR
>(data())); } 
 127 class CopyOutDbRecordAttributes 
: public CopyOut 
{ 
 129         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
)) { } 
 130         CssmDbRecordAttributeData 
*attribute_data() { return static_cast<CssmDbRecordAttributeData 
*>(reinterpret_cast<CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR
>(data())); } 
 133 class CopyOutQuery 
: public CopyOut 
{ 
 135         CopyOutQuery(void *copy
, size_t size
) : CopyOut(copy
, size
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_QUERY_PTR
)) { } 
 136         operator CssmQuery 
*() { return static_cast<CssmQuery 
*>(reinterpret_cast<CSSM_QUERY_PTR
>(data())); } 
 140 // Take a DATA type RPC argument purportedly representing a Blob of some kind, 
 141 // turn it into a Blob, and fail properly if it's not kosher. 
 143 template <class BlobType
> 
 144 const BlobType 
*makeBlob(const CssmData 
&blobData
, CSSM_RETURN error 
= CSSM_ERRCODE_INVALID_DATA
) 
 146         if (!blobData
.data() || blobData
.length() < sizeof(BlobType
)) 
 147                 CssmError::throwMe(error
); 
 148         const BlobType 
*blob 
= static_cast<const BlobType 
*>(blobData
.data()); 
 149         if (blob
->totalLength 
!= blobData
.length()) 
 150                 CssmError::throwMe(error
); 
 155 // An OutputData object will take memory allocated within securityd, 
 156 // hand it to the MIG return-output parameters, and schedule it to be released 
 157 // after the MIG reply has been sent. It will also get rid of it in case of 
 160 class OutputData 
: public CssmData 
{ 
 162         OutputData(void **outP
, mach_msg_type_number_t 
*outLength
) 
 163                 : mData(*outP
), mLength(*outLength
) { } 
 165         { mData 
= data(); mLength 
= length(); Server::releaseWhenDone(mData
); } 
 167     void operator = (const CssmData 
&source
) 
 168     { CssmData::operator = (source
); } 
 172         mach_msg_type_number_t 
&mLength
; 
 176 // Choose a Database from a choice of two sources, giving preference 
 177 // to persistent stores and to earlier sources. 
 179 Database 
*pickDb(Database 
*db1
, Database 
*db2
); 
 181 static inline Database 
*dbOf(Key 
*key
)  { return key 
? &key
->database() : NULL
; } 
 183 inline Database 
*pickDb(Key 
*k1
, Key 
*k2
) { return pickDb(dbOf(k1
), dbOf(k2
)); } 
 184 inline Database 
*pickDb(Database 
*db1
, Key 
*k2
) { return pickDb(db1
, dbOf(k2
)); } 
 185 inline Database 
*pickDb(Key 
*k1
, Database 
*db2
) { return pickDb(dbOf(k1
), db2
); } 
 188 // Choose a Database from a choice of two sources, giving preference 
 189 // to persistent stores and to earlier sources. 
 191 Database 
*pickDb(Database 
*db1
, Database 
*db2
) 
 193         // persistent db1 always wins 
 194         if (db1 
&& !db1
->transient()) 
 197         // persistent db2 is next choice 
 198         if (db2 
&& !db2
->transient()) 
 201         // pick any existing transient database 
 207         // none at all. use the canonical transient store 
 208         return Server::optionalDatabase(noDb
); 
 212 // Setup/Teardown functions. 
 214 kern_return_t 
ucsp_server_setup(UCSP_ARGS
, mach_port_t taskPort
, ClientSetupInfo info
, const char *identity
) 
 217         Server::active().setupConnection(Server::connectNewProcess
, servicePort
, replyPort
, 
 218                 taskPort
, auditToken
, &info
, identity
); 
 223 kern_return_t 
ucsp_server_setupNew(UCSP_ARGS
, mach_port_t taskPort
, 
 224         ClientSetupInfo info
, const char *identity
, 
 225         mach_port_t 
*newServicePort
) 
 229                 RefPointer
<Session
> session 
= new DynamicSession(taskPort
); 
 230                 Server::active().setupConnection(Server::connectNewSession
, session
->servicePort(), replyPort
, 
 231                         taskPort
, auditToken
, &info
, identity
); 
 232                 *newServicePort 
= session
->servicePort(); 
 233         } catch (const MachPlusPlus::Error 
&err
) { 
 235                 case BOOTSTRAP_SERVICE_ACTIVE
: 
 236                         MacOSError::throwMe(errSessionAuthorizationDenied
);     // translate 
 245 kern_return_t 
ucsp_server_setupThread(UCSP_ARGS
, mach_port_t taskPort
) 
 248         Server::active().setupConnection(Server::connectNewThread
, servicePort
, replyPort
, 
 249                 taskPort
, auditToken
); 
 255 kern_return_t 
ucsp_server_teardown(UCSP_ARGS
) 
 258         Server::active().endConnection(replyPort
); 
 265 // Common database operations 
 267 kern_return_t 
ucsp_server_authenticateDb(UCSP_ARGS
, IPCDbHandle db
, 
 268         CSSM_DB_ACCESS_TYPE accessType
, DATA_IN(cred
)) 
 271     secdebug("dl", "authenticateDb"); 
 272         CopyOutAccessCredentials 
creds(cred
, credLength
); 
 273         // ignoring accessType 
 274     Server::database(db
)->authenticate(accessType
, creds
); 
 278 kern_return_t 
ucsp_server_releaseDb(UCSP_ARGS
, IPCDbHandle db
) 
 281         connection
.process().kill(*Server::database(db
)); 
 286 kern_return_t 
ucsp_server_getDbName(UCSP_ARGS
, IPCDbHandle db
, char name
[PATH_MAX
]) 
 289         string result 
= Server::database(db
)->dbName(); 
 290         assert(result
.length() < PATH_MAX
); 
 291         memcpy(name
, result
.c_str(), result
.length() + 1); 
 295 kern_return_t 
ucsp_server_setDbName(UCSP_ARGS
, IPCDbHandle db
, const char *name
) 
 298         Server::database(db
)->dbName(name
); 
 304 // External database interface 
 306 kern_return_t 
ucsp_server_openToken(UCSP_ARGS
, uint32 ssid
, FilePath name
, 
 307         DATA_IN(accessCredentials
), IPCDbHandle 
*db
) 
 310         CopyOutAccessCredentials 
creds(accessCredentials
, accessCredentialsLength
); 
 311         *db 
= (new TokenDatabase(ssid
, connection
.process(), name
, creds
))->handle(); 
 315 kern_return_t 
ucsp_server_findFirst(UCSP_ARGS
, IPCDbHandle db
, 
 316         DATA_IN(inQuery
), DATA_IN(inAttributes
), DATA_OUT(outAttributes
), 
 317         boolean_t getData
, DATA_OUT(data
),  
 318     IPCKeyHandle 
*hKey
, IPCSearchHandle 
*hSearch
, IPCRecordHandle 
*hRecord
) 
 321         CopyOutQuery 
query(inQuery
, inQueryLength
); 
 322         CopyOutDbRecordAttributes 
attrs(inAttributes
, inAttributesLength
); 
 324         RefPointer
<Database::Search
> search
; 
 325         RefPointer
<Database::Record
> record
; 
 328         CssmDbRecordAttributeData 
*outAttrs 
= NULL
; mach_msg_type_number_t outAttrsLength
; 
 329         Server::database(db
)->findFirst(*query
,  
 330         attrs
.attribute_data(), attrs
.length(), 
 331                 getData 
? &outData 
: NULL
, key
, search
, record
, outAttrs
, outAttrsLength
); 
 333         // handle nothing-found case without exceptions 
 340                 *hRecord 
= record
->handle(); 
 341                 *hSearch 
= search
->handle(); 
 342                 *hKey 
= key 
? key
->handle() : noKey
; 
 344         if (outAttrsLength 
&& outAttrs
) { 
 345             Server::releaseWhenDone(outAttrs
); // exception proof it against next line 
 346             if (!copyin(outAttrs
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA
), outAttributes
, outAttributesLength
)) 
 347                 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
); 
 348             Server::releaseWhenDone(*outAttributes
); 
 351                 // return data (temporary fix) 
 353                         Server::releaseWhenDone(outData
.data()); 
 354             xdrproc_t encode_proc 
= reinterpret_cast<xdrproc_t
>(xdr_CSSM_NO_KEY_IN_DATA
); 
 356                 encode_proc 
= reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEY_IN_DATA
); 
 357                         if (!copyin(&outData
, encode_proc
, data
, dataLength
)) 
 358                                 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
); 
 359                         Server::releaseWhenDone(*data
); 
 366 kern_return_t 
ucsp_server_findNext(UCSP_ARGS
, IPCSearchHandle hSearch
, 
 367         DATA_IN(inAttributes
), 
 368         DATA_OUT(outAttributes
), 
 369         boolean_t getData
, DATA_OUT(data
), IPCKeyHandle 
*hKey
, 
 370         IPCRecordHandle 
*hRecord
) 
 373         CopyOutDbRecordAttributes 
attrs(inAttributes
, inAttributesLength
); 
 374         RefPointer
<Database::Search
> search 
= 
 375                 Server::find
<Database::Search
>(hSearch
, CSSMERR_DL_INVALID_RESULTS_HANDLE
); 
 376         RefPointer
<Database::Record
> record
; 
 379         CssmDbRecordAttributeData 
*outAttrs 
= NULL
; mach_msg_type_number_t outAttrsLength
; 
 380         search
->database().findNext(search
, attrs
.attribute_data(), attrs
.length(), 
 381                 getData 
? &outData 
: NULL
, key
, record
, outAttrs
, outAttrsLength
); 
 383         // handle nothing-found case without exceptions 
 389                 *hRecord 
= record
->handle(); 
 390                 *hKey 
= key 
? key
->handle() : noKey
; 
 392         if (outAttrsLength 
&& outAttrs
) { 
 393                         secdebug("attrmem", "Found attrs: %p of length: %d", outAttrs
, outAttrsLength
); 
 394             Server::releaseWhenDone(outAttrs
); // exception proof it against next line 
 395             if (!copyin(outAttrs
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA
), outAttributes
, outAttributesLength
)) 
 396                 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
); 
 397                         secdebug("attrmem", "Copied attrs: %p of length: %d", *outAttributes
, *outAttributesLength
); 
 398             Server::releaseWhenDone(*outAttributes
); 
 401                 // return data (temporary fix) 
 403                         Server::releaseWhenDone(outData
.data()); 
 404             xdrproc_t encode_proc 
= reinterpret_cast<xdrproc_t
>(xdr_CSSM_NO_KEY_IN_DATA
); 
 406                 encode_proc 
= reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEY_IN_DATA
); 
 407             if (!copyin(&outData
, encode_proc
, data
, dataLength
)) 
 408                 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
); 
 409                         Server::releaseWhenDone(*data
); 
 415 kern_return_t 
ucsp_server_findRecordHandle(UCSP_ARGS
, IPCRecordHandle hRecord
, 
 416         DATA_IN(inAttributes
), DATA_OUT(outAttributes
), 
 417         boolean_t getData
, DATA_OUT(data
), IPCKeyHandle 
*hKey
) 
 420         CopyOutDbRecordAttributes 
attrs(inAttributes
, inAttributesLength
); 
 421         RefPointer
<Database::Record
> record 
= 
 422                 Server::find
<Database::Record
>(hRecord
, CSSMERR_DL_INVALID_RECORD_UID
); 
 425         CssmDbRecordAttributeData 
*outAttrs
; mach_msg_type_number_t outAttrsLength
; 
 426         record
->database().findRecordHandle(record
, attrs
.attribute_data(), attrs
.length(), 
 427                 getData 
? &outData 
: NULL
, key
, outAttrs
, outAttrsLength
); 
 430         *hKey 
= key 
? key
->handle() : noKey
; 
 432     if (outAttrsLength 
&& outAttrs
) { 
 433         Server::releaseWhenDone(outAttrs
); // exception proof it against next line 
 434         if (!copyin(outAttrs
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA
), outAttributes
, outAttributesLength
)) 
 435             CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
); 
 436         Server::releaseWhenDone(*outAttributes
); 
 439         // return data (temporary fix) 
 441                 Server::releaseWhenDone(outData
.data()); 
 442         xdrproc_t encode_proc 
= reinterpret_cast<xdrproc_t
>(xdr_CSSM_NO_KEY_IN_DATA
); 
 444             encode_proc 
= reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEY_IN_DATA
); 
 445         if (!copyin(&outData
, encode_proc
, data
, dataLength
)) 
 446             CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
); 
 447         Server::releaseWhenDone(*data
); 
 452 kern_return_t 
ucsp_server_insertRecord(UCSP_ARGS
, IPCDbHandle db
, CSSM_DB_RECORDTYPE recordType
, 
 453         DATA_IN(inAttributes
), DATA_IN(data
), IPCRecordHandle 
*record
) 
 456         RecordHandle recordHandle
; 
 457         CopyOutDbRecordAttributes 
attrs(inAttributes
, inAttributesLength
); 
 458         Server::database(db
)->insertRecord(recordType
, attrs
.attribute_data(), attrs
.length(), 
 459                 DATA(data
), recordHandle
); 
 460         *record 
= recordHandle
; 
 464 kern_return_t 
ucsp_server_modifyRecord(UCSP_ARGS
, IPCDbHandle db
, IPCRecordHandle 
*hRecord
, 
 465         CSSM_DB_RECORDTYPE recordType
, DATA_IN(attributes
), 
 466         boolean_t setData
, DATA_IN(data
), CSSM_DB_MODIFY_MODE modifyMode
) 
 469         CopyOutDbRecordAttributes 
attrs(attributes
, attributesLength
); 
 470         CssmData 
newData(DATA(data
)); 
 471         RefPointer
<Database::Record
> record 
= 
 472                 Server::find
<Database::Record
>(*hRecord
, CSSMERR_DL_INVALID_RECORD_UID
); 
 473         Server::database(db
)->modifyRecord(recordType
, record
, attrs
.attribute_data(), attrs
.length(), 
 474                 setData 
? &newData 
: NULL
, modifyMode
); 
 475         // note that the record handle presented to the client never changes here 
 476         // (we could, but have no reason to - our record handles are just always up to date) 
 480 kern_return_t 
ucsp_server_deleteRecord(UCSP_ARGS
, IPCDbHandle db
, IPCRecordHandle hRecord
) 
 483         Server::database(db
)->deleteRecord( 
 484                 Server::find
<Database::Record
>(hRecord
, CSSMERR_DL_INVALID_RECORD_UID
)); 
 488 kern_return_t 
ucsp_server_releaseSearch(UCSP_ARGS
, IPCSearchHandle hSearch
) 
 491         RefPointer
<Database::Search
> search 
= Server::find
<Database::Search
>(hSearch
, 0); 
 492         search
->database().releaseSearch(*search
); 
 496 kern_return_t 
ucsp_server_releaseRecord(UCSP_ARGS
, IPCRecordHandle hRecord
) 
 499         RefPointer
<Database::Record
> record 
= Server::find
<Database::Record
>(hRecord
, 0); 
 500         record
->database().releaseRecord(*record
); 
 506 // Internal database management 
 508 kern_return_t 
ucsp_server_createDb(UCSP_ARGS
, IPCDbHandle 
*db
, 
 509         DATA_IN(ident
), DATA_IN(cred
), DATA_IN(owner
), 
 513         CopyOutAccessCredentials 
creds(cred
, credLength
); 
 514         CopyOutEntryAcl 
owneracl(owner
, ownerLength
); 
 515         CopyOut 
flatident(ident
, identLength
, reinterpret_cast<xdrproc_t
>(xdr_DLDbFlatIdentifierRef
)); 
 516         *db 
= (new KeychainDatabase(*reinterpret_cast<DLDbFlatIdentifier
*>(flatident
.data()), params
, connection
.process(), creds
, owneracl
))->handle(); 
 520 // keychain synchronization 
 521 // @@@  caller should be required to call decodeDb() to get a DbHandle 
 522 //      instead of passing the blob itself 
 523 kern_return_t 
ucsp_server_cloneDbForSync(UCSP_ARGS
, DATA_IN(blob
),  
 524         IPCDbHandle srcDb
, DATA_IN(agentData
), IPCDbHandle 
*newDb
) 
 527         RefPointer
<KeychainDatabase
> srcKC 
= Server::keychain(srcDb
); 
 528         *newDb 
= (new KeychainDatabase(*srcKC
, connection
.process(), 
 529                 SSBLOB(DbBlob
, blob
), DATA(agentData
)))->handle(); 
 533 kern_return_t 
ucsp_server_commitDbForSync(UCSP_ARGS
, IPCDbHandle srcDb
, 
 534     IPCDbHandle cloneDb
, DATA_OUT(blob
)) 
 537     RefPointer
<KeychainDatabase
> srcKC 
= Server::keychain(srcDb
); 
 538     RefPointer
<KeychainDatabase
> cloneKC 
= Server::keychain(cloneDb
); 
 539     srcKC
->commitSecretsForSync(*cloneKC
); 
 541         // re-encode blob for convenience 
 542         if (blob 
&& blobLength
) { 
 543                 DbBlob 
*dbBlob 
= srcKC
->blob(); 
 545                 *blobLength 
= dbBlob
->length(); 
 547                 secdebug("kcrecode", "No blob can be returned to client"); 
 552 kern_return_t 
ucsp_server_decodeDb(UCSP_ARGS
, IPCDbHandle 
*db
, 
 553     DATA_IN(ident
), DATA_IN(cred
), DATA_IN(blob
)) 
 556         CopyOutAccessCredentials 
creds(cred
, credLength
); 
 557         CopyOut 
flatident(ident
, identLength
, reinterpret_cast<xdrproc_t
>(xdr_DLDbFlatIdentifierRef
)); 
 558         *db 
= (new KeychainDatabase(*reinterpret_cast<DLDbFlatIdentifier
*>(flatident
.data()), SSBLOB(DbBlob
, blob
), 
 559         connection
.process(), creds
))->handle(); 
 563 kern_return_t 
ucsp_server_encodeDb(UCSP_ARGS
, IPCDbHandle db
, DATA_OUT(blob
)) 
 566     DbBlob 
*dbBlob 
= Server::keychain(db
)->blob();      // memory owned by database 
 568     *blobLength 
= dbBlob
->length(); 
 572 kern_return_t 
ucsp_server_setDbParameters(UCSP_ARGS
, IPCDbHandle db
, DBParameters params
) 
 575         Server::keychain(db
)->setParameters(params
); 
 579 kern_return_t 
ucsp_server_getDbParameters(UCSP_ARGS
, IPCDbHandle db
, DBParameters 
*params
) 
 582         Server::keychain(db
)->getParameters(*params
); 
 586 kern_return_t 
ucsp_server_changePassphrase(UCSP_ARGS
, IPCDbHandle db
, 
 590         CopyOutAccessCredentials 
creds(cred
, credLength
); 
 591         Server::keychain(db
)->changePassphrase(creds
); 
 595 kern_return_t 
ucsp_server_lockAll (UCSP_ARGS
, boolean_t
) 
 598         connection
.session().processLockAll(); 
 602 kern_return_t 
ucsp_server_unlockDb(UCSP_ARGS
, IPCDbHandle db
) 
 605         Server::keychain(db
)->unlockDb(); 
 609 kern_return_t 
ucsp_server_unlockDbWithPassphrase(UCSP_ARGS
, IPCDbHandle db
, DATA_IN(passphrase
)) 
 612         Server::keychain(db
)->unlockDb(DATA(passphrase
)); 
 616 kern_return_t 
ucsp_server_isLocked(UCSP_ARGS
, IPCDbHandle db
, boolean_t 
*locked
) 
 619     *locked 
= Server::database(db
)->isLocked(); 
 627 kern_return_t 
ucsp_server_encodeKey(UCSP_ARGS
, IPCKeyHandle keyh
, DATA_OUT(blob
), 
 628     boolean_t wantUid
, DATA_OUT(uid
)) 
 631         RefPointer
<Key
> gKey 
= Server::key(keyh
); 
 632         if (KeychainKey 
*key 
= dynamic_cast<KeychainKey 
*>(gKey
.get())) { 
 633                 KeyBlob 
*keyBlob 
= key
->blob(); // still owned by key 
 635                 *blobLength 
= keyBlob
->length(); 
 636                 if (wantUid
) {  // uid generation is not implemented 
 637                         CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
); 
 639                         *uidLength 
= 0; // do not return this 
 641         } else {        // not a KeychainKey 
 642                 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE
); 
 647 kern_return_t 
ucsp_server_decodeKey(UCSP_ARGS
, IPCKeyHandle 
*keyh
, DATA_OUT(keyHeader
), 
 648         IPCDbHandle db
, DATA_IN(blob
)) 
 651     RefPointer
<Key
> key 
= new KeychainKey(*Server::keychain(db
), SSBLOB(KeyBlob
, blob
)); 
 652         CssmKey::Header header
; 
 654     key
->returnKey(keyHandle
, header
); 
 656         if (!copyin(&header
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_KEYHEADER
), keyHeader
, keyHeaderLength
)) 
 657                 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
); 
 658         Server::releaseWhenDone(*keyHeader
); 
 662 // keychain synchronization 
 663 kern_return_t 
ucsp_server_recodeKey(UCSP_ARGS
, IPCDbHandle oldDb
, IPCKeyHandle keyh
,  
 664         IPCDbHandle newDb
, DATA_OUT(newBlob
)) 
 667         // If the old key is passed in as DATA_IN(oldBlob): 
 668         // RefPointer<KeychainKey> key = new KeychainKey(*Server::keychain(oldDb), SSBLOB(KeyBlob, oldBlob)); 
 669         RefPointer
<Key
> key 
= Server::key(keyh
); 
 670         if (KeychainKey 
*kckey 
= dynamic_cast<KeychainKey 
*>(key
.get())) { 
 671                 KeyBlob 
*blob 
= Server::keychain(newDb
)->recodeKey(*kckey
); 
 673                 *newBlobLength 
= blob
->length(); 
 674                 Server::releaseWhenDone(*newBlob
); 
 675                 // @@@  stop leaking blob 
 676         } else {        // not a KeychainKey 
 677                 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE
); 
 682 kern_return_t 
ucsp_server_releaseKey(UCSP_ARGS
, IPCKeyHandle keyh
) 
 685         RefPointer
<Key
> key 
= Server::key(keyh
); 
 686         key
->database().releaseKey(*key
); 
 690 kern_return_t 
ucsp_server_queryKeySizeInBits(UCSP_ARGS
, IPCKeyHandle keyh
, CSSM_KEY_SIZE 
*length
) 
 693         RefPointer
<Key
> key 
= Server::key(keyh
); 
 694         key
->database().queryKeySizeInBits(*key
, CssmKeySize::overlay(*length
)); 
 698 kern_return_t 
ucsp_server_getOutputSize(UCSP_ARGS
, DATA_IN(context
), IPCKeyHandle keyh
, 
 699     uint32 inputSize
, boolean_t encrypt
, uint32 
*outputSize
) 
 702         CopyOutContext 
ctx(context
, contextLength
); 
 703         RefPointer
<Key
> key 
= Server::key(keyh
); 
 704     key
->database().getOutputSize(*ctx
, *key
, inputSize
, encrypt
, *outputSize
); 
 708 kern_return_t 
ucsp_server_getKeyDigest(UCSP_ARGS
, IPCKeyHandle key
, DATA_OUT(digest
)) 
 711         CssmData digestData 
= Server::key(key
)->canonicalDigest(); 
 712         *digest 
= digestData
.data(); 
 713         *digestLength 
= digestData
.length(); 
 719 // Signatures and MACs 
 721 kern_return_t 
ucsp_server_generateSignature(UCSP_ARGS
, DATA_IN(context
), IPCKeyHandle keyh
, 
 722         CSSM_ALGORITHMS signOnlyAlgorithm
, DATA_IN(data
), DATA_OUT(signature
)) 
 725         CopyOutContext 
ctx(context
, contextLength
); 
 726         RefPointer
<Key
> key 
= Server::key(keyh
); 
 727         OutputData 
sigData(signature
, signatureLength
); 
 728         key
->database().generateSignature(*ctx
, *key
, signOnlyAlgorithm
, 
 729                 DATA(data
), sigData
); 
 733 kern_return_t 
ucsp_server_verifySignature(UCSP_ARGS
, DATA_IN(context
), IPCKeyHandle keyh
, 
 734                 CSSM_ALGORITHMS verifyOnlyAlgorithm
, DATA_IN(data
), DATA_IN(signature
)) 
 737         CopyOutContext 
ctx(context
, contextLength
); 
 738         RefPointer
<Key
> key 
= Server::key(keyh
); 
 739         key
->database().verifySignature(*ctx
, *key
, verifyOnlyAlgorithm
, 
 740                 DATA(data
), DATA(signature
)); 
 744 kern_return_t 
ucsp_server_generateMac(UCSP_ARGS
, DATA_IN(context
), IPCKeyHandle keyh
, 
 745                 DATA_IN(data
), DATA_OUT(mac
)) 
 748         CopyOutContext 
ctx(context
, contextLength
); 
 749         RefPointer
<Key
> key 
= Server::key(keyh
); 
 750         OutputData 
macData(mac
, macLength
); 
 751         key
->database().generateMac(*ctx
, *key
, DATA(data
), macData
); 
 755 kern_return_t 
ucsp_server_verifyMac(UCSP_ARGS
, DATA_IN(context
), IPCKeyHandle keyh
, 
 756                 DATA_IN(data
), DATA_IN(mac
)) 
 759         CopyOutContext 
ctx(context
, contextLength
); 
 760         RefPointer
<Key
> key 
= Server::key(keyh
); 
 761         key
->database().verifyMac(*ctx
, *key
, DATA(data
), DATA(mac
)); 
 767 // Encryption/Decryption 
 769 kern_return_t 
ucsp_server_encrypt(UCSP_ARGS
, DATA_IN(context
), IPCKeyHandle keyh
, 
 770         DATA_IN(clear
), DATA_OUT(cipher
)) 
 773         CopyOutContext 
ctx(context
, contextLength
); 
 774         RefPointer
<Key
> key 
= Server::key(keyh
); 
 775         OutputData 
cipherOut(cipher
, cipherLength
); 
 776         key
->database().encrypt(*ctx
, *key
, DATA(clear
), cipherOut
); 
 780 kern_return_t 
ucsp_server_decrypt(UCSP_ARGS
, DATA_IN(context
), IPCKeyHandle keyh
, 
 781         DATA_IN(cipher
), DATA_OUT(clear
)) 
 784         CopyOutContext 
ctx(context
, contextLength
); 
 785         RefPointer
<Key
> key 
= Server::key(keyh
); 
 786         OutputData 
clearOut(clear
, clearLength
); 
 787         key
->database().decrypt(*ctx
, *key
, DATA(cipher
), clearOut
); 
 795 kern_return_t 
ucsp_server_generateKey(UCSP_ARGS
, IPCDbHandle db
, DATA_IN(context
), 
 796         DATA_IN(cred
), DATA_IN(owner
), 
 797         uint32 usage
, uint32 attrs
, IPCKeyHandle 
*newKey
, DATA_OUT(keyHeader
)) 
 800         CopyOutContext 
ctx(context
, contextLength
); 
 801         CopyOutAccessCredentials 
creds(cred
, credLength
); 
 803         CopyOutEntryAcl 
owneracl(owner
, ownerLength
); 
 804         //@@@ preliminary interpretation - will get "type handle" 
 805         RefPointer
<Database
> database 
= 
 806                 Server::optionalDatabase(db
, attrs 
& CSSM_KEYATTR_PERMANENT
); 
 808         database
->generateKey(*ctx
, creds
, owneracl
, usage
, attrs
, key
); 
 809         CssmKey::Header newHeader
; 
 811     key
->returnKey(keyHandle
, newHeader
); 
 814         if (!copyin(&newHeader
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_KEYHEADER
), keyHeader
, keyHeaderLength
)) 
 815                 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
); 
 816         Server::releaseWhenDone(*keyHeader
); 
 820 kern_return_t 
ucsp_server_generateKeyPair(UCSP_ARGS
, IPCDbHandle db
, DATA_IN(context
), 
 821         DATA_IN(cred
), DATA_IN(owner
), 
 822         uint32 pubUsage
, uint32 pubAttrs
, uint32 privUsage
, uint32 privAttrs
, 
 823         IPCKeyHandle 
*pubKey
, DATA_OUT(pubHeader
), IPCKeyHandle 
*privKey
, DATA_OUT(privHeader
)) 
 826         CopyOutContext 
ctx(context
, contextLength
); 
 827         CopyOutAccessCredentials 
creds(cred
, credLength
); 
 828         CopyOutEntryAcl 
owneracl(owner
, ownerLength
); 
 829         RefPointer
<Database
> database 
= 
 830                 Server::optionalDatabase(db
, (privAttrs 
| pubAttrs
) & CSSM_KEYATTR_PERMANENT
); 
 831         RefPointer
<Key
> pub
, priv
; 
 832         database
->generateKey(*ctx
, creds
, owneracl
, 
 833                 pubUsage
, pubAttrs
, privUsage
, privAttrs
, pub
, priv
); 
 834         CssmKey::Header tmpPubHeader
, tmpPrivHeader
; 
 835         KeyHandle pubKeyHandle
, privKeyHandle
; 
 837     pub
->returnKey(pubKeyHandle
, tmpPubHeader
); 
 838         *pubKey 
= pubKeyHandle
; 
 839         if (!copyin(&tmpPubHeader
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_KEYHEADER
), pubHeader
, pubHeaderLength
)) 
 840                 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
); 
 841         Server::releaseWhenDone(*pubHeader
); 
 843     priv
->returnKey(privKeyHandle
, tmpPrivHeader
); 
 844         *privKey 
= privKeyHandle
; 
 845         if (!copyin(&tmpPrivHeader
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_KEYHEADER
), privHeader
, privHeaderLength
)) 
 846                 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
); 
 847         Server::releaseWhenDone(*privHeader
); 
 854 // Key wrapping and unwrapping 
 856 kern_return_t 
ucsp_server_wrapKey(UCSP_ARGS
, DATA_IN(context
), IPCKeyHandle hWrappingKey
, 
 857         DATA_IN(cred
), IPCKeyHandle hKeyToBeWrapped
, 
 858         DATA_IN(descriptiveData
), DATA_OUT(wrappedKeyData
)) 
 862         CopyOutContext 
ctx(context
, contextLength
); 
 863         CopyOutAccessCredentials 
creds(cred
, credLength
); 
 864         RefPointer
<Key
> subjectKey 
= Server::key(hKeyToBeWrapped
); 
 865         RefPointer
<Key
> wrappingKey 
= Server::optionalKey(hWrappingKey
); 
 866         if ((ctx
.context().algorithm() == CSSM_ALGID_NONE 
&& subjectKey
->attribute(CSSM_KEYATTR_SENSITIVE
)) 
 867                 || !subjectKey
->attribute(CSSM_KEYATTR_EXTRACTABLE
)) 
 868                 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK
); 
 869         pickDb(subjectKey
, wrappingKey
)->wrapKey(*ctx
, creds
, wrappingKey
, *subjectKey
, DATA(descriptiveData
), wrappedKey
); 
 870         Server::releaseWhenDone(wrappedKey
.keyData().data()); 
 872         if (!copyin(&wrappedKey
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_KEY
), wrappedKeyData
, wrappedKeyDataLength
)) 
 873                 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
); 
 875         Server::releaseWhenDone(*wrappedKeyData
); 
 879 kern_return_t 
ucsp_server_unwrapKey(UCSP_ARGS
, IPCDbHandle db
, DATA_IN(context
), 
 880         IPCKeyHandle hWrappingKey
, DATA_IN(cred
), DATA_IN(owner
), 
 881         IPCKeyHandle hPublicKey
, DATA_IN(wrappedKeyData
), 
 882         CSSM_KEYUSE usage
, CSSM_KEYATTR_FLAGS attrs
, DATA_OUT(descriptiveData
), 
 883     IPCKeyHandle 
*newKey
, DATA_OUT(keyHeader
)/*CssmKey::Header *newHeader*/) 
 886         CopyOutContext 
ctx(context
, contextLength
); 
 887         CopyOutKey 
wrappedKey(wrappedKeyData
, wrappedKeyDataLength
); 
 888         CopyOutAccessCredentials 
creds(cred
, credLength
); 
 889         CopyOutEntryAcl 
owneracl(owner
, ownerLength
); 
 890         OutputData 
descriptiveDatas(descriptiveData
, descriptiveDataLength
); 
 891         RefPointer
<Key
> wrappingKey 
= Server::optionalKey(hWrappingKey
); 
 892     RefPointer
<Key
> unwrappedKey
; 
 893         pickDb(Server::optionalDatabase(db
), wrappingKey
)->unwrapKey(*ctx
, creds
, owneracl
, 
 894                 wrappingKey
, Server::optionalKey(hPublicKey
), 
 895                 usage
, attrs
, wrappedKey
.key(), unwrappedKey
, descriptiveDatas
); 
 897         CssmKey::Header newHeader
; 
 899         unwrappedKey
->returnKey(keyHandle
, newHeader
); 
 901         if (!copyin(&newHeader
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_KEYHEADER
), keyHeader
, keyHeaderLength
)) 
 902                 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
); 
 903         Server::releaseWhenDone(*keyHeader
); 
 912 // Note that the "param" argument can have structure. The walker for the 
 913 // (artificial) POD CssmDeriveData handles those that are known; if you add 
 914 // an algorithm with structured param, you need to add a case there. 
 916 kern_return_t 
ucsp_server_deriveKey(UCSP_ARGS
, IPCDbHandle db
, DATA_IN(context
), IPCKeyHandle hKey
, 
 917         DATA_IN(cred
), DATA_IN(owner
), 
 918     DATA_IN(paramInput
), DATA_OUT(paramOutput
), 
 919         uint32 usage
, uint32 attrs
, IPCKeyHandle 
*newKey
, DATA_OUT(keyHeader
)) 
 922         CopyOutContext 
ctx(context
, contextLength
); 
 923         CopyOutAccessCredentials 
creds(cred
, credLength
); 
 924         CopyOutEntryAcl 
owneracl(owner
, ownerLength
); 
 925         CopyOutDeriveData 
deriveParam(paramInput
, paramInputLength
); 
 926         if (deriveParam
.algorithm() != ctx
.context().algorithm()) 
 927                 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
); // client layer fault 
 929         RefPointer
<Database
> database 
= 
 930                 Server::optionalDatabase(db
, attrs 
& CSSM_KEYATTR_PERMANENT
); 
 931         RefPointer
<Key
> key 
= Server::optionalKey(hKey
); 
 932         CSSM_DATA param 
= deriveParam
.cssm_data(); 
 933         RefPointer
<Key
> derivedKey
; 
 934         pickDb(Server::optionalDatabase(db
, attrs 
& CSSM_KEYATTR_PERMANENT
), 
 935                 key
)->deriveKey(*ctx
, key
, creds
, owneracl
, static_cast<CssmData
*>(¶m
), usage
, attrs
, derivedKey
); 
 937         CssmKey::Header newHeader
; 
 939         derivedKey
->returnKey(keyHandle
, newHeader
); 
 942         if (!copyin(&newHeader
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_KEYHEADER
), keyHeader
, keyHeaderLength
)) 
 943                 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
); 
 944         Server::releaseWhenDone(*keyHeader
); 
 947         if (!param
.Data
)        // CSP screwed up 
 948             CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
); 
 949                 OutputData(paramOutput
, paramOutputLength
) = CssmAutoData(Server::csp().allocator(), param
).release(); 
 958 kern_return_t 
ucsp_server_generateRandom(UCSP_ARGS
, uint32 ssid
, DATA_IN(context
), DATA_OUT(data
)) 
 961         CopyOutContext 
ctx(context
, contextLength
); 
 963                 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
); 
 965         // default version (use /dev/random) 
 966         Allocator 
&allocator 
= Allocator::standard(Allocator::sensitive
); 
 967         if (size_t bytes 
= ctx
.context().getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE
)) { 
 968                 void *buffer 
= allocator
.malloc(bytes
); 
 969                 Server::active().random(buffer
, bytes
); 
 972                 Server::releaseWhenDone(allocator
, buffer
); 
 980 // Watch out for the memory-management tap-dance. 
 982 kern_return_t 
ucsp_server_getOwner(UCSP_ARGS
, AclKind kind
, IPCKeyHandle key
, 
 986         AclOwnerPrototype owner
; 
 987         Server::aclBearer(kind
, key
).getOwner(owner
);   // allocates memory in owner 
 988         void *owners_data
; u_int owners_length
; 
 989         if (!::copyin(&owner
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_OWNER_PROTOTYPE
), &owners_data
, &owners_length
)) 
 990                         CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR
);   
 992         { ChunkFreeWalker free
; walk(free
, owner
); } // release chunked original 
 993         Server::releaseWhenDone(owners_data
); // throw flat copy out when done 
 994         *ownerOut 
= owners_data
; 
 995         *ownerOutLength 
= owners_length
; 
 999 kern_return_t 
ucsp_server_setOwner(UCSP_ARGS
, AclKind kind
, IPCKeyHandle key
, 
1000         DATA_IN(cred
), DATA_IN(owner
)) 
1003         CopyOutAccessCredentials 
creds(cred
, credLength
); 
1004         CopyOutOwnerAcl 
owneracl(owner
, ownerLength
); 
1005         Server::aclBearer(kind
, key
).changeOwner(*owneracl
, creds
); 
1009 kern_return_t 
ucsp_server_getAcl(UCSP_ARGS
, AclKind kind
, IPCKeyHandle key
, 
1010         boolean_t haveTag
, const char *tag
, 
1011         uint32 
*countp
, DATA_OUT(acls
)) 
1015         AclEntryInfo 
*aclList
; 
1016         Server::aclBearer(kind
, key
).getAcl(haveTag 
? tag 
: NULL
, count
, aclList
); 
1018         CSSM_ACL_ENTRY_INFO_ARRAY aclsArray 
= { count
, aclList 
}; 
1019         void *acls_data
; u_int acls_length
; 
1020         if (!::copyin(&aclsArray
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_INFO_ARRAY
), &acls_data
, &acls_length
)) 
1021                         CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR
);   
1023         {       // release the chunked memory originals 
1024                         ChunkFreeWalker free
; 
1025                         for (uint32 n 
= 0; n 
< count
; n
++) 
1026                                         walk(free
, aclList
[n
]); 
1028                         // release the memory allocated for the list itself when we are done 
1029                         Allocator::standard().free (aclList
); 
1033         *countp 
= count
; // XXX/cs count becomes part of the blob 
1034         *aclsLength 
= acls_length
; 
1036         Server::releaseWhenDone(acls_data
); 
1040 kern_return_t 
ucsp_server_changeAcl(UCSP_ARGS
, AclKind kind
, IPCKeyHandle key
, 
1041         DATA_IN(cred
), CSSM_ACL_EDIT_MODE mode
, IPCGenericHandle handle
, 
1045         CopyOutAccessCredentials 
creds(cred
, credLength
); 
1046         CopyOutAclEntryInput 
entryacl(acl
, aclLength
); 
1048         Server::aclBearer(kind
, key
).changeAcl(AclEdit(mode
, handle
, entryacl
), creds
); 
1056 kern_return_t 
ucsp_server_login(UCSP_ARGS
, DATA_IN(cred
), DATA_IN(name
)) 
1059         CopyOutAccessCredentials 
creds(cred
, credLength
); 
1060         CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
); 
1064 kern_return_t 
ucsp_server_logout(UCSP_ARGS
) 
1067         CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
); 
1073 // Miscellaneous CSP-related calls 
1075 kern_return_t 
ucsp_server_getStatistics(UCSP_ARGS
, uint32 ssid
, CSSM_CSP_OPERATIONAL_STATISTICS 
*statistics
) 
1078         CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
); 
1082 kern_return_t 
ucsp_server_getTime(UCSP_ARGS
, uint32 ssid
, CSSM_ALGORITHMS algorithm
, DATA_OUT(data
)) 
1085         CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
); 
1089 kern_return_t 
ucsp_server_getCounter(UCSP_ARGS
, uint32 ssid
, DATA_OUT(data
)) 
1092         CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
); 
1096 kern_return_t 
ucsp_server_selfVerify(UCSP_ARGS
, uint32 ssid
) 
1099         CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
); 
1105 // Passthrough calls (separate for CSP and DL passthroughs) 
1107 kern_return_t 
ucsp_server_cspPassThrough(UCSP_ARGS
, uint32 ssid
, uint32 id
, DATA_IN(context
), 
1108         IPCKeyHandle hKey
, DATA_IN(inData
), DATA_OUT(outData
)) 
1111         CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
); 
1115 kern_return_t 
ucsp_server_dlPassThrough(UCSP_ARGS
, uint32 ssid
, uint32 id
, 
1116         DATA_IN(inData
), DATA_OUT(outData
)) 
1119         CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
); 
1125 // Database key management. 
1126 // ExtractMasterKey looks vaguely like a key derivation operation, and is in fact 
1127 // presented by the CSPDL's CSSM layer as such. 
1129 kern_return_t 
ucsp_server_extractMasterKey(UCSP_ARGS
, IPCDbHandle db
, DATA_IN(context
), IPCDbHandle sourceDb
, 
1130         DATA_IN(cred
), DATA_IN(owner
), 
1131         uint32 usage
, uint32 attrs
, IPCKeyHandle 
*newKey
, DATA_OUT(keyHeader
)) 
1134         CopyOutAccessCredentials 
creds(cred
, credLength
); 
1135         CopyOutEntryAcl 
owneracl(owner
, ownerLength
); 
1136         CopyOutContext 
ctx(context
, contextLength
); 
1137         RefPointer
<KeychainDatabase
> keychain 
= Server::keychain(sourceDb
); 
1138         RefPointer
<Key
> masterKey 
= keychain
->extractMasterKey( 
1139                 *Server::optionalDatabase(db
, attrs 
& CSSM_KEYATTR_PERMANENT
), 
1140                 creds
, owneracl
, usage
, attrs
); 
1141         KeyHandle keyHandle
; 
1142         CssmKey::Header header
; 
1143         masterKey
->returnKey(keyHandle
, header
); 
1144         *newKey 
= keyHandle
; 
1145         if (!copyin(&header
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_KEYHEADER
), keyHeader
, keyHeaderLength
)) 
1146                 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
); 
1147         Server::releaseWhenDone(*keyHeader
); 
1153 // Authorization subsystem support 
1155 kern_return_t 
ucsp_server_authorizationCreate(UCSP_ARGS
, 
1156         void *inRights
, mach_msg_type_number_t inRightsLength
, 
1158         void *inEnvironment
, mach_msg_type_number_t inEnvironmentLength
, 
1159         AuthorizationBlob 
*authorization
) 
1162         AuthorizationItemSet 
*authrights 
= NULL
, *authenvironment 
= NULL
; 
1164         if (inRights 
&& !copyout_AuthorizationItemSet(inRights
, inRightsLength
, &authrights
)) 
1165                 CssmError::throwMe(errAuthorizationInternal
); // allocation error probably 
1167         if (inEnvironment 
&& !copyout_AuthorizationItemSet(inEnvironment
, inEnvironmentLength
, &authenvironment
)) 
1170                 CssmError::throwMe(errAuthorizationInternal
); // allocation error probably 
1173         Authorization::AuthItemSet 
rights(authrights
), environment(authenvironment
); 
1175         *rcode 
= connection
.process().session().authCreate(rights
, environment
,  
1176                 flags
, *authorization
, auditToken
); 
1178         // @@@ safe-guard against code throw()ing in here 
1183         if (authenvironment
) 
1184                 free(authenvironment
); 
1189 kern_return_t 
ucsp_server_authorizationRelease(UCSP_ARGS
, 
1190         AuthorizationBlob authorization
, uint32 flags
) 
1193         connection
.process().session().authFree(authorization
, flags
); 
1197 kern_return_t 
ucsp_server_authorizationCopyRights(UCSP_ARGS
, 
1198         AuthorizationBlob authorization
, 
1199         void *inRights
, mach_msg_type_number_t inRightsLength
, 
1201         void *inEnvironment
, mach_msg_type_number_t inEnvironmentLength
, 
1202         void **result
, mach_msg_type_number_t 
*resultLength
) 
1205         AuthorizationItemSet 
*authrights 
= NULL
, *authenvironment 
= NULL
; 
1207         if (inRights 
&& !copyout_AuthorizationItemSet(inRights
, inRightsLength
, &authrights
)) 
1208                 CssmError::throwMe(errAuthorizationInternal
); // allocation error probably 
1210         if (inEnvironment 
&& !copyout_AuthorizationItemSet(inEnvironment
, inEnvironmentLength
, &authenvironment
)) 
1213                 CssmError::throwMe(errAuthorizationInternal
); // allocation error probably 
1216         Authorization::AuthItemSet 
rights(authrights
), environment(authenvironment
), grantedRights
; 
1217         *rcode 
= Session::authGetRights(authorization
, rights
, environment
, flags
, grantedRights
); 
1219         // @@@ safe-guard against code throw()ing in here 
1224         if (authenvironment
) 
1225                 free(authenvironment
); 
1227         if (result 
&& resultLength
) 
1229                 AuthorizationItemSet 
*copyout 
= grantedRights
.copy(); 
1230                 if (!copyin_AuthorizationItemSet(copyout
, result
, resultLength
)) 
1233                         CssmError::throwMe(errAuthorizationInternal
); 
1236                 Server::releaseWhenDone(*result
); 
1241 kern_return_t 
ucsp_server_authorizationCopyInfo(UCSP_ARGS
, 
1242         AuthorizationBlob authorization
, 
1243         AuthorizationString tag
, 
1244         void **info
, mach_msg_type_number_t 
*infoLength
) 
1247     Authorization::AuthItemSet infoSet
; 
1250     *rcode 
= connection
.process().session().authGetInfo(authorization
, 
1251         tag
[0] ? tag 
: NULL
, infoSet
); 
1252     if (*rcode 
== noErr
) 
1254                 AuthorizationItemSet 
*copyout 
= infoSet
.copy(); 
1255                 if (!copyin_AuthorizationItemSet(copyout
, info
, infoLength
)) 
1258                         CssmError::throwMe(errAuthorizationInternal
); 
1261         Server::releaseWhenDone(*info
); 
1266 kern_return_t 
ucsp_server_authorizationExternalize(UCSP_ARGS
, 
1267         AuthorizationBlob authorization
, AuthorizationExternalForm 
*extForm
) 
1270         *rcode 
= connection
.process().session().authExternalize(authorization
, *extForm
); 
1274 kern_return_t 
ucsp_server_authorizationInternalize(UCSP_ARGS
, 
1275         AuthorizationExternalForm extForm
, AuthorizationBlob 
*authorization
) 
1278         *rcode 
= connection
.process().session().authInternalize(extForm
, *authorization
); 
1284 // Session management subsystem 
1286 kern_return_t 
ucsp_server_getSessionInfo(UCSP_ARGS
, 
1287     SecuritySessionId 
*sessionId
, SessionAttributeBits 
*attrs
) 
1290     Session 
&session 
= Session::find(*sessionId
); 
1291     *sessionId 
= session
.handle(); 
1292     *attrs 
= session
.attributes(); 
1296 kern_return_t 
ucsp_server_setupSession(UCSP_ARGS
, 
1297     SessionCreationFlags flags
, SessionAttributeBits attrs
) 
1300         Server::process().session().setupAttributes(flags
, attrs
); 
1304 kern_return_t 
ucsp_server_setSessionDistinguishedUid(UCSP_ARGS
, 
1305         SecuritySessionId sessionId
, uid_t user
) 
1308         Session::find
<DynamicSession
>(sessionId
).originatorUid(user
); 
1312 kern_return_t 
ucsp_server_getSessionDistinguishedUid(UCSP_ARGS
, 
1313         SecuritySessionId sessionId
, uid_t 
*user
) 
1316         *user 
= Session::find(sessionId
).originatorUid(); 
1320 kern_return_t 
ucsp_server_setSessionUserPrefs(UCSP_ARGS
, SecuritySessionId sessionId
, DATA_IN(userPrefs
)) 
1323         CFRef
<CFDataRef
> data(CFDataCreate(NULL
, (UInt8 
*)userPrefs
, userPrefsLength
)); 
1327                 *rcode 
= errSessionValueNotSet
; 
1331         Session::find
<DynamicSession
>(sessionId
).setUserPrefs(data
); 
1340 // Notification core subsystem 
1343 kern_return_t 
ucsp_server_postNotification(UCSP_ARGS
, uint32 domain
, uint32 event
, 
1344         DATA_IN(data
), uint32 sequence
) 
1347                 Listener::notify(domain
, event
, sequence
, DATA(data
)); 
1353 // AuthorizationDB modification 
1355 kern_return_t 
ucsp_server_authorizationdbGet(UCSP_ARGS
, const char *rightname
, DATA_OUT(rightDefinition
)) 
1358         CFDictionaryRef rightDict
; 
1360         *rcode 
= connection
.process().session().authorizationdbGet(rightname
, &rightDict
); 
1362         if (!*rcode 
&& rightDict
) 
1364                 CFRef
<CFDataRef
> data(CFPropertyListCreateXMLData (NULL
, rightDict
)); 
1365                 CFRelease(rightDict
); 
1367                         return errAuthorizationInternal
; 
1369                 // @@@ copy data to avoid having to do a delayed cfrelease 
1370                 mach_msg_type_number_t length 
= CFDataGetLength(data
); 
1371                 void *xmlData 
= Allocator::standard().malloc(length
); 
1372                 memcpy(xmlData
, CFDataGetBytePtr(data
), length
); 
1373                 Server::releaseWhenDone(xmlData
); 
1375                 *rightDefinition 
= xmlData
; 
1376                 *rightDefinitionLength 
= length
; 
1381 kern_return_t 
ucsp_server_authorizationdbSet(UCSP_ARGS
, AuthorizationBlob authorization
, const char *rightname
, DATA_IN(rightDefinition
)) 
1384         CFRef
<CFDataRef
> data(CFDataCreate(NULL
, (UInt8 
*)rightDefinition
, rightDefinitionLength
)); 
1387                 return errAuthorizationInternal
; 
1389         CFRef
<CFDictionaryRef
> rightDefinition(static_cast<CFDictionaryRef
>(CFPropertyListCreateFromXMLData(NULL
, data
, kCFPropertyListImmutable
, NULL
))); 
1391         if (!rightDefinition 
|| (CFGetTypeID(rightDefinition
) != CFDictionaryGetTypeID())) 
1392                 return errAuthorizationInternal
; 
1394         *rcode 
= connection
.process().session().authorizationdbSet(authorization
, rightname
, rightDefinition
); 
1399 kern_return_t 
ucsp_server_authorizationdbRemove(UCSP_ARGS
, AuthorizationBlob authorization
, const char *rightname
) 
1402         *rcode 
= connection
.process().session().authorizationdbRemove(authorization
, rightname
); 
1408 // Miscellaneous administrative functions 
1410 kern_return_t 
ucsp_server_addCodeEquivalence(UCSP_ARGS
, DATA_IN(oldHash
), DATA_IN(newHash
), 
1411         const char *name
, boolean_t forSystem
) 
1414         Server::codeSignatures().addLink(DATA(oldHash
), DATA(newHash
), name
, forSystem
); 
1418 kern_return_t 
ucsp_server_removeCodeEquivalence(UCSP_ARGS
, DATA_IN(hash
), 
1419         const char *name
, boolean_t forSystem
) 
1422         Server::codeSignatures().removeLink(DATA(hash
), name
, forSystem
); 
1426 kern_return_t 
ucsp_server_setAlternateSystemRoot(UCSP_ARGS
, const char *root
) 
1430         if (connection
.process().uid() != 0) 
1431                 CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED
); 
1433         Server::codeSignatures().open((string(root
) + EQUIVALENCEDBPATH
).c_str()); 
1439 // Child check-in service. 
1440 // Note that this isn't using the standard argument pattern. 
1442 kern_return_t 
ucsp_server_childCheckIn(mach_port_t serverPort
, 
1443         mach_port_t servicePort
, mach_port_t taskPort
) 
1446                 ServerChild::checkIn(servicePort
, TaskPort(taskPort
).pid()); 
1447         END_IPCS(mach_port_deallocate(mach_task_self(), taskPort
)) 
1452 // Code Signing Hosting registration. 
1453 // Note that the Code Signing Proxy facility (implementing the "cshosting" 
1454 // IPC protocol) is elsewhere. 
1456 kern_return_t 
ucsp_server_registerHosting(UCSP_ARGS
, mach_port_t hostingPort
, uint32 flags
) 
1459         connection
.process().registerCodeSigning(hostingPort
, flags
); 
1463 kern_return_t 
ucsp_server_hostingPort(UCSP_ARGS
, pid_t hostPid
, mach_port_t 
*hostingPort
) 
1466         if (RefPointer
<Process
> process 
= Server::active().findPid(hostPid
)) 
1467                 *hostingPort 
= process
->hostingPort(); 
1469                 *hostingPort 
= MACH_PORT_NULL
; 
1470         secdebug("hosting", "hosting port for for pid=%d is port %d", hostPid
, *hostingPort
); 
1475 kern_return_t 
ucsp_server_setGuest(UCSP_ARGS
, SecGuestRef guest
, SecCSFlags flags
) 
1478         connection
.guestRef(guest
, flags
); 
1483 kern_return_t 
ucsp_server_createGuest(UCSP_ARGS
, SecGuestRef host
, 
1484         uint32_t status
, const char *path
, DATA_IN(attributes
), SecCSFlags flags
, SecGuestRef 
*newGuest
) 
1487         *newGuest 
= connection
.process().createGuest(host
, status
, path
, DATA(attributes
), flags
); 
1491 kern_return_t 
ucsp_server_setGuestStatus(UCSP_ARGS
, SecGuestRef guest
, 
1492         uint32_t status
, DATA_IN(attributes
)) 
1495         connection
.process().setGuestStatus(guest
, status
, DATA(attributes
)); 
1499 kern_return_t 
ucsp_server_removeGuest(UCSP_ARGS
, SecGuestRef host
, SecGuestRef guest
) 
1502         connection
.process().removeGuest(host
, guest
);