]> git.saurik.com Git - apple/security.git/blob - SecurityServer/transition.cpp
Security-54.tar.gz
[apple/security.git] / SecurityServer / transition.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 //
20 // transition - SecurityServer IPC-to-class-methods transition layer
21 //
22 #include <Security/AuthorizationWalkers.h>
23 #include "server.h"
24 #include "ucsp.h"
25 #include "session.h"
26 #include "xdatabase.h"
27 #include <mach/mach_error.h>
28
29
30 //
31 // Bracket Macros
32 //
33 #define UCSP_ARGS mach_port_t servicePort, mach_port_t replyPort, security_token_t securityToken, \
34 CSSM_RETURN *rcode
35 #define CONTEXT_ARGS Context context, Pointer contextBase, Context::Attr *attributes, mach_msg_type_number_t attrCount
36
37 #define BEGIN_IPCN *rcode = CSSM_OK; try {
38 #define BEGIN_IPC BEGIN_IPCN Connection &connection = Server::connection(replyPort);
39 #define END_IPC(base) END_IPCN(base) Server::requestComplete(); return KERN_SUCCESS;
40 #define END_IPCN(base) } \
41 catch (const CssmCommonError &err) { *rcode = err.cssmError(CSSM_ ## base ## _BASE_ERROR); } \
42 catch (const std::bad_alloc &) { *rcode = CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \
43 catch (Connection *conn) { *rcode = 0; } \
44 catch (...) { *rcode = CssmError::merge(CSSM_ERRCODE_INTERNAL_ERROR, CSSM_ ## base ## _BASE_ERROR); }
45
46 #define DATA_IN(base) void *base, mach_msg_type_number_t base##Length
47 #define DATA_OUT(base) void **base, mach_msg_type_number_t *base##Length
48 #define DATA(base) CssmData(base, base##Length)
49
50 #define COPY_IN(type,name) type *name, mach_msg_type_number_t name##Length, type *name##Base
51 #define COPY_OUT(type,name) \
52 type **name, mach_msg_type_number_t *name##Length, type **name##Base
53
54
55 using LowLevelMemoryUtilities::increment;
56 using LowLevelMemoryUtilities::difference;
57
58
59 //
60 // An OutputData object will take memory allocated within the SecurityServer,
61 // hand it to the MIG return-output parameters, and schedule it to be released
62 // after the MIG reply has been sent. It will also get rid of it in case of
63 // error.
64 //
65 class OutputData : public CssmData {
66 public:
67 OutputData(void **outP, mach_msg_type_number_t *outLength)
68 : mData(*outP), mLength(*outLength) { }
69 ~OutputData()
70 { mData = data(); mLength = length(); Server::releaseWhenDone(mData); }
71
72 void operator = (const CssmData &source)
73 { CssmData::operator = (source); }
74
75 private:
76 void * &mData;
77 mach_msg_type_number_t &mLength;
78 };
79
80
81 //
82 // A CheckingReconstituteWalker is a variant of an ordinary ReconstituteWalker
83 // that checks object pointers and sizes against the incoming block limits.
84 // It throws an exception if incoming data has pointers outside the incoming block.
85 // This avoids trouble inside of the SecurityServer caused (by bug or malice)
86 // from someone spoofing the client access side.
87 //
88 class CheckingReconstituteWalker {
89 public:
90 CheckingReconstituteWalker(void *ptr, void *base, size_t size)
91 : mBase(base), mLimit(increment(base, size)), mOffset(difference(ptr, base)) { }
92
93 template <class T>
94 void operator () (T * &addr, size_t size = sizeof(T))
95 {
96 if (addr) {
97 if (addr < mBase || increment(addr, size) > mLimit)
98 CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER);
99 addr = increment<T>(addr, mOffset);
100 }
101 }
102
103 static const bool needsRelinking = true;
104 static const bool needsSize = false;
105
106 private:
107 void *mBase; // old base address
108 void *mLimit; // old last byte address + 1
109 off_t mOffset; // relocation offset
110 };
111
112 template <class T>
113 void relocate(T *obj, T *base, size_t size)
114 {
115 if (obj) {
116 if (base == NULL) // invalid, could confuse walkers
117 CssmError::throwMe(CSSM_ERRCODE_INVALID_POINTER);
118 CheckingReconstituteWalker w(obj, base, size);
119 walk(w, base);
120 }
121 }
122
123
124 //
125 // Setup/Teardown functions.
126 //
127 kern_return_t ucsp_server_setup(UCSP_ARGS, mach_port_t taskPort, const char *identity)
128 {
129 BEGIN_IPCN
130 Server::active().setupConnection(servicePort, replyPort, taskPort, securityToken, identity);
131 END_IPCN(CSSM)
132 return KERN_SUCCESS;
133 }
134
135 kern_return_t ucsp_server_setupNew(UCSP_ARGS, mach_port_t taskPort, const char *identity,
136 mach_port_t *newServicePort)
137 {
138 BEGIN_IPCN
139 Session *session = new DynamicSession(TaskPort(taskPort).bootstrap());
140 Server::active().setupConnection(session->servicePort(), replyPort,
141 taskPort, securityToken, identity);
142 *newServicePort = session->servicePort();
143 END_IPCN(CSSM)
144 return KERN_SUCCESS;
145 }
146
147 kern_return_t ucsp_server_teardown(UCSP_ARGS)
148 {
149 BEGIN_IPCN
150 Server::active().endConnection(replyPort);
151 END_IPCN(CSSM)
152 return KERN_SUCCESS;
153 }
154
155
156 //
157 // Database management
158 //
159 kern_return_t ucsp_server_createDb(UCSP_ARGS, DbHandle *db,
160 COPY_IN(DLDbFlatIdentifier, ident),
161 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
162 DBParameters params)
163 {
164 BEGIN_IPC
165 relocate(cred, credBase, credLength);
166 relocate(owner, ownerBase, ownerLength);
167 relocate(ident, identBase, identLength);
168 *db = (new Database(*ident, params, connection.process, cred, owner))->handle();
169 END_IPC(DL)
170 }
171
172 kern_return_t ucsp_server_decodeDb(UCSP_ARGS, DbHandle *db,
173 COPY_IN(DLDbFlatIdentifier, ident), COPY_IN(AccessCredentials, cred), DATA_IN(blob))
174 {
175 BEGIN_IPC
176 relocate(cred, credBase, credLength);
177 relocate(ident, identBase, identLength);
178 *db = (new Database(*ident, DATA(blob).interpretedAs<DbBlob>(),
179 connection.process, cred))->handle();
180 END_IPC(DL)
181 }
182
183 kern_return_t ucsp_server_encodeDb(UCSP_ARGS, DbHandle db, DATA_OUT(blob))
184 {
185 BEGIN_IPC
186 DbBlob *dbBlob = Server::database(db).encode(); // memory owned by database
187 *blob = dbBlob;
188 *blobLength = dbBlob->length();
189 END_IPC(DL)
190 }
191
192 kern_return_t ucsp_server_releaseDb(UCSP_ARGS, DbHandle db)
193 {
194 BEGIN_IPC
195 delete &Server::database(db);
196 END_IPC(DL)
197 }
198
199 kern_return_t ucsp_server_authenticateDb(UCSP_ARGS, DbHandle db,
200 COPY_IN(AccessCredentials, cred))
201 {
202 BEGIN_IPC
203 relocate(cred, credBase, credLength);
204 Server::database(db).authenticate(cred);
205 END_IPC(DL)
206 }
207
208 kern_return_t ucsp_server_setDbParameters(UCSP_ARGS, DbHandle db, DBParameters params)
209 {
210 BEGIN_IPC
211 Server::database(db).setParameters(params);
212 END_IPC(DL)
213 }
214
215 kern_return_t ucsp_server_getDbParameters(UCSP_ARGS, DbHandle db, DBParameters *params)
216 {
217 BEGIN_IPC
218 Server::database(db).getParameters(*params);
219 END_IPC(DL)
220 }
221
222 kern_return_t ucsp_server_changePassphrase(UCSP_ARGS, DbHandle db,
223 COPY_IN(AccessCredentials, cred))
224 {
225 BEGIN_IPC
226 relocate(cred, credBase, credLength);
227 Server::database(db).changePassphrase(cred);
228 END_IPC(DL)
229 }
230
231 kern_return_t ucsp_server_lockDb(UCSP_ARGS, DbHandle db)
232 {
233 BEGIN_IPC
234 Server::database(db).lock();
235 END_IPC(DL)
236 }
237
238 kern_return_t ucsp_server_unlockDb(UCSP_ARGS, DbHandle db)
239 {
240 BEGIN_IPC
241 Server::database(db).unlock();
242 END_IPC(DL)
243 }
244
245 kern_return_t ucsp_server_unlockDbWithPassphrase(UCSP_ARGS, DbHandle db, DATA_IN(passphrase))
246 {
247 BEGIN_IPC
248 Server::database(db).unlock(DATA(passphrase));
249 END_IPC(DL)
250 }
251
252 kern_return_t ucsp_server_isLocked(UCSP_ARGS, DbHandle db, boolean_t *locked)
253 {
254 BEGIN_IPC
255 *locked = Server::database(db).isLocked();
256 END_IPC(DL)
257 }
258
259
260 //
261 // Key management
262 //
263 kern_return_t ucsp_server_encodeKey(UCSP_ARGS, KeyHandle keyh, DATA_OUT(blob),
264 boolean_t wantUid, DATA_OUT(uid))
265 {
266 BEGIN_IPC
267 Key &key = Server::key(keyh);
268 KeyBlob *keyBlob = key.blob(); // still owned by key
269 *blob = keyBlob;
270 *blobLength = keyBlob->length();
271 if (wantUid) {
272 *uid = &key.uid();
273 *uidLength = sizeof(KeyUID);
274 } else {
275 *uidLength = 0; // do not return this
276 }
277 END_IPC(CSP)
278 }
279
280 kern_return_t ucsp_server_decodeKey(UCSP_ARGS, KeyHandle *keyh, CssmKey::Header *header,
281 DbHandle db, DATA_IN(blob))
282 {
283 BEGIN_IPC
284 Key &key = *new Key(Server::database(db), DATA(blob).interpretedAs<KeyBlob>());
285 key.returnKey(*keyh, *header);
286 END_IPC(CSP)
287 }
288
289 kern_return_t ucsp_server_releaseKey(UCSP_ARGS, KeyHandle key)
290 {
291 BEGIN_IPC
292 connection.releaseKey(key);
293 END_IPC(CSP)
294 }
295
296 kern_return_t ucsp_server_queryKeySizeInBits(UCSP_ARGS, KeyHandle key, CSSM_KEY_SIZE *length)
297 {
298 BEGIN_IPC
299 *length = connection.queryKeySize(findHandle<Key>(key));
300 END_IPC(CSP)
301 }
302
303 kern_return_t ucsp_server_getOutputSize(UCSP_ARGS, CONTEXT_ARGS, KeyHandle key,
304 uint32 inputSize, boolean_t encrypt, uint32 *outputSize)
305 {
306 BEGIN_IPC
307 context.postIPC(contextBase, attributes);
308 *outputSize = connection.getOutputSize(context, findHandle<Key>(key), inputSize, encrypt);
309 END_IPC(CSP)
310 }
311
312
313 //
314 // RNG interface
315 //
316 kern_return_t ucsp_server_generateRandom(UCSP_ARGS, uint32 bytes, DATA_OUT(data))
317 {
318 BEGIN_IPC
319 CssmAllocator &allocator = CssmAllocator::standard(CssmAllocator::sensitive);
320 void *buffer = allocator.malloc(bytes);
321 Server::active().random(buffer, bytes);
322 *data = buffer;
323 *dataLength = bytes;
324 Server::releaseWhenDone(allocator, buffer);
325 END_IPC(CSP)
326 }
327
328
329 //
330 // Signatures and MACs
331 //
332 kern_return_t ucsp_server_generateSignature(UCSP_ARGS, CONTEXT_ARGS, KeyHandle key,
333 CSSM_ALGORITHMS signOnlyAlgorithm, DATA_IN(data), DATA_OUT(signature))
334 {
335 BEGIN_IPC
336 context.postIPC(contextBase, attributes);
337 OutputData sigData(signature, signatureLength);
338 connection.generateSignature(context, findHandle<Key>(key), signOnlyAlgorithm,
339 DATA(data), sigData);
340 END_IPC(CSP)
341 }
342
343 kern_return_t ucsp_server_verifySignature(UCSP_ARGS, CONTEXT_ARGS, KeyHandle key,
344 CSSM_ALGORITHMS verifyOnlyAlgorithm, DATA_IN(data), DATA_IN(signature))
345 {
346 BEGIN_IPC
347 context.postIPC(contextBase, attributes);
348 connection.verifySignature(context, findHandle<Key>(key), verifyOnlyAlgorithm,
349 DATA(data), DATA(signature));
350 END_IPC(CSP)
351 }
352
353 kern_return_t ucsp_server_generateMac(UCSP_ARGS, CONTEXT_ARGS, KeyHandle key,
354 DATA_IN(data), DATA_OUT(mac))
355 {
356 BEGIN_IPC
357 context.postIPC(contextBase, attributes);
358 OutputData macData(mac, macLength);
359 connection.generateMac(context, findHandle<Key>(key),
360 DATA(data), macData);
361 END_IPC(CSP)
362 }
363
364 kern_return_t ucsp_server_verifyMac(UCSP_ARGS, CONTEXT_ARGS, KeyHandle key,
365 DATA_IN(data), DATA_IN(mac))
366 {
367 BEGIN_IPC
368 context.postIPC(contextBase, attributes);
369 connection.verifyMac(context, findHandle<Key>(key),
370 DATA(data), DATA(mac));
371 END_IPC(CSP)
372 }
373
374
375 //
376 // Encryption/Decryption
377 //
378 kern_return_t ucsp_server_encrypt(UCSP_ARGS, CONTEXT_ARGS, KeyHandle key,
379 DATA_IN(clear), DATA_OUT(cipher))
380 {
381 BEGIN_IPC
382 context.postIPC(contextBase, attributes);
383 OutputData cipherOut(cipher, cipherLength);
384 connection.encrypt(context, findHandle<Key>(key),
385 DATA(clear), cipherOut);
386 END_IPC(CSP)
387 }
388
389 kern_return_t ucsp_server_decrypt(UCSP_ARGS, CONTEXT_ARGS, KeyHandle key,
390 DATA_IN(cipher), DATA_OUT(clear))
391 {
392 BEGIN_IPC
393 context.postIPC(contextBase, attributes);
394 OutputData clearOut(clear, clearLength);
395 connection.decrypt(context, findHandle<Key>(key),
396 DATA(cipher), clearOut);
397 END_IPC(CSP)
398 }
399
400
401 //
402 // Key generation
403 //
404 kern_return_t ucsp_server_generateKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS,
405 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
406 uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader)
407 {
408 BEGIN_IPC
409 context.postIPC(contextBase, attributes);
410 relocate(cred, credBase, credLength);
411 relocate(owner, ownerBase, ownerLength);
412 Key *key;
413 connection.generateKey(Server::optionalDatabase(db),
414 context, cred, owner, usage, attrs, key);
415 key->returnKey(*newKey, *newHeader);
416 END_IPC(CSP)
417 }
418
419 kern_return_t ucsp_server_generateKeyPair(UCSP_ARGS, DbHandle db, CONTEXT_ARGS,
420 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
421 uint32 pubUsage, uint32 pubAttrs, uint32 privUsage, uint32 privAttrs,
422 KeyHandle *pubKey, CssmKey::Header *pubHeader, KeyHandle *privKey, CssmKey::Header *privHeader)
423 {
424 BEGIN_IPC
425 context.postIPC(contextBase, attributes);
426 relocate(cred, credBase, credLength);
427 relocate(owner, ownerBase, ownerLength);
428 Key *pub, *priv;
429 connection.generateKey(Server::optionalDatabase(db),
430 context, cred, owner,
431 pubUsage, pubAttrs, privUsage, privAttrs, pub, priv);
432 pub->returnKey(*pubKey, *pubHeader);
433 priv->returnKey(*privKey, *privHeader);
434 END_IPC(CSP)
435 }
436
437
438 //
439 // Key derivation.
440 // This is a bit strained; the incoming 'param' value may have structure
441 // and needs to be handled on a per-algorithm basis, which means we have to
442 // know which key derivation algorithms we support for passing to our CSP(s).
443 // The default behavior is to handle "flat" data blobs, which is as good
444 // a default as we can manage.
445 // NOTE: The param-specific handling must be synchronized with the client library
446 // code (in sstransit.h).
447 //
448 kern_return_t ucsp_server_deriveKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, KeyHandle key,
449 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
450 COPY_IN(void, paramInputData), DATA_OUT(paramOutput),
451 uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader)
452 {
453 BEGIN_IPC
454 context.postIPC(contextBase, attributes);
455 relocate(cred, credBase, credLength);
456 relocate(owner, ownerBase, ownerLength);
457
458 // munge together the incoming 'param' value according to algorithm
459 CssmData param;
460 switch (context.algorithm()) {
461 case CSSM_ALGID_PKCS5_PBKDF2:
462 relocate((CSSM_PKCS5_PBKDF2_PARAMS *)paramInputData,
463 (CSSM_PKCS5_PBKDF2_PARAMS *)paramInputDataBase,
464 paramInputDataLength);
465 param = CssmData(paramInputData, sizeof(CSSM_PKCS5_PBKDF2_PARAMS));
466 break;
467 default:
468 param = CssmData(paramInputData, paramInputDataLength);
469 break;
470 }
471 Key &theKey = connection.deriveKey(Server::optionalDatabase(db),
472 context, Server::optionalKey(key), cred, owner, &param, usage, attrs);
473 theKey.returnKey(*newKey, *newHeader);
474 if (param.length()) {
475 if (!param) // CSP screwed up
476 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
477 if (paramInputDataLength) // using incoming buffer; make a copy
478 param = CssmAutoData(Server::csp().allocator(), param).release();
479 OutputData(paramOutput, paramOutputLength) = param; // return the data
480 }
481 END_IPC(CSP)
482 }
483
484
485 //
486 // Key wrapping and unwrapping
487 //
488 kern_return_t ucsp_server_wrapKey(UCSP_ARGS, CONTEXT_ARGS, KeyHandle key,
489 COPY_IN(AccessCredentials, cred), KeyHandle keyToBeWrapped,
490 DATA_IN(descriptiveData), CssmKey *wrappedKey, DATA_OUT(keyData))
491 {
492 BEGIN_IPC
493 context.postIPC(contextBase, attributes);
494 relocate(cred, credBase, credLength);
495 connection.wrapKey(context, Server::optionalKey(key),
496 Server::key(keyToBeWrapped), cred, DATA(descriptiveData), *wrappedKey);
497 // transmit key data back as a separate blob
498 *keyData = wrappedKey->data();
499 *keyDataLength = wrappedKey->length();
500 Server::releaseWhenDone(*keyData);
501 END_IPC(CSP)
502 }
503
504 kern_return_t ucsp_server_unwrapKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, KeyHandle key,
505 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
506 KeyHandle publicKey, CssmKey wrappedKey, DATA_IN(wrappedKeyData),
507 uint32 usage, uint32 attr, DATA_OUT(descriptiveData),
508 KeyHandle *newKey, CssmKey::Header *newHeader)
509 {
510 BEGIN_IPC
511 context.postIPC(contextBase, attributes);
512 wrappedKey.KeyData = DATA(wrappedKeyData);
513 relocate(cred, credBase, credLength);
514 relocate(owner, ownerBase, ownerLength);
515 CssmData descriptiveDatas;
516 Key &theKey = connection.unwrapKey(Server::optionalDatabase(db),
517 context, Server::optionalKey(key), cred, owner, usage, attr, wrappedKey,
518 Server::optionalKey(publicKey), &descriptiveDatas);
519 theKey.returnKey(*newKey, *newHeader);
520 *descriptiveData = descriptiveDatas.data();
521 *descriptiveDataLength = descriptiveDatas.length();
522 Server::releaseWhenDone(*descriptiveData);
523 END_IPC(CSP)
524 }
525
526
527 //
528 // ACL management.
529 // Watch out for the memory-management tap-dance.
530 //
531 kern_return_t ucsp_server_getOwner(UCSP_ARGS, AclKind kind, KeyHandle key,
532 COPY_OUT(AclOwnerPrototype, ownerOut))
533 {
534 BEGIN_IPC
535 AclOwnerPrototype owner;
536 Server::aclBearer(kind, key).cssmGetOwner(owner); // allocates memory in owner
537 Copier<AclOwnerPrototype> owners(&owner, CssmAllocator::standard()); // make flat copy
538 { ChunkFreeWalker free; walk(free, owner); } // release chunked original
539 *ownerOut = *ownerOutBase = owners;
540 *ownerOutLength = owners.length();
541 Server::releaseWhenDone(owners.keep()); // throw flat copy out when done
542 END_IPC(CSP)
543 }
544
545 kern_return_t ucsp_server_setOwner(UCSP_ARGS, AclKind kind, KeyHandle key,
546 COPY_IN(AccessCredentials, cred), COPY_IN(AclOwnerPrototype, owner))
547 {
548 BEGIN_IPC
549 relocate(cred, credBase, credLength);
550 relocate(owner, ownerBase, ownerLength);
551 Server::aclBearer(kind, key).cssmChangeOwner(*owner, cred);
552 END_IPC(CSP)
553 }
554
555 kern_return_t ucsp_server_getAcl(UCSP_ARGS, AclKind kind, KeyHandle key,
556 boolean_t haveTag, const char *tag,
557 uint32 *countp, COPY_OUT(AclEntryInfo, acls))
558 {
559 BEGIN_IPC
560 uint32 count;
561 AclEntryInfo *aclList;
562 Server::aclBearer(kind, key).cssmGetAcl(haveTag ? tag : NULL, count, aclList);
563 *countp = count;
564 Copier<AclEntryInfo> aclsOut(AclEntryInfo::overlay(aclList), count); // make flat copy
565
566 { // release the chunked memory originals
567 ChunkFreeWalker free;
568 for (uint32 n = 0; n < count; n++)
569 walk(free, aclList[n]);
570 }
571
572 // set result
573 *acls = *aclsBase = aclsOut;
574 *aclsLength = aclsOut.length();
575 Server::releaseWhenDone(aclsOut.keep());
576 END_IPC(CSP)
577 }
578
579 kern_return_t ucsp_server_changeAcl(UCSP_ARGS, AclKind kind, KeyHandle key,
580 COPY_IN(AccessCredentials, cred), CSSM_ACL_EDIT_MODE mode, CSSM_ACL_HANDLE handle,
581 COPY_IN(AclEntryInput, acl))
582 {
583 BEGIN_IPC
584 relocate(cred, credBase, credLength);
585 relocate(acl, aclBase, aclLength);
586 Server::aclBearer(kind, key).cssmChangeAcl(AclEdit(mode, handle, acl), cred);
587 END_IPC(CSP)
588 }
589
590
591 //
592 // Authorization subsystem support
593 //
594 kern_return_t ucsp_server_authorizationCreate(UCSP_ARGS,
595 COPY_IN(AuthorizationItemSet, rights),
596 uint32 flags,
597 COPY_IN(AuthorizationItemSet, environment),
598 AuthorizationBlob *authorization)
599 {
600 BEGIN_IPC
601 relocate(rights, rightsBase, rightsLength);
602 relocate(environment, environmentBase, environmentLength);
603 *rcode = connection.process.session.authCreate(rights, environment,
604 flags, *authorization);
605 END_IPC(CSSM)
606 }
607
608 kern_return_t ucsp_server_authorizationRelease(UCSP_ARGS,
609 AuthorizationBlob authorization, uint32 flags)
610 {
611 BEGIN_IPC
612 connection.process.session.authFree(authorization, flags);
613 END_IPC(CSSM)
614 }
615
616 kern_return_t ucsp_server_authorizationCopyRights(UCSP_ARGS,
617 AuthorizationBlob authorization,
618 COPY_IN(AuthorizationItemSet, rights),
619 uint32 flags,
620 COPY_IN(AuthorizationItemSet, environment),
621 COPY_OUT(AuthorizationItemSet, result))
622 {
623 BEGIN_IPC
624 relocate(rights, rightsBase, rightsLength);
625 relocate(environment, environmentBase, environmentLength);
626 Authorization::MutableRightSet grantedRights;
627 *rcode = connection.process.session.authGetRights(authorization,
628 rights, environment, flags, grantedRights);
629 Copier<AuthorizationRights> returnedRights(grantedRights, CssmAllocator::standard());
630 *result = *resultBase = returnedRights;
631 *resultLength = returnedRights.length();
632 Server::releaseWhenDone(returnedRights.keep());
633 END_IPC(CSSM)
634 }
635
636 kern_return_t ucsp_server_authorizationCopyInfo(UCSP_ARGS,
637 AuthorizationBlob authorization,
638 AuthorizationString tag,
639 COPY_OUT(AuthorizationItemSet, info))
640 {
641 BEGIN_IPC
642 AuthorizationItemSet *result;
643 *info = *infoBase = NULL;
644 *infoLength = 0;
645 *rcode = connection.process.session.authGetInfo(authorization,
646 tag[0] ? tag : NULL, result); // result is a deep copy
647 if (*rcode == noErr)
648 {
649 *info = *infoBase = result;
650 *infoLength = size(result);
651 Server::releaseWhenDone(result);
652 }
653 END_IPC(CSSM)
654 }
655
656 kern_return_t ucsp_server_authorizationExternalize(UCSP_ARGS,
657 AuthorizationBlob authorization, AuthorizationExternalForm *extForm)
658 {
659 BEGIN_IPC
660 *rcode = connection.process.session.authExternalize(authorization, *extForm);
661 END_IPC(CSSM)
662 }
663
664 kern_return_t ucsp_server_authorizationInternalize(UCSP_ARGS,
665 AuthorizationExternalForm extForm, AuthorizationBlob *authorization)
666 {
667 BEGIN_IPC
668 *rcode = connection.process.session.authInternalize(extForm, *authorization);
669 END_IPC(CSSM)
670 }
671
672
673 //
674 // Session management subsystem
675 //
676 kern_return_t ucsp_server_getSessionInfo(UCSP_ARGS,
677 SecuritySessionId *sessionId, SessionAttributeBits *attrs)
678 {
679 BEGIN_IPC
680 Session &session = Session::find(*sessionId);
681 *sessionId = session.handle();
682 *attrs = session.attributes();
683 END_IPC(CSSM)
684 }
685
686 kern_return_t ucsp_server_setupSession(UCSP_ARGS,
687 SessionCreationFlags flags, SessionAttributeBits attrs)
688 {
689 BEGIN_IPC
690 Session::setup(flags, attrs);
691 END_IPC(CSSM)
692 }
693
694
695 //
696 // Notification core subsystem
697 //
698 kern_return_t ucsp_server_requestNotification(UCSP_ARGS, mach_port_t receiver, uint32 domain, uint32 events)
699 {
700 BEGIN_IPC
701 connection.process.requestNotifications(receiver, domain, events);
702 END_IPC(CSSM)
703 }
704
705 kern_return_t ucsp_server_stopNotification(UCSP_ARGS, mach_port_t receiver)
706 {
707 BEGIN_IPC
708 connection.process.stopNotifications(receiver);
709 END_IPC(CSSM)
710 }
711
712 kern_return_t ucsp_server_postNotification(UCSP_ARGS, uint32 domain, uint32 event, DATA_IN(data))
713 {
714 BEGIN_IPC
715 connection.process.postNotification(domain, event, DATA(data));
716 END_IPC(CSSM)
717 }