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