diff --git a/src/jrd/CryptoManager.cpp b/src/jrd/CryptoManager.cpp index a54a14f953c..aaec8b0b2ee 100644 --- a/src/jrd/CryptoManager.cpp +++ b/src/jrd/CryptoManager.cpp @@ -368,7 +368,7 @@ namespace Jrd { // tdbb w/o attachment comes when database is shutting down in the end of detachDatabase() // the only needed here page is header, i.e. we can live w/o cryptPlugin - if ((crypt || process) && (!cryptPlugin) && tdbb->getAttachment()) + if ((crypt || process) && tdbb->getAttachment()) { ClumpletWriter hc(ClumpletWriter::UnTagged, hdr->hdr_page_size); hdr.getClumplets(hc); @@ -377,18 +377,55 @@ namespace Jrd { else keyName = ""; - loadPlugin(tdbb, hdr->hdr_crypt_plugin); - - string valid; - calcValidation(valid, cryptPlugin); - if (hc.find(Ods::HDR_crypt_hash)) + if (!cryptPlugin) { - hc.getString(hash); - if (hash != valid) - (Arg::Gds(isc_bad_crypt_key) << keyName).raise(); + loadPlugin(tdbb, hdr->hdr_crypt_plugin); + string valid; + calcValidation(valid, cryptPlugin); + if (hc.find(Ods::HDR_crypt_hash)) + { + hc.getString(hash); + if (hash != valid) + (Arg::Gds(isc_bad_crypt_key) << keyName).raise(); + } + else + hash = valid; } else - hash = valid; + { + for (GetPlugins keyControl(IPluginManager::TYPE_KEY_HOLDER, dbb.dbb_config); + keyControl.hasData(); keyControl.next()) + { + // check does keyHolder want to provide a key for us + IKeyHolderPlugin* keyHolder = keyControl.plugin(); + + FbLocalStatus st; + int keyCallbackRc = keyHolder->keyCallback(&st, tdbb->getAttachment()->att_crypt_callback); + st.check(); + if (!keyCallbackRc) + continue; + + // validate a key + AutoPlugin crypt(checkFactory->makeInstance()); + setDbInfo(crypt); + crypt->setKey(&st, 1, &keyHolder, keyName.c_str()); + + + string valid; + calcValidation(valid, crypt); + if (hc.find(Ods::HDR_crypt_hash)) + { + hc.getString(hash); + if (hash == valid) + { + // unload old plugin and set new one + PluginManagerInterfacePtr()->releasePlugin(cryptPlugin); + cryptPlugin = NULL; + cryptPlugin = crypt.release(); + } + } + } + } } if (cryptPlugin && (flags & CRYPT_HDR_INIT)) @@ -495,7 +532,7 @@ namespace Jrd { checkFactory = NULL; // store new one - if (dbb.dbb_config->getServerMode() == MODE_SUPER && !holderLess) + if (!holderLess) checkFactory = cryptControl.release(); } @@ -670,7 +707,36 @@ namespace Jrd { } } else + { + for (GetPlugins keyControl(IPluginManager::TYPE_KEY_HOLDER, dbb.dbb_config); + keyControl.hasData(); keyControl.next()) + { + // check does keyHolder want to provide a key for us + IKeyHolderPlugin* keyHolder = keyControl.plugin(); + + FbLocalStatus st; + int keyCallbackRc = keyHolder->keyCallback(&st, tdbb->getAttachment()->att_crypt_callback); + st.check(); + if (!keyCallbackRc) + continue; + + // validate a key + AutoPlugin crypt(checkFactory->makeInstance()); + setDbInfo(crypt); + crypt->setKey(&st, 1, &keyHolder, keyName.c_str()); + + + string valid; + calcValidation(valid, crypt); + if (hc.find(Ods::HDR_crypt_hash)) + { + hc.getString(hash); + if (hash != valid) + (Arg::Gds(isc_bad_crypt_key) << keyName).raise(); + } + } header->hdr_flags &= ~Ods::hdr_encrypted; + } hdr.setClumplets(hc);