]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2000-2008,2011-2013 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
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 - SecurityServer client library transition code. | |
27 | // | |
28 | // These are the functions that implement CssmClient methods in terms of | |
29 | // MIG IPC client calls, plus their supporting machinery. | |
30 | // | |
31 | // WARNING! HERE BE DRAGONS! | |
32 | // This code involves moderately arcane magic including (but not limited to) | |
33 | // dancing macros paired off with self-maintaining stack objects. Don't take | |
34 | // anything for granted! Be very afraid of ALL-CAPS names. Your best bet is | |
35 | // probably to stick with the existing patterns. | |
36 | // | |
37 | // Dragons, the sequel. You just don't go killing of that kind of prose, so | |
38 | // we'll continue the saga here with a bit of an update. In transitioning | |
39 | // into securityd there are a couple of steps. The current setup is there | |
40 | // to allow Security.framework to have 32 and 64 bit clients and either | |
41 | // big or little endian. Data is packaged up as hand-generated XDR, which | |
42 | // means it's also in network byte-order. | |
43 | // | |
44 | // CSSM_HANDLEs have remained longs in the 64 bit transition to keep the | |
45 | // optimization option open to allow cssm modules to hand back pointers as | |
46 | // handles. Since we don't identify the client, handles across ipc will | |
47 | // remain 32 bit. Handles you see here are passed out by securityd, and | |
48 | // are clipped and expanded in this layer (high bits always zero). | |
49 | // | |
50 | #include "sstransit.h" | |
51 | #include <security_cdsa_client/cspclient.h> | |
b1ab9ed8 A |
52 | |
53 | #include <securityd_client/xdr_auth.h> | |
54 | #include <securityd_client/xdr_cssm.h> | |
55 | #include <securityd_client/xdr_dldb.h> | |
56 | ||
57 | namespace Security { | |
58 | namespace SecurityServer { | |
59 | ||
60 | using MachPlusPlus::check; | |
61 | using MachPlusPlus::VMGuard; | |
62 | ||
63 | // | |
64 | // Common database interface | |
65 | // | |
66 | void ClientSession::authenticateDb(DbHandle db, CSSM_DB_ACCESS_TYPE type, | |
67 | const AccessCredentials *cred) | |
68 | { | |
69 | // XXX/cs Leave it up to DatabaseAccessCredentials to rewrite it for now | |
70 | DatabaseAccessCredentials creds(cred, internalAllocator); | |
71 | CopyIn copy(creds.value(), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
72 | IPC(ucsp_client_authenticateDb(UCSP_ARGS, db, type, copy.data(), copy.length())); | |
73 | } | |
74 | ||
75 | ||
76 | void ClientSession::releaseDb(DbHandle db) | |
77 | { | |
78 | IPC(ucsp_client_releaseDb(UCSP_ARGS, db)); | |
79 | } | |
80 | ||
81 | ||
82 | // | |
83 | // External database interface | |
84 | // | |
85 | DbHandle ClientSession::openToken(uint32 ssid, const AccessCredentials *cred, | |
86 | const char *name) | |
87 | { | |
88 | DbHandle db; | |
89 | DatabaseAccessCredentials creds(cred, internalAllocator); | |
90 | CopyIn copycreds(creds.value(), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
91 | ||
92 | IPC(ucsp_client_openToken(UCSP_ARGS, ssid, name ? name : "", copycreds.data(), copycreds.length(), &db)); | |
93 | ||
94 | return db; | |
95 | } | |
96 | ||
97 | ||
98 | RecordHandle ClientSession::insertRecord(DbHandle db, | |
99 | CSSM_DB_RECORDTYPE recordType, | |
100 | const CssmDbRecordAttributeData *attributes, | |
101 | const CssmData *data) | |
102 | { | |
103 | RecordHandle record; | |
104 | CopyIn db_record_attr_data(attributes, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); | |
105 | ||
427c49bc | 106 | IPC(ucsp_client_insertRecord(UCSP_ARGS, db, recordType, db_record_attr_data.data(), (mach_msg_type_number_t)db_record_attr_data.length(), OPTIONALDATA(data), &record)); |
b1ab9ed8 A |
107 | |
108 | return record; | |
109 | } | |
110 | ||
111 | ||
112 | void ClientSession::deleteRecord(DbHandle db, RecordHandle record) | |
113 | { | |
114 | IPC(ucsp_client_deleteRecord(UCSP_ARGS, db, record)); | |
115 | } | |
116 | ||
117 | ||
118 | void ClientSession::modifyRecord(DbHandle db, RecordHandle &record, | |
119 | CSSM_DB_RECORDTYPE recordType, | |
120 | const CssmDbRecordAttributeData *attributes, | |
121 | const CssmData *data, | |
122 | CSSM_DB_MODIFY_MODE modifyMode) | |
123 | { | |
124 | CopyIn db_record_attr_data(attributes, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); | |
125 | ||
427c49bc | 126 | IPC(ucsp_client_modifyRecord(UCSP_ARGS, db, &record, recordType, db_record_attr_data.data(), (mach_msg_type_number_t)db_record_attr_data.length(), |
b1ab9ed8 A |
127 | data != NULL, OPTIONALDATA(data), modifyMode)); |
128 | } | |
129 | ||
427c49bc | 130 | static |
b1ab9ed8 A |
131 | void copy_back_attribute_return_data(CssmDbRecordAttributeData *dest_attrs, CssmDbRecordAttributeData *source_attrs, Allocator &returnAllocator) |
132 | { | |
133 | assert(dest_attrs->size() == source_attrs->size()); | |
134 | // global (per-record) fields | |
135 | dest_attrs->recordType(source_attrs->recordType()); | |
136 | dest_attrs->semanticInformation(source_attrs->semanticInformation()); | |
137 | ||
138 | // transfer data values (but not infos, which we keep in the original vector) | |
139 | for (uint32 n = 0; n < dest_attrs->size(); n++) | |
140 | dest_attrs->at(n).copyValues(source_attrs->at(n), returnAllocator); | |
141 | } | |
142 | ||
143 | RecordHandle ClientSession::findFirst(DbHandle db, | |
144 | const CssmQuery &inQuery, | |
145 | SearchHandle &hSearch, | |
146 | CssmDbRecordAttributeData *attributes, | |
147 | CssmData *data, KeyHandle &hKey) | |
148 | { | |
149 | CopyIn query(&inQuery, reinterpret_cast<xdrproc_t>(xdr_CSSM_QUERY)); | |
150 | CopyIn in_attr(attributes, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); | |
151 | void *out_attr_data = NULL, *out_data = NULL; | |
152 | mach_msg_size_t out_attr_length = 0, out_data_length = 0; | |
153 | RecordHandle ipcHRecord = 0; | |
154 | ||
155 | IPC(ucsp_client_findFirst(UCSP_ARGS, db, | |
156 | query.data(), query.length(), in_attr.data(), in_attr.length(), | |
157 | &out_attr_data, &out_attr_length, (data != NULL), &out_data, &out_data_length, | |
158 | &hKey, &hSearch, &ipcHRecord)); | |
159 | ||
160 | if (ipcHRecord != 0) | |
161 | { | |
162 | CopyOut out_attrs(out_attr_data, out_attr_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR), true); | |
163 | copy_back_attribute_return_data(attributes, reinterpret_cast<CssmDbRecordAttributeData*>(out_attrs.data()), returnAllocator); | |
164 | } | |
165 | ||
166 | // decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data) | |
167 | CopyOut possible_key_in_data(out_data, out_data_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR), true, data); | |
168 | ||
169 | return ipcHRecord; | |
170 | } | |
171 | ||
172 | ||
173 | RecordHandle ClientSession::findNext(SearchHandle hSearch, | |
174 | CssmDbRecordAttributeData *attributes, | |
175 | CssmData *data, KeyHandle &hKey) | |
176 | { | |
177 | CopyIn in_attr(attributes, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); | |
178 | void *out_attr_data = NULL, *out_data = NULL; | |
179 | mach_msg_size_t out_attr_length = 0, out_data_length = 0; | |
180 | //DataOutput out_data(data, returnAllocator); | |
181 | RecordHandle ipcHRecord = 0; | |
182 | ||
183 | IPC(ucsp_client_findNext(UCSP_ARGS, hSearch, | |
184 | in_attr.data(), in_attr.length(), &out_attr_data, &out_attr_length, | |
185 | (data != NULL), &out_data, &out_data_length, &hKey, &ipcHRecord)); | |
186 | ||
187 | if (ipcHRecord != 0) | |
188 | { | |
189 | CopyOut out_attrs(out_attr_data, out_attr_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR), true); | |
190 | copy_back_attribute_return_data(attributes, reinterpret_cast<CssmDbRecordAttributeData*>(out_attrs.data()), returnAllocator); | |
191 | } | |
192 | ||
193 | // decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data) | |
194 | CopyOut possible_key_in_data(out_data, out_data_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR), true, data); | |
195 | ||
196 | return ipcHRecord; | |
197 | } | |
198 | ||
199 | ||
200 | void ClientSession::findRecordHandle(RecordHandle hRecord, | |
201 | CssmDbRecordAttributeData *attributes, | |
202 | CssmData *data, KeyHandle &hKey) | |
203 | { | |
204 | CopyIn in_attr(attributes, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA)); | |
205 | void *out_attr_data = NULL, *out_data = NULL; | |
206 | mach_msg_size_t out_attr_length = 0, out_data_length = 0; | |
207 | IPC(ucsp_client_findRecordHandle(UCSP_ARGS, hRecord, | |
208 | in_attr.data(), in_attr.length(), &out_attr_data, &out_attr_length, | |
209 | data != NULL, &out_data, &out_data_length, &hKey)); | |
210 | ||
211 | if (hRecord != 0) | |
212 | { | |
213 | CopyOut out_attrs(out_attr_data, out_attr_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR), true); | |
214 | copy_back_attribute_return_data(attributes, reinterpret_cast<CssmDbRecordAttributeData*>(out_attrs.data()), returnAllocator); | |
215 | } | |
216 | ||
217 | // decode data from server as cssm_data or cssm_key (get data on keys returns cssm_key in data) | |
218 | CopyOut possible_key_in_data(out_data, out_data_length, reinterpret_cast<xdrproc_t>(xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR), true, data); | |
219 | } | |
220 | ||
221 | ||
222 | void ClientSession::releaseSearch(SearchHandle searchHandle) | |
223 | { | |
224 | IPC(ucsp_client_releaseSearch(UCSP_ARGS, searchHandle)); | |
225 | } | |
226 | ||
227 | ||
228 | void ClientSession::releaseRecord(RecordHandle record) | |
229 | { | |
230 | IPC(ucsp_client_releaseRecord(UCSP_ARGS, record)); | |
231 | } | |
232 | ||
233 | void ClientSession::getDbName(DbHandle db, string &name) | |
234 | { | |
235 | char result[PATH_MAX]; | |
236 | ||
237 | IPC(ucsp_client_getDbName(UCSP_ARGS, db, result)); | |
238 | ||
239 | name = result; | |
240 | } | |
241 | ||
242 | void ClientSession::setDbName(DbHandle db, const string &name) | |
243 | { | |
244 | IPC(ucsp_client_setDbName(UCSP_ARGS, db, name.c_str())); | |
245 | } | |
246 | ||
247 | ||
248 | // | |
249 | // Internal database management | |
250 | // | |
251 | DbHandle ClientSession::createDb(const DLDbIdentifier &dbId, | |
252 | const AccessCredentials *cred, const AclEntryInput *owner, | |
253 | const DBParameters ¶ms) | |
254 | { | |
255 | DatabaseAccessCredentials creds(cred, internalAllocator); | |
256 | CopyIn copycreds(creds.value(), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
257 | CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); | |
258 | // XXX/64 make xdr routines translate directly between dldbident and flat rep | |
259 | DataWalkers::DLDbFlatIdentifier ident(dbId); | |
260 | CopyIn id(&ident, reinterpret_cast<xdrproc_t>(xdr_DLDbFlatIdentifier)); | |
261 | DbHandle db; | |
262 | ||
263 | IPC(ucsp_client_createDb(UCSP_ARGS, &db, id.data(), id.length(), copycreds.data(), copycreds.length(), proto.data(), proto.length(), params)); | |
264 | ||
265 | return db; | |
266 | } | |
267 | ||
fa7225c8 A |
268 | DbHandle ClientSession::cloneDb(const DLDbIdentifier &newDbId, DbHandle srcDb) { |
269 | DataWalkers::DLDbFlatIdentifier ident(newDbId); | |
270 | CopyIn id(&ident, reinterpret_cast<xdrproc_t>(xdr_DLDbFlatIdentifier)); | |
271 | ||
272 | DbHandle db; | |
273 | IPC(ucsp_client_cloneDb(UCSP_ARGS, srcDb, id.data(), id.length(), &db)); | |
274 | return db; | |
275 | } | |
276 | ||
b1ab9ed8 A |
277 | DbHandle ClientSession::recodeDbForSync(DbHandle dbToClone, |
278 | DbHandle srcDb) | |
279 | { | |
280 | DbHandle newDb; | |
281 | ||
282 | IPC(ucsp_client_recodeDbForSync(UCSP_ARGS, dbToClone, srcDb, &newDb)); | |
fa7225c8 A |
283 | |
284 | return newDb; | |
b1ab9ed8 A |
285 | } |
286 | ||
e3d460c9 A |
287 | DbHandle ClientSession::recodeDbToVersion(uint32 newVersion, DbHandle srcDb) |
288 | { | |
289 | DbHandle newDb; | |
290 | ||
291 | IPC(ucsp_client_recodeDbToVersion(UCSP_ARGS, newVersion, srcDb, &newDb)); | |
292 | ||
293 | return newDb; | |
294 | } | |
295 | ||
fa7225c8 A |
296 | void ClientSession::recodeFinished(DbHandle db) |
297 | { | |
298 | IPC(ucsp_client_recodeFinished(UCSP_ARGS, db)); | |
299 | } | |
300 | ||
b1ab9ed8 A |
301 | DbHandle ClientSession::authenticateDbsForSync(const CssmData &dbHandleArray, |
302 | const CssmData &agentData) | |
303 | { | |
304 | DbHandle newDb; | |
305 | ||
306 | IPC(ucsp_client_authenticateDbsForSync(UCSP_ARGS, DATA(dbHandleArray), DATA(agentData), &newDb)); | |
307 | ||
308 | return newDb; | |
309 | } | |
310 | ||
311 | void ClientSession::commitDbForSync(DbHandle srcDb, DbHandle cloneDb, | |
312 | CssmData &blob, Allocator &alloc) | |
313 | { | |
314 | DataOutput outBlob(blob, alloc); | |
427c49bc | 315 | IPC(ucsp_client_commitDbForSync(UCSP_ARGS, srcDb, cloneDb, DATA_OUT(outBlob))); |
b1ab9ed8 A |
316 | } |
317 | ||
318 | DbHandle ClientSession::decodeDb(const DLDbIdentifier &dbId, | |
319 | const AccessCredentials *cred, const CssmData &blob) | |
320 | { | |
321 | // XXX/64 fold into one translation | |
322 | DatabaseAccessCredentials credentials(cred, internalAllocator); | |
323 | CopyIn creds(credentials.value(), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
324 | // XXX/64 fold into one translation | |
325 | DataWalkers::DLDbFlatIdentifier ident(dbId); | |
326 | CopyIn id(&ident, reinterpret_cast<xdrproc_t>(xdr_DLDbFlatIdentifier)); | |
327 | DbHandle db; | |
328 | ||
329 | IPC(ucsp_client_decodeDb(UCSP_ARGS, &db, id.data(), id.length(), creds.data(), creds.length(), DATA(blob))); | |
330 | ||
331 | return db; | |
332 | } | |
333 | ||
334 | void ClientSession::encodeDb(DbHandle db, CssmData &blob, Allocator &alloc) | |
335 | { | |
336 | DataOutput outBlob(blob, alloc); | |
427c49bc | 337 | IPC(ucsp_client_encodeDb(UCSP_ARGS, db, DATA_OUT(outBlob))); |
b1ab9ed8 A |
338 | } |
339 | ||
340 | void ClientSession::setDbParameters(DbHandle db, const DBParameters ¶ms) | |
341 | { | |
342 | IPC(ucsp_client_setDbParameters(UCSP_ARGS, db, params)); | |
343 | } | |
344 | ||
345 | void ClientSession::getDbParameters(DbHandle db, DBParameters ¶ms) | |
346 | { | |
347 | IPC(ucsp_client_getDbParameters(UCSP_ARGS, db, ¶ms)); | |
348 | } | |
349 | ||
350 | void ClientSession::changePassphrase(DbHandle db, const AccessCredentials *cred) | |
351 | { | |
352 | CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
353 | IPC(ucsp_client_changePassphrase(UCSP_ARGS, db, creds.data(), creds.length())); | |
354 | } | |
355 | ||
356 | ||
357 | void ClientSession::lock(DbHandle db) | |
358 | { | |
359 | IPC(ucsp_client_authenticateDb(UCSP_ARGS, db, CSSM_DB_ACCESS_RESET, NULL, 0)); | |
360 | //@@@VIRTUAL IPC(ucsp_client_lockDb(UCSP_ARGS, db)); | |
361 | } | |
362 | ||
363 | void ClientSession::lockAll (bool forSleep) | |
364 | { | |
365 | IPC(ucsp_client_lockAll (UCSP_ARGS, forSleep)); | |
366 | } | |
367 | ||
368 | void ClientSession::unlock(DbHandle db) | |
369 | { | |
370 | IPC(ucsp_client_unlockDb(UCSP_ARGS, db)); | |
371 | } | |
372 | ||
373 | void ClientSession::unlock(DbHandle db, const CssmData &passphrase) | |
374 | { | |
375 | IPC(ucsp_client_unlockDbWithPassphrase(UCSP_ARGS, db, DATA(passphrase))); | |
376 | } | |
377 | ||
427c49bc A |
378 | void ClientSession::stashDb(DbHandle db) |
379 | { | |
380 | IPC(ucsp_client_stashDb(UCSP_ARGS, db)); | |
381 | } | |
382 | ||
383 | void ClientSession::stashDbCheck(DbHandle db) | |
384 | { | |
385 | IPC(ucsp_client_stashDbCheck(UCSP_ARGS, db)); | |
386 | } | |
387 | ||
b1ab9ed8 A |
388 | bool ClientSession::isLocked(DbHandle db) |
389 | { | |
390 | boolean_t locked; | |
391 | IPC(ucsp_client_isLocked(UCSP_ARGS, db, &locked)); | |
392 | return locked; | |
393 | } | |
394 | ||
427c49bc A |
395 | void ClientSession::verifyKeyStorePassphrase(uint32_t retries) |
396 | { | |
397 | IPC(ucsp_client_verifyKeyStorePassphrase(UCSP_ARGS, retries)); | |
398 | } | |
399 | ||
400 | void ClientSession::resetKeyStorePassphrase(const CssmData &passphrase) | |
401 | { | |
402 | IPC(ucsp_client_resetKeyStorePassphrase(UCSP_ARGS, DATA(passphrase))); | |
403 | } | |
404 | ||
405 | void ClientSession::changeKeyStorePassphrase() | |
406 | { | |
407 | IPC(ucsp_client_changeKeyStorePassphrase(UCSP_ARGS)); | |
408 | } | |
b1ab9ed8 A |
409 | |
410 | // | |
411 | // Key control | |
412 | // | |
413 | void ClientSession::encodeKey(KeyHandle key, CssmData &blob, | |
414 | KeyUID *uid, Allocator &alloc) | |
415 | { | |
416 | // Not really used as output | |
417 | DataOutput oBlob(blob, alloc); | |
418 | void *uidp; | |
419 | mach_msg_type_number_t uidLength; | |
420 | ||
421 | IPC(ucsp_client_encodeKey(UCSP_ARGS, key, oBlob.data(), oBlob.length(), | |
422 | (uid != NULL), &uidp, &uidLength)); | |
423 | ||
424 | // return key uid if requested | |
425 | if (uid) { | |
426 | assert(uidLength == sizeof(KeyUID)); | |
427 | memcpy(uid, uidp, sizeof(KeyUID)); | |
428 | } | |
429 | } | |
430 | ||
431 | KeyHandle ClientSession::decodeKey(DbHandle db, const CssmData &blob, CssmKey::Header &header) | |
432 | { | |
433 | KeyHandle key; | |
434 | void *keyHeaderData; | |
435 | mach_msg_type_number_t keyHeaderDataLength; | |
436 | ||
427c49bc | 437 | IPC(ucsp_client_decodeKey(UCSP_ARGS, &key, &keyHeaderData, &keyHeaderDataLength, db, blob.data(), (mach_msg_type_number_t)blob.length())); |
b1ab9ed8 A |
438 | |
439 | CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true); | |
440 | header = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedKeyHeaderXDR.data())); | |
441 | ||
442 | return key; | |
443 | } | |
444 | ||
445 | // keychain synchronization | |
446 | void ClientSession::recodeKey(DbHandle oldDb, KeyHandle key, DbHandle newDb, | |
447 | CssmData &blob) | |
448 | { | |
449 | DataOutput outBlob(blob, returnAllocator); | |
427c49bc | 450 | IPC(ucsp_client_recodeKey(UCSP_ARGS, oldDb, key, newDb, DATA_OUT(outBlob))); |
b1ab9ed8 A |
451 | } |
452 | ||
453 | void ClientSession::releaseKey(KeyHandle key) | |
454 | { | |
455 | IPC(ucsp_client_releaseKey(UCSP_ARGS, key)); | |
456 | } | |
457 | ||
458 | ||
459 | CssmKeySize ClientSession::queryKeySizeInBits(KeyHandle key) | |
460 | { | |
461 | CssmKeySize length; | |
462 | IPC(ucsp_client_queryKeySizeInBits(UCSP_ARGS, key, &length)); | |
463 | return length; | |
464 | } | |
465 | ||
466 | ||
467 | uint32 ClientSession::getOutputSize(const Context &context, KeyHandle key, | |
468 | uint32 inputSize, bool encrypt) | |
469 | { | |
470 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
471 | uint32 outputSize; | |
472 | ||
473 | IPC(ucsp_client_getOutputSize(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, inputSize, encrypt, &outputSize)); | |
474 | return outputSize; | |
475 | } | |
476 | ||
477 | ||
478 | // | |
479 | // Random number generation. | |
480 | // This interfaces to the secure RNG inside the SecurityServer; it does not access | |
481 | // a PRNG in its CSP. If you need a reproducible PRNG, attach a local CSP and use it. | |
482 | // Note that this function does not allocate a buffer; it always fills the buffer provided. | |
483 | // | |
484 | void ClientSession::generateRandom(const Security::Context &context, CssmData &data, Allocator &alloc) | |
485 | { | |
486 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
487 | DataOutput result(data, alloc); | |
488 | ||
427c49bc | 489 | IPC(ucsp_client_generateRandom(UCSP_ARGS, 0, ctxcopy.data(), ctxcopy.length(), DATA_OUT(result))); |
b1ab9ed8 A |
490 | } |
491 | ||
492 | ||
493 | // | |
494 | // Signatures and MACs | |
495 | // | |
496 | void ClientSession::generateSignature(const Context &context, KeyHandle key, | |
497 | const CssmData &data, CssmData &signature, Allocator &alloc, CSSM_ALGORITHMS signOnlyAlgorithm) | |
498 | { | |
499 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
500 | DataOutput sig(signature, alloc); | |
501 | ||
502 | IPCKEY(ucsp_client_generateSignature(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, signOnlyAlgorithm, | |
427c49bc | 503 | DATA(data), DATA_OUT(sig)), |
b1ab9ed8 A |
504 | key, CSSM_ACL_AUTHORIZATION_SIGN); |
505 | } | |
506 | ||
507 | void ClientSession::verifySignature(const Context &context, KeyHandle key, | |
508 | const CssmData &data, const CssmData &signature, CSSM_ALGORITHMS verifyOnlyAlgorithm) | |
509 | { | |
510 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
511 | ||
512 | IPC(ucsp_client_verifySignature(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, verifyOnlyAlgorithm, DATA(data), DATA(signature))); | |
513 | } | |
514 | ||
515 | ||
516 | void ClientSession::generateMac(const Context &context, KeyHandle key, | |
517 | const CssmData &data, CssmData &signature, Allocator &alloc) | |
518 | { | |
519 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
520 | DataOutput sig(signature, alloc); | |
521 | ||
427c49bc | 522 | IPCKEY(ucsp_client_generateMac(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, DATA(data), DATA_OUT(sig)), |
b1ab9ed8 A |
523 | key, CSSM_ACL_AUTHORIZATION_MAC); |
524 | } | |
525 | ||
526 | void ClientSession::verifyMac(const Context &context, KeyHandle key, | |
527 | const CssmData &data, const CssmData &signature) | |
528 | { | |
529 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
530 | ||
531 | IPCKEY(ucsp_client_verifyMac(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, | |
532 | DATA(data), DATA(signature)), | |
533 | key, CSSM_ACL_AUTHORIZATION_MAC); | |
534 | } | |
535 | ||
536 | ||
537 | // | |
538 | // Encryption/Decryption | |
539 | // | |
540 | ||
541 | void ClientSession::encrypt(const Context &context, KeyHandle key, | |
542 | const CssmData &clear, CssmData &cipher, Allocator &alloc) | |
543 | { | |
544 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
545 | DataOutput cipherOut(cipher, alloc); | |
427c49bc | 546 | IPCKEY(ucsp_client_encrypt(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, DATA(clear), DATA_OUT(cipherOut)), |
b1ab9ed8 A |
547 | key, CSSM_ACL_AUTHORIZATION_ENCRYPT); |
548 | } | |
549 | ||
550 | void ClientSession::decrypt(const Context &context, KeyHandle key, | |
551 | const CssmData &cipher, CssmData &clear, Allocator &alloc) | |
552 | { | |
553 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
554 | DataOutput clearOut(clear, alloc); | |
555 | ||
427c49bc | 556 | IPCKEY(ucsp_client_decrypt(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), key, DATA(cipher), DATA_OUT(clearOut)), |
b1ab9ed8 A |
557 | key, CSSM_ACL_AUTHORIZATION_DECRYPT); |
558 | } | |
559 | ||
560 | ||
561 | // | |
562 | // Key generation | |
563 | // | |
564 | void ClientSession::generateKey(DbHandle db, const Context &context, uint32 keyUsage, uint32 keyAttr, | |
565 | const AccessCredentials *cred, const AclEntryInput *owner, | |
566 | KeyHandle &newKey, CssmKey::Header &newHeader) | |
567 | { | |
568 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
569 | CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
570 | CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); | |
571 | void *keyHeaderData; | |
572 | mach_msg_type_number_t keyHeaderDataLength; | |
573 | ||
574 | IPC(ucsp_client_generateKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), | |
575 | creds.data(), creds.length(), proto.data(), proto.length(), | |
576 | keyUsage, keyAttr, &newKey, &keyHeaderData, &keyHeaderDataLength)); | |
577 | ||
578 | CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true); | |
579 | newHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedKeyHeaderXDR.data())); | |
580 | } | |
581 | ||
582 | void ClientSession::generateKey(DbHandle db, const Context &context, | |
583 | uint32 pubKeyUsage, uint32 pubKeyAttr, | |
584 | uint32 privKeyUsage, uint32 privKeyAttr, | |
585 | const AccessCredentials *cred, const AclEntryInput *owner, | |
586 | KeyHandle &pubKey, CssmKey::Header &pubHeader, | |
587 | KeyHandle &privKey, CssmKey::Header &privHeader) | |
588 | { | |
589 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
590 | CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
591 | CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); | |
592 | void *pubKeyHeaderData, *privKeyHeaderData; | |
593 | mach_msg_type_number_t pubKeyHeaderDataLength, privKeyHeaderDataLength; | |
594 | ||
595 | IPC(ucsp_client_generateKeyPair(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), | |
596 | creds.data(), creds.length(), proto.data(), proto.length(), | |
597 | pubKeyUsage, pubKeyAttr, privKeyUsage, privKeyAttr, | |
598 | &pubKey, &pubKeyHeaderData, &pubKeyHeaderDataLength, | |
599 | &privKey, &privKeyHeaderData, &privKeyHeaderDataLength)); | |
600 | ||
601 | CopyOut wrappedPubKeyHeaderXDR(pubKeyHeaderData, pubKeyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true); | |
602 | pubHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedPubKeyHeaderXDR.data())); | |
603 | CopyOut wrappedPrivKeyHeaderXDR(privKeyHeaderData, privKeyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true); | |
604 | privHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedPrivKeyHeaderXDR.data())); | |
605 | ||
606 | } | |
607 | ||
608 | ||
609 | // | |
610 | // Key derivation | |
611 | // This is a bit strained; the incoming 'param' value may have structure, | |
612 | // and we use a synthetic CssmDeriveData structure (with ad-hoc walker) to | |
613 | // handle that. Param also is input/output, which is always a pain (not to mention | |
614 | // ill-defined by the CDSA standard). | |
615 | // | |
616 | // If you're here because an algorithm of yours requires structured parameter | |
617 | // input, go to security_cdsa_utilities/cssmwalkers.h and add a case to the | |
618 | // CssmDeriveData walker. | |
619 | // | |
620 | void ClientSession::deriveKey(DbHandle db, const Context &context, KeyHandle baseKey, | |
621 | CSSM_KEYUSE usage, CSSM_KEYATTR_FLAGS attrs, CssmData ¶m, | |
622 | const AccessCredentials *cred, const AclEntryInput *owner, | |
623 | KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &allocator) | |
624 | { | |
625 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
626 | CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
627 | CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); | |
628 | CSSM_DERIVE_DATA inParamForm = { context.algorithm(), param }; | |
629 | CopyIn inParam(&inParamForm, reinterpret_cast<xdrproc_t>(xdr_CSSM_DERIVE_DATA)); | |
630 | ||
631 | try | |
632 | { | |
633 | DataOutput paramOutput(param, allocator); | |
634 | void *keyHeaderData; | |
635 | mach_msg_type_number_t keyHeaderDataLength; | |
636 | ||
637 | IPCKEY(ucsp_client_deriveKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), baseKey, | |
638 | creds.data(), creds.length(), proto.data(), proto.length(), | |
427c49bc | 639 | inParam.data(), inParam.length(), DATA_OUT(paramOutput), |
b1ab9ed8 A |
640 | usage, attrs, &newKey, &keyHeaderData, &keyHeaderDataLength), |
641 | baseKey, CSSM_ACL_AUTHORIZATION_DERIVE); | |
642 | ||
643 | CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true); | |
644 | newHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedKeyHeaderXDR.data())); | |
645 | } | |
646 | catch (CssmError& e) | |
647 | { | |
648 | // filter out errors for CSSM_ALGID_PKCS5_PBKDF2 | |
649 | if (context.algorithm() != CSSM_ALGID_PKCS5_PBKDF2 && e.error != CSSMERR_CSP_OUTPUT_LENGTH_ERROR) | |
650 | { | |
651 | throw; | |
652 | } | |
653 | } | |
654 | } | |
655 | ||
656 | ||
657 | // | |
658 | // Digest generation | |
659 | // | |
660 | void ClientSession::getKeyDigest(KeyHandle key, CssmData &digest, Allocator &allocator) | |
661 | { | |
662 | DataOutput dig(digest, allocator); | |
427c49bc | 663 | IPC(ucsp_client_getKeyDigest(UCSP_ARGS, key, DATA_OUT(dig))); |
b1ab9ed8 A |
664 | } |
665 | ||
666 | ||
667 | // | |
668 | // Key wrapping and unwrapping | |
669 | // | |
670 | void ClientSession::wrapKey(const Context &context, KeyHandle wrappingKey, | |
671 | KeyHandle keyToBeWrapped, const AccessCredentials *cred, | |
672 | const CssmData *descriptiveData, CssmWrappedKey &wrappedKey, Allocator &alloc) | |
673 | { | |
674 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
675 | CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
676 | void *keyData; | |
677 | mach_msg_type_number_t keyDataLength; | |
678 | ||
679 | IPCKEY(ucsp_client_wrapKey(UCSP_ARGS, ctxcopy.data(), ctxcopy.length(), wrappingKey, | |
680 | creds.data(), creds.length(), | |
681 | keyToBeWrapped, OPTIONALDATA(descriptiveData), | |
682 | &keyData, &keyDataLength), | |
683 | keyToBeWrapped, | |
684 | context.algorithm() == CSSM_ALGID_NONE | |
685 | ? CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR : CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED); | |
686 | ||
687 | CopyOut wrappedKeyXDR(keyData, keyDataLength + sizeof(CSSM_KEY), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEY_PTR), true); | |
688 | CssmWrappedKey *wrappedKeyIPC = reinterpret_cast<CssmWrappedKey*>(wrappedKeyXDR.data()); | |
689 | wrappedKey.header() = wrappedKeyIPC->header(); | |
690 | wrappedKey.keyData() = CssmData(alloc.malloc(wrappedKeyIPC->keyData().length()), wrappedKeyIPC->keyData().length()); | |
691 | memcpy(wrappedKey.keyData().data(), wrappedKeyIPC->keyData(), wrappedKeyIPC->keyData().length()); | |
692 | } | |
693 | ||
694 | void ClientSession::unwrapKey(DbHandle db, const Context &context, KeyHandle key, | |
695 | KeyHandle publicKey, const CssmWrappedKey &wrappedKey, | |
696 | uint32 usage, uint32 attr, | |
697 | const AccessCredentials *cred, const AclEntryInput *acl, | |
698 | CssmData &descriptiveData, | |
699 | KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &alloc) | |
700 | { | |
701 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
702 | DataOutput descriptor(descriptiveData, alloc); | |
703 | CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
704 | CopyIn proto(acl ? &acl->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); | |
705 | CopyIn wrappedKeyXDR(&wrappedKey, reinterpret_cast<xdrproc_t>(xdr_CSSM_KEY)); | |
706 | void *keyHeaderData; | |
707 | mach_msg_type_number_t keyHeaderDataLength; | |
708 | ||
709 | IPCKEY(ucsp_client_unwrapKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), key, | |
710 | creds.data(), creds.length(), proto.data(), proto.length(), | |
427c49bc | 711 | publicKey, wrappedKeyXDR.data(), wrappedKeyXDR.length(), usage, attr, DATA_OUT(descriptor), |
b1ab9ed8 A |
712 | &newKey, &keyHeaderData, &keyHeaderDataLength), |
713 | key, CSSM_ACL_AUTHORIZATION_DECRYPT); | |
714 | ||
715 | CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true); | |
716 | newHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedKeyHeaderXDR.data())); | |
717 | } | |
718 | ||
719 | ||
720 | // | |
721 | // ACL management | |
722 | // | |
723 | void ClientSession::getAcl(AclKind kind, GenericHandle key, const char *tag, | |
724 | uint32 &infoCount, AclEntryInfo * &infoArray, Allocator &alloc) | |
725 | { | |
726 | uint32 count; | |
727 | void* info; mach_msg_type_number_t infoLength; | |
728 | IPC(ucsp_client_getAcl(UCSP_ARGS, kind, key, | |
729 | (tag != NULL), tag ? tag : "", | |
730 | &count, &info, &infoLength)); | |
731 | ||
732 | CSSM_ACL_ENTRY_INFO_ARRAY_PTR aclsArray; | |
733 | if (!::copyout_chunked(info, infoLength, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_INFO_ARRAY_PTR), reinterpret_cast<void**>(&aclsArray))) | |
734 | CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR); | |
735 | ||
736 | infoCount = aclsArray->count; | |
737 | infoArray = reinterpret_cast<AclEntryInfo*>(aclsArray->acls); | |
738 | free(aclsArray); | |
739 | } | |
740 | ||
741 | void ClientSession::changeAcl(AclKind kind, GenericHandle key, const AccessCredentials &cred, | |
742 | const AclEdit &edit) | |
743 | { | |
744 | CopyIn creds(&cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
745 | //@@@ ignoring callback | |
746 | CopyIn newEntry(edit.newEntry(), reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_INPUT)); | |
747 | ||
748 | IPCKEY(ucsp_client_changeAcl(UCSP_ARGS, kind, key, creds.data(), creds.length(), | |
749 | edit.mode(), toIPCHandle(edit.handle()), newEntry.data(), newEntry.length()), | |
750 | key, CSSM_ACL_AUTHORIZATION_CHANGE_ACL); | |
751 | } | |
752 | ||
753 | void ClientSession::getOwner(AclKind kind, GenericHandle key, AclOwnerPrototype &owner, | |
754 | Allocator &alloc) | |
755 | { | |
756 | void* proto; mach_msg_type_number_t protoLength; | |
757 | IPC(ucsp_client_getOwner(UCSP_ARGS, kind, key, &proto, &protoLength)); | |
758 | ||
759 | CSSM_ACL_OWNER_PROTOTYPE_PTR tmpOwner; | |
760 | if (!::copyout_chunked(proto, protoLength, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_OWNER_PROTOTYPE_PTR), reinterpret_cast<void **>(&tmpOwner))) | |
761 | CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR); | |
762 | owner = *static_cast<AclOwnerPrototypePtr>(tmpOwner); | |
763 | free(tmpOwner); | |
764 | } | |
765 | ||
766 | void ClientSession::changeOwner(AclKind kind, GenericHandle key, | |
767 | const AccessCredentials &cred, const AclOwnerPrototype &proto) | |
768 | { | |
769 | CopyIn creds(&cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
770 | CopyIn protos(&proto, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_OWNER_PROTOTYPE)); | |
771 | IPCKEY(ucsp_client_setOwner(UCSP_ARGS, kind, key, creds.data(), creds.length(), protos.data(), protos.length()), | |
772 | key, CSSM_ACL_AUTHORIZATION_CHANGE_OWNER); | |
773 | } | |
774 | ||
775 | ||
776 | void ClientSession::getKeyAcl(DbHandle db, const char *tag, | |
777 | uint32 &count, AclEntryInfo * &info, Allocator &alloc) | |
778 | { getAcl(keyAcl, db, tag, count, info, alloc); } | |
779 | ||
780 | void ClientSession::changeKeyAcl(DbHandle db, const AccessCredentials &cred, | |
781 | const AclEdit &edit) | |
782 | { changeAcl(keyAcl, db, cred, edit); } | |
783 | ||
784 | void ClientSession::getKeyOwner(DbHandle db, AclOwnerPrototype &owner, Allocator &alloc) | |
785 | { getOwner(keyAcl, db, owner, alloc); } | |
786 | ||
787 | void ClientSession::changeKeyOwner(DbHandle db, const AccessCredentials &cred, | |
788 | const AclOwnerPrototype &edit) | |
789 | { changeOwner(keyAcl, db, cred, edit); } | |
790 | ||
791 | void ClientSession::getDbAcl(DbHandle db, const char *tag, | |
792 | uint32 &count, AclEntryInfo * &info, Allocator &alloc) | |
793 | { getAcl(dbAcl, db, tag, count, info, alloc); } | |
794 | ||
795 | void ClientSession::changeDbAcl(DbHandle db, const AccessCredentials &cred, | |
796 | const AclEdit &edit) | |
797 | { changeAcl(dbAcl, db, cred, edit); } | |
798 | ||
799 | void ClientSession::getDbOwner(DbHandle db, AclOwnerPrototype &owner, Allocator &alloc) | |
800 | { getOwner(dbAcl, db, owner, alloc); } | |
801 | ||
802 | void ClientSession::changeDbOwner(DbHandle db, const AccessCredentials &cred, | |
803 | const AclOwnerPrototype &edit) | |
804 | { changeOwner(dbAcl, db, cred, edit); } | |
805 | ||
806 | ||
807 | // | |
808 | // Database key management | |
809 | // | |
810 | void ClientSession::extractMasterKey(DbHandle db, const Context &context, DbHandle sourceDb, | |
811 | uint32 keyUsage, uint32 keyAttr, | |
812 | const AccessCredentials *cred, const AclEntryInput *owner, | |
813 | KeyHandle &newKey, CssmKey::Header &newHeader, Allocator &alloc) | |
814 | { | |
815 | CopyIn ctxcopy(&context, reinterpret_cast<xdrproc_t>(xdr_CSSM_CONTEXT)); | |
816 | CopyIn creds(cred, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACCESS_CREDENTIALS)); | |
817 | CopyIn proto(owner ? &owner->proto() : NULL, reinterpret_cast<xdrproc_t>(xdr_CSSM_ACL_ENTRY_PROTOTYPE)); | |
818 | void *keyHeaderData; | |
819 | mach_msg_type_number_t keyHeaderDataLength; | |
820 | ||
821 | IPC(ucsp_client_extractMasterKey(UCSP_ARGS, db, ctxcopy.data(), ctxcopy.length(), sourceDb, | |
822 | creds.data(), creds.length(), proto.data(), proto.length(), | |
823 | keyUsage, keyAttr, &newKey, &keyHeaderData, &keyHeaderDataLength)); | |
824 | ||
825 | CopyOut wrappedKeyHeaderXDR(keyHeaderData, keyHeaderDataLength + sizeof(CSSM_KEYHEADER), reinterpret_cast<xdrproc_t>(xdr_CSSM_KEYHEADER_PTR), true); | |
826 | newHeader = *static_cast<CssmKey::Header *>(reinterpret_cast<CSSM_KEYHEADER*>(wrappedKeyHeaderXDR.data())); | |
827 | } | |
828 | ||
829 | ||
b1ab9ed8 A |
830 | void ClientSession::postNotification(NotificationDomain domain, NotificationEvent event, const CssmData &data) |
831 | { | |
832 | uint32 seq = ++mGlobal().thread().notifySeq; | |
833 | #if !defined(NDEBUG) | |
834 | if (getenv("NOTIFYJITTER")) { | |
835 | // artificially reverse odd/even sequences to test securityd's jitter buffer | |
836 | seq += 2 * (seq % 2) - 1; | |
fa7225c8 | 837 | secinfo("notify", "POSTING FAKE SEQUENCE %d NOTIFICATION", seq); |
b1ab9ed8 A |
838 | } |
839 | #endif //NDEBUG | |
fa7225c8 | 840 | secinfo("notify", "posting domain 0x%x event %d sequence %d", |
b1ab9ed8 A |
841 | domain, event, seq); |
842 | IPC(ucsp_client_postNotification(UCSP_ARGS, domain, event, DATA(data), seq)); | |
843 | } | |
844 | ||
b1ab9ed8 | 845 | |
b1ab9ed8 A |
846 | // |
847 | // Code Signing related | |
848 | // | |
849 | void ClientSession::registerHosting(mach_port_t hostingPort, SecCSFlags flags) | |
850 | { | |
851 | IPC(ucsp_client_registerHosting(UCSP_ARGS, hostingPort, flags)); | |
852 | } | |
853 | ||
854 | mach_port_t ClientSession::hostingPort(pid_t pid) | |
855 | { | |
856 | mach_port_t result; | |
857 | IPC(ucsp_client_hostingPort(UCSP_ARGS, pid, &result)); | |
858 | return result; | |
859 | } | |
860 | ||
861 | SecGuestRef ClientSession::createGuest(SecGuestRef host, | |
862 | uint32_t status, const char *path, const CssmData &cdhash, const CssmData &attributes, SecCSFlags flags) | |
863 | { | |
864 | SecGuestRef newGuest; | |
865 | IPC(ucsp_client_createGuest(UCSP_ARGS, host, status, path, DATA(cdhash), DATA(attributes), flags, &newGuest)); | |
866 | if (flags & kSecCSDedicatedHost) { | |
fa7225c8 | 867 | secinfo("ssclient", "setting dedicated guest to 0x%x (was 0x%x)", |
b1ab9ed8 A |
868 | mDedicatedGuest, newGuest); |
869 | mDedicatedGuest = newGuest; | |
870 | } | |
871 | return newGuest; | |
872 | } | |
873 | ||
874 | void ClientSession::setGuestStatus(SecGuestRef guest, uint32 status, const CssmData &attributes) | |
875 | { | |
876 | IPC(ucsp_client_setGuestStatus(UCSP_ARGS, guest, status, DATA(attributes))); | |
877 | } | |
878 | ||
879 | void ClientSession::removeGuest(SecGuestRef host, SecGuestRef guest) | |
880 | { | |
881 | IPC(ucsp_client_removeGuest(UCSP_ARGS, host, guest)); | |
882 | } | |
883 | ||
884 | void ClientSession::selectGuest(SecGuestRef newGuest) | |
885 | { | |
886 | if (mDedicatedGuest) { | |
fa7225c8 | 887 | secinfo("ssclient", "ignoring selectGuest(0x%x) because dedicated guest=0x%x", |
b1ab9ed8 A |
888 | newGuest, mDedicatedGuest); |
889 | } else { | |
fa7225c8 | 890 | secinfo("ssclient", "switching to guest 0x%x", newGuest); |
b1ab9ed8 A |
891 | mGlobal().thread().currentGuest = newGuest; |
892 | } | |
893 | } | |
894 | ||
895 | SecGuestRef ClientSession::selectedGuest() const | |
896 | { | |
897 | if (mDedicatedGuest) | |
898 | return mDedicatedGuest; | |
899 | else | |
900 | return mGlobal().thread().currentGuest; | |
901 | } | |
902 | ||
fa7225c8 A |
903 | // |
904 | // Testing related | |
905 | // | |
906 | ||
907 | // Return the number of Keychain users prompts securityd has considered showing. | |
908 | // On non-internal installs, this returns 0. | |
909 | void ClientSession::getUserPromptAttempts(uint32_t& attempts) { | |
910 | IPC(ucsp_client_getUserPromptAttempts(UCSP_ARGS, &attempts)); | |
911 | } | |
912 | ||
b1ab9ed8 A |
913 | |
914 | } // end namespace SecurityServer | |
915 | } // end namespace Security |