mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 20:03:02 +01:00
Frontported CORE-5735: Additional keyholder opens unauthorized connections to encrypted database
This commit is contained in:
parent
50ad173172
commit
a8473b0ee3
@ -3787,12 +3787,12 @@ interface is main interface of database crypt key holder plugin.</font></p>
|
||||
<li/>
|
||||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
|
||||
useOnlyOwnKeys(StatusType* status) – informs firebird engine
|
||||
whether a key, provided by another key holder, be used or not. Makes
|
||||
sense only for SuperServer – only it can share database crypt keys
|
||||
whether a key, provided by key holder, can be used in other attachments.
|
||||
Makes sense only for SuperServer – only it can share database crypt keys
|
||||
between attachments. Returning FB_TRUE from this method enforces
|
||||
firebird to make sure that this particular key holder (and therefore
|
||||
in turn attachment related to it) provides correct crypt key before
|
||||
letting it to work with database.</font></p>
|
||||
in turn attachment related to it) provides correct crypt key for
|
||||
any other attachment to this database.</font></p>
|
||||
<li/>
|
||||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKeyCallback*
|
||||
chainHandle(StatusType* status) – support of a chain of key
|
||||
|
@ -1818,6 +1818,8 @@ C --
|
||||
PARAMETER (GDS__hdr_overflow = 335545202)
|
||||
INTEGER*4 GDS__vld_plugins
|
||||
PARAMETER (GDS__vld_plugins = 335545203)
|
||||
INTEGER*4 GDS__db_crypt_key
|
||||
PARAMETER (GDS__db_crypt_key = 335545204)
|
||||
INTEGER*4 GDS__gfix_db_name
|
||||
PARAMETER (GDS__gfix_db_name = 335740929)
|
||||
INTEGER*4 GDS__gfix_invalid_sw
|
||||
|
@ -1813,6 +1813,8 @@ const
|
||||
gds_hdr_overflow = 335545202;
|
||||
isc_vld_plugins = 335545203;
|
||||
gds_vld_plugins = 335545203;
|
||||
isc_db_crypt_key = 335545204;
|
||||
gds_db_crypt_key = 335545204;
|
||||
isc_gfix_db_name = 335740929;
|
||||
gds_gfix_db_name = 335740929;
|
||||
isc_gfix_invalid_sw = 335740930;
|
||||
|
@ -905,6 +905,7 @@ static const struct {
|
||||
{"map_overflow", 335545201},
|
||||
{"hdr_overflow", 335545202},
|
||||
{"vld_plugins", 335545203},
|
||||
{"db_crypt_key", 335545204},
|
||||
{"gfix_db_name", 335740929},
|
||||
{"gfix_invalid_sw", 335740930},
|
||||
{"gfix_incmp_sw", 335740932},
|
||||
|
@ -939,6 +939,7 @@ const ISC_STATUS isc_map_event = 335545200L;
|
||||
const ISC_STATUS isc_map_overflow = 335545201L;
|
||||
const ISC_STATUS isc_hdr_overflow = 335545202L;
|
||||
const ISC_STATUS isc_vld_plugins = 335545203L;
|
||||
const ISC_STATUS isc_db_crypt_key = 335545204L;
|
||||
const ISC_STATUS isc_gfix_db_name = 335740929L;
|
||||
const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
|
||||
const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
|
||||
@ -1413,7 +1414,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L;
|
||||
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
|
||||
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
|
||||
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
|
||||
const ISC_STATUS isc_err_max = 1357;
|
||||
const ISC_STATUS isc_err_max = 1358;
|
||||
|
||||
#else /* c definitions */
|
||||
|
||||
@ -2322,6 +2323,7 @@ const ISC_STATUS isc_err_max = 1357;
|
||||
#define isc_map_overflow 335545201L
|
||||
#define isc_hdr_overflow 335545202L
|
||||
#define isc_vld_plugins 335545203L
|
||||
#define isc_db_crypt_key 335545204L
|
||||
#define isc_gfix_db_name 335740929L
|
||||
#define isc_gfix_invalid_sw 335740930L
|
||||
#define isc_gfix_incmp_sw 335740932L
|
||||
@ -2796,7 +2798,7 @@ const ISC_STATUS isc_err_max = 1357;
|
||||
#define isc_trace_switch_param_miss 337182758L
|
||||
#define isc_trace_param_act_notcompat 337182759L
|
||||
#define isc_trace_mandatory_switch_miss 337182760L
|
||||
#define isc_err_max 1357
|
||||
#define isc_err_max 1358
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -908,6 +908,7 @@ Data source : @4"}, /* eds_statement */
|
||||
{335545201, "Global mapping memory overflow"}, /* map_overflow */
|
||||
{335545202, "Header page overflow - too many clumplets on it"}, /* hdr_overflow */
|
||||
{335545203, "No matching client/server authentication plugins configured for execute statement in embedded datasource"}, /* vld_plugins */
|
||||
{335545204, "Missing database encryption key for your attachment"}, /* db_crypt_key */
|
||||
{335740929, "data base file name (@1) already given"}, /* gfix_db_name */
|
||||
{335740930, "invalid switch @1"}, /* gfix_invalid_sw */
|
||||
{335740932, "incompatible switch combination"}, /* gfix_incmp_sw */
|
||||
|
@ -904,6 +904,7 @@ static const struct {
|
||||
{335545201, -902}, /* 881 map_overflow */
|
||||
{335545202, -901}, /* 882 hdr_overflow */
|
||||
{335545203, -901}, /* 883 vld_plugins */
|
||||
{335545204, -902}, /* 884 db_crypt_key */
|
||||
{335740929, -901}, /* 1 gfix_db_name */
|
||||
{335740930, -901}, /* 2 gfix_invalid_sw */
|
||||
{335740932, -901}, /* 4 gfix_incmp_sw */
|
||||
|
@ -904,6 +904,7 @@ static const struct {
|
||||
{335545201, "54000"}, // 881 map_overflow
|
||||
{335545202, "54000"}, // 882 hdr_overflow
|
||||
{335545203, "28000"}, // 883 vld_plugins
|
||||
{335545204, "08004"}, // 884 db_crypt_key
|
||||
{335740929, "00000"}, // 1 gfix_db_name
|
||||
{335740930, "00000"}, // 2 gfix_invalid_sw
|
||||
{335740932, "00000"}, // 4 gfix_incmp_sw
|
||||
|
@ -278,7 +278,8 @@ namespace Jrd {
|
||||
: PermanentStorage(*tdbb->getDatabase()->dbb_permanent),
|
||||
sync(this),
|
||||
keyName(getPool()),
|
||||
keyHolderPlugins(getPool(), this),
|
||||
keyProviders(getPool()),
|
||||
keyConsumers(getPool()),
|
||||
hash(getPool()),
|
||||
dbInfo(FB_NEW DbInfo(this)),
|
||||
cryptThreadId(0),
|
||||
@ -430,7 +431,47 @@ namespace Jrd {
|
||||
IDbCryptPlugin* p = cryptControl->plugin();
|
||||
setDbInfo(p);
|
||||
|
||||
keyHolderPlugins.init(p, keyName);
|
||||
bool fLoad = false, fTry = false;
|
||||
bool holderLess = false;
|
||||
for (GetPlugins<IKeyHolderPlugin> keyControl(IPluginManager::TYPE_KEY_HOLDER, dbb.dbb_config);
|
||||
keyControl.hasData(); keyControl.next())
|
||||
{
|
||||
IKeyHolderPlugin* keyPlugin = keyControl.plugin();
|
||||
|
||||
FbLocalStatus st;
|
||||
int keyCallbackRc = keyPlugin->keyCallback(&st, tdbb->getAttachment()->att_crypt_callback);
|
||||
st.check();
|
||||
if (!keyCallbackRc)
|
||||
continue;
|
||||
|
||||
fTry = true;
|
||||
p->setKey(&st, 1, &keyPlugin, keyName.c_str());
|
||||
if (st.isSuccess())
|
||||
{
|
||||
if (!keyPlugin->useOnlyOwnKeys(&st))
|
||||
{
|
||||
MutexLockGuard g(holdersMutex, FB_FUNCTION);
|
||||
keyProviders.push(tdbb->getAttachment());
|
||||
}
|
||||
fLoad = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fTry)
|
||||
{
|
||||
FbLocalStatus status;
|
||||
p->setKey(&status, 0, NULL, keyName.c_str());
|
||||
if (status.isSuccess())
|
||||
{
|
||||
holderLess = true;
|
||||
fLoad = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fLoad)
|
||||
Arg::Gds(isc_db_crypt_key).raise();
|
||||
|
||||
cryptPlugin = p;
|
||||
cryptPlugin->addRef();
|
||||
|
||||
@ -439,11 +480,8 @@ namespace Jrd {
|
||||
checkFactory = NULL;
|
||||
|
||||
// store new one
|
||||
if (dbb.dbb_config->getServerMode() == MODE_SUPER)
|
||||
{
|
||||
if (dbb.dbb_config->getServerMode() == MODE_SUPER && !holderLess)
|
||||
checkFactory = cryptControl.release();
|
||||
keyHolderPlugins.validateNewAttachment(tdbb->getAttachment(), keyName);
|
||||
}
|
||||
}
|
||||
|
||||
void CryptoManager::prepareChangeCryptState(thread_db* tdbb, const MetaName& plugName,
|
||||
@ -598,7 +636,25 @@ namespace Jrd {
|
||||
hc.insertString(Ods::HDR_crypt_key, keyName);
|
||||
|
||||
if (checkFactory)
|
||||
keyHolderPlugins.validateExistingAttachments(keyName);
|
||||
{
|
||||
// Create local copy of existing attachments
|
||||
AttVector existing;
|
||||
{
|
||||
SyncLockGuard dsGuard(&dbb.dbb_sync, SYNC_EXCLUSIVE, FB_FUNCTION);
|
||||
for (Attachment* att = dbb.dbb_attachments; att; att = att->att_next)
|
||||
existing.push(att);
|
||||
}
|
||||
|
||||
// Loop through attachments
|
||||
MutexLockGuard g(holdersMutex, FB_FUNCTION);
|
||||
|
||||
for (unsigned n = 0; n < existing.getCount(); ++n)
|
||||
validateAttachment(tdbb, existing[n], true);
|
||||
|
||||
// In case of missing providers close consumers
|
||||
if (keyProviders.getCount() == 0)
|
||||
shutdownConsumers(tdbb);
|
||||
}
|
||||
}
|
||||
else
|
||||
header->hdr_flags &= ~Ods::hdr_encrypted;
|
||||
@ -640,6 +696,16 @@ namespace Jrd {
|
||||
startCryptThread(tdbb);
|
||||
}
|
||||
|
||||
void CryptoManager::shutdownConsumers(thread_db* tdbb)
|
||||
{
|
||||
MutexLockGuard g(holdersMutex, FB_FUNCTION);
|
||||
|
||||
for (unsigned i = 0; i < keyConsumers.getCount(); ++i)
|
||||
keyConsumers[i]->signalShutdown(isc_db_crypt_key);
|
||||
|
||||
keyConsumers.clear();
|
||||
}
|
||||
|
||||
void CryptoManager::blockingAstChangeCryptState()
|
||||
{
|
||||
AsyncContextHolder tdbb(&dbb, FB_FUNCTION);
|
||||
@ -656,18 +722,94 @@ namespace Jrd {
|
||||
LCK_convert(tdbb, stateLock, CRYPT_RELEASE, LCK_NO_WAIT);
|
||||
}
|
||||
|
||||
bool CryptoManager::validateAttachment(thread_db* tdbb, Attachment* att, bool consume)
|
||||
{
|
||||
bool fLoad = false, fProvide = false;
|
||||
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, att->att_crypt_callback);
|
||||
st.check();
|
||||
if (!keyCallbackRc)
|
||||
continue;
|
||||
|
||||
// validate a key
|
||||
AutoPtr<IDbCryptPlugin, ReleasePlugin> crypt(checkFactory->makeInstance());
|
||||
setDbInfo(crypt);
|
||||
crypt->setKey(&st, 1, &keyHolder, keyName.c_str());
|
||||
|
||||
if (st.isSuccess())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (checkValidation(crypt))
|
||||
fLoad = true;
|
||||
}
|
||||
catch (const Exception&)
|
||||
{ } // Ignore possible errors, continue analysis
|
||||
|
||||
if (fLoad)
|
||||
fProvide = !keyHolder->useOnlyOwnKeys(&st);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply results
|
||||
|
||||
if (fProvide)
|
||||
keyProviders.push(att);
|
||||
else if (consume && !fLoad)
|
||||
keyConsumers.push(att);
|
||||
|
||||
return fLoad;
|
||||
}
|
||||
|
||||
void CryptoManager::attach(thread_db* tdbb, Attachment* att)
|
||||
{
|
||||
keyHolderPlugins.attach(att, dbb.dbb_config);
|
||||
if (checkFactory)
|
||||
{
|
||||
MutexLockGuard g(holdersMutex, FB_FUNCTION);
|
||||
|
||||
Factory* f = checkFactory;
|
||||
if (!validateAttachment(tdbb, att, false))
|
||||
{
|
||||
if (keyProviders.getCount() == 0)
|
||||
Arg::Gds(isc_db_crypt_key).raise();
|
||||
|
||||
keyConsumers.push(att);
|
||||
}
|
||||
}
|
||||
|
||||
lockAndReadHeader(tdbb, CRYPT_HDR_INIT);
|
||||
}
|
||||
|
||||
if (f && f == checkFactory)
|
||||
void CryptoManager::detach(thread_db* tdbb, Attachment* att)
|
||||
{
|
||||
if (!keyHolderPlugins.validateNewAttachment(att, keyName))
|
||||
(Arg::Gds(isc_bad_crypt_key) << keyName).raise();
|
||||
if (!checkFactory)
|
||||
return;
|
||||
|
||||
MutexLockGuard g(holdersMutex, FB_FUNCTION);
|
||||
for (unsigned n = 0; n < keyConsumers.getCount(); ++n)
|
||||
{
|
||||
if (keyConsumers[n] == att)
|
||||
{
|
||||
keyConsumers.remove(n);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned n = 0; n < keyProviders.getCount(); ++n)
|
||||
{
|
||||
if (keyProviders[n] == att)
|
||||
{
|
||||
keyProviders.remove(n);
|
||||
if (keyProviders.getCount() == 0)
|
||||
shutdownConsumers(tdbb);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1193,203 +1335,6 @@ namespace Jrd {
|
||||
return keyName.c_str();
|
||||
}
|
||||
|
||||
void CryptoManager::KeyHolderPlugins::attach(Attachment* att, const Config* config)
|
||||
{
|
||||
MutexLockGuard g(holdersMutex, FB_FUNCTION);
|
||||
|
||||
for (GetPlugins<IKeyHolderPlugin> keyControl(IPluginManager::TYPE_KEY_HOLDER, config);
|
||||
keyControl.hasData(); keyControl.next())
|
||||
{
|
||||
IKeyHolderPlugin* keyPlugin = keyControl.plugin();
|
||||
FbLocalStatus st;
|
||||
bool flProvide = false;
|
||||
|
||||
if (keyPlugin->keyCallback(&st, att->att_crypt_callback))
|
||||
flProvide = true;
|
||||
else
|
||||
{
|
||||
st.check();
|
||||
flProvide = !keyPlugin->useOnlyOwnKeys(&st);
|
||||
// Ignore error condition to support old plugins
|
||||
}
|
||||
|
||||
if (flProvide)
|
||||
{
|
||||
// holder is going to provide a key
|
||||
PerAttHolders* pa = NULL;
|
||||
|
||||
for (unsigned i = 0; i < knownHolders.getCount(); ++i)
|
||||
{
|
||||
if (knownHolders[i].first == att)
|
||||
{
|
||||
pa = &knownHolders[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pa)
|
||||
{
|
||||
pa = &(knownHolders.add());
|
||||
pa->first = att;
|
||||
}
|
||||
|
||||
if (pa)
|
||||
{
|
||||
pa->second.add(keyPlugin);
|
||||
keyPlugin->addRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CryptoManager::KeyHolderPlugins::detach(Attachment* att)
|
||||
{
|
||||
MutexLockGuard g(holdersMutex, FB_FUNCTION);
|
||||
|
||||
for (unsigned i = 0; i < knownHolders.getCount(); ++i)
|
||||
{
|
||||
if (knownHolders[i].first == att)
|
||||
{
|
||||
releaseHolders(knownHolders[i]);
|
||||
knownHolders.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CryptoManager::KeyHolderPlugins::releaseHolders(PerAttHolders& pa)
|
||||
{
|
||||
unsigned j = 0;
|
||||
|
||||
for (; j < pa.second.getCount(); ++j)
|
||||
PluginManagerInterfacePtr()->releasePlugin(pa.second[j]);
|
||||
|
||||
pa.second.removeCount(0, j);
|
||||
}
|
||||
|
||||
void CryptoManager::KeyHolderPlugins::init(IDbCryptPlugin* crypt, const MetaName& keyName)
|
||||
{
|
||||
MutexLockGuard g(holdersMutex, FB_FUNCTION);
|
||||
|
||||
Firebird::HalfStaticArray<Firebird::IKeyHolderPlugin*, 64> holdersVector;
|
||||
|
||||
for (unsigned i = 0; i < knownHolders.getCount(); ++i)
|
||||
{
|
||||
PerAttHolders pa = knownHolders[i];
|
||||
for (unsigned j = 0; j < pa.second.getCount(); ++j)
|
||||
holdersVector.push(pa.second[j]);
|
||||
}
|
||||
|
||||
FbLocalStatus st;
|
||||
crypt->setKey(&st, holdersVector.getCount(), holdersVector.begin(), keyName.c_str());
|
||||
st.check();
|
||||
}
|
||||
|
||||
bool CryptoManager::KeyHolderPlugins::validateHoldersGroup(PerAttHolders& pa, const MetaName& keyName)
|
||||
{
|
||||
FbLocalStatus st;
|
||||
fb_assert(holdersMutex.locked());
|
||||
|
||||
for (unsigned j = 0; j < pa.second.getCount(); ++j)
|
||||
{
|
||||
IKeyHolderPlugin* keyHolder = pa.second[j];
|
||||
if (!keyHolder->useOnlyOwnKeys(&st))
|
||||
return true;
|
||||
|
||||
if (validateHolder(keyHolder, keyName))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CryptoManager::KeyHolderPlugins::validateNewAttachment(Attachment* att, const MetaName& keyName)
|
||||
{
|
||||
FbLocalStatus st;
|
||||
MutexLockGuard g(holdersMutex, FB_FUNCTION);
|
||||
|
||||
// Check for current attachment
|
||||
for (unsigned i = 0; i < knownHolders.getCount(); ++i)
|
||||
{
|
||||
PerAttHolders& pa = knownHolders[i];
|
||||
|
||||
if (pa.first == att)
|
||||
{
|
||||
bool empty = (pa.second.getCount() == 0);
|
||||
bool result = empty ? false : validateHoldersGroup(pa, keyName);
|
||||
|
||||
if (empty)
|
||||
break;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Special case - holders not needed at all
|
||||
return validateHolder(NULL, keyName);
|
||||
}
|
||||
|
||||
bool CryptoManager::KeyHolderPlugins::validateHolder(IKeyHolderPlugin* keyHolder, const MetaName& keyName)
|
||||
{
|
||||
fb_assert(mgr->checkFactory);
|
||||
if (!mgr->checkFactory)
|
||||
return false;
|
||||
|
||||
FbLocalStatus st;
|
||||
|
||||
AutoPtr<IDbCryptPlugin, ReleasePlugin> crypt(mgr->checkFactory->makeInstance());
|
||||
mgr->setDbInfo(crypt);
|
||||
crypt->setKey(&st, keyHolder ? 1 : 0, &keyHolder, keyName.c_str());
|
||||
|
||||
if (st.isSuccess())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (mgr->checkValidation(crypt))
|
||||
return true;
|
||||
}
|
||||
catch (const Exception&)
|
||||
{ } // Ignore possible errors, continue analysis
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CryptoManager::KeyHolderPlugins::validateExistingAttachments(const MetaName& keyName)
|
||||
{
|
||||
FbLocalStatus st;
|
||||
|
||||
// Special case - holders not needed at all
|
||||
if (validateHolder(NULL, keyName))
|
||||
return;
|
||||
|
||||
// Loop through whole attachments list of DBB, shutdown attachments missing any holders
|
||||
fb_assert(!mgr->dbb.dbb_sync.isLocked());
|
||||
MutexLockGuard g(holdersMutex, FB_FUNCTION);
|
||||
SyncLockGuard dsGuard(&mgr->dbb.dbb_sync, SYNC_EXCLUSIVE, FB_FUNCTION);
|
||||
for (Attachment* att = mgr->dbb.dbb_attachments; att; att = att->att_next)
|
||||
{
|
||||
bool found = false;
|
||||
for (unsigned i = 0; i < knownHolders.getCount(); ++i)
|
||||
{
|
||||
if (knownHolders[i].first == att)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
att->signalShutdown(0 /* no special shutdown code */);
|
||||
}
|
||||
|
||||
// Loop through internal attachments list closing one missing valid holders
|
||||
for (unsigned i = 0; i < knownHolders.getCount(); ++i)
|
||||
{
|
||||
if (!validateHoldersGroup(knownHolders[i], keyName))
|
||||
knownHolders[i].first->signalShutdown(0);
|
||||
}
|
||||
}
|
||||
|
||||
void CryptoManager::addClumplet(string& signature, ClumpletReader& block, UCHAR tag)
|
||||
{
|
||||
if (block.find(tag))
|
||||
|
@ -270,6 +270,7 @@ class CryptoManager FB_FINAL : public Firebird::PermanentStorage, public BarSync
|
||||
{
|
||||
public:
|
||||
typedef Firebird::GetPlugins<Firebird::IDbCryptPlugin> Factory;
|
||||
typedef Firebird::HalfStaticArray<Attachment*, 16> AttVector;
|
||||
|
||||
explicit CryptoManager(thread_db* tdbb);
|
||||
~CryptoManager();
|
||||
@ -326,33 +327,6 @@ private:
|
||||
char buf[MAX_PAGE_SIZE + PAGE_ALIGNMENT - 1];
|
||||
};
|
||||
|
||||
class KeyHolderPlugins
|
||||
{
|
||||
public:
|
||||
typedef CryptoManager::Factory Factory;
|
||||
|
||||
explicit KeyHolderPlugins(Firebird::MemoryPool& p, CryptoManager* m)
|
||||
: knownHolders(p), mgr(m)
|
||||
{ }
|
||||
|
||||
void attach(Attachment* att, const Config* config);
|
||||
void init(Firebird::IDbCryptPlugin* crypt, const Firebird::MetaName& keyName);
|
||||
bool validateNewAttachment(Attachment*, const Firebird::MetaName& keyName);
|
||||
void validateExistingAttachments(const Firebird::MetaName& keyName);
|
||||
void detach(Attachment* att);
|
||||
|
||||
private:
|
||||
Firebird::Mutex holdersMutex;
|
||||
typedef Firebird::Pair<Firebird::Right<Attachment*,
|
||||
Firebird::HalfStaticArray<Firebird::IKeyHolderPlugin*, 4> > > PerAttHolders;
|
||||
Firebird::ObjectsArray<PerAttHolders> knownHolders;
|
||||
CryptoManager* mgr;
|
||||
|
||||
bool validateHoldersGroup(PerAttHolders& pa, const Firebird::MetaName& keyName);
|
||||
bool validateHolder(Firebird::IKeyHolderPlugin* keyHolder, const Firebird::MetaName& keyName);
|
||||
void releaseHolders(PerAttHolders& pa);
|
||||
};
|
||||
|
||||
class DbInfo;
|
||||
friend class DbInfo;
|
||||
|
||||
@ -392,10 +366,12 @@ private:
|
||||
void doOnAst(thread_db* tdbb);
|
||||
|
||||
void loadPlugin(thread_db* tdbb, const char* pluginName);
|
||||
bool validateAttachment(thread_db* tdbb, Attachment* att, bool consume);
|
||||
ULONG getLastPage(thread_db* tdbb);
|
||||
void writeDbHeader(thread_db* tdbb, ULONG runpage);
|
||||
void calcValidation(Firebird::string& valid, Firebird::IDbCryptPlugin* plugin);
|
||||
void checkValidation();
|
||||
void shutdownConsumers(thread_db* tdbb);
|
||||
|
||||
void lockAndReadHeader(thread_db* tdbb, unsigned flags = 0);
|
||||
static const unsigned CRYPT_HDR_INIT = 0x01;
|
||||
@ -409,8 +385,8 @@ private:
|
||||
BarSync sync;
|
||||
Firebird::MetaName keyName;
|
||||
ULONG currentPage;
|
||||
Firebird::Mutex pluginLoadMtx, cryptThreadMtx;
|
||||
KeyHolderPlugins keyHolderPlugins;
|
||||
Firebird::Mutex pluginLoadMtx, cryptThreadMtx, holdersMutex;
|
||||
AttVector keyProviders, keyConsumers;
|
||||
Firebird::string hash;
|
||||
Firebird::RefPtr<DbInfo> dbInfo;
|
||||
Thread::Handle cryptThreadId;
|
||||
|
@ -6925,6 +6925,9 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
|
||||
if (!attachment)
|
||||
return;
|
||||
|
||||
if (dbb->dbb_crypto_manager)
|
||||
dbb->dbb_crypto_manager->detach(tdbb, attachment);
|
||||
|
||||
Monitoring::cleanupAttachment(tdbb);
|
||||
|
||||
dbb->dbb_extManager.closeAttachment(tdbb, attachment);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* MAX_NUMBER is the next number to be used, always one more than the highest message number. */
|
||||
set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES (?, ?, ?, ?);
|
||||
--
|
||||
('2017-11-10 18:40:00', 'JRD', 0, 884)
|
||||
('2018-02-01 17:40:00', 'JRD', 0, 885)
|
||||
('2015-03-17 18:33:00', 'QLI', 1, 533)
|
||||
('2015-01-07 18:01:51', 'GFIX', 3, 134)
|
||||
('1996-11-07 13:39:40', 'GPRE', 4, 1)
|
||||
|
@ -991,6 +991,7 @@ Data source : @4', NULL, NULL)
|
||||
('map_overflow', NULL, 'Mapping.cpp', NULL, 0, 881, NULL, 'Global mapping memory overflow', NULL, NULL);
|
||||
('hdr_overflow', NULL, 'CryptoManager.cpp', NULL, 0, 882, NULL, 'Header page overflow - too many clumplets on it', NULL, NULL);
|
||||
('vld_plugins', NULL, 'ValidatePassword.cpp', NULL, 0, 883, NULL, 'No matching client/server authentication plugins configured for execute statement in embedded datasource', NULL, NULL);
|
||||
('db_crypt_key', NULL, 'CryptoManager.cpp', NULL, 0, 884, NULL, 'Missing database encryption key for your attachment', NULL, NULL);
|
||||
-- QLI
|
||||
(NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL);
|
||||
(NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL);
|
||||
|
@ -890,6 +890,7 @@ set bulk_insert INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, FA
|
||||
(-902, '54', '000', 0, 881, 'map_overflow', NULL, NULL)
|
||||
(-901, '54', '000', 0, 882, 'hdr_overflow', NULL, NULL)
|
||||
(-901, '28', '000', 0, 883, 'vld_plugins', NULL, NULL)
|
||||
(-902, '08', '004', 0, 884, 'db_crypt_key', NULL, NULL)
|
||||
-- GFIX
|
||||
(-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL)
|
||||
(-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL)
|
||||
|
@ -194,6 +194,21 @@ public:
|
||||
if (networkCallback.isStopped())
|
||||
return 0;
|
||||
|
||||
Reference r(*port);
|
||||
loadClientKey();
|
||||
unsigned rc = keyCallback ?
|
||||
keyCallback->callback(dataLength, data, bufferLength, buffer) :
|
||||
// use legacy behavior if holders to do wish to accept keys from client
|
||||
networkCallback.callback(dataLength, data, bufferLength, buffer);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void loadClientKey()
|
||||
{
|
||||
if (keyCallback)
|
||||
return;
|
||||
|
||||
Reference r(*port);
|
||||
|
||||
for (GetPlugins<IKeyHolderPlugin> kh(IPluginManager::TYPE_KEY_HOLDER, port->getPortConfig());
|
||||
@ -215,14 +230,6 @@ public:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned rc = keyCallback ?
|
||||
keyCallback->callback(dataLength, data, bufferLength, buffer) :
|
||||
// use legacy behavior if holders to do wish to accept keys from client
|
||||
networkCallback.callback(dataLength, data, bufferLength, buffer);
|
||||
|
||||
//stop();
|
||||
return rc;
|
||||
}
|
||||
|
||||
void wakeup(unsigned int length, const void* data)
|
||||
@ -259,6 +266,7 @@ public:
|
||||
|
||||
ICryptKeyCallback* getInterface()
|
||||
{
|
||||
cryptCallback.loadClientKey();
|
||||
return &cryptCallback;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user