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 =
# ----------------------------
#
# 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 <firebird/Message.h>
using namespace Firebird;
@ -79,7 +80,7 @@ public:
status->dispose();
}
enum Action {NONE, ENC, DEC};
enum Action {NONE, ENC, DEC, EX_LCL, EX_RMT};
void execute(const char* dbName, const Action a)
{
@ -104,18 +105,55 @@ public:
throw "startTransaction";
}
if (a == ENC)
switch(a)
{
case ENC:
att->execute(status, tra, 0,
"ALTER DATABASE ENCRYPT WITH \"DbCrypt_example\"", 3, NULL, NULL, NULL, NULL);
if (status->getState() & IStatus::STATE_ERRORS)
throw "execute";
}
if (a == DEC)
{
break;
case DEC:
att->execute(status, tra, 0, "ALTER DATABASE DECRYPT", 3, NULL, NULL, NULL, NULL);
if (status->getState() & IStatus::STATE_ERRORS)
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)
@ -126,7 +164,7 @@ public:
tra = NULL;
}
printf("Providing key for crypt plugin - press enter to continue ...");
printf("\nProviding key for crypt plugin - press enter to continue ...");
getchar();
att->detach(status);
@ -151,13 +189,14 @@ private:
IProvider* p;
IAttachment* att;
ITransaction* tra;
IResultSet* curs;
CryptKey key;
};
int usage()
{
fprintf(stderr, "Usage: CryptApplication [ -e | -d ] { db-name }\n");
fprintf(stderr, "Usage: cryptAppSample [ -e | -d | -l | -r ] { db-name }\n");
return 2;
}
@ -181,6 +220,12 @@ int main(int ac, char** av)
case 'd':
act = App::DEC;
break;
case 'l':
act = App::EX_LCL;
break;
case 'r':
act = App::EX_RMT;
break;
default:
return usage();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -33,12 +33,12 @@ namespace Firebird
class RefCounted
{
public:
virtual int addRef()
virtual int addRef() const
{
return ++m_refCnt;
}
virtual int release()
virtual int release() const
{
fb_assert(m_refCnt.value() > 0);
const int refCnt = --m_refCnt;
@ -56,7 +56,7 @@ namespace Firebird
}
private:
AtomicCounter m_refCnt;
mutable AtomicCounter m_refCnt;
};
// 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;
}
*/
const Firebird::RefPtr<Config>& getDefaultConfig() const
Firebird::RefPtr<const Config>& getDefaultConfig()
{
return defaultConfig;
}
@ -92,7 +94,7 @@ public:
}
private:
Firebird::RefPtr<Config> defaultConfig;
Firebird::RefPtr<const Config> defaultConfig;
ConfigImpl(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, "WireCompression", (ConfigValue) false},
{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;
}
void Config::notify()
void Config::notify() const
{
if (!notifyDatabase.hasData())
return;
@ -264,7 +267,7 @@ void Config::notify()
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())
{
@ -338,7 +341,7 @@ Config::~Config()
* Public interface
*/
const Firebird::RefPtr<Config>& Config::getDefaultConfig()
const Firebird::RefPtr<const Config>& Config::getDefaultConfig()
{
return firebirdConf().getDefaultConfig();
}
@ -810,3 +813,8 @@ int Config::getMaxIdentifierCharLength() const
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_MAX_IDENTIFIER_BYTE_LENGTH,
KEY_MAX_IDENTIFIER_CHAR_LENGTH,
KEY_ENCRYPT_SECURITY_DATABASE,
MAX_CONFIG_KEY // keep it last
};
@ -174,7 +175,7 @@ private:
static const ConfigEntry entries[MAX_CONFIG_KEY];
ConfigValue values[MAX_CONFIG_KEY];
Firebird::PathName notifyDatabase;
mutable Firebird::PathName notifyDatabase;
public:
explicit Config(const ConfigFile& file); // use to build default config
@ -184,7 +185,7 @@ public:
// Call it when database with given config is created
void notify();
void notify() const;
// Check for missing firebird.conf
@ -199,10 +200,10 @@ public:
static const Firebird::PathName* getCommandLineRootDirectory();
// 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
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
static unsigned int getKeyByName(ConfigName name);
@ -349,6 +350,8 @@ public:
int getMaxIdentifierByteLength() const;
int getMaxIdentifierCharLength() const;
bool getCryptSecurityDatabase() const;
};
// 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:
FirebirdConf(Config* existingConfig)
FirebirdConf(const Config* existingConfig)
: config(existingConfig)
{ }
@ -369,7 +372,7 @@ public:
int release();
private:
Firebird::RefPtr<Config> config;
Firebird::RefPtr<const Config> config;
};
// Create default instance of IFirebirdConf interface

View File

@ -227,7 +227,7 @@ namespace
}
PathName name;
RefPtr<Config> config;
RefPtr<const Config> config;
#ifdef HAVE_ID_BY_NAME
Id* id;
#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.
// 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;
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
bool expandDatabaseName(Firebird::PathName alias,
Firebird::PathName& file,
Firebird::RefPtr<Config>* config)
Firebird::RefPtr<const Config>* config)
{
try
{

View File

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

View File

@ -41,7 +41,7 @@ void raise()
namespace Auth {
Get::Get(Config* firebirdConf)
Get::Get(const Config* firebirdConf)
: GetPlugins<Firebird::IManagement>(IPluginManager::TYPE_AUTH_USER_MANAGEMENT, firebirdConf)
{
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)
{
if (!hasData())

View File

@ -259,8 +259,8 @@ public:
class Get : public Firebird::GetPlugins<Firebird::IManagement>
{
public:
explicit Get(Config* firebirdConf);
Get(Config* firebirdConf, const char* plugName);
explicit Get(const Config* firebirdConf);
Get(const Config* firebirdConf, const char* plugName);
};
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 *,
USHORT);
typedef ISC_STATUS API_ROUTINE prototype_fb_database_crypt_callback(ISC_STATUS *,
void *);
struct FirebirdApiPointers
{
prototype_isc_attach_database *isc_attach_database;
@ -519,6 +522,7 @@ struct FirebirdApiPointers
prototype_isc_service_query *isc_service_query;
prototype_isc_service_start *isc_service_start;
prototype_fb_cancel_operation *fb_cancel_operation;
prototype_fb_database_crypt_callback *fb_database_crypt_callback;
};
#endif

View File

@ -599,6 +599,8 @@ interface Server : Auth
{
[notImplemented(Auth::AUTH_FAILED)]
int authenticate(Status status, ServerBlock sBlock, Writer writerInterface);
version: // 3.0.1 => 4.0
void setDbCryptCallback(Status status, CryptKeyCallback cryptCallback);
}
// .. 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.
// Use of keys, got by database crypt plugin from other attachments, is prohibited.
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
{
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:
@ -2415,7 +2416,7 @@ namespace Firebird
}
public:
static const unsigned VERSION = 5;
static const unsigned VERSION = 6;
template <typename StatusType> int authenticate(StatusType* status, IServerBlock* sBlock, IWriter* writerInterface)
{
@ -2424,6 +2425,19 @@ namespace Firebird
StatusType::checkException(status);
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
@ -2906,6 +2920,7 @@ namespace Firebird
int (CLOOP_CARG *keyCallback)(IKeyHolderPlugin* self, IStatus* status, ICryptKeyCallback* callback) throw();
ICryptKeyCallback* (CLOOP_CARG *keyHandle)(IKeyHolderPlugin* self, IStatus* status, const char* keyName) throw();
FB_BOOLEAN (CLOOP_CARG *useOnlyOwnKeys)(IKeyHolderPlugin* self, IStatus* status) throw();
ICryptKeyCallback* (CLOOP_CARG *chainHandle)(IKeyHolderPlugin* self, IStatus* status) throw();
};
protected:
@ -2950,6 +2965,20 @@ namespace Firebird
StatusType::checkException(status);
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
@ -10013,6 +10042,7 @@ namespace Firebird
this->setOwner = &Name::cloopsetOwnerDispatcher;
this->getOwner = &Name::cloopgetOwnerDispatcher;
this->authenticate = &Name::cloopauthenticateDispatcher;
this->setDbCryptCallback = &Name::cloopsetDbCryptCallbackDispatcher;
}
} 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()
{
try
@ -10099,6 +10143,7 @@ namespace Firebird
}
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>
@ -11246,6 +11291,7 @@ namespace Firebird
this->keyCallback = &Name::cloopkeyCallbackDispatcher;
this->keyHandle = &Name::cloopkeyHandleDispatcher;
this->useOnlyOwnKeys = &Name::cloopuseOnlyOwnKeysDispatcher;
this->chainHandle = &Name::cloopchainHandleDispatcher;
}
} 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()
{
try
@ -11364,6 +11425,7 @@ namespace Firebird
virtual int keyCallback(StatusType* status, ICryptKeyCallback* callback) = 0;
virtual ICryptKeyCallback* keyHandle(StatusType* status, const char* keyName) = 0;
virtual FB_BOOLEAN useOnlyOwnKeys(StatusType* status) = 0;
virtual ICryptKeyCallback* chainHandle(StatusType* status) = 0;
};
template <typename Name, typename StatusType, typename Base>

View File

@ -47,7 +47,7 @@
#include "../jrd/Monitoring.h"
#include "../jrd/os/pio_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/ClumpletWriter.h"
#include "../common/sha.h"
@ -69,6 +69,19 @@ namespace {
const UCHAR CRYPT_INIT = LCK_EX;
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)),
cryptThreadId(0),
cryptPlugin(NULL),
checkPlugin(NULL),
checkFactory(NULL),
dbb(*tdbb->getDatabase()),
cryptAtt(NULL),
slowIO(0),
@ -291,6 +304,7 @@ namespace Jrd {
delete stateLock;
delete threadLock;
delete checkFactory;
dbInfo->destroy();
}
@ -363,7 +377,7 @@ namespace Jrd {
else
keyName = "";
loadPlugin(hdr->hdr_crypt_plugin);
loadPlugin(tdbb, hdr->hdr_crypt_plugin);
string valid;
calcValidation(valid, cryptPlugin);
@ -378,10 +392,10 @@ namespace Jrd {
}
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)
{
@ -394,14 +408,14 @@ namespace Jrd {
return;
}
GetPlugins<IDbCryptPlugin> cryptControl(IPluginManager::TYPE_DB_CRYPT, dbb.dbb_config, pluginName);
if (!cryptControl.hasData())
AutoPtr<Factory> cryptControl(FB_NEW Factory(IPluginManager::TYPE_DB_CRYPT, dbb.dbb_config, pluginName));
if (!cryptControl->hasData())
{
(Arg::Gds(isc_no_crypt_plugin) << pluginName).raise();
}
// do not assign cryptPlugin directly before key init complete
IDbCryptPlugin* p = cryptControl.plugin();
IDbCryptPlugin* p = cryptControl->plugin();
FbLocalStatus status;
p->setInfo(&status, dbInfo);
@ -416,17 +430,15 @@ namespace Jrd {
cryptPlugin = p;
cryptPlugin->addRef();
// May be load second instance to validate keys
if (checkPlugin)
{
PluginManagerInterfacePtr()->releasePlugin(checkPlugin);
checkPlugin = NULL;
}
// remove old factory if present
delete checkFactory;
checkFactory = NULL;
// store new one
if (dbb.dbb_config->getServerMode() == MODE_SUPER)
{
checkPlugin = cryptControl.makeInstance();
keyHolderPlugins.validate(checkPlugin, NULL, keyName);
checkFactory = cryptControl.release();
keyHolderPlugins.validateNewAttachment(tdbb->getAttachment(), keyName);
}
}
@ -483,7 +495,7 @@ namespace Jrd {
}
keyName = key;
loadPlugin(plugName.c_str());
loadPlugin(tdbb, plugName.c_str());
}
}
}
@ -560,7 +572,7 @@ namespace Jrd {
// Load plugin
if (newCryptState)
{
loadPlugin(plugName.c_str());
loadPlugin(tdbb, plugName.c_str());
}
crypt = newCryptState;
@ -580,6 +592,9 @@ namespace Jrd {
hc.deleteWithTag(Ods::HDR_crypt_key);
if (keyName.hasData())
hc.insertString(Ods::HDR_crypt_key, keyName);
if (checkFactory)
keyHolderPlugins.validateExistingAttachments(keyName);
}
else
header->hdr_flags &= ~Ods::hdr_encrypted;
@ -591,7 +606,7 @@ namespace Jrd {
header->hdr_flags |= Ods::hdr_crypt_process;
process = true;
digitalySignDatabase(hdr);
digitalySignDatabase(tdbb, hdr);
hdr.flush();
}
catch (const Exception&)
@ -641,13 +656,13 @@ namespace Jrd {
{
keyHolderPlugins.attach(att, dbb.dbb_config);
IDbCryptPlugin* p = checkPlugin;
Factory* f = checkFactory;
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();
}
}
@ -713,7 +728,7 @@ namespace Jrd {
crypt = hdr->hdr_flags & Ods::hdr_encrypted ? true : false;
// 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;
LCK_release(tdbb, threadLock);
@ -956,7 +971,7 @@ namespace Jrd {
}
}
digitalySignDatabase(hdr);
digitalySignDatabase(tdbb, hdr);
hdr.flush();
}
@ -1162,7 +1177,7 @@ namespace Jrd {
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);
@ -1196,7 +1211,7 @@ namespace Jrd {
}
}
if ((!pa) && config->getServerMode() == MODE_SUPER)
if (!pa)
{
pa = &(knownHolders.add());
pa->first = att;
@ -1254,7 +1269,7 @@ namespace Jrd {
st.check();
}
bool CryptoManager::KeyHolderPlugins::validateHoldersGroup(PerAttHolders& pa, IDbCryptPlugin* crypt, const MetaName& keyName)
bool CryptoManager::KeyHolderPlugins::validateHoldersGroup(PerAttHolders& pa, const MetaName& keyName)
{
FbLocalStatus st;
fb_assert(holdersMutex.locked());
@ -1265,15 +1280,14 @@ namespace Jrd {
if (!keyHolder->useOnlyOwnKeys(&st))
return true;
crypt->setKey(&st, 1, &keyHolder, keyName.c_str());
if (st.isSuccess() && mgr->checkValidation(crypt))
if (validateHolder(keyHolder, keyName))
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;
MutexLockGuard g(holdersMutex, FB_FUNCTION);
@ -1286,10 +1300,7 @@ namespace Jrd {
if (pa.first == att)
{
bool empty = (pa.second.getCount() == 0);
bool result = empty ? false : validateHoldersGroup(pa, crypt, keyName);
releaseHolders(pa);
knownHolders.remove(i);
bool result = empty ? false : validateHoldersGroup(pa, keyName);
if (empty)
break;
@ -1299,25 +1310,45 @@ namespace Jrd {
}
// Special case - holders not needed at all
crypt->setKey(&st, 0, NULL, keyName.c_str());
if (st.isSuccess() && mgr->checkValidation(crypt))
return true;
return validateHolder(NULL, keyName);
}
bool CryptoManager::KeyHolderPlugins::validateHolder(IKeyHolderPlugin* keyHolder, const MetaName& keyName)
{
fb_assert(mgr->checkFactory);
if (!mgr->checkFactory)
return false;
FbLocalStatus st;
AutoPtr<IDbCryptPlugin, ReleasePlugin> crypt(mgr->checkFactory->makeInstance());
crypt->setKey(&st, keyHolder ? 1 : 0, &keyHolder, keyName.c_str());
if (st.isSuccess())
{
try
{
if (mgr->checkValidation(crypt))
return true;
}
catch (const Exception&)
{ } // Ignore possible errors, continue analysis
}
return false;
}
void CryptoManager::KeyHolderPlugins::validate(IDbCryptPlugin* crypt, const MetaName& keyName)
void CryptoManager::KeyHolderPlugins::validateExistingAttachments(const MetaName& keyName)
{
FbLocalStatus st;
MutexLockGuard g(holdersMutex, FB_FUNCTION);
fb_assert(mgr->dbb.dbb_sync.isLocked());
// Special case - holders not needed at all
crypt->setKey(&st, 0, NULL, keyName.c_str());
if (st.isSuccess() && mgr->checkValidation(crypt))
if (validateHolder(NULL, keyName))
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 (unsigned i = 0; i < knownHolders.getCount(); ++i)
@ -1326,21 +1357,16 @@ namespace Jrd {
goto found;
}
att->signalCancel();
att->signalShutdown();
found:;
}
// Loop through internal attachments list closing one missing valid holders
for (unsigned i = 0; i < knownHolders.getCount(); ++i)
{
if (!validateHoldersGroup(knownHolders[i], crypt, keyName))
knownHolders[i].first->signalCancel();
// Cleanup holders list
releaseHolders(knownHolders[i]);
if (!validateHoldersGroup(knownHolders[i], keyName))
knownHolders[i].first->signalShutdown();
}
knownHolders.clear();
}
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)
@ -1383,7 +1409,7 @@ found:;
unsigned len = signature.length();
len &= ~(QUANTUM - 1);
loadPlugin(hdr->hdr_crypt_plugin);
loadPlugin(tdbb, hdr->hdr_crypt_plugin);
string enc;
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);
hdr.getClumplets(hc);
@ -1407,7 +1433,7 @@ found:;
{
wf = true;
string signature;
calcDigitalSignature(signature, hdr);
calcDigitalSignature(tdbb, signature, hdr);
hc.insertString(Ods::HDR_crypt_checksum, signature);
}
@ -1415,7 +1441,7 @@ found:;
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))
{
@ -1426,7 +1452,7 @@ found:;
string sig1, sig2;
hc.getString(sig1);
calcDigitalSignature(sig2, hdr);
calcDigitalSignature(tdbb, sig2, hdr);
if (sig1 != sig2)
Arg::Gds(isc_crypt_checksum).raise();
}

View File

@ -36,6 +36,7 @@
#include "../common/classes/objects_array.h"
#include "../common/classes/condition.h"
#include "../common/classes/MetaName.h"
#include "../common/classes/GetPlugins.h"
#include "../common/ThreadStart.h"
#include "../jrd/ods.h"
#include "../jrd/status.h"
@ -268,6 +269,8 @@ private:
class CryptoManager FB_FINAL : public Firebird::PermanentStorage, public BarSync::IBar
{
public:
typedef Firebird::GetPlugins<Firebird::IDbCryptPlugin> Factory;
explicit CryptoManager(thread_db* tdbb);
~CryptoManager();
@ -324,14 +327,16 @@ private:
class KeyHolderPlugins
{
public:
typedef CryptoManager::Factory Factory;
explicit KeyHolderPlugins(Firebird::MemoryPool& p, CryptoManager* 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);
bool validate(Firebird::IDbCryptPlugin* crypt, Attachment*, const Firebird::MetaName& keyName);
void validate(Firebird::IDbCryptPlugin* crypt, const Firebird::MetaName& keyName);
bool validateNewAttachment(Attachment*, const Firebird::MetaName& keyName);
void validateExistingAttachments(const Firebird::MetaName& keyName);
void detach(Attachment* att);
private:
@ -341,7 +346,8 @@ private:
Firebird::ObjectsArray<PerAttHolders> knownHolders;
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);
};
@ -383,7 +389,7 @@ private:
void doOnTakenWriteSync(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);
void writeDbHeader(thread_db* tdbb, ULONG runpage);
void calcValidation(Firebird::string& valid, Firebird::IDbCryptPlugin* plugin);
@ -394,9 +400,9 @@ private:
static const unsigned CRYPT_HDR_NOWAIT = 0x02;
void addClumplet(Firebird::string& value, Firebird::ClumpletReader& block, UCHAR tag);
void calcDigitalSignature(Firebird::string& signature, const class Header& hdr);
void digitalySignDatabase(class CchHdr& hdr);
void checkDigitalSignature(const class Header& hdr);
void calcDigitalSignature(thread_db* tdbb, Firebird::string& signature, const class Header& hdr);
void digitalySignDatabase(thread_db* tdbb, class CchHdr& hdr);
void checkDigitalSignature(thread_db* tdbb, const class Header& hdr);
BarSync sync;
Firebird::MetaName keyName;
@ -407,7 +413,7 @@ private:
Firebird::RefPtr<DbInfo> dbInfo;
Thread::Handle cryptThreadId;
Firebird::IDbCryptPlugin* cryptPlugin;
Firebird::IDbCryptPlugin* checkPlugin;
Factory* checkFactory;
Database& dbb;
Lock* stateLock;
Lock* threadLock;

View File

@ -461,7 +461,7 @@ public:
BackupManager* dbb_backup_manager; // physical backup manager
Firebird::TimeStamp dbb_creation_date; // creation date
ExternalFileDirectoryList* dbb_external_file_directory_list;
Firebird::RefPtr<Config> dbb_config;
Firebird::RefPtr<const Config> dbb_config;
SharedCounter dbb_shared_counter;
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()),
m_process(NULL),
m_processOffset(0),

View File

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

View File

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

View File

@ -124,14 +124,26 @@ void IscConnection::attach(thread_db* tdbb, const PathName& dbName, const MetaNa
FbLocalStatus status;
{
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_handle, newDpb.getBufferLength(),
reinterpret_cast<const char*>(newDpb.getBuffer()));
}
if (status->getState() & IStatus::STATE_ERRORS) {
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];
{
EngineCallbackGuard guard(tdbb, *this, FB_FUNCTION);
@ -1474,6 +1486,15 @@ ISC_STATUS ISC_EXPORT IscProvider::fb_cancel_operation(FbStatusVector* user_stat
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()
{
FbLocalStatus status;
@ -1565,7 +1586,8 @@ static FirebirdApiPointers isc_callbacks =
PROTO(isc_service_detach),
PROTO(isc_service_query),
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*,
isc_db_handle*,
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);
// Build list of client/server plugins
RefPtr<Config> config;
RefPtr<const Config> config;
PathName list;
expandDatabaseName(file, list /* unused value */, &config);
PathName serverList = config->getPlugins(IPluginManager::TYPE_AUTH_SERVER);

View File

@ -969,7 +969,7 @@ public:
void get(const UCHAR*, USHORT, bool&);
void setBuffers(RefPtr<Config> config)
void setBuffers(RefPtr<const Config> config)
{
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,
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*);
static JAttachment* create_attachment(const PathName&, Database*, const DatabaseOptions&, bool newDb);
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 purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsigned flags = 0);
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);
@ -1343,7 +1343,7 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
ThreadContextHolder tdbb(user_status);
DatabaseOptions options;
RefPtr<Config> config;
RefPtr<const Config> config;
bool invalid_client_SQL_dialect = false;
PathName org_filename, expanded_name;
bool is_alias = false;
@ -2427,7 +2427,7 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
DatabaseOptions options;
PathName org_filename, expanded_name;
bool is_alias = false;
Firebird::RefPtr<Config> config;
Firebird::RefPtr<const Config> config;
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,
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,
JProvider* provider)
{
@ -7126,7 +7126,7 @@ static VdnResult verifyDatabaseName(const PathName& name, FbStatusVector* status
if (!securityNameBuffer->hasData())
{
const RefPtr<Config> defConf(Config::getDefaultConfig());
const RefPtr<const Config> defConf(Config::getDefaultConfig());
securityNameBuffer->assign(defConf->getSecurityDatabase());
expandedSecurityNameBuffer->assign(securityNameBuffer);
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,
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)
{
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())
{
PathName dummy;
RefPtr<Config> config;
RefPtr<const Config> config;
expandDatabaseName(svc_expected_db, dummy, &config);
string trusted_role;
@ -1310,7 +1310,7 @@ ISC_STATUS Service::query2(thread_db* /*tdbb*/,
{
// The path to the user security database (security2.fdb)
char* pb = reinterpret_cast<char*>(buffer);
const RefPtr<Config> defConf(Config::getDefaultConfig());
const RefPtr<const Config> defConf(Config::getDefaultConfig());
strcpy(pb, defConf->getSecurityDatabase());
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)
char* pb = reinterpret_cast<char*>(buffer);
const RefPtr<Config> defConf(Config::getDefaultConfig());
const RefPtr<const Config> defConf(Config::getDefaultConfig());
strcpy(pb, defConf->getSecurityDatabase());
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())
{
PathName dummy;
RefPtr<Config> config;
RefPtr<const Config> config;
expandDatabaseName(service->getExpectedDb(), dummy, &config);
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;
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);
@ -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()),
m_bugcheck(false),
m_sharedFileCreated(false),

View File

@ -398,7 +398,7 @@ class LockManager : private Firebird::RefCounted,
const int PID;
public:
static LockManager* create(const Firebird::string&, Firebird::RefPtr<Config>);
static LockManager* create(const Firebird::string&, Firebird::RefPtr<const Config>);
static void destroy(LockManager*);
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);
private:
explicit LockManager(const Firebird::string&, Firebird::RefPtr<Config>);
explicit LockManager(const Firebird::string&, Firebird::RefPtr<const Config>);
~LockManager();
void acquire_shmem(SRQ_PTR);
@ -500,7 +500,7 @@ private:
bool m_blockage;
Firebird::string m_dbId;
Firebird::RefPtr<Config> m_config;
Firebird::RefPtr<const Config> m_config;
// configurations parameters - cached values
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_working_directory(ClumpletWriter&, const PathName&);
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_dsql_fetch(rem_port*, struct rmtque *, USHORT);
static void clear_queue(rem_port*);
@ -798,7 +799,7 @@ IAttachment* RProvider::attach(CheckStatusWrapper* status, const char* filename,
PathName node_name;
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)
{
@ -1420,7 +1421,7 @@ Firebird::IAttachment* RProvider::create(CheckStatusWrapper* status, const char*
PathName node_name;
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)
{
@ -4631,7 +4632,7 @@ Firebird::IService* RProvider::attachSvc(CheckStatusWrapper* status, const char*
if (newSpb.find(isc_spb_expected_db))
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);
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,
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,
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,
@ -5498,7 +5500,7 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned
ISC_utf8ToSystem(node_name);
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
@ -5527,7 +5529,7 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned
if (!port)
{
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 TEXT*,
ClumpletReader&,
RefPtr<Config>*,
RefPtr<const Config>*,
const PathName*,
int);
static bool inet_write(XDR*);
@ -538,8 +538,9 @@ rem_port* INET_analyze(ClntAuthBlock* cBlock,
const TEXT* node_name,
bool uv_flag,
ClumpletReader &dpb,
RefPtr<Config>* config,
RefPtr<const Config>* config,
const PathName* ref_db_name,
Firebird::ICryptKeyCallback* cryptCb,
int af)
{
/**************************************
@ -619,7 +620,8 @@ rem_port* INET_analyze(ClntAuthBlock* cBlock,
REMOTE_PROTOCOL(PROTOCOL_VERSION11, ptype_lazy_send, 2),
REMOTE_PROTOCOL(PROTOCOL_VERSION12, ptype_lazy_send, 3),
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));
cnct->p_cnct_count = FB_NELEM(protocols_to_try);
@ -634,8 +636,11 @@ rem_port* INET_analyze(ClntAuthBlock* cBlock,
}
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(;;)
{
accept = NULL;
switch (packet->p_operation)
{
case op_accept_data:
@ -659,6 +664,45 @@ rem_port* INET_analyze(ClntAuthBlock* cBlock,
accept = &packet->p_acpt;
break;
case op_crypt_key_callback:
try
{
UCharBuffer buf;
P_CRYPT_CALLBACK* cc = &packet->p_cc;
if (cryptCb)
{
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
{
@ -681,6 +725,9 @@ rem_port* INET_analyze(ClntAuthBlock* cBlock,
break;
}
break; // Always leave for() loop here
}
fb_assert(accept);
fb_assert(port);
port->port_protocol = accept->p_acpt_version;
@ -720,7 +767,7 @@ rem_port* INET_connect(const TEXT* name,
PACKET* packet,
USHORT flag,
ClumpletReader* dpb,
RefPtr<Config>* config,
RefPtr<const Config>* config,
int af)
{
/**************************************
@ -2662,7 +2709,7 @@ static rem_port* inet_try_connect(PACKET* packet,
const PathName& file_name,
const TEXT* node_name,
ClumpletReader& dpb,
RefPtr<Config>* config,
RefPtr<const Config>* config,
const PathName* ref_db_name,
int af)
{

View File

@ -34,10 +34,10 @@ namespace Firebird
}
rem_port* INET_analyze(ClntAuthBlock*, const Firebird::PathName&, const TEXT*,
bool, Firebird::ClumpletReader&, Firebird::RefPtr<Config>*,
const Firebird::PathName*, int af = AF_UNSPEC);
bool, Firebird::ClumpletReader&, Firebird::RefPtr<const Config>*,
const Firebird::PathName*, Firebird::ICryptKeyCallback*, int af = AF_UNSPEC);
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_server(SOCKET);
void setStopMainThread(FPTR_INT func);

View File

@ -72,7 +72,7 @@ static void disconnect(rem_port*);
static void exit_handler(void*);
#endif
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 int send_full(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 TEXT* node_name,
bool uv_flag,
RefPtr<Config>* config,
RefPtr<const Config>* config,
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
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)
{
/**************************************

View File

@ -32,8 +32,8 @@ extern "C" {
rem_port* WNET_analyze(ClntAuthBlock*, const Firebird::PathName&, const TEXT*, bool,
Firebird::RefPtr<Config>*, const Firebird::PathName*);
rem_port* WNET_connect(const TEXT*, struct packet*, USHORT, Firebird::RefPtr<Config>*);
Firebird::RefPtr<const Config>*, const Firebird::PathName*);
rem_port* WNET_connect(const TEXT*, struct packet*, USHORT, Firebird::RefPtr<const Config>*);
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);
private:
@ -238,7 +238,7 @@ static void xnet_log_error(const char* err_msg)
rem_port* XNET_analyze(ClntAuthBlock* cBlock,
const PathName& file_name,
bool uv_flag,
RefPtr<Config>* config,
RefPtr<const Config>* config,
const Firebird::PathName* ref_db_name)
{
/**************************************
@ -403,7 +403,7 @@ rem_port* XNET_analyze(ClntAuthBlock* cBlock,
rem_port* XNET_connect(PACKET* packet,
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)
{

View File

@ -32,9 +32,9 @@
#define rem_port void
#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*);
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);
#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);
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));
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);
// Protocol 15:
// - supports crypt key callback at connect phaze
const USHORT PROTOCOL_VERSION15 = (FB_PROTOCOL_FLAG | 15);
// Architecture types
enum P_ARCH

View File

@ -61,7 +61,7 @@ void REMOTE_reset_request (struct Rrq *, struct RMessage*);
void REMOTE_reset_statement (struct Rsr *);
bool_t REMOTE_getbytes (XDR*, SCHAR*, u_int);
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);
void REMOTE_check_response(Firebird::IStatus* warning, Rdb* rdb, PACKET* packet, bool checkKeys = false);
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;
}
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();
}
@ -1006,7 +1011,7 @@ void ClntAuthBlock::resetClnt(const Firebird::PathName* fileName, const CSTRING*
plugins.set(final.c_str());
}
Firebird::RefPtr<Config>* ClntAuthBlock::getConfig()
Firebird::RefPtr<const Config>* ClntAuthBlock::getConfig()
{
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));
}
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)
{
Firebird::RefPtr<Config> config;
Firebird::RefPtr<const Config> config;
if (dbName && dbName->hasData())
{

View File

@ -703,7 +703,7 @@ private:
Firebird::UCharBuffer dataForPlugin, dataFromPlugin;
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::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
bool hasCryptKey; // DPB contains disk crypt key, may be passed only over encrypted wire
@ -733,7 +733,7 @@ public:
Firebird::PathName getPluginName();
void tryNewKeys(rem_port*);
void releaseKeys(unsigned from);
Firebird::RefPtr<Config>* getConfig();
Firebird::RefPtr<const Config>* getConfig();
// Firebird::IClientBlock implementation
int release();
@ -947,7 +947,7 @@ struct rem_port : public Firebird::GlobalStorage, public Firebird::RefCounted
OBJCT port_last_object_id; // cached last id
Firebird::ObjectsArray< Firebird::Array<char> > port_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
ServerAuthBase* port_srv_auth;
@ -1023,7 +1023,8 @@ public:
static bool checkCompression();
void linkParent(rem_port* const parent);
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;
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_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 dpb[] = {isc_dpb_version1, isc_dpb_sec_attach, 1, 1, isc_dpb_address_path, 0};

View File

@ -105,7 +105,175 @@ public:
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
class FailedLogin
{
public:
@ -287,6 +455,7 @@ static void getMultiPartConnectParameter(T& putTo, Firebird::ClumpletReader& id,
// delayed authentication block for auth callback
class ServerAuth : public GlobalStorage, public ServerAuthBase
{
public:
@ -379,6 +548,11 @@ public:
authPort->port_srv_auth_block->setDataForPlugin(u);
}
#endif
if (!authPort->port_server_crypt_callback)
{
authPort->port_server_crypt_callback = FB_NEW ServerCallback(authPort);
}
}
~ServerAuth()
@ -425,6 +599,13 @@ public:
{
authServer = authItr->plugin();
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
@ -774,6 +955,9 @@ private:
Rvnt* event;
};
// Stores types of known wire crypt keys
class CryptKeyTypeManager : public PermanentStorage
{
class CryptKeyType : public PermanentStorage
@ -868,91 +1052,6 @@ private:
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
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;
protocol < end; protocol++)
{
if ((protocol->p_cnct_version == PROTOCOL_VERSION10 ||
protocol->p_cnct_version == PROTOCOL_VERSION11 ||
protocol->p_cnct_version == PROTOCOL_VERSION12 ||
protocol->p_cnct_version == PROTOCOL_VERSION13 ||
protocol->p_cnct_version == PROTOCOL_VERSION14) &&
if ((protocol->p_cnct_version >= PROTOCOL_VERSION10 &&
protocol->p_cnct_version <= PROTOCOL_VERSION15) &&
(protocol->p_cnct_architecture == arch_generic ||
protocol->p_cnct_architecture == ARCHITECTURE) &&
protocol->p_cnct_weight >= weight)
@ -2239,13 +2335,10 @@ void DatabaseAuth::accept(PACKET* send, Auth::WriterImplementation* authBlock)
const UCHAR* dpb = pb->getBuffer();
unsigned int dl = (ULONG) pb->getBufferLength();
if (!authPort->port_server_crypt_callback)
{
authPort->port_server_crypt_callback = FB_NEW ServerCallback(authPort);
}
LocalStatus ls;
CheckStatusWrapper status_vector(&ls);
fb_assert(authPort->port_server_crypt_callback);
provider->setDbCryptCallback(&status_vector, authPort->port_server_crypt_callback->getInterface());
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.
REMOTE_get_timeout_params(this, spb);
if (!port_server_crypt_callback)
{
port_server_crypt_callback = FB_NEW ServerCallback(this);
}
DispatcherPtr provider;
LocalStatus ls;
CheckStatusWrapper status_vector(&ls);
fb_assert(port_server_crypt_callback);
provider->setDbCryptCallback(&status_vector, port_server_crypt_callback->getInterface());
if (!(status_vector.getState() & Firebird::IStatus::STATE_ERRORS))
{
dumpAuthBlock("rem_port::service_attach()", spb, isc_spb_auth_block);
@ -6500,7 +6590,7 @@ void SrvAuthBlock::createPluginsItr()
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());
}

View File

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

View File

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

View File

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