2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 // sstransit - SecurityServer client library transition code.
22 // These are the functions that implement CssmClient methods in terms of
23 // MIG IPC client calls, plus their supporting machinery.
25 #include "sstransit.h"
26 #include <Security/cspclient.h>
27 #include <Security/ktracecodes.h>
28 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
32 using MachPlusPlus::check
;
33 using MachPlusPlus::VMGuard
;
38 // This happens "at the end" of a glue method, via the DataOutput destructor.
40 DataOutput::~DataOutput()
42 VMGuard
_(mData
, mLength
);
43 if (mData
) { // was assigned to; IPC returned OK
44 if (argument
) { // buffer was provided
45 if (argument
.length() < mLength
)
46 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR
);
47 argument
.length(mLength
);
48 } else { // allocate buffer
49 argument
= CssmData(allocator
.malloc(mLength
), mLength
);
51 memcpy(argument
.data(), mData
, mLength
);
56 CssmList
chunkCopy(CssmList
&list
, CssmAllocator
&alloc
)
59 ChunkCopyWalker
w(alloc
);
66 // Create a packaged-up Context for IPC transmission.
67 // In addition to collecting the context into a contiguous blob for transmission,
68 // we also evaluate CssmCryptoData callbacks at this time.
70 SendContext::SendContext(const Security::Context
&ctx
) : context(ctx
)
72 CssmCryptoData cryptoDataValue
; // holding area for CssmCryptoData element
73 IFDEBUG(uint32 cryptoDataUsed
= 0);
74 Context::Builder
builder(CssmAllocator::standard());
75 for (unsigned n
= 0; n
< ctx
.attributesInUse(); n
++) {
76 switch (ctx
[n
].baseType()) {
77 case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA
: {
78 CssmCryptoData
&data
= ctx
[n
]; // extract CssmCryptoData value
79 cryptoDataValue
= data(); // evaluate callback (if any)
80 builder
.setup(&cryptoDataValue
); // use evaluted value
81 IFDEBUG(cryptoDataUsed
++);
85 builder
.setup(ctx
[n
]);
89 attributeSize
= builder
.make();
90 for (unsigned n
= 0; n
< ctx
.attributesInUse(); n
++) {
91 const Context::Attr
&attr
= ctx
[n
];
92 switch (attr
.baseType()) {
93 case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA
:
94 builder
.put(attr
.type(), &cryptoDataValue
);
101 uint32 count
; // not needed
102 builder
.done(attributes
, count
);
103 assert(cryptoDataUsed
<= 1); // no more than one slot converted
108 // Copy an AccessCredentials for shipment.
109 // In addition, scan the samples for "special" database locking samples
110 // and translate certain items for safe shipment. Note that this overwrites
111 // part of the CssmList value (CSPHandle -> SS/KeyHandle), but we do it on
112 // the COPY, so that's okay.
114 DatabaseAccessCredentials::DatabaseAccessCredentials(const AccessCredentials
*creds
, CssmAllocator
&alloc
)
115 : Copier
<AccessCredentials
>(creds
, alloc
)
118 for (uint32 n
= 0; n
< value()->samples().length(); n
++) {
119 TypedList sample
= value()->samples()[n
];
120 sample
.checkProper();
121 switch (sample
.type()) {
122 case CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK
:
123 case CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK
:
124 sample
.snip(); // skip sample type
125 sample
.checkProper();
126 if (sample
.type() == CSSM_WORDID_SYMMETRIC_KEY
) {
127 secdebug("SSclient", "key sample encountered");
128 // proper form is sample[1] = DATA:CSPHandle, sample[2] = DATA:CSSM_KEY
129 if (sample
.length() != 3
130 || sample
[1].type() != CSSM_LIST_ELEMENT_DATUM
131 || sample
[2].type() != CSSM_LIST_ELEMENT_DATUM
)
132 CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE
);
134 *sample
[1].data().interpretedAs
<CSSM_CSP_HANDLE
>(CSSM_ERRCODE_INVALID_SAMPLE_VALUE
),
135 *sample
[2].data().interpretedAs
<CssmKey
>(CSSM_ERRCODE_INVALID_SAMPLE_VALUE
));
145 void DatabaseAccessCredentials::mapKeySample(CSSM_CSP_HANDLE
&cspHandle
, CssmKey
&key
)
147 // if the key belongs to the AppleCSPDL, look it up and write the SS KeyHandle
148 // into the CSPHandle element for transmission
149 if (key
.header().cspGuid() == gGuidAppleCSPDL
) {
150 // @@@ can't use CssmClient (it makes its own attachments)
152 if (CSSM_RETURN err
= CSSM_CSP_CreatePassThroughContext(cspHandle
, &key
, &ctx
))
153 CssmError::throwMe(err
);
155 CSSM_RETURN passthroughError
=
156 CSSM_CSP_PassThrough(ctx
, CSSM_APPLESCPDL_CSP_GET_KEYHANDLE
, NULL
, (void **)&ssKey
);
157 CSSM_DeleteContext(ctx
); // ignore error
158 if (passthroughError
)
159 CssmError::throwMe(passthroughError
);
160 // we happen to know that they're both uint32 values
161 assert(sizeof(CSSM_CSP_HANDLE
) >= sizeof(KeyHandle
));
163 secdebug("SSclient", "key sample mapped to key 0x%lx", ssKey
);
168 namespace SecurityServer
174 DbHandle
ClientSession::createDb(const DLDbIdentifier
&dbId
,
175 const AccessCredentials
*cred
, const AclEntryInput
*owner
,
176 const DBParameters
¶ms
)
178 DatabaseAccessCredentials
creds(cred
, internalAllocator
);
179 Copier
<AclEntryPrototype
> proto(&owner
->proto(), internalAllocator
);
180 DataWalkers::DLDbFlatIdentifier
ident(dbId
);
181 Copier
<DataWalkers::DLDbFlatIdentifier
> id(&ident
, internalAllocator
);
183 IPC(ucsp_client_createDb(UCSP_ARGS
, &db
, COPY(id
), COPY(creds
), COPY(proto
), params
));
187 DbHandle
ClientSession::decodeDb(const DLDbIdentifier
&dbId
,
188 const AccessCredentials
*cred
, const CssmData
&blob
)
190 DatabaseAccessCredentials
creds(cred
, internalAllocator
);
191 DataWalkers::DLDbFlatIdentifier
ident(dbId
);
192 Copier
<DataWalkers::DLDbFlatIdentifier
> id(&ident
, internalAllocator
);
194 IPC(ucsp_client_decodeDb(UCSP_ARGS
, &db
, COPY(id
), COPY(creds
), DATA(blob
)));
198 void ClientSession::encodeDb(DbHandle db
, CssmData
&blob
, CssmAllocator
&alloc
)
200 DataOutput
outBlob(blob
, alloc
);
201 IPC(ucsp_client_encodeDb(UCSP_ARGS
, db
, DATA(outBlob
)));
204 void ClientSession::releaseDb(DbHandle db
)
206 IPC(ucsp_client_releaseDb(UCSP_ARGS
, db
));
209 void ClientSession::getDbSuggestedIndex(DbHandle db
, CssmData
&index
, CssmAllocator
&alloc
)
211 DataOutput
outBlob(index
, alloc
);
212 IPC(ucsp_client_getDbIndex(UCSP_ARGS
, db
, DATA(outBlob
)));
215 void ClientSession::authenticateDb(DbHandle db
, DBAccessType type
,
216 const AccessCredentials
*cred
)
218 DatabaseAccessCredentials
creds(cred
, internalAllocator
);
219 IPC(ucsp_client_authenticateDb(UCSP_ARGS
, db
, COPY(creds
)));
222 void ClientSession::setDbParameters(DbHandle db
, const DBParameters
¶ms
)
224 IPC(ucsp_client_setDbParameters(UCSP_ARGS
, db
, params
));
227 void ClientSession::getDbParameters(DbHandle db
, DBParameters
¶ms
)
229 IPC(ucsp_client_getDbParameters(UCSP_ARGS
, db
, ¶ms
));
232 void ClientSession::changePassphrase(DbHandle db
, const AccessCredentials
*cred
)
234 Copier
<AccessCredentials
> creds(cred
, internalAllocator
);
235 IPC(ucsp_client_changePassphrase(UCSP_ARGS
, db
, COPY(creds
)));
239 void ClientSession::lock(DbHandle db
)
241 IPC(ucsp_client_lockDb(UCSP_ARGS
, db
));
244 void ClientSession::lockAll (bool forSleep
)
246 IPC(ucsp_client_lockAll (UCSP_ARGS
, forSleep
));
249 void ClientSession::unlock(DbHandle db
)
251 IPC(ucsp_client_unlockDb(UCSP_ARGS
, db
));
254 void ClientSession::unlock(DbHandle db
, const CssmData
&passphrase
)
256 IPC(ucsp_client_unlockDbWithPassphrase(UCSP_ARGS
, db
, DATA(passphrase
)));
259 bool ClientSession::isLocked(DbHandle db
)
262 IPC(ucsp_client_isLocked(UCSP_ARGS
, db
, &locked
));
270 void ClientSession::encodeKey(KeyHandle key
, CssmData
&blob
,
271 KeyUID
*uid
, CssmAllocator
&alloc
)
273 DataOutput
oBlob(blob
, alloc
);
275 mach_msg_type_number_t uidLength
;
276 IPC(ucsp_client_encodeKey(UCSP_ARGS
, key
, oBlob
.data(), oBlob
.length(),
277 (uid
!= NULL
), &uidp
, &uidLength
));
278 // return key uid if requested
280 assert(uidLength
== sizeof(KeyUID
));
281 memcpy(uid
, uidp
, sizeof(KeyUID
));
286 KeyHandle
ClientSession::decodeKey(DbHandle db
, const CssmData
&blob
, CssmKey::Header
&header
)
289 IPC(ucsp_client_decodeKey(UCSP_ARGS
, &key
, &header
, db
, blob
.data(), blob
.length()));
293 void ClientSession::releaseKey(KeyHandle key
)
295 IPC(ucsp_client_releaseKey(UCSP_ARGS
, key
));
299 CssmKeySize
ClientSession::queryKeySizeInBits(KeyHandle key
)
302 IPC(ucsp_client_queryKeySizeInBits(UCSP_ARGS
, key
, &length
));
307 uint32
ClientSession::getOutputSize(const Context
&context
, KeyHandle key
,
308 uint32 inputSize
, bool encrypt
)
310 SendContext
ctx(context
);
312 IPC(ucsp_client_getOutputSize(UCSP_ARGS
, CONTEXT(ctx
), key
, inputSize
, encrypt
, &outputSize
));
318 // Random number generation.
319 // This interfaces to the secure RNG inside the SecurityServer; it does not access
320 // a PRNG in its CSP. If you need a reproducible PRNG, attach a local CSP and use it.
321 // Note that this function does not allocate a buffer; it always fills the buffer provided.
323 void ClientSession::generateRandom(CssmData
&data
)
326 mach_msg_type_number_t resultLength
;
327 IPC(ucsp_client_generateRandom(UCSP_ARGS
, data
.length(), &result
, &resultLength
));
328 assert(resultLength
== data
.length());
329 memcpy(data
.data(), result
, data
.length());
334 // Signatures and MACs
336 void ClientSession::generateSignature(const Context
&context
, KeyHandle key
,
337 const CssmData
&data
, CssmData
&signature
, CssmAllocator
&alloc
, CSSM_ALGORITHMS signOnlyAlgorithm
)
339 SendContext
ctx(context
);
340 DataOutput
sig(signature
, alloc
);
341 IPCKEY(ucsp_client_generateSignature(UCSP_ARGS
, CONTEXT(ctx
), key
, signOnlyAlgorithm
,
342 DATA(data
), DATA(sig
)),
343 key
, CSSM_ACL_AUTHORIZATION_SIGN
);
346 void ClientSession::verifySignature(const Context
&context
, KeyHandle key
,
347 const CssmData
&data
, const CssmData
&signature
, CSSM_ALGORITHMS verifyOnlyAlgorithm
)
349 SendContext
ctx(context
);
350 IPC(ucsp_client_verifySignature(UCSP_ARGS
, CONTEXT(ctx
), key
, verifyOnlyAlgorithm
,
351 DATA(data
), DATA(signature
)));
355 void ClientSession::generateMac(const Context
&context
, KeyHandle key
,
356 const CssmData
&data
, CssmData
&signature
, CssmAllocator
&alloc
)
358 SendContext
ctx(context
);
359 DataOutput
sig(signature
, alloc
);
360 IPCKEY(ucsp_client_generateMac(UCSP_ARGS
, CONTEXT(ctx
), key
,
361 DATA(data
), DATA(sig
)),
362 key
, CSSM_ACL_AUTHORIZATION_MAC
);
365 void ClientSession::verifyMac(const Context
&context
, KeyHandle key
,
366 const CssmData
&data
, const CssmData
&signature
)
368 SendContext
ctx(context
);
369 IPCKEY(ucsp_client_verifyMac(UCSP_ARGS
, CONTEXT(ctx
), key
,
370 DATA(data
), DATA(signature
)),
371 key
, CSSM_ACL_AUTHORIZATION_MAC
);
376 // Encryption/Decryption
379 void ClientSession::encrypt(const Context
&context
, KeyHandle key
,
380 const CssmData
&clear
, CssmData
&cipher
, CssmAllocator
&alloc
)
382 SendContext
ctx(context
);
383 DataOutput
cipherOut(cipher
, alloc
);
384 IPCKEY(ucsp_client_encrypt(UCSP_ARGS
, CONTEXT(ctx
), key
, DATA(clear
), DATA(cipherOut
)),
385 key
, CSSM_ACL_AUTHORIZATION_ENCRYPT
);
388 void ClientSession::decrypt(const Context
&context
, KeyHandle key
,
389 const CssmData
&cipher
, CssmData
&clear
, CssmAllocator
&alloc
)
391 Debug::trace (kSecTraceUCSPServerDecryptBegin
);
393 SendContext
ctx(context
);
394 DataOutput
clearOut(clear
, alloc
);
395 IPCKEY(ucsp_client_decrypt(UCSP_ARGS
, CONTEXT(ctx
), key
, DATA(cipher
), DATA(clearOut
)),
396 key
, CSSM_ACL_AUTHORIZATION_DECRYPT
);
403 void ClientSession::generateKey(DbHandle db
, const Context
&context
, uint32 keyUsage
, uint32 keyAttr
,
404 const AccessCredentials
*cred
, const AclEntryInput
*owner
,
405 KeyHandle
&newKey
, CssmKey::Header
&newHeader
)
407 SendContext
ctx(context
);
408 Copier
<AccessCredentials
> creds(cred
, internalAllocator
);
409 Copier
<AclEntryPrototype
> proto(&owner
->proto(), internalAllocator
);
410 IPC(ucsp_client_generateKey(UCSP_ARGS
, db
, CONTEXT(ctx
),
411 COPY(creds
), COPY(proto
), keyUsage
, keyAttr
, &newKey
, &newHeader
));
414 void ClientSession::generateKey(DbHandle db
, const Context
&context
,
415 uint32 pubKeyUsage
, uint32 pubKeyAttr
,
416 uint32 privKeyUsage
, uint32 privKeyAttr
,
417 const AccessCredentials
*cred
, const AclEntryInput
*owner
,
418 KeyHandle
&pubKey
, CssmKey::Header
&pubHeader
,
419 KeyHandle
&privKey
, CssmKey::Header
&privHeader
)
421 SendContext
ctx(context
);
422 Copier
<AccessCredentials
> creds(cred
, internalAllocator
);
423 Copier
<AclEntryPrototype
> proto(&owner
->proto(), internalAllocator
);
424 IPC(ucsp_client_generateKeyPair(UCSP_ARGS
, db
, CONTEXT(ctx
),
425 COPY(creds
), COPY(proto
),
426 pubKeyUsage
, pubKeyAttr
, privKeyUsage
, privKeyAttr
,
427 &pubKey
, &pubHeader
, &privKey
, &privHeader
));
433 // This is a bit strained; the incoming 'param' value may have structure
434 // and needs to be handled on a per-algorithm basis, which means we have to
435 // know which key derivation algorithms we support for passing to our CSP(s).
436 // The default behavior is to handle "flat" data blobs, which is as good
437 // a default as we can manage.
438 // NOTE: The param-specific handling must be synchronized with the server
439 // transition layer code (in transition.cpp).
441 void ClientSession::deriveKey(DbHandle db
, const Context
&context
, KeyHandle baseKey
,
442 uint32 keyUsage
, uint32 keyAttr
, CssmData
¶m
,
443 const AccessCredentials
*cred
, const AclEntryInput
*owner
,
444 KeyHandle
&newKey
, CssmKey::Header
&newHeader
, CssmAllocator
&allocator
)
446 SendContext
ctx(context
);
447 Copier
<AccessCredentials
> creds(cred
, internalAllocator
);
448 Copier
<AclEntryPrototype
> proto(&owner
->proto(), internalAllocator
);
449 DataOutput
paramOutput(param
, allocator
);
450 switch (context
.algorithm()) {
451 case CSSM_ALGID_PKCS5_PBKDF2
: {
452 typedef CSSM_PKCS5_PBKDF2_PARAMS Params
;
453 Copier
<Params
> params(param
.interpretedAs
<Params
>(CSSM_ERRCODE_INVALID_INPUT_POINTER
),
455 IPCKEY(ucsp_client_deriveKey(UCSP_ARGS
, db
, CONTEXT(ctx
), baseKey
,
456 COPY(creds
), COPY(proto
), COPY(params
), DATA(paramOutput
),
457 keyUsage
, keyAttr
, &newKey
, &newHeader
),
458 baseKey
, CSSM_ACL_AUTHORIZATION_DERIVE
);
461 IPCKEY(ucsp_client_deriveKey(UCSP_ARGS
, db
, CONTEXT(ctx
), baseKey
,
462 COPY(creds
), COPY(proto
),
463 param
.data(), param
.length(), param
.data(),
465 keyUsage
, keyAttr
, &newKey
, &newHeader
),
466 baseKey
, CSSM_ACL_AUTHORIZATION_DERIVE
);
475 void ClientSession::getKeyDigest(KeyHandle key
, CssmData
&digest
, CssmAllocator
&allocator
)
477 DataOutput
dig(digest
, allocator
);
478 IPC(ucsp_client_getKeyDigest(UCSP_ARGS
, key
, DATA(dig
)));
483 // Key wrapping and unwrapping
485 void ClientSession::wrapKey(const Context
&context
, KeyHandle wrappingKey
,
486 KeyHandle keyToBeWrapped
, const AccessCredentials
*cred
,
487 const CssmData
*descriptiveData
, CssmWrappedKey
&wrappedKey
, CssmAllocator
&alloc
)
489 SendContext
ctx(context
);
490 Copier
<AccessCredentials
> creds(cred
, internalAllocator
);
491 DataOutput
keyData(wrappedKey
, alloc
);
492 /* @@@ When <rdar://problem/3525664>: CSSM_WrapKey doesn't check the acl of the key doing the wrapping. is fixed, we need to potentially edit the CSSM_ACL_AUTHORIZATION_ENCRYPT acl of the wrapping key as opposed to the key being wrapped. We need to know which of the 2 keys to edit though somehow. */
493 IPCKEY(ucsp_client_wrapKey(UCSP_ARGS
, CONTEXT(ctx
), wrappingKey
, COPY(creds
),
494 keyToBeWrapped
, OPTIONALDATA(descriptiveData
),
495 &wrappedKey
, DATA(keyData
)),
497 context
.algorithm() == CSSM_ALGID_NONE
498 ? CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR
: CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED
);
499 wrappedKey
= CssmData(); // null out data section (force allocation for key data)
502 void ClientSession::unwrapKey(DbHandle db
, const Context
&context
, KeyHandle key
,
503 KeyHandle publicKey
, const CssmWrappedKey
&wrappedKey
,
504 uint32 usage
, uint32 attr
,
505 const AccessCredentials
*cred
, const AclEntryInput
*acl
,
506 CssmData
&descriptiveData
,
507 KeyHandle
&newKey
, CssmKey::Header
&newHeader
, CssmAllocator
&alloc
)
509 SendContext
ctx(context
);
510 DataOutput
descriptor(descriptiveData
, alloc
);
511 Copier
<AccessCredentials
> creds(cred
, internalAllocator
);
512 Copier
<AclEntryPrototype
> proto(&acl
->proto(), internalAllocator
);
513 IPCKEY(ucsp_client_unwrapKey(UCSP_ARGS
, db
, CONTEXT(ctx
), key
,
514 COPY(creds
), COPY(proto
),
515 publicKey
, wrappedKey
, DATA(wrappedKey
), usage
, attr
, DATA(descriptor
),
516 &newKey
, &newHeader
),
517 key
, CSSM_ACL_AUTHORIZATION_DECRYPT
);
524 void ClientSession::getAcl(AclKind kind
, KeyHandle key
, const char *tag
,
525 uint32
&infoCount
, AclEntryInfo
* &infoArray
, CssmAllocator
&alloc
)
528 AclEntryInfo
*info
, *infoBase
;
529 mach_msg_type_number_t infoLength
;
530 IPC(ucsp_client_getAcl(UCSP_ARGS
, kind
, key
,
531 (tag
!= NULL
), tag
? tag
: "",
532 &count
, COPY_OUT(info
)));
533 VMGuard
_(info
, infoLength
);
536 // relocate incoming AclEntryInfo array
537 ReconstituteWalker
relocator(info
, infoBase
);
538 for (uint32 n
= 0; n
< count
; n
++)
539 walk(relocator
, info
[n
]);
541 // copy AclEntryInfo array into discrete memory nodes
542 infoArray
= alloc
.alloc
<AclEntryInfo
>(count
);
543 ChunkCopyWalker
chunker(alloc
);
544 for (uint32 n
= 0; n
< count
; n
++) {
545 infoArray
[n
] = info
[n
];
546 walk(chunker
, infoArray
[n
]);
550 void ClientSession::changeAcl(AclKind kind
, KeyHandle key
, const AccessCredentials
&cred
,
553 Copier
<AccessCredentials
> creds(&cred
, internalAllocator
);
554 //@@@ ignoring callback
555 Copier
<AclEntryInput
> newEntry(edit
.newEntry(), internalAllocator
);
556 IPCKEY(ucsp_client_changeAcl(UCSP_ARGS
, kind
, key
, COPY(creds
),
557 edit
.mode(), edit
.handle(), COPY(newEntry
)),
558 key
, CSSM_ACL_AUTHORIZATION_CHANGE_ACL
);
561 void ClientSession::getOwner(AclKind kind
, KeyHandle key
, AclOwnerPrototype
&owner
,
562 CssmAllocator
&alloc
)
564 AclOwnerPrototype
*proto
, *protoBase
;
565 mach_msg_type_number_t protoLength
;
566 IPC(ucsp_client_getOwner(UCSP_ARGS
, kind
, key
, COPY_OUT(proto
)));
567 // turn the returned AclOwnerPrototype into its proper output form
568 relocate(proto
, protoBase
);
569 owner
.TypedSubject
= chunkCopy(proto
->subject(), alloc
);
570 owner
.Delegate
= proto
->delegate();
573 void ClientSession::changeOwner(AclKind kind
, KeyHandle key
,
574 const AccessCredentials
&cred
, const AclOwnerPrototype
&proto
)
576 Copier
<AccessCredentials
> creds(&cred
, internalAllocator
);
577 Copier
<AclOwnerPrototype
> protos(&proto
, internalAllocator
);
578 IPCKEY(ucsp_client_setOwner(UCSP_ARGS
, kind
, key
, COPY(creds
), COPY(protos
)),
579 key
, CSSM_ACL_AUTHORIZATION_CHANGE_OWNER
);
583 void ClientSession::getKeyAcl(DbHandle db
, const char *tag
,
584 uint32
&count
, AclEntryInfo
* &info
, CssmAllocator
&alloc
)
585 { getAcl(keyAcl
, db
, tag
, count
, info
, alloc
); }
587 void ClientSession::changeKeyAcl(DbHandle db
, const AccessCredentials
&cred
,
589 { changeAcl(keyAcl
, db
, cred
, edit
); }
591 void ClientSession::getKeyOwner(DbHandle db
, AclOwnerPrototype
&owner
, CssmAllocator
&alloc
)
592 { getOwner(keyAcl
, db
, owner
, alloc
); }
594 void ClientSession::changeKeyOwner(DbHandle db
, const AccessCredentials
&cred
,
595 const AclOwnerPrototype
&edit
)
596 { changeOwner(keyAcl
, db
, cred
, edit
); }
598 void ClientSession::getDbAcl(DbHandle db
, const char *tag
,
599 uint32
&count
, AclEntryInfo
* &info
, CssmAllocator
&alloc
)
600 { getAcl(dbAcl
, db
, tag
, count
, info
, alloc
); }
602 void ClientSession::changeDbAcl(DbHandle db
, const AccessCredentials
&cred
,
604 { changeAcl(dbAcl
, db
, cred
, edit
); }
606 void ClientSession::getDbOwner(DbHandle db
, AclOwnerPrototype
&owner
, CssmAllocator
&alloc
)
607 { getOwner(dbAcl
, db
, owner
, alloc
); }
609 void ClientSession::changeDbOwner(DbHandle db
, const AccessCredentials
&cred
,
610 const AclOwnerPrototype
&edit
)
611 { changeOwner(dbAcl
, db
, cred
, edit
); }
615 // Database key management
617 void ClientSession::extractMasterKey(DbHandle db
, const Context
&context
, DbHandle sourceDb
,
618 uint32 keyUsage
, uint32 keyAttr
,
619 const AccessCredentials
*cred
, const AclEntryInput
*owner
,
620 KeyHandle
&newKey
, CssmKey::Header
&newHeader
, CssmAllocator
&alloc
)
622 SendContext
ctx(context
);
623 Copier
<AccessCredentials
> creds(cred
, internalAllocator
);
624 Copier
<AclEntryPrototype
> proto(&owner
->proto(), internalAllocator
);
625 IPC(ucsp_client_extractMasterKey(UCSP_ARGS
, db
, CONTEXT(ctx
), sourceDb
,
626 COPY(creds
), COPY(proto
),
627 keyUsage
, keyAttr
, &newKey
, &newHeader
));
632 // Authorization subsystem entry
634 void ClientSession::authCreate(const AuthorizationItemSet
*rights
,
635 const AuthorizationItemSet
*environment
, AuthorizationFlags flags
,
636 AuthorizationBlob
&result
)
638 Copier
<AuthorizationItemSet
> rightSet(rights
, internalAllocator
);
639 Copier
<AuthorizationItemSet
> environ(environment
, internalAllocator
);
640 IPC(ucsp_client_authorizationCreate(UCSP_ARGS
,
641 COPY(rightSet
), flags
, COPY(environ
), &result
));
644 void ClientSession::authRelease(const AuthorizationBlob
&auth
,
645 AuthorizationFlags flags
)
647 IPC(ucsp_client_authorizationRelease(UCSP_ARGS
, auth
, flags
));
650 void ClientSession::authCopyRights(const AuthorizationBlob
&auth
,
651 const AuthorizationItemSet
*rights
, const AuthorizationItemSet
*environment
,
652 AuthorizationFlags flags
,
653 AuthorizationItemSet
**grantedRights
)
655 Copier
<AuthorizationItemSet
> rightSet(rights
, internalAllocator
);
656 Copier
<AuthorizationItemSet
> environ(environment
, internalAllocator
);
657 COPY_OUT_DECL(AuthorizationItemSet
, result
);
658 IPC(ucsp_client_authorizationCopyRights(UCSP_ARGS
, auth
, COPY(rightSet
),
659 flags
| (grantedRights
? 0 : kAuthorizationFlagNoData
),
660 COPY(environ
), COPY_OUT(result
)));
661 VMGuard
_(result
, resultLength
);
662 // return rights vector (only) if requested
664 relocate(result
, resultBase
);
665 *grantedRights
= copy(result
, returnAllocator
);
669 void ClientSession::authCopyInfo(const AuthorizationBlob
&auth
,
671 AuthorizationItemSet
* &info
)
673 COPY_OUT_DECL(AuthorizationItemSet
, result
);
676 else if (tag
[0] == '\0')
677 MacOSError::throwMe(errAuthorizationInvalidTag
);
678 IPC(ucsp_client_authorizationCopyInfo(UCSP_ARGS
, auth
, tag
, COPY_OUT(result
)));
679 VMGuard
_(result
, resultLength
);
680 relocate(result
, resultBase
);
681 info
= copy(result
, returnAllocator
);
684 void ClientSession::authExternalize(const AuthorizationBlob
&auth
,
685 AuthorizationExternalForm
&extForm
)
687 IPC(ucsp_client_authorizationExternalize(UCSP_ARGS
, auth
, &extForm
));
690 void ClientSession::authInternalize(const AuthorizationExternalForm
&extForm
,
691 AuthorizationBlob
&auth
)
693 IPC(ucsp_client_authorizationInternalize(UCSP_ARGS
, extForm
, &auth
));
698 // Get session information (security session status)
700 void ClientSession::getSessionInfo(SecuritySessionId
&sessionId
, SessionAttributeBits
&attrs
)
702 IPC(ucsp_client_getSessionInfo(UCSP_ARGS
, &sessionId
, &attrs
));
707 // Create a new session.
709 // Caveat: This discards all SecurityServer held state for this process, including
710 // authorizations, database handles, etc. If you are multi-threaded at this point,
711 // and other threads have talked to SecurityServer, they will leak a few resources
712 // (mach ports and the like). Nothing horrendous, unless you create masses of sessions
713 // that way (which we wouldn't exactly recommend for other reasons).
715 // Hacker's note: This engages in an interesting dance with SecurityServer's state tracking.
716 // If you don't know the choreography, don't change things here until talking to an expert.
718 // Yes, if the client had multiple threads each of which has talked to SecurityServer,
719 // the reply ports for all but the calling thread will leak. If that ever turns out to
720 // be a real problem, we can fix it by keeping a (locked) set of client replyPorts to ditch.
721 // Hardly worth it, though. This is a rare call.
723 void ClientSession::setupSession(SessionCreationFlags flags
, SessionAttributeBits attrs
)
725 mGlobal().thread().replyPort
.destroy(); // kill this thread's reply port
726 mGlobal
.reset(); // kill existing cache (leak all other threads)
727 mSetupSession
= true; // global flag to Global constructor
728 IPC(ucsp_client_setupSession(UCSP_ARGS
, flags
, attrs
)); // reinitialize and call
733 // Notification subsystem
735 void ClientSession::requestNotification(Port receiver
, Listener::Domain domain
, Listener::EventMask events
)
737 IPC(ucsp_client_requestNotification(UCSP_ARGS
, receiver
, domain
, events
));
740 void ClientSession::stopNotification(Port port
)
742 IPC(ucsp_client_stopNotification(UCSP_ARGS
, port
.port()));
745 void ClientSession::postNotification(Listener::Domain domain
, Listener::Event event
, const CssmData
&data
)
747 IPC(ucsp_client_postNotification(UCSP_ARGS
, domain
, event
, DATA(data
)));
750 OSStatus
ClientSession::dispatchNotification(const mach_msg_header_t
*message
,
751 ConsumeNotification
*consumer
, void *context
) throw()
754 mach_msg_header_t Head
;
755 /* start of the kernel processed data */
756 mach_msg_body_t msgh_body
;
757 mach_msg_ool_descriptor_t data
;
758 /* end of the kernel processed data */
762 mach_msg_type_number_t dataCnt
;
764 } *msg
= (Message
*)message
;
769 status
= consumer(msg
->domain
, msg
->event
, msg
->data
.address
, msg
->dataCnt
, context
);
771 catch (const CssmCommonError
&err
) { status
= err
.osStatus(); }
772 catch (const std::bad_alloc
&) { status
= memFullErr
; }
773 catch (...) { status
= internalComponentErr
; }
775 mig_deallocate((vm_offset_t
) msg
->data
.address
, msg
->dataCnt
);
776 msg
->data
.address
= (vm_offset_t
) 0;
777 msg
->data
.size
= (mach_msg_size_t
) 0;
784 // authorizationdbGet/Set/Remove
786 void ClientSession::authorizationdbGet(const AuthorizationString rightname
, CssmData
&rightDefinition
, CssmAllocator
&alloc
)
788 DataOutput
definition(rightDefinition
, alloc
);
789 IPC(ucsp_client_authorizationdbGet(UCSP_ARGS
, rightname
, DATA(definition
)));
792 void ClientSession::authorizationdbSet(const AuthorizationBlob
&auth
, const AuthorizationString rightname
, uint32_t rightDefinitionLength
, const void *rightDefinition
)
794 // @@@ DATA_IN in transition.cpp is not const void *
795 IPC(ucsp_client_authorizationdbSet(UCSP_ARGS
, auth
, rightname
, const_cast<void *>(rightDefinition
), rightDefinitionLength
));
798 void ClientSession::authorizationdbRemove(const AuthorizationBlob
&auth
, const AuthorizationString rightname
)
800 IPC(ucsp_client_authorizationdbRemove(UCSP_ARGS
, auth
, rightname
));
805 // Miscellaneous administrative calls
807 void ClientSession::addCodeEquivalence(const CssmData
&oldHash
, const CssmData
&newHash
,
808 const char *name
, bool forSystem
/* = false */)
810 IPC(ucsp_client_addCodeEquivalence(UCSP_ARGS
, DATA(oldHash
), DATA(newHash
),
814 void ClientSession::removeCodeEquivalence(const CssmData
&hash
, const char *name
, bool forSystem
/* = false */)
816 IPC(ucsp_client_removeCodeEquivalence(UCSP_ARGS
, DATA(hash
), name
, forSystem
));
819 void ClientSession::setAlternateSystemRoot(const char *path
)
821 IPC(ucsp_client_setAlternateSystemRoot(UCSP_ARGS
, path
));
825 } // end namespace SecurityServer
826 } // end namespace Security