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

Backported CORE-6450 & CORE-6441

This commit is contained in:
AlexPeshkoff 2020-11-19 13:38:18 +03:00
parent aae85103ce
commit 8f49cd73de
5 changed files with 77 additions and 47 deletions

View File

@ -51,7 +51,7 @@ void CachedSecurityDatabase::handler()
} }
void PluginDatabases::getInstance(IPluginConfig* pluginConfig, RefPtr<CachedSecurityDatabase>& instance) void PluginDatabases::getInstance(IPluginConfig* pluginConfig, CachedSecurityDatabase::Instance& instance)
{ {
// Determine sec.db name based on existing config // Determine sec.db name based on existing config
PathName secDbName; PathName secDbName;
@ -74,18 +74,28 @@ void PluginDatabases::getInstance(IPluginConfig* pluginConfig, RefPtr<CachedSecu
{ // guard scope { // guard scope
MutexLockGuard g(arrayMutex, FB_FUNCTION); MutexLockGuard g(arrayMutex, FB_FUNCTION);
for (unsigned int i = 0; i < dbArray.getCount(); ++i) for (unsigned int i = 0; i < dbArray.getCount(); )
{ {
if (secDbName == dbArray[i]->secureDbName) if (secDbName == dbArray[i]->secureDbName)
{ {
instance = dbArray[i]; CachedSecurityDatabase* fromCache = dbArray[i];
break; if (fromCache->secDb->test())
{
instance.set(fromCache);
break;
}
else
{
dbArray.remove(i);
continue;
}
} }
++i;
} }
if (!instance) if (!instance)
{ {
instance = FB_NEW CachedSecurityDatabase(this, secDbName); instance.set(FB_NEW CachedSecurityDatabase(this, secDbName));
instance->addRef(); instance->addRef();
secDbName.copyTo(instance->secureDbName, sizeof(instance->secureDbName)); secDbName.copyTo(instance->secureDbName, sizeof(instance->secureDbName));
dbArray.add(instance); dbArray.add(instance);

View File

@ -49,6 +49,7 @@ public:
} }
virtual bool lookup(void* inMsg, void* outMsg) = 0; virtual bool lookup(void* inMsg, void* outMsg) = 0;
virtual bool test() = 0;
}; };
@ -85,6 +86,33 @@ public:
Firebird::Mutex mutex; Firebird::Mutex mutex;
Firebird::AutoPtr<VSecDb> secDb; Firebird::AutoPtr<VSecDb> secDb;
PluginDatabases* list; PluginDatabases* list;
public:
// Related RAII holder
class Instance : public Firebird::RefPtr<CachedSecurityDatabase>
{
public:
Instance()
{ }
void set(CachedSecurityDatabase* db)
{
fb_assert(!hasData());
fb_assert(db);
assign(db);
(*this)->mutex.enter(FB_FUNCTION);
}
~Instance()
{
if (hasData())
{
(*this)->mutex.leave();
(*this)->close();
}
}
};
}; };
class PluginDatabases class PluginDatabases
@ -99,7 +127,7 @@ private:
Firebird::Mutex arrayMutex; Firebird::Mutex arrayMutex;
public: public:
void getInstance(Firebird::IPluginConfig* pluginConfig, Firebird::RefPtr<CachedSecurityDatabase>& instance); void getInstance(Firebird::IPluginConfig* pluginConfig, CachedSecurityDatabase::Instance& instance);
int shutdown(); int shutdown();
void handler(CachedSecurityDatabase* tgt); void handler(CachedSecurityDatabase* tgt);
}; };

View File

@ -120,6 +120,14 @@ public:
return false; // safe default return false; // safe default
} }
bool test() override
{
Jrd::FbLocalStatus status;
att->ping(&status);
return !(status->getState() & IStatus::STATE_ERRORS);
}
// This 2 are needed to satisfy temporarily different calling requirements // This 2 are needed to satisfy temporarily different calling requirements
static int shutdown(const int, const int, void*) static int shutdown(const int, const int, void*)
{ {
@ -293,28 +301,19 @@ int SrpServer::authenticate(CheckStatusWrapper* status, IServerBlock* sb, IWrite
messages.param->loginNull = 0; messages.param->loginNull = 0;
messages.data.clear(); messages.data.clear();
{ // reference & mutex scope scope { // instance RAII scope
CachedSecurityDatabase::Instance instance;
// Get database block from cache // Get database block from cache
RefPtr<CachedSecurityDatabase> instance;
instances->getInstance(iParameter, instance); instances->getInstance(iParameter, instance);
secDbName = instance->secureDbName;
try // Create SecurityDatabase if needed
{ if (!instance->secDb)
MutexLockGuard g(instance->mutex, FB_FUNCTION); instance->secDb = FB_NEW SecurityDatabase(instance->secureDbName, cryptCallback);
secDbName = instance->secureDbName; // Lookup
if (!instance->secDb) instance->secDb->lookup(messages.param.getData(), messages.data.getData());
instance->secDb = FB_NEW SecurityDatabase(instance->secureDbName, cryptCallback);
instance->secDb->lookup(messages.param.getData(), messages.data.getData());
}
catch(const Exception&)
{
instance->close();
throw;
}
instance->close();
} }
HANDSHAKE_DEBUG(fprintf(stderr, "Srv: SRP1: Executed statement\n")); HANDSHAKE_DEBUG(fprintf(stderr, "Srv: SRP1: Executed statement\n"));

View File

@ -149,6 +149,11 @@ class SecurityDatabase : public VSecDb
public: public:
bool lookup(void* inMsg, void* outMsg); bool lookup(void* inMsg, void* outMsg);
bool test() override
{
return fb_ping(status, &lookup_db) == FB_SUCCESS;
}
// This 2 are needed to satisfy temporarily different calling requirements // This 2 are needed to satisfy temporarily different calling requirements
static int shutdown(const int, const int, void*) static int shutdown(const int, const int, void*)
{ {
@ -326,32 +331,20 @@ int SecurityDatabaseServer::authenticate(CheckStatusWrapper* status, IServerBloc
bool found = false; bool found = false;
char pw1[MAX_LEGACY_PASSWORD_LENGTH + 1]; char pw1[MAX_LEGACY_PASSWORD_LENGTH + 1];
PathName secureDbName; PathName secureDbName;
{ // reference & mutex scope scope { // instance scope
// Get database block from cache // Get database block from cache
RefPtr<CachedSecurityDatabase> instance; CachedSecurityDatabase::Instance instance;
instances->getInstance(iParameter, instance); instances->getInstance(iParameter, instance);
try secureDbName = instance->secureDbName;
{ if (!instance->secDb)
MutexLockGuard g(instance->mutex, FB_FUNCTION); instance->secDb = FB_NEW SecurityDatabase(instance->secureDbName);
secureDbName = instance->secureDbName; user_name uname; // user name buffer
if (!instance->secDb) login.copyTo(uname, sizeof uname);
instance->secDb = FB_NEW SecurityDatabase(instance->secureDbName); user_record user_block; // user record
found = instance->secDb->lookup(uname, &user_block);
user_name uname; // user name buffer fb_utils::copy_terminate(pw1, user_block.password, MAX_LEGACY_PASSWORD_LENGTH + 1);
login.copyTo(uname, sizeof uname);
user_record user_block; // user record
found = instance->secDb->lookup(uname, &user_block);
fb_utils::copy_terminate(pw1, user_block.password, MAX_LEGACY_PASSWORD_LENGTH + 1);
}
catch(const Exception&)
{
instance->close();
throw;
}
instance->close();
} }
if (!found) if (!found)
{ {

View File

@ -193,7 +193,7 @@ namespace Firebird
return ptr; return ptr;
} }
private: protected:
T* assign(T* const p) T* assign(T* const p)
{ {
if (ptr != p) if (ptr != p)