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