8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 22:43:03 +01:00

Frontported CORE-5735: Additional keyholder opens unauthorized connections to encrypted database

This commit is contained in:
AlexPeshkoff 2018-02-01 18:10:09 +03:00
parent 50ad173172
commit a8473b0ee3
15 changed files with 197 additions and 253 deletions

View File

@ -3787,12 +3787,12 @@ interface is main interface of database crypt key holder plugin.</font></p>
<li/> <li/>
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
useOnlyOwnKeys(StatusType* status) informs firebird engine useOnlyOwnKeys(StatusType* status) informs firebird engine
whether a key, provided by another key holder, be used or not. Makes whether a key, provided by key holder, can be used in other attachments.
sense only for SuperServer only it can share database crypt keys Makes sense only for SuperServer only it can share database crypt keys
between attachments. Returning FB_TRUE from this method enforces between attachments. Returning FB_TRUE from this method enforces
firebird to make sure that this particular key holder (and therefore firebird to make sure that this particular key holder (and therefore
in turn attachment related to it) provides correct crypt key before in turn attachment related to it) provides correct crypt key for
letting it to work with database.</font></p> any other attachment to this database.</font></p>
<li/> <li/>
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKeyCallback* <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKeyCallback*
chainHandle(StatusType* status) support of a chain of key chainHandle(StatusType* status) support of a chain of key

View File

@ -1818,6 +1818,8 @@ C --
PARAMETER (GDS__hdr_overflow = 335545202) PARAMETER (GDS__hdr_overflow = 335545202)
INTEGER*4 GDS__vld_plugins INTEGER*4 GDS__vld_plugins
PARAMETER (GDS__vld_plugins = 335545203) PARAMETER (GDS__vld_plugins = 335545203)
INTEGER*4 GDS__db_crypt_key
PARAMETER (GDS__db_crypt_key = 335545204)
INTEGER*4 GDS__gfix_db_name INTEGER*4 GDS__gfix_db_name
PARAMETER (GDS__gfix_db_name = 335740929) PARAMETER (GDS__gfix_db_name = 335740929)
INTEGER*4 GDS__gfix_invalid_sw INTEGER*4 GDS__gfix_invalid_sw

View File

@ -1813,6 +1813,8 @@ const
gds_hdr_overflow = 335545202; gds_hdr_overflow = 335545202;
isc_vld_plugins = 335545203; isc_vld_plugins = 335545203;
gds_vld_plugins = 335545203; gds_vld_plugins = 335545203;
isc_db_crypt_key = 335545204;
gds_db_crypt_key = 335545204;
isc_gfix_db_name = 335740929; isc_gfix_db_name = 335740929;
gds_gfix_db_name = 335740929; gds_gfix_db_name = 335740929;
isc_gfix_invalid_sw = 335740930; isc_gfix_invalid_sw = 335740930;

View File

@ -905,6 +905,7 @@ static const struct {
{"map_overflow", 335545201}, {"map_overflow", 335545201},
{"hdr_overflow", 335545202}, {"hdr_overflow", 335545202},
{"vld_plugins", 335545203}, {"vld_plugins", 335545203},
{"db_crypt_key", 335545204},
{"gfix_db_name", 335740929}, {"gfix_db_name", 335740929},
{"gfix_invalid_sw", 335740930}, {"gfix_invalid_sw", 335740930},
{"gfix_incmp_sw", 335740932}, {"gfix_incmp_sw", 335740932},

View File

@ -939,6 +939,7 @@ const ISC_STATUS isc_map_event = 335545200L;
const ISC_STATUS isc_map_overflow = 335545201L; const ISC_STATUS isc_map_overflow = 335545201L;
const ISC_STATUS isc_hdr_overflow = 335545202L; const ISC_STATUS isc_hdr_overflow = 335545202L;
const ISC_STATUS isc_vld_plugins = 335545203L; 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_db_name = 335740929L;
const ISC_STATUS isc_gfix_invalid_sw = 335740930L; const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
const ISC_STATUS isc_gfix_incmp_sw = 335740932L; 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_switch_param_miss = 337182758L;
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L; const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L; 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 */ #else /* c definitions */
@ -2322,6 +2323,7 @@ const ISC_STATUS isc_err_max = 1357;
#define isc_map_overflow 335545201L #define isc_map_overflow 335545201L
#define isc_hdr_overflow 335545202L #define isc_hdr_overflow 335545202L
#define isc_vld_plugins 335545203L #define isc_vld_plugins 335545203L
#define isc_db_crypt_key 335545204L
#define isc_gfix_db_name 335740929L #define isc_gfix_db_name 335740929L
#define isc_gfix_invalid_sw 335740930L #define isc_gfix_invalid_sw 335740930L
#define isc_gfix_incmp_sw 335740932L #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_switch_param_miss 337182758L
#define isc_trace_param_act_notcompat 337182759L #define isc_trace_param_act_notcompat 337182759L
#define isc_trace_mandatory_switch_miss 337182760L #define isc_trace_mandatory_switch_miss 337182760L
#define isc_err_max 1357 #define isc_err_max 1358
#endif #endif

View File

@ -908,6 +908,7 @@ Data source : @4"}, /* eds_statement */
{335545201, "Global mapping memory overflow"}, /* map_overflow */ {335545201, "Global mapping memory overflow"}, /* map_overflow */
{335545202, "Header page overflow - too many clumplets on it"}, /* hdr_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 */ {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 */ {335740929, "data base file name (@1) already given"}, /* gfix_db_name */
{335740930, "invalid switch @1"}, /* gfix_invalid_sw */ {335740930, "invalid switch @1"}, /* gfix_invalid_sw */
{335740932, "incompatible switch combination"}, /* gfix_incmp_sw */ {335740932, "incompatible switch combination"}, /* gfix_incmp_sw */

View File

@ -904,6 +904,7 @@ static const struct {
{335545201, -902}, /* 881 map_overflow */ {335545201, -902}, /* 881 map_overflow */
{335545202, -901}, /* 882 hdr_overflow */ {335545202, -901}, /* 882 hdr_overflow */
{335545203, -901}, /* 883 vld_plugins */ {335545203, -901}, /* 883 vld_plugins */
{335545204, -902}, /* 884 db_crypt_key */
{335740929, -901}, /* 1 gfix_db_name */ {335740929, -901}, /* 1 gfix_db_name */
{335740930, -901}, /* 2 gfix_invalid_sw */ {335740930, -901}, /* 2 gfix_invalid_sw */
{335740932, -901}, /* 4 gfix_incmp_sw */ {335740932, -901}, /* 4 gfix_incmp_sw */

View File

@ -904,6 +904,7 @@ static const struct {
{335545201, "54000"}, // 881 map_overflow {335545201, "54000"}, // 881 map_overflow
{335545202, "54000"}, // 882 hdr_overflow {335545202, "54000"}, // 882 hdr_overflow
{335545203, "28000"}, // 883 vld_plugins {335545203, "28000"}, // 883 vld_plugins
{335545204, "08004"}, // 884 db_crypt_key
{335740929, "00000"}, // 1 gfix_db_name {335740929, "00000"}, // 1 gfix_db_name
{335740930, "00000"}, // 2 gfix_invalid_sw {335740930, "00000"}, // 2 gfix_invalid_sw
{335740932, "00000"}, // 4 gfix_incmp_sw {335740932, "00000"}, // 4 gfix_incmp_sw

View File

@ -278,7 +278,8 @@ namespace Jrd {
: PermanentStorage(*tdbb->getDatabase()->dbb_permanent), : PermanentStorage(*tdbb->getDatabase()->dbb_permanent),
sync(this), sync(this),
keyName(getPool()), keyName(getPool()),
keyHolderPlugins(getPool(), this), keyProviders(getPool()),
keyConsumers(getPool()),
hash(getPool()), hash(getPool()),
dbInfo(FB_NEW DbInfo(this)), dbInfo(FB_NEW DbInfo(this)),
cryptThreadId(0), cryptThreadId(0),
@ -430,7 +431,47 @@ namespace Jrd {
IDbCryptPlugin* p = cryptControl->plugin(); IDbCryptPlugin* p = cryptControl->plugin();
setDbInfo(p); 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 = p;
cryptPlugin->addRef(); cryptPlugin->addRef();
@ -439,11 +480,8 @@ namespace Jrd {
checkFactory = NULL; checkFactory = NULL;
// store new one // store new one
if (dbb.dbb_config->getServerMode() == MODE_SUPER) if (dbb.dbb_config->getServerMode() == MODE_SUPER && !holderLess)
{
checkFactory = cryptControl.release(); checkFactory = cryptControl.release();
keyHolderPlugins.validateNewAttachment(tdbb->getAttachment(), keyName);
}
} }
void CryptoManager::prepareChangeCryptState(thread_db* tdbb, const MetaName& plugName, void CryptoManager::prepareChangeCryptState(thread_db* tdbb, const MetaName& plugName,
@ -598,7 +636,25 @@ namespace Jrd {
hc.insertString(Ods::HDR_crypt_key, keyName); hc.insertString(Ods::HDR_crypt_key, keyName);
if (checkFactory) 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 else
header->hdr_flags &= ~Ods::hdr_encrypted; header->hdr_flags &= ~Ods::hdr_encrypted;
@ -640,6 +696,16 @@ namespace Jrd {
startCryptThread(tdbb); 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() void CryptoManager::blockingAstChangeCryptState()
{ {
AsyncContextHolder tdbb(&dbb, FB_FUNCTION); AsyncContextHolder tdbb(&dbb, FB_FUNCTION);
@ -656,18 +722,94 @@ namespace Jrd {
LCK_convert(tdbb, stateLock, CRYPT_RELEASE, LCK_NO_WAIT); 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) 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); lockAndReadHeader(tdbb, CRYPT_HDR_INIT);
}
if (f && f == checkFactory) void CryptoManager::detach(thread_db* tdbb, Attachment* att)
{ {
if (!keyHolderPlugins.validateNewAttachment(att, keyName)) if (!checkFactory)
(Arg::Gds(isc_bad_crypt_key) << keyName).raise(); 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(); 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) void CryptoManager::addClumplet(string& signature, ClumpletReader& block, UCHAR tag)
{ {
if (block.find(tag)) if (block.find(tag))

View File

@ -270,6 +270,7 @@ class CryptoManager FB_FINAL : public Firebird::PermanentStorage, public BarSync
{ {
public: public:
typedef Firebird::GetPlugins<Firebird::IDbCryptPlugin> Factory; typedef Firebird::GetPlugins<Firebird::IDbCryptPlugin> Factory;
typedef Firebird::HalfStaticArray<Attachment*, 16> AttVector;
explicit CryptoManager(thread_db* tdbb); explicit CryptoManager(thread_db* tdbb);
~CryptoManager(); ~CryptoManager();
@ -326,33 +327,6 @@ private:
char buf[MAX_PAGE_SIZE + PAGE_ALIGNMENT - 1]; 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; class DbInfo;
friend class DbInfo; friend class DbInfo;
@ -392,10 +366,12 @@ private:
void doOnAst(thread_db* tdbb); void doOnAst(thread_db* tdbb);
void loadPlugin(thread_db* tdbb, const char* pluginName); void loadPlugin(thread_db* tdbb, const char* pluginName);
bool validateAttachment(thread_db* tdbb, Attachment* att, bool consume);
ULONG getLastPage(thread_db* tdbb); ULONG getLastPage(thread_db* tdbb);
void writeDbHeader(thread_db* tdbb, ULONG runpage); void writeDbHeader(thread_db* tdbb, ULONG runpage);
void calcValidation(Firebird::string& valid, Firebird::IDbCryptPlugin* plugin); void calcValidation(Firebird::string& valid, Firebird::IDbCryptPlugin* plugin);
void checkValidation(); void checkValidation();
void shutdownConsumers(thread_db* tdbb);
void lockAndReadHeader(thread_db* tdbb, unsigned flags = 0); void lockAndReadHeader(thread_db* tdbb, unsigned flags = 0);
static const unsigned CRYPT_HDR_INIT = 0x01; static const unsigned CRYPT_HDR_INIT = 0x01;
@ -409,8 +385,8 @@ private:
BarSync sync; BarSync sync;
Firebird::MetaName keyName; Firebird::MetaName keyName;
ULONG currentPage; ULONG currentPage;
Firebird::Mutex pluginLoadMtx, cryptThreadMtx; Firebird::Mutex pluginLoadMtx, cryptThreadMtx, holdersMutex;
KeyHolderPlugins keyHolderPlugins; AttVector keyProviders, keyConsumers;
Firebird::string hash; Firebird::string hash;
Firebird::RefPtr<DbInfo> dbInfo; Firebird::RefPtr<DbInfo> dbInfo;
Thread::Handle cryptThreadId; Thread::Handle cryptThreadId;

View File

@ -6925,6 +6925,9 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
if (!attachment) if (!attachment)
return; return;
if (dbb->dbb_crypto_manager)
dbb->dbb_crypto_manager->detach(tdbb, attachment);
Monitoring::cleanupAttachment(tdbb); Monitoring::cleanupAttachment(tdbb);
dbb->dbb_extManager.closeAttachment(tdbb, attachment); dbb->dbb_extManager.closeAttachment(tdbb, attachment);

View File

@ -1,7 +1,7 @@
/* MAX_NUMBER is the next number to be used, always one more than the highest message number. */ /* 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 (?, ?, ?, ?); 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-03-17 18:33:00', 'QLI', 1, 533)
('2015-01-07 18:01:51', 'GFIX', 3, 134) ('2015-01-07 18:01:51', 'GFIX', 3, 134)
('1996-11-07 13:39:40', 'GPRE', 4, 1) ('1996-11-07 13:39:40', 'GPRE', 4, 1)

View File

@ -991,6 +991,7 @@ Data source : @4', NULL, NULL)
('map_overflow', NULL, 'Mapping.cpp', NULL, 0, 881, NULL, 'Global mapping memory overflow', 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); ('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); ('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 -- QLI
(NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL); (NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL);
(NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL); (NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL);

View File

@ -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) (-902, '54', '000', 0, 881, 'map_overflow', NULL, NULL)
(-901, '54', '000', 0, 882, 'hdr_overflow', NULL, NULL) (-901, '54', '000', 0, 882, 'hdr_overflow', NULL, NULL)
(-901, '28', '000', 0, 883, 'vld_plugins', NULL, NULL) (-901, '28', '000', 0, 883, 'vld_plugins', NULL, NULL)
(-902, '08', '004', 0, 884, 'db_crypt_key', NULL, NULL)
-- GFIX -- GFIX
(-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL) (-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL)
(-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL) (-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL)

View File

@ -194,6 +194,21 @@ public:
if (networkCallback.isStopped()) if (networkCallback.isStopped())
return 0; 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); Reference r(*port);
for (GetPlugins<IKeyHolderPlugin> kh(IPluginManager::TYPE_KEY_HOLDER, port->getPortConfig()); for (GetPlugins<IKeyHolderPlugin> kh(IPluginManager::TYPE_KEY_HOLDER, port->getPortConfig());
@ -215,14 +230,6 @@ public:
break; 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) void wakeup(unsigned int length, const void* data)
@ -259,6 +266,7 @@ public:
ICryptKeyCallback* getInterface() ICryptKeyCallback* getInterface()
{ {
cryptCallback.loadClientKey();
return &cryptCallback; return &cryptCallback;
} }