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
);
263 kern_return_t
ucsp_server_verifyPrivileged(UCSP_ARGS
)
266 // This line intentionally left blank.
272 // Common database operations
274 kern_return_t
ucsp_server_authenticateDb(UCSP_ARGS
, IPCDbHandle db
,
275 CSSM_DB_ACCESS_TYPE accessType
, DATA_IN(cred
))
278 secdebug("dl", "authenticateDb");
279 CopyOutAccessCredentials
creds(cred
, credLength
);
280 // ignoring accessType
281 Server::database(db
)->authenticate(accessType
, creds
);
285 kern_return_t
ucsp_server_releaseDb(UCSP_ARGS
, IPCDbHandle db
)
288 connection
.process().kill(*Server::database(db
));
293 kern_return_t
ucsp_server_getDbName(UCSP_ARGS
, IPCDbHandle db
, char name
[PATH_MAX
])
296 string result
= Server::database(db
)->dbName();
297 assert(result
.length() < PATH_MAX
);
298 memcpy(name
, result
.c_str(), result
.length() + 1);
302 kern_return_t
ucsp_server_setDbName(UCSP_ARGS
, IPCDbHandle db
, const char *name
)
305 Server::database(db
)->dbName(name
);
311 // External database interface
313 kern_return_t
ucsp_server_openToken(UCSP_ARGS
, uint32 ssid
, FilePath name
,
314 DATA_IN(accessCredentials
), IPCDbHandle
*db
)
317 CopyOutAccessCredentials
creds(accessCredentials
, accessCredentialsLength
);
318 *db
= (new TokenDatabase(ssid
, connection
.process(), name
, creds
))->handle();
322 kern_return_t
ucsp_server_findFirst(UCSP_ARGS
, IPCDbHandle db
,
323 DATA_IN(inQuery
), DATA_IN(inAttributes
), DATA_OUT(outAttributes
),
324 boolean_t getData
, DATA_OUT(data
),
325 IPCKeyHandle
*hKey
, IPCSearchHandle
*hSearch
, IPCRecordHandle
*hRecord
)
328 CopyOutQuery
query(inQuery
, inQueryLength
);
329 CopyOutDbRecordAttributes
attrs(inAttributes
, inAttributesLength
);
331 RefPointer
<Database::Search
> search
;
332 RefPointer
<Database::Record
> record
;
335 CssmDbRecordAttributeData
*outAttrs
= NULL
; mach_msg_type_number_t outAttrsLength
;
336 Server::database(db
)->findFirst(*query
,
337 attrs
.attribute_data(), attrs
.length(),
338 getData
? &outData
: NULL
, key
, search
, record
, outAttrs
, outAttrsLength
);
340 // handle nothing-found case without exceptions
347 *hRecord
= record
->handle();
348 *hSearch
= search
->handle();
349 *hKey
= key
? key
->handle() : noKey
;
351 if (outAttrsLength
&& outAttrs
) {
352 Server::releaseWhenDone(outAttrs
); // exception proof it against next line
353 if (!copyin(outAttrs
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA
), outAttributes
, outAttributesLength
))
354 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
);
355 Server::releaseWhenDone(*outAttributes
);
358 // return data (temporary fix)
360 Server::releaseWhenDone(outData
.data());
361 xdrproc_t encode_proc
= reinterpret_cast<xdrproc_t
>(xdr_CSSM_NO_KEY_IN_DATA
);
363 encode_proc
= reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEY_IN_DATA
);
364 if (!copyin(&outData
, encode_proc
, data
, dataLength
))
365 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
);
366 Server::releaseWhenDone(*data
);
373 kern_return_t
ucsp_server_findNext(UCSP_ARGS
, IPCSearchHandle hSearch
,
374 DATA_IN(inAttributes
),
375 DATA_OUT(outAttributes
),
376 boolean_t getData
, DATA_OUT(data
), IPCKeyHandle
*hKey
,
377 IPCRecordHandle
*hRecord
)
380 CopyOutDbRecordAttributes
attrs(inAttributes
, inAttributesLength
);
381 RefPointer
<Database::Search
> search
=
382 Server::find
<Database::Search
>(hSearch
, CSSMERR_DL_INVALID_RESULTS_HANDLE
);
383 RefPointer
<Database::Record
> record
;
386 CssmDbRecordAttributeData
*outAttrs
= NULL
; mach_msg_type_number_t outAttrsLength
;
387 search
->database().findNext(search
, attrs
.attribute_data(), attrs
.length(),
388 getData
? &outData
: NULL
, key
, record
, outAttrs
, outAttrsLength
);
390 // handle nothing-found case without exceptions
396 *hRecord
= record
->handle();
397 *hKey
= key
? key
->handle() : noKey
;
399 if (outAttrsLength
&& outAttrs
) {
400 secdebug("attrmem", "Found attrs: %p of length: %d", outAttrs
, outAttrsLength
);
401 Server::releaseWhenDone(outAttrs
); // exception proof it against next line
402 if (!copyin(outAttrs
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA
), outAttributes
, outAttributesLength
))
403 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
);
404 secdebug("attrmem", "Copied attrs: %p of length: %d", *outAttributes
, *outAttributesLength
);
405 Server::releaseWhenDone(*outAttributes
);
408 // return data (temporary fix)
410 Server::releaseWhenDone(outData
.data());
411 xdrproc_t encode_proc
= reinterpret_cast<xdrproc_t
>(xdr_CSSM_NO_KEY_IN_DATA
);
413 encode_proc
= reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEY_IN_DATA
);
414 if (!copyin(&outData
, encode_proc
, data
, dataLength
))
415 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
);
416 Server::releaseWhenDone(*data
);
422 kern_return_t
ucsp_server_findRecordHandle(UCSP_ARGS
, IPCRecordHandle hRecord
,
423 DATA_IN(inAttributes
), DATA_OUT(outAttributes
),
424 boolean_t getData
, DATA_OUT(data
), IPCKeyHandle
*hKey
)
427 CopyOutDbRecordAttributes
attrs(inAttributes
, inAttributesLength
);
428 RefPointer
<Database::Record
> record
=
429 Server::find
<Database::Record
>(hRecord
, CSSMERR_DL_INVALID_RECORD_UID
);
432 CssmDbRecordAttributeData
*outAttrs
; mach_msg_type_number_t outAttrsLength
;
433 record
->database().findRecordHandle(record
, attrs
.attribute_data(), attrs
.length(),
434 getData
? &outData
: NULL
, key
, outAttrs
, outAttrsLength
);
437 *hKey
= key
? key
->handle() : noKey
;
439 if (outAttrsLength
&& outAttrs
) {
440 Server::releaseWhenDone(outAttrs
); // exception proof it against next line
441 if (!copyin(outAttrs
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA
), outAttributes
, outAttributesLength
))
442 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
);
443 Server::releaseWhenDone(*outAttributes
);
446 // return data (temporary fix)
448 Server::releaseWhenDone(outData
.data());
449 xdrproc_t encode_proc
= reinterpret_cast<xdrproc_t
>(xdr_CSSM_NO_KEY_IN_DATA
);
451 encode_proc
= reinterpret_cast<xdrproc_t
>(xdr_CSSM_KEY_IN_DATA
);
452 if (!copyin(&outData
, encode_proc
, data
, dataLength
))
453 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
);
454 Server::releaseWhenDone(*data
);
459 kern_return_t
ucsp_server_insertRecord(UCSP_ARGS
, IPCDbHandle db
, CSSM_DB_RECORDTYPE recordType
,
460 DATA_IN(inAttributes
), DATA_IN(data
), IPCRecordHandle
*record
)
463 RecordHandle recordHandle
;
464 CopyOutDbRecordAttributes
attrs(inAttributes
, inAttributesLength
);
465 Server::database(db
)->insertRecord(recordType
, attrs
.attribute_data(), attrs
.length(),
466 DATA(data
), recordHandle
);
467 *record
= recordHandle
;
471 kern_return_t
ucsp_server_modifyRecord(UCSP_ARGS
, IPCDbHandle db
, IPCRecordHandle
*hRecord
,
472 CSSM_DB_RECORDTYPE recordType
, DATA_IN(attributes
),
473 boolean_t setData
, DATA_IN(data
), CSSM_DB_MODIFY_MODE modifyMode
)
476 CopyOutDbRecordAttributes
attrs(attributes
, attributesLength
);
477 CssmData
newData(DATA(data
));
478 RefPointer
<Database::Record
> record
=
479 Server::find
<Database::Record
>(*hRecord
, CSSMERR_DL_INVALID_RECORD_UID
);
480 Server::database(db
)->modifyRecord(recordType
, record
, attrs
.attribute_data(), attrs
.length(),
481 setData
? &newData
: NULL
, modifyMode
);
482 // note that the record handle presented to the client never changes here
483 // (we could, but have no reason to - our record handles are just always up to date)
487 kern_return_t
ucsp_server_deleteRecord(UCSP_ARGS
, IPCDbHandle db
, IPCRecordHandle hRecord
)
490 Server::database(db
)->deleteRecord(
491 Server::find
<Database::Record
>(hRecord
, CSSMERR_DL_INVALID_RECORD_UID
));
495 kern_return_t
ucsp_server_releaseSearch(UCSP_ARGS
, IPCSearchHandle hSearch
)
498 RefPointer
<Database::Search
> search
= Server::find
<Database::Search
>(hSearch
, 0);
499 search
->database().releaseSearch(*search
);
503 kern_return_t
ucsp_server_releaseRecord(UCSP_ARGS
, IPCRecordHandle hRecord
)
506 RefPointer
<Database::Record
> record
= Server::find
<Database::Record
>(hRecord
, 0);
507 record
->database().releaseRecord(*record
);
513 // Internal database management
515 kern_return_t
ucsp_server_createDb(UCSP_ARGS
, IPCDbHandle
*db
,
516 DATA_IN(ident
), DATA_IN(cred
), DATA_IN(owner
),
520 CopyOutAccessCredentials
creds(cred
, credLength
);
521 CopyOutEntryAcl
owneracl(owner
, ownerLength
);
522 CopyOut
flatident(ident
, identLength
, reinterpret_cast<xdrproc_t
>(xdr_DLDbFlatIdentifierRef
));
523 *db
= (new KeychainDatabase(*reinterpret_cast<DLDbFlatIdentifier
*>(flatident
.data()), params
, connection
.process(), creds
, owneracl
))->handle();
527 // keychain synchronization
528 // @@@ caller should be required to call decodeDb() to get a DbHandle
529 // instead of passing the blob itself
530 kern_return_t
ucsp_server_cloneDbForSync(UCSP_ARGS
, DATA_IN(blob
),
531 IPCDbHandle srcDb
, DATA_IN(agentData
), IPCDbHandle
*newDb
)
534 RefPointer
<KeychainDatabase
> srcKC
= Server::keychain(srcDb
);
535 *newDb
= (new KeychainDatabase(*srcKC
, connection
.process(),
536 SSBLOB(DbBlob
, blob
), DATA(agentData
)))->handle();
540 kern_return_t
ucsp_server_commitDbForSync(UCSP_ARGS
, IPCDbHandle srcDb
,
541 IPCDbHandle cloneDb
, DATA_OUT(blob
))
544 RefPointer
<KeychainDatabase
> srcKC
= Server::keychain(srcDb
);
545 RefPointer
<KeychainDatabase
> cloneKC
= Server::keychain(cloneDb
);
546 srcKC
->commitSecretsForSync(*cloneKC
);
548 // re-encode blob for convenience
549 if (blob
&& blobLength
) {
550 DbBlob
*dbBlob
= srcKC
->blob();
552 *blobLength
= dbBlob
->length();
554 secdebug("kcrecode", "No blob can be returned to client");
559 kern_return_t
ucsp_server_decodeDb(UCSP_ARGS
, IPCDbHandle
*db
,
560 DATA_IN(ident
), DATA_IN(cred
), DATA_IN(blob
))
563 CopyOutAccessCredentials
creds(cred
, credLength
);
564 CopyOut
flatident(ident
, identLength
, reinterpret_cast<xdrproc_t
>(xdr_DLDbFlatIdentifierRef
));
565 *db
= (new KeychainDatabase(*reinterpret_cast<DLDbFlatIdentifier
*>(flatident
.data()), SSBLOB(DbBlob
, blob
),
566 connection
.process(), creds
))->handle();
570 kern_return_t
ucsp_server_encodeDb(UCSP_ARGS
, IPCDbHandle db
, DATA_OUT(blob
))
573 DbBlob
*dbBlob
= Server::keychain(db
)->blob(); // memory owned by database
575 *blobLength
= dbBlob
->length();
579 kern_return_t
ucsp_server_setDbParameters(UCSP_ARGS
, IPCDbHandle db
, DBParameters params
)
582 Server::keychain(db
)->setParameters(params
);
586 kern_return_t
ucsp_server_getDbParameters(UCSP_ARGS
, IPCDbHandle db
, DBParameters
*params
)
589 Server::keychain(db
)->getParameters(*params
);
593 kern_return_t
ucsp_server_changePassphrase(UCSP_ARGS
, IPCDbHandle db
,
597 CopyOutAccessCredentials
creds(cred
, credLength
);
598 Server::keychain(db
)->changePassphrase(creds
);
602 kern_return_t
ucsp_server_lockAll (UCSP_ARGS
, boolean_t
)
605 connection
.session().processLockAll();
609 kern_return_t
ucsp_server_unlockDb(UCSP_ARGS
, IPCDbHandle db
)
612 Server::keychain(db
)->unlockDb();
616 kern_return_t
ucsp_server_unlockDbWithPassphrase(UCSP_ARGS
, IPCDbHandle db
, DATA_IN(passphrase
))
619 Server::keychain(db
)->unlockDb(DATA(passphrase
));
623 kern_return_t
ucsp_server_isLocked(UCSP_ARGS
, IPCDbHandle db
, boolean_t
*locked
)
626 *locked
= Server::database(db
)->isLocked();
634 kern_return_t
ucsp_server_encodeKey(UCSP_ARGS
, IPCKeyHandle keyh
, DATA_OUT(blob
),
635 boolean_t wantUid
, DATA_OUT(uid
))
638 RefPointer
<Key
> gKey
= Server::key(keyh
);
639 if (KeychainKey
*key
= dynamic_cast<KeychainKey
*>(gKey
.get())) {
640 KeyBlob
*keyBlob
= key
->blob(); // still owned by key
642 *blobLength
= keyBlob
->length();
643 if (wantUid
) { // uid generation is not implemented
644 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
);
646 *uidLength
= 0; // do not return this
648 } else { // not a KeychainKey
649 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE
);
654 kern_return_t
ucsp_server_decodeKey(UCSP_ARGS
, IPCKeyHandle
*keyh
, DATA_OUT(keyHeader
),
655 IPCDbHandle db
, DATA_IN(blob
))
658 RefPointer
<Key
> key
= new KeychainKey(*Server::keychain(db
), SSBLOB(KeyBlob
, blob
));
659 CssmKey::Header header
;
661 key
->returnKey(keyHandle
, header
);
663 if (!copyin(&header
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_KEYHEADER
), keyHeader
, keyHeaderLength
))
664 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
);
665 Server::releaseWhenDone(*keyHeader
);
669 // keychain synchronization
670 kern_return_t
ucsp_server_recodeKey(UCSP_ARGS
, IPCDbHandle oldDb
, IPCKeyHandle keyh
,
671 IPCDbHandle newDb
, DATA_OUT(newBlob
))
674 // If the old key is passed in as DATA_IN(oldBlob):
675 // RefPointer<KeychainKey> key = new KeychainKey(*Server::keychain(oldDb), SSBLOB(KeyBlob, oldBlob));
676 RefPointer
<Key
> key
= Server::key(keyh
);
677 if (KeychainKey
*kckey
= dynamic_cast<KeychainKey
*>(key
.get())) {
678 KeyBlob
*blob
= Server::keychain(newDb
)->recodeKey(*kckey
);
680 *newBlobLength
= blob
->length();
681 Server::releaseWhenDone(*newBlob
);
682 // @@@ stop leaking blob
683 } else { // not a KeychainKey
684 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE
);
689 kern_return_t
ucsp_server_releaseKey(UCSP_ARGS
, IPCKeyHandle keyh
)
692 RefPointer
<Key
> key
= Server::key(keyh
);
693 key
->database().releaseKey(*key
);
697 kern_return_t
ucsp_server_queryKeySizeInBits(UCSP_ARGS
, IPCKeyHandle keyh
, CSSM_KEY_SIZE
*length
)
700 RefPointer
<Key
> key
= Server::key(keyh
);
701 key
->database().queryKeySizeInBits(*key
, CssmKeySize::overlay(*length
));
705 kern_return_t
ucsp_server_getOutputSize(UCSP_ARGS
, DATA_IN(context
), IPCKeyHandle keyh
,
706 uint32 inputSize
, boolean_t encrypt
, uint32
*outputSize
)
709 CopyOutContext
ctx(context
, contextLength
);
710 RefPointer
<Key
> key
= Server::key(keyh
);
711 key
->database().getOutputSize(*ctx
, *key
, inputSize
, encrypt
, *outputSize
);
715 kern_return_t
ucsp_server_getKeyDigest(UCSP_ARGS
, IPCKeyHandle key
, DATA_OUT(digest
))
718 CssmData digestData
= Server::key(key
)->canonicalDigest();
719 *digest
= digestData
.data();
720 *digestLength
= digestData
.length();
726 // Signatures and MACs
728 kern_return_t
ucsp_server_generateSignature(UCSP_ARGS
, DATA_IN(context
), IPCKeyHandle keyh
,
729 CSSM_ALGORITHMS signOnlyAlgorithm
, DATA_IN(data
), DATA_OUT(signature
))
732 CopyOutContext
ctx(context
, contextLength
);
733 RefPointer
<Key
> key
= Server::key(keyh
);
734 OutputData
sigData(signature
, signatureLength
);
735 key
->database().generateSignature(*ctx
, *key
, signOnlyAlgorithm
,
736 DATA(data
), sigData
);
740 kern_return_t
ucsp_server_verifySignature(UCSP_ARGS
, DATA_IN(context
), IPCKeyHandle keyh
,
741 CSSM_ALGORITHMS verifyOnlyAlgorithm
, DATA_IN(data
), DATA_IN(signature
))
744 CopyOutContext
ctx(context
, contextLength
);
745 RefPointer
<Key
> key
= Server::key(keyh
);
746 key
->database().verifySignature(*ctx
, *key
, verifyOnlyAlgorithm
,
747 DATA(data
), DATA(signature
));
751 kern_return_t
ucsp_server_generateMac(UCSP_ARGS
, DATA_IN(context
), IPCKeyHandle keyh
,
752 DATA_IN(data
), DATA_OUT(mac
))
755 CopyOutContext
ctx(context
, contextLength
);
756 RefPointer
<Key
> key
= Server::key(keyh
);
757 OutputData
macData(mac
, macLength
);
758 key
->database().generateMac(*ctx
, *key
, DATA(data
), macData
);
762 kern_return_t
ucsp_server_verifyMac(UCSP_ARGS
, DATA_IN(context
), IPCKeyHandle keyh
,
763 DATA_IN(data
), DATA_IN(mac
))
766 CopyOutContext
ctx(context
, contextLength
);
767 RefPointer
<Key
> key
= Server::key(keyh
);
768 key
->database().verifyMac(*ctx
, *key
, DATA(data
), DATA(mac
));
774 // Encryption/Decryption
776 kern_return_t
ucsp_server_encrypt(UCSP_ARGS
, DATA_IN(context
), IPCKeyHandle keyh
,
777 DATA_IN(clear
), DATA_OUT(cipher
))
780 CopyOutContext
ctx(context
, contextLength
);
781 RefPointer
<Key
> key
= Server::key(keyh
);
782 OutputData
cipherOut(cipher
, cipherLength
);
783 key
->database().encrypt(*ctx
, *key
, DATA(clear
), cipherOut
);
787 kern_return_t
ucsp_server_decrypt(UCSP_ARGS
, DATA_IN(context
), IPCKeyHandle keyh
,
788 DATA_IN(cipher
), DATA_OUT(clear
))
791 CopyOutContext
ctx(context
, contextLength
);
792 RefPointer
<Key
> key
= Server::key(keyh
);
793 OutputData
clearOut(clear
, clearLength
);
794 key
->database().decrypt(*ctx
, *key
, DATA(cipher
), clearOut
);
802 kern_return_t
ucsp_server_generateKey(UCSP_ARGS
, IPCDbHandle db
, DATA_IN(context
),
803 DATA_IN(cred
), DATA_IN(owner
),
804 uint32 usage
, uint32 attrs
, IPCKeyHandle
*newKey
, DATA_OUT(keyHeader
))
807 CopyOutContext
ctx(context
, contextLength
);
808 CopyOutAccessCredentials
creds(cred
, credLength
);
810 CopyOutEntryAcl
owneracl(owner
, ownerLength
);
811 //@@@ preliminary interpretation - will get "type handle"
812 RefPointer
<Database
> database
=
813 Server::optionalDatabase(db
, attrs
& CSSM_KEYATTR_PERMANENT
);
815 database
->generateKey(*ctx
, creds
, owneracl
, usage
, attrs
, key
);
816 CssmKey::Header newHeader
;
818 key
->returnKey(keyHandle
, newHeader
);
821 if (!copyin(&newHeader
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_KEYHEADER
), keyHeader
, keyHeaderLength
))
822 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
);
823 Server::releaseWhenDone(*keyHeader
);
827 kern_return_t
ucsp_server_generateKeyPair(UCSP_ARGS
, IPCDbHandle db
, DATA_IN(context
),
828 DATA_IN(cred
), DATA_IN(owner
),
829 uint32 pubUsage
, uint32 pubAttrs
, uint32 privUsage
, uint32 privAttrs
,
830 IPCKeyHandle
*pubKey
, DATA_OUT(pubHeader
), IPCKeyHandle
*privKey
, DATA_OUT(privHeader
))
833 CopyOutContext
ctx(context
, contextLength
);
834 CopyOutAccessCredentials
creds(cred
, credLength
);
835 CopyOutEntryAcl
owneracl(owner
, ownerLength
);
836 RefPointer
<Database
> database
=
837 Server::optionalDatabase(db
, (privAttrs
| pubAttrs
) & CSSM_KEYATTR_PERMANENT
);
838 RefPointer
<Key
> pub
, priv
;
839 database
->generateKey(*ctx
, creds
, owneracl
,
840 pubUsage
, pubAttrs
, privUsage
, privAttrs
, pub
, priv
);
841 CssmKey::Header tmpPubHeader
, tmpPrivHeader
;
842 KeyHandle pubKeyHandle
, privKeyHandle
;
844 pub
->returnKey(pubKeyHandle
, tmpPubHeader
);
845 *pubKey
= pubKeyHandle
;
846 if (!copyin(&tmpPubHeader
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_KEYHEADER
), pubHeader
, pubHeaderLength
))
847 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
);
848 Server::releaseWhenDone(*pubHeader
);
850 priv
->returnKey(privKeyHandle
, tmpPrivHeader
);
851 *privKey
= privKeyHandle
;
852 if (!copyin(&tmpPrivHeader
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_KEYHEADER
), privHeader
, privHeaderLength
))
853 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
);
854 Server::releaseWhenDone(*privHeader
);
861 // Key wrapping and unwrapping
863 kern_return_t
ucsp_server_wrapKey(UCSP_ARGS
, DATA_IN(context
), IPCKeyHandle hWrappingKey
,
864 DATA_IN(cred
), IPCKeyHandle hKeyToBeWrapped
,
865 DATA_IN(descriptiveData
), DATA_OUT(wrappedKeyData
))
869 CopyOutContext
ctx(context
, contextLength
);
870 CopyOutAccessCredentials
creds(cred
, credLength
);
871 RefPointer
<Key
> subjectKey
= Server::key(hKeyToBeWrapped
);
872 RefPointer
<Key
> wrappingKey
= Server::optionalKey(hWrappingKey
);
873 if ((ctx
.context().algorithm() == CSSM_ALGID_NONE
&& subjectKey
->attribute(CSSM_KEYATTR_SENSITIVE
))
874 || !subjectKey
->attribute(CSSM_KEYATTR_EXTRACTABLE
))
875 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK
);
876 pickDb(subjectKey
, wrappingKey
)->wrapKey(*ctx
, creds
, wrappingKey
, *subjectKey
, DATA(descriptiveData
), wrappedKey
);
877 Server::releaseWhenDone(wrappedKey
.keyData().data());
879 if (!copyin(&wrappedKey
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_KEY
), wrappedKeyData
, wrappedKeyDataLength
))
880 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
);
882 Server::releaseWhenDone(*wrappedKeyData
);
886 kern_return_t
ucsp_server_unwrapKey(UCSP_ARGS
, IPCDbHandle db
, DATA_IN(context
),
887 IPCKeyHandle hWrappingKey
, DATA_IN(cred
), DATA_IN(owner
),
888 IPCKeyHandle hPublicKey
, DATA_IN(wrappedKeyData
),
889 CSSM_KEYUSE usage
, CSSM_KEYATTR_FLAGS attrs
, DATA_OUT(descriptiveData
),
890 IPCKeyHandle
*newKey
, DATA_OUT(keyHeader
)/*CssmKey::Header *newHeader*/)
893 CopyOutContext
ctx(context
, contextLength
);
894 CopyOutKey
wrappedKey(wrappedKeyData
, wrappedKeyDataLength
);
895 CopyOutAccessCredentials
creds(cred
, credLength
);
896 CopyOutEntryAcl
owneracl(owner
, ownerLength
);
897 OutputData
descriptiveDatas(descriptiveData
, descriptiveDataLength
);
898 RefPointer
<Key
> wrappingKey
= Server::optionalKey(hWrappingKey
);
899 RefPointer
<Key
> unwrappedKey
;
900 pickDb(Server::optionalDatabase(db
), wrappingKey
)->unwrapKey(*ctx
, creds
, owneracl
,
901 wrappingKey
, Server::optionalKey(hPublicKey
),
902 usage
, attrs
, wrappedKey
.key(), unwrappedKey
, descriptiveDatas
);
904 CssmKey::Header newHeader
;
906 unwrappedKey
->returnKey(keyHandle
, newHeader
);
908 if (!copyin(&newHeader
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_KEYHEADER
), keyHeader
, keyHeaderLength
))
909 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
);
910 Server::releaseWhenDone(*keyHeader
);
919 // Note that the "param" argument can have structure. The walker for the
920 // (artificial) POD CssmDeriveData handles those that are known; if you add
921 // an algorithm with structured param, you need to add a case there.
923 kern_return_t
ucsp_server_deriveKey(UCSP_ARGS
, IPCDbHandle db
, DATA_IN(context
), IPCKeyHandle hKey
,
924 DATA_IN(cred
), DATA_IN(owner
),
925 DATA_IN(paramInput
), DATA_OUT(paramOutput
),
926 uint32 usage
, uint32 attrs
, IPCKeyHandle
*newKey
, DATA_OUT(keyHeader
))
929 CopyOutContext
ctx(context
, contextLength
);
930 CopyOutAccessCredentials
creds(cred
, credLength
);
931 CopyOutEntryAcl
owneracl(owner
, ownerLength
);
932 CopyOutDeriveData
deriveParam(paramInput
, paramInputLength
);
933 if (deriveParam
.algorithm() != ctx
.context().algorithm())
934 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
); // client layer fault
936 RefPointer
<Database
> database
=
937 Server::optionalDatabase(db
, attrs
& CSSM_KEYATTR_PERMANENT
);
938 RefPointer
<Key
> key
= Server::optionalKey(hKey
);
939 CSSM_DATA param
= deriveParam
.cssm_data();
940 RefPointer
<Key
> derivedKey
;
941 pickDb(Server::optionalDatabase(db
, attrs
& CSSM_KEYATTR_PERMANENT
),
942 key
)->deriveKey(*ctx
, key
, creds
, owneracl
, static_cast<CssmData
*>(¶m
), usage
, attrs
, derivedKey
);
944 CssmKey::Header newHeader
;
946 derivedKey
->returnKey(keyHandle
, newHeader
);
949 if (!copyin(&newHeader
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_KEYHEADER
), keyHeader
, keyHeaderLength
))
950 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
);
951 Server::releaseWhenDone(*keyHeader
);
954 if (!param
.Data
) // CSP screwed up
955 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR
);
956 OutputData(paramOutput
, paramOutputLength
) = CssmAutoData(Server::csp().allocator(), param
).release();
965 kern_return_t
ucsp_server_generateRandom(UCSP_ARGS
, uint32 ssid
, DATA_IN(context
), DATA_OUT(data
))
968 CopyOutContext
ctx(context
, contextLength
);
970 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
);
972 // default version (use /dev/random)
973 Allocator
&allocator
= Allocator::standard(Allocator::sensitive
);
974 if (size_t bytes
= ctx
.context().getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE
)) {
975 void *buffer
= allocator
.malloc(bytes
);
976 Server::active().random(buffer
, bytes
);
979 Server::releaseWhenDone(allocator
, buffer
);
987 // Watch out for the memory-management tap-dance.
989 kern_return_t
ucsp_server_getOwner(UCSP_ARGS
, AclKind kind
, IPCKeyHandle key
,
993 AclOwnerPrototype owner
;
994 Server::aclBearer(kind
, key
).getOwner(owner
); // allocates memory in owner
995 void *owners_data
; u_int owners_length
;
996 if (!::copyin(&owner
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_OWNER_PROTOTYPE
), &owners_data
, &owners_length
))
997 CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR
);
999 { ChunkFreeWalker free
; walk(free
, owner
); } // release chunked original
1000 Server::releaseWhenDone(owners_data
); // throw flat copy out when done
1001 *ownerOut
= owners_data
;
1002 *ownerOutLength
= owners_length
;
1006 kern_return_t
ucsp_server_setOwner(UCSP_ARGS
, AclKind kind
, IPCKeyHandle key
,
1007 DATA_IN(cred
), DATA_IN(owner
))
1010 CopyOutAccessCredentials
creds(cred
, credLength
);
1011 CopyOutOwnerAcl
owneracl(owner
, ownerLength
);
1012 Server::aclBearer(kind
, key
).changeOwner(*owneracl
, creds
);
1016 kern_return_t
ucsp_server_getAcl(UCSP_ARGS
, AclKind kind
, IPCKeyHandle key
,
1017 boolean_t haveTag
, const char *tag
,
1018 uint32
*countp
, DATA_OUT(acls
))
1022 AclEntryInfo
*aclList
;
1023 Server::aclBearer(kind
, key
).getAcl(haveTag
? tag
: NULL
, count
, aclList
);
1025 CSSM_ACL_ENTRY_INFO_ARRAY aclsArray
= { count
, aclList
};
1026 void *acls_data
; u_int acls_length
;
1027 if (!::copyin(&aclsArray
, reinterpret_cast<xdrproc_t
>(xdr_CSSM_ACL_ENTRY_INFO_ARRAY
), &acls_data
, &acls_length
))
1028 CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR
);
1030 { // release the chunked memory originals
1031 ChunkFreeWalker free
;
1032 for (uint32 n
= 0; n
< count
; n
++)
1033 walk(free
, aclList
[n
]);
1035 // release the memory allocated for the list itself when we are done
1036 Allocator::standard().free (aclList
);
1040 *countp
= count
; // XXX/cs count becomes part of the blob
1041 *aclsLength
= acls_length
;
1043 Server::releaseWhenDone(acls_data
);
1047 kern_return_t
ucsp_server_changeAcl(UCSP_ARGS
, AclKind kind
, IPCKeyHandle key
,
1048 DATA_IN(cred
), CSSM_ACL_EDIT_MODE mode
, IPCGenericHandle handle
,
1052 CopyOutAccessCredentials
creds(cred
, credLength
);
1053 CopyOutAclEntryInput
entryacl(acl
, aclLength
);
1055 Server::aclBearer(kind
, key
).changeAcl(AclEdit(mode
, handle
, entryacl
), creds
);
1063 kern_return_t
ucsp_server_login(UCSP_ARGS
, DATA_IN(cred
), DATA_IN(name
))
1066 CopyOutAccessCredentials
creds(cred
, credLength
);
1067 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
);
1071 kern_return_t
ucsp_server_logout(UCSP_ARGS
)
1074 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
);
1080 // Miscellaneous CSP-related calls
1082 kern_return_t
ucsp_server_getStatistics(UCSP_ARGS
, uint32 ssid
, CSSM_CSP_OPERATIONAL_STATISTICS
*statistics
)
1085 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
);
1089 kern_return_t
ucsp_server_getTime(UCSP_ARGS
, uint32 ssid
, CSSM_ALGORITHMS algorithm
, DATA_OUT(data
))
1092 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
);
1096 kern_return_t
ucsp_server_getCounter(UCSP_ARGS
, uint32 ssid
, DATA_OUT(data
))
1099 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
);
1103 kern_return_t
ucsp_server_selfVerify(UCSP_ARGS
, uint32 ssid
)
1106 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
);
1112 // Passthrough calls (separate for CSP and DL passthroughs)
1114 kern_return_t
ucsp_server_cspPassThrough(UCSP_ARGS
, uint32 ssid
, uint32 id
, DATA_IN(context
),
1115 IPCKeyHandle hKey
, DATA_IN(inData
), DATA_OUT(outData
))
1118 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
);
1122 kern_return_t
ucsp_server_dlPassThrough(UCSP_ARGS
, uint32 ssid
, uint32 id
,
1123 DATA_IN(inData
), DATA_OUT(outData
))
1126 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED
);
1132 // Database key management.
1133 // ExtractMasterKey looks vaguely like a key derivation operation, and is in fact
1134 // presented by the CSPDL's CSSM layer as such.
1136 kern_return_t
ucsp_server_extractMasterKey(UCSP_ARGS
, IPCDbHandle db
, DATA_IN(context
), IPCDbHandle sourceDb
,
1137 DATA_IN(cred
), DATA_IN(owner
),
1138 uint32 usage
, uint32 attrs
, IPCKeyHandle
*newKey
, DATA_OUT(keyHeader
))
1141 CopyOutAccessCredentials
creds(cred
, credLength
);
1142 CopyOutEntryAcl
owneracl(owner
, ownerLength
);
1143 CopyOutContext
ctx(context
, contextLength
);
1144 RefPointer
<KeychainDatabase
> keychain
= Server::keychain(sourceDb
);
1145 RefPointer
<Key
> masterKey
= keychain
->extractMasterKey(
1146 *Server::optionalDatabase(db
, attrs
& CSSM_KEYATTR_PERMANENT
),
1147 creds
, owneracl
, usage
, attrs
);
1148 KeyHandle keyHandle
;
1149 CssmKey::Header header
;
1150 masterKey
->returnKey(keyHandle
, header
);
1151 *newKey
= keyHandle
;
1152 if (!copyin(&header
, reinterpret_cast<xdrproc_t
> (xdr_CSSM_KEYHEADER
), keyHeader
, keyHeaderLength
))
1153 CssmError::throwMe(CSSMERR_CSSM_MEMORY_ERROR
);
1154 Server::releaseWhenDone(*keyHeader
);
1160 // Authorization subsystem support
1162 kern_return_t
ucsp_server_authorizationCreate(UCSP_ARGS
,
1163 void *inRights
, mach_msg_type_number_t inRightsLength
,
1165 void *inEnvironment
, mach_msg_type_number_t inEnvironmentLength
,
1166 AuthorizationBlob
*authorization
)
1169 AuthorizationItemSet
*authrights
= NULL
, *authenvironment
= NULL
;
1171 if (inRights
&& !copyout_AuthorizationItemSet(inRights
, inRightsLength
, &authrights
))
1172 CssmError::throwMe(errAuthorizationInternal
); // allocation error probably
1174 if (inEnvironment
&& !copyout_AuthorizationItemSet(inEnvironment
, inEnvironmentLength
, &authenvironment
))
1177 CssmError::throwMe(errAuthorizationInternal
); // allocation error probably
1180 Authorization::AuthItemSet
rights(authrights
), environment(authenvironment
);
1182 *rcode
= connection
.process().session().authCreate(rights
, environment
,
1183 flags
, *authorization
, auditToken
);
1185 // @@@ safe-guard against code throw()ing in here
1190 if (authenvironment
)
1191 free(authenvironment
);
1196 kern_return_t
ucsp_server_authorizationRelease(UCSP_ARGS
,
1197 AuthorizationBlob authorization
, uint32 flags
)
1200 connection
.process().session().authFree(authorization
, flags
);
1204 kern_return_t
ucsp_server_authorizationCopyRights(UCSP_ARGS
,
1205 AuthorizationBlob authorization
,
1206 void *inRights
, mach_msg_type_number_t inRightsLength
,
1208 void *inEnvironment
, mach_msg_type_number_t inEnvironmentLength
,
1209 void **result
, mach_msg_type_number_t
*resultLength
)
1212 AuthorizationItemSet
*authrights
= NULL
, *authenvironment
= NULL
;
1214 if (inRights
&& !copyout_AuthorizationItemSet(inRights
, inRightsLength
, &authrights
))
1215 CssmError::throwMe(errAuthorizationInternal
); // allocation error probably
1217 if (inEnvironment
&& !copyout_AuthorizationItemSet(inEnvironment
, inEnvironmentLength
, &authenvironment
))
1220 CssmError::throwMe(errAuthorizationInternal
); // allocation error probably
1223 Authorization::AuthItemSet
rights(authrights
), environment(authenvironment
), grantedRights
;
1224 *rcode
= Session::authGetRights(authorization
, rights
, environment
, flags
, grantedRights
);
1226 // @@@ safe-guard against code throw()ing in here
1231 if (authenvironment
)
1232 free(authenvironment
);
1234 if (result
&& resultLength
)
1236 AuthorizationItemSet
*copyout
= grantedRights
.copy();
1237 if (!copyin_AuthorizationItemSet(copyout
, result
, resultLength
))
1240 CssmError::throwMe(errAuthorizationInternal
);
1243 Server::releaseWhenDone(*result
);
1248 kern_return_t
ucsp_server_authorizationCopyInfo(UCSP_ARGS
,
1249 AuthorizationBlob authorization
,
1250 AuthorizationString tag
,
1251 void **info
, mach_msg_type_number_t
*infoLength
)
1254 Authorization::AuthItemSet infoSet
;
1257 *rcode
= connection
.process().session().authGetInfo(authorization
,
1258 tag
[0] ? tag
: NULL
, infoSet
);
1259 if (*rcode
== noErr
)
1261 AuthorizationItemSet
*copyout
= infoSet
.copy();
1262 if (!copyin_AuthorizationItemSet(copyout
, info
, infoLength
))
1265 CssmError::throwMe(errAuthorizationInternal
);
1268 Server::releaseWhenDone(*info
);
1273 kern_return_t
ucsp_server_authorizationExternalize(UCSP_ARGS
,
1274 AuthorizationBlob authorization
, AuthorizationExternalForm
*extForm
)
1277 *rcode
= connection
.process().session().authExternalize(authorization
, *extForm
);
1281 kern_return_t
ucsp_server_authorizationInternalize(UCSP_ARGS
,
1282 AuthorizationExternalForm extForm
, AuthorizationBlob
*authorization
)
1285 *rcode
= connection
.process().session().authInternalize(extForm
, *authorization
);
1291 // Session management subsystem
1293 kern_return_t
ucsp_server_getSessionInfo(UCSP_ARGS
,
1294 SecuritySessionId
*sessionId
, SessionAttributeBits
*attrs
)
1297 Session
&session
= Session::find(*sessionId
);
1298 *sessionId
= session
.handle();
1299 *attrs
= session
.attributes();
1303 kern_return_t
ucsp_server_setupSession(UCSP_ARGS
,
1304 SessionCreationFlags flags
, SessionAttributeBits attrs
)
1307 Server::process().session().setupAttributes(flags
, attrs
);
1311 kern_return_t
ucsp_server_setSessionDistinguishedUid(UCSP_ARGS
,
1312 SecuritySessionId sessionId
, uid_t user
)
1315 Session::find
<DynamicSession
>(sessionId
).originatorUid(user
);
1319 kern_return_t
ucsp_server_getSessionDistinguishedUid(UCSP_ARGS
,
1320 SecuritySessionId sessionId
, uid_t
*user
)
1323 *user
= Session::find(sessionId
).originatorUid();
1327 kern_return_t
ucsp_server_setSessionUserPrefs(UCSP_ARGS
, SecuritySessionId sessionId
, DATA_IN(userPrefs
))
1330 CFRef
<CFDataRef
> data(CFDataCreate(NULL
, (UInt8
*)userPrefs
, userPrefsLength
));
1334 *rcode
= errSessionValueNotSet
;
1338 Session::find
<DynamicSession
>(sessionId
).setUserPrefs(data
);
1347 // Notification core subsystem
1350 kern_return_t
ucsp_server_postNotification(UCSP_ARGS
, uint32 domain
, uint32 event
,
1351 DATA_IN(data
), uint32 sequence
)
1354 Listener::notify(domain
, event
, sequence
, DATA(data
));
1360 // AuthorizationDB modification
1362 kern_return_t
ucsp_server_authorizationdbGet(UCSP_ARGS
, const char *rightname
, DATA_OUT(rightDefinition
))
1365 CFDictionaryRef rightDict
;
1367 *rcode
= connection
.process().session().authorizationdbGet(rightname
, &rightDict
);
1369 if (!*rcode
&& rightDict
)
1371 CFRef
<CFDataRef
> data(CFPropertyListCreateXMLData (NULL
, rightDict
));
1372 CFRelease(rightDict
);
1374 return errAuthorizationInternal
;
1376 // @@@ copy data to avoid having to do a delayed cfrelease
1377 mach_msg_type_number_t length
= CFDataGetLength(data
);
1378 void *xmlData
= Allocator::standard().malloc(length
);
1379 memcpy(xmlData
, CFDataGetBytePtr(data
), length
);
1380 Server::releaseWhenDone(xmlData
);
1382 *rightDefinition
= xmlData
;
1383 *rightDefinitionLength
= length
;
1388 kern_return_t
ucsp_server_authorizationdbSet(UCSP_ARGS
, AuthorizationBlob authorization
, const char *rightname
, DATA_IN(rightDefinition
))
1391 CFRef
<CFDataRef
> data(CFDataCreate(NULL
, (UInt8
*)rightDefinition
, rightDefinitionLength
));
1394 return errAuthorizationInternal
;
1396 CFRef
<CFDictionaryRef
> rightDefinition(static_cast<CFDictionaryRef
>(CFPropertyListCreateFromXMLData(NULL
, data
, kCFPropertyListImmutable
, NULL
)));
1398 if (!rightDefinition
|| (CFGetTypeID(rightDefinition
) != CFDictionaryGetTypeID()))
1399 return errAuthorizationInternal
;
1401 *rcode
= connection
.process().session().authorizationdbSet(authorization
, rightname
, rightDefinition
);
1406 kern_return_t
ucsp_server_authorizationdbRemove(UCSP_ARGS
, AuthorizationBlob authorization
, const char *rightname
)
1409 *rcode
= connection
.process().session().authorizationdbRemove(authorization
, rightname
);
1415 // Miscellaneous administrative functions
1417 kern_return_t
ucsp_server_addCodeEquivalence(UCSP_ARGS
, DATA_IN(oldHash
), DATA_IN(newHash
),
1418 const char *name
, boolean_t forSystem
)
1421 Server::codeSignatures().addLink(DATA(oldHash
), DATA(newHash
), name
, forSystem
);
1425 kern_return_t
ucsp_server_removeCodeEquivalence(UCSP_ARGS
, DATA_IN(hash
),
1426 const char *name
, boolean_t forSystem
)
1429 Server::codeSignatures().removeLink(DATA(hash
), name
, forSystem
);
1433 kern_return_t
ucsp_server_setAlternateSystemRoot(UCSP_ARGS
, const char *root
)
1437 if (connection
.process().uid() != 0)
1438 CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED
);
1440 Server::codeSignatures().open((string(root
) + EQUIVALENCEDBPATH
).c_str());
1446 // Child check-in service.
1447 // Note that this isn't using the standard argument pattern.
1449 kern_return_t
ucsp_server_childCheckIn(mach_port_t serverPort
,
1450 mach_port_t servicePort
, mach_port_t taskPort
)
1453 ServerChild::checkIn(servicePort
, TaskPort(taskPort
).pid());
1454 END_IPCS(mach_port_deallocate(mach_task_self(), taskPort
))
1459 // Code Signing Hosting registration.
1460 // Note that the Code Signing Proxy facility (implementing the "cshosting"
1461 // IPC protocol) is elsewhere.
1463 kern_return_t
ucsp_server_registerHosting(UCSP_ARGS
, mach_port_t hostingPort
, uint32 flags
)
1466 connection
.process().registerCodeSigning(hostingPort
, flags
);
1470 kern_return_t
ucsp_server_hostingPort(UCSP_ARGS
, pid_t hostPid
, mach_port_t
*hostingPort
)
1473 if (RefPointer
<Process
> process
= Server::active().findPid(hostPid
))
1474 *hostingPort
= process
->hostingPort();
1476 *hostingPort
= MACH_PORT_NULL
;
1477 secdebug("hosting", "hosting port for for pid=%d is port %d", hostPid
, *hostingPort
);
1482 kern_return_t
ucsp_server_setGuest(UCSP_ARGS
, SecGuestRef guest
, SecCSFlags flags
)
1485 connection
.guestRef(guest
, flags
);
1490 kern_return_t
ucsp_server_createGuest(UCSP_ARGS
, SecGuestRef host
,
1491 uint32_t status
, const char *path
, DATA_IN(attributes
), SecCSFlags flags
, SecGuestRef
*newGuest
)
1494 *newGuest
= connection
.process().createGuest(host
, status
, path
, DATA(attributes
), flags
);
1498 kern_return_t
ucsp_server_setGuestStatus(UCSP_ARGS
, SecGuestRef guest
,
1499 uint32_t status
, DATA_IN(attributes
))
1502 connection
.process().setGuestStatus(guest
, status
, DATA(attributes
));
1506 kern_return_t
ucsp_server_removeGuest(UCSP_ARGS
, SecGuestRef host
, SecGuestRef guest
)
1509 connection
.process().removeGuest(host
, guest
);