mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 00:03:02 +01:00
Implemented CORE-4851: Apply methods, used for cross security database authentication, to the trace
This commit is contained in:
parent
5a9ae4a65b
commit
b692e85f56
@ -122,6 +122,7 @@
|
||||
#define isc_dpb_config 87
|
||||
#define isc_dpb_nolinger 88
|
||||
#define isc_dpb_reset_icu 89
|
||||
#define isc_dpb_map_attach 90
|
||||
|
||||
/**************************************************/
|
||||
/* clumplet tags used inside isc_dpb_address_path */
|
||||
|
@ -480,6 +480,7 @@ const ULONG ATT_system = 0x04000L; // Special system attachment
|
||||
const ULONG ATT_creator = 0x08000L; // This attachment created the DB
|
||||
const ULONG ATT_monitor_done = 0x10000L; // Monitoring data is refreshed
|
||||
const ULONG ATT_security_db = 0x20000L; // Attachment used for security purposes
|
||||
const ULONG ATT_mapping = 0x40000L; // Attachment used for mapping auth block
|
||||
|
||||
const ULONG ATT_NO_CLEANUP = (ATT_no_cleanup | ATT_notify_gc);
|
||||
|
||||
|
@ -79,6 +79,7 @@ class ExternalFileDirectoryList;
|
||||
class MonitoringData;
|
||||
class GarbageCollector;
|
||||
class CryptoManager;
|
||||
class JProvider;
|
||||
|
||||
// general purpose vector
|
||||
template <class T, BlockType TYPE = type_vec>
|
||||
@ -330,12 +331,13 @@ public:
|
||||
bool active;
|
||||
};
|
||||
|
||||
static Database* create(Firebird::IPluginConfig* pConf, bool shared)
|
||||
static Database* create(Firebird::IPluginConfig* pConf, JProvider* provider, bool shared)
|
||||
{
|
||||
Firebird::MemoryStats temp_stats;
|
||||
MemoryPool* const pool = MemoryPool::createPool(NULL, temp_stats);
|
||||
Database* const dbb = FB_NEW(*pool) Database(pool, pConf, shared);
|
||||
pool->setStatsGroup(dbb->dbb_memory_stats);
|
||||
dbb->dbb_provider = provider;
|
||||
return dbb;
|
||||
}
|
||||
|
||||
@ -375,6 +377,7 @@ public:
|
||||
LockManager* dbb_lock_mgr;
|
||||
EventManager* dbb_event_mgr;
|
||||
|
||||
JProvider* dbb_provider;
|
||||
Database* dbb_next; // Next database block in system
|
||||
Attachment* dbb_attachments; // Active attachments
|
||||
Attachment* dbb_sys_attachments; // System attachments
|
||||
|
@ -409,6 +409,11 @@ public:
|
||||
return p;
|
||||
}
|
||||
|
||||
Firebird::ICryptKeyCallback* getCryptCallback()
|
||||
{
|
||||
return cryptCallback;
|
||||
}
|
||||
|
||||
// IProvider implementation
|
||||
JAttachment* attachDatabase(Firebird::CheckStatusWrapper* status, const char* fileName,
|
||||
unsigned int dpbLength, const unsigned char* dpb);
|
||||
@ -418,7 +423,7 @@ public:
|
||||
unsigned int spbLength, const unsigned char* spb);
|
||||
void shutdown(Firebird::CheckStatusWrapper* status, unsigned int timeout, const int reason);
|
||||
void setDbCryptCallback(Firebird::CheckStatusWrapper* status,
|
||||
Firebird::ICryptKeyCallback* cryptCallback);
|
||||
Firebird::ICryptKeyCallback* cryptCb);
|
||||
|
||||
int release();
|
||||
|
||||
|
@ -921,6 +921,7 @@ void mapUser(string& name, string& trusted_role, Firebird::string* auth_method,
|
||||
embeddedSysdba.insertString(isc_dpb_user_name, SYSDBA_USER_NAME,
|
||||
fb_strlen(SYSDBA_USER_NAME));
|
||||
embeddedSysdba.insertByte(isc_dpb_sec_attach, TRUE);
|
||||
embeddedSysdba.insertByte(isc_dpb_map_attach, TRUE);
|
||||
embeddedSysdba.insertByte(isc_dpb_no_db_triggers, TRUE);
|
||||
|
||||
if (!iSec)
|
||||
@ -966,10 +967,12 @@ void mapUser(string& name, string& trusted_role, Firebird::string* auth_method,
|
||||
if (db)
|
||||
cDb = locate(alias, db);
|
||||
Cache* cSec = locate(securityAlias, securityDb);
|
||||
if (cDb == cSec)
|
||||
cDb = NULL;
|
||||
|
||||
SyncObject dummySync;
|
||||
Sync sDb((!(flags & FLAG_DB)) ? &cDb->syncObject : &dummySync, FB_FUNCTION);
|
||||
Sync sSec((!(flags & FLAG_SEC)) ? &cSec->syncObject : &dummySync, FB_FUNCTION);
|
||||
SyncObject dummySync1, dummySync2;
|
||||
Sync sDb(((!(flags & FLAG_DB)) && cDb) ? &cDb->syncObject : &dummySync1, FB_FUNCTION);
|
||||
Sync sSec((!(flags & FLAG_SEC)) ? &cSec->syncObject : &dummySync2, FB_FUNCTION);
|
||||
|
||||
sSec.lock(syncType);
|
||||
if (!sDb.lockConditional(syncType))
|
||||
|
@ -747,7 +747,7 @@ namespace
|
||||
|
||||
DefaultCallback defCallback;
|
||||
|
||||
ICryptKeyCallback* getCryptCallback(ICryptKeyCallback* callback)
|
||||
ICryptKeyCallback* getDefCryptCallback(ICryptKeyCallback* callback)
|
||||
{
|
||||
return callback ? callback : &defCallback;
|
||||
}
|
||||
@ -904,6 +904,7 @@ public:
|
||||
ULONG dpb_flags; // to OR'd with dbb_flags
|
||||
bool dpb_nolinger;
|
||||
bool dpb_reset_icu;
|
||||
bool dpb_map_attach;
|
||||
|
||||
// here begin compound objects
|
||||
// for constructor to work properly dpb_user_name
|
||||
@ -1015,7 +1016,7 @@ static VdnResult verifyDatabaseName(const PathName&, FbStatusVector*, bool);
|
||||
static void unwindAttach(thread_db* tdbb, const Exception& ex, FbStatusVector* userStatus,
|
||||
Jrd::Attachment* attachment, Database* dbb, unsigned internalFlags);
|
||||
static JAttachment* initAttachment(thread_db*, const PathName&, const PathName&, RefPtr<Config>, bool,
|
||||
const DatabaseOptions&, RefMutexUnlock&, IPluginConfig*);
|
||||
const DatabaseOptions&, RefMutexUnlock&, IPluginConfig*, JProvider*);
|
||||
static JAttachment* create_attachment(const PathName&, Database*, const DatabaseOptions&, bool newDb);
|
||||
static void prepare_tra(thread_db*, jrd_tra*, USHORT, const UCHAR*);
|
||||
static void start_transaction(thread_db* tdbb, bool transliterate, jrd_tra** tra_handle,
|
||||
@ -1467,7 +1468,7 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
|
||||
RefMutexUnlock initGuard;
|
||||
JAttachment* jAtt = initAttachment(tdbb, expanded_name,
|
||||
is_alias ? org_filename : expanded_name,
|
||||
config, true, options, initGuard, pluginConfig);
|
||||
config, true, options, initGuard, pluginConfig, this);
|
||||
|
||||
dbb = tdbb->getDatabase();
|
||||
fb_assert(dbb);
|
||||
@ -1483,13 +1484,15 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
|
||||
|
||||
EngineContextHolder tdbb(user_status, jAtt, FB_FUNCTION, AttachmentHolder::ATT_DONT_LOCK);
|
||||
|
||||
attachment->att_crypt_callback = getCryptCallback(cryptCallback);
|
||||
attachment->att_crypt_callback = getDefCryptCallback(cryptCallback);
|
||||
attachment->att_client_charset = attachment->att_charset = options.dpb_interp;
|
||||
|
||||
if (options.dpb_no_garbage)
|
||||
attachment->att_flags |= ATT_no_cleanup;
|
||||
if (options.dpb_sec_attach)
|
||||
attachment->att_flags |= ATT_security_db;
|
||||
if (options.dpb_map_attach)
|
||||
attachment->att_flags |= ATT_mapping;
|
||||
|
||||
if (options.dpb_gbak_attach)
|
||||
attachment->att_utility = Attachment::UTIL_GBAK;
|
||||
@ -2492,7 +2495,7 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
|
||||
RefMutexUnlock initGuard;
|
||||
JAttachment* jAtt = initAttachment(tdbb, expanded_name,
|
||||
is_alias ? org_filename : expanded_name,
|
||||
config, false, options, initGuard, pluginConfig);
|
||||
config, false, options, initGuard, pluginConfig, this);
|
||||
|
||||
dbb = tdbb->getDatabase();
|
||||
fb_assert(dbb);
|
||||
@ -2506,13 +2509,15 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
|
||||
|
||||
EngineContextHolder tdbb(user_status, jAtt, FB_FUNCTION, AttachmentHolder::ATT_DONT_LOCK);
|
||||
|
||||
attachment->att_crypt_callback = getCryptCallback(cryptCallback);
|
||||
attachment->att_crypt_callback = getDefCryptCallback(cryptCallback);
|
||||
|
||||
if (options.dpb_working_directory.hasData())
|
||||
attachment->att_working_directory = options.dpb_working_directory;
|
||||
|
||||
if (options.dpb_sec_attach)
|
||||
attachment->att_flags |= ATT_security_db;
|
||||
if (options.dpb_map_attach)
|
||||
attachment->att_flags |= ATT_mapping;
|
||||
|
||||
if (options.dpb_gbak_attach)
|
||||
attachment->att_utility = Attachment::UTIL_GBAK;
|
||||
@ -4120,10 +4125,10 @@ void JProvider::shutdown(CheckStatusWrapper* status, unsigned int timeout, const
|
||||
}
|
||||
|
||||
|
||||
void JProvider::setDbCryptCallback(CheckStatusWrapper* status, ICryptKeyCallback* callback)
|
||||
void JProvider::setDbCryptCallback(CheckStatusWrapper* status, ICryptKeyCallback* cryptCb)
|
||||
{
|
||||
status->init();
|
||||
cryptCallback = callback;
|
||||
cryptCallback = cryptCb;
|
||||
}
|
||||
|
||||
|
||||
@ -5843,6 +5848,10 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
|
||||
dpb_sec_attach = rdr.getInt() != 0;
|
||||
break;
|
||||
|
||||
case isc_dpb_map_attach:
|
||||
dpb_map_attach = true;
|
||||
break;
|
||||
|
||||
case isc_dpb_gbak_attach:
|
||||
{
|
||||
string gbakStr;
|
||||
@ -5977,7 +5986,8 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
|
||||
|
||||
static JAttachment* initAttachment(thread_db* tdbb, const PathName& expanded_name,
|
||||
const PathName& alias_name, RefPtr<Config> config, bool attach_flag,
|
||||
const DatabaseOptions& options, RefMutexUnlock& initGuard, IPluginConfig* pConf)
|
||||
const DatabaseOptions& options, RefMutexUnlock& initGuard, IPluginConfig* pConf,
|
||||
JProvider* provider)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -6100,7 +6110,7 @@ static JAttachment* initAttachment(thread_db* tdbb, const PathName& expanded_nam
|
||||
|
||||
Config::merge(config, &options.dpb_config);
|
||||
|
||||
dbb = Database::create(pConf, shared);
|
||||
dbb = Database::create(pConf, provider, shared);
|
||||
dbb->dbb_config = config;
|
||||
dbb->dbb_filename = expanded_name;
|
||||
#ifdef HAVE_ID_BY_NAME
|
||||
|
@ -194,6 +194,8 @@ public: // external interface with service
|
||||
const Firebird::string& getRemoteAddress() const { return svc_remote_address; }
|
||||
const Firebird::string& getRemoteProcess() const { return svc_remote_process; }
|
||||
int getRemotePID() const { return svc_remote_pid; }
|
||||
const Firebird::PathName& getExpectedDb() const { return svc_expected_db; }
|
||||
Firebird::ICryptKeyCallback* getCryptCallback() { return svc_crypt_callback; }
|
||||
|
||||
private:
|
||||
// Service must have private destructor, called from finish
|
||||
|
@ -399,35 +399,19 @@ void fbtrace(UtilSvc* uSvc, TraceSvcIntf* traceSvc)
|
||||
}
|
||||
}
|
||||
|
||||
// This is a temporal hack!!!
|
||||
// AuthBlock should be passed inside trace and used on per-database basis
|
||||
// to make sure which attachments may be traced.
|
||||
AuthReader::AuthBlock authBlock;
|
||||
const unsigned char* bytes;
|
||||
unsigned int authBlockSize = uSvc->getAuthBlock(&bytes);
|
||||
if (authBlockSize)
|
||||
{
|
||||
AuthReader::AuthBlock authBlock;
|
||||
authBlock.add(bytes, authBlockSize);
|
||||
|
||||
AuthReader auth(authBlock);
|
||||
AuthReader::Info info;
|
||||
|
||||
if (auth.getInfo(info))
|
||||
{
|
||||
pwd = "";
|
||||
user = info.name.ToString();
|
||||
adminRole = false;
|
||||
|
||||
if (!info.secDb.hasData())
|
||||
{
|
||||
auth.moveNext();
|
||||
if (auth.getInfo(info))
|
||||
adminRole = true;
|
||||
}
|
||||
}
|
||||
pwd = "";
|
||||
user = "";
|
||||
adminRole = false;
|
||||
}
|
||||
|
||||
traceSvc->setAttachInfo(svc_name, user, pwd, adminRole);
|
||||
traceSvc->setAttachInfo(svc_name, user, pwd, authBlock, adminRole);
|
||||
|
||||
switch (action_sw->in_sw)
|
||||
{
|
||||
|
@ -336,6 +336,9 @@ void ConfigStorage::addSession(TraceSession& session)
|
||||
if (!session.ses_name.empty()) {
|
||||
putItem(tagName, session.ses_name.length(), session.ses_name.c_str());
|
||||
}
|
||||
if (session.ses_auth.hasData()) {
|
||||
putItem(tagAuthBlock, session.ses_auth.getCount(), session.ses_auth.begin());
|
||||
}
|
||||
putItem(tagUserName, session.ses_user.length(), session.ses_user.c_str());
|
||||
putItem(tagFlags, sizeof(session.ses_flags), &session.ses_flags);
|
||||
putItem(tagConfig, session.ses_config.length(), session.ses_config.c_str());
|
||||
@ -409,6 +412,11 @@ bool ConfigStorage::getNextSession(TraceSession& session)
|
||||
p = session.ses_logfile.getBuffer(len);
|
||||
break;
|
||||
|
||||
case tagAuthBlock:
|
||||
if (session.ses_id)
|
||||
p = session.ses_auth.getBuffer(len);
|
||||
break;
|
||||
|
||||
default:
|
||||
fb_assert(false);
|
||||
}
|
||||
|
@ -109,6 +109,7 @@ private:
|
||||
{
|
||||
tagID = 1, // session ID
|
||||
tagName, // session Name
|
||||
tagAuthBlock, // with which creator logged in
|
||||
tagUserName, // creator user name
|
||||
tagFlags, // session flags
|
||||
tagConfig, // configuration
|
||||
|
@ -30,10 +30,12 @@
|
||||
|
||||
#include "../../jrd/trace/TraceManager.h"
|
||||
#include "../../jrd/trace/TraceObjects.h"
|
||||
#include "../../jrd/Mapping.h"
|
||||
#include "../../common/os/path_utils.h"
|
||||
#include "../../common/ScanDir.h"
|
||||
#include "../../common/isc_proto.h"
|
||||
#include "../../common/classes/GetPlugins.h"
|
||||
#include "../../common/db_alias.h"
|
||||
|
||||
#ifdef WIN_NT
|
||||
#include <process.h>
|
||||
@ -223,12 +225,61 @@ void TraceManager::update_session(const TraceSession& session)
|
||||
{
|
||||
if (attachment)
|
||||
{
|
||||
if (!attachment->att_user || attachment->att_user->usr_user_name != session.ses_user)
|
||||
if ((!attachment->att_user) || (attachment->att_flags & ATT_mapping))
|
||||
return;
|
||||
|
||||
string s_user = session.ses_user;
|
||||
string t_role;
|
||||
if (session.ses_auth.hasData())
|
||||
{
|
||||
Database* dbb = attachment->att_database;
|
||||
fb_assert(dbb);
|
||||
|
||||
try
|
||||
{
|
||||
mapUser(s_user, t_role, NULL, NULL, session.ses_auth,
|
||||
attachment->att_filename.c_str(), dbb->dbb_filename.c_str(),
|
||||
dbb->dbb_config->getSecurityDatabase(),
|
||||
dbb->dbb_provider->getCryptCallback());
|
||||
}
|
||||
catch(const Firebird::Exception&)
|
||||
{
|
||||
// Error in mapUser() means missing context, therefore...
|
||||
return;
|
||||
}
|
||||
t_role.upper();
|
||||
}
|
||||
|
||||
if (s_user != SYSDBA_USER_NAME && t_role != ADMIN_ROLE &&
|
||||
attachment->att_user->usr_user_name != s_user)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (service)
|
||||
{
|
||||
if (session.ses_user != service->getUserName())
|
||||
string s_user = session.ses_user;
|
||||
string t_role;
|
||||
if (session.ses_auth.hasData())
|
||||
{
|
||||
PathName dummy;
|
||||
RefPtr<Config> config;
|
||||
expandDatabaseName(service->getExpectedDb(), dummy, &config);
|
||||
|
||||
try
|
||||
{
|
||||
mapUser(s_user, t_role, NULL, NULL, session.ses_auth, "services manager", NULL,
|
||||
config->getSecurityDatabase(), service->getCryptCallback());
|
||||
}
|
||||
catch(const Firebird::Exception&)
|
||||
{
|
||||
// Error in mapUser() means missing context, therefore...
|
||||
return;
|
||||
}
|
||||
t_role.upper();
|
||||
}
|
||||
|
||||
if (s_user != SYSDBA_USER_NAME && t_role != ADMIN_ROLE && service->getUserName() != s_user)
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
@ -54,8 +54,8 @@ public:
|
||||
|
||||
virtual ~TraceSvcJrd() {};
|
||||
|
||||
virtual void setAttachInfo(const string& service_name, const string& user,
|
||||
const string& pwd, bool isAdmin);
|
||||
virtual void setAttachInfo(const string& service_name, const string& user, const string& pwd,
|
||||
const AuthReader::AuthBlock& authBlock, bool isAdmin);
|
||||
|
||||
virtual void startSession(TraceSession& session, bool interactive);
|
||||
virtual void stopSession(ULONG id);
|
||||
@ -69,13 +69,15 @@ private:
|
||||
|
||||
Service& m_svc;
|
||||
string m_user;
|
||||
AuthReader::AuthBlock m_authBlock;
|
||||
bool m_admin;
|
||||
ULONG m_chg_number;
|
||||
};
|
||||
|
||||
void TraceSvcJrd::setAttachInfo(const string& /*service_name*/, const string& user,
|
||||
const string& /*pwd*/, bool isAdmin)
|
||||
void TraceSvcJrd::setAttachInfo(const string& /*svc_name*/, const string& user, const string& pwd,
|
||||
const AuthReader::AuthBlock& authBlock, bool isAdmin)
|
||||
{
|
||||
m_authBlock = authBlock;
|
||||
m_user = user;
|
||||
m_admin = isAdmin || (m_user == SYSDBA_USER_NAME);
|
||||
}
|
||||
@ -93,6 +95,7 @@ void TraceSvcJrd::startSession(TraceSession& session, bool interactive)
|
||||
{ // scope
|
||||
StorageGuard guard(storage);
|
||||
|
||||
session.ses_auth = m_authBlock;
|
||||
session.ses_user = m_user;
|
||||
|
||||
session.ses_flags = trs_active;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "fb_exception.h"
|
||||
#include "iberror.h"
|
||||
#include "../../common/classes/fb_string.h"
|
||||
#include "../../common/classes/ClumpletReader.h"
|
||||
#include "../../common/StatusArg.h"
|
||||
#include "../../common/UtilSvc.h"
|
||||
#include "../../jrd/constants.h"
|
||||
@ -47,8 +48,8 @@ namespace Firebird {
|
||||
class TraceSvcIntf
|
||||
{
|
||||
public:
|
||||
virtual void setAttachInfo(const string& service_name, const string& user,
|
||||
const string& pwd, bool isAdmin) = 0;
|
||||
virtual void setAttachInfo(const string& service_name, const string& user, const string& pwd,
|
||||
const AuthReader::AuthBlock& authBlock, bool isAdmin) = 0;
|
||||
|
||||
virtual void startSession(TraceSession& session, bool interactive) = 0;
|
||||
virtual void stopSession(ULONG id) = 0;
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include "firebird.h"
|
||||
#include "../../common/classes/fb_string.h"
|
||||
#include "../../common/classes/ClumpletReader.h"
|
||||
|
||||
|
||||
namespace Firebird {
|
||||
@ -46,6 +47,7 @@ public:
|
||||
explicit TraceSession(MemoryPool& pool) :
|
||||
ses_id(0),
|
||||
ses_name(pool),
|
||||
ses_auth(pool),
|
||||
ses_user(pool),
|
||||
ses_config(pool),
|
||||
ses_start(0),
|
||||
@ -59,6 +61,7 @@ public:
|
||||
{
|
||||
ses_id = 0;
|
||||
ses_name = "";
|
||||
ses_auth.clear();
|
||||
ses_user = "";
|
||||
ses_config = "";
|
||||
ses_start = 0;
|
||||
@ -68,6 +71,7 @@ public:
|
||||
|
||||
ULONG ses_id;
|
||||
string ses_name;
|
||||
AuthReader::AuthBlock ses_auth;
|
||||
string ses_user;
|
||||
string ses_config;
|
||||
time_t ses_start;
|
||||
|
@ -2167,6 +2167,10 @@ void DatabaseAuth::accept(PACKET* send, Auth::WriterImplementation* authBlock)
|
||||
case isc_dpb_password:
|
||||
case isc_dpb_password_enc:
|
||||
|
||||
// remove tags for specific internal attaches
|
||||
case isc_dpb_map_attach:
|
||||
case isc_dpb_sec_attach:
|
||||
|
||||
// remove client's config information
|
||||
case isc_dpb_config:
|
||||
pb->deleteClumplet();
|
||||
|
@ -47,8 +47,8 @@ public:
|
||||
TraceSvcUtil();
|
||||
virtual ~TraceSvcUtil();
|
||||
|
||||
virtual void setAttachInfo(const string& service_name, const string& user,
|
||||
const string& pwd, bool isAdmin);
|
||||
virtual void setAttachInfo(const string& service_name, const string& user, const string& pwd,
|
||||
const AuthReader::AuthBlock& authBlock, bool isAdmin);
|
||||
|
||||
virtual void startSession(TraceSession& session, bool interactive);
|
||||
virtual void stopSession(ULONG id);
|
||||
@ -83,8 +83,8 @@ TraceSvcUtil::~TraceSvcUtil()
|
||||
}
|
||||
}
|
||||
|
||||
void TraceSvcUtil::setAttachInfo(const string& service_name, const string& user,
|
||||
const string& pwd, bool isAdmin)
|
||||
void TraceSvcUtil::setAttachInfo(const string& service_name, const string& user, const string& pwd,
|
||||
const AuthReader::AuthBlock& /*authBlock*/, bool isAdmin)
|
||||
{
|
||||
ISC_STATUS_ARRAY status = {0};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user