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

Fixed CORE-5472: Problems with dbcrypt key transfer

This commit is contained in:
AlexPeshkoff 2017-01-31 17:38:53 +03:00
parent 7fadd8e9f9
commit 4da3997b49
51 changed files with 3639 additions and 2680 deletions

View File

@ -466,6 +466,37 @@
# #
#KeyHolderPlugin = #KeyHolderPlugin =
# ----------------------------
#
# Ability to use encrypted security database
#
# If one relies on network encryption feature with crypt key generated
# by authentication plugin (like SRP does) to transfer database crypt
# keys over the wire then use of encrypted security databases is a kind of
# vicious circle. In order to send DB crypt key over the wire in secure way
# wire transfers should be already encrypted but this requires wire crypt key
# from authentication plugin which needs to open security database for hash
# validation which in turn requires DB crypt key. Luckily in most cases there
# is no big need to encrypt security database - it protects itself quite well
# if you use high quality passwords. But in some cases it's desired to have
# security database encrypted, for example if one wants to use self security
# database feature for encrypted database. In that case special care should be
# taken to encrypt that key before passing it to server using callback. Make
# sure your keys are well encrypted before enabling this parameter. Take into
# account that with CryptSecurityDatabase=TRUE unencrypted by firebird protocol
# key transfer may take place even with not encrypted security database.
# This feature is not supported by legacy authentication plugin - if you care
# about security please never use legacy authentication.
#
# Type: boolean
#
# Per-database configurable.
#
#########################################################################
# Please understand what are you doing before enabling this feature !!! #
#########################################################################
#
#CryptSecurityDatabase = false
# ---------------------------- # ----------------------------
# #

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,7 @@
*/ */
#include "../interfaces/ifaceExamples.h" #include "../interfaces/ifaceExamples.h"
#include <firebird/Message.h>
using namespace Firebird; using namespace Firebird;
@ -79,7 +80,7 @@ public:
status->dispose(); status->dispose();
} }
enum Action {NONE, ENC, DEC}; enum Action {NONE, ENC, DEC, EX_LCL, EX_RMT};
void execute(const char* dbName, const Action a) void execute(const char* dbName, const Action a)
{ {
@ -104,18 +105,55 @@ public:
throw "startTransaction"; throw "startTransaction";
} }
if (a == ENC) switch(a)
{ {
case ENC:
att->execute(status, tra, 0, att->execute(status, tra, 0,
"ALTER DATABASE ENCRYPT WITH \"DbCrypt_example\"", 3, NULL, NULL, NULL, NULL); "ALTER DATABASE ENCRYPT WITH \"DbCrypt_example\"", 3, NULL, NULL, NULL, NULL);
if (status->getState() & IStatus::STATE_ERRORS) if (status->getState() & IStatus::STATE_ERRORS)
throw "execute"; throw "execute";
} break;
if (a == DEC)
{ case DEC:
att->execute(status, tra, 0, "ALTER DATABASE DECRYPT", 3, NULL, NULL, NULL, NULL); att->execute(status, tra, 0, "ALTER DATABASE DECRYPT", 3, NULL, NULL, NULL, NULL);
if (status->getState() & IStatus::STATE_ERRORS) if (status->getState() & IStatus::STATE_ERRORS)
throw "execute"; throw "execute";
break;
case EX_LCL:
case EX_RMT:
{
FB_MESSAGE(Output, CheckStatusWrapper,
(FB_VARCHAR(31), logon)
) output(status, master);
const char* sqlL = "select current_user from rdb$database";
const char* sqlR = "execute block returns(logon varchar(31)) as begin "
"execute statement 'select current_user from rdb$database' "
"on external 'localhost:employee' as user 'test' password 'test' into :logon; "
"suspend; end";
const char* sql = a == EX_LCL ? sqlL : sqlR;
curs = att->openCursor(status, tra, 0, sql, 3, NULL, NULL, output.getMetadata(), NULL, 0);
if (status->getState() & IStatus::STATE_ERRORS)
throw "openCursor";
printf("\nExec SQL: %s\nReturns:\n", sql);
while (curs->fetchNext(status, output.getData()) == IStatus::RESULT_OK)
{
unsigned l = output->logonNull ? 0 : output->logon.length;
printf("%*.*s\n", l, l, output->logon.str);
}
printf("done.\n");
if (status->getState() & IStatus::STATE_ERRORS)
throw "fetchNext";
curs->close(status);
if (status->getState() & IStatus::STATE_ERRORS)
throw "close";
curs = NULL;
break;
}
} }
if (tra) if (tra)
@ -126,7 +164,7 @@ public:
tra = NULL; tra = NULL;
} }
printf("Providing key for crypt plugin - press enter to continue ..."); printf("\nProviding key for crypt plugin - press enter to continue ...");
getchar(); getchar();
att->detach(status); att->detach(status);
@ -151,13 +189,14 @@ private:
IProvider* p; IProvider* p;
IAttachment* att; IAttachment* att;
ITransaction* tra; ITransaction* tra;
IResultSet* curs;
CryptKey key; CryptKey key;
}; };
int usage() int usage()
{ {
fprintf(stderr, "Usage: CryptApplication [ -e | -d ] { db-name }\n"); fprintf(stderr, "Usage: cryptAppSample [ -e | -d | -l | -r ] { db-name }\n");
return 2; return 2;
} }
@ -181,6 +220,12 @@ int main(int ac, char** av)
case 'd': case 'd':
act = App::DEC; act = App::DEC;
break; break;
case 'l':
act = App::EX_LCL;
break;
case 'r':
act = App::EX_RMT;
break;
default: default:
return usage(); return usage();
} }

View File

@ -77,6 +77,7 @@ public:
// IKeyHolderPlugin implementation // IKeyHolderPlugin implementation
int keyCallback(CheckStatusWrapper* status, ICryptKeyCallback* callback); int keyCallback(CheckStatusWrapper* status, ICryptKeyCallback* callback);
ICryptKeyCallback* keyHandle(CheckStatusWrapper* status, const char* keyName); ICryptKeyCallback* keyHandle(CheckStatusWrapper* status, const char* keyName);
ICryptKeyCallback* chainHandle(CheckStatusWrapper* status);
int release() int release()
{ {
@ -200,8 +201,6 @@ IConfigEntry* CryptKeyHolder::getEntry(CheckStatusWrapper* status, const char* e
int CryptKeyHolder::keyCallback(CheckStatusWrapper* status, ICryptKeyCallback* callback) int CryptKeyHolder::keyCallback(CheckStatusWrapper* status, ICryptKeyCallback* callback)
{ {
status->init();
if (key != 0) if (key != 0)
return 1; return 1;
@ -258,6 +257,12 @@ ICryptKeyCallback* CryptKeyHolder::keyHandle(CheckStatusWrapper* status, const c
return NULL; return NULL;
} }
ICryptKeyCallback* CryptKeyHolder::chainHandle(CheckStatusWrapper* status)
{
return &callbackInterface;
}
class Factory : public IPluginFactoryImpl<Factory, CheckStatusWrapper> class Factory : public IPluginFactoryImpl<Factory, CheckStatusWrapper>
{ {
public: public:

View File

@ -236,7 +236,9 @@ void DbCrypt::setKey(CheckStatusWrapper* status, unsigned int length, IKeyHolder
return; return;
if (callback && callback->callback(0, NULL, 1, &key) == 1) if (callback && callback->callback(0, NULL, 1, &key) == 1)
{
return; return;
}
} }
key = 0; key = 0;

View File

@ -123,6 +123,9 @@ int DebugServer::authenticate(Firebird::CheckStatusWrapper* status, Firebird::IS
return AUTH_FAILED; return AUTH_FAILED;
} }
void DebugServer::setDbCryptCallback(Firebird::CheckStatusWrapper*, Firebird::ICryptKeyCallback*)
{ /* ignore it */ }
int DebugServer::release() int DebugServer::release()
{ {
if (--refCounter == 0) if (--refCounter == 0)

View File

@ -54,6 +54,7 @@ public:
int authenticate(Firebird::CheckStatusWrapper* status, Firebird::IServerBlock* sBlock, int authenticate(Firebird::CheckStatusWrapper* status, Firebird::IServerBlock* sBlock,
Firebird::IWriter* writerInterface); Firebird::IWriter* writerInterface);
void setDbCryptCallback(Firebird::CheckStatusWrapper*, Firebird::ICryptKeyCallback*);
int release(); int release();
private: private:

View File

@ -55,7 +55,7 @@ public:
: server(NULL), data(getPool()), account(getPool()), : server(NULL), data(getPool()), account(getPool()),
clientPubKey(getPool()), serverPubKey(getPool()), clientPubKey(getPool()), serverPubKey(getPool()),
verifier(getPool()), salt(getPool()), sessionKey(getPool()), verifier(getPool()), salt(getPool()), sessionKey(getPool()),
secDbName(NULL) secDbName(NULL), cryptCallback(NULL)
{ {
LocalStatus ls; LocalStatus ls;
CheckStatusWrapper s(&ls); CheckStatusWrapper s(&ls);
@ -65,6 +65,7 @@ public:
// IServer implementation // IServer implementation
int authenticate(CheckStatusWrapper* status, IServerBlock* sBlock, IWriter* writerInterface); int authenticate(CheckStatusWrapper* status, IServerBlock* sBlock, IWriter* writerInterface);
void setDbCryptCallback(CheckStatusWrapper* status, ICryptKeyCallback* callback);
int release(); int release();
private: private:
@ -82,6 +83,7 @@ private:
UCharBuffer sessionKey; UCharBuffer sessionKey;
RefPtr<IFirebirdConf> config; RefPtr<IFirebirdConf> config;
const char* secDbName; const char* secDbName;
ICryptKeyCallback* cryptCallback;
}; };
int SrpServer::authenticate(CheckStatusWrapper* status, IServerBlock* sb, IWriter* writerInterface) int SrpServer::authenticate(CheckStatusWrapper* status, IServerBlock* sb, IWriter* writerInterface)
@ -130,6 +132,12 @@ int SrpServer::authenticate(CheckStatusWrapper* status, IServerBlock* sb, IWrite
try try
{ {
if (cryptCallback)
{
p->setDbCryptCallback(status, cryptCallback);
status->init(); // ignore possible errors like missing call in provider
}
ClumpletWriter dpb(ClumpletReader::dpbList, MAX_DPB_SIZE); ClumpletWriter dpb(ClumpletReader::dpbList, MAX_DPB_SIZE);
dpb.insertByte(isc_dpb_sec_attach, TRUE); dpb.insertByte(isc_dpb_sec_attach, TRUE);
dpb.insertString(isc_dpb_user_name, DBA_USER_NAME, fb_strlen(DBA_USER_NAME)); dpb.insertString(isc_dpb_user_name, DBA_USER_NAME, fb_strlen(DBA_USER_NAME));
@ -287,6 +295,11 @@ int SrpServer::authenticate(CheckStatusWrapper* status, IServerBlock* sb, IWrite
return AUTH_CONTINUE; return AUTH_CONTINUE;
} }
void SrpServer::setDbCryptCallback(CheckStatusWrapper* status, ICryptKeyCallback* callback)
{
cryptCallback = callback;
}
int SrpServer::release() int SrpServer::release()
{ {
if (--refCounter == 0) if (--refCounter == 0)

View File

@ -134,6 +134,7 @@ public:
// IServer implementation // IServer implementation
int authenticate(Firebird::CheckStatusWrapper* status, Firebird::IServerBlock* sBlock, int authenticate(Firebird::CheckStatusWrapper* status, Firebird::IServerBlock* sBlock,
Firebird::IWriter* writerInterface); Firebird::IWriter* writerInterface);
void setDbCryptCallback(Firebird::CheckStatusWrapper*, Firebird::ICryptKeyCallback*) { } // ignore
int release(); int release();
private: private:

View File

@ -54,7 +54,7 @@ public:
} }
GetPlugins(unsigned int interfaceType, GetPlugins(unsigned int interfaceType,
Config* knownConfig, const char* namesList = NULL) const Config* knownConfig, const char* namesList = NULL)
: masterInterface(), pluginInterface(), : masterInterface(), pluginInterface(),
pluginSet(NULL), currentPlugin(NULL), pluginSet(NULL), currentPlugin(NULL),
ls(*getDefaultMemoryPool()), status(&ls) ls(*getDefaultMemoryPool()), status(&ls)

View File

@ -33,12 +33,12 @@ namespace Firebird
class RefCounted class RefCounted
{ {
public: public:
virtual int addRef() virtual int addRef() const
{ {
return ++m_refCnt; return ++m_refCnt;
} }
virtual int release() virtual int release() const
{ {
fb_assert(m_refCnt.value() > 0); fb_assert(m_refCnt.value() > 0);
const int refCnt = --m_refCnt; const int refCnt = --m_refCnt;
@ -56,7 +56,7 @@ namespace Firebird
} }
private: private:
AtomicCounter m_refCnt; mutable AtomicCounter m_refCnt;
}; };
// reference counted object guard // reference counted object guard

View File

@ -69,12 +69,14 @@ public:
} }
} }
/* void changeDefaultConfig(Config* newConfig) /* It was a kind of getting ready for changing config remotely...
void changeDefaultConfig(Config* newConfig)
{ {
defaultConfig = newConfig; defaultConfig = newConfig;
} }
*/ */
const Firebird::RefPtr<Config>& getDefaultConfig() const Firebird::RefPtr<const Config>& getDefaultConfig()
{ {
return defaultConfig; return defaultConfig;
} }
@ -92,7 +94,7 @@ public:
} }
private: private:
Firebird::RefPtr<Config> defaultConfig; Firebird::RefPtr<const Config> defaultConfig;
ConfigImpl(const ConfigImpl&); ConfigImpl(const ConfigImpl&);
void operator=(const ConfigImpl&); void operator=(const ConfigImpl&);
@ -194,7 +196,8 @@ const Config::ConfigEntry Config::entries[MAX_CONFIG_KEY] =
{TYPE_BOOLEAN, "IPv6V6Only", (ConfigValue) false}, {TYPE_BOOLEAN, "IPv6V6Only", (ConfigValue) false},
{TYPE_BOOLEAN, "WireCompression", (ConfigValue) false}, {TYPE_BOOLEAN, "WireCompression", (ConfigValue) false},
{TYPE_INTEGER, "MaxIdentifierByteLength", (ConfigValue) -1}, {TYPE_INTEGER, "MaxIdentifierByteLength", (ConfigValue) -1},
{TYPE_INTEGER, "MaxIdentifierCharLength", (ConfigValue) -1} {TYPE_INTEGER, "MaxIdentifierCharLength", (ConfigValue) -1},
{TYPE_BOOLEAN, "CryptSecurityDatabase", (ConfigValue) false}
}; };
/****************************************************************************** /******************************************************************************
@ -256,7 +259,7 @@ Config::Config(const ConfigFile& file, const Config& base, const Firebird::PathN
notifyDatabase = notify; notifyDatabase = notify;
} }
void Config::notify() void Config::notify() const
{ {
if (!notifyDatabase.hasData()) if (!notifyDatabase.hasData())
return; return;
@ -264,7 +267,7 @@ void Config::notify()
notifyDatabase.erase(); notifyDatabase.erase();
} }
void Config::merge(Firebird::RefPtr<Config>& config, const Firebird::string* dpbConfig) void Config::merge(Firebird::RefPtr<const Config>& config, const Firebird::string* dpbConfig)
{ {
if (dpbConfig && dpbConfig->hasData()) if (dpbConfig && dpbConfig->hasData())
{ {
@ -338,7 +341,7 @@ Config::~Config()
* Public interface * Public interface
*/ */
const Firebird::RefPtr<Config>& Config::getDefaultConfig() const Firebird::RefPtr<const Config>& Config::getDefaultConfig()
{ {
return firebirdConf().getDefaultConfig(); return firebirdConf().getDefaultConfig();
} }
@ -810,3 +813,8 @@ int Config::getMaxIdentifierCharLength() const
return MIN(MAX(rc, 1), METADATA_IDENTIFIER_CHAR_LEN); return MIN(MAX(rc, 1), METADATA_IDENTIFIER_CHAR_LEN);
} }
bool Config::getCryptSecurityDatabase() const
{
return get<bool>(KEY_ENCRYPT_SECURITY_DATABASE);
}

View File

@ -142,6 +142,7 @@ public:
KEY_WIRE_COMPRESSION, KEY_WIRE_COMPRESSION,
KEY_MAX_IDENTIFIER_BYTE_LENGTH, KEY_MAX_IDENTIFIER_BYTE_LENGTH,
KEY_MAX_IDENTIFIER_CHAR_LENGTH, KEY_MAX_IDENTIFIER_CHAR_LENGTH,
KEY_ENCRYPT_SECURITY_DATABASE,
MAX_CONFIG_KEY // keep it last MAX_CONFIG_KEY // keep it last
}; };
@ -174,7 +175,7 @@ private:
static const ConfigEntry entries[MAX_CONFIG_KEY]; static const ConfigEntry entries[MAX_CONFIG_KEY];
ConfigValue values[MAX_CONFIG_KEY]; ConfigValue values[MAX_CONFIG_KEY];
Firebird::PathName notifyDatabase; mutable Firebird::PathName notifyDatabase;
public: public:
explicit Config(const ConfigFile& file); // use to build default config explicit Config(const ConfigFile& file); // use to build default config
@ -184,7 +185,7 @@ public:
// Call it when database with given config is created // Call it when database with given config is created
void notify(); void notify() const;
// Check for missing firebird.conf // Check for missing firebird.conf
@ -199,10 +200,10 @@ public:
static const Firebird::PathName* getCommandLineRootDirectory(); static const Firebird::PathName* getCommandLineRootDirectory();
// Master config - needed to provide per-database config // Master config - needed to provide per-database config
static const Firebird::RefPtr<Config>& getDefaultConfig(); static const Firebird::RefPtr<const Config>& getDefaultConfig();
// Merge config entries from DPB into existing config // Merge config entries from DPB into existing config
static void merge(Firebird::RefPtr<Config>& config, const Firebird::string* dpbConfig); static void merge(Firebird::RefPtr<const Config>& config, const Firebird::string* dpbConfig);
// reports key to be used by the following functions // reports key to be used by the following functions
static unsigned int getKeyByName(ConfigName name); static unsigned int getKeyByName(ConfigName name);
@ -349,6 +350,8 @@ public:
int getMaxIdentifierByteLength() const; int getMaxIdentifierByteLength() const;
int getMaxIdentifierCharLength() const; int getMaxIdentifierCharLength() const;
bool getCryptSecurityDatabase() const;
}; };
// Implementation of interface to access master configuration file // Implementation of interface to access master configuration file
@ -356,7 +359,7 @@ class FirebirdConf FB_FINAL :
public Firebird::RefCntIface<Firebird::IFirebirdConfImpl<FirebirdConf, Firebird::CheckStatusWrapper> > public Firebird::RefCntIface<Firebird::IFirebirdConfImpl<FirebirdConf, Firebird::CheckStatusWrapper> >
{ {
public: public:
FirebirdConf(Config* existingConfig) FirebirdConf(const Config* existingConfig)
: config(existingConfig) : config(existingConfig)
{ } { }
@ -369,7 +372,7 @@ public:
int release(); int release();
private: private:
Firebird::RefPtr<Config> config; Firebird::RefPtr<const Config> config;
}; };
// Create default instance of IFirebirdConf interface // Create default instance of IFirebirdConf interface

View File

@ -227,7 +227,7 @@ namespace
} }
PathName name; PathName name;
RefPtr<Config> config; RefPtr<const Config> config;
#ifdef HAVE_ID_BY_NAME #ifdef HAVE_ID_BY_NAME
Id* id; Id* id;
#endif #endif
@ -417,7 +417,7 @@ static inline bool hasSeparator(const PathName& name)
// Search for 'alias' in databases.conf, return its value in 'file' if found. Else set file to alias. // Search for 'alias' in databases.conf, return its value in 'file' if found. Else set file to alias.
// Returns true if alias is found in databases.conf. // Returns true if alias is found in databases.conf.
static bool resolveAlias(const PathName& alias, PathName& file, RefPtr<Config>* config) static bool resolveAlias(const PathName& alias, PathName& file, RefPtr<const Config>* config)
{ {
PathName correctedAlias = alias; PathName correctedAlias = alias;
replace_dir_sep(correctedAlias); replace_dir_sep(correctedAlias);
@ -492,7 +492,7 @@ static bool setPath(const PathName& filename, PathName& expandedName)
// Returns true if alias was found in databases.conf // Returns true if alias was found in databases.conf
bool expandDatabaseName(Firebird::PathName alias, bool expandDatabaseName(Firebird::PathName alias,
Firebird::PathName& file, Firebird::PathName& file,
Firebird::RefPtr<Config>* config) Firebird::RefPtr<const Config>* config)
{ {
try try
{ {

View File

@ -30,7 +30,7 @@ class Config;
bool expandDatabaseName(Firebird::PathName alias, bool expandDatabaseName(Firebird::PathName alias,
Firebird::PathName& file, Firebird::PathName& file,
Firebird::RefPtr<Config>* config); Firebird::RefPtr<const Config>* config);
bool notifyDatabaseName(const Firebird::PathName& file); bool notifyDatabaseName(const Firebird::PathName& file);

View File

@ -41,7 +41,7 @@ void raise()
namespace Auth { namespace Auth {
Get::Get(Config* firebirdConf) Get::Get(const Config* firebirdConf)
: GetPlugins<Firebird::IManagement>(IPluginManager::TYPE_AUTH_USER_MANAGEMENT, firebirdConf) : GetPlugins<Firebird::IManagement>(IPluginManager::TYPE_AUTH_USER_MANAGEMENT, firebirdConf)
{ {
if (!hasData()) if (!hasData())
@ -50,7 +50,7 @@ Get::Get(Config* firebirdConf)
} }
} }
Get::Get(Config* firebirdConf, const char* plugName) Get::Get(const Config* firebirdConf, const char* plugName)
: GetPlugins<Firebird::IManagement>(IPluginManager::TYPE_AUTH_USER_MANAGEMENT, firebirdConf, plugName) : GetPlugins<Firebird::IManagement>(IPluginManager::TYPE_AUTH_USER_MANAGEMENT, firebirdConf, plugName)
{ {
if (!hasData()) if (!hasData())

View File

@ -259,8 +259,8 @@ public:
class Get : public Firebird::GetPlugins<Firebird::IManagement> class Get : public Firebird::GetPlugins<Firebird::IManagement>
{ {
public: public:
explicit Get(Config* firebirdConf); explicit Get(const Config* firebirdConf);
Get(Config* firebirdConf, const char* plugName); Get(const Config* firebirdConf, const char* plugName);
}; };
int setGsecCode(int code, unsigned int operation); int setGsecCode(int code, unsigned int operation);

View File

@ -439,6 +439,9 @@ typedef ISC_STATUS API_ROUTINE prototype_fb_cancel_operation(ISC_STATUS *,
isc_db_handle *, isc_db_handle *,
USHORT); USHORT);
typedef ISC_STATUS API_ROUTINE prototype_fb_database_crypt_callback(ISC_STATUS *,
void *);
struct FirebirdApiPointers struct FirebirdApiPointers
{ {
prototype_isc_attach_database *isc_attach_database; prototype_isc_attach_database *isc_attach_database;
@ -519,6 +522,7 @@ struct FirebirdApiPointers
prototype_isc_service_query *isc_service_query; prototype_isc_service_query *isc_service_query;
prototype_isc_service_start *isc_service_start; prototype_isc_service_start *isc_service_start;
prototype_fb_cancel_operation *fb_cancel_operation; prototype_fb_cancel_operation *fb_cancel_operation;
prototype_fb_database_crypt_callback *fb_database_crypt_callback;
}; };
#endif #endif

View File

@ -599,6 +599,8 @@ interface Server : Auth
{ {
[notImplemented(Auth::AUTH_FAILED)] [notImplemented(Auth::AUTH_FAILED)]
int authenticate(Status status, ServerBlock sBlock, Writer writerInterface); int authenticate(Status status, ServerBlock sBlock, Writer writerInterface);
version: // 3.0.1 => 4.0
void setDbCryptCallback(Status status, CryptKeyCallback cryptCallback);
} }
// .. and corresponding client // .. and corresponding client
@ -737,6 +739,8 @@ version: // 3.0.1 => 4.0
// With returning true here KeyHolder attachment can use only keys, provided by this KeyHolder. // With returning true here KeyHolder attachment can use only keys, provided by this KeyHolder.
// Use of keys, got by database crypt plugin from other attachments, is prohibited. // Use of keys, got by database crypt plugin from other attachments, is prohibited.
boolean useOnlyOwnKeys(Status status); boolean useOnlyOwnKeys(Status status);
// Communication in a chain of key holders - get callback interface for chaining holders
CryptKeyCallback chainHandle(Status status);
} }

View File

@ -2402,6 +2402,7 @@ namespace Firebird
struct VTable : public IAuth::VTable struct VTable : public IAuth::VTable
{ {
int (CLOOP_CARG *authenticate)(IServer* self, IStatus* status, IServerBlock* sBlock, IWriter* writerInterface) throw(); int (CLOOP_CARG *authenticate)(IServer* self, IStatus* status, IServerBlock* sBlock, IWriter* writerInterface) throw();
void (CLOOP_CARG *setDbCryptCallback)(IServer* self, IStatus* status, ICryptKeyCallback* cryptCallback) throw();
}; };
protected: protected:
@ -2415,7 +2416,7 @@ namespace Firebird
} }
public: public:
static const unsigned VERSION = 5; static const unsigned VERSION = 6;
template <typename StatusType> int authenticate(StatusType* status, IServerBlock* sBlock, IWriter* writerInterface) template <typename StatusType> int authenticate(StatusType* status, IServerBlock* sBlock, IWriter* writerInterface)
{ {
@ -2424,6 +2425,19 @@ namespace Firebird
StatusType::checkException(status); StatusType::checkException(status);
return ret; return ret;
} }
template <typename StatusType> void setDbCryptCallback(StatusType* status, ICryptKeyCallback* cryptCallback)
{
if (cloopVTable->version < 6)
{
StatusType::setVersionError(status, "IServer", cloopVTable->version, 6);
StatusType::checkException(status);
return;
}
StatusType::clearException(status);
static_cast<VTable*>(this->cloopVTable)->setDbCryptCallback(this, status, cryptCallback);
StatusType::checkException(status);
}
}; };
class IClient : public IAuth class IClient : public IAuth
@ -2906,6 +2920,7 @@ namespace Firebird
int (CLOOP_CARG *keyCallback)(IKeyHolderPlugin* self, IStatus* status, ICryptKeyCallback* callback) throw(); int (CLOOP_CARG *keyCallback)(IKeyHolderPlugin* self, IStatus* status, ICryptKeyCallback* callback) throw();
ICryptKeyCallback* (CLOOP_CARG *keyHandle)(IKeyHolderPlugin* self, IStatus* status, const char* keyName) throw(); ICryptKeyCallback* (CLOOP_CARG *keyHandle)(IKeyHolderPlugin* self, IStatus* status, const char* keyName) throw();
FB_BOOLEAN (CLOOP_CARG *useOnlyOwnKeys)(IKeyHolderPlugin* self, IStatus* status) throw(); FB_BOOLEAN (CLOOP_CARG *useOnlyOwnKeys)(IKeyHolderPlugin* self, IStatus* status) throw();
ICryptKeyCallback* (CLOOP_CARG *chainHandle)(IKeyHolderPlugin* self, IStatus* status) throw();
}; };
protected: protected:
@ -2950,6 +2965,20 @@ namespace Firebird
StatusType::checkException(status); StatusType::checkException(status);
return ret; return ret;
} }
template <typename StatusType> ICryptKeyCallback* chainHandle(StatusType* status)
{
if (cloopVTable->version < 5)
{
StatusType::setVersionError(status, "IKeyHolderPlugin", cloopVTable->version, 5);
StatusType::checkException(status);
return 0;
}
StatusType::clearException(status);
ICryptKeyCallback* ret = static_cast<VTable*>(this->cloopVTable)->chainHandle(this, status);
StatusType::checkException(status);
return ret;
}
}; };
class IDbCryptInfo : public IReferenceCounted class IDbCryptInfo : public IReferenceCounted
@ -10013,6 +10042,7 @@ namespace Firebird
this->setOwner = &Name::cloopsetOwnerDispatcher; this->setOwner = &Name::cloopsetOwnerDispatcher;
this->getOwner = &Name::cloopgetOwnerDispatcher; this->getOwner = &Name::cloopgetOwnerDispatcher;
this->authenticate = &Name::cloopauthenticateDispatcher; this->authenticate = &Name::cloopauthenticateDispatcher;
this->setDbCryptCallback = &Name::cloopsetDbCryptCallbackDispatcher;
} }
} vTable; } vTable;
@ -10034,6 +10064,20 @@ namespace Firebird
} }
} }
static void CLOOP_CARG cloopsetDbCryptCallbackDispatcher(IServer* self, IStatus* status, ICryptKeyCallback* cryptCallback) throw()
{
StatusType status2(status);
try
{
static_cast<Name*>(self)->Name::setDbCryptCallback(&status2, cryptCallback);
}
catch (...)
{
StatusType::catchException(&status2);
}
}
static void CLOOP_CARG cloopsetOwnerDispatcher(IPluginBase* self, IReferenceCounted* r) throw() static void CLOOP_CARG cloopsetOwnerDispatcher(IPluginBase* self, IReferenceCounted* r) throw()
{ {
try try
@ -10099,6 +10143,7 @@ namespace Firebird
} }
virtual int authenticate(StatusType* status, IServerBlock* sBlock, IWriter* writerInterface) = 0; virtual int authenticate(StatusType* status, IServerBlock* sBlock, IWriter* writerInterface) = 0;
virtual void setDbCryptCallback(StatusType* status, ICryptKeyCallback* cryptCallback) = 0;
}; };
template <typename Name, typename StatusType, typename Base> template <typename Name, typename StatusType, typename Base>
@ -11246,6 +11291,7 @@ namespace Firebird
this->keyCallback = &Name::cloopkeyCallbackDispatcher; this->keyCallback = &Name::cloopkeyCallbackDispatcher;
this->keyHandle = &Name::cloopkeyHandleDispatcher; this->keyHandle = &Name::cloopkeyHandleDispatcher;
this->useOnlyOwnKeys = &Name::cloopuseOnlyOwnKeysDispatcher; this->useOnlyOwnKeys = &Name::cloopuseOnlyOwnKeysDispatcher;
this->chainHandle = &Name::cloopchainHandleDispatcher;
} }
} vTable; } vTable;
@ -11297,6 +11343,21 @@ namespace Firebird
} }
} }
static ICryptKeyCallback* CLOOP_CARG cloopchainHandleDispatcher(IKeyHolderPlugin* self, IStatus* status) throw()
{
StatusType status2(status);
try
{
return static_cast<Name*>(self)->Name::chainHandle(&status2);
}
catch (...)
{
StatusType::catchException(&status2);
return static_cast<ICryptKeyCallback*>(0);
}
}
static void CLOOP_CARG cloopsetOwnerDispatcher(IPluginBase* self, IReferenceCounted* r) throw() static void CLOOP_CARG cloopsetOwnerDispatcher(IPluginBase* self, IReferenceCounted* r) throw()
{ {
try try
@ -11364,6 +11425,7 @@ namespace Firebird
virtual int keyCallback(StatusType* status, ICryptKeyCallback* callback) = 0; virtual int keyCallback(StatusType* status, ICryptKeyCallback* callback) = 0;
virtual ICryptKeyCallback* keyHandle(StatusType* status, const char* keyName) = 0; virtual ICryptKeyCallback* keyHandle(StatusType* status, const char* keyName) = 0;
virtual FB_BOOLEAN useOnlyOwnKeys(StatusType* status) = 0; virtual FB_BOOLEAN useOnlyOwnKeys(StatusType* status) = 0;
virtual ICryptKeyCallback* chainHandle(StatusType* status) = 0;
}; };
template <typename Name, typename StatusType, typename Base> template <typename Name, typename StatusType, typename Base>

View File

@ -47,7 +47,7 @@
#include "../jrd/Monitoring.h" #include "../jrd/Monitoring.h"
#include "../jrd/os/pio_proto.h" #include "../jrd/os/pio_proto.h"
#include "../common/isc_proto.h" #include "../common/isc_proto.h"
#include "../common/classes/GetPlugins.h" #include "../common/classes/auto.h"
#include "../common/classes/RefMutex.h" #include "../common/classes/RefMutex.h"
#include "../common/classes/ClumpletWriter.h" #include "../common/classes/ClumpletWriter.h"
#include "../common/sha.h" #include "../common/sha.h"
@ -69,6 +69,19 @@ namespace {
const UCHAR CRYPT_INIT = LCK_EX; const UCHAR CRYPT_INIT = LCK_EX;
const int MAX_PLUGIN_NAME_LEN = 31; const int MAX_PLUGIN_NAME_LEN = 31;
class ReleasePlugin
{
public:
static void clear(IPluginBase* ptr)
{
if (ptr)
{
PluginManagerInterfacePtr()->releasePlugin(ptr);
}
}
};
} }
@ -270,7 +283,7 @@ namespace Jrd {
dbInfo(FB_NEW DbInfo(this)), dbInfo(FB_NEW DbInfo(this)),
cryptThreadId(0), cryptThreadId(0),
cryptPlugin(NULL), cryptPlugin(NULL),
checkPlugin(NULL), checkFactory(NULL),
dbb(*tdbb->getDatabase()), dbb(*tdbb->getDatabase()),
cryptAtt(NULL), cryptAtt(NULL),
slowIO(0), slowIO(0),
@ -291,6 +304,7 @@ namespace Jrd {
delete stateLock; delete stateLock;
delete threadLock; delete threadLock;
delete checkFactory;
dbInfo->destroy(); dbInfo->destroy();
} }
@ -363,7 +377,7 @@ namespace Jrd {
else else
keyName = ""; keyName = "";
loadPlugin(hdr->hdr_crypt_plugin); loadPlugin(tdbb, hdr->hdr_crypt_plugin);
string valid; string valid;
calcValidation(valid, cryptPlugin); calcValidation(valid, cryptPlugin);
@ -378,10 +392,10 @@ namespace Jrd {
} }
if (flags & CRYPT_HDR_INIT) if (flags & CRYPT_HDR_INIT)
checkDigitalSignature(hdr); checkDigitalSignature(tdbb, hdr);
} }
void CryptoManager::loadPlugin(const char* pluginName) void CryptoManager::loadPlugin(thread_db* tdbb, const char* pluginName)
{ {
if (cryptPlugin) if (cryptPlugin)
{ {
@ -394,14 +408,14 @@ namespace Jrd {
return; return;
} }
GetPlugins<IDbCryptPlugin> cryptControl(IPluginManager::TYPE_DB_CRYPT, dbb.dbb_config, pluginName); AutoPtr<Factory> cryptControl(FB_NEW Factory(IPluginManager::TYPE_DB_CRYPT, dbb.dbb_config, pluginName));
if (!cryptControl.hasData()) if (!cryptControl->hasData())
{ {
(Arg::Gds(isc_no_crypt_plugin) << pluginName).raise(); (Arg::Gds(isc_no_crypt_plugin) << pluginName).raise();
} }
// do not assign cryptPlugin directly before key init complete // do not assign cryptPlugin directly before key init complete
IDbCryptPlugin* p = cryptControl.plugin(); IDbCryptPlugin* p = cryptControl->plugin();
FbLocalStatus status; FbLocalStatus status;
p->setInfo(&status, dbInfo); p->setInfo(&status, dbInfo);
@ -416,17 +430,15 @@ namespace Jrd {
cryptPlugin = p; cryptPlugin = p;
cryptPlugin->addRef(); cryptPlugin->addRef();
// May be load second instance to validate keys // remove old factory if present
if (checkPlugin) delete checkFactory;
{ checkFactory = NULL;
PluginManagerInterfacePtr()->releasePlugin(checkPlugin);
checkPlugin = NULL;
}
// store new one
if (dbb.dbb_config->getServerMode() == MODE_SUPER) if (dbb.dbb_config->getServerMode() == MODE_SUPER)
{ {
checkPlugin = cryptControl.makeInstance(); checkFactory = cryptControl.release();
keyHolderPlugins.validate(checkPlugin, NULL, keyName); keyHolderPlugins.validateNewAttachment(tdbb->getAttachment(), keyName);
} }
} }
@ -483,7 +495,7 @@ namespace Jrd {
} }
keyName = key; keyName = key;
loadPlugin(plugName.c_str()); loadPlugin(tdbb, plugName.c_str());
} }
} }
} }
@ -560,7 +572,7 @@ namespace Jrd {
// Load plugin // Load plugin
if (newCryptState) if (newCryptState)
{ {
loadPlugin(plugName.c_str()); loadPlugin(tdbb, plugName.c_str());
} }
crypt = newCryptState; crypt = newCryptState;
@ -580,6 +592,9 @@ namespace Jrd {
hc.deleteWithTag(Ods::HDR_crypt_key); hc.deleteWithTag(Ods::HDR_crypt_key);
if (keyName.hasData()) if (keyName.hasData())
hc.insertString(Ods::HDR_crypt_key, keyName); hc.insertString(Ods::HDR_crypt_key, keyName);
if (checkFactory)
keyHolderPlugins.validateExistingAttachments(keyName);
} }
else else
header->hdr_flags &= ~Ods::hdr_encrypted; header->hdr_flags &= ~Ods::hdr_encrypted;
@ -591,7 +606,7 @@ namespace Jrd {
header->hdr_flags |= Ods::hdr_crypt_process; header->hdr_flags |= Ods::hdr_crypt_process;
process = true; process = true;
digitalySignDatabase(hdr); digitalySignDatabase(tdbb, hdr);
hdr.flush(); hdr.flush();
} }
catch (const Exception&) catch (const Exception&)
@ -641,13 +656,13 @@ namespace Jrd {
{ {
keyHolderPlugins.attach(att, dbb.dbb_config); keyHolderPlugins.attach(att, dbb.dbb_config);
IDbCryptPlugin* p = checkPlugin; Factory* f = checkFactory;
lockAndReadHeader(tdbb, CRYPT_HDR_INIT); lockAndReadHeader(tdbb, CRYPT_HDR_INIT);
if (p && p == checkPlugin) if (f && f == checkFactory)
{ {
if (!keyHolderPlugins.validate(checkPlugin, att, keyName)) if (!keyHolderPlugins.validateNewAttachment(att, keyName))
(Arg::Gds(isc_bad_crypt_key) << keyName).raise(); (Arg::Gds(isc_bad_crypt_key) << keyName).raise();
} }
} }
@ -713,7 +728,7 @@ namespace Jrd {
crypt = hdr->hdr_flags & Ods::hdr_encrypted ? true : false; crypt = hdr->hdr_flags & Ods::hdr_encrypted ? true : false;
// If we are going to start crypt thread, we need plugin to be loaded // If we are going to start crypt thread, we need plugin to be loaded
loadPlugin(hdr->hdr_crypt_plugin); loadPlugin(tdbb, hdr->hdr_crypt_plugin);
releasingLock = true; releasingLock = true;
LCK_release(tdbb, threadLock); LCK_release(tdbb, threadLock);
@ -956,7 +971,7 @@ namespace Jrd {
} }
} }
digitalySignDatabase(hdr); digitalySignDatabase(tdbb, hdr);
hdr.flush(); hdr.flush();
} }
@ -1162,7 +1177,7 @@ namespace Jrd {
return (crypt ? fb_info_crypt_encrypted : 0) | (process ? fb_info_crypt_process : 0); return (crypt ? fb_info_crypt_encrypted : 0) | (process ? fb_info_crypt_process : 0);
} }
void CryptoManager::KeyHolderPlugins::attach(Attachment* att, Config* config) void CryptoManager::KeyHolderPlugins::attach(Attachment* att, const Config* config)
{ {
MutexLockGuard g(holdersMutex, FB_FUNCTION); MutexLockGuard g(holdersMutex, FB_FUNCTION);
@ -1196,7 +1211,7 @@ namespace Jrd {
} }
} }
if ((!pa) && config->getServerMode() == MODE_SUPER) if (!pa)
{ {
pa = &(knownHolders.add()); pa = &(knownHolders.add());
pa->first = att; pa->first = att;
@ -1254,7 +1269,7 @@ namespace Jrd {
st.check(); st.check();
} }
bool CryptoManager::KeyHolderPlugins::validateHoldersGroup(PerAttHolders& pa, IDbCryptPlugin* crypt, const MetaName& keyName) bool CryptoManager::KeyHolderPlugins::validateHoldersGroup(PerAttHolders& pa, const MetaName& keyName)
{ {
FbLocalStatus st; FbLocalStatus st;
fb_assert(holdersMutex.locked()); fb_assert(holdersMutex.locked());
@ -1265,15 +1280,14 @@ namespace Jrd {
if (!keyHolder->useOnlyOwnKeys(&st)) if (!keyHolder->useOnlyOwnKeys(&st))
return true; return true;
crypt->setKey(&st, 1, &keyHolder, keyName.c_str()); if (validateHolder(keyHolder, keyName))
if (st.isSuccess() && mgr->checkValidation(crypt))
return true; return true;
} }
return true; return false;
} }
bool CryptoManager::KeyHolderPlugins::validate(IDbCryptPlugin* crypt, Attachment* att, const MetaName& keyName) bool CryptoManager::KeyHolderPlugins::validateNewAttachment(Attachment* att, const MetaName& keyName)
{ {
FbLocalStatus st; FbLocalStatus st;
MutexLockGuard g(holdersMutex, FB_FUNCTION); MutexLockGuard g(holdersMutex, FB_FUNCTION);
@ -1286,10 +1300,7 @@ namespace Jrd {
if (pa.first == att) if (pa.first == att)
{ {
bool empty = (pa.second.getCount() == 0); bool empty = (pa.second.getCount() == 0);
bool result = empty ? false : validateHoldersGroup(pa, crypt, keyName); bool result = empty ? false : validateHoldersGroup(pa, keyName);
releaseHolders(pa);
knownHolders.remove(i);
if (empty) if (empty)
break; break;
@ -1299,25 +1310,45 @@ namespace Jrd {
} }
// Special case - holders not needed at all // Special case - holders not needed at all
crypt->setKey(&st, 0, NULL, keyName.c_str()); return validateHolder(NULL, keyName);
if (st.isSuccess() && mgr->checkValidation(crypt)) }
return true;
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());
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; return false;
} }
void CryptoManager::KeyHolderPlugins::validate(IDbCryptPlugin* crypt, const MetaName& keyName) void CryptoManager::KeyHolderPlugins::validateExistingAttachments(const MetaName& keyName)
{ {
FbLocalStatus st; FbLocalStatus st;
MutexLockGuard g(holdersMutex, FB_FUNCTION);
fb_assert(mgr->dbb.dbb_sync.isLocked());
// Special case - holders not needed at all // Special case - holders not needed at all
crypt->setKey(&st, 0, NULL, keyName.c_str()); if (validateHolder(NULL, keyName))
if (st.isSuccess() && mgr->checkValidation(crypt))
return; return;
// Loop through whole attathment list of DBB, shutdown attachments missing any holders // 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) for (Attachment* att = mgr->dbb.dbb_attachments; att; att = att->att_next)
{ {
for (unsigned i = 0; i < knownHolders.getCount(); ++i) for (unsigned i = 0; i < knownHolders.getCount(); ++i)
@ -1326,21 +1357,16 @@ namespace Jrd {
goto found; goto found;
} }
att->signalCancel(); att->signalShutdown();
found:; found:;
} }
// Loop through internal attachments list closing one missing valid holders // Loop through internal attachments list closing one missing valid holders
for (unsigned i = 0; i < knownHolders.getCount(); ++i) for (unsigned i = 0; i < knownHolders.getCount(); ++i)
{ {
if (!validateHoldersGroup(knownHolders[i], crypt, keyName)) if (!validateHoldersGroup(knownHolders[i], keyName))
knownHolders[i].first->signalCancel(); knownHolders[i].first->signalShutdown();
// Cleanup holders list
releaseHolders(knownHolders[i]);
} }
knownHolders.clear();
} }
void CryptoManager::addClumplet(string& signature, ClumpletReader& block, UCHAR tag) void CryptoManager::addClumplet(string& signature, ClumpletReader& block, UCHAR tag)
@ -1354,7 +1380,7 @@ found:;
} }
} }
void CryptoManager::calcDigitalSignature(string& signature, const Header& hdr) void CryptoManager::calcDigitalSignature(thread_db* tdbb, string& signature, const Header& hdr)
{ {
/* /*
We use the following items to calculate digital signature (hash of encrypted string) We use the following items to calculate digital signature (hash of encrypted string)
@ -1383,7 +1409,7 @@ found:;
unsigned len = signature.length(); unsigned len = signature.length();
len &= ~(QUANTUM - 1); len &= ~(QUANTUM - 1);
loadPlugin(hdr->hdr_crypt_plugin); loadPlugin(tdbb, hdr->hdr_crypt_plugin);
string enc; string enc;
FbLocalStatus sv; FbLocalStatus sv;
@ -1395,7 +1421,7 @@ found:;
} }
void CryptoManager::digitalySignDatabase(CchHdr& hdr) void CryptoManager::digitalySignDatabase(thread_db* tdbb, CchHdr& hdr)
{ {
ClumpletWriter hc(ClumpletWriter::UnTagged, hdr->hdr_page_size); ClumpletWriter hc(ClumpletWriter::UnTagged, hdr->hdr_page_size);
hdr.getClumplets(hc); hdr.getClumplets(hc);
@ -1407,7 +1433,7 @@ found:;
{ {
wf = true; wf = true;
string signature; string signature;
calcDigitalSignature(signature, hdr); calcDigitalSignature(tdbb, signature, hdr);
hc.insertString(Ods::HDR_crypt_checksum, signature); hc.insertString(Ods::HDR_crypt_checksum, signature);
} }
@ -1415,7 +1441,7 @@ found:;
hdr.setClumplets(hc); hdr.setClumplets(hc);
} }
void CryptoManager::checkDigitalSignature(const Header& hdr) void CryptoManager::checkDigitalSignature(thread_db* tdbb, const Header& hdr)
{ {
if (hdr->hdr_flags & (Ods::hdr_crypt_process | Ods::hdr_encrypted)) if (hdr->hdr_flags & (Ods::hdr_crypt_process | Ods::hdr_encrypted))
{ {
@ -1426,7 +1452,7 @@ found:;
string sig1, sig2; string sig1, sig2;
hc.getString(sig1); hc.getString(sig1);
calcDigitalSignature(sig2, hdr); calcDigitalSignature(tdbb, sig2, hdr);
if (sig1 != sig2) if (sig1 != sig2)
Arg::Gds(isc_crypt_checksum).raise(); Arg::Gds(isc_crypt_checksum).raise();
} }

View File

@ -36,6 +36,7 @@
#include "../common/classes/objects_array.h" #include "../common/classes/objects_array.h"
#include "../common/classes/condition.h" #include "../common/classes/condition.h"
#include "../common/classes/MetaName.h" #include "../common/classes/MetaName.h"
#include "../common/classes/GetPlugins.h"
#include "../common/ThreadStart.h" #include "../common/ThreadStart.h"
#include "../jrd/ods.h" #include "../jrd/ods.h"
#include "../jrd/status.h" #include "../jrd/status.h"
@ -268,6 +269,8 @@ private:
class CryptoManager FB_FINAL : public Firebird::PermanentStorage, public BarSync::IBar class CryptoManager FB_FINAL : public Firebird::PermanentStorage, public BarSync::IBar
{ {
public: public:
typedef Firebird::GetPlugins<Firebird::IDbCryptPlugin> Factory;
explicit CryptoManager(thread_db* tdbb); explicit CryptoManager(thread_db* tdbb);
~CryptoManager(); ~CryptoManager();
@ -324,31 +327,34 @@ private:
class KeyHolderPlugins class KeyHolderPlugins
{ {
public: public:
typedef CryptoManager::Factory Factory;
explicit KeyHolderPlugins(Firebird::MemoryPool& p, CryptoManager* m) explicit KeyHolderPlugins(Firebird::MemoryPool& p, CryptoManager* m)
: knownHolders(p), mgr(m) : knownHolders(p), mgr(m)
{ } { }
void attach(Attachment* att, Config* config); void attach(Attachment* att, const Config* config);
void init(Firebird::IDbCryptPlugin* crypt, const Firebird::MetaName& keyName); void init(Firebird::IDbCryptPlugin* crypt, const Firebird::MetaName& keyName);
bool validate(Firebird::IDbCryptPlugin* crypt, Attachment*, const Firebird::MetaName& keyName); bool validateNewAttachment(Attachment*, const Firebird::MetaName& keyName);
void validate(Firebird::IDbCryptPlugin* crypt, const Firebird::MetaName& keyName); void validateExistingAttachments(const Firebird::MetaName& keyName);
void detach(Attachment* att); void detach(Attachment* att);
private: private:
Firebird::Mutex holdersMutex; Firebird::Mutex holdersMutex;
typedef Firebird::Pair<Firebird::Right<Attachment*, typedef Firebird::Pair<Firebird::Right<Attachment*,
Firebird::HalfStaticArray<Firebird::IKeyHolderPlugin*, 4>>> PerAttHolders; Firebird::HalfStaticArray<Firebird::IKeyHolderPlugin*, 4> > > PerAttHolders;
Firebird::ObjectsArray<PerAttHolders> knownHolders; Firebird::ObjectsArray<PerAttHolders> knownHolders;
CryptoManager* mgr; CryptoManager* mgr;
bool validateHoldersGroup(PerAttHolders& pa, Firebird::IDbCryptPlugin* crypt, const Firebird::MetaName& keyName); bool validateHoldersGroup(PerAttHolders& pa, const Firebird::MetaName& keyName);
bool validateHolder(Firebird::IKeyHolderPlugin* keyHolder, const Firebird::MetaName& keyName);
void releaseHolders(PerAttHolders& pa); void releaseHolders(PerAttHolders& pa);
}; };
class DbInfo; class DbInfo;
friend class DbInfo; friend class DbInfo;
class DbInfo FB_FINAL : public Firebird::RefCntIface<Firebird::IDbCryptInfoImpl<DbInfo, Firebird::CheckStatusWrapper>> class DbInfo FB_FINAL : public Firebird::RefCntIface<Firebird::IDbCryptInfoImpl<DbInfo, Firebird::CheckStatusWrapper> >
{ {
public: public:
DbInfo(CryptoManager* cm) DbInfo(CryptoManager* cm)
@ -383,7 +389,7 @@ private:
void doOnTakenWriteSync(thread_db* tdbb); void doOnTakenWriteSync(thread_db* tdbb);
void doOnAst(thread_db* tdbb); void doOnAst(thread_db* tdbb);
void loadPlugin(const char* pluginName); void loadPlugin(thread_db* tdbb, const char* pluginName);
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);
@ -394,9 +400,9 @@ private:
static const unsigned CRYPT_HDR_NOWAIT = 0x02; static const unsigned CRYPT_HDR_NOWAIT = 0x02;
void addClumplet(Firebird::string& value, Firebird::ClumpletReader& block, UCHAR tag); void addClumplet(Firebird::string& value, Firebird::ClumpletReader& block, UCHAR tag);
void calcDigitalSignature(Firebird::string& signature, const class Header& hdr); void calcDigitalSignature(thread_db* tdbb, Firebird::string& signature, const class Header& hdr);
void digitalySignDatabase(class CchHdr& hdr); void digitalySignDatabase(thread_db* tdbb, class CchHdr& hdr);
void checkDigitalSignature(const class Header& hdr); void checkDigitalSignature(thread_db* tdbb, const class Header& hdr);
BarSync sync; BarSync sync;
Firebird::MetaName keyName; Firebird::MetaName keyName;
@ -407,7 +413,7 @@ private:
Firebird::RefPtr<DbInfo> dbInfo; Firebird::RefPtr<DbInfo> dbInfo;
Thread::Handle cryptThreadId; Thread::Handle cryptThreadId;
Firebird::IDbCryptPlugin* cryptPlugin; Firebird::IDbCryptPlugin* cryptPlugin;
Firebird::IDbCryptPlugin* checkPlugin; Factory* checkFactory;
Database& dbb; Database& dbb;
Lock* stateLock; Lock* stateLock;
Lock* threadLock; Lock* threadLock;

View File

@ -461,7 +461,7 @@ public:
BackupManager* dbb_backup_manager; // physical backup manager BackupManager* dbb_backup_manager; // physical backup manager
Firebird::TimeStamp dbb_creation_date; // creation date Firebird::TimeStamp dbb_creation_date; // creation date
ExternalFileDirectoryList* dbb_external_file_directory_list; ExternalFileDirectoryList* dbb_external_file_directory_list;
Firebird::RefPtr<Config> dbb_config; Firebird::RefPtr<const Config> dbb_config;
SharedCounter dbb_shared_counter; SharedCounter dbb_shared_counter;
CryptoManager* dbb_crypto_manager; CryptoManager* dbb_crypto_manager;

View File

@ -120,7 +120,7 @@ void EventManager::destroy(EventManager* eventMgr)
} }
EventManager::EventManager(const Firebird::string& id, Firebird::RefPtr<Config> conf) EventManager::EventManager(const Firebird::string& id, Firebird::RefPtr<const Config> conf)
: PID(getpid()), : PID(getpid()),
m_process(NULL), m_process(NULL),
m_processOffset(0), m_processOffset(0),

View File

@ -51,7 +51,7 @@ public:
static void init(Attachment*); static void init(Attachment*);
static void destroy(EventManager*); static void destroy(EventManager*);
EventManager(const Firebird::string& id, Firebird::RefPtr<Config> conf); EventManager(const Firebird::string& id, Firebird::RefPtr<const Config> conf);
~EventManager(); ~EventManager();
void deleteSession(SLONG); void deleteSession(SLONG);
@ -104,7 +104,7 @@ private:
SLONG m_processOffset; SLONG m_processOffset;
Firebird::string m_dbId; Firebird::string m_dbId;
Firebird::RefPtr<Config> m_config; Firebird::RefPtr<const Config> m_config;
Firebird::AutoPtr<Firebird::SharedMemory<evh> > m_sharedMemory; Firebird::AutoPtr<Firebird::SharedMemory<evh> > m_sharedMemory;
Firebird::Semaphore m_startupSemaphore; Firebird::Semaphore m_startupSemaphore;

View File

@ -109,7 +109,7 @@ namespace Jrd
} }
private: private:
RefPtr<Config> config; RefPtr<const Config> config;
}; };
} }

View File

@ -124,12 +124,24 @@ void IscConnection::attach(thread_db* tdbb, const PathName& dbName, const MetaNa
FbLocalStatus status; FbLocalStatus status;
{ {
EngineCallbackGuard guard(tdbb, *this, FB_FUNCTION); EngineCallbackGuard guard(tdbb, *this, FB_FUNCTION);
ICryptKeyCallback* cb = tdbb->getAttachment()->att_crypt_callback;
m_iscProvider.fb_database_crypt_callback(&status, cb);
if (status->getState() & IStatus::STATE_ERRORS) {
raise(&status, tdbb, "crypt_callback");
}
m_iscProvider.isc_attach_database(&status, m_dbName.length(), m_dbName.c_str(), m_iscProvider.isc_attach_database(&status, m_dbName.length(), m_dbName.c_str(),
&m_handle, newDpb.getBufferLength(), &m_handle, newDpb.getBufferLength(),
reinterpret_cast<const char*>(newDpb.getBuffer())); reinterpret_cast<const char*>(newDpb.getBuffer()));
} if (status->getState() & IStatus::STATE_ERRORS) {
if (status->getState() & IStatus::STATE_ERRORS) { raise(&status, tdbb, "attach");
raise(&status, tdbb, "attach"); }
m_iscProvider.fb_database_crypt_callback(&status, NULL);
if (status->getState() & IStatus::STATE_ERRORS) {
raise(&status, tdbb, "crypt_callback");
}
} }
char buff[16]; char buff[16];
@ -1474,6 +1486,15 @@ ISC_STATUS ISC_EXPORT IscProvider::fb_cancel_operation(FbStatusVector* user_stat
return notImplemented(user_status); return notImplemented(user_status);
} }
ISC_STATUS ISC_EXPORT IscProvider::fb_database_crypt_callback(FbStatusVector* user_status,
void* cb)
{
if (m_api.fb_database_crypt_callback)
return m_api.fb_database_crypt_callback(IscStatus(user_status), cb);
return notImplemented(user_status);
}
void IscProvider::loadAPI() void IscProvider::loadAPI()
{ {
FbLocalStatus status; FbLocalStatus status;
@ -1565,7 +1586,8 @@ static FirebirdApiPointers isc_callbacks =
PROTO(isc_service_detach), PROTO(isc_service_detach),
PROTO(isc_service_query), PROTO(isc_service_query),
PROTO(isc_service_start), PROTO(isc_service_start),
PROTO(fb_cancel_operation) PROTO(fb_cancel_operation),
PROTO(fb_database_crypt_callback)
}; };

View File

@ -482,6 +482,9 @@ public:
virtual ISC_STATUS ISC_EXPORT fb_cancel_operation(Jrd::FbStatusVector*, virtual ISC_STATUS ISC_EXPORT fb_cancel_operation(Jrd::FbStatusVector*,
isc_db_handle*, isc_db_handle*,
USHORT); USHORT);
virtual ISC_STATUS ISC_EXPORT fb_database_crypt_callback(Jrd::FbStatusVector*,
void*);
}; };

View File

@ -180,7 +180,7 @@ void validatePassword(thread_db* tdbb, const PathName& file, ClumpletWriter& dpb
Arg::Gds loginError(isc_login_error); Arg::Gds loginError(isc_login_error);
// Build list of client/server plugins // Build list of client/server plugins
RefPtr<Config> config; RefPtr<const Config> config;
PathName list; PathName list;
expandDatabaseName(file, list /* unused value */, &config); expandDatabaseName(file, list /* unused value */, &config);
PathName serverList = config->getPlugins(IPluginManager::TYPE_AUTH_SERVER); PathName serverList = config->getPlugins(IPluginManager::TYPE_AUTH_SERVER);

View File

@ -969,7 +969,7 @@ public:
void get(const UCHAR*, USHORT, bool&); void get(const UCHAR*, USHORT, bool&);
void setBuffers(RefPtr<Config> config) void setBuffers(RefPtr<const Config> config)
{ {
if (dpb_buffers == 0) if (dpb_buffers == 0)
{ {
@ -1046,7 +1046,7 @@ static VdnResult verifyDatabaseName(const PathName&, FbStatusVector*, bool);
static void unwindAttach(thread_db* tdbb, const Exception& ex, FbStatusVector* userStatus, static void unwindAttach(thread_db* tdbb, const Exception& ex, FbStatusVector* userStatus,
Jrd::Attachment* attachment, Database* dbb, bool internalFlag); Jrd::Attachment* attachment, Database* dbb, bool internalFlag);
static JAttachment* initAttachment(thread_db*, const PathName&, const PathName&, RefPtr<Config>, bool, static JAttachment* initAttachment(thread_db*, const PathName&, const PathName&, RefPtr<const Config>, bool,
const DatabaseOptions&, RefMutexUnlock&, IPluginConfig*, JProvider*); const DatabaseOptions&, RefMutexUnlock&, IPluginConfig*, JProvider*);
static JAttachment* create_attachment(const PathName&, Database*, const DatabaseOptions&, bool newDb); static JAttachment* create_attachment(const PathName&, Database*, const DatabaseOptions&, bool newDb);
static void prepare_tra(thread_db*, jrd_tra*, USHORT, const UCHAR*); static void prepare_tra(thread_db*, jrd_tra*, USHORT, const UCHAR*);
@ -1056,7 +1056,7 @@ static void release_attachment(thread_db*, Jrd::Attachment*);
static void rollback(thread_db*, jrd_tra*, const bool); static void rollback(thread_db*, jrd_tra*, const bool);
static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsigned flags = 0); static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsigned flags = 0);
static void getUserInfo(UserId&, const DatabaseOptions&, const char*, const char*, static void getUserInfo(UserId&, const DatabaseOptions&, const char*, const char*,
const RefPtr<Config>*, bool, IAttachment*, ICryptKeyCallback*); const RefPtr<const Config>*, bool, IAttachment*, ICryptKeyCallback*);
static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM); static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM);
@ -1343,7 +1343,7 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
ThreadContextHolder tdbb(user_status); ThreadContextHolder tdbb(user_status);
DatabaseOptions options; DatabaseOptions options;
RefPtr<Config> config; RefPtr<const Config> config;
bool invalid_client_SQL_dialect = false; bool invalid_client_SQL_dialect = false;
PathName org_filename, expanded_name; PathName org_filename, expanded_name;
bool is_alias = false; bool is_alias = false;
@ -2427,7 +2427,7 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
DatabaseOptions options; DatabaseOptions options;
PathName org_filename, expanded_name; PathName org_filename, expanded_name;
bool is_alias = false; bool is_alias = false;
Firebird::RefPtr<Config> config; Firebird::RefPtr<const Config> config;
try try
{ {
@ -5981,7 +5981,7 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
static JAttachment* initAttachment(thread_db* tdbb, const PathName& expanded_name, static JAttachment* initAttachment(thread_db* tdbb, const PathName& expanded_name,
const PathName& alias_name, RefPtr<Config> config, bool attach_flag, const PathName& alias_name, RefPtr<const Config> config, bool attach_flag,
const DatabaseOptions& options, RefMutexUnlock& initGuard, IPluginConfig* pConf, const DatabaseOptions& options, RefMutexUnlock& initGuard, IPluginConfig* pConf,
JProvider* provider) JProvider* provider)
{ {
@ -7126,7 +7126,7 @@ static VdnResult verifyDatabaseName(const PathName& name, FbStatusVector* status
if (!securityNameBuffer->hasData()) if (!securityNameBuffer->hasData())
{ {
const RefPtr<Config> defConf(Config::getDefaultConfig()); const RefPtr<const Config> defConf(Config::getDefaultConfig());
securityNameBuffer->assign(defConf->getSecurityDatabase()); securityNameBuffer->assign(defConf->getSecurityDatabase());
expandedSecurityNameBuffer->assign(securityNameBuffer); expandedSecurityNameBuffer->assign(securityNameBuffer);
ISC_expand_filename(expandedSecurityNameBuffer, false); ISC_expand_filename(expandedSecurityNameBuffer, false);
@ -7166,7 +7166,7 @@ static VdnResult verifyDatabaseName(const PathName& name, FbStatusVector* status
**/ **/
static void getUserInfo(UserId& user, const DatabaseOptions& options, static void getUserInfo(UserId& user, const DatabaseOptions& options,
const char* aliasName, const char* dbName, const RefPtr<Config>* config, bool creating, const char* aliasName, const char* dbName, const RefPtr<const Config>* config, bool creating,
IAttachment* iAtt, ICryptKeyCallback* cryptCb) IAttachment* iAtt, ICryptKeyCallback* cryptCb)
{ {
bool wheel = false; bool wheel = false;

View File

@ -729,7 +729,7 @@ Service::Service(const TEXT* service_name, USHORT spb_length, const UCHAR* spb_d
if (svc_auth_block.hasData()) if (svc_auth_block.hasData())
{ {
PathName dummy; PathName dummy;
RefPtr<Config> config; RefPtr<const Config> config;
expandDatabaseName(svc_expected_db, dummy, &config); expandDatabaseName(svc_expected_db, dummy, &config);
string trusted_role; string trusted_role;
@ -1310,7 +1310,7 @@ ISC_STATUS Service::query2(thread_db* /*tdbb*/,
{ {
// The path to the user security database (security2.fdb) // The path to the user security database (security2.fdb)
char* pb = reinterpret_cast<char*>(buffer); char* pb = reinterpret_cast<char*>(buffer);
const RefPtr<Config> defConf(Config::getDefaultConfig()); const RefPtr<const Config> defConf(Config::getDefaultConfig());
strcpy(pb, defConf->getSecurityDatabase()); strcpy(pb, defConf->getSecurityDatabase());
if (!(info = INF_put_item(item, static_cast<USHORT>(strlen(pb)), buffer, info, end))) if (!(info = INF_put_item(item, static_cast<USHORT>(strlen(pb)), buffer, info, end)))
@ -1764,7 +1764,7 @@ void Service::query(USHORT send_item_length,
{ {
// The path to the user security database (security2.fdb) // The path to the user security database (security2.fdb)
char* pb = reinterpret_cast<char*>(buffer); char* pb = reinterpret_cast<char*>(buffer);
const RefPtr<Config> defConf(Config::getDefaultConfig()); const RefPtr<const Config> defConf(Config::getDefaultConfig());
strcpy(pb, defConf->getSecurityDatabase()); strcpy(pb, defConf->getSecurityDatabase());
if (!(info = INF_put_item(item, static_cast<USHORT>(strlen(pb)), buffer, info, end))) if (!(info = INF_put_item(item, static_cast<USHORT>(strlen(pb)), buffer, info, end)))

View File

@ -285,7 +285,7 @@ void TraceManager::update_session(const TraceSession& session)
if (session.ses_auth.hasData()) if (session.ses_auth.hasData())
{ {
PathName dummy; PathName dummy;
RefPtr<Config> config; RefPtr<const Config> config;
expandDatabaseName(service->getExpectedDb(), dummy, &config); expandDatabaseName(service->getExpectedDb(), dummy, &config);
if (mapUser(false, s_user, t_role, NULL, NULL, NULL, session.ses_auth, "services manager", if (mapUser(false, s_user, t_role, NULL, NULL, NULL, session.ses_auth, "services manager",

View File

@ -167,7 +167,7 @@ Firebird::GlobalPtr<LockManager::DbLockMgrMap> LockManager::g_lmMap;
Firebird::GlobalPtr<Firebird::Mutex> LockManager::g_mapMutex; Firebird::GlobalPtr<Firebird::Mutex> LockManager::g_mapMutex;
LockManager* LockManager::create(const Firebird::string& id, RefPtr<Config> conf) LockManager* LockManager::create(const Firebird::string& id, RefPtr<const Config> conf)
{ {
Firebird::MutexLockGuard guard(g_mapMutex, FB_FUNCTION); Firebird::MutexLockGuard guard(g_mapMutex, FB_FUNCTION);
@ -208,7 +208,7 @@ void LockManager::destroy(LockManager* lockMgr)
} }
LockManager::LockManager(const Firebird::string& id, RefPtr<Config> conf) LockManager::LockManager(const Firebird::string& id, RefPtr<const Config> conf)
: PID(getpid()), : PID(getpid()),
m_bugcheck(false), m_bugcheck(false),
m_sharedFileCreated(false), m_sharedFileCreated(false),

View File

@ -398,7 +398,7 @@ class LockManager : private Firebird::RefCounted,
const int PID; const int PID;
public: public:
static LockManager* create(const Firebird::string&, Firebird::RefPtr<Config>); static LockManager* create(const Firebird::string&, Firebird::RefPtr<const Config>);
static void destroy(LockManager*); static void destroy(LockManager*);
bool initializeOwner(Firebird::CheckStatusWrapper*, LOCK_OWNER_T, UCHAR, SRQ_PTR*); bool initializeOwner(Firebird::CheckStatusWrapper*, LOCK_OWNER_T, UCHAR, SRQ_PTR*);
@ -421,7 +421,7 @@ public:
void exceptionHandler(const Firebird::Exception& ex, ThreadFinishSync<LockManager*>::ThreadRoutine* routine); void exceptionHandler(const Firebird::Exception& ex, ThreadFinishSync<LockManager*>::ThreadRoutine* routine);
private: private:
explicit LockManager(const Firebird::string&, Firebird::RefPtr<Config>); explicit LockManager(const Firebird::string&, Firebird::RefPtr<const Config>);
~LockManager(); ~LockManager();
void acquire_shmem(SRQ_PTR); void acquire_shmem(SRQ_PTR);
@ -500,7 +500,7 @@ private:
bool m_blockage; bool m_blockage;
Firebird::string m_dbId; Firebird::string m_dbId;
Firebird::RefPtr<Config> m_config; Firebird::RefPtr<const Config> m_config;
// configurations parameters - cached values // configurations parameters - cached values
const ULONG m_acquireSpins; const ULONG m_acquireSpins;

View File

@ -693,7 +693,8 @@ static Rvnt* add_event(rem_port*);
static void add_other_params(rem_port*, ClumpletWriter&, const ParametersSet&); static void add_other_params(rem_port*, ClumpletWriter&, const ParametersSet&);
static void add_working_directory(ClumpletWriter&, const PathName&); static void add_working_directory(ClumpletWriter&, const PathName&);
static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned flags, static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned flags,
ClumpletWriter& pb, const ParametersSet& parSet, PathName& node_name, PathName* ref_db_name); ClumpletWriter& pb, const ParametersSet& parSet, PathName& node_name, PathName* ref_db_name,
Firebird::ICryptKeyCallback* cryptCb);
static void batch_gds_receive(rem_port*, struct rmtque *, USHORT); static void batch_gds_receive(rem_port*, struct rmtque *, USHORT);
static void batch_dsql_fetch(rem_port*, struct rmtque *, USHORT); static void batch_dsql_fetch(rem_port*, struct rmtque *, USHORT);
static void clear_queue(rem_port*); static void clear_queue(rem_port*);
@ -798,7 +799,7 @@ IAttachment* RProvider::attach(CheckStatusWrapper* status, const char* filename,
PathName node_name; PathName node_name;
ClntAuthBlock cBlock(&expanded_name, &newDpb, &dpbParam); ClntAuthBlock cBlock(&expanded_name, &newDpb, &dpbParam);
rem_port* port = analyze(cBlock, expanded_name, flags, newDpb, dpbParam, node_name, NULL); rem_port* port = analyze(cBlock, expanded_name, flags, newDpb, dpbParam, node_name, NULL, cryptCallback);
if (!port) if (!port)
{ {
@ -1420,7 +1421,7 @@ Firebird::IAttachment* RProvider::create(CheckStatusWrapper* status, const char*
PathName node_name; PathName node_name;
ClntAuthBlock cBlock(&expanded_name, &newDpb, &dpbParam); ClntAuthBlock cBlock(&expanded_name, &newDpb, &dpbParam);
rem_port* port = analyze(cBlock, expanded_name, flags, newDpb, dpbParam, node_name, NULL); rem_port* port = analyze(cBlock, expanded_name, flags, newDpb, dpbParam, node_name, NULL, cryptCallback);
if (!port) if (!port)
{ {
@ -4631,7 +4632,7 @@ Firebird::IService* RProvider::attachSvc(CheckStatusWrapper* status, const char*
if (newSpb.find(isc_spb_expected_db)) if (newSpb.find(isc_spb_expected_db))
newSpb.getPath(refDbName); newSpb.getPath(refDbName);
rem_port* port = analyze(cBlock, expanded_name, flags, newSpb, spbParam, node_name, &refDbName); rem_port* port = analyze(cBlock, expanded_name, flags, newSpb, spbParam, node_name, &refDbName, cryptCallback);
RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION); RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
Rdb* rdb = port->port_context; Rdb* rdb = port->port_context;
@ -5400,7 +5401,8 @@ static void secureAuthentication(ClntAuthBlock& cBlock, rem_port* port)
static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned flags, static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned flags,
ClumpletWriter& pb, const ParametersSet& parSet, PathName& node_name, PathName* ref_db_name) ClumpletWriter& pb, const ParametersSet& parSet, PathName& node_name, PathName* ref_db_name,
Firebird::ICryptKeyCallback* cryptCb)
{ {
/************************************** /**************************************
* *
@ -5464,7 +5466,7 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned
} }
port = INET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_UV, pb, port = INET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_UV, pb,
cBlock.getConfig(), ref_db_name, inet_af); cBlock.getConfig(), ref_db_name, cryptCb, inet_af);
} }
// We have a local connection string. If it's a file on a network share, // We have a local connection string. If it's a file on a network share,
@ -5498,7 +5500,7 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned
ISC_utf8ToSystem(node_name); ISC_utf8ToSystem(node_name);
port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_UV, pb, port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_UV, pb,
cBlock.getConfig(), ref_db_name); cBlock.getConfig(), ref_db_name, cryptCb);
} }
} }
#endif #endif
@ -5527,7 +5529,7 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned
if (!port) if (!port)
{ {
port = INET_analyze(&cBlock, attach_name, INET_LOCALHOST, flags & ANALYZE_UV, pb, port = INET_analyze(&cBlock, attach_name, INET_LOCALHOST, flags & ANALYZE_UV, pb,
cBlock.getConfig(), ref_db_name); cBlock.getConfig(), ref_db_name, cryptCb);
} }
} }
} }

View File

@ -457,7 +457,7 @@ static rem_port* inet_try_connect( PACKET*,
const PathName&, const PathName&,
const TEXT*, const TEXT*,
ClumpletReader&, ClumpletReader&,
RefPtr<Config>*, RefPtr<const Config>*,
const PathName*, const PathName*,
int); int);
static bool inet_write(XDR*); static bool inet_write(XDR*);
@ -538,8 +538,9 @@ rem_port* INET_analyze(ClntAuthBlock* cBlock,
const TEXT* node_name, const TEXT* node_name,
bool uv_flag, bool uv_flag,
ClumpletReader &dpb, ClumpletReader &dpb,
RefPtr<Config>* config, RefPtr<const Config>* config,
const PathName* ref_db_name, const PathName* ref_db_name,
Firebird::ICryptKeyCallback* cryptCb,
int af) int af)
{ {
/************************************** /**************************************
@ -619,7 +620,8 @@ rem_port* INET_analyze(ClntAuthBlock* cBlock,
REMOTE_PROTOCOL(PROTOCOL_VERSION11, ptype_lazy_send, 2), REMOTE_PROTOCOL(PROTOCOL_VERSION11, ptype_lazy_send, 2),
REMOTE_PROTOCOL(PROTOCOL_VERSION12, ptype_lazy_send, 3), REMOTE_PROTOCOL(PROTOCOL_VERSION12, ptype_lazy_send, 3),
REMOTE_PROTOCOL(PROTOCOL_VERSION13, ptype_lazy_send, 4), REMOTE_PROTOCOL(PROTOCOL_VERSION13, ptype_lazy_send, 4),
REMOTE_PROTOCOL(PROTOCOL_VERSION14, ptype_lazy_send, 5) REMOTE_PROTOCOL(PROTOCOL_VERSION14, ptype_lazy_send, 5),
REMOTE_PROTOCOL(PROTOCOL_VERSION15, ptype_lazy_send, 6)
}; };
fb_assert(FB_NELEM(protocols_to_try) <= FB_NELEM(cnct->p_cnct_versions)); fb_assert(FB_NELEM(protocols_to_try) <= FB_NELEM(cnct->p_cnct_versions));
cnct->p_cnct_count = FB_NELEM(protocols_to_try); cnct->p_cnct_count = FB_NELEM(protocols_to_try);
@ -634,51 +636,96 @@ rem_port* INET_analyze(ClntAuthBlock* cBlock,
} }
rem_port* port = inet_try_connect(packet, rdb, file_name, node_name, dpb, config, ref_db_name, af); rem_port* port = inet_try_connect(packet, rdb, file_name, node_name, dpb, config, ref_db_name, af);
P_ACPT* accept;
P_ACPT* accept = NULL; for(;;)
switch (packet->p_operation)
{ {
case op_accept_data: accept = NULL;
case op_cond_accept: switch (packet->p_operation)
accept = &packet->p_acpd;
if (cBlock)
{ {
cBlock->storeDataForPlugin(packet->p_acpd.p_acpt_data.cstr_length, case op_accept_data:
packet->p_acpd.p_acpt_data.cstr_address); case op_cond_accept:
cBlock->authComplete = packet->p_acpd.p_acpt_authenticated; accept = &packet->p_acpd;
port->addServerKeys(&packet->p_acpd.p_acpt_keys); if (cBlock)
cBlock->resetClnt(&file_name, &packet->p_acpd.p_acpt_keys); {
} cBlock->storeDataForPlugin(packet->p_acpd.p_acpt_data.cstr_length,
break; packet->p_acpd.p_acpt_data.cstr_address);
cBlock->authComplete = packet->p_acpd.p_acpt_authenticated;
port->addServerKeys(&packet->p_acpd.p_acpt_keys);
cBlock->resetClnt(&file_name, &packet->p_acpd.p_acpt_keys);
}
break;
case op_accept: case op_accept:
if (cBlock) if (cBlock)
{ {
cBlock->resetClnt(&file_name); cBlock->resetClnt(&file_name);
} }
accept = &packet->p_acpt; accept = &packet->p_acpt;
break; break;
case op_response: case op_crypt_key_callback:
try try
{ {
LocalStatus warning; // Ignore connect warnings for a while UCharBuffer buf;
CheckStatusWrapper statusWrapper(&warning); P_CRYPT_CALLBACK* cc = &packet->p_cc;
REMOTE_check_response(&statusWrapper, rdb, packet, false);
} if (cryptCb)
catch (const Exception&) {
{ if (cc->p_cc_reply <= 0)
{
cc->p_cc_reply = 1;
}
UCHAR* reply = buf.getBuffer(cc->p_cc_reply);
unsigned l = cryptCb->callback(cc->p_cc_data.cstr_length,
cc->p_cc_data.cstr_address, cc->p_cc_reply, reply);
REMOTE_free_packet(port, packet, true);
cc->p_cc_data.cstr_length = l;
cc->p_cc_data.cstr_address = reply;
}
else
{
REMOTE_free_packet(port, packet, true);
cc->p_cc_data.cstr_length = 0;
}
packet->p_operation = op_crypt_key_callback;
cc->p_cc_reply = 0;
port->send(packet);
port->receive(packet);
continue;
}
catch (const Exception&)
{
disconnect(port);
delete rdb;
throw;
}
case op_response:
try
{
LocalStatus warning; // Ignore connect warnings for a while
CheckStatusWrapper statusWrapper(&warning);
REMOTE_check_response(&statusWrapper, rdb, packet, false);
}
catch (const Exception&)
{
disconnect(port);
delete rdb;
throw;
}
// fall through - response is not a required accept
default:
disconnect(port); disconnect(port);
delete rdb; delete rdb;
throw; Arg::Gds(isc_connect_reject).raise();
break;
} }
// fall through - response is not a required accept
default: break; // Always leave for() loop here
disconnect(port);
delete rdb;
Arg::Gds(isc_connect_reject).raise();
break;
} }
fb_assert(accept); fb_assert(accept);
@ -720,7 +767,7 @@ rem_port* INET_connect(const TEXT* name,
PACKET* packet, PACKET* packet,
USHORT flag, USHORT flag,
ClumpletReader* dpb, ClumpletReader* dpb,
RefPtr<Config>* config, RefPtr<const Config>* config,
int af) int af)
{ {
/************************************** /**************************************
@ -2662,7 +2709,7 @@ static rem_port* inet_try_connect(PACKET* packet,
const PathName& file_name, const PathName& file_name,
const TEXT* node_name, const TEXT* node_name,
ClumpletReader& dpb, ClumpletReader& dpb,
RefPtr<Config>* config, RefPtr<const Config>* config,
const PathName* ref_db_name, const PathName* ref_db_name,
int af) int af)
{ {

View File

@ -34,10 +34,10 @@ namespace Firebird
} }
rem_port* INET_analyze(ClntAuthBlock*, const Firebird::PathName&, const TEXT*, rem_port* INET_analyze(ClntAuthBlock*, const Firebird::PathName&, const TEXT*,
bool, Firebird::ClumpletReader&, Firebird::RefPtr<Config>*, bool, Firebird::ClumpletReader&, Firebird::RefPtr<const Config>*,
const Firebird::PathName*, int af = AF_UNSPEC); const Firebird::PathName*, Firebird::ICryptKeyCallback*, int af = AF_UNSPEC);
rem_port* INET_connect(const TEXT*, struct packet*, USHORT, Firebird::ClumpletReader*, rem_port* INET_connect(const TEXT*, struct packet*, USHORT, Firebird::ClumpletReader*,
Firebird::RefPtr<Config>*, int af = AF_UNSPEC); Firebird::RefPtr<const Config>*, int af = AF_UNSPEC);
rem_port* INET_reconnect(SOCKET); rem_port* INET_reconnect(SOCKET);
rem_port* INET_server(SOCKET); rem_port* INET_server(SOCKET);
void setStopMainThread(FPTR_INT func); void setStopMainThread(FPTR_INT func);

View File

@ -72,7 +72,7 @@ static void disconnect(rem_port*);
static void exit_handler(void*); static void exit_handler(void*);
#endif #endif
static void force_close(rem_port*); static void force_close(rem_port*);
static rem_str* make_pipe_name(const RefPtr<Config>&, const TEXT*, const TEXT*, const TEXT*); static rem_str* make_pipe_name(const RefPtr<const Config>&, const TEXT*, const TEXT*, const TEXT*);
static rem_port* receive(rem_port*, PACKET*); static rem_port* receive(rem_port*, PACKET*);
static int send_full(rem_port*, PACKET*); static int send_full(rem_port*, PACKET*);
static int send_partial(rem_port*, PACKET*); static int send_partial(rem_port*, PACKET*);
@ -104,7 +104,7 @@ rem_port* WNET_analyze(ClntAuthBlock* cBlock,
const PathName& file_name, const PathName& file_name,
const TEXT* node_name, const TEXT* node_name,
bool uv_flag, bool uv_flag,
RefPtr<Config>* config, RefPtr<const Config>* config,
const Firebird::PathName* ref_db_name) const Firebird::PathName* ref_db_name)
{ {
/************************************** /**************************************
@ -269,7 +269,7 @@ rem_port* WNET_analyze(ClntAuthBlock* cBlock,
} }
rem_port* WNET_connect(const TEXT* name, PACKET* packet, USHORT flag, Firebird::RefPtr<Config>* config) rem_port* WNET_connect(const TEXT* name, PACKET* packet, USHORT flag, Firebird::RefPtr<const Config>* config)
{ {
/************************************** /**************************************
* *
@ -800,7 +800,7 @@ static void exit_handler(void* main_port)
#endif #endif
static rem_str* make_pipe_name(const RefPtr<Config>& config, const TEXT* connect_name, static rem_str* make_pipe_name(const RefPtr<const Config>& config, const TEXT* connect_name,
const TEXT* suffix_name, const TEXT* str_pid) const TEXT* suffix_name, const TEXT* str_pid)
{ {
/************************************** /**************************************

View File

@ -32,8 +32,8 @@ extern "C" {
rem_port* WNET_analyze(ClntAuthBlock*, const Firebird::PathName&, const TEXT*, bool, rem_port* WNET_analyze(ClntAuthBlock*, const Firebird::PathName&, const TEXT*, bool,
Firebird::RefPtr<Config>*, const Firebird::PathName*); Firebird::RefPtr<const Config>*, const Firebird::PathName*);
rem_port* WNET_connect(const TEXT*, struct packet*, USHORT, Firebird::RefPtr<Config>*); rem_port* WNET_connect(const TEXT*, struct packet*, USHORT, Firebird::RefPtr<const Config>*);
rem_port* WNET_reconnect(HANDLE); rem_port* WNET_reconnect(HANDLE);

View File

@ -148,7 +148,7 @@ namespace Remote
{ {
} }
rem_port* connect_client(PACKET*, const RefPtr<Config>*); rem_port* connect_client(PACKET*, const RefPtr<const Config>*);
void server_shutdown(rem_port* port); void server_shutdown(rem_port* port);
private: private:
@ -238,7 +238,7 @@ static void xnet_log_error(const char* err_msg)
rem_port* XNET_analyze(ClntAuthBlock* cBlock, rem_port* XNET_analyze(ClntAuthBlock* cBlock,
const PathName& file_name, const PathName& file_name,
bool uv_flag, bool uv_flag,
RefPtr<Config>* config, RefPtr<const Config>* config,
const Firebird::PathName* ref_db_name) const Firebird::PathName* ref_db_name)
{ {
/************************************** /**************************************
@ -403,7 +403,7 @@ rem_port* XNET_analyze(ClntAuthBlock* cBlock,
rem_port* XNET_connect(PACKET* packet, rem_port* XNET_connect(PACKET* packet,
USHORT flag, USHORT flag,
Firebird::RefPtr<Config>* config) Firebird::RefPtr<const Config>* config)
{ {
/************************************** /**************************************
* *
@ -1087,7 +1087,7 @@ static void raise_lostconn_or_syserror(const char* msg)
} }
rem_port* XnetClientEndPoint::connect_client(PACKET* packet, const RefPtr<Config>* config) rem_port* XnetClientEndPoint::connect_client(PACKET* packet, const RefPtr<const Config>* config)
{ {
/************************************** /**************************************
* *
@ -1100,7 +1100,7 @@ rem_port* XnetClientEndPoint::connect_client(PACKET* packet, const RefPtr<Config
* *
**************************************/ **************************************/
const Firebird::RefPtr<Config>& conf(config ? *config : Config::getDefaultConfig()); const Firebird::RefPtr<const Config>& conf(config ? *config : Config::getDefaultConfig());
if (!xnet_initialized) if (!xnet_initialized)
{ {

View File

@ -32,9 +32,9 @@
#define rem_port void #define rem_port void
#endif #endif
rem_port* XNET_analyze(ClntAuthBlock*, const Firebird::PathName&, bool, Firebird::RefPtr<Config>*, rem_port* XNET_analyze(ClntAuthBlock*, const Firebird::PathName&, bool, Firebird::RefPtr<const Config>*,
const Firebird::PathName*); const Firebird::PathName*);
rem_port* XNET_connect(struct packet*, USHORT, Firebird::RefPtr<Config>*); rem_port* XNET_connect(struct packet*, USHORT, Firebird::RefPtr<const Config>*);
rem_port* XNET_reconnect(ULONG); rem_port* XNET_reconnect(ULONG);
#endif // REMOTE_XNET_PROTO_H #endif // REMOTE_XNET_PROTO_H

View File

@ -803,7 +803,9 @@ bool_t xdr_protocol(XDR* xdrs, PACKET* p)
MAP(xdr_cstring, cc->p_cc_data); MAP(xdr_cstring, cc->p_cc_data);
rem_port* port = (rem_port*) xdrs->x_public; rem_port* port = (rem_port*) xdrs->x_public;
if (port->port_protocol >= PROTOCOL_VERSION14) // If the protocol is 0 we are in the process of establishing a connection.
// crypt_key_callback at this phaze means server protocol is at least P15
if (port->port_protocol >= PROTOCOL_VERSION14 || port->port_protocol == 0)
MAP(xdr_short, reinterpret_cast<SSHORT&>(cc->p_cc_reply)); MAP(xdr_short, reinterpret_cast<SSHORT&>(cc->p_cc_reply));
DEBUG_PRINTSIZE(xdrs, p->p_operation); DEBUG_PRINTSIZE(xdrs, p->p_operation);

View File

@ -82,6 +82,11 @@ const USHORT PROTOCOL_VERSION13 = (FB_PROTOCOL_FLAG | 13);
const USHORT PROTOCOL_VERSION14 = (FB_PROTOCOL_FLAG | 14); const USHORT PROTOCOL_VERSION14 = (FB_PROTOCOL_FLAG | 14);
// Protocol 15:
// - supports crypt key callback at connect phaze
const USHORT PROTOCOL_VERSION15 = (FB_PROTOCOL_FLAG | 15);
// Architecture types // Architecture types
enum P_ARCH enum P_ARCH

View File

@ -61,7 +61,7 @@ void REMOTE_reset_request (struct Rrq *, struct RMessage*);
void REMOTE_reset_statement (struct Rsr *); void REMOTE_reset_statement (struct Rsr *);
bool_t REMOTE_getbytes (XDR*, SCHAR*, u_int); bool_t REMOTE_getbytes (XDR*, SCHAR*, u_int);
LegacyPlugin REMOTE_legacy_auth(const char* nm, int protocol); LegacyPlugin REMOTE_legacy_auth(const char* nm, int protocol);
Firebird::RefPtr<Config> REMOTE_get_config(const Firebird::PathName* dbName, Firebird::RefPtr<const Config> REMOTE_get_config(const Firebird::PathName* dbName,
const Firebird::string* dpb_config = NULL); const Firebird::string* dpb_config = NULL);
void REMOTE_check_response(Firebird::IStatus* warning, Rdb* rdb, PACKET* packet, bool checkKeys = false); void REMOTE_check_response(Firebird::IStatus* warning, Rdb* rdb, PACKET* packet, bool checkKeys = false);
bool REMOTE_inflate(rem_port*, PacketReceive*, UCHAR*, SSHORT, SSHORT*); bool REMOTE_inflate(rem_port*, PacketReceive*, UCHAR*, SSHORT, SSHORT*);

View File

@ -604,7 +604,12 @@ void rem_port::linkParent(rem_port* const parent)
parent->port_clients = parent->port_next = this; parent->port_clients = parent->port_next = this;
} }
const Firebird::RefPtr<Config>& rem_port::getPortConfig() const const Firebird::RefPtr<const Config>& rem_port::getPortConfig() const
{
return port_config.hasData() ? port_config : Config::getDefaultConfig();
}
Firebird::RefPtr<const Config> rem_port::getPortConfig()
{ {
return port_config.hasData() ? port_config : Config::getDefaultConfig(); return port_config.hasData() ? port_config : Config::getDefaultConfig();
} }
@ -1006,7 +1011,7 @@ void ClntAuthBlock::resetClnt(const Firebird::PathName* fileName, const CSTRING*
plugins.set(final.c_str()); plugins.set(final.c_str());
} }
Firebird::RefPtr<Config>* ClntAuthBlock::getConfig() Firebird::RefPtr<const Config>* ClntAuthBlock::getConfig()
{ {
return clntConfig.hasData() ? &clntConfig : NULL; return clntConfig.hasData() ? &clntConfig : NULL;
} }
@ -1017,10 +1022,10 @@ void ClntAuthBlock::storeDataForPlugin(unsigned int length, const unsigned char*
HANDSHAKE_DEBUG(fprintf(stderr, "Cli: accepted data for plugin length=%d\n", length)); HANDSHAKE_DEBUG(fprintf(stderr, "Cli: accepted data for plugin length=%d\n", length));
} }
Firebird::RefPtr<Config> REMOTE_get_config(const Firebird::PathName* dbName, Firebird::RefPtr<const Config> REMOTE_get_config(const Firebird::PathName* dbName,
const Firebird::string* dpb_config) const Firebird::string* dpb_config)
{ {
Firebird::RefPtr<Config> config; Firebird::RefPtr<const Config> config;
if (dbName && dbName->hasData()) if (dbName && dbName->hasData())
{ {

View File

@ -703,7 +703,7 @@ private:
Firebird::UCharBuffer dataForPlugin, dataFromPlugin; Firebird::UCharBuffer dataForPlugin, dataFromPlugin;
Firebird::HalfStaticArray<InternalCryptKey*, 1> cryptKeys; // Wire crypt keys that came from plugin(s) last time Firebird::HalfStaticArray<InternalCryptKey*, 1> cryptKeys; // Wire crypt keys that came from plugin(s) last time
Firebird::string dpbConfig; // Used to recreate config with new filename Firebird::string dpbConfig; // Used to recreate config with new filename
Firebird::RefPtr<Config> clntConfig; // Used to get plugins list and pass to port Firebird::RefPtr<const Config> clntConfig; // Used to get plugins list and pass to port
unsigned nextKey; // First key to be analyzed unsigned nextKey; // First key to be analyzed
bool hasCryptKey; // DPB contains disk crypt key, may be passed only over encrypted wire bool hasCryptKey; // DPB contains disk crypt key, may be passed only over encrypted wire
@ -733,7 +733,7 @@ public:
Firebird::PathName getPluginName(); Firebird::PathName getPluginName();
void tryNewKeys(rem_port*); void tryNewKeys(rem_port*);
void releaseKeys(unsigned from); void releaseKeys(unsigned from);
Firebird::RefPtr<Config>* getConfig(); Firebird::RefPtr<const Config>* getConfig();
// Firebird::IClientBlock implementation // Firebird::IClientBlock implementation
int release(); int release();
@ -947,7 +947,7 @@ struct rem_port : public Firebird::GlobalStorage, public Firebird::RefCounted
OBJCT port_last_object_id; // cached last id OBJCT port_last_object_id; // cached last id
Firebird::ObjectsArray< Firebird::Array<char> > port_queue; Firebird::ObjectsArray< Firebird::Array<char> > port_queue;
FB_SIZE_T port_qoffset; // current packet in the queue FB_SIZE_T port_qoffset; // current packet in the queue
Firebird::RefPtr<Config> port_config; // connection-specific configuration info Firebird::RefPtr<const Config> port_config; // connection-specific configuration info
// Authentication and crypt stuff // Authentication and crypt stuff
ServerAuthBase* port_srv_auth; ServerAuthBase* port_srv_auth;
@ -1023,7 +1023,8 @@ public:
static bool checkCompression(); static bool checkCompression();
void linkParent(rem_port* const parent); void linkParent(rem_port* const parent);
void unlinkParent(); void unlinkParent();
const Firebird::RefPtr<Config>& getPortConfig() const; Firebird::RefPtr<const Config> getPortConfig();
const Firebird::RefPtr<const Config>& getPortConfig() const;
void versionInfo(Firebird::string& version) const; void versionInfo(Firebird::string& version) const;
bool extractNewKeys(CSTRING* to, bool flagPlugList = false) bool extractNewKeys(CSTRING* to, bool flagPlugList = false)

View File

@ -399,7 +399,7 @@ int CLIB_ROUTINE main( int argc, char** argv)
ISC_STATUS_ARRAY status; ISC_STATUS_ARRAY status;
isc_db_handle db_handle = 0L; isc_db_handle db_handle = 0L;
const Firebird::RefPtr<Config> defConf(Config::getDefaultConfig()); const Firebird::RefPtr<const Config> defConf(Config::getDefaultConfig());
const char* path = defConf->getSecurityDatabase(); const char* path = defConf->getSecurityDatabase();
const char dpb[] = {isc_dpb_version1, isc_dpb_sec_attach, 1, 1, isc_dpb_address_path, 0}; const char dpb[] = {isc_dpb_version1, isc_dpb_sec_attach, 1, 1, isc_dpb_address_path, 0};

View File

@ -105,7 +105,175 @@ public:
namespace { namespace {
// DB crypt key passthrough
class NetworkCallback : public VersionedIface<ICryptKeyCallbackImpl<NetworkCallback, CheckStatusWrapper> >
{
public:
explicit NetworkCallback(rem_port* prt)
: port(prt), l(0), d(NULL), stopped(false), wake(false)
{ }
unsigned int callback(unsigned int dataLength, const void* data,
unsigned int bufferLength, void* buffer)
{
if (stopped)
return 0;
if (port->port_protocol < PROTOCOL_VERSION13)
return 0;
Reference r(*port);
d = buffer;
l = bufferLength;
PACKET p;
p.p_operation = op_crypt_key_callback;
p.p_cc.p_cc_data.cstr_length = dataLength;
p.p_cc.p_cc_data.cstr_address = (UCHAR*) data;
p.p_cc.p_cc_reply = bufferLength;
port->send(&p);
if (!sem.tryEnter(60))
return 0;
return l;
}
void wakeup(unsigned int length, const void* data)
{
if (l > length)
l = length;
memcpy(d, data, l);
wake = true;
sem.release();
}
void stop()
{
stopped = true;
}
bool isStopped() const
{
return stopped;
}
private:
rem_port* port;
Semaphore sem;
unsigned int l;
void* d;
bool stopped;
public:
bool wake;
};
class CryptKeyCallback : public VersionedIface<ICryptKeyCallbackImpl<CryptKeyCallback, CheckStatusWrapper> >
{
public:
explicit CryptKeyCallback(rem_port* prt)
: port(prt), networkCallback(prt), keyHolder(NULL), keyCallback(NULL)
{ }
~CryptKeyCallback()
{
if (keyHolder)
PluginManagerInterfacePtr()->releasePlugin(keyHolder);
}
unsigned int callback(unsigned int dataLength, const void* data,
unsigned int bufferLength, void* buffer)
{
if (keyCallback)
return keyCallback->callback(dataLength, data, bufferLength, buffer);
if (networkCallback.isStopped())
return 0;
Reference r(*port);
for (GetPlugins<IKeyHolderPlugin> kh(IPluginManager::TYPE_KEY_HOLDER, port->getPortConfig());
kh.hasData(); kh.next())
{
IKeyHolderPlugin* keyPlugin = kh.plugin();
LocalStatus ls;
CheckStatusWrapper st(&ls);
networkCallback.wake = false;
if (keyPlugin->keyCallback(&st, &networkCallback) && networkCallback.wake)
{
// current holder has a key and it seems to be from the client
keyHolder = keyPlugin;
keyHolder->addRef();
keyCallback = keyHolder->chainHandle(&st);
if (st.isEmpty() && keyCallback)
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)
{
networkCallback.wakeup(length, data);
}
void stop()
{
networkCallback.stop();
}
private:
rem_port* port;
NetworkCallback networkCallback;
IKeyHolderPlugin* keyHolder;
ICryptKeyCallback* keyCallback;
};
class ServerCallback : public ServerCallbackBase, public GlobalStorage
{
public:
explicit ServerCallback(rem_port* prt)
: cryptCallback(prt)
{ }
~ServerCallback()
{ }
void wakeup(unsigned int length, const void* data)
{
cryptCallback.wakeup(length, data);
}
ICryptKeyCallback* getInterface()
{
return &cryptCallback;
}
void stop()
{
cryptCallback.stop();
}
private:
CryptKeyCallback cryptCallback;
};
// Disable attempts to brute-force logins/passwords // Disable attempts to brute-force logins/passwords
class FailedLogin class FailedLogin
{ {
public: public:
@ -287,6 +455,7 @@ static void getMultiPartConnectParameter(T& putTo, Firebird::ClumpletReader& id,
// delayed authentication block for auth callback // delayed authentication block for auth callback
class ServerAuth : public GlobalStorage, public ServerAuthBase class ServerAuth : public GlobalStorage, public ServerAuthBase
{ {
public: public:
@ -379,6 +548,11 @@ public:
authPort->port_srv_auth_block->setDataForPlugin(u); authPort->port_srv_auth_block->setDataForPlugin(u);
} }
#endif #endif
if (!authPort->port_server_crypt_callback)
{
authPort->port_server_crypt_callback = FB_NEW ServerCallback(authPort);
}
} }
~ServerAuth() ~ServerAuth()
@ -425,6 +599,13 @@ public:
{ {
authServer = authItr->plugin(); authServer = authItr->plugin();
authPort->port_srv_auth_block->authBlockWriter.setPlugin(authItr->name()); authPort->port_srv_auth_block->authBlockWriter.setPlugin(authItr->name());
if (authPort->getPortConfig()->getCryptSecurityDatabase() &&
authPort->port_protocol >= PROTOCOL_VERSION15 &&
authPort->port_server_crypt_callback)
{
authServer->setDbCryptCallback(&st, authPort->port_server_crypt_callback->getInterface());
}
} }
// if we asked for more data but received nothing switch to next plugin // if we asked for more data but received nothing switch to next plugin
@ -774,6 +955,9 @@ private:
Rvnt* event; Rvnt* event;
}; };
// Stores types of known wire crypt keys
class CryptKeyTypeManager : public PermanentStorage class CryptKeyTypeManager : public PermanentStorage
{ {
class CryptKeyType : public PermanentStorage class CryptKeyType : public PermanentStorage
@ -868,91 +1052,6 @@ private:
InitInstance<CryptKeyTypeManager> knownCryptKeyTypes; InitInstance<CryptKeyTypeManager> knownCryptKeyTypes;
class CryptKeyCallback : public VersionedIface<ICryptKeyCallbackImpl<CryptKeyCallback, CheckStatusWrapper> >
{
public:
explicit CryptKeyCallback(rem_port* prt)
: port(prt), l(0), d(NULL), stopped(false)
{ }
unsigned int callback(unsigned int dataLength, const void* data,
unsigned int bufferLength, void* buffer)
{
if (stopped)
return 0;
Reference r(*port);
PACKET p;
p.p_operation = op_crypt_key_callback;
p.p_cc.p_cc_data.cstr_length = dataLength;
p.p_cc.p_cc_data.cstr_address = (UCHAR*) data;
p.p_cc.p_cc_reply = bufferLength;
port->send(&p);
if (!sem.tryEnter(10))
return 0;
if (bufferLength > l)
bufferLength = l;
memcpy(buffer, d, bufferLength);
if (l)
sem2.release();
return l;
}
void wakeup(unsigned int length, const void* data)
{
l = length;
d = data;
sem.release();
if (l)
sem2.enter();
}
void stop()
{
stopped = true;
}
private:
rem_port* port;
Semaphore sem, sem2;
unsigned int l;
const void* d;
bool stopped;
};
class ServerCallback : public ServerCallbackBase, public GlobalStorage
{
public:
explicit ServerCallback(rem_port* prt)
: cryptCallback(prt)
{ }
~ServerCallback()
{ }
void wakeup(unsigned int length, const void* data)
{
cryptCallback.wakeup(length, data);
}
ICryptKeyCallback* getInterface()
{
return &cryptCallback;
}
void stop()
{
cryptCallback.stop();
}
private:
CryptKeyCallback cryptCallback;
};
} // anonymous } // anonymous
static void free_request(server_req_t*); static void free_request(server_req_t*);
@ -1715,11 +1814,8 @@ static bool accept_connection(rem_port* port, P_CNCT* connect, PACKET* send)
for (const p_cnct::p_cnct_repeat* const end = protocol + connect->p_cnct_count; for (const p_cnct::p_cnct_repeat* const end = protocol + connect->p_cnct_count;
protocol < end; protocol++) protocol < end; protocol++)
{ {
if ((protocol->p_cnct_version == PROTOCOL_VERSION10 || if ((protocol->p_cnct_version >= PROTOCOL_VERSION10 &&
protocol->p_cnct_version == PROTOCOL_VERSION11 || protocol->p_cnct_version <= PROTOCOL_VERSION15) &&
protocol->p_cnct_version == PROTOCOL_VERSION12 ||
protocol->p_cnct_version == PROTOCOL_VERSION13 ||
protocol->p_cnct_version == PROTOCOL_VERSION14) &&
(protocol->p_cnct_architecture == arch_generic || (protocol->p_cnct_architecture == arch_generic ||
protocol->p_cnct_architecture == ARCHITECTURE) && protocol->p_cnct_architecture == ARCHITECTURE) &&
protocol->p_cnct_weight >= weight) protocol->p_cnct_weight >= weight)
@ -2239,13 +2335,10 @@ void DatabaseAuth::accept(PACKET* send, Auth::WriterImplementation* authBlock)
const UCHAR* dpb = pb->getBuffer(); const UCHAR* dpb = pb->getBuffer();
unsigned int dl = (ULONG) pb->getBufferLength(); unsigned int dl = (ULONG) pb->getBufferLength();
if (!authPort->port_server_crypt_callback)
{
authPort->port_server_crypt_callback = FB_NEW ServerCallback(authPort);
}
LocalStatus ls; LocalStatus ls;
CheckStatusWrapper status_vector(&ls); CheckStatusWrapper status_vector(&ls);
fb_assert(authPort->port_server_crypt_callback);
provider->setDbCryptCallback(&status_vector, authPort->port_server_crypt_callback->getInterface()); provider->setDbCryptCallback(&status_vector, authPort->port_server_crypt_callback->getInterface());
if (!(status_vector.getState() & Firebird::IStatus::STATE_ERRORS)) if (!(status_vector.getState() & Firebird::IStatus::STATE_ERRORS))
@ -5378,16 +5471,13 @@ ISC_STATUS rem_port::service_attach(const char* service_name,
// they will be stuffed in the SPB if so. // they will be stuffed in the SPB if so.
REMOTE_get_timeout_params(this, spb); REMOTE_get_timeout_params(this, spb);
if (!port_server_crypt_callback)
{
port_server_crypt_callback = FB_NEW ServerCallback(this);
}
DispatcherPtr provider; DispatcherPtr provider;
LocalStatus ls; LocalStatus ls;
CheckStatusWrapper status_vector(&ls); CheckStatusWrapper status_vector(&ls);
fb_assert(port_server_crypt_callback);
provider->setDbCryptCallback(&status_vector, port_server_crypt_callback->getInterface()); provider->setDbCryptCallback(&status_vector, port_server_crypt_callback->getInterface());
if (!(status_vector.getState() & Firebird::IStatus::STATE_ERRORS)) if (!(status_vector.getState() & Firebird::IStatus::STATE_ERRORS))
{ {
dumpAuthBlock("rem_port::service_attach()", spb, isc_spb_auth_block); dumpAuthBlock("rem_port::service_attach()", spb, isc_spb_auth_block);
@ -6500,7 +6590,7 @@ void SrvAuthBlock::createPluginsItr()
REMOTE_makeList(pluginList, final); REMOTE_makeList(pluginList, final);
RefPtr<Config> portConf(port->getPortConfig()); RefPtr<const Config> portConf(port->getPortConfig());
plugins = FB_NEW AuthServerPlugins(IPluginManager::TYPE_AUTH_SERVER, portConf, pluginList.c_str()); plugins = FB_NEW AuthServerPlugins(IPluginManager::TYPE_AUTH_SERVER, portConf, pluginList.c_str());
} }

View File

@ -379,7 +379,7 @@ int gsec(Firebird::UtilSvc* uSvc)
} }
else else
{ {
const Firebird::RefPtr<Config> defConf(Config::getDefaultConfig()); const Firebird::RefPtr<const Config> defConf(Config::getDefaultConfig());
databaseName = defConf->getSecurityDatabase(); databaseName = defConf->getSecurityDatabase();
} }
@ -460,8 +460,8 @@ int gsec(Firebird::UtilSvc* uSvc)
Firebird::string databaseText; Firebird::string databaseText;
databaseText.printf("SecurityDatabase = %s\n", databaseName.c_str()); databaseText.printf("SecurityDatabase = %s\n", databaseName.c_str());
ConfigFile gsecDatabase(ConfigFile::USE_TEXT, databaseText.c_str()); ConfigFile gsecDatabase(ConfigFile::USE_TEXT, databaseText.c_str());
Firebird::RefPtr<Config> defaultConfig(Config::getDefaultConfig()); Firebird::RefPtr<const Config> defaultConfig(Config::getDefaultConfig());
Firebird::RefPtr<Config> pseudoConfig(FB_NEW Config(gsecDatabase, *defaultConfig)); Firebird::RefPtr<const Config> pseudoConfig(FB_NEW Config(gsecDatabase, *defaultConfig));
uSvc->checkService(); uSvc->checkService();

View File

@ -563,7 +563,7 @@ namespace
{ {
if (!firebirdConf.hasData()) if (!firebirdConf.hasData())
{ {
RefPtr<Config> specificConf(Config::getDefaultConfig()); RefPtr<const Config> specificConf(Config::getDefaultConfig());
firebirdConf = FB_NEW FirebirdConf(specificConf); firebirdConf = FB_NEW FirebirdConf(specificConf);
} }
@ -1257,7 +1257,7 @@ public:
try try
{ {
PathName dummy; PathName dummy;
Firebird::RefPtr<Config> config; Firebird::RefPtr<const Config> config;
expandDatabaseName(dbName, dummy, &config); expandDatabaseName(dbName, dummy, &config);
IFirebirdConf* firebirdConf = FB_NEW FirebirdConf(config); IFirebirdConf* firebirdConf = FB_NEW FirebirdConf(config);

View File

@ -5663,7 +5663,7 @@ YAttachment* Dispatcher::attachOrCreateDatabase(Firebird::CheckStatusWrapper* st
orgFilename.rtrim(); orgFilename.rtrim();
PathName expandedFilename; PathName expandedFilename;
RefPtr<Config> config; RefPtr<const Config> config;
if (expandDatabaseName(orgFilename, expandedFilename, &config)) if (expandDatabaseName(orgFilename, expandedFilename, &config))
{ {
expandedFilename = orgFilename; expandedFilename = orgFilename;
@ -5790,7 +5790,7 @@ YService* Dispatcher::attachServiceManager(CheckStatusWrapper* status, const cha
} }
// Build correct config // Build correct config
RefPtr<Config> config(Config::getDefaultConfig()); RefPtr<const Config> config(Config::getDefaultConfig());
if (spbWriter.find(isc_spb_config)) if (spbWriter.find(isc_spb_config))
{ {
string spb_config; string spb_config;