]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
3 | * |
4 | * The contents of this file constitute Original Code as defined in and are | |
5 | * subject to the Apple Public Source License Version 1.2 (the 'License'). | |
6 | * You may not use this file except in compliance with the License. Please obtain | |
7 | * a copy of the License at http://www.apple.com/publicsource and read it before | |
8 | * using this file. | |
9 | * | |
10 | * This Original Code and all software distributed under the License are | |
11 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS | |
12 | * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT | |
13 | * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | |
14 | * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the | |
15 | * specific language governing rights and limitations under the License. | |
16 | */ | |
17 | ||
18 | ||
19 | // | |
20 | // SSDatabase.cpp - Security Server database object | |
21 | // | |
22 | #include "SSDatabase.h" | |
23 | ||
24 | #include <security_cdsa_utilities/KeySchema.h> | |
e3d460c9 A |
25 | #include <security_utilities/CSPDLTransaction.h> |
26 | #include <Security/SecBasePriv.h> | |
b1ab9ed8 A |
27 | |
28 | using namespace CssmClient; | |
29 | using namespace SecurityServer; | |
30 | ||
31 | const char *const SSDatabaseImpl::DBBlobRelationName = "DBBlob"; | |
32 | ||
33 | ||
34 | SSDatabaseImpl::SSDatabaseImpl(ClientSession &inClientSession, const CssmClient::DL &dl, | |
35 | const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation) | |
36 | : Db::Impl(dl, inDbName, inDbLocation), mClientSession(inClientSession), mSSDbHandle(noDb) | |
37 | { | |
e3d460c9 | 38 | mTransaction = NULL; |
b1ab9ed8 A |
39 | } |
40 | ||
41 | SSDatabaseImpl::~SSDatabaseImpl() | |
427c49bc | 42 | try |
b1ab9ed8 A |
43 | { |
44 | if (mSSDbHandle != noDb) | |
45 | mClientSession.releaseDb(mSSDbHandle); | |
46 | } | |
427c49bc A |
47 | catch (...) |
48 | { | |
49 | } | |
b1ab9ed8 A |
50 | |
51 | SSUniqueRecord | |
fa7225c8 | 52 | SSDatabaseImpl::ssInsert(CSSM_DB_RECORDTYPE recordType, |
b1ab9ed8 | 53 | const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, |
fa7225c8 | 54 | const CSSM_DATA *data) |
b1ab9ed8 A |
55 | { |
56 | SSUniqueRecord uniqueId(SSDatabase(this)); | |
57 | check(CSSM_DL_DataInsert(handle(), recordType, | |
58 | attributes, | |
59 | data, uniqueId)); | |
60 | // Activate uniqueId so CSSM_DL_FreeUniqueRecord() gets called when it goes out of scope. | |
61 | uniqueId->activate(); | |
62 | return uniqueId; | |
63 | } | |
64 | ||
65 | void | |
66 | SSDatabaseImpl::authenticate(CSSM_DB_ACCESS_TYPE inAccessRequest, | |
67 | const CSSM_ACCESS_CREDENTIALS *inAccessCredentials) | |
68 | { | |
69 | mClientSession.authenticateDb(dbHandle(), inAccessRequest, | |
70 | AccessCredentials::overlay(inAccessCredentials)); | |
71 | } | |
72 | ||
73 | void | |
74 | SSDatabaseImpl::lock() | |
75 | { | |
76 | mClientSession.lock(dbHandle()); | |
77 | ||
78 | } | |
79 | ||
80 | void | |
81 | SSDatabaseImpl::unlock() | |
82 | { | |
83 | mClientSession.unlock(dbHandle()); | |
84 | } | |
85 | ||
86 | void | |
87 | SSDatabaseImpl::unlock(const CSSM_DATA &password) | |
88 | { | |
89 | mClientSession.unlock(dbHandle(), CssmData::overlay(password)); | |
90 | } | |
91 | ||
427c49bc A |
92 | void |
93 | SSDatabaseImpl::stash() | |
94 | { | |
95 | mClientSession.stashDb(dbHandle()); | |
96 | } | |
97 | ||
98 | void | |
99 | SSDatabaseImpl::stashCheck() | |
100 | { | |
101 | mClientSession.stashDbCheck(dbHandle()); | |
102 | } | |
103 | ||
b1ab9ed8 A |
104 | void |
105 | SSDatabaseImpl::getSettings(uint32 &outIdleTimeout, bool &outLockOnSleep) | |
106 | { | |
107 | DBParameters parameters; | |
108 | mClientSession.getDbParameters(dbHandle(), parameters); | |
109 | outIdleTimeout = parameters.idleTimeout; | |
110 | outLockOnSleep = parameters.lockOnSleep; | |
111 | } | |
112 | ||
113 | void | |
114 | SSDatabaseImpl::setSettings(uint32 inIdleTimeout, bool inLockOnSleep) | |
115 | { | |
116 | DBParameters parameters; | |
117 | parameters.idleTimeout = inIdleTimeout; | |
118 | parameters.lockOnSleep = inLockOnSleep; | |
119 | mClientSession.setDbParameters(dbHandle(), parameters); | |
120 | ||
121 | // Reencode the db blob. | |
122 | CssmDataContainer dbb(allocator()); | |
123 | mClientSession.encodeDb(mSSDbHandle, dbb, allocator()); | |
124 | getDbBlobId()->modify(DBBlobRelationID, NULL, &dbb, CSSM_DB_MODIFY_ATTRIBUTE_NONE); | |
125 | } | |
126 | ||
127 | bool | |
128 | SSDatabaseImpl::isLocked() | |
129 | { | |
130 | return mClientSession.isLocked(dbHandle()); | |
131 | } | |
132 | ||
133 | void | |
134 | SSDatabaseImpl::changePassphrase(const CSSM_ACCESS_CREDENTIALS *cred) | |
135 | { | |
136 | mClientSession.changePassphrase(dbHandle(), AccessCredentials::overlay(cred)); | |
137 | ||
138 | // Reencode the db blob. | |
139 | CssmDataContainer dbb(allocator()); | |
140 | mClientSession.encodeDb(mSSDbHandle, dbb, allocator()); | |
141 | getDbBlobId()->modify(DBBlobRelationID, NULL, &dbb, CSSM_DB_MODIFY_ATTRIBUTE_NONE); | |
142 | } | |
143 | ||
144 | DbHandle | |
145 | SSDatabaseImpl::dbHandle() | |
146 | { | |
147 | activate(); | |
148 | if (mForked()) { | |
149 | // re-establish the dbHandle with the SecurityServer | |
150 | CssmDataContainer dbb(allocator()); | |
151 | getDbBlobId(&dbb); | |
152 | mSSDbHandle = mClientSession.decodeDb(mIdentifier, | |
153 | AccessCredentials::overlay(accessCredentials()), dbb); | |
154 | } | |
155 | return mSSDbHandle; | |
156 | } | |
157 | ||
158 | void | |
159 | SSDatabaseImpl::commonCreate(const DLDbIdentifier &dlDbIdentifier, bool &autoCommit) | |
160 | { | |
161 | mIdentifier = dlDbIdentifier; | |
162 | // Set to false if autocommit should remain off after the create. | |
163 | autoCommit = true; | |
164 | ||
165 | // OpenParameters to use | |
166 | CSSM_APPLEDL_OPEN_PARAMETERS newOpenParameters = | |
167 | { | |
168 | sizeof(CSSM_APPLEDL_OPEN_PARAMETERS), | |
169 | CSSM_APPLEDL_OPEN_PARAMETERS_VERSION, | |
170 | CSSM_FALSE, // do not auto-commit | |
171 | 0 // mask - do not use following fields | |
172 | }; | |
173 | ||
174 | // Get the original openParameters and apply them to the ones we | |
175 | // are passing in. | |
176 | const CSSM_APPLEDL_OPEN_PARAMETERS *inOpenParameters = | |
177 | reinterpret_cast<const CSSM_APPLEDL_OPEN_PARAMETERS *>(openParameters()); | |
178 | if (inOpenParameters) | |
179 | { | |
180 | switch (inOpenParameters->version) | |
181 | { | |
182 | case 1: | |
183 | if (inOpenParameters->length < sizeof(CSSM_APPLEDL_OPEN_PARAMETERS)) | |
184 | CssmError::throwMe(CSSMERR_APPLEDL_INVALID_OPEN_PARAMETERS); | |
185 | ||
186 | newOpenParameters.mask = inOpenParameters->mask; | |
187 | newOpenParameters.mode = inOpenParameters->mode; | |
188 | /*DROPTHROUGH*/ | |
189 | case 0: | |
190 | //if (inOpenParameters->length < sizeof(CSSM_APPLEDL_OPEN_PARAMETERS_V0)) | |
191 | // CssmError::throwMe(CSSMERR_APPLEDL_INVALID_OPEN_PARAMETERS); | |
192 | ||
193 | // This will determine whether we leave autocommit off or not. | |
194 | autoCommit = inOpenParameters->autoCommit == CSSM_FALSE ? false : true; | |
195 | break; | |
196 | ||
197 | default: | |
198 | CssmError::throwMe(CSSMERR_APPLEDL_INVALID_OPEN_PARAMETERS); | |
199 | } | |
200 | } | |
201 | ||
202 | // Use the new openParameters | |
203 | openParameters(&newOpenParameters); | |
204 | try | |
205 | { | |
206 | DbImpl::create(); | |
207 | // Restore the original openparameters again. | |
208 | openParameters(inOpenParameters); | |
209 | } | |
210 | catch (...) | |
211 | { | |
212 | // Make sure restore the original openparameters again even if | |
213 | // create throws. | |
214 | openParameters(inOpenParameters); | |
215 | throw; | |
216 | } | |
217 | ||
218 | // @@@ The CSSM_DB_SCHEMA_ATTRIBUTE_INFO and CSSM_DB_SCHEMA_INDEX_INFO | |
219 | // arguments should be optional. | |
220 | createRelation(DBBlobRelationID, DBBlobRelationName, | |
221 | 0, (CSSM_DB_SCHEMA_ATTRIBUTE_INFO *)42, | |
222 | 0, (CSSM_DB_SCHEMA_INDEX_INFO *)42); | |
223 | ||
224 | // @@@ Only iff not already in mDbInfo | |
225 | createRelation(CSSM_DL_DB_RECORD_PUBLIC_KEY, "CSSM_DL_DB_RECORD_PUBLIC_KEY", | |
226 | KeySchema::KeySchemaAttributeCount, KeySchema::KeySchemaAttributeList, | |
227 | KeySchema::KeySchemaIndexCount, KeySchema::KeySchemaIndexList); | |
228 | ||
229 | // @@@ Only iff not already in mDbInfo | |
230 | createRelation(CSSM_DL_DB_RECORD_PRIVATE_KEY, "CSSM_DL_DB_RECORD_PRIVATE_KEY", | |
231 | KeySchema::KeySchemaAttributeCount, KeySchema::KeySchemaAttributeList, | |
232 | KeySchema::KeySchemaIndexCount, KeySchema::KeySchemaIndexList); | |
233 | ||
234 | // @@@ Only iff not already in mDbInfo | |
235 | createRelation(CSSM_DL_DB_RECORD_SYMMETRIC_KEY, "CSSM_DL_DB_RECORD_SYMMETRIC_KEY", | |
236 | KeySchema::KeySchemaAttributeCount, KeySchema::KeySchemaAttributeList, | |
237 | KeySchema::KeySchemaIndexCount, KeySchema::KeySchemaIndexList); | |
238 | } | |
239 | ||
240 | void | |
fa7225c8 | 241 | SSDatabaseImpl::ssCreate(const DLDbIdentifier &dlDbIdentifier) |
b1ab9ed8 A |
242 | { |
243 | try | |
244 | { | |
245 | bool autoCommit; | |
246 | commonCreate(dlDbIdentifier, autoCommit); | |
247 | ||
248 | DBParameters dbParameters; | |
249 | memset(&dbParameters, 0, sizeof(DBParameters)); | |
250 | dbParameters.idleTimeout = kDefaultIdleTimeout; | |
251 | dbParameters.lockOnSleep = kDefaultLockOnSleep; | |
252 | ||
253 | const AccessCredentials *cred = NULL; | |
254 | const AclEntryInput *owner = NULL; | |
255 | if (resourceControlContext()) | |
256 | { | |
257 | cred = AccessCredentials::overlay(resourceControlContext()->AccessCred); | |
258 | owner = &AclEntryInput::overlay(resourceControlContext()->InitialAclEntry); | |
259 | } | |
260 | mSSDbHandle = mClientSession.createDb(dlDbIdentifier, cred, owner, dbParameters); | |
261 | CssmDataContainer dbb(allocator()); | |
262 | mClientSession.encodeDb(mSSDbHandle, dbb, allocator()); | |
fa7225c8 | 263 | secnotice("integrity", "opening %s", name()); |
b1ab9ed8 A |
264 | Db::Impl::insert(DBBlobRelationID, NULL, &dbb); |
265 | if (autoCommit) | |
266 | { | |
267 | passThrough(CSSM_APPLEFILEDL_COMMIT, NULL); | |
268 | passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, | |
269 | reinterpret_cast<const void *>(1)); | |
270 | } | |
271 | } | |
272 | catch(CssmError e) | |
273 | { | |
274 | if (e.error != CSSMERR_DL_DATASTORE_ALREADY_EXISTS) | |
275 | { | |
276 | DbImpl::deleteDb(); | |
277 | } | |
278 | throw; | |
279 | } | |
280 | catch(...) | |
281 | { | |
282 | DbImpl::deleteDb(); | |
283 | throw; | |
284 | } | |
285 | } | |
286 | ||
287 | void | |
fa7225c8 | 288 | SSDatabaseImpl::ssCreateWithBlob(const DLDbIdentifier &dlDbIdentifier, const CSSM_DATA &blob) |
b1ab9ed8 A |
289 | { |
290 | try | |
291 | { | |
292 | bool autoCommit; | |
293 | commonCreate(dlDbIdentifier, autoCommit); | |
fa7225c8 | 294 | secnotice("integrity", "opening %s", name()); |
b1ab9ed8 A |
295 | Db::Impl::insert(DBBlobRelationID, NULL, &blob); |
296 | if (autoCommit) | |
297 | { | |
298 | passThrough(CSSM_APPLEFILEDL_COMMIT, NULL); | |
299 | passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, | |
300 | reinterpret_cast<const void *>(1)); | |
301 | } | |
302 | } | |
303 | catch(...) | |
304 | { | |
305 | DbImpl::deleteDb(); | |
306 | throw; | |
307 | } | |
308 | } | |
309 | ||
310 | void | |
fa7225c8 | 311 | SSDatabaseImpl::ssOpen(const DLDbIdentifier &dlDbIdentifier) |
b1ab9ed8 | 312 | { |
fa7225c8 | 313 | load(dlDbIdentifier); |
b1ab9ed8 | 314 | |
fa7225c8 A |
315 | CssmDataContainer dbb(allocator()); |
316 | getDbBlobId(&dbb); | |
e3d460c9 A |
317 | |
318 | // Pull our version out of the database blob | |
b1ab9ed8 A |
319 | mSSDbHandle = mClientSession.decodeDb(dlDbIdentifier, AccessCredentials::overlay(accessCredentials()), dbb); |
320 | } | |
321 | ||
322 | void | |
fa7225c8 A |
323 | SSDatabaseImpl::load(const DLDbIdentifier &dlDbIdentifier) { |
324 | mIdentifier = dlDbIdentifier; | |
325 | Db::Impl::open(); | |
326 | ||
327 | CssmDataContainer dbb(allocator()); | |
328 | getDbBlobId(&dbb); | |
329 | ||
330 | secnotice("integrity", "loading %s", name()); | |
331 | } | |
332 | ||
333 | void | |
334 | SSDatabaseImpl::ssRecode(const CssmData &dbHandleArray, const CssmData &agentData) | |
b1ab9ed8 | 335 | { |
e3d460c9 A |
336 | // Start a transaction (Implies activate()). |
337 | passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, 0); | |
338 | ||
339 | try | |
340 | { | |
341 | CssmDataContainer dbb(allocator()); | |
342 | // Make sure mSSDbHandle is valid. | |
343 | CssmClient::DbUniqueRecord dbBlobId = getDbBlobId(&dbb); | |
344 | if (mForked()) { | |
345 | // re-establish the dbHandle with the SecurityServer | |
346 | mSSDbHandle = mClientSession.decodeDb(mIdentifier, | |
347 | AccessCredentials::overlay(accessCredentials()), dbb); | |
348 | } | |
349 | dbb.clear(); | |
350 | ||
351 | DbHandle successfulHdl = mClientSession.authenticateDbsForSync(dbHandleArray, agentData); | |
352 | ||
353 | // Create a newDbHandle using the master secrets from the dbBlob we are | |
354 | // recoding to. | |
355 | SecurityServer::DbHandle clonedDbHandle = | |
356 | mClientSession.recodeDbForSync(successfulHdl, mSSDbHandle); | |
357 | ||
358 | // @@@ If the dbb changed since we fetched it we should abort or | |
359 | // retry the operation here. | |
360 | ||
361 | recodeHelper(clonedDbHandle, dbBlobId); | |
362 | ||
363 | // Commit the transaction to the db | |
364 | passThrough(CSSM_APPLEFILEDL_COMMIT, NULL); | |
365 | passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, | |
366 | reinterpret_cast<const void *>(1)); | |
367 | } | |
368 | catch (...) | |
369 | { | |
370 | // Something went wrong rollback the transaction | |
371 | passThrough(CSSM_APPLEFILEDL_ROLLBACK, NULL); | |
372 | passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, | |
373 | reinterpret_cast<const void *>(1)); | |
374 | throw; | |
375 | } | |
376 | } | |
b1ab9ed8 | 377 | |
e3d460c9 A |
378 | uint32 |
379 | SSDatabaseImpl::recodeDbToVersion(uint32 newBlobVersion) { | |
380 | // Start a transaction (Implies activate()). | |
381 | DLTransaction transaction(handle()); | |
382 | ||
383 | try | |
384 | { | |
385 | if(isLocked()) { | |
fa7225c8 | 386 | secnotice("integrity", "is currently locked"); |
e3d460c9 | 387 | } else { |
fa7225c8 | 388 | secnotice("integrity", "is already unlocked"); |
e3d460c9 A |
389 | } |
390 | ||
391 | CssmDataContainer dbb(allocator()); | |
392 | // Make sure mSSDbHandle is valid. | |
393 | CssmClient::DbUniqueRecord dbBlobId = getDbBlobId(&dbb); | |
394 | ||
395 | // always establish the dbHandle with the SecurityServer | |
396 | mSSDbHandle = mClientSession.decodeDb(mIdentifier, AccessCredentials::overlay(accessCredentials()), dbb); | |
397 | dbb.clear(); | |
398 | ||
399 | // Create a newDbHandle using the master secrets from the dbBlob we are recoding to. | |
fa7225c8 | 400 | secnotice("integrity", "recoding db with handle %d", mSSDbHandle); |
e3d460c9 | 401 | SecurityServer::DbHandle clonedDbHandle = mClientSession.recodeDbToVersion(newBlobVersion, mSSDbHandle); |
fa7225c8 | 402 | secnotice("integrity", "received db with handle %d", clonedDbHandle); |
e3d460c9 A |
403 | |
404 | // @@@ If the dbb changed since we fetched it we should abort or | |
405 | // retry the operation here. | |
406 | ||
407 | uint32 newBlobVersion = recodeHelper(clonedDbHandle, dbBlobId); | |
fa7225c8 | 408 | secnotice("integrity", "committing transaction %d", clonedDbHandle); |
e3d460c9 A |
409 | |
410 | // Commit the transaction to the db | |
fa7225c8 | 411 | transaction.commit(); |
e3d460c9 A |
412 | return newBlobVersion; |
413 | } | |
414 | catch (...) | |
415 | { | |
416 | throw; | |
417 | } | |
418 | } | |
b1ab9ed8 | 419 | |
fa7225c8 A |
420 | void |
421 | SSDatabaseImpl::recodeFinished() { | |
422 | mClientSession.recodeFinished(mSSDbHandle); | |
423 | } | |
424 | ||
e3d460c9 A |
425 | void SSDatabaseImpl::takeFileLock() { |
426 | if(mTransaction) { | |
427 | // you're already in the middle of a file lock. | |
428 | return; | |
429 | } | |
430 | mTransaction = new DLTransaction(handle()); | |
431 | passThrough(CSSM_APPLEFILEDL_TAKE_FILE_LOCK, NULL, NULL); | |
432 | } | |
b1ab9ed8 | 433 | |
e3d460c9 A |
434 | void SSDatabaseImpl::releaseFileLock(bool success) { |
435 | if(mTransaction) { | |
436 | try { | |
437 | if(success) { | |
fa7225c8 | 438 | mTransaction->commit(); |
e3d460c9 | 439 | } |
fa7225c8 | 440 | // If we didn't commit, the destructor will roll back and re-enable autocommit |
e3d460c9 A |
441 | delete mTransaction; |
442 | mTransaction = NULL; | |
443 | } catch(...) { | |
444 | mTransaction = NULL; | |
445 | throw; | |
446 | } | |
447 | } | |
448 | } | |
b1ab9ed8 | 449 | |
e3d460c9 A |
450 | void SSDatabaseImpl::makeBackup() { |
451 | passThrough(CSSM_APPLEFILEDL_MAKE_BACKUP, NULL, NULL); | |
452 | } | |
b1ab9ed8 | 453 | |
fa7225c8 A |
454 | void SSDatabaseImpl::makeCopy(const char* path) { |
455 | passThrough(CSSM_APPLEFILEDL_MAKE_COPY, path, NULL); | |
456 | } | |
457 | ||
458 | void SSDatabaseImpl::deleteFile() { | |
459 | passThrough(CSSM_APPLEFILEDL_DELETE_FILE, NULL, NULL); | |
460 | } | |
461 | ||
462 | SSDatabase SSDatabaseImpl::ssCloneTo(const DLDbIdentifier& dldbidentifier) { | |
463 | makeCopy(dldbidentifier.dbName()); | |
464 | SSDatabase db(mClientSession, dl(), dldbidentifier.dbName(), dldbidentifier.dbLocation()); | |
465 | ||
466 | db->load(dldbidentifier); | |
467 | db->mSSDbHandle = mClientSession.cloneDb(dldbidentifier, mSSDbHandle); | |
468 | ||
469 | return db; | |
470 | } | |
471 | ||
472 | ||
b1ab9ed8 | 473 | |
e3d460c9 A |
474 | uint32 SSDatabaseImpl::recodeHelper(SecurityServer::DbHandle clonedDbHandle, CssmClient::DbUniqueRecord& dbBlobId) { |
475 | // Recode all keys | |
476 | DbCursor cursor(SSDatabase(this)); | |
477 | cursor->recordType(CSSM_DL_DB_RECORD_ALL_KEYS); | |
478 | CssmDataContainer keyBlob(allocator()); | |
479 | CssmClient::DbUniqueRecord keyBlobId; | |
480 | DbAttributes attributes; | |
481 | while (cursor->next(&attributes, &keyBlob, keyBlobId)) | |
482 | { | |
483 | KeyHandle keyHandle = 0; | |
484 | try { | |
485 | // Decode the old key | |
486 | CssmKey::Header header; | |
487 | keyHandle = mClientSession.decodeKey(mSSDbHandle, keyBlob, header); | |
488 | // Recode the key | |
489 | CssmDataContainer newKeyBlob(mClientSession.returnAllocator); | |
490 | mClientSession.recodeKey(mSSDbHandle, keyHandle, clonedDbHandle, newKeyBlob); | |
491 | mClientSession.releaseKey(keyHandle); | |
492 | keyHandle = 0; | |
493 | // Write the recoded key blob to the database | |
494 | keyBlobId->modify(attributes.recordType(), NULL, &newKeyBlob, | |
495 | CSSM_DB_MODIFY_ATTRIBUTE_NONE); | |
496 | } catch (CssmError cssme) { | |
497 | const char* errStr = cssmErrorString(cssme.error); | |
fa7225c8 A |
498 | secnotice("integrity", "corrupt item while recoding: %d %s", (int) cssme.error, errStr); |
499 | secnotice("integrity", "deleting corrupt item"); | |
e3d460c9 A |
500 | |
501 | ||
502 | keyBlobId->deleteRecord(); | |
503 | ||
504 | if(keyHandle != 0) { | |
505 | // tell securityd not to worry about this key again | |
506 | try { | |
fa7225c8 | 507 | secnotice("integrity", "releasing corrupt key"); |
e3d460c9 A |
508 | mClientSession.releaseKey(keyHandle); |
509 | } catch(CssmError cssme) { | |
510 | // swallow the error | |
511 | const char* errStr = cssmErrorString(cssme.error); | |
fa7225c8 | 512 | secnotice("integrity", "couldn't release corrupt key: %d %s", (int) cssme.error, errStr); |
e3d460c9 A |
513 | } |
514 | } | |
515 | } | |
516 | } | |
517 | ||
518 | // Commit the new blob to securityd, reencode the db blob, release the | |
519 | // cloned db handle and commit the new blob to the db. | |
520 | CssmDataContainer dbb(allocator()); | |
fa7225c8 | 521 | secnotice("integrity", "committing %d", clonedDbHandle); |
e3d460c9 A |
522 | mClientSession.commitDbForSync(mSSDbHandle, clonedDbHandle, |
523 | dbb, allocator()); | |
524 | dbBlobId->modify(DBBlobRelationID, NULL, &dbb, | |
525 | CSSM_DB_MODIFY_ATTRIBUTE_NONE); | |
526 | return getDbVersionFromBlob(dbb); | |
b1ab9ed8 A |
527 | } |
528 | ||
e3d460c9 | 529 | |
b1ab9ed8 A |
530 | void SSDatabaseImpl::getRecordIdentifier(CSSM_DB_UNIQUE_RECORD_PTR uniqueRecord, CSSM_DATA &recordID) |
531 | { | |
532 | // the unique ID is composed of three uint32s (plus one filler word). Pull | |
533 | // them out and byte swap them | |
534 | recordID.Length = sizeof (uint32) * kNumIDWords; | |
535 | recordID.Data = (uint8*) allocator().malloc(recordID.Length); | |
536 | ||
537 | // copy the data | |
538 | uint32* dest = (uint32*) recordID.Data; | |
539 | uint32* src = (uint32*) uniqueRecord->RecordIdentifier.Data; | |
540 | ||
541 | dest[0] = htonl (src[0]); | |
542 | dest[1] = htonl (src[1]); | |
543 | dest[2] = htonl (src[2]); | |
544 | dest[3] = 0; | |
545 | } | |
546 | ||
fa7225c8 | 547 | void SSDatabaseImpl::ssCopyBlob(CSSM_DATA& data) |
b1ab9ed8 A |
548 | { |
549 | // get the blob from the database | |
550 | CssmDataContainer dbb(allocator()); | |
551 | getDbBlobId(&dbb); | |
552 | ||
553 | // copy the data back | |
554 | data.Data = dbb.Data; | |
555 | data.Length = dbb.Length; | |
556 | ||
557 | // zap the return structure so that we don't get zapped when dbb goes out of scope... | |
558 | dbb.Data = NULL; | |
559 | dbb.Length = 0; | |
560 | } | |
561 | ||
e3d460c9 A |
562 | uint32 |
563 | SSDatabaseImpl::dbBlobVersion() { | |
564 | CssmDataContainer dbb(allocator()); | |
565 | getDbBlobId(&dbb); | |
566 | return getDbVersionFromBlob(dbb); | |
567 | } | |
568 | ||
569 | uint32 | |
570 | SSDatabaseImpl::getDbVersionFromBlob(const CssmData& dbb) { | |
571 | DbBlob* x = Allocator::standard().malloc<DbBlob>(dbb.length()); | |
572 | memcpy(x, dbb, dbb.length()); | |
573 | uint32 version = x->version(); | |
574 | Allocator::standard().free(x); | |
575 | return version; | |
576 | } | |
577 | ||
b1ab9ed8 A |
578 | DbUniqueRecordImpl * |
579 | SSDatabaseImpl::newDbUniqueRecord() | |
580 | { | |
581 | return new SSUniqueRecordImpl(SSDatabase(this)); | |
582 | } | |
583 | ||
584 | CssmClient::DbUniqueRecord | |
585 | SSDatabaseImpl::getDbBlobId(CssmDataContainer *dbb) | |
586 | { | |
587 | CssmClient::DbUniqueRecord dbBlobId; | |
588 | ||
589 | DbCursor cursor(SSDatabase(this)); | |
590 | cursor->recordType(DBBlobRelationID); | |
591 | if (!cursor->next(NULL, dbb, dbBlobId)) | |
592 | CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT); | |
593 | ||
594 | return dbBlobId; | |
595 | } | |
596 | ||
597 | ||
598 | ||
599 | SSUniqueRecordImpl::SSUniqueRecordImpl(const SSDatabase &db) | |
600 | : DbUniqueRecord::Impl(db) | |
601 | { | |
602 | } | |
603 | ||
604 | SSUniqueRecordImpl::~SSUniqueRecordImpl() | |
605 | { | |
606 | } | |
607 | ||
608 | SSDatabase | |
609 | SSUniqueRecordImpl::database() const | |
610 | { | |
611 | return parent<SSDatabase>(); | |
612 | } |