mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 16:03:03 +01:00
Fixed CORE-5472: Problems with dbcrypt key transfer
This commit is contained in:
parent
7fadd8e9f9
commit
4da3997b49
@ -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
@ -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();
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -236,7 +236,9 @@ void DbCrypt::setKey(CheckStatusWrapper* status, unsigned int length, IKeyHolder
|
||||
return;
|
||||
|
||||
if (callback && callback->callback(0, NULL, 1, &key) == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
key = 0;
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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())
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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,31 +327,34 @@ 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:
|
||||
Firebird::Mutex holdersMutex;
|
||||
typedef Firebird::Pair<Firebird::Right<Attachment*,
|
||||
Firebird::HalfStaticArray<Firebird::IKeyHolderPlugin*, 4>>> PerAttHolders;
|
||||
Firebird::HalfStaticArray<Firebird::IKeyHolderPlugin*, 4> > > PerAttHolders;
|
||||
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);
|
||||
};
|
||||
|
||||
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:
|
||||
DbInfo(CryptoManager* cm)
|
||||
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
|
@ -109,7 +109,7 @@ namespace Jrd
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<Config> config;
|
||||
RefPtr<const Config> config;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -124,12 +124,24 @@ 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");
|
||||
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];
|
||||
@ -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)
|
||||
};
|
||||
|
||||
|
||||
|
@ -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*);
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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)))
|
||||
|
@ -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",
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,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);
|
||||
P_ACPT* accept;
|
||||
|
||||
P_ACPT* accept = NULL;
|
||||
switch (packet->p_operation)
|
||||
for(;;)
|
||||
{
|
||||
case op_accept_data:
|
||||
case op_cond_accept:
|
||||
accept = &packet->p_acpd;
|
||||
if (cBlock)
|
||||
accept = NULL;
|
||||
switch (packet->p_operation)
|
||||
{
|
||||
cBlock->storeDataForPlugin(packet->p_acpd.p_acpt_data.cstr_length,
|
||||
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_data:
|
||||
case op_cond_accept:
|
||||
accept = &packet->p_acpd;
|
||||
if (cBlock)
|
||||
{
|
||||
cBlock->storeDataForPlugin(packet->p_acpd.p_acpt_data.cstr_length,
|
||||
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:
|
||||
if (cBlock)
|
||||
{
|
||||
cBlock->resetClnt(&file_name);
|
||||
}
|
||||
accept = &packet->p_acpt;
|
||||
break;
|
||||
case op_accept:
|
||||
if (cBlock)
|
||||
{
|
||||
cBlock->resetClnt(&file_name);
|
||||
}
|
||||
accept = &packet->p_acpt;
|
||||
break;
|
||||
|
||||
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&)
|
||||
{
|
||||
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
|
||||
{
|
||||
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);
|
||||
delete rdb;
|
||||
throw;
|
||||
Arg::Gds(isc_connect_reject).raise();
|
||||
break;
|
||||
}
|
||||
// fall through - response is not a required accept
|
||||
|
||||
default:
|
||||
disconnect(port);
|
||||
delete rdb;
|
||||
Arg::Gds(isc_connect_reject).raise();
|
||||
break;
|
||||
break; // Always leave for() loop here
|
||||
}
|
||||
|
||||
fb_assert(accept);
|
||||
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
/**************************************
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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*);
|
||||
|
@ -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())
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user