+ secnotice("integrity", "dbBlobVersion() failed for an unknown reason after a rename");
+ return false;
+ }
+
+ endsWithKeychainDb = (path.size() > keychainDbSuffix.size() && (0 == path.compare(path.size() - keychainDbSuffix.size(), keychainDbSuffix.size(), keychainDbSuffix)));
+ keychainDbPath = StorageManager::makeKeychainDbFilename(path);
+ secnotice("integrity", "after rename, our database thinks that it is %s", path.c_str());
+ }
+
+ // Migrate an old keychain in ~/Library/Keychains
+ if(inHomeLibraryKeychains && dbBlobVersion != SecurityServer::DbBlob::version_partition && !endsWithKeychainDb) {
+ // We can only attempt to migrate an unlocked keychain.
+ if(mDb->isLocked()) {
+ // However, it's possible that while we weren't doing any keychain operations, someone upgraded the keychain,
+ // and then locked it. No way around hitting the filesystem here: check for the existence of a new file and,
+ // if no new file exists, quit.
+ DLDbIdentifier mungedDLDbIdentifier = StorageManager::mungeDLDbIdentifier(mDb->dlDbIdentifier(), false);
+ string mungedPath(mungedDLDbIdentifier.dbName());
+
+ // If this matches the file we already have, skip the upgrade. Otherwise, continue.
+ if(mungedPath == path) {
+ secnotice("integrity", "skipping upgrade for locked keychain %s\n", mDb->name());
+ return false;
+ }
+ }
+
+ result = keychainMigration(path, dbBlobVersion, keychainDbPath, SecurityServer::DbBlob::version_partition);
+ } else if(inHomeLibraryKeychains && dbBlobVersion == SecurityServer::DbBlob::version_partition && !endsWithKeychainDb) {
+ // This is a new-style keychain with the wrong name, try to rename it
+ attemptKeychainRename(path, keychainDbPath, dbBlobVersion);
+ result = true;
+ } else if(isSystemKeychain && dbBlobVersion == SecurityServer::DbBlob::version_partition) {
+ // Try to "unupgrade" the system keychain, to clean up our old issues
+ secnotice("integrity", "attempting downgrade for %s version %d (%d %d %d)", path.c_str(), dbBlobVersion, inHomeLibraryKeychains, endsWithKeychainDb, isSystemKeychain);
+
+ // First step: acquire the credentials to allow for ACL modification
+ SecurityServer::SystemKeychainKey skk(kSystemUnlockFile);
+ if(skk.valid()) {
+ // We've managed to read the key; now, create credentials using it
+ CssmClient::Key systemKeychainMasterKey(csp(), skk.key(), true);
+ CssmClient::AclFactory::MasterKeyUnlockCredentials creds(systemKeychainMasterKey, Allocator::standard(Allocator::sensitive));
+
+ // Attempt the downgrade, using our master key as the ACL override
+ result = keychainMigration(path, dbBlobVersion, path, SecurityServer::DbBlob::version_MacOS_10_0, creds.getAccessCredentials());
+ } else {
+ secnotice("integrity", "Couldn't read System.keychain key, skipping update");