]> git.saurik.com Git - apple/securityd.git/blob - src/transition.cpp
securityd-26674.tar.gz
[apple/securityd.git] / src / transition.cpp
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 //
26 // transition - securityd IPC-to-class-methods transition layer
27 //
28 #include <securityd_client/ucsp.h>
29 #include "server.h"
30 #include "session.h"
31 #include "database.h"
32 #include "kcdatabase.h"
33 #include "tokendatabase.h"
34 #include "kckey.h"
35 #include "transwalkers.h"
36 #include "child.h"
37 #include <mach/mach_error.h>
38
39 #include <CoreFoundation/CFDictionary.h>
40 #include <CoreFoundation/CFPropertyList.h>
41
42
43 //
44 // Bracket Macros
45 //
46 #define UCSP_ARGS mach_port_t servicePort, mach_port_t replyPort, audit_token_t auditToken, \
47 CSSM_RETURN *rcode
48 #define CONTEXT_ARGS Context context, Pointer contextBase, Context::Attr *attributes, mach_msg_type_number_t attrSize
49
50 #define BEGIN_IPCN *rcode = CSSM_OK; try {
51 #define BEGIN_IPC BEGIN_IPCN RefPointer<Connection> connRef(&Server::connection(replyPort)); \
52 Connection &connection __attribute__((unused)) = *connRef;
53 #define END_IPC(base) END_IPCN(base) Server::requestComplete(); return KERN_SUCCESS;
54 #define END_IPCN(base) } \
55 catch (const CommonError &err) { *rcode = CssmError::cssmError(err, CSSM_ ## base ## _BASE_ERROR); } \
56 catch (const std::bad_alloc &) { *rcode = CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \
57 catch (Connection *conn) { *rcode = 0; } \
58 catch (...) { *rcode = CssmError::merge(CSSM_ERRCODE_INTERNAL_ERROR, CSSM_ ## base ## _BASE_ERROR); }
59
60 #define BEGIN_IPCS try {
61 #define END_IPCS(more) } catch (...) { } \
62 mach_port_deallocate(mach_task_self(), serverPort); more; return KERN_SUCCESS;
63
64 #define DATA_IN(base) void *base, mach_msg_type_number_t base##Length
65 #define DATA_OUT(base) void **base, mach_msg_type_number_t *base##Length
66 #define DATA(base) CssmData(base, base##Length)
67 #define OPTDATA(base) (base ? &CssmData(base, base##Length) : NULL)
68
69 #define SSBLOB(Type, name) makeBlob<Type>(DATA(name))
70
71 #define COPY_IN(type,name) type *name, mach_msg_type_number_t name##Length, type *name##Base
72 #define COPY_OUT(type,name) \
73 type **name, mach_msg_type_number_t *name##Length, type **name##Base
74
75
76 using LowLevelMemoryUtilities::increment;
77 using LowLevelMemoryUtilities::difference;
78
79
80 //
81 // Setup/Teardown functions.
82 //
83 kern_return_t ucsp_server_setup(UCSP_ARGS, mach_port_t taskPort, ClientSetupInfo info, const char *identity)
84 {
85 BEGIN_IPCN
86 Server::active().setupConnection(Server::connectNewProcess, servicePort, replyPort,
87 taskPort, auditToken, &info, identity);
88 END_IPCN(CSSM)
89 return KERN_SUCCESS;
90 }
91
92 kern_return_t ucsp_server_setupNew(UCSP_ARGS, mach_port_t taskPort,
93 ClientSetupInfo info, const char *identity,
94 mach_port_t *newServicePort)
95 {
96 BEGIN_IPCN
97 try {
98 RefPointer<Session> session = new DynamicSession(taskPort);
99 Server::active().setupConnection(Server::connectNewSession, session->servicePort(), replyPort,
100 taskPort, auditToken, &info, identity);
101 *newServicePort = session->servicePort();
102 } catch (const MachPlusPlus::Error &err) {
103 switch (err.error) {
104 case BOOTSTRAP_SERVICE_ACTIVE:
105 MacOSError::throwMe(errSessionAuthorizationDenied); // translate
106 default:
107 throw;
108 }
109 }
110 END_IPCN(CSSM)
111 return KERN_SUCCESS;
112 }
113
114 kern_return_t ucsp_server_setupThread(UCSP_ARGS, mach_port_t taskPort)
115 {
116 BEGIN_IPCN
117 Server::active().setupConnection(Server::connectNewThread, servicePort, replyPort,
118 taskPort, auditToken);
119 END_IPCN(CSSM)
120 return KERN_SUCCESS;
121 }
122
123
124 kern_return_t ucsp_server_teardown(UCSP_ARGS)
125 {
126 BEGIN_IPCN
127 Server::active().endConnection(replyPort);
128 END_IPCN(CSSM)
129 return KERN_SUCCESS;
130 }
131
132
133 //
134 // Common database operations
135 //
136 kern_return_t ucsp_server_authenticateDb(UCSP_ARGS, DbHandle db,
137 CSSM_DB_ACCESS_TYPE accessType, COPY_IN(AccessCredentials, cred))
138 {
139 BEGIN_IPC
140 secdebug("dl", "authenticateDb");
141 relocate(cred, credBase, credLength);
142 // ignoring accessType
143 Server::database(db)->authenticate(accessType, cred);
144 END_IPC(DL)
145 }
146
147 kern_return_t ucsp_server_releaseDb(UCSP_ARGS, DbHandle db)
148 {
149 BEGIN_IPC
150 connection.process().kill(*Server::database(db));
151 END_IPC(DL)
152 }
153
154
155 kern_return_t ucsp_server_getDbName(UCSP_ARGS, DbHandle db, char name[PATH_MAX])
156 {
157 BEGIN_IPC
158 string result = Server::database(db)->dbName();
159 assert(result.length() < PATH_MAX);
160 memcpy(name, result.c_str(), result.length() + 1);
161 END_IPC(DL)
162 }
163
164 kern_return_t ucsp_server_setDbName(UCSP_ARGS, DbHandle db, const char *name)
165 {
166 BEGIN_IPC
167 Server::database(db)->dbName(name);
168 END_IPC(DL)
169 }
170
171
172 //
173 // External database interface
174 //
175 kern_return_t ucsp_server_openToken(UCSP_ARGS, uint32 ssid, FilePath name,
176 COPY_IN(AccessCredentials, accessCredentials), DbHandle *db)
177 {
178 BEGIN_IPC
179 relocate(accessCredentials, accessCredentialsBase, accessCredentialsLength);
180 *db = (new TokenDatabase(ssid, connection.process(), name, accessCredentials))->handle();
181 END_IPC(DL)
182 }
183
184 kern_return_t ucsp_server_findFirst(UCSP_ARGS, DbHandle db,
185 COPY_IN(CssmQuery, query),
186 COPY_IN(CssmDbRecordAttributeData, inAttributes),
187 COPY_OUT(CssmDbRecordAttributeData, outAttributes),
188 boolean_t getData,
189 DATA_OUT(data), KeyHandle *hKey, SearchHandle *hSearch, RecordHandle *hRecord)
190 {
191 BEGIN_IPC
192 relocate(query, queryBase, queryLength);
193 relocate(inAttributes, inAttributesBase, inAttributesLength);
194
195 RefPointer<Database::Search> search;
196 RefPointer<Database::Record> record;
197 RefPointer<Key> key;
198 CssmData outData; //OutputData outData(data, dataLength);
199 CssmDbRecordAttributeData *outAttrs; mach_msg_type_number_t outAttrsLength;
200 Server::database(db)->findFirst(*query, inAttributes, inAttributesLength,
201 getData ? &outData : NULL, key, search, record, outAttrs, outAttrsLength);
202
203 // handle nothing-found case without exceptions
204 if (!record) {
205 *hRecord = noRecord;
206 *hSearch = noSearch;
207 *hKey = noKey;
208 } else {
209 // return handles
210 *hRecord = record->handle();
211 *hSearch = search->handle();
212 *hKey = key ? key->handle() : noKey;
213
214 // return attributes (assumes relocated flat blob)
215 flips(outAttrs, outAttributes, outAttributesBase);
216 *outAttributesLength = outAttrsLength;
217
218 // return data (temporary fix)
219 if (getData) {
220 *data = outData.data();
221 *dataLength = outData.length();
222 }
223 }
224 END_IPC(DL)
225 }
226
227 kern_return_t ucsp_server_findNext(UCSP_ARGS, SearchHandle hSearch,
228 COPY_IN(CssmDbRecordAttributeData, inAttributes),
229 COPY_OUT(CssmDbRecordAttributeData, outAttributes),
230 boolean_t getData, DATA_OUT(data), KeyHandle *hKey,
231 RecordHandle *hRecord)
232 {
233 BEGIN_IPC
234 relocate(inAttributes, inAttributesBase, inAttributesLength);
235 RefPointer<Database::Search> search =
236 Server::find<Database::Search>(hSearch, CSSMERR_DL_INVALID_RESULTS_HANDLE);
237 RefPointer<Database::Record> record;
238 RefPointer<Key> key;
239 CssmData outData; //OutputData outData(data, dataLength);
240 CssmDbRecordAttributeData *outAttrs; mach_msg_type_number_t outAttrsLength;
241 search->database().findNext(search, inAttributes, inAttributesLength,
242 getData ? &outData : NULL, key, record, outAttrs, outAttrsLength);
243
244 // handle nothing-found case without exceptions
245 if (!record) {
246 *hRecord = noRecord;
247 *hKey = noKey;
248 } else {
249 // return handles
250 *hRecord = record->handle();
251 *hKey = key ? key->handle() : noKey;
252
253 // return attributes (assumes relocated flat blob)
254 flips(outAttrs, outAttributes, outAttributesBase);
255 *outAttributesLength = outAttrsLength;
256
257 // return data (temporary fix)
258 if (getData) {
259 *data = outData.data();
260 *dataLength = outData.length();
261 }
262 }
263 END_IPC(DL)
264 }
265
266 kern_return_t ucsp_server_findRecordHandle(UCSP_ARGS, RecordHandle hRecord,
267 COPY_IN(CssmDbRecordAttributeData, inAttributes),
268 COPY_OUT(CssmDbRecordAttributeData, outAttributes),
269 boolean_t getData, DATA_OUT(data), KeyHandle *hKey)
270 {
271 BEGIN_IPC
272 relocate(inAttributes, inAttributesBase, inAttributesLength);
273 RefPointer<Database::Record> record =
274 Server::find<Database::Record>(hRecord, CSSMERR_DL_INVALID_RECORD_UID);
275 RefPointer<Key> key;
276 CssmData outData; //OutputData outData(data, dataLength);
277 CssmDbRecordAttributeData *outAttrs; mach_msg_type_number_t outAttrsLength;
278 record->database().findRecordHandle(record, inAttributes, inAttributesLength,
279 getData ? &outData : NULL, key, outAttrs, outAttrsLength);
280
281 // return handles
282 *hKey = key ? key->handle() : noKey;
283
284 // return attributes (assumes relocated flat blob)
285 flips(outAttrs, outAttributes, outAttributesBase);
286 *outAttributesLength = outAttrsLength;
287
288 // return data (temporary fix)
289 if (getData) {
290 *data = outData.data();
291 *dataLength = outData.length();
292 }
293 END_IPC(DL)
294 }
295
296 kern_return_t ucsp_server_insertRecord(UCSP_ARGS, DbHandle db, CSSM_DB_RECORDTYPE recordType,
297 COPY_IN(CssmDbRecordAttributeData, attributes), DATA_IN(data), RecordHandle *record)
298 {
299 BEGIN_IPC
300 relocate(attributes, attributesBase, attributesLength);
301 Server::database(db)->insertRecord(recordType, attributes, attributesLength,
302 DATA(data), *record);
303 END_IPC(DL)
304 }
305
306 kern_return_t ucsp_server_modifyRecord(UCSP_ARGS, DbHandle db, RecordHandle *hRecord,
307 CSSM_DB_RECORDTYPE recordType, COPY_IN(CssmDbRecordAttributeData, attributes),
308 boolean_t setData, DATA_IN(data), CSSM_DB_MODIFY_MODE modifyMode)
309 {
310 BEGIN_IPC
311 relocate(attributes, attributesBase, attributesLength);
312 CssmData newData(DATA(data));
313 RefPointer<Database::Record> record =
314 Server::find<Database::Record>(*hRecord, CSSMERR_DL_INVALID_RECORD_UID);
315 Server::database(db)->modifyRecord(recordType, record, attributes, attributesLength,
316 setData ? &newData : NULL, modifyMode);
317 // note that the record handle presented to the client never changes here
318 // (we could, but have no reason to - our record handles are just always up to date)
319 END_IPC(DL)
320 }
321
322 kern_return_t ucsp_server_deleteRecord(UCSP_ARGS, DbHandle db, RecordHandle hRecord)
323 {
324 BEGIN_IPC
325 Server::database(db)->deleteRecord(
326 Server::find<Database::Record>(hRecord, CSSMERR_DL_INVALID_RECORD_UID));
327 END_IPC(DL)
328 }
329
330 kern_return_t ucsp_server_releaseSearch(UCSP_ARGS, SearchHandle hSearch)
331 {
332 BEGIN_IPC
333 RefPointer<Database::Search> search = Server::find<Database::Search>(hSearch, 0);
334 search->database().releaseSearch(*search);
335 END_IPC(DL)
336 }
337
338 kern_return_t ucsp_server_releaseRecord(UCSP_ARGS, RecordHandle hRecord)
339 {
340 BEGIN_IPC
341 RefPointer<Database::Record> record = Server::find<Database::Record>(hRecord, 0);
342 record->database().releaseRecord(*record);
343 END_IPC(DL)
344 }
345
346 kern_return_t ucsp_server_getRecordFromHandle(UCSP_ARGS, RecordHandle record,
347 COPY_IN(CssmDbRecordAttributeData, inAttributes),
348 COPY_OUT(CssmDbRecordAttributeData, outAttributes),
349 boolean_t getData,
350 DATA_OUT(data))
351 {
352 BEGIN_IPC
353 secdebug("dl", "getRecordFromHandle");
354 relocate(inAttributes, inAttributesBase, inAttributesLength);
355 // @@@
356 END_IPC(DL)
357 }
358
359
360 //
361 // Internal database management
362 //
363 kern_return_t ucsp_server_createDb(UCSP_ARGS, DbHandle *db,
364 COPY_IN(DLDbFlatIdentifier, ident),
365 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
366 DBParameters params)
367 {
368 BEGIN_IPC
369 relocate(cred, credBase, credLength);
370 relocate(owner, ownerBase, ownerLength);
371 relocate(ident, identBase, identLength);
372 *db = (new KeychainDatabase(*ident, params, connection.process(), cred, owner))->handle();
373 END_IPC(DL)
374 }
375
376 // keychain synchronization
377 // @@@ caller should be required to call decodeDb() to get a DbHandle
378 // instead of passing the blob itself
379 kern_return_t ucsp_server_cloneDbForSync(UCSP_ARGS, DATA_IN(blob),
380 DbHandle srcDb, DATA_IN(agentData), DbHandle *newDb)
381 {
382 BEGIN_IPC
383 RefPointer<KeychainDatabase> srcKC = Server::keychain(srcDb);
384 *newDb = (new KeychainDatabase(*srcKC, connection.process(),
385 SSBLOB(DbBlob, blob), DATA(agentData)))->handle();
386 END_IPC(DL)
387 }
388
389 kern_return_t ucsp_server_commitDbForSync(UCSP_ARGS, DbHandle srcDb,
390 DbHandle cloneDb, DATA_OUT(blob))
391 {
392 BEGIN_IPC
393 RefPointer<KeychainDatabase> srcKC = Server::keychain(srcDb);
394 RefPointer<KeychainDatabase> cloneKC = Server::keychain(cloneDb);
395 srcKC->commitSecretsForSync(*cloneKC);
396
397 // re-encode blob for convenience
398 if (blob && blobLength) {
399 DbBlob *dbBlob = srcKC->blob();
400 *blob = dbBlob;
401 *blobLength = dbBlob->length();
402 } else {
403 secdebug("kcrecode", "No blob can be returned to client");
404 }
405 END_IPC(DL)
406 }
407
408 kern_return_t ucsp_server_decodeDb(UCSP_ARGS, DbHandle *db,
409 COPY_IN(DLDbFlatIdentifier, ident), COPY_IN(AccessCredentials, cred), DATA_IN(blob))
410 {
411 BEGIN_IPC
412 relocate(cred, credBase, credLength);
413 relocate(ident, identBase, identLength);
414 *db = (new KeychainDatabase(*ident, SSBLOB(DbBlob, blob),
415 connection.process(), cred))->handle();
416 END_IPC(DL)
417 }
418
419 kern_return_t ucsp_server_encodeDb(UCSP_ARGS, DbHandle db, DATA_OUT(blob))
420 {
421 BEGIN_IPC
422 DbBlob *dbBlob = Server::keychain(db)->blob(); // memory owned by database
423 *blob = dbBlob;
424 *blobLength = dbBlob->length();
425 END_IPC(DL)
426 }
427
428 kern_return_t ucsp_server_setDbParameters(UCSP_ARGS, DbHandle db, DBParameters params)
429 {
430 BEGIN_IPC
431 Server::keychain(db)->setParameters(params);
432 END_IPC(DL)
433 }
434
435 kern_return_t ucsp_server_getDbParameters(UCSP_ARGS, DbHandle db, DBParameters *params)
436 {
437 BEGIN_IPC
438 Server::keychain(db)->getParameters(*params);
439 END_IPC(DL)
440 }
441
442 kern_return_t ucsp_server_changePassphrase(UCSP_ARGS, DbHandle db,
443 COPY_IN(AccessCredentials, cred))
444 {
445 BEGIN_IPC
446 relocate(cred, credBase, credLength);
447 Server::keychain(db)->changePassphrase(cred);
448 END_IPC(DL)
449 }
450
451 kern_return_t ucsp_server_lockAll (UCSP_ARGS, boolean_t)
452 {
453 BEGIN_IPC
454 connection.session().processLockAll();
455 END_IPC(DL)
456 }
457
458 kern_return_t ucsp_server_unlockDb(UCSP_ARGS, DbHandle db)
459 {
460 BEGIN_IPC
461 Server::keychain(db)->unlockDb();
462 END_IPC(DL)
463 }
464
465 kern_return_t ucsp_server_unlockDbWithPassphrase(UCSP_ARGS, DbHandle db, DATA_IN(passphrase))
466 {
467 BEGIN_IPC
468 Server::keychain(db)->unlockDb(DATA(passphrase));
469 END_IPC(DL)
470 }
471
472 kern_return_t ucsp_server_isLocked(UCSP_ARGS, DbHandle db, boolean_t *locked)
473 {
474 BEGIN_IPC
475 *locked = Server::database(db)->isLocked();
476 END_IPC(DL)
477 }
478
479
480 //
481 // Key management
482 //
483 kern_return_t ucsp_server_encodeKey(UCSP_ARGS, KeyHandle keyh, DATA_OUT(blob),
484 boolean_t wantUid, DATA_OUT(uid))
485 {
486 BEGIN_IPC
487 RefPointer<Key> gKey = Server::key(keyh);
488 if (KeychainKey *key = dynamic_cast<KeychainKey *>(gKey.get())) {
489 KeyBlob *keyBlob = key->blob(); // still owned by key
490 *blob = keyBlob;
491 *blobLength = keyBlob->length();
492 if (wantUid) { // uid generation is not implemented
493 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
494 } else {
495 *uidLength = 0; // do not return this
496 }
497 } else { // not a KeychainKey
498 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE);
499 }
500 END_IPC(CSP)
501 }
502
503 kern_return_t ucsp_server_decodeKey(UCSP_ARGS, KeyHandle *keyh, CssmKey::Header *header,
504 DbHandle db, DATA_IN(blob))
505 {
506 BEGIN_IPC
507 RefPointer<Key> key = new KeychainKey(*Server::keychain(db), SSBLOB(KeyBlob, blob));
508 key->returnKey(*keyh, *header);
509 flip(*header);
510 END_IPC(CSP)
511 }
512
513 // keychain synchronization
514 kern_return_t ucsp_server_recodeKey(UCSP_ARGS, DbHandle oldDb, KeyHandle keyh,
515 DbHandle newDb, DATA_OUT(newBlob))
516 {
517 BEGIN_IPC
518 // If the old key is passed in as DATA_IN(oldBlob):
519 // RefPointer<KeychainKey> key = new KeychainKey(*Server::keychain(oldDb), SSBLOB(KeyBlob, oldBlob));
520 RefPointer<Key> key = Server::key(keyh);
521 if (KeychainKey *kckey = dynamic_cast<KeychainKey *>(key.get())) {
522 KeyBlob *blob = Server::keychain(newDb)->recodeKey(*kckey);
523 *newBlob = blob;
524 *newBlobLength = blob->length();
525 Server::releaseWhenDone(*newBlob);
526 // @@@ stop leaking blob
527 } else { // not a KeychainKey
528 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE);
529 }
530 END_IPC(CSP)
531 }
532
533 kern_return_t ucsp_server_releaseKey(UCSP_ARGS, KeyHandle keyh)
534 {
535 BEGIN_IPC
536 RefPointer<Key> key = Server::key(keyh);
537 key->database().releaseKey(*key);
538 END_IPC(CSP)
539 }
540
541 kern_return_t ucsp_server_queryKeySizeInBits(UCSP_ARGS, KeyHandle keyh, CSSM_KEY_SIZE *length)
542 {
543 BEGIN_IPC
544 RefPointer<Key> key = Server::key(keyh);
545 key->database().queryKeySizeInBits(*key, CssmKeySize::overlay(*length));
546 END_IPC(CSP)
547 }
548
549 kern_return_t ucsp_server_getOutputSize(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh,
550 uint32 inputSize, boolean_t encrypt, uint32 *outputSize)
551 {
552 BEGIN_IPC
553 relocate(context, contextBase, attributes, attrSize);
554 RefPointer<Key> key = Server::key(keyh);
555 key->database().getOutputSize(context, *key, inputSize, encrypt, *outputSize);
556 END_IPC(CSP)
557 }
558
559 kern_return_t ucsp_server_getKeyDigest(UCSP_ARGS, KeyHandle key, DATA_OUT(digest))
560 {
561 BEGIN_IPC
562 CssmData digestData = Server::key(key)->canonicalDigest();
563 *digest = digestData.data();
564 *digestLength = digestData.length();
565 END_IPC(CSP)
566 }
567
568
569 //
570 // Signatures and MACs
571 //
572 kern_return_t ucsp_server_generateSignature(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh,
573 CSSM_ALGORITHMS signOnlyAlgorithm, DATA_IN(data), DATA_OUT(signature))
574 {
575 BEGIN_IPC
576 relocate(context, contextBase, attributes, attrSize);
577 RefPointer<Key> key = Server::key(keyh);
578 OutputData sigData(signature, signatureLength);
579 key->database().generateSignature(context, *key, signOnlyAlgorithm,
580 DATA(data), sigData);
581 END_IPC(CSP)
582 }
583
584 kern_return_t ucsp_server_verifySignature(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh,
585 CSSM_ALGORITHMS verifyOnlyAlgorithm, DATA_IN(data), DATA_IN(signature))
586 {
587 BEGIN_IPC
588 relocate(context, contextBase, attributes, attrSize);
589 RefPointer<Key> key = Server::key(keyh);
590 key->database().verifySignature(context, *key, verifyOnlyAlgorithm,
591 DATA(data), DATA(signature));
592 END_IPC(CSP)
593 }
594
595 kern_return_t ucsp_server_generateMac(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh,
596 DATA_IN(data), DATA_OUT(mac))
597 {
598 BEGIN_IPC
599 relocate(context, contextBase, attributes, attrSize);
600 RefPointer<Key> key = Server::key(keyh);
601 OutputData macData(mac, macLength);
602 key->database().generateMac(context, *key, DATA(data), macData);
603 END_IPC(CSP)
604 }
605
606 kern_return_t ucsp_server_verifyMac(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh,
607 DATA_IN(data), DATA_IN(mac))
608 {
609 BEGIN_IPC
610 relocate(context, contextBase, attributes, attrSize);
611 RefPointer<Key> key = Server::key(keyh);
612 key->database().verifyMac(context, *key, DATA(data), DATA(mac));
613 END_IPC(CSP)
614 }
615
616
617 //
618 // Encryption/Decryption
619 //
620 kern_return_t ucsp_server_encrypt(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh,
621 DATA_IN(clear), DATA_OUT(cipher))
622 {
623 BEGIN_IPC
624 relocate(context, contextBase, attributes, attrSize);
625 RefPointer<Key> key = Server::key(keyh);
626 OutputData cipherOut(cipher, cipherLength);
627 key->database().encrypt(context, *key, DATA(clear), cipherOut);
628 END_IPC(CSP)
629 }
630
631 kern_return_t ucsp_server_decrypt(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh,
632 DATA_IN(cipher), DATA_OUT(clear))
633 {
634 BEGIN_IPC
635 relocate(context, contextBase, attributes, attrSize);
636 RefPointer<Key> key = Server::key(keyh);
637 OutputData clearOut(clear, clearLength);
638 key->database().decrypt(context, *key, DATA(cipher), clearOut);
639 END_IPC(CSP)
640 }
641
642
643 //
644 // Key generation
645 //
646 kern_return_t ucsp_server_generateKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS,
647 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
648 uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader)
649 {
650 BEGIN_IPC
651 relocate(context, contextBase, attributes, attrSize);
652 relocate(cred, credBase, credLength);
653 relocate(owner, ownerBase, ownerLength);
654 //@@@ preliminary interpretation - will get "type handle"
655 RefPointer<Database> database =
656 Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT);
657 RefPointer<Key> key;
658 database->generateKey(context, cred, owner, usage, attrs, key);
659 key->returnKey(*newKey, *newHeader);
660 flip(*newHeader);
661 END_IPC(CSP)
662 }
663
664 kern_return_t ucsp_server_generateKeyPair(UCSP_ARGS, DbHandle db, CONTEXT_ARGS,
665 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
666 uint32 pubUsage, uint32 pubAttrs, uint32 privUsage, uint32 privAttrs,
667 KeyHandle *pubKey, CssmKey::Header *pubHeader, KeyHandle *privKey, CssmKey::Header *privHeader)
668 {
669 BEGIN_IPC
670 relocate(context, contextBase, attributes, attrSize);
671 relocate(cred, credBase, credLength);
672 relocate(owner, ownerBase, ownerLength);
673 RefPointer<Database> database =
674 Server::optionalDatabase(db, (privAttrs | pubAttrs) & CSSM_KEYATTR_PERMANENT);
675 RefPointer<Key> pub, priv;
676 database->generateKey(context, cred, owner,
677 pubUsage, pubAttrs, privUsage, privAttrs, pub, priv);
678 pub->returnKey(*pubKey, *pubHeader);
679 flip(*pubHeader);
680 priv->returnKey(*privKey, *privHeader);
681 flip(*privHeader);
682 END_IPC(CSP)
683 }
684
685
686 //
687 // Key wrapping and unwrapping
688 //
689 kern_return_t ucsp_server_wrapKey(UCSP_ARGS, CONTEXT_ARGS, KeyHandle hWrappingKey,
690 COPY_IN(AccessCredentials, cred), KeyHandle hKeyToBeWrapped,
691 DATA_IN(descriptiveData), CssmKey *wrappedKey, DATA_OUT(keyData))
692 {
693 BEGIN_IPC
694 relocate(context, contextBase, attributes, attrSize);
695 relocate(cred, credBase, credLength);
696 RefPointer<Key> subjectKey = Server::key(hKeyToBeWrapped);
697 RefPointer<Key> wrappingKey = Server::optionalKey(hWrappingKey);
698 if ((context.algorithm() == CSSM_ALGID_NONE && subjectKey->attribute(CSSM_KEYATTR_SENSITIVE))
699 || !subjectKey->attribute(CSSM_KEYATTR_EXTRACTABLE))
700 CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK);
701 pickDb(subjectKey, wrappingKey)->wrapKey(context, cred, wrappingKey, *subjectKey, DATA(descriptiveData), *wrappedKey);
702
703 // transmit key data back as a separate blob
704 OutputData keyDatas(keyData, keyDataLength);
705 keyDatas = wrappedKey->keyData();
706 flip(*wrappedKey);
707 END_IPC(CSP)
708 }
709
710 kern_return_t ucsp_server_unwrapKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS,
711 KeyHandle hWrappingKey, COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
712 KeyHandle hPublicKey, CssmKey wrappedKey, DATA_IN(wrappedKeyData),
713 CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, DATA_OUT(descriptiveData),
714 KeyHandle *newKey, CssmKey::Header *newHeader)
715 {
716 BEGIN_IPC
717 relocate(context, contextBase, attributes, attrSize);
718 flip(wrappedKey);
719 wrappedKey.keyData() = DATA(wrappedKeyData);
720 relocate(cred, credBase, credLength);
721 relocate(owner, ownerBase, ownerLength);
722 OutputData descriptiveDatas(descriptiveData, descriptiveDataLength);
723 RefPointer<Key> wrappingKey = Server::optionalKey(hWrappingKey);
724 RefPointer<Key> unwrappedKey;
725 pickDb(Server::optionalDatabase(db), wrappingKey)->unwrapKey(context, cred, owner,
726 wrappingKey, Server::optionalKey(hPublicKey),
727 usage, attrs, wrappedKey, unwrappedKey, descriptiveDatas);
728 unwrappedKey->returnKey(*newKey, *newHeader);
729 flip(*newHeader);
730 END_IPC(CSP)
731 }
732
733
734 //
735 // Key derivation.
736 //
737 // Note that the "param" argument can have structure. The walker for the
738 // (artificial) POD CssmDeriveData handles those that are known; if you add
739 // an algorithm with structured param, you need to add a case there.
740 //
741 kern_return_t ucsp_server_deriveKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, KeyHandle hKey,
742 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
743 COPY_IN(CssmDeriveData, paramInput), DATA_OUT(paramOutput),
744 uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader)
745 {
746 BEGIN_IPC
747 relocate(context, contextBase, attributes, attrSize);
748 relocate(cred, credBase, credLength);
749 relocate(owner, ownerBase, ownerLength);
750 relocate(paramInput, paramInputBase, paramInputLength);
751 if (!paramInput || paramInput->algorithm != context.algorithm())
752 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); // client layer fault
753
754 RefPointer<Database> database =
755 Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT);
756 RefPointer<Key> key = Server::optionalKey(hKey);
757 CssmData *param = paramInput ? &paramInput->baseData : NULL;
758 RefPointer<Key> derivedKey;
759 pickDb(Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT),
760 key)->deriveKey(context, key, cred, owner, param, usage, attrs, derivedKey);
761 derivedKey->returnKey(*newKey, *newHeader);
762 flip(*newHeader);
763 if (param && param->length()) {
764 if (!param->data()) // CSP screwed up
765 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
766 if (paramInputLength) // using incoming buffer; make a copy
767 *param = CssmAutoData(Server::csp().allocator(), *param).release();
768 OutputData(paramOutput, paramOutputLength) = *param; // return the data
769 }
770 END_IPC(CSP)
771 }
772
773
774 //
775 // Random generation
776 //
777 kern_return_t ucsp_server_generateRandom(UCSP_ARGS, uint32 ssid, CONTEXT_ARGS, DATA_OUT(data))
778 {
779 BEGIN_IPC
780 relocate(context, contextBase, attributes, attrSize);
781 if (ssid)
782 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
783
784 // default version (use /dev/random)
785 Allocator &allocator = Allocator::standard(Allocator::sensitive);
786 if (size_t bytes = context.getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE)) {
787 void *buffer = allocator.malloc(bytes);
788 Server::active().random(buffer, bytes);
789 *data = buffer;
790 *dataLength = bytes;
791 Server::releaseWhenDone(allocator, buffer);
792 }
793 END_IPC(CSP)
794 }
795
796
797 //
798 // ACL management.
799 // Watch out for the memory-management tap-dance.
800 //
801 kern_return_t ucsp_server_getOwner(UCSP_ARGS, AclKind kind, KeyHandle key,
802 COPY_OUT(AclOwnerPrototype, ownerOut))
803 {
804 BEGIN_IPC
805 AclOwnerPrototype owner;
806 Server::aclBearer(kind, key).getOwner(owner); // allocates memory in owner
807 Copier<AclOwnerPrototype> owners(&owner, Allocator::standard()); // make flat copy
808 { ChunkFreeWalker free; walk(free, owner); } // release chunked original
809 *ownerOutLength = owners.length();
810 flips(owners.value(), ownerOut, ownerOutBase);
811 Server::releaseWhenDone(owners.keep()); // throw flat copy out when done
812 END_IPC(CSP)
813 }
814
815 kern_return_t ucsp_server_setOwner(UCSP_ARGS, AclKind kind, KeyHandle key,
816 COPY_IN(AccessCredentials, cred), COPY_IN(AclOwnerPrototype, owner))
817 {
818 BEGIN_IPC
819 relocate(cred, credBase, credLength);
820 relocate(owner, ownerBase, ownerLength);
821 Server::aclBearer(kind, key).changeOwner(*owner, cred);
822 END_IPC(CSP)
823 }
824
825 kern_return_t ucsp_server_getAcl(UCSP_ARGS, AclKind kind, KeyHandle key,
826 boolean_t haveTag, const char *tag,
827 uint32 *countp, COPY_OUT(AclEntryInfo, acls))
828 {
829 BEGIN_IPC
830 uint32 count;
831 AclEntryInfo *aclList;
832 Server::aclBearer(kind, key).getAcl(haveTag ? tag : NULL, count, aclList);
833 *countp = count;
834 Copier<AclEntryInfo> aclsOut(aclList, count); // make flat copy
835
836 { // release the chunked memory originals
837 ChunkFreeWalker free;
838 for (uint32 n = 0; n < count; n++)
839 walk(free, aclList[n]);
840
841 // release the memory allocated for the list itself when we are done
842 Allocator::standard().free (aclList);
843 }
844
845 // set result (note: this is *almost* flips(), but on an array)
846 *aclsLength = aclsOut.length();
847 *acls = *aclsBase = aclsOut;
848 if (flipClient()) {
849 FlipWalker w;
850 for (uint32 n = 0; n < count; n++)
851 walk(w, (*acls)[n]);
852 w.doFlips();
853 Flippers::flip(*aclsBase);
854 }
855 Server::releaseWhenDone(aclsOut.keep());
856 END_IPC(CSP)
857 }
858
859 kern_return_t ucsp_server_changeAcl(UCSP_ARGS, AclKind kind, KeyHandle key,
860 COPY_IN(AccessCredentials, cred), CSSM_ACL_EDIT_MODE mode, CSSM_ACL_HANDLE handle,
861 COPY_IN(AclEntryInput, acl))
862 {
863 BEGIN_IPC
864 relocate(cred, credBase, credLength);
865 relocate(acl, aclBase, aclLength);
866 Server::aclBearer(kind, key).changeAcl(AclEdit(mode, handle, acl), cred);
867 END_IPC(CSP)
868 }
869
870
871 //
872 // Login/Logout
873 //
874 kern_return_t ucsp_server_login(UCSP_ARGS, COPY_IN(AccessCredentials, cred), DATA_IN(name))
875 {
876 BEGIN_IPC
877 relocate(cred, credBase, credLength);
878 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
879 END_IPC(CSP)
880 }
881
882 kern_return_t ucsp_server_logout(UCSP_ARGS)
883 {
884 BEGIN_IPC
885 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
886 END_IPC(CSP)
887 }
888
889
890 //
891 // Miscellaneous CSP-related calls
892 //
893 kern_return_t ucsp_server_getStatistics(UCSP_ARGS, uint32 ssid, CSPOperationalStatistics *statistics)
894 {
895 BEGIN_IPC
896 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
897 END_IPC(CSP)
898 }
899
900 kern_return_t ucsp_server_getTime(UCSP_ARGS, uint32 ssid, CSSM_ALGORITHMS algorithm, DATA_OUT(data))
901 {
902 BEGIN_IPC
903 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
904 END_IPC(CSP)
905 }
906
907 kern_return_t ucsp_server_getCounter(UCSP_ARGS, uint32 ssid, DATA_OUT(data))
908 {
909 BEGIN_IPC
910 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
911 END_IPC(CSP)
912 }
913
914 kern_return_t ucsp_server_selfVerify(UCSP_ARGS, uint32 ssid)
915 {
916 BEGIN_IPC
917 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
918 END_IPC(CSP)
919 }
920
921
922 //
923 // Passthrough calls (separate for CSP and DL passthroughs)
924 //
925 kern_return_t ucsp_server_cspPassThrough(UCSP_ARGS, uint32 ssid, uint32 id, CONTEXT_ARGS,
926 KeyHandle hKey, DATA_IN(inData), DATA_OUT(outData))
927 {
928 BEGIN_IPC
929 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
930 END_IPC(CSP)
931 }
932
933 kern_return_t ucsp_server_dlPassThrough(UCSP_ARGS, uint32 ssid, uint32 id,
934 DATA_IN(inData), DATA_OUT(outData))
935 {
936 BEGIN_IPC
937 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
938 END_IPC(DL)
939 }
940
941
942 //
943 // Database key management.
944 // ExtractMasterKey looks vaguely like a key derivation operation, and is in fact
945 // presented by the CSPDL's CSSM layer as such.
946 //
947 kern_return_t ucsp_server_extractMasterKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, DbHandle sourceDb,
948 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
949 uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader)
950 {
951 BEGIN_IPC
952 context.postIPC(contextBase, attributes);
953 relocate(cred, credBase, credLength);
954 relocate(owner, ownerBase, ownerLength);
955 RefPointer<KeychainDatabase> keychain = Server::keychain(sourceDb);
956 RefPointer<Key> masterKey = keychain->extractMasterKey(
957 *Server::optionalDatabase(db, attrs & CSSM_KEYATTR_PERMANENT),
958 cred, owner, usage, attrs);
959 masterKey->returnKey(*newKey, *newHeader);
960 flip(*newHeader);
961 END_IPC(CSP)
962 }
963
964
965 //
966 // Authorization subsystem support
967 //
968 kern_return_t ucsp_server_authorizationCreate(UCSP_ARGS,
969 COPY_IN(AuthorizationItemSet, inRights),
970 uint32 flags,
971 COPY_IN(AuthorizationItemSet, inEnvironment),
972 AuthorizationBlob *authorization)
973 {
974 BEGIN_IPC
975 relocate(inRights, inRightsBase, inRightsLength);
976 relocate(inEnvironment, inEnvironmentBase, inEnvironmentLength);
977 Authorization::AuthItemSet rights(inRights), environment(inEnvironment);
978
979 *rcode = connection.process().session().authCreate(rights, environment,
980 flags, *authorization, auditToken);
981 END_IPC(CSSM)
982 }
983
984 kern_return_t ucsp_server_authorizationRelease(UCSP_ARGS,
985 AuthorizationBlob authorization, uint32 flags)
986 {
987 BEGIN_IPC
988 connection.process().session().authFree(authorization, flags);
989 END_IPC(CSSM)
990 }
991
992 kern_return_t ucsp_server_authorizationCopyRights(UCSP_ARGS,
993 AuthorizationBlob authorization,
994 COPY_IN(AuthorizationItemSet, inRights),
995 uint32 flags,
996 COPY_IN(AuthorizationItemSet, inEnvironment),
997 COPY_OUT(AuthorizationItemSet, result))
998 {
999 BEGIN_IPC
1000 relocate(inRights, inRightsBase, inRightsLength);
1001 relocate(inEnvironment, inEnvironmentBase, inEnvironmentLength);
1002 Authorization::AuthItemSet rights(inRights), environment(inEnvironment), grantedRights;
1003 *rcode = connection.process().session().authGetRights(authorization,
1004 rights, environment, flags, grantedRights);
1005 if (result && resultLength)
1006 {
1007 size_t resultSize;
1008 grantedRights.copy(*result, resultSize);
1009 *resultLength = resultSize;
1010 *resultBase = *result;
1011 flips(*result, result, resultBase);
1012 Server::releaseWhenDone(*result);
1013 }
1014 END_IPC(CSSM)
1015 }
1016
1017 kern_return_t ucsp_server_authorizationCopyInfo(UCSP_ARGS,
1018 AuthorizationBlob authorization,
1019 AuthorizationString tag,
1020 COPY_OUT(AuthorizationItemSet, info))
1021 {
1022 BEGIN_IPC
1023 Authorization::AuthItemSet infoSet;
1024 *info = *infoBase = NULL;
1025 *infoLength = 0;
1026 *rcode = connection.process().session().authGetInfo(authorization,
1027 tag[0] ? tag : NULL, infoSet);
1028 if (*rcode == noErr) {
1029 size_t infoSize;
1030 infoSet.copy(*info, infoSize);
1031 *infoLength = infoSize;
1032 *infoBase = *info;
1033 flips(*info, info, infoBase);
1034 Server::releaseWhenDone(*info);
1035 }
1036 END_IPC(CSSM)
1037 }
1038
1039 kern_return_t ucsp_server_authorizationExternalize(UCSP_ARGS,
1040 AuthorizationBlob authorization, AuthorizationExternalForm *extForm)
1041 {
1042 BEGIN_IPC
1043 *rcode = connection.process().session().authExternalize(authorization, *extForm);
1044 END_IPC(CSSM)
1045 }
1046
1047 kern_return_t ucsp_server_authorizationInternalize(UCSP_ARGS,
1048 AuthorizationExternalForm extForm, AuthorizationBlob *authorization)
1049 {
1050 BEGIN_IPC
1051 *rcode = connection.process().session().authInternalize(extForm, *authorization);
1052 END_IPC(CSSM)
1053 }
1054
1055
1056 //
1057 // Session management subsystem
1058 //
1059 kern_return_t ucsp_server_getSessionInfo(UCSP_ARGS,
1060 SecuritySessionId *sessionId, SessionAttributeBits *attrs)
1061 {
1062 BEGIN_IPC
1063 Session &session = Session::find(*sessionId);
1064 *sessionId = session.handle();
1065 *attrs = session.attributes();
1066 END_IPC(CSSM)
1067 }
1068
1069 kern_return_t ucsp_server_setupSession(UCSP_ARGS,
1070 SessionCreationFlags flags, SessionAttributeBits attrs)
1071 {
1072 BEGIN_IPC
1073 Server::process().session().setupAttributes(flags, attrs);
1074 END_IPC(CSSM)
1075 }
1076
1077 kern_return_t ucsp_server_setSessionDistinguishedUid(UCSP_ARGS,
1078 SecuritySessionId sessionId, uid_t user)
1079 {
1080 BEGIN_IPC
1081 Session::find<DynamicSession>(sessionId).originatorUid(user);
1082 END_IPC(CSSM)
1083 }
1084
1085 kern_return_t ucsp_server_getSessionDistinguishedUid(UCSP_ARGS,
1086 SecuritySessionId sessionId, uid_t *user)
1087 {
1088 BEGIN_IPC
1089 *user = Session::find(sessionId).originatorUid();
1090 END_IPC(CSSM)
1091 }
1092
1093 kern_return_t ucsp_server_setSessionUserPrefs(UCSP_ARGS, SecuritySessionId sessionId, DATA_IN(userPrefs))
1094 {
1095 BEGIN_IPC
1096 CFRef<CFDataRef> data(CFDataCreate(NULL, (UInt8 *)userPrefs, userPrefsLength));
1097
1098 if (!data)
1099 {
1100 *rcode = errSessionValueNotSet;
1101 return 0;
1102 }
1103
1104 Session::find<DynamicSession>(sessionId).setUserPrefs(data);
1105 *rcode = 0;
1106
1107 END_IPC(CSSM)
1108 }
1109
1110
1111
1112 //
1113 // Notification core subsystem
1114 //
1115 kern_return_t ucsp_server_requestNotification(UCSP_ARGS, mach_port_t receiver, uint32 domain, uint32 events)
1116 {
1117 BEGIN_IPC
1118 connection.process().requestNotifications(receiver, domain, events);
1119 END_IPC(CSSM)
1120 }
1121
1122 kern_return_t ucsp_server_stopNotification(UCSP_ARGS, mach_port_t receiver)
1123 {
1124 BEGIN_IPC
1125 connection.process().stopNotifications(receiver);
1126 END_IPC(CSSM)
1127 }
1128
1129 kern_return_t ucsp_server_postNotification(mach_port_t serverPort, uint32 domain, uint32 event, DATA_IN(data))
1130 {
1131 BEGIN_IPCS
1132 Listener::notify(domain, event, DATA(data));
1133 END_IPCS()
1134 }
1135
1136
1137 //
1138 // AuthorizationDB modification
1139 //
1140 kern_return_t ucsp_server_authorizationdbGet(UCSP_ARGS, const char *rightname, DATA_OUT(rightDefinition))
1141 {
1142 BEGIN_IPC
1143 CFDictionaryRef rightDict;
1144
1145 *rcode = connection.process().session().authorizationdbGet(rightname, &rightDict);
1146
1147 if (!*rcode && rightDict)
1148 {
1149 CFRef<CFDataRef> data(CFPropertyListCreateXMLData (NULL, rightDict));
1150 CFRelease(rightDict);
1151 if (!data)
1152 return errAuthorizationInternal;
1153
1154 // @@@ copy data to avoid having to do a delayed cfrelease
1155 mach_msg_type_number_t length = CFDataGetLength(data);
1156 void *xmlData = Allocator::standard().malloc(length);
1157 memcpy(xmlData, CFDataGetBytePtr(data), length);
1158 Server::releaseWhenDone(xmlData);
1159
1160 *rightDefinition = xmlData;
1161 *rightDefinitionLength = length;
1162 }
1163 END_IPC(CSSM)
1164 }
1165
1166 kern_return_t ucsp_server_authorizationdbSet(UCSP_ARGS, AuthorizationBlob authorization, const char *rightname, DATA_IN(rightDefinition))
1167 {
1168 BEGIN_IPC
1169 CFRef<CFDataRef> data(CFDataCreate(NULL, (UInt8 *)rightDefinition, rightDefinitionLength));
1170
1171 if (!data)
1172 return errAuthorizationInternal;
1173
1174 CFRef<CFDictionaryRef> rightDefinition(static_cast<CFDictionaryRef>(CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListImmutable, NULL)));
1175
1176 if (!rightDefinition || (CFGetTypeID(rightDefinition) != CFDictionaryGetTypeID()))
1177 return errAuthorizationInternal;
1178
1179 *rcode = connection.process().session().authorizationdbSet(authorization, rightname, rightDefinition);
1180
1181 END_IPC(CSSM)
1182 }
1183
1184 kern_return_t ucsp_server_authorizationdbRemove(UCSP_ARGS, AuthorizationBlob authorization, const char *rightname)
1185 {
1186 BEGIN_IPC
1187 *rcode = connection.process().session().authorizationdbRemove(authorization, rightname);
1188 END_IPC(CSSM)
1189 }
1190
1191
1192 //
1193 // Miscellaneous administrative functions
1194 //
1195 kern_return_t ucsp_server_addCodeEquivalence(UCSP_ARGS, DATA_IN(oldHash), DATA_IN(newHash),
1196 const char *name, boolean_t forSystem)
1197 {
1198 BEGIN_IPC
1199 Server::codeSignatures().addLink(DATA(oldHash), DATA(newHash), name, forSystem);
1200 END_IPC(CSSM)
1201 }
1202
1203 kern_return_t ucsp_server_removeCodeEquivalence(UCSP_ARGS, DATA_IN(hash),
1204 const char *name, boolean_t forSystem)
1205 {
1206 BEGIN_IPC
1207 Server::codeSignatures().removeLink(DATA(hash), name, forSystem);
1208 END_IPC(CSSM)
1209 }
1210
1211 kern_return_t ucsp_server_setAlternateSystemRoot(UCSP_ARGS, const char *root)
1212 {
1213 BEGIN_IPC
1214 #if defined(NDEBUG)
1215 if (connection.process().uid() != 0)
1216 CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED);
1217 #endif //NDEBUG
1218 Server::codeSignatures().open((string(root) + EQUIVALENCEDBPATH).c_str());
1219 END_IPC(CSSM)
1220 }
1221
1222
1223 //
1224 // Child check-in service.
1225 // Note that this isn't using the standard argument pattern.
1226 //
1227 kern_return_t ucsp_server_childCheckIn(mach_port_t serverPort,
1228 mach_port_t servicePort, mach_port_t taskPort)
1229 {
1230 BEGIN_IPCS
1231 ServerChild::checkIn(servicePort, TaskPort(taskPort).pid());
1232 END_IPCS(mach_port_deallocate(mach_task_self(), taskPort))
1233 }