8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-02-02 10:40:38 +01:00

Backported implementation of CORE-5374: Make database name available to crypt plugin

This commit is contained in:
AlexPeshkoff 2016-10-12 15:24:03 +03:00
parent 27ff10f31d
commit 0971eebb8f
6 changed files with 301 additions and 3 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

@ -725,6 +725,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
@ -735,6 +742,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 => 3.0.2
// Crypto manager may pass some additional info to plugin
void setInfo(Status status, DbCryptInfo info);
}

View File

@ -72,6 +72,7 @@ namespace Firebird
class IWireCryptPlugin;
class ICryptKeyCallback;
class IKeyHolderPlugin;
class IDbCryptInfo;
class IDbCryptPlugin;
class IExternalContext;
class IExternalResultSet;
@ -2873,6 +2874,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:
@ -2881,6 +2912,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:
@ -2894,7 +2926,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)
{
@ -2916,6 +2948,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
@ -11074,6 +11119,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
{
@ -11094,6 +11218,7 @@ namespace Firebird
this->setKey = &Name::cloopsetKeyDispatcher;
this->encrypt = &Name::cloopencryptDispatcher;
this->decrypt = &Name::cloopdecryptDispatcher;
this->setInfo = &Name::cloopsetInfoDispatcher;
}
} vTable;
@ -11142,6 +11267,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
@ -11209,6 +11348,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

@ -57,6 +57,7 @@ type
IWireCryptPlugin = class;
ICryptKeyCallback = class;
IKeyHolderPlugin = class;
IDbCryptInfo = class;
IDbCryptPlugin = class;
IExternalContext = class;
IExternalResultSet = class;
@ -361,9 +362,11 @@ type
ICryptKeyCallback_callbackPtr = function(this: ICryptKeyCallback; dataLength: Cardinal; data: Pointer; bufferLength: Cardinal; buffer: Pointer): Cardinal; cdecl;
IKeyHolderPlugin_keyCallbackPtr = function(this: IKeyHolderPlugin; status: IStatus; callback: ICryptKeyCallback): Integer; cdecl;
IKeyHolderPlugin_keyHandlePtr = function(this: IKeyHolderPlugin; status: IStatus; keyName: PAnsiChar): ICryptKeyCallback; cdecl;
IDbCryptInfo_getDatabaseFullPathPtr = function(this: IDbCryptInfo; status: IStatus): PAnsiChar; cdecl;
IDbCryptPlugin_setKeyPtr = procedure(this: IDbCryptPlugin; status: IStatus; length: Cardinal; sources: IKeyHolderPluginPtr; keyName: PAnsiChar); cdecl;
IDbCryptPlugin_encryptPtr = procedure(this: IDbCryptPlugin; status: IStatus; length: Cardinal; from: Pointer; to_: Pointer); cdecl;
IDbCryptPlugin_decryptPtr = procedure(this: IDbCryptPlugin; status: IStatus; length: Cardinal; from: Pointer; to_: Pointer); cdecl;
IDbCryptPlugin_setInfoPtr = procedure(this: IDbCryptPlugin; status: IStatus; info: IDbCryptInfo); cdecl;
IExternalContext_getMasterPtr = function(this: IExternalContext): IMaster; cdecl;
IExternalContext_getEnginePtr = function(this: IExternalContext; status: IStatus): IExternalEngine; cdecl;
IExternalContext_getAttachmentPtr = function(this: IExternalContext; status: IStatus): IAttachment; cdecl;
@ -1919,18 +1922,38 @@ type
function keyHandle(status: IStatus; keyName: PAnsiChar): ICryptKeyCallback; virtual; abstract;
end;
DbCryptInfoVTable = class(ReferenceCountedVTable)
getDatabaseFullPath: IDbCryptInfo_getDatabaseFullPathPtr;
end;
IDbCryptInfo = class(IReferenceCounted)
const VERSION = 3;
function getDatabaseFullPath(status: IStatus): PAnsiChar;
end;
IDbCryptInfoImpl = class(IDbCryptInfo)
constructor create;
procedure addRef(); virtual; abstract;
function release(): Integer; virtual; abstract;
function getDatabaseFullPath(status: IStatus): PAnsiChar; virtual; abstract;
end;
DbCryptPluginVTable = class(PluginBaseVTable)
setKey: IDbCryptPlugin_setKeyPtr;
encrypt: IDbCryptPlugin_encryptPtr;
decrypt: IDbCryptPlugin_decryptPtr;
setInfo: IDbCryptPlugin_setInfoPtr;
end;
IDbCryptPlugin = class(IPluginBase)
const VERSION = 7;
const VERSION = 8;
procedure setKey(status: IStatus; length: Cardinal; sources: IKeyHolderPluginPtr; keyName: PAnsiChar);
procedure encrypt(status: IStatus; length: Cardinal; from: Pointer; to_: Pointer);
procedure decrypt(status: IStatus; length: Cardinal; from: Pointer; to_: Pointer);
procedure setInfo(status: IStatus; info: IDbCryptInfo);
end;
IDbCryptPluginImpl = class(IDbCryptPlugin)
@ -1943,6 +1966,7 @@ type
procedure setKey(status: IStatus; length: Cardinal; sources: IKeyHolderPluginPtr; keyName: PAnsiChar); virtual; abstract;
procedure encrypt(status: IStatus; length: Cardinal; from: Pointer; to_: Pointer); virtual; abstract;
procedure decrypt(status: IStatus; length: Cardinal; from: Pointer; to_: Pointer); virtual; abstract;
procedure setInfo(status: IStatus; info: IDbCryptInfo); virtual; abstract;
end;
ExternalContextVTable = class(VersionedVTable)
@ -5919,6 +5943,12 @@ begin
FbException.checkException(status);
end;
function IDbCryptInfo.getDatabaseFullPath(status: IStatus): PAnsiChar;
begin
Result := DbCryptInfoVTable(vTable).getDatabaseFullPath(Self, status);
FbException.checkException(status);
end;
procedure IDbCryptPlugin.setKey(status: IStatus; length: Cardinal; sources: IKeyHolderPluginPtr; keyName: PAnsiChar);
begin
DbCryptPluginVTable(vTable).setKey(Self, status, length, sources, keyName);
@ -5937,6 +5967,12 @@ begin
FbException.checkException(status);
end;
procedure IDbCryptPlugin.setInfo(status: IStatus; info: IDbCryptInfo);
begin
DbCryptPluginVTable(vTable).setInfo(Self, status, info);
FbException.checkException(status);
end;
function IExternalContext.getMaster(): IMaster;
begin
Result := ExternalContextVTable(vTable).getMaster(Self);
@ -9826,6 +9862,41 @@ begin
vTable := IKeyHolderPluginImpl_vTable;
end;
procedure IDbCryptInfoImpl_addRefDispatcher(this: IDbCryptInfo); cdecl;
begin
try
IDbCryptInfoImpl(this).addRef();
except
on e: Exception do FbException.catchException(nil, e);
end
end;
function IDbCryptInfoImpl_releaseDispatcher(this: IDbCryptInfo): Integer; cdecl;
begin
try
Result := IDbCryptInfoImpl(this).release();
except
on e: Exception do FbException.catchException(nil, e);
end
end;
function IDbCryptInfoImpl_getDatabaseFullPathDispatcher(this: IDbCryptInfo; status: IStatus): PAnsiChar; cdecl;
begin
try
Result := IDbCryptInfoImpl(this).getDatabaseFullPath(status);
except
on e: Exception do FbException.catchException(status, e);
end
end;
var
IDbCryptInfoImpl_vTable: DbCryptInfoVTable;
constructor IDbCryptInfoImpl.create;
begin
vTable := IDbCryptInfoImpl_vTable;
end;
procedure IDbCryptPluginImpl_addRefDispatcher(this: IDbCryptPlugin); cdecl;
begin
try
@ -9889,6 +9960,15 @@ begin
end
end;
procedure IDbCryptPluginImpl_setInfoDispatcher(this: IDbCryptPlugin; status: IStatus; info: IDbCryptInfo); cdecl;
begin
try
IDbCryptPluginImpl(this).setInfo(status, info);
except
on e: Exception do FbException.catchException(status, e);
end
end;
var
IDbCryptPluginImpl_vTable: DbCryptPluginVTable;
@ -12574,8 +12654,14 @@ initialization
IKeyHolderPluginImpl_vTable.keyCallback := @IKeyHolderPluginImpl_keyCallbackDispatcher;
IKeyHolderPluginImpl_vTable.keyHandle := @IKeyHolderPluginImpl_keyHandleDispatcher;
IDbCryptInfoImpl_vTable := DbCryptInfoVTable.create;
IDbCryptInfoImpl_vTable.version := 3;
IDbCryptInfoImpl_vTable.addRef := @IDbCryptInfoImpl_addRefDispatcher;
IDbCryptInfoImpl_vTable.release := @IDbCryptInfoImpl_releaseDispatcher;
IDbCryptInfoImpl_vTable.getDatabaseFullPath := @IDbCryptInfoImpl_getDatabaseFullPathDispatcher;
IDbCryptPluginImpl_vTable := DbCryptPluginVTable.create;
IDbCryptPluginImpl_vTable.version := 7;
IDbCryptPluginImpl_vTable.version := 8;
IDbCryptPluginImpl_vTable.addRef := @IDbCryptPluginImpl_addRefDispatcher;
IDbCryptPluginImpl_vTable.release := @IDbCryptPluginImpl_releaseDispatcher;
IDbCryptPluginImpl_vTable.setOwner := @IDbCryptPluginImpl_setOwnerDispatcher;
@ -12583,6 +12669,7 @@ initialization
IDbCryptPluginImpl_vTable.setKey := @IDbCryptPluginImpl_setKeyDispatcher;
IDbCryptPluginImpl_vTable.encrypt := @IDbCryptPluginImpl_encryptDispatcher;
IDbCryptPluginImpl_vTable.decrypt := @IDbCryptPluginImpl_decryptDispatcher;
IDbCryptPluginImpl_vTable.setInfo := @IDbCryptPluginImpl_setInfoDispatcher;
IExternalContextImpl_vTable := ExternalContextVTable.create;
IExternalContextImpl_vTable.version := 10;
@ -12952,6 +13039,7 @@ finalization
IWireCryptPluginImpl_vTable.destroy;
ICryptKeyCallbackImpl_vTable.destroy;
IKeyHolderPluginImpl_vTable.destroy;
IDbCryptInfoImpl_vTable.destroy;
IDbCryptPluginImpl_vTable.destroy;
IExternalContextImpl_vTable.destroy;
IExternalResultSetImpl_vTable.destroy;

View File

@ -275,6 +275,7 @@ namespace Jrd {
sync(this),
keyName(getPool()),
keyHolderPlugins(getPool()),
dbInfo(FB_NEW DbInfo(this)),
cryptThreadId(0),
cryptPlugin(NULL),
dbb(*tdbb->getDatabase()),
@ -297,6 +298,8 @@ namespace Jrd {
delete stateLock;
delete threadLock;
dbInfo->destroy();
}
void CryptoManager::shutdown(thread_db* tdbb)
@ -405,6 +408,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();
@ -1327,4 +1340,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;