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

Implemented CORE-5374: Make database name available to crypt plugin

This commit is contained in:
AlexPeshkoff 2016-10-12 15:22:15 +03:00
parent d079557458
commit b76648f1f6
5 changed files with 211 additions and 1 deletions

View File

@ -81,6 +81,13 @@ public:
void decrypt(CheckStatusWrapper* status, unsigned int length, const void* from, void* to);
void setKey(CheckStatusWrapper* status, unsigned int length, IKeyHolderPlugin** sources,
const char* keyName);
// One if free to ignore passed info when not needed
void setInfo(CheckStatusWrapper* status, IDbCryptInfo* info)
{
#ifdef NEVERDEF
fprintf(stderr, "DbInfo: name is %s\n", info->getDatabaseFullPath(status));
#endif
}
int release()
{

View File

@ -735,6 +735,13 @@ interface KeyHolderPlugin : PluginBase
}
// Information calls available for crypt plugin
interface DbCryptInfo : ReferenceCounted
{
const string getDatabaseFullPath(Status status);
}
interface DbCryptPlugin : PluginBase
{
// When database crypt plugin is loaded, setKey() is called to provide information
@ -745,6 +752,10 @@ interface DbCryptPlugin : PluginBase
void setKey(Status status, uint length, KeyHolderPlugin* sources, const string keyName);
void encrypt(Status status, uint length, const void* from, void* to);
void decrypt(Status status, uint length, const void* from, void* to);
version: // 3.0.1 => 4.0
// Crypto manager may pass some additional info to plugin
void setInfo(Status status, DbCryptInfo info);
}

View File

@ -73,6 +73,7 @@ namespace Firebird
class IWireCryptPlugin;
class ICryptKeyCallback;
class IKeyHolderPlugin;
class IDbCryptInfo;
class IDbCryptPlugin;
class IExternalContext;
class IExternalResultSet;
@ -2936,6 +2937,36 @@ namespace Firebird
}
};
class IDbCryptInfo : public IReferenceCounted
{
public:
struct VTable : public IReferenceCounted::VTable
{
const char* (CLOOP_CARG *getDatabaseFullPath)(IDbCryptInfo* self, IStatus* status) throw();
};
protected:
IDbCryptInfo(DoNotInherit)
: IReferenceCounted(DoNotInherit())
{
}
~IDbCryptInfo()
{
}
public:
static const unsigned VERSION = 3;
template <typename StatusType> const char* getDatabaseFullPath(StatusType* status)
{
StatusType::clearException(status);
const char* ret = static_cast<VTable*>(this->cloopVTable)->getDatabaseFullPath(this, status);
StatusType::checkException(status);
return ret;
}
};
class IDbCryptPlugin : public IPluginBase
{
public:
@ -2944,6 +2975,7 @@ namespace Firebird
void (CLOOP_CARG *setKey)(IDbCryptPlugin* self, IStatus* status, unsigned length, IKeyHolderPlugin** sources, const char* keyName) throw();
void (CLOOP_CARG *encrypt)(IDbCryptPlugin* self, IStatus* status, unsigned length, const void* from, void* to) throw();
void (CLOOP_CARG *decrypt)(IDbCryptPlugin* self, IStatus* status, unsigned length, const void* from, void* to) throw();
void (CLOOP_CARG *setInfo)(IDbCryptPlugin* self, IStatus* status, IDbCryptInfo* info) throw();
};
protected:
@ -2957,7 +2989,7 @@ namespace Firebird
}
public:
static const unsigned VERSION = 4;
static const unsigned VERSION = 5;
template <typename StatusType> void setKey(StatusType* status, unsigned length, IKeyHolderPlugin** sources, const char* keyName)
{
@ -2979,6 +3011,19 @@ namespace Firebird
static_cast<VTable*>(this->cloopVTable)->decrypt(this, status, length, from, to);
StatusType::checkException(status);
}
template <typename StatusType> void setInfo(StatusType* status, IDbCryptInfo* info)
{
if (cloopVTable->version < 5)
{
StatusType::setVersionError(status, "IDbCryptPlugin", cloopVTable->version, 5);
StatusType::checkException(status);
return;
}
StatusType::clearException(status);
static_cast<VTable*>(this->cloopVTable)->setInfo(this, status, info);
StatusType::checkException(status);
}
};
class IExternalContext : public IVersioned
@ -11289,6 +11334,85 @@ namespace Firebird
virtual ICryptKeyCallback* keyHandle(StatusType* status, const char* keyName) = 0;
};
template <typename Name, typename StatusType, typename Base>
class IDbCryptInfoBaseImpl : public Base
{
public:
typedef IDbCryptInfo Declaration;
IDbCryptInfoBaseImpl(DoNotInherit = DoNotInherit())
{
static struct VTableImpl : Base::VTable
{
VTableImpl()
{
this->version = Base::VERSION;
this->addRef = &Name::cloopaddRefDispatcher;
this->release = &Name::cloopreleaseDispatcher;
this->getDatabaseFullPath = &Name::cloopgetDatabaseFullPathDispatcher;
}
} vTable;
this->cloopVTable = &vTable;
}
static const char* CLOOP_CARG cloopgetDatabaseFullPathDispatcher(IDbCryptInfo* self, IStatus* status) throw()
{
StatusType status2(status);
try
{
return static_cast<Name*>(self)->Name::getDatabaseFullPath(&status2);
}
catch (...)
{
StatusType::catchException(&status2);
return static_cast<const char*>(0);
}
}
static void CLOOP_CARG cloopaddRefDispatcher(IReferenceCounted* self) throw()
{
try
{
static_cast<Name*>(self)->Name::addRef();
}
catch (...)
{
StatusType::catchException(0);
}
}
static int CLOOP_CARG cloopreleaseDispatcher(IReferenceCounted* self) throw()
{
try
{
return static_cast<Name*>(self)->Name::release();
}
catch (...)
{
StatusType::catchException(0);
return static_cast<int>(0);
}
}
};
template <typename Name, typename StatusType, typename Base = IReferenceCountedImpl<Name, StatusType, Inherit<IVersionedImpl<Name, StatusType, Inherit<IDbCryptInfo> > > > >
class IDbCryptInfoImpl : public IDbCryptInfoBaseImpl<Name, StatusType, Base>
{
protected:
IDbCryptInfoImpl(DoNotInherit = DoNotInherit())
{
}
public:
virtual ~IDbCryptInfoImpl()
{
}
virtual const char* getDatabaseFullPath(StatusType* status) = 0;
};
template <typename Name, typename StatusType, typename Base>
class IDbCryptPluginBaseImpl : public Base
{
@ -11309,6 +11433,7 @@ namespace Firebird
this->setKey = &Name::cloopsetKeyDispatcher;
this->encrypt = &Name::cloopencryptDispatcher;
this->decrypt = &Name::cloopdecryptDispatcher;
this->setInfo = &Name::cloopsetInfoDispatcher;
}
} vTable;
@ -11357,6 +11482,20 @@ namespace Firebird
}
}
static void CLOOP_CARG cloopsetInfoDispatcher(IDbCryptPlugin* self, IStatus* status, IDbCryptInfo* info) throw()
{
StatusType status2(status);
try
{
static_cast<Name*>(self)->Name::setInfo(&status2, info);
}
catch (...)
{
StatusType::catchException(&status2);
}
}
static void CLOOP_CARG cloopsetOwnerDispatcher(IPluginBase* self, IReferenceCounted* r) throw()
{
try
@ -11424,6 +11563,7 @@ namespace Firebird
virtual void setKey(StatusType* status, unsigned length, IKeyHolderPlugin** sources, const char* keyName) = 0;
virtual void encrypt(StatusType* status, unsigned length, const void* from, void* to) = 0;
virtual void decrypt(StatusType* status, unsigned length, const void* from, void* to) = 0;
virtual void setInfo(StatusType* status, IDbCryptInfo* info) = 0;
};
template <typename Name, typename StatusType, typename Base>

View File

@ -266,6 +266,7 @@ namespace Jrd {
sync(this),
keyName(getPool()),
keyHolderPlugins(getPool()),
dbInfo(FB_NEW DbInfo(this)),
cryptThreadId(0),
cryptPlugin(NULL),
dbb(*tdbb->getDatabase()),
@ -288,6 +289,8 @@ namespace Jrd {
delete stateLock;
delete threadLock;
dbInfo->destroy();
}
void CryptoManager::shutdown(thread_db* tdbb)
@ -396,6 +399,16 @@ namespace Jrd {
// do not assign cryptPlugin directly before key init complete
IDbCryptPlugin* p = cryptControl.plugin();
FbLocalStatus status;
p->setInfo(&status, dbInfo);
if (status->getState() & IStatus::STATE_ERRORS)
{
const ISC_STATUS* v = status->getErrors();
if (v[0] == isc_arg_gds && v[1] != isc_arg_end && v[1] != isc_interface_version_too_old)
status_exception::raise(&status);
}
keyHolderPlugins.init(p, keyName.c_str());
cryptPlugin = p;
cryptPlugin->addRef();
@ -1319,4 +1332,11 @@ namespace Jrd {
}
}
const char* CryptoManager::DbInfo::getDatabaseFullPath(Firebird::CheckStatusWrapper* status)
{
if (!cryptoManager)
return NULL;
return cryptoManager->dbb.dbb_filename.c_str();
}
} // namespace Jrd

View File

@ -357,6 +357,37 @@ private:
Firebird::ObjectsArray<HolderAttachments> knownHolders;
};
class DbInfo;
friend class DbInfo;
class DbInfo FB_FINAL : public Firebird::RefCntIface<Firebird::IDbCryptInfoImpl<DbInfo, Firebird::CheckStatusWrapper>>
{
public:
DbInfo(CryptoManager* cm)
: cryptoManager(cm)
{ }
void destroy()
{
cryptoManager = NULL;
}
// IDbCryptInfo implementation
const char* getDatabaseFullPath(Firebird::CheckStatusWrapper* status);
int release()
{
if (--refCounter != 0)
return 1;
delete this;
return 0;
}
private:
CryptoManager* cryptoManager;
};
static int blockingAstChangeCryptState(void*);
void blockingAstChangeCryptState();
@ -383,6 +414,7 @@ private:
ULONG currentPage;
Firebird::Mutex pluginLoadMtx, cryptThreadMtx;
KeyHolderPlugins keyHolderPlugins;
Firebird::RefPtr<DbInfo> dbInfo;
Thread::Handle cryptThreadId;
Firebird::IDbCryptPlugin* cryptPlugin;
Database& dbb;