mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 16:43:03 +01:00
Fixed CORE-6093: Errors simultaneously accessing security database from two engines
This commit is contained in:
parent
d7fc847bff
commit
6bb80e1845
File diff suppressed because it is too large
Load Diff
@ -48,15 +48,14 @@
|
||||
|
||||
namespace {
|
||||
|
||||
const unsigned int INIT_KEY = ((~0) - 1);
|
||||
unsigned int secDbKey = INIT_KEY;
|
||||
|
||||
const unsigned int SZ_LOGIN = 31;
|
||||
const unsigned int SZ_NAME = 31;
|
||||
typedef Field<Varying> Varfield;
|
||||
typedef Field<ISC_QUAD> Blob;
|
||||
typedef Field<FB_BOOLEAN> Boolean;
|
||||
|
||||
Firebird::GlobalPtr<Firebird::ConfigKeys> keys;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace Auth {
|
||||
@ -221,12 +220,8 @@ public:
|
||||
(Firebird::Arg::Gds(isc_random) << "Database is already attached in SRP").raise();
|
||||
}
|
||||
|
||||
if (secDbKey == INIT_KEY)
|
||||
{
|
||||
secDbKey = config->getKey("SecurityDatabase");
|
||||
}
|
||||
unsigned int secDbKey = keys->getKey(config, "SecurityDatabase");
|
||||
const char* secDbName = config->asString(secDbKey);
|
||||
|
||||
if (!(secDbName && secDbName[0]))
|
||||
{
|
||||
Firebird::Arg::Gds(isc_secdb_name).raise();
|
||||
|
@ -39,8 +39,7 @@ using namespace Firebird;
|
||||
|
||||
namespace {
|
||||
|
||||
const unsigned int INIT_KEY = ((~0) - 1);
|
||||
unsigned int secDbKey = INIT_KEY;
|
||||
GlobalPtr<ConfigKeys> keys;
|
||||
|
||||
const unsigned int SZ_LOGIN = 31;
|
||||
|
||||
@ -132,11 +131,7 @@ int SrpServer::authenticate(CheckStatusWrapper* status, IServerBlock* sb, IWrite
|
||||
|
||||
// read salt and verifier from database
|
||||
// obviously we need something like attachments cache here
|
||||
if (secDbKey == INIT_KEY)
|
||||
{
|
||||
secDbKey = config->getKey("SecurityDatabase");
|
||||
}
|
||||
|
||||
unsigned int secDbKey = keys->getKey(config, "SecurityDatabase");
|
||||
secDbName = config->asString(secDbKey);
|
||||
if (!(secDbName && secDbName[0]))
|
||||
{
|
||||
|
@ -100,8 +100,7 @@ static bool grantRevokeAdmin(ISC_STATUS* isc_status, FB_API_HANDLE database, FB_
|
||||
}
|
||||
|
||||
|
||||
const static unsigned int INIT_KEY = ((~0) - 1);
|
||||
static unsigned int secDbKey = INIT_KEY;
|
||||
static Firebird::GlobalPtr<Firebird::ConfigKeys> keys;
|
||||
|
||||
namespace Auth {
|
||||
|
||||
@ -120,12 +119,8 @@ void SecurityDatabaseManagement::start(Firebird::CheckStatusWrapper* st, Firebir
|
||||
{
|
||||
st->init();
|
||||
|
||||
if (secDbKey == INIT_KEY)
|
||||
{
|
||||
secDbKey = config->getKey("SecurityDatabase");
|
||||
}
|
||||
unsigned int secDbKey = keys->getKey(config, "SecurityDatabase");
|
||||
const char* secDbName = config->asString(secDbKey);
|
||||
|
||||
if (!(secDbName && secDbName[0]))
|
||||
{
|
||||
Firebird::Arg::Gds(isc_secdb_name).raise();
|
||||
|
@ -471,8 +471,7 @@ int SecurityDatabase::shutdown()
|
||||
return FB_SUCCESS;
|
||||
}
|
||||
|
||||
const static unsigned int INIT_KEY = ((~0) - 1);
|
||||
static unsigned int secDbKey = INIT_KEY;
|
||||
static Firebird::GlobalPtr<Firebird::ConfigKeys> keys;
|
||||
|
||||
int SecurityDatabaseServer::authenticate(Firebird::CheckStatusWrapper* status, IServerBlock* sBlock,
|
||||
IWriter* writerInterface)
|
||||
@ -488,10 +487,7 @@ int SecurityDatabaseServer::authenticate(Firebird::CheckStatusWrapper* status, I
|
||||
RefPtr<IFirebirdConf> config(REF_NO_INCR, iParameter->getFirebirdConf(&s));
|
||||
check(&s);
|
||||
|
||||
if (secDbKey == INIT_KEY)
|
||||
{
|
||||
secDbKey = config->getKey("SecurityDatabase");
|
||||
}
|
||||
unsigned int secDbKey = keys->getKey(config, "SecurityDatabase");
|
||||
const char* tmp = config->asString(secDbKey);
|
||||
if (!tmp)
|
||||
{
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "firebird.h"
|
||||
#include "../common/classes/fb_tls.h"
|
||||
#include "../common/classes/ImplementHelper.h"
|
||||
#include "../common/status.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -66,6 +67,23 @@ IMaster* CachedMasterInterface::getMasterInterface()
|
||||
return cached;
|
||||
}
|
||||
|
||||
unsigned int ConfigKeys::getKey(IFirebirdConf* config, const char* keyName)
|
||||
{
|
||||
FbLocalStatus status;
|
||||
unsigned int version = config->getVersion(&status) & 0xFFFF0000;
|
||||
for (const_iterator itr = this->begin(); itr != this->end(); ++itr)
|
||||
{
|
||||
if (((*itr) & 0xFFFF0000) == version)
|
||||
return *itr;
|
||||
}
|
||||
|
||||
unsigned int secDbKey = config->getKey(keyName);
|
||||
if (secDbKey != INVALID_KEY)
|
||||
this->push(secDbKey);
|
||||
|
||||
return secDbKey;
|
||||
}
|
||||
|
||||
|
||||
#ifdef NOT_USED_OR_REPLACED
|
||||
class IDebug
|
||||
|
@ -389,6 +389,19 @@ inline void check(IStatus* status)
|
||||
}
|
||||
|
||||
|
||||
// Config keys cache
|
||||
class ConfigKeys : private HalfStaticArray<unsigned int, 8>
|
||||
{
|
||||
public:
|
||||
ConfigKeys(MemoryPool& p)
|
||||
: HalfStaticArray<unsigned int, 8>(p)
|
||||
{ }
|
||||
|
||||
const static unsigned int INVALID_KEY = ~0u;
|
||||
|
||||
unsigned int getKey(IFirebirdConf* config, const char* keyName);
|
||||
};
|
||||
|
||||
// debugger for reference counters
|
||||
|
||||
#ifdef NEVERDEF
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "../jrd/constants.h"
|
||||
#include "firebird/Interface.h"
|
||||
#include "../common/db_alias.h"
|
||||
#include "../jrd/build_no.h"
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
@ -764,23 +765,58 @@ const char* Config::getPlugins(unsigned int type) const
|
||||
return NULL; // compiler warning silencer
|
||||
}
|
||||
|
||||
|
||||
// array format: major, minor, release, build
|
||||
static unsigned short fileVerNumber[4] = {FILE_VER_NUMBER};
|
||||
|
||||
static inline unsigned int getPartialVersion()
|
||||
{
|
||||
// major // minor
|
||||
return (fileVerNumber[0] << 24) | (fileVerNumber[1] << 16);
|
||||
}
|
||||
|
||||
static inline unsigned int getFullVersion()
|
||||
{
|
||||
// build_no
|
||||
return getPartialVersion() | fileVerNumber[3];
|
||||
}
|
||||
|
||||
static unsigned int PARTIAL_MASK = 0xFFFF0000;
|
||||
static unsigned int KEY_MASK = 0xFFFF;
|
||||
|
||||
static inline void checkKey(unsigned int& key)
|
||||
{
|
||||
if (key & PARTIAL_MASK != getPartialVersion())
|
||||
key = KEY_MASK;
|
||||
else
|
||||
key &= KEY_MASK;
|
||||
}
|
||||
|
||||
unsigned int FirebirdConf::getVersion(Firebird::CheckStatusWrapper* status)
|
||||
{
|
||||
return getFullVersion();
|
||||
}
|
||||
|
||||
unsigned int FirebirdConf::getKey(const char* name)
|
||||
{
|
||||
return Config::getKeyByName(name);
|
||||
return Config::getKeyByName(name) | getPartialVersion();
|
||||
}
|
||||
|
||||
ISC_INT64 FirebirdConf::asInteger(unsigned int key)
|
||||
{
|
||||
checkKey(key);
|
||||
return config->getInt(key);
|
||||
}
|
||||
|
||||
const char* FirebirdConf::asString(unsigned int key)
|
||||
{
|
||||
checkKey(key);
|
||||
return config->getString(key);
|
||||
}
|
||||
|
||||
FB_BOOLEAN FirebirdConf::asBoolean(unsigned int key)
|
||||
{
|
||||
checkKey(key);
|
||||
return config->getBoolean(key);
|
||||
}
|
||||
|
||||
@ -795,6 +831,7 @@ int FirebirdConf::release()
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
const char* Config::getSecurityDatabase() const
|
||||
{
|
||||
return get<const char*>(KEY_SECURITY_DATABASE);
|
||||
|
@ -406,6 +406,7 @@ public:
|
||||
SINT64 asInteger(unsigned int key);
|
||||
const char* asString(unsigned int key);
|
||||
FB_BOOLEAN asBoolean(unsigned int key);
|
||||
unsigned int getVersion(Firebird::CheckStatusWrapper* status);
|
||||
|
||||
int release();
|
||||
|
||||
|
@ -187,6 +187,7 @@ interface FirebirdConf : ReferenceCounted
|
||||
// Get integer key by it's name
|
||||
// Value ~0 means name is invalid
|
||||
// Keys are stable: one can use once obtained key in other instances of this interface
|
||||
// provided they have same minor version (upper 16 bits match with getVersion())
|
||||
uint getKey(const string name);
|
||||
// Use to access integer values
|
||||
int64 asInteger(uint key);
|
||||
@ -194,6 +195,10 @@ interface FirebirdConf : ReferenceCounted
|
||||
const string asString(uint key);
|
||||
// Use to access boolean values
|
||||
boolean asBoolean(uint key);
|
||||
version: // 3.0 => 4.0
|
||||
// Use to access version of configuration manager serving this interface
|
||||
// Format: major byte, minor byte, buildno 2-byte
|
||||
uint getVersion(Status status);
|
||||
}
|
||||
|
||||
// This interface is passed to plugin's factory as it's single parameter
|
||||
|
@ -611,6 +611,7 @@ namespace Firebird
|
||||
ISC_INT64 (CLOOP_CARG *asInteger)(IFirebirdConf* self, unsigned key) throw();
|
||||
const char* (CLOOP_CARG *asString)(IFirebirdConf* self, unsigned key) throw();
|
||||
FB_BOOLEAN (CLOOP_CARG *asBoolean)(IFirebirdConf* self, unsigned key) throw();
|
||||
unsigned (CLOOP_CARG *getVersion)(IFirebirdConf* self, IStatus* status) throw();
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -624,7 +625,7 @@ namespace Firebird
|
||||
}
|
||||
|
||||
public:
|
||||
static const unsigned VERSION = 3;
|
||||
static const unsigned VERSION = 4;
|
||||
|
||||
unsigned getKey(const char* name)
|
||||
{
|
||||
@ -649,6 +650,20 @@ namespace Firebird
|
||||
FB_BOOLEAN ret = static_cast<VTable*>(this->cloopVTable)->asBoolean(this, key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename StatusType> unsigned getVersion(StatusType* status)
|
||||
{
|
||||
if (cloopVTable->version < 4)
|
||||
{
|
||||
StatusType::setVersionError(status, "IFirebirdConf", cloopVTable->version, 4);
|
||||
StatusType::checkException(status);
|
||||
return 0;
|
||||
}
|
||||
StatusType::clearException(status);
|
||||
unsigned ret = static_cast<VTable*>(this->cloopVTable)->getVersion(this, status);
|
||||
StatusType::checkException(status);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
class IPluginConfig : public IReferenceCounted
|
||||
@ -7113,6 +7128,7 @@ namespace Firebird
|
||||
this->asInteger = &Name::cloopasIntegerDispatcher;
|
||||
this->asString = &Name::cloopasStringDispatcher;
|
||||
this->asBoolean = &Name::cloopasBooleanDispatcher;
|
||||
this->getVersion = &Name::cloopgetVersionDispatcher;
|
||||
}
|
||||
} vTable;
|
||||
|
||||
@ -7171,6 +7187,21 @@ namespace Firebird
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned CLOOP_CARG cloopgetVersionDispatcher(IFirebirdConf* self, IStatus* status) throw()
|
||||
{
|
||||
StatusType status2(status);
|
||||
|
||||
try
|
||||
{
|
||||
return static_cast<Name*>(self)->Name::getVersion(&status2);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
StatusType::catchException(&status2);
|
||||
return static_cast<unsigned>(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopaddRefDispatcher(IReferenceCounted* self) throw()
|
||||
{
|
||||
try
|
||||
@ -7214,6 +7245,7 @@ namespace Firebird
|
||||
virtual ISC_INT64 asInteger(unsigned key) = 0;
|
||||
virtual const char* asString(unsigned key) = 0;
|
||||
virtual FB_BOOLEAN asBoolean(unsigned key) = 0;
|
||||
virtual unsigned getVersion(StatusType* status) = 0;
|
||||
};
|
||||
|
||||
template <typename Name, typename StatusType, typename Base>
|
||||
|
Loading…
Reference in New Issue
Block a user