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