Skip to content

Commit

Permalink
Fix resetting and accidental key damaging/deleting FB5 port (#7415)
Browse files Browse the repository at this point in the history
This should add key correctness check in case of resetting encryption key on Classic server with multiple attachments, and fix hanging Super server in case of accidental key damaging/deleting
  • Loading branch information
AlexeyMochalov authored and AlexPeshkoff committed Dec 21, 2022
1 parent 45e9c97 commit 3897cd7
Showing 1 changed file with 78 additions and 12 deletions.
90 changes: 78 additions & 12 deletions src/jrd/CryptoManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,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);
Expand All @@ -368,19 +368,56 @@ namespace Jrd {
else
keyName = "";

loadPlugin(tdbb, hdr->hdr_crypt_plugin);
pluginName = 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);
pluginName = 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<IKeyHolderPlugin> 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<IDbCryptPlugin> 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))
Expand Down Expand Up @@ -484,7 +521,7 @@ namespace Jrd {
checkFactory = NULL;

// store new one
if (dbb.dbb_config->getServerMode() == MODE_SUPER && !holderLess)
if (!holderLess)
checkFactory = cryptControl.release();
}

Expand Down Expand Up @@ -661,7 +698,36 @@ namespace Jrd {
}
}
else
{
for (GetPlugins<IKeyHolderPlugin> 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<IDbCryptPlugin> 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);

Expand Down

0 comments on commit 3897cd7

Please sign in to comment.