Skip to content

Commit

Permalink
Implemented CORE-5374: Make database name available to crypt plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexPeshkoff committed Oct 12, 2016
1 parent d079557 commit b76648f
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 1 deletion.
7 changes: 7 additions & 0 deletions examples/dbcrypt/DbCrypt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ class DbCrypt : public IDbCryptPluginImpl<DbCrypt, CheckStatusWrapper>
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

This comment has been minimized.

Copy link
@asfernandes

asfernandes Oct 13, 2016

Member

I see you already used this NEVERDEF in common for another thing. It misses the objective of defines when you use a same [not good] name for different things.

This comment has been minimized.

Copy link
@AlexPeshkoff

AlexPeshkoff Oct 14, 2016

Author Member

I use it for same purpose as NOT_USED_OR_REPLACED widely used to mark unused code. But re. this particular place I agree - comment is better

fprintf(stderr, "DbInfo: name is %s\n", info->getDatabaseFullPath(status));
#endif
}

int release()
{
Expand Down
11 changes: 11 additions & 0 deletions src/include/firebird/FirebirdInterface.idl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}


Expand Down
142 changes: 141 additions & 1 deletion src/include/firebird/IdlFbInterfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ namespace Firebird
class IWireCryptPlugin;
class ICryptKeyCallback;
class IKeyHolderPlugin;
class IDbCryptInfo;
class IDbCryptPlugin;
class IExternalContext;
class IExternalResultSet;
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand All @@ -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)
{
Expand All @@ -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
Expand Down Expand Up @@ -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
{
Expand All @@ -11309,6 +11433,7 @@ namespace Firebird
this->setKey = &Name::cloopsetKeyDispatcher;
this->encrypt = &Name::cloopencryptDispatcher;
this->decrypt = &Name::cloopdecryptDispatcher;
this->setInfo = &Name::cloopsetInfoDispatcher;
}
} vTable;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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>
Expand Down
20 changes: 20 additions & 0 deletions src/jrd/CryptoManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ namespace Jrd {
sync(this),
keyName(getPool()),
keyHolderPlugins(getPool()),
dbInfo(FB_NEW DbInfo(this)),
cryptThreadId(0),
cryptPlugin(NULL),
dbb(*tdbb->getDatabase()),
Expand All @@ -288,6 +289,8 @@ namespace Jrd {

delete stateLock;
delete threadLock;

dbInfo->destroy();
}

void CryptoManager::shutdown(thread_db* tdbb)
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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
32 changes: 32 additions & 0 deletions src/jrd/CryptoManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,37 @@ class CryptoManager FB_FINAL : public Firebird::PermanentStorage, public BarSync
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();

Expand All @@ -383,6 +414,7 @@ class CryptoManager FB_FINAL : public Firebird::PermanentStorage, public BarSync
ULONG currentPage;
Firebird::Mutex pluginLoadMtx, cryptThreadMtx;
KeyHolderPlugins keyHolderPlugins;
Firebird::RefPtr<DbInfo> dbInfo;
Thread::Handle cryptThreadId;
Firebird::IDbCryptPlugin* cryptPlugin;
Database& dbb;
Expand Down

1 comment on commit b76648f

@aafemt
Copy link
Contributor

@aafemt aafemt commented on b76648f Oct 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing of interface without discussion or RFC is not a good idea.

Please sign in to comment.