]> git.saurik.com Git - apple/securityd.git/blob - src/transition.cpp
0d1f9099afec74b3bffc729ea3c93520cf1c191c
[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 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26
27 //
28 // transition - SecurityServer IPC-to-class-methods transition layer
29 //
30 #include <securityd_client/ucsp.h>
31 #include "server.h"
32 #include "session.h"
33 #include "database.h"
34 #include "kcdatabase.h"
35 #include "kckey.h"
36 #include "transwalkers.h"
37 #include <mach/mach_error.h>
38
39 #include <CoreFoundation/CFDictionary.h>
40 #include <CoreFoundation/CFPropertyList.h>
41
42 //
43 // Bracket Macros
44 //
45 #define UCSP_ARGS mach_port_t servicePort, mach_port_t replyPort, security_token_t securityToken, \
46 CSSM_RETURN *rcode
47 #define CONTEXT_ARGS Context context, Pointer contextBase, Context::Attr *attributes, mach_msg_type_number_t attrSize
48
49 #define BEGIN_IPCN *rcode = CSSM_OK; try {
50 #define BEGIN_IPC BEGIN_IPCN RefPointer<Connection> connRef(&Server::connection(replyPort)); \
51 Connection &connection __attribute__((unused)) = *connRef;
52 #define END_IPC(base) END_IPCN(base) Server::requestComplete(); return KERN_SUCCESS;
53 #define END_IPCN(base) } \
54 catch (const CommonError &err) { *rcode = CssmError::cssmError(err, CSSM_ ## base ## _BASE_ERROR); } \
55 catch (const std::bad_alloc &) { *rcode = CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \
56 catch (Connection *conn) { *rcode = 0; } \
57 catch (...) { *rcode = CssmError::merge(CSSM_ERRCODE_INTERNAL_ERROR, CSSM_ ## base ## _BASE_ERROR); }
58
59 #define DATA_IN(base) void *base, mach_msg_type_number_t base##Length
60 #define DATA_OUT(base) void **base, mach_msg_type_number_t *base##Length
61 #define DATA(base) CssmData(base, base##Length)
62
63 #define COPY_IN(type,name) type *name, mach_msg_type_number_t name##Length, type *name##Base
64 #define COPY_OUT(type,name) \
65 type **name, mach_msg_type_number_t *name##Length, type **name##Base
66
67
68 using LowLevelMemoryUtilities::increment;
69 using LowLevelMemoryUtilities::difference;
70
71
72 //
73 // An OutputData object will take memory allocated within the SecurityServer,
74 // hand it to the MIG return-output parameters, and schedule it to be released
75 // after the MIG reply has been sent. It will also get rid of it in case of
76 // error.
77 //
78 class OutputData : public CssmData {
79 public:
80 OutputData(void **outP, mach_msg_type_number_t *outLength)
81 : mData(*outP), mLength(*outLength) { }
82 ~OutputData()
83 { mData = data(); mLength = length(); Server::releaseWhenDone(mData); }
84
85 void operator = (const CssmData &source)
86 { CssmData::operator = (source); }
87
88 private:
89 void * &mData;
90 mach_msg_type_number_t &mLength;
91 };
92
93
94 //
95 // Setup/Teardown functions.
96 //
97 kern_return_t ucsp_server_setup(UCSP_ARGS, mach_port_t taskPort, ClientSetupInfo info, const char *identity)
98 {
99 BEGIN_IPCN
100 Server::active().setupConnection(Server::connectNewProcess, servicePort, replyPort,
101 taskPort, securityToken, &info, identity);
102 END_IPCN(CSSM)
103 return KERN_SUCCESS;
104 }
105
106 kern_return_t ucsp_server_setupNew(UCSP_ARGS, mach_port_t taskPort,
107 ClientSetupInfo info, const char *identity,
108 mach_port_t *newServicePort)
109 {
110 BEGIN_IPCN
111 try {
112 RefPointer<Session> session = new DynamicSession(TaskPort(taskPort).bootstrap());
113 Server::active().setupConnection(Server::connectNewSession, session->servicePort(), replyPort,
114 taskPort, securityToken, &info, identity);
115 *newServicePort = session->servicePort();
116 } catch (const MachPlusPlus::Error &err) {
117 switch (err.error) {
118 case BOOTSTRAP_SERVICE_ACTIVE:
119 MacOSError::throwMe(errSessionAuthorizationDenied); // translate
120 default:
121 throw;
122 }
123 }
124 END_IPCN(CSSM)
125 return KERN_SUCCESS;
126 }
127
128 kern_return_t ucsp_server_setupThread(UCSP_ARGS, mach_port_t taskPort)
129 {
130 BEGIN_IPCN
131 Server::active().setupConnection(Server::connectNewThread, servicePort, replyPort,
132 taskPort, securityToken);
133 END_IPCN(CSSM)
134 return KERN_SUCCESS;
135 }
136
137
138 kern_return_t ucsp_server_teardown(UCSP_ARGS)
139 {
140 BEGIN_IPCN
141 Server::active().endConnection(replyPort);
142 END_IPCN(CSSM)
143 return KERN_SUCCESS;
144 }
145
146
147
148 //
149 // DL Interface
150 //
151 kern_return_t ucsp_server_attach(UCSP_ARGS, COPY_IN(CssmSubserviceUid, ssUid), AttachmentHandle *attachment)
152 {
153 BEGIN_IPC
154 secdebug("dl", "attach");
155 relocate(ssUid, ssUidBase, ssUidLength);
156 // @@@
157 *attachment = 0;
158 END_IPC(DL)
159 }
160
161 kern_return_t ucsp_server_detach(UCSP_ARGS, AttachmentHandle attachment)
162 {
163 BEGIN_IPC
164 secdebug("dl", "detach");
165 // @@@
166 END_IPC(DL)
167 }
168
169 kern_return_t ucsp_server_openDb(UCSP_ARGS, AttachmentHandle attachment, DATA_IN(name),
170 COPY_IN(CssmNetAddress, location), CSSM_DB_ACCESS_TYPE accessType,
171 COPY_IN(AccessCredentials, accessCredentials), DATA_IN(openParameters), DbHandle *db)
172 {
173 BEGIN_IPC
174 secdebug("dl", "openDb");
175 //DATA(name);
176 relocate(location, locationBase, locationLength);
177 relocate(accessCredentials, accessCredentialsBase, accessCredentialsLength);
178 //DATA(openParameters);
179 // @@@
180 *db = 0;
181 END_IPC(DL)
182 }
183
184 kern_return_t ucsp_server_createDb2(UCSP_ARGS, AttachmentHandle attachment, DATA_IN(name),
185 COPY_IN(CssmNetAddress, location), COPY_IN(CSSM_DBINFO, dbInfo), CSSM_DB_ACCESS_TYPE accessType,
186 COPY_IN(AccessCredentials, accessCredentials), COPY_IN(AclEntryPrototype, aclEntryPrototype),
187 DATA_IN(openParameters), DbHandle *db)
188 {
189 BEGIN_IPC
190 secdebug("dl", "createDb2");
191 //DATA(name);
192 relocate(location, locationBase, locationLength);
193 relocate(dbInfo, dbInfoBase, dbInfoLength);
194 relocate(accessCredentials, accessCredentialsBase, accessCredentialsLength);
195 relocate(aclEntryPrototype, aclEntryPrototypeBase, aclEntryPrototypeLength);
196 //DATA(openParameters);
197 // @@@
198 *db = 0;
199 END_IPC(DL)
200 }
201
202 kern_return_t ucsp_server_deleteDb(UCSP_ARGS, AttachmentHandle attachment,
203 DATA_IN(name), COPY_IN(CssmNetAddress, location), COPY_IN(AccessCredentials, accessCredentials))
204 {
205 BEGIN_IPC
206 secdebug("dl", "deleteDb");
207 //DATA(name);
208 relocate(location, locationBase, locationLength);
209 relocate(accessCredentials, accessCredentialsBase, accessCredentialsLength);
210 // @@@
211 END_IPC(DL)
212 }
213
214 kern_return_t ucsp_server_getDbNames(UCSP_ARGS, AttachmentHandle attachment,
215 COPY_OUT(CSSM_NAME_LIST, outNameList))
216 {
217 BEGIN_IPC
218 secdebug("dl", "getDbNames");
219 // @@@
220
221 CSSM_NAME_LIST *nameList;
222 //Attachment &a = Proccess::attachment(attachment);
223 //nameList = a.copyNameList();
224 Copier<CSSM_NAME_LIST> nameLists(nameList, Allocator::standard()); // make flat copy
225 //a.freeNameList(nameList); // Release original
226 *outNameListLength = nameLists.length();
227 //flips(nameLists.value(), outNameList, outNameListBase);
228 Server::releaseWhenDone(nameLists.keep()); // throw flat copy out when done
229 END_IPC(DL)
230 }
231
232 kern_return_t ucsp_server_getDbNameFromHandle(UCSP_ARGS, DbHandle db, DATA_OUT(name))
233 {
234 BEGIN_IPC
235 secdebug("dl", "getDbNameFromHandle");
236 // @@@
237 END_IPC(DL)
238 }
239
240 kern_return_t ucsp_server_closeDb(UCSP_ARGS, DbHandle db)
241 {
242 BEGIN_IPC
243 secdebug("dl", "closeDb");
244 // @@@
245 END_IPC(DL)
246 }
247
248 kern_return_t ucsp_server_authenticateDb(UCSP_ARGS, DbHandle db,
249 CSSM_DB_ACCESS_TYPE accessType, COPY_IN(AccessCredentials, cred))
250 {
251 BEGIN_IPC
252 secdebug("dl", "authenticateDb");
253 relocate(cred, credBase, credLength);
254 // @@@ Pass in accessType.
255 Server::database(db)->authenticate(cred);
256 END_IPC(DL)
257 }
258
259 kern_return_t ucsp_server_createRelation(UCSP_ARGS, DbHandle db,
260 CSSM_DB_RECORDTYPE recordType,
261 RelationName relationName,
262 uint32 attributeCount,
263 COPY_IN(CSSM_DB_SCHEMA_ATTRIBUTE_INFO, attributes),
264 uint32 indexCount,
265 COPY_IN(CSSM_DB_SCHEMA_INDEX_INFO, indices))
266 {
267 BEGIN_IPC
268 secdebug("dl", "createRelation");
269 CheckingReconstituteWalker relocator(attributes, attributesBase, attributesLength,
270 Server::process().byteFlipped());
271 for (uint32 ix = 0; ix < attributeCount; ++ix)
272 walk(relocator, attributes[ix]);
273 CheckingReconstituteWalker relocator2(indices, indicesBase, indicesLength,
274 Server::process().byteFlipped());
275 for (uint32 ix = 0; ix < indexCount; ++ix)
276 walk(relocator, indices[ix]);
277 // @@@
278 END_IPC(DL)
279 }
280
281 kern_return_t ucsp_server_destroyRelation(UCSP_ARGS, DbHandle db, CSSM_DB_RECORDTYPE recordType)
282 {
283 BEGIN_IPC
284 secdebug("dl", "destroyRelation");
285 // @@@
286 END_IPC(DL)
287 }
288
289 kern_return_t ucsp_server_insertRecord(UCSP_ARGS, DbHandle db, CSSM_DB_RECORDTYPE recordType,
290 COPY_IN(CssmDbRecordAttributeData, attributes), DATA_IN(data), RecordHandle *record)
291 {
292 BEGIN_IPC
293 secdebug("dl", "insertRecord");
294 // @@@
295 END_IPC(DL)
296 }
297
298 kern_return_t ucsp_server_deleteRecord(UCSP_ARGS, RecordHandle record)
299 {
300 BEGIN_IPC
301 secdebug("dl", "deleteRecord");
302 // @@@
303 END_IPC(DL)
304 }
305
306 kern_return_t ucsp_server_modifyRecord(UCSP_ARGS, RecordHandle record, CSSM_DB_RECORDTYPE recordType,
307 COPY_IN(CssmDbRecordAttributeData, attributes), DATA_IN(data), CSSM_DB_MODIFY_MODE modifyMode)
308 {
309 BEGIN_IPC
310 secdebug("dl", "modifyRecord");
311 // @@@
312 END_IPC(DL)
313 }
314
315 kern_return_t ucsp_server_findFirstRecord(UCSP_ARGS, DbHandle db,
316 COPY_IN(CssmQuery, query),
317 SearchHandle *search,
318 COPY_IN(CssmDbRecordAttributeData, inAttributes),
319 COPY_OUT(CssmDbRecordAttributeData, outAttributes),
320 boolean_t getData,
321 DATA_OUT(data),
322 RecordHandle *record
323 )
324 {
325 BEGIN_IPC
326 secdebug("dl", "findFirstRecord");
327 // @@@
328 END_IPC(DL)
329 }
330
331 kern_return_t ucsp_server_findNextRecord(UCSP_ARGS, SearchHandle search,
332 COPY_IN(CssmDbRecordAttributeData, inAttributes),
333 COPY_OUT(CssmDbRecordAttributeData, outAttributes),
334 boolean_t getData,
335 DATA_OUT(data),
336 RecordHandle *record)
337 {
338 BEGIN_IPC
339 secdebug("dl", "findNextRecord");
340 // @@@
341 END_IPC(DL)
342 }
343
344 kern_return_t ucsp_server_abortFind(UCSP_ARGS, SearchHandle search)
345 {
346 BEGIN_IPC
347 secdebug("dl", "abortFind");
348 //delete &Process::search(search);
349 // @@@
350 END_IPC(DL)
351 }
352
353 kern_return_t ucsp_server_getRecordFromHandle(UCSP_ARGS, RecordHandle record,
354 COPY_IN(CssmDbRecordAttributeData, inAttributes),
355 COPY_OUT(CssmDbRecordAttributeData, outAttributes),
356 boolean_t getData,
357 DATA_OUT(data))
358 {
359 BEGIN_IPC
360 secdebug("dl", "getRecordFromHandle");
361 relocate(inAttributes, inAttributesBase, inAttributesLength);
362 // @@@
363 END_IPC(DL)
364 }
365
366 kern_return_t ucsp_server_freeRecordHandle(UCSP_ARGS, RecordHandle record)
367 {
368 BEGIN_IPC
369 secdebug("dl", "freeRecordHandle");
370 //delete &Process::record(record);
371 // @@@
372 END_IPC(DL)
373 }
374
375
376 //
377 // Database management
378 //
379 kern_return_t ucsp_server_createDb(UCSP_ARGS, DbHandle *db,
380 COPY_IN(DLDbFlatIdentifier, ident),
381 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
382 DBParameters params)
383 {
384 BEGIN_IPC
385 relocate(cred, credBase, credLength);
386 relocate(owner, ownerBase, ownerLength);
387 relocate(ident, identBase, identLength);
388 *db = (new KeychainDatabase(*ident, params, connection.process(), cred, owner))->handle();
389 END_IPC(DL)
390 }
391
392 kern_return_t ucsp_server_decodeDb(UCSP_ARGS, DbHandle *db,
393 COPY_IN(DLDbFlatIdentifier, ident), COPY_IN(AccessCredentials, cred), DATA_IN(blob))
394 {
395 BEGIN_IPC
396 relocate(cred, credBase, credLength);
397 relocate(ident, identBase, identLength);
398 *db = (new KeychainDatabase(*ident, DATA(blob).interpretedAs<DbBlob>(),
399 connection.process(), cred))->handle();
400 END_IPC(DL)
401 }
402
403 kern_return_t ucsp_server_encodeDb(UCSP_ARGS, DbHandle db, DATA_OUT(blob))
404 {
405 BEGIN_IPC
406 DbBlob *dbBlob = Server::keychain(db)->blob(); // memory owned by database
407 *blob = dbBlob;
408 *blobLength = dbBlob->length();
409 END_IPC(DL)
410 }
411
412 kern_return_t ucsp_server_releaseDb(UCSP_ARGS, DbHandle db)
413 {
414 BEGIN_IPC
415 connection.process().removeReference(*Server::database(db));
416 END_IPC(DL)
417 }
418
419 kern_return_t ucsp_server_getDbIndex(UCSP_ARGS, DbHandle db, DATA_OUT(index))
420 {
421 BEGIN_IPC
422 OutputData indexData(index, indexLength);
423 Server::keychain(db)->getDbIndex(indexData);
424 END_IPC(DL)
425 }
426
427 kern_return_t ucsp_server_authenticateDb(UCSP_ARGS, DbHandle db,
428 COPY_IN(AccessCredentials, cred))
429 {
430 BEGIN_IPC
431 relocate(cred, credBase, credLength);
432 Server::database(db)->authenticate(cred);
433 END_IPC(DL)
434 }
435
436 kern_return_t ucsp_server_setDbParameters(UCSP_ARGS, DbHandle db, DBParameters params)
437 {
438 BEGIN_IPC
439 Server::keychain(db)->setParameters(params);
440 END_IPC(DL)
441 }
442
443 kern_return_t ucsp_server_getDbParameters(UCSP_ARGS, DbHandle db, DBParameters *params)
444 {
445 BEGIN_IPC
446 Server::keychain(db)->getParameters(*params);
447 END_IPC(DL)
448 }
449
450 kern_return_t ucsp_server_changePassphrase(UCSP_ARGS, DbHandle db,
451 COPY_IN(AccessCredentials, cred))
452 {
453 BEGIN_IPC
454 relocate(cred, credBase, credLength);
455 Server::keychain(db)->changePassphrase(cred);
456 END_IPC(DL)
457 }
458
459 kern_return_t ucsp_server_lockDb(UCSP_ARGS, DbHandle db)
460 {
461 BEGIN_IPC
462 Server::keychain(db)->lockDb();
463 END_IPC(DL)
464 }
465
466 kern_return_t ucsp_server_lockAll (UCSP_ARGS, boolean_t forSleep)
467 {
468 BEGIN_IPC
469 connection.session().allReferences(&DbCommon::sleepProcessing);
470 END_IPC(DL)
471 }
472
473 kern_return_t ucsp_server_unlockDb(UCSP_ARGS, DbHandle db)
474 {
475 BEGIN_IPC
476 Server::keychain(db)->unlockDb();
477 END_IPC(DL)
478 }
479
480 kern_return_t ucsp_server_unlockDbWithPassphrase(UCSP_ARGS, DbHandle db, DATA_IN(passphrase))
481 {
482 BEGIN_IPC
483 Server::keychain(db)->unlockDb(DATA(passphrase));
484 END_IPC(DL)
485 }
486
487 kern_return_t ucsp_server_isLocked(UCSP_ARGS, DbHandle db, boolean_t *locked)
488 {
489 BEGIN_IPC
490 *locked = Server::keychain(db)->isLocked();
491 END_IPC(DL)
492 }
493
494
495 //
496 // Key management
497 //
498 kern_return_t ucsp_server_encodeKey(UCSP_ARGS, KeyHandle keyh, DATA_OUT(blob),
499 boolean_t wantUid, DATA_OUT(uid))
500 {
501 BEGIN_IPC
502 RefPointer<Key> gKey = Server::key(keyh);
503 if (KeychainKey *key = dynamic_cast<KeychainKey *>(gKey.get())) {
504 KeyBlob *keyBlob = key->blob(); // still owned by key
505 *blob = keyBlob;
506 *blobLength = keyBlob->length();
507 if (wantUid) { // uid generation is not implemented
508 CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED);
509 } else {
510 *uidLength = 0; // do not return this
511 }
512 } else { // not a KeychainKey
513 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE);
514 }
515 END_IPC(CSP)
516 }
517
518 kern_return_t ucsp_server_decodeKey(UCSP_ARGS, KeyHandle *keyh, CssmKey::Header *header,
519 DbHandle db, DATA_IN(blob))
520 {
521 BEGIN_IPC
522 RefPointer<Key> key = new KeychainKey(*Server::keychain(db), DATA(blob).interpretedAs<KeyBlob>());
523 key->returnKey(*keyh, *header);
524 flip(*header);
525 END_IPC(CSP)
526 }
527
528 kern_return_t ucsp_server_releaseKey(UCSP_ARGS, KeyHandle keyh)
529 {
530 BEGIN_IPC
531 RefPointer<Key> key = Server::key(keyh);
532 key->database().releaseKey(*key);
533 END_IPC(CSP)
534 }
535
536 kern_return_t ucsp_server_queryKeySizeInBits(UCSP_ARGS, KeyHandle keyh, CSSM_KEY_SIZE *length)
537 {
538 BEGIN_IPC
539 RefPointer<Key> key = Server::key(keyh);
540 *length = key->database().queryKeySize(*key);
541 END_IPC(CSP)
542 }
543
544 kern_return_t ucsp_server_getOutputSize(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh,
545 uint32 inputSize, boolean_t encrypt, uint32 *outputSize)
546 {
547 BEGIN_IPC
548 relocate(context, contextBase, attributes, attrSize);
549 RefPointer<Key> key = Server::key(keyh);
550 *outputSize = key->database().getOutputSize(context, *key, inputSize, encrypt);
551 END_IPC(CSP)
552 }
553
554 kern_return_t ucsp_server_getKeyDigest(UCSP_ARGS, KeyHandle key, DATA_OUT(digest))
555 {
556 BEGIN_IPC
557 CssmData digestData = Server::key(key)->canonicalDigest();
558 *digest = digestData.data();
559 *digestLength = digestData.length();
560 END_IPC(CSP)
561 }
562
563 //
564 // RNG interface
565 //
566 kern_return_t ucsp_server_generateRandom(UCSP_ARGS, uint32 bytes, DATA_OUT(data))
567 {
568 BEGIN_IPC
569 Allocator &allocator = Allocator::standard(Allocator::sensitive);
570 void *buffer = allocator.malloc(bytes);
571 Server::active().random(buffer, bytes);
572 *data = buffer;
573 *dataLength = bytes;
574 Server::releaseWhenDone(allocator, buffer);
575 END_IPC(CSP)
576 }
577
578
579 //
580 // Signatures and MACs
581 //
582 kern_return_t ucsp_server_generateSignature(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh,
583 CSSM_ALGORITHMS signOnlyAlgorithm, DATA_IN(data), DATA_OUT(signature))
584 {
585 BEGIN_IPC
586 relocate(context, contextBase, attributes, attrSize);
587 RefPointer<Key> key = Server::key(keyh);
588 OutputData sigData(signature, signatureLength);
589 key->database().generateSignature(context, *key, signOnlyAlgorithm,
590 DATA(data), sigData);
591 END_IPC(CSP)
592 }
593
594 kern_return_t ucsp_server_verifySignature(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh,
595 CSSM_ALGORITHMS verifyOnlyAlgorithm, DATA_IN(data), DATA_IN(signature))
596 {
597 BEGIN_IPC
598 relocate(context, contextBase, attributes, attrSize);
599 RefPointer<Key> key = Server::key(keyh);
600 key->database().verifySignature(context, *key, verifyOnlyAlgorithm,
601 DATA(data), DATA(signature));
602 END_IPC(CSP)
603 }
604
605 kern_return_t ucsp_server_generateMac(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh,
606 DATA_IN(data), DATA_OUT(mac))
607 {
608 BEGIN_IPC
609 relocate(context, contextBase, attributes, attrSize);
610 RefPointer<Key> key = Server::key(keyh);
611 OutputData macData(mac, macLength);
612 key->database().generateMac(context, *key, DATA(data), macData);
613 END_IPC(CSP)
614 }
615
616 kern_return_t ucsp_server_verifyMac(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh,
617 DATA_IN(data), DATA_IN(mac))
618 {
619 BEGIN_IPC
620 relocate(context, contextBase, attributes, attrSize);
621 RefPointer<Key> key = Server::key(keyh);
622 key->database().verifyMac(context, *key, DATA(data), DATA(mac));
623 END_IPC(CSP)
624 }
625
626
627 //
628 // Encryption/Decryption
629 //
630 kern_return_t ucsp_server_encrypt(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh,
631 DATA_IN(clear), DATA_OUT(cipher))
632 {
633 BEGIN_IPC
634 relocate(context, contextBase, attributes, attrSize);
635 RefPointer<Key> key = Server::key(keyh);
636 OutputData cipherOut(cipher, cipherLength);
637 key->database().encrypt(context, *key, DATA(clear), cipherOut);
638 END_IPC(CSP)
639 }
640
641 kern_return_t ucsp_server_decrypt(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh,
642 DATA_IN(cipher), DATA_OUT(clear))
643 {
644 BEGIN_IPC
645 relocate(context, contextBase, attributes, attrSize);
646 RefPointer<Key> key = Server::key(keyh);
647 OutputData clearOut(clear, clearLength);
648 key->database().decrypt(context, *key, DATA(cipher), clearOut);
649 END_IPC(CSP)
650 }
651
652
653 //
654 // Key generation
655 //
656 kern_return_t ucsp_server_generateKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS,
657 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
658 uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader)
659 {
660 BEGIN_IPC
661 relocate(context, contextBase, attributes, attrSize);
662 relocate(cred, credBase, credLength);
663 relocate(owner, ownerBase, ownerLength);
664 //@@@ preliminary interpretation - will get "type handle"
665 RefPointer<Database> database = Server::optionalDatabase(db);
666 RefPointer<Key> key;
667 database->generateKey(context, cred, owner, usage, attrs, key);
668 key->returnKey(*newKey, *newHeader);
669 flip(*newHeader);
670 END_IPC(CSP)
671 }
672
673 kern_return_t ucsp_server_generateKeyPair(UCSP_ARGS, DbHandle db, CONTEXT_ARGS,
674 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
675 uint32 pubUsage, uint32 pubAttrs, uint32 privUsage, uint32 privAttrs,
676 KeyHandle *pubKey, CssmKey::Header *pubHeader, KeyHandle *privKey, CssmKey::Header *privHeader)
677 {
678 BEGIN_IPC
679 relocate(context, contextBase, attributes, attrSize);
680 relocate(cred, credBase, credLength);
681 relocate(owner, ownerBase, ownerLength);
682 RefPointer<Key> pub, priv;
683 RefPointer<Database> database = Server::optionalDatabase(db);
684 database->generateKey(context, cred, owner,
685 pubUsage, pubAttrs, privUsage, privAttrs, pub, priv);
686 pub->returnKey(*pubKey, *pubHeader);
687 flip(*pubHeader);
688 priv->returnKey(*privKey, *privHeader);
689 flip(*privHeader);
690 END_IPC(CSP)
691 }
692
693
694 //
695 // Key derivation.
696 // This is a bit strained; the incoming 'param' value may have structure
697 // and needs to be handled on a per-algorithm basis, which means we have to
698 // know which key derivation algorithms we support for passing to our CSP(s).
699 // The default behavior is to handle "flat" data blobs, which is as good
700 // a default as we can manage.
701 // NOTE: The param-specific handling must be synchronized with the client library
702 // code (in sstransit.h).
703 //
704 kern_return_t ucsp_server_deriveKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, KeyHandle keyh,
705 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
706 COPY_IN(void, paramInputData), DATA_OUT(paramOutput),
707 uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader)
708 {
709 BEGIN_IPC
710 relocate(context, contextBase, attributes, attrSize);
711 relocate(cred, credBase, credLength);
712 relocate(owner, ownerBase, ownerLength);
713
714 // munge together the incoming 'param' value according to algorithm
715 CssmData param;
716 switch (context.algorithm()) {
717 case CSSM_ALGID_PKCS5_PBKDF2:
718 relocate((CSSM_PKCS5_PBKDF2_PARAMS *)paramInputData,
719 (CSSM_PKCS5_PBKDF2_PARAMS *)paramInputDataBase,
720 paramInputDataLength);
721 param = CssmData(paramInputData, sizeof(CSSM_PKCS5_PBKDF2_PARAMS));
722 break;
723 default:
724 param = CssmData(paramInputData, paramInputDataLength);
725 break;
726 }
727 RefPointer<Database> database = Server::optionalDatabase(db);
728 RefPointer<Key> theKey = database->deriveKey(context, Server::optionalKey(keyh),
729 cred, owner, &param, usage, attrs);
730 theKey->returnKey(*newKey, *newHeader);
731 flip(*newHeader);
732 if (param.length()) {
733 if (!param) // CSP screwed up
734 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
735 if (paramInputDataLength) // using incoming buffer; make a copy
736 param = CssmAutoData(Server::csp().allocator(), param).release();
737 OutputData(paramOutput, paramOutputLength) = param; // return the data
738 }
739 END_IPC(CSP)
740 }
741
742
743 //
744 // Key wrapping and unwrapping
745 //
746 kern_return_t ucsp_server_wrapKey(UCSP_ARGS, CONTEXT_ARGS, KeyHandle keyh,
747 COPY_IN(AccessCredentials, cred), KeyHandle keyToBeWrappedh,
748 DATA_IN(descriptiveData), CssmKey *wrappedKey, DATA_OUT(keyData))
749 {
750 BEGIN_IPC
751 relocate(context, contextBase, attributes, attrSize);
752 relocate(cred, credBase, credLength);
753 RefPointer<Key> inputKey = Server::key(keyToBeWrappedh);
754 inputKey->database().wrapKey(context, Server::optionalKey(keyh),
755 *inputKey, cred, DATA(descriptiveData), *wrappedKey);
756 // transmit key data back as a separate blob
757 *keyData = wrappedKey->data();
758 *keyDataLength = wrappedKey->length();
759 Server::releaseWhenDone(*keyData);
760 flip(*wrappedKey);
761 END_IPC(CSP)
762 }
763
764 kern_return_t ucsp_server_unwrapKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, KeyHandle keyh,
765 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
766 KeyHandle publicKeyh, CssmKey wrappedKey, DATA_IN(wrappedKeyData),
767 uint32 usage, uint32 attr, DATA_OUT(descriptiveData),
768 KeyHandle *newKey, CssmKey::Header *newHeader)
769 {
770 BEGIN_IPC
771 relocate(context, contextBase, attributes, attrSize);
772 flip(wrappedKey);
773 wrappedKey.KeyData = DATA(wrappedKeyData);
774 relocate(cred, credBase, credLength);
775 relocate(owner, ownerBase, ownerLength);
776 RefPointer<Database> database = Server::optionalDatabase(db);
777 CssmData descriptiveDatas;
778 RefPointer<Key> theKey = database->unwrapKey(context, Server::optionalKey(keyh),
779 cred, owner, usage, attr, wrappedKey,
780 Server::optionalKey(publicKeyh), &descriptiveDatas);
781 theKey->returnKey(*newKey, *newHeader);
782 flip(*newHeader);
783 *descriptiveData = descriptiveDatas.data();
784 *descriptiveDataLength = descriptiveDatas.length();
785 Server::releaseWhenDone(*descriptiveData);
786 END_IPC(CSP)
787 }
788
789
790 //
791 // ACL management.
792 // Watch out for the memory-management tap-dance.
793 //
794 kern_return_t ucsp_server_getOwner(UCSP_ARGS, AclKind kind, KeyHandle key,
795 COPY_OUT(AclOwnerPrototype, ownerOut))
796 {
797 BEGIN_IPC
798 AclOwnerPrototype owner;
799 Server::aclBearer(kind, key).cssmGetOwner(owner); // allocates memory in owner
800 Copier<AclOwnerPrototype> owners(&owner, Allocator::standard()); // make flat copy
801 { ChunkFreeWalker free; walk(free, owner); } // release chunked original
802 *ownerOutLength = owners.length();
803 flips(owners.value(), ownerOut, ownerOutBase);
804 Server::releaseWhenDone(owners.keep()); // throw flat copy out when done
805 END_IPC(CSP)
806 }
807
808 kern_return_t ucsp_server_setOwner(UCSP_ARGS, AclKind kind, KeyHandle key,
809 COPY_IN(AccessCredentials, cred), COPY_IN(AclOwnerPrototype, owner))
810 {
811 BEGIN_IPC
812 relocate(cred, credBase, credLength);
813 relocate(owner, ownerBase, ownerLength);
814 Server::aclBearer(kind, key).cssmChangeOwner(*owner, cred);
815 END_IPC(CSP)
816 }
817
818 kern_return_t ucsp_server_getAcl(UCSP_ARGS, AclKind kind, KeyHandle key,
819 boolean_t haveTag, const char *tag,
820 uint32 *countp, COPY_OUT(AclEntryInfo, acls))
821 {
822 BEGIN_IPC
823 uint32 count;
824 AclEntryInfo *aclList;
825 Server::aclBearer(kind, key).cssmGetAcl(haveTag ? tag : NULL, count, aclList);
826 *countp = count;
827 Copier<AclEntryInfo> aclsOut(AclEntryInfo::overlay(aclList), count); // make flat copy
828
829 { // release the chunked memory originals
830 ChunkFreeWalker free;
831 for (uint32 n = 0; n < count; n++)
832 walk(free, aclList[n]);
833
834 // release the memory allocated for the list itself when we are done
835 Allocator::standard().free (aclList);
836 }
837
838 // set result (note: this is *almost* flips(), but on an array)
839 *aclsLength = aclsOut.length();
840 *acls = *aclsBase = aclsOut;
841 if (flipClient()) {
842 FlipWalker w;
843 for (uint32 n = 0; n < count; n++)
844 walk(w, (*acls)[n]);
845 w.doFlips();
846 Flippers::flip(*aclsBase);
847 }
848 Server::releaseWhenDone(aclsOut.keep());
849 END_IPC(CSP)
850 }
851
852 kern_return_t ucsp_server_changeAcl(UCSP_ARGS, AclKind kind, KeyHandle key,
853 COPY_IN(AccessCredentials, cred), CSSM_ACL_EDIT_MODE mode, CSSM_ACL_HANDLE handle,
854 COPY_IN(AclEntryInput, acl))
855 {
856 BEGIN_IPC
857 relocate(cred, credBase, credLength);
858 relocate(acl, aclBase, aclLength);
859 Server::aclBearer(kind, key).cssmChangeAcl(AclEdit(mode, handle, acl), cred);
860 END_IPC(CSP)
861 }
862
863
864 //
865 // Database key management.
866 // ExtractMasterKey looks vaguely like a key derivation operation, and is in fact
867 // presented by the CSPDL's CSSM layer as such.
868 //
869 kern_return_t ucsp_server_extractMasterKey(UCSP_ARGS, DbHandle db, CONTEXT_ARGS, DbHandle sourceDb,
870 COPY_IN(AccessCredentials, cred), COPY_IN(AclEntryPrototype, owner),
871 uint32 usage, uint32 attrs, KeyHandle *newKey, CssmKey::Header *newHeader)
872 {
873 BEGIN_IPC
874 context.postIPC(contextBase, attributes);
875 relocate(cred, credBase, credLength);
876 relocate(owner, ownerBase, ownerLength);
877 RefPointer<KeychainDatabase> keychain = Server::keychain(sourceDb);
878 RefPointer<Key> masterKey = keychain->extractMasterKey(*Server::optionalDatabase(db),
879 cred, owner, usage, attrs);
880 masterKey->returnKey(*newKey, *newHeader);
881 flip(*newHeader);
882 END_IPC(CSP)
883 }
884
885
886 //
887 // Authorization subsystem support
888 //
889 kern_return_t ucsp_server_authorizationCreate(UCSP_ARGS,
890 COPY_IN(AuthorizationItemSet, inRights),
891 uint32 flags,
892 COPY_IN(AuthorizationItemSet, inEnvironment),
893 AuthorizationBlob *authorization)
894 {
895 BEGIN_IPC
896 relocate(inRights, inRightsBase, inRightsLength);
897 relocate(inEnvironment, inEnvironmentBase, inEnvironmentLength);
898 Authorization::AuthItemSet rights(inRights), environment(inEnvironment);
899
900 *rcode = connection.process().session().authCreate(rights, environment,
901 flags, *authorization, securityToken);
902 END_IPC(CSSM)
903 }
904
905 kern_return_t ucsp_server_authorizationRelease(UCSP_ARGS,
906 AuthorizationBlob authorization, uint32 flags)
907 {
908 BEGIN_IPC
909 connection.process().session().authFree(authorization, flags);
910 END_IPC(CSSM)
911 }
912
913 kern_return_t ucsp_server_authorizationCopyRights(UCSP_ARGS,
914 AuthorizationBlob authorization,
915 COPY_IN(AuthorizationItemSet, inRights),
916 uint32 flags,
917 COPY_IN(AuthorizationItemSet, inEnvironment),
918 COPY_OUT(AuthorizationItemSet, result))
919 {
920 BEGIN_IPC
921 relocate(inRights, inRightsBase, inRightsLength);
922 relocate(inEnvironment, inEnvironmentBase, inEnvironmentLength);
923 Authorization::AuthItemSet rights(inRights), environment(inEnvironment), grantedRights;
924 *rcode = connection.process().session().authGetRights(authorization,
925 rights, environment, flags, grantedRights);
926 if (result && resultLength)
927 {
928 size_t resultSize;
929 grantedRights.copy(*result, resultSize);
930 *resultLength = resultSize;
931 *resultBase = *result;
932 flips(*result, result, resultBase);
933 Server::releaseWhenDone(*result);
934 }
935 END_IPC(CSSM)
936 }
937
938 kern_return_t ucsp_server_authorizationCopyInfo(UCSP_ARGS,
939 AuthorizationBlob authorization,
940 AuthorizationString tag,
941 COPY_OUT(AuthorizationItemSet, info))
942 {
943 BEGIN_IPC
944 Authorization::AuthItemSet infoSet;
945 *info = *infoBase = NULL;
946 *infoLength = 0;
947 *rcode = connection.process().session().authGetInfo(authorization,
948 tag[0] ? tag : NULL, infoSet);
949 if (*rcode == noErr) {
950 size_t infoSize;
951 infoSet.copy(*info, infoSize);
952 *infoLength = infoSize;
953 *infoBase = *info;
954 flips(*info, info, infoBase);
955 Server::releaseWhenDone(*info);
956 }
957 END_IPC(CSSM)
958 }
959
960 kern_return_t ucsp_server_authorizationExternalize(UCSP_ARGS,
961 AuthorizationBlob authorization, AuthorizationExternalForm *extForm)
962 {
963 BEGIN_IPC
964 *rcode = connection.process().session().authExternalize(authorization, *extForm);
965 END_IPC(CSSM)
966 }
967
968 kern_return_t ucsp_server_authorizationInternalize(UCSP_ARGS,
969 AuthorizationExternalForm extForm, AuthorizationBlob *authorization)
970 {
971 BEGIN_IPC
972 *rcode = connection.process().session().authInternalize(extForm, *authorization);
973 END_IPC(CSSM)
974 }
975
976
977 //
978 // Session management subsystem
979 //
980 kern_return_t ucsp_server_getSessionInfo(UCSP_ARGS,
981 SecuritySessionId *sessionId, SessionAttributeBits *attrs)
982 {
983 BEGIN_IPC
984 Session &session = Session::find(*sessionId);
985 *sessionId = session.handle();
986 *attrs = session.attributes();
987 END_IPC(CSSM)
988 }
989
990 kern_return_t ucsp_server_setupSession(UCSP_ARGS,
991 SessionCreationFlags flags, SessionAttributeBits attrs)
992 {
993 BEGIN_IPC
994 Session::setup(flags, attrs);
995 END_IPC(CSSM)
996 }
997
998
999 //
1000 // Notification core subsystem
1001 //
1002 kern_return_t ucsp_server_requestNotification(UCSP_ARGS, mach_port_t receiver, uint32 domain, uint32 events)
1003 {
1004 BEGIN_IPC
1005 connection.process().requestNotifications(receiver, domain, events);
1006 END_IPC(CSSM)
1007 }
1008
1009 kern_return_t ucsp_server_stopNotification(UCSP_ARGS, mach_port_t receiver)
1010 {
1011 BEGIN_IPC
1012 connection.process().stopNotifications(receiver);
1013 END_IPC(CSSM)
1014 }
1015
1016 kern_return_t ucsp_server_postNotification(UCSP_ARGS, uint32 domain, uint32 event, DATA_IN(data))
1017 {
1018 BEGIN_IPC
1019 Listener::notify(domain, event, DATA(data));
1020 END_IPC(CSSM)
1021 }
1022
1023
1024 //
1025 // AuthorizationDB modification
1026 //
1027 kern_return_t ucsp_server_authorizationdbGet(UCSP_ARGS, const char *rightname, DATA_OUT(rightDefinition))
1028 {
1029 BEGIN_IPC
1030 CFDictionaryRef rightDict;
1031
1032 *rcode = connection.process().session().authorizationdbGet(rightname, &rightDict);
1033
1034 if (!*rcode && rightDict)
1035 {
1036 CFRef<CFDataRef> data(CFPropertyListCreateXMLData (NULL, rightDict));
1037 CFRelease(rightDict);
1038 if (!data)
1039 return errAuthorizationInternal;
1040
1041 // @@@ copy data to avoid having to do a delayed cfrelease
1042 mach_msg_type_number_t length = CFDataGetLength(data);
1043 void *xmlData = Allocator::standard().malloc(length);
1044 memcpy(xmlData, CFDataGetBytePtr(data), length);
1045 Server::releaseWhenDone(xmlData);
1046
1047 *rightDefinition = xmlData;
1048 *rightDefinitionLength = length;
1049 }
1050 END_IPC(CSSM)
1051 }
1052
1053 kern_return_t ucsp_server_authorizationdbSet(UCSP_ARGS, AuthorizationBlob authorization, const char *rightname, DATA_IN(rightDefinition))
1054 {
1055 BEGIN_IPC
1056 CFRef<CFDataRef> data(CFDataCreate(NULL, (UInt8 *)rightDefinition, rightDefinitionLength));
1057
1058 if (!data)
1059 return errAuthorizationInternal;
1060
1061 CFRef<CFDictionaryRef> rightDefinition(static_cast<CFDictionaryRef>(CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListImmutable, NULL)));
1062
1063 if (!rightDefinition || (CFGetTypeID(rightDefinition) != CFDictionaryGetTypeID()))
1064 return errAuthorizationInternal;
1065
1066 *rcode = connection.process().session().authorizationdbSet(authorization, rightname, rightDefinition);
1067
1068 END_IPC(CSSM)
1069 }
1070
1071 kern_return_t ucsp_server_authorizationdbRemove(UCSP_ARGS, AuthorizationBlob authorization, const char *rightname)
1072 {
1073 BEGIN_IPC
1074 *rcode = connection.process().session().authorizationdbRemove(authorization, rightname);
1075 END_IPC(CSSM)
1076 }
1077
1078
1079 //
1080 // Miscellaneous administrative functions
1081 //
1082 kern_return_t ucsp_server_addCodeEquivalence(UCSP_ARGS, DATA_IN(oldHash), DATA_IN(newHash),
1083 const char *name, boolean_t forSystem)
1084 {
1085 BEGIN_IPC
1086 Server::codeSignatures().addLink(DATA(oldHash), DATA(newHash), name, forSystem);
1087 END_IPC(CSSM)
1088 }
1089
1090 kern_return_t ucsp_server_removeCodeEquivalence(UCSP_ARGS, DATA_IN(hash),
1091 const char *name, boolean_t forSystem)
1092 {
1093 BEGIN_IPC
1094 Server::codeSignatures().removeLink(DATA(hash), name, forSystem);
1095 END_IPC(CSSM)
1096 }
1097
1098 kern_return_t ucsp_server_setAlternateSystemRoot(UCSP_ARGS, const char *root)
1099 {
1100 BEGIN_IPC
1101 #if defined(NDEBUG)
1102 if (connection.process().uid() != 0)
1103 CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED);
1104 #endif //NDEBUG
1105 Server::codeSignatures().open((string(root) + EQUIVALENCEDBPATH).c_str());
1106 END_IPC(CSSM)
1107 }