]> git.saurik.com Git - apple/security.git/blob - SecurityServer/transition.cpp
Security-179.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 "server.h"
23 #include "ucsp.h"
24 #include "session.h"
25 #include "xdatabase.h"
26 #include "transwalkers.h"
27 #include <mach/mach_error.h>
28
29 #include <CoreFoundation/CFDictionary.h>
30 #include <CoreFoundation/CFPropertyList.h>
31
32 //
33 // Bracket Macros
34 //
35 #define UCSP_ARGS mach_port_t servicePort, mach_port_t replyPort, audit_token_t auditToken, \
36 CSSM_RETURN *rcode
37 #define CONTEXT_ARGS Context context, Pointer contextBase, Context::Attr *attributes, mach_msg_type_number_t attrSize
38
39 #define BEGIN_IPCN *rcode = CSSM_OK; try {
40 #define BEGIN_IPC BEGIN_IPCN Connection &connection __attribute__((unused)) = Server::connection(replyPort);
41 #define END_IPC(base) END_IPCN(base) Server::requestComplete(); return KERN_SUCCESS;
42 #define END_IPCN(base) } \
43 catch (const CssmCommonError &err) { *rcode = err.cssmError(CSSM_ ## base ## _BASE_ERROR); } \
44 catch (const std::bad_alloc &) { *rcode = CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \
45 catch (Connection *conn) { *rcode = 0; } \
46 catch (...) { *rcode = CssmError::merge(CSSM_ERRCODE_INTERNAL_ERROR, CSSM_ ## base ## _BASE_ERROR); }
47
48 #define DATA_IN(base) void *base, mach_msg_type_number_t base##Length
49 #define DATA_OUT(base) void **base, mach_msg_type_number_t *base##Length
50 #define DATA(base) CssmData(base, base##Length)
51
52 #define COPY_IN(type,name) type *name, mach_msg_type_number_t name##Length, type *name##Base
53 #define COPY_OUT(type,name) \
54 type **name, mach_msg_type_number_t *name##Length, type **name##Base
55
56
57 using LowLevelMemoryUtilities::increment;
58 using LowLevelMemoryUtilities::difference;
59
60
61 //
62 // An OutputData object will take memory allocated within the SecurityServer,
63 // hand it to the MIG return-output parameters, and schedule it to be released
64 // after the MIG reply has been sent. It will also get rid of it in case of
65 // error.
66 //
67 class OutputData : public CssmData {
68 public:
69 OutputData(void **outP, mach_msg_type_number_t *outLength)
70 : mData(*outP), mLength(*outLength) { }
71 ~OutputData()
72 { mData = data(); mLength = length(); Server::releaseWhenDone(mData); }
73
74 void operator = (const CssmData &source)
75 { CssmData::operator = (source); }
76
77 private:
78 void * &mData;
79 mach_msg_type_number_t &mLength;
80 };
81
82
83 //
84 // Setup/Teardown functions.
85 //
86 kern_return_t ucsp_server_setup(UCSP_ARGS, mach_port_t taskPort, ClientSetupInfo info, const char *identity)
87 {
88 BEGIN_IPCN
89 Server::active().setupConnection(Server::connectNewProcess, servicePort, replyPort,
90 taskPort, auditToken, &info, identity);
91 END_IPCN(CSSM)
92 return KERN_SUCCESS;
93 }
94
95 kern_return_t ucsp_server_setupNew(UCSP_ARGS, mach_port_t taskPort,
96 ClientSetupInfo info, const char *identity,
97 mach_port_t *newServicePort)
98 {
99 BEGIN_IPCN
100 try {
101 Session *session = new DynamicSession(TaskPort(taskPort).bootstrap());
102 Server::active().setupConnection(Server::connectNewSession, session->servicePort(), replyPort,
103 taskPort, auditToken, &info, identity);
104 *newServicePort = session->servicePort();
105 } catch (const MachPlusPlus::Error &err) {
106 switch (err.error) {
107 case BOOTSTRAP_SERVICE_ACTIVE:
108 MacOSError::throwMe(errSessionAuthorizationDenied); // translate
109 default:
110 throw;
111 }
112 }
113 END_IPCN(CSSM)
114 return KERN_SUCCESS;
115 }
116
117 kern_return_t ucsp_server_setupThread(UCSP_ARGS, mach_port_t taskPort)
118 {
119 BEGIN_IPCN
120 Server::active().setupConnection(Server::connectNewThread, servicePort, replyPort,
121 taskPort, auditToken);
122 END_IPCN(CSSM)
123 return KERN_SUCCESS;
124 }
125
126
127 kern_return_t ucsp_server_teardown(UCSP_ARGS)
128 {
129 BEGIN_IPCN
130 Server::active().endConnection(replyPort);
131 END_IPCN(CSSM)
132 return KERN_SUCCESS;
133 }
134
135
136 //
137 // Database management
138 //
139 kern_return_t ucsp_server_createDb(UCSP_ARGS, DbHandle *db,
140 COPY_IN(DLDbFlatIdentifier, ident),
141 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
142 DBParameters params)
143 {
144 BEGIN_IPC
145 relocate(cred, credBase, credLength);
146 relocate(owner, ownerBase, ownerLength);
147 relocate(ident, identBase, identLength);
148 *db = (new Database(*ident, params, connection.process, cred, owner))->handle();
149 END_IPC(DL)
150 }
151
152 kern_return_t ucsp_server_decodeDb(UCSP_ARGS, DbHandle *db,
153 COPY_IN(DLDbFlatIdentifier, ident), COPY_IN(AccessCredentials, cred), DATA_IN(blob))
154 {
155 BEGIN_IPC
156 relocate(cred, credBase, credLength);
157 relocate(ident, identBase, identLength);
158 *db = (new Database(*ident, DATA(blob).interpretedAs<DbBlob>(),
159 connection.process, cred))->handle();
160 END_IPC(DL)
161 }
162
163 kern_return_t ucsp_server_encodeDb(UCSP_ARGS, DbHandle db, DATA_OUT(blob))
164 {
165 BEGIN_IPC
166 DbBlob *dbBlob = Server::database(db).blob(); // memory owned by database
167 *blob = dbBlob;
168 *blobLength = dbBlob->length();
169 END_IPC(DL)
170 }
171
172 kern_return_t ucsp_server_releaseDb(UCSP_ARGS, DbHandle db)
173 {
174 BEGIN_IPC
175 delete &Server::database(db);
176 END_IPC(DL)
177 }
178
179 kern_return_t ucsp_server_getDbIndex(UCSP_ARGS, DbHandle db, DATA_OUT(index))
180 {
181 BEGIN_IPC
182 OutputData indexData(index, indexLength);
183 Server::database(db).getDbIndex(indexData);
184 END_IPC(DL)
185 }
186
187 kern_return_t ucsp_server_authenticateDb(UCSP_ARGS, DbHandle db,
188 COPY_IN(AccessCredentials, cred))
189 {
190 BEGIN_IPC
191 relocate(cred, credBase, credLength);
192 Server::database(db).authenticate(cred);
193 END_IPC(DL)
194 }
195
196 kern_return_t ucsp_server_setDbParameters(UCSP_ARGS, DbHandle db, DBParameters params)
197 {
198 BEGIN_IPC
199 Server::database(db).setParameters(params);
200 END_IPC(DL)
201 }
202
203 kern_return_t ucsp_server_getDbParameters(UCSP_ARGS, DbHandle db, DBParameters *params)
204 {
205 BEGIN_IPC
206 Server::database(db).getParameters(*params);
207 END_IPC(DL)
208 }
209
210 kern_return_t ucsp_server_changePassphrase(UCSP_ARGS, DbHandle db,
211 COPY_IN(AccessCredentials, cred))
212 {
213 BEGIN_IPC
214 relocate(cred, credBase, credLength);
215 Server::database(db).changePassphrase(cred);
216 END_IPC(DL)
217 }
218
219 kern_return_t ucsp_server_lockDb(UCSP_ARGS, DbHandle db)
220 {
221 BEGIN_IPC
222 Server::database(db).lock();
223 END_IPC(DL)
224 }
225
226 kern_return_t ucsp_server_lockAll (UCSP_ARGS, boolean_t forSleep)
227 {
228 BEGIN_IPC
229 Database::lockAllDatabases(connection.process.session.databases(), forSleep);
230 END_IPC(DL)
231 }
232
233 kern_return_t ucsp_server_unlockDb(UCSP_ARGS, DbHandle db)
234 {
235 BEGIN_IPC
236 Server::database(db).unlock();
237 END_IPC(DL)
238 }
239
240 kern_return_t ucsp_server_unlockDbWithPassphrase(UCSP_ARGS, DbHandle db, DATA_IN(passphrase))
241 {
242 BEGIN_IPC
243 Server::database(db).unlock(DATA(passphrase));
244 END_IPC(DL)
245 }
246
247 kern_return_t ucsp_server_isLocked(UCSP_ARGS, DbHandle db, boolean_t *locked)
248 {
249 BEGIN_IPC
250 *locked = Server::database(db).isLocked();
251 END_IPC(DL)
252 }
253
254
255 //
256 // Key management
257 //
258 kern_return_t ucsp_server_encodeKey(UCSP_ARGS, KeyHandle keyh, DATA_OUT(blob),
259 boolean_t wantUid, DATA_OUT(uid))
260 {
261 BEGIN_IPC
262 Key &key = Server::key(keyh);
263 KeyBlob *keyBlob = key.blob(); // still owned by key
264 *blob = keyBlob;
265 *blobLength = keyBlob->length();
266 if (wantUid) {
267 *uid = &key.uid();
268 *uidLength = sizeof(KeyUID);
269 } else {
270 *uidLength = 0; // do not return this
271 }
272 END_IPC(CSP)
273 }
274
275 kern_return_t ucsp_server_decodeKey(UCSP_ARGS, KeyHandle *keyh, CssmKey::Header *header,
276 DbHandle db, DATA_IN(blob))
277 {
278 BEGIN_IPC
279 Key &key = *new Key(Server::database(db), DATA(blob).interpretedAs<KeyBlob>());
280 key.returnKey(*keyh, *header);
281 flip(*header);
282 END_IPC(CSP)
283 }
284
285 kern_return_t ucsp_server_releaseKey(UCSP_ARGS, KeyHandle key)
286 {
287 BEGIN_IPC
288 connection.releaseKey(key);
289 END_IPC(CSP)
290 }
291
292 kern_return_t ucsp_server_queryKeySizeInBits(UCSP_ARGS, KeyHandle key, CSSM_KEY_SIZE *length)
293 {
294 BEGIN_IPC
295 *length = connection.queryKeySize(Server::key(key));
296 END_IPC(CSP)
297 }
298
299 kern_return_t ucsp_server_getOutputSize(UCSP_ARGS, CONTEXT_ARGS, KeyHandle key,
300 uint32 inputSize, boolean_t encrypt, uint32 *outputSize)
301 {
302 BEGIN_IPC
303 relocate(context, contextBase, attributes, attrSize);
304 *outputSize = connection.getOutputSize(context, Server::key(key), inputSize, encrypt);
305 END_IPC(CSP)
306 }
307
308 kern_return_t ucsp_server_getKeyDigest(UCSP_ARGS, KeyHandle key, DATA_OUT(digest))
309 {
310 BEGIN_IPC
311 CssmData digestData = Server::key(key).canonicalDigest();
312 *digest = digestData.data();
313 *digestLength = digestData.length();
314 END_IPC(CSP)
315 }
316
317 //
318 // RNG interface
319 //
320 kern_return_t ucsp_server_generateRandom(UCSP_ARGS, uint32 bytes, DATA_OUT(data))
321 {
322 BEGIN_IPC
323 CssmAllocator &allocator = CssmAllocator::standard(CssmAllocator::sensitive);
324 void *buffer = allocator.malloc(bytes);
325 Server::active().random(buffer, bytes);
326 *data = buffer;
327 *dataLength = bytes;
328 Server::releaseWhenDone(allocator, buffer);
329 END_IPC(CSP)
330 }
331
332
333 //
334 // Signatures and MACs
335 //
336 kern_return_t ucsp_server_generateSignature(UCSP_ARGS, CONTEXT_ARGS, KeyHandle key,
337 CSSM_ALGORITHMS signOnlyAlgorithm, DATA_IN(data), DATA_OUT(signature))
338 {
339 BEGIN_IPC
340 relocate(context, contextBase, attributes, attrSize);
341 OutputData sigData(signature, signatureLength);
342 connection.generateSignature(context, Server::key(key), signOnlyAlgorithm,
343 DATA(data), sigData);
344 END_IPC(CSP)
345 }
346
347 kern_return_t ucsp_server_verifySignature(UCSP_ARGS, CONTEXT_ARGS, KeyHandle key,
348 CSSM_ALGORITHMS verifyOnlyAlgorithm, DATA_IN(data), DATA_IN(signature))
349 {
350 BEGIN_IPC
351 relocate(context, contextBase, attributes, attrSize);
352 connection.verifySignature(context, Server::key(key), verifyOnlyAlgorithm,
353 DATA(data), DATA(signature));
354 END_IPC(CSP)
355 }
356
357 kern_return_t ucsp_server_generateMac(UCSP_ARGS, CONTEXT_ARGS, KeyHandle key,
358 DATA_IN(data), DATA_OUT(mac))
359 {
360 BEGIN_IPC
361 relocate(context, contextBase, attributes, attrSize);
362 OutputData macData(mac, macLength);
363 connection.generateMac(context, Server::key(key),
364 DATA(data), macData);
365 END_IPC(CSP)
366 }
367
368 kern_return_t ucsp_server_verifyMac(UCSP_ARGS, CONTEXT_ARGS, KeyHandle key,
369 DATA_IN(data), DATA_IN(mac))
370 {
371 BEGIN_IPC
372 relocate(context, contextBase, attributes, attrSize);
373 connection.verifyMac(context, Server::key(key), DATA(data), DATA(mac));
374 END_IPC(CSP)
375 }
376
377
378 //
379 // Encryption/Decryption
380 //
381 kern_return_t ucsp_server_encrypt(UCSP_ARGS, CONTEXT_ARGS, KeyHandle key,
382 DATA_IN(clear), DATA_OUT(cipher))
383 {
384 BEGIN_IPC
385 relocate(context, contextBase, attributes, attrSize);
386 OutputData cipherOut(cipher, cipherLength);
387 connection.encrypt(context, Server::key(key),
388 DATA(clear), cipherOut);
389 END_IPC(CSP)
390 }
391
392 kern_return_t ucsp_server_decrypt(UCSP_ARGS, CONTEXT_ARGS, KeyHandle key,
393 DATA_IN(cipher), DATA_OUT(clear))
394 {
395 BEGIN_IPC
396 relocate(context, contextBase, attributes, attrSize);
397 OutputData clearOut(clear, clearLength);
398 connection.decrypt(context, Server::key(key),
399 DATA(cipher), clearOut);
400 END_IPC(CSP)
401 }
402
403
404 //
405 // Key generation
406 //
407 kern_return_t ucsp_server_generateKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS,
408 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
409 uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader)
410 {
411 BEGIN_IPC
412 relocate(context, contextBase, attributes, attrSize);
413 relocate(cred, credBase, credLength);
414 relocate(owner, ownerBase, ownerLength);
415 Key *key;
416 connection.generateKey(Server::optionalDatabase(db),
417 context, cred, owner, usage, attrs, key);
418 key->returnKey(*newKey, *newHeader);
419 flip(*newHeader);
420 END_IPC(CSP)
421 }
422
423 kern_return_t ucsp_server_generateKeyPair(UCSP_ARGS, DbHandle db, CONTEXT_ARGS,
424 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
425 uint32 pubUsage, uint32 pubAttrs, uint32 privUsage, uint32 privAttrs,
426 KeyHandle *pubKey, CssmKey::Header *pubHeader, KeyHandle *privKey, CssmKey::Header *privHeader)
427 {
428 BEGIN_IPC
429 relocate(context, contextBase, attributes, attrSize);
430 relocate(cred, credBase, credLength);
431 relocate(owner, ownerBase, ownerLength);
432 Key *pub, *priv;
433 connection.generateKey(Server::optionalDatabase(db),
434 context, cred, owner,
435 pubUsage, pubAttrs, privUsage, privAttrs, pub, priv);
436 pub->returnKey(*pubKey, *pubHeader);
437 flip(*pubHeader);
438 priv->returnKey(*privKey, *privHeader);
439 flip(*privHeader);
440 END_IPC(CSP)
441 }
442
443
444 //
445 // Key derivation.
446 // This is a bit strained; the incoming 'param' value may have structure
447 // and needs to be handled on a per-algorithm basis, which means we have to
448 // know which key derivation algorithms we support for passing to our CSP(s).
449 // The default behavior is to handle "flat" data blobs, which is as good
450 // a default as we can manage.
451 // NOTE: The param-specific handling must be synchronized with the client library
452 // code (in sstransit.h).
453 //
454 kern_return_t ucsp_server_deriveKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, KeyHandle key,
455 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
456 COPY_IN(void, paramInputData), DATA_OUT(paramOutput),
457 uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader)
458 {
459 BEGIN_IPC
460 relocate(context, contextBase, attributes, attrSize);
461 relocate(cred, credBase, credLength);
462 relocate(owner, ownerBase, ownerLength);
463
464 // munge together the incoming 'param' value according to algorithm
465 CssmData param;
466 switch (context.algorithm()) {
467 case CSSM_ALGID_PKCS5_PBKDF2:
468 relocate((CSSM_PKCS5_PBKDF2_PARAMS *)paramInputData,
469 (CSSM_PKCS5_PBKDF2_PARAMS *)paramInputDataBase,
470 paramInputDataLength);
471 param = CssmData(paramInputData, sizeof(CSSM_PKCS5_PBKDF2_PARAMS));
472 break;
473 default:
474 param = CssmData(paramInputData, paramInputDataLength);
475 break;
476 }
477 Key &theKey = connection.deriveKey(Server::optionalDatabase(db),
478 context, Server::optionalKey(key), cred, owner, &param, usage, attrs);
479 theKey.returnKey(*newKey, *newHeader);
480 flip(*newHeader);
481 if (param.length()) {
482 if (!param) // CSP screwed up
483 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
484 if (paramInputDataLength) // using incoming buffer; make a copy
485 param = CssmAutoData(Server::csp().allocator(), param).release();
486 OutputData(paramOutput, paramOutputLength) = param; // return the data
487 }
488 END_IPC(CSP)
489 }
490
491
492 //
493 // Key wrapping and unwrapping
494 //
495 kern_return_t ucsp_server_wrapKey(UCSP_ARGS, CONTEXT_ARGS, KeyHandle key,
496 COPY_IN(AccessCredentials, cred), KeyHandle keyToBeWrapped,
497 DATA_IN(descriptiveData), CssmKey *wrappedKey, DATA_OUT(keyData))
498 {
499 BEGIN_IPC
500 relocate(context, contextBase, attributes, attrSize);
501 relocate(cred, credBase, credLength);
502 connection.wrapKey(context, Server::optionalKey(key),
503 Server::key(keyToBeWrapped), cred, DATA(descriptiveData), *wrappedKey);
504 // transmit key data back as a separate blob
505 *keyData = wrappedKey->data();
506 *keyDataLength = wrappedKey->length();
507 Server::releaseWhenDone(*keyData);
508 flip(*wrappedKey);
509 END_IPC(CSP)
510 }
511
512 kern_return_t ucsp_server_unwrapKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, KeyHandle key,
513 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
514 KeyHandle publicKey, CssmKey wrappedKey, DATA_IN(wrappedKeyData),
515 uint32 usage, uint32 attr, DATA_OUT(descriptiveData),
516 KeyHandle *newKey, CssmKey::Header *newHeader)
517 {
518 BEGIN_IPC
519 relocate(context, contextBase, attributes, attrSize);
520 flip(wrappedKey);
521 wrappedKey.KeyData = DATA(wrappedKeyData);
522 relocate(cred, credBase, credLength);
523 relocate(owner, ownerBase, ownerLength);
524 CssmData descriptiveDatas;
525 Key &theKey = connection.unwrapKey(Server::optionalDatabase(db),
526 context, Server::optionalKey(key), cred, owner, usage, attr, wrappedKey,
527 Server::optionalKey(publicKey), &descriptiveDatas);
528 theKey.returnKey(*newKey, *newHeader);
529 flip(*newHeader);
530 *descriptiveData = descriptiveDatas.data();
531 *descriptiveDataLength = descriptiveDatas.length();
532 Server::releaseWhenDone(*descriptiveData);
533 END_IPC(CSP)
534 }
535
536
537 //
538 // ACL management.
539 // Watch out for the memory-management tap-dance.
540 //
541 kern_return_t ucsp_server_getOwner(UCSP_ARGS, AclKind kind, KeyHandle key,
542 COPY_OUT(AclOwnerPrototype, ownerOut))
543 {
544 BEGIN_IPC
545 AclOwnerPrototype owner;
546 Server::aclBearer(kind, key).cssmGetOwner(owner); // allocates memory in owner
547 Copier<AclOwnerPrototype> owners(&owner, CssmAllocator::standard()); // make flat copy
548 { ChunkFreeWalker free; walk(free, owner); } // release chunked original
549 *ownerOutLength = owners.length();
550 flips(owners.value(), ownerOut, ownerOutBase);
551 Server::releaseWhenDone(owners.keep()); // throw flat copy out when done
552 END_IPC(CSP)
553 }
554
555 kern_return_t ucsp_server_setOwner(UCSP_ARGS, AclKind kind, KeyHandle key,
556 COPY_IN(AccessCredentials, cred), COPY_IN(AclOwnerPrototype, owner))
557 {
558 BEGIN_IPC
559 relocate(cred, credBase, credLength);
560 relocate(owner, ownerBase, ownerLength);
561 Server::aclBearer(kind, key).cssmChangeOwner(*owner, cred);
562 END_IPC(CSP)
563 }
564
565 kern_return_t ucsp_server_getAcl(UCSP_ARGS, AclKind kind, KeyHandle key,
566 boolean_t haveTag, const char *tag,
567 uint32 *countp, COPY_OUT(AclEntryInfo, acls))
568 {
569 BEGIN_IPC
570 uint32 count;
571 AclEntryInfo *aclList;
572 Server::aclBearer(kind, key).cssmGetAcl(haveTag ? tag : NULL, count, aclList);
573 *countp = count;
574 Copier<AclEntryInfo> aclsOut(AclEntryInfo::overlay(aclList), count); // make flat copy
575
576 { // release the chunked memory originals
577 ChunkFreeWalker free;
578 for (uint32 n = 0; n < count; n++)
579 walk(free, aclList[n]);
580
581 // release the memory allocated for the list itself when we are done
582 CssmAllocator::standard().free (aclList);
583 }
584
585 // set result (note: this is *almost* flips(), but on an array)
586 *aclsLength = aclsOut.length();
587 *acls = *aclsBase = aclsOut;
588 if (flipClient()) {
589 FlipWalker w;
590 for (uint32 n = 0; n < count; n++)
591 walk(w, (*acls)[n]);
592 w.doFlips();
593 Flippers::flip(*aclsBase);
594 }
595 Server::releaseWhenDone(aclsOut.keep());
596 END_IPC(CSP)
597 }
598
599 kern_return_t ucsp_server_changeAcl(UCSP_ARGS, AclKind kind, KeyHandle key,
600 COPY_IN(AccessCredentials, cred), CSSM_ACL_EDIT_MODE mode, CSSM_ACL_HANDLE handle,
601 COPY_IN(AclEntryInput, acl))
602 {
603 BEGIN_IPC
604 relocate(cred, credBase, credLength);
605 relocate(acl, aclBase, aclLength);
606 Server::aclBearer(kind, key).cssmChangeAcl(AclEdit(mode, handle, acl), cred);
607 END_IPC(CSP)
608 }
609
610
611 //
612 // Database key management.
613 // ExtractMasterKey looks vaguely like a key derivation operation, and is in fact
614 // presented by the CSPDL's CSSM layer as such.
615 //
616 kern_return_t ucsp_server_extractMasterKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, DbHandle sourceDb,
617 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
618 uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader)
619 {
620 BEGIN_IPC
621 context.postIPC(contextBase, attributes);
622 relocate(cred, credBase, credLength);
623 relocate(owner, ownerBase, ownerLength);
624 Key *masterKey = Server::database(sourceDb).extractMasterKey(Server::optionalDatabase(db),
625 cred, owner, usage, attrs);
626 masterKey->returnKey(*newKey, *newHeader);
627 flip(*newHeader);
628 END_IPC(CSP)
629 }
630
631
632 //
633 // Authorization subsystem support
634 //
635 kern_return_t ucsp_server_authorizationCreate(UCSP_ARGS,
636 COPY_IN(AuthorizationItemSet, inRights),
637 uint32 flags,
638 COPY_IN(AuthorizationItemSet, inEnvironment),
639 AuthorizationBlob *authorization)
640 {
641 BEGIN_IPC
642 relocate(inRights, inRightsBase, inRightsLength);
643 relocate(inEnvironment, inEnvironmentBase, inEnvironmentLength);
644 Authorization::AuthItemSet rights(inRights), environment(inEnvironment);
645
646 *rcode = connection.process.session.authCreate(rights, environment,
647 flags, *authorization, auditToken);
648 END_IPC(CSSM)
649 }
650
651 kern_return_t ucsp_server_authorizationRelease(UCSP_ARGS,
652 AuthorizationBlob authorization, uint32 flags)
653 {
654 BEGIN_IPC
655 connection.process.session.authFree(authorization, flags);
656 END_IPC(CSSM)
657 }
658
659 kern_return_t ucsp_server_authorizationCopyRights(UCSP_ARGS,
660 AuthorizationBlob authorization,
661 COPY_IN(AuthorizationItemSet, inRights),
662 uint32 flags,
663 COPY_IN(AuthorizationItemSet, inEnvironment),
664 COPY_OUT(AuthorizationItemSet, result))
665 {
666 BEGIN_IPC
667 relocate(inRights, inRightsBase, inRightsLength);
668 relocate(inEnvironment, inEnvironmentBase, inEnvironmentLength);
669 Authorization::AuthItemSet rights(inRights), environment(inEnvironment), grantedRights;
670 *rcode = connection.process.session.authGetRights(authorization,
671 rights, environment, flags, grantedRights);
672 if (result && resultLength)
673 {
674 size_t resultSize;
675 grantedRights.copy(*result, resultSize);
676 *resultLength = resultSize;
677 *resultBase = *result;
678 flips(*result, result, resultBase);
679 Server::releaseWhenDone(*result);
680 }
681 END_IPC(CSSM)
682 }
683
684 kern_return_t ucsp_server_authorizationCopyInfo(UCSP_ARGS,
685 AuthorizationBlob authorization,
686 AuthorizationString tag,
687 COPY_OUT(AuthorizationItemSet, info))
688 {
689 BEGIN_IPC
690 Authorization::AuthItemSet infoSet;
691 *info = *infoBase = NULL;
692 *infoLength = 0;
693 *rcode = connection.process.session.authGetInfo(authorization,
694 tag[0] ? tag : NULL, infoSet);
695 if (*rcode == noErr) {
696 size_t infoSize;
697 infoSet.copy(*info, infoSize);
698 *infoLength = infoSize;
699 *infoBase = *info;
700 flips(*info, info, infoBase);
701 Server::releaseWhenDone(*info);
702 }
703 END_IPC(CSSM)
704 }
705
706 kern_return_t ucsp_server_authorizationExternalize(UCSP_ARGS,
707 AuthorizationBlob authorization, AuthorizationExternalForm *extForm)
708 {
709 BEGIN_IPC
710 *rcode = connection.process.session.authExternalize(authorization, *extForm);
711 END_IPC(CSSM)
712 }
713
714 kern_return_t ucsp_server_authorizationInternalize(UCSP_ARGS,
715 AuthorizationExternalForm extForm, AuthorizationBlob *authorization)
716 {
717 BEGIN_IPC
718 *rcode = connection.process.session.authInternalize(extForm, *authorization);
719 END_IPC(CSSM)
720 }
721
722
723 //
724 // Session management subsystem
725 //
726 kern_return_t ucsp_server_getSessionInfo(UCSP_ARGS,
727 SecuritySessionId *sessionId, SessionAttributeBits *attrs)
728 {
729 BEGIN_IPC
730 Session &session = Session::find(*sessionId);
731 *sessionId = session.handle();
732 *attrs = session.attributes();
733 END_IPC(CSSM)
734 }
735
736 kern_return_t ucsp_server_setupSession(UCSP_ARGS,
737 SessionCreationFlags flags, SessionAttributeBits attrs)
738 {
739 BEGIN_IPC
740 Session::setup(flags, attrs);
741 END_IPC(CSSM)
742 }
743
744
745 //
746 // Notification core subsystem
747 //
748 kern_return_t ucsp_server_requestNotification(UCSP_ARGS, mach_port_t receiver, uint32 domain, uint32 events)
749 {
750 BEGIN_IPC
751 connection.process.requestNotifications(receiver, domain, events);
752 END_IPC(CSSM)
753 }
754
755 kern_return_t ucsp_server_stopNotification(UCSP_ARGS, mach_port_t receiver)
756 {
757 BEGIN_IPC
758 connection.process.stopNotifications(receiver);
759 END_IPC(CSSM)
760 }
761
762 kern_return_t ucsp_server_postNotification(UCSP_ARGS, uint32 domain, uint32 event, DATA_IN(data))
763 {
764 BEGIN_IPC
765 connection.process.postNotification(domain, event, DATA(data));
766 END_IPC(CSSM)
767 }
768
769
770 //
771 // AuthorizationDB modification
772 //
773 kern_return_t ucsp_server_authorizationdbGet(UCSP_ARGS, const char *rightname, DATA_OUT(rightDefinition))
774 {
775 BEGIN_IPC
776 CFDictionaryRef rightDict;
777
778 *rcode = connection.process.session.authorizationdbGet(rightname, &rightDict);
779
780 if (!*rcode && rightDict)
781 {
782 CFRef<CFDataRef> data(CFPropertyListCreateXMLData (NULL, rightDict));
783 CFRelease(rightDict);
784 if (!data)
785 return errAuthorizationInternal;
786
787 // @@@ copy data to avoid having to do a delayed cfrelease
788 mach_msg_type_number_t length = CFDataGetLength(data);
789 void *xmlData = CssmAllocator::standard().malloc(length);
790 memcpy(xmlData, CFDataGetBytePtr(data), length);
791 Server::releaseWhenDone(xmlData);
792
793 *rightDefinition = xmlData;
794 *rightDefinitionLength = length;
795 }
796 END_IPC(CSSM)
797 }
798
799 kern_return_t ucsp_server_authorizationdbSet(UCSP_ARGS, AuthorizationBlob authorization, const char *rightname, DATA_IN(rightDefinition))
800 {
801 BEGIN_IPC
802 CFRef<CFDataRef> data(CFDataCreate(NULL, (UInt8 *)rightDefinition, rightDefinitionLength));
803
804 if (!data)
805 return errAuthorizationInternal;
806
807 CFRef<CFDictionaryRef> rightDefinition(static_cast<CFDictionaryRef>(CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListImmutable, NULL)));
808
809 if (!rightDefinition || (CFGetTypeID(rightDefinition) != CFDictionaryGetTypeID()))
810 return errAuthorizationInternal;
811
812 *rcode = connection.process.session.authorizationdbSet(authorization, rightname, rightDefinition);
813
814 END_IPC(CSSM)
815 }
816
817 kern_return_t ucsp_server_authorizationdbRemove(UCSP_ARGS, AuthorizationBlob authorization, const char *rightname)
818 {
819 BEGIN_IPC
820 *rcode = connection.process.session.authorizationdbRemove(authorization, rightname);
821 END_IPC(CSSM)
822 }
823
824
825 //
826 // Miscellaneous administrative functions
827 //
828 kern_return_t ucsp_server_addCodeEquivalence(UCSP_ARGS, DATA_IN(oldHash), DATA_IN(newHash),
829 const char *name, boolean_t forSystem)
830 {
831 BEGIN_IPC
832 Server::codeSignatures().addLink(DATA(oldHash), DATA(newHash), name, forSystem);
833 END_IPC(CSSM)
834 }
835
836 kern_return_t ucsp_server_removeCodeEquivalence(UCSP_ARGS, DATA_IN(hash),
837 const char *name, boolean_t forSystem)
838 {
839 BEGIN_IPC
840 Server::codeSignatures().removeLink(DATA(hash), name, forSystem);
841 END_IPC(CSSM)
842 }
843
844 kern_return_t ucsp_server_setAlternateSystemRoot(UCSP_ARGS, const char *root)
845 {
846 BEGIN_IPC
847 #if defined(NDEBUG)
848 if (connection.process.uid() != 0)
849 CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED);
850 #endif //NDEBUG
851 Server::codeSignatures().open((string(root) + EQUIVALENCEDBPATH).c_str());
852 END_IPC(CSSM)
853 }