mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 20:43:02 +01:00
Implemented #7951: Make it possible to handle attach errors in key holder plugin.
This commit is contained in:
parent
6dce8db8ca
commit
c2238907a7
@ -941,6 +941,21 @@ interface CryptKeyCallback : Versioned
|
||||
// any further details.
|
||||
uint callback(uint dataLength, const void* data,
|
||||
uint bufferLength, void* buffer);
|
||||
|
||||
version: // 6.0
|
||||
// Result returned by afterAttach()
|
||||
const uint NO_RETRY = 0; // Returned by old plugins & stub
|
||||
const uint DO_RETRY = 1;
|
||||
|
||||
// NULL in attStatus means attach was successful.
|
||||
// DO_RETRY return will be ignored in this case, but plugin has a chance
|
||||
// to reflect internally success.
|
||||
[stub defaultAction]
|
||||
uint afterAttach(Status status, const string dbName, const Status attStatus);
|
||||
|
||||
// interface not needed any more
|
||||
[stub defaultAction]
|
||||
void dispose();
|
||||
}
|
||||
|
||||
|
||||
|
@ -3891,7 +3891,7 @@ namespace Firebird
|
||||
}
|
||||
};
|
||||
|
||||
#define FIREBIRD_ICRYPT_KEY_CALLBACK_VERSION 2u
|
||||
#define FIREBIRD_ICRYPT_KEY_CALLBACK_VERSION 3u
|
||||
|
||||
class ICryptKeyCallback : public IVersioned
|
||||
{
|
||||
@ -3899,6 +3899,8 @@ namespace Firebird
|
||||
struct VTable : public IVersioned::VTable
|
||||
{
|
||||
unsigned (CLOOP_CARG *callback)(ICryptKeyCallback* self, unsigned dataLength, const void* data, unsigned bufferLength, void* buffer) CLOOP_NOEXCEPT;
|
||||
unsigned (CLOOP_CARG *afterAttach)(ICryptKeyCallback* self, IStatus* status, const char* dbName, const IStatus* attStatus) CLOOP_NOEXCEPT;
|
||||
void (CLOOP_CARG *dispose)(ICryptKeyCallback* self) CLOOP_NOEXCEPT;
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -3914,11 +3916,37 @@ namespace Firebird
|
||||
public:
|
||||
static CLOOP_CONSTEXPR unsigned VERSION = FIREBIRD_ICRYPT_KEY_CALLBACK_VERSION;
|
||||
|
||||
static CLOOP_CONSTEXPR unsigned NO_RETRY = 0;
|
||||
static CLOOP_CONSTEXPR unsigned DO_RETRY = 1;
|
||||
|
||||
unsigned callback(unsigned dataLength, const void* data, unsigned bufferLength, void* buffer)
|
||||
{
|
||||
unsigned ret = static_cast<VTable*>(this->cloopVTable)->callback(this, dataLength, data, bufferLength, buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename StatusType> unsigned afterAttach(StatusType* status, const char* dbName, const IStatus* attStatus)
|
||||
{
|
||||
if (cloopVTable->version < 3)
|
||||
{
|
||||
StatusType::setVersionError(status, "ICryptKeyCallback", cloopVTable->version, 3);
|
||||
StatusType::checkException(status);
|
||||
return 0;
|
||||
}
|
||||
StatusType::clearException(status);
|
||||
unsigned ret = static_cast<VTable*>(this->cloopVTable)->afterAttach(this, status, dbName, attStatus);
|
||||
StatusType::checkException(status);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dispose()
|
||||
{
|
||||
if (cloopVTable->version < 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
static_cast<VTable*>(this->cloopVTable)->dispose(this);
|
||||
}
|
||||
};
|
||||
|
||||
#define FIREBIRD_IKEY_HOLDER_PLUGIN_VERSION 5u
|
||||
@ -14395,6 +14423,8 @@ namespace Firebird
|
||||
{
|
||||
this->version = Base::VERSION;
|
||||
this->callback = &Name::cloopcallbackDispatcher;
|
||||
this->afterAttach = &Name::cloopafterAttachDispatcher;
|
||||
this->dispose = &Name::cloopdisposeDispatcher;
|
||||
}
|
||||
} vTable;
|
||||
|
||||
@ -14413,6 +14443,33 @@ namespace Firebird
|
||||
return static_cast<unsigned>(0);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned CLOOP_CARG cloopafterAttachDispatcher(ICryptKeyCallback* self, IStatus* status, const char* dbName, const IStatus* attStatus) CLOOP_NOEXCEPT
|
||||
{
|
||||
StatusType status2(status);
|
||||
|
||||
try
|
||||
{
|
||||
return static_cast<Name*>(self)->Name::afterAttach(&status2, dbName, attStatus);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
StatusType::catchException(&status2);
|
||||
return static_cast<unsigned>(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopdisposeDispatcher(ICryptKeyCallback* self) CLOOP_NOEXCEPT
|
||||
{
|
||||
try
|
||||
{
|
||||
static_cast<Name*>(self)->Name::dispose();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
StatusType::catchException(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<ICryptKeyCallback> > >
|
||||
@ -14429,6 +14486,13 @@ namespace Firebird
|
||||
}
|
||||
|
||||
virtual unsigned callback(unsigned dataLength, const void* data, unsigned bufferLength, void* buffer) = 0;
|
||||
virtual unsigned afterAttach(StatusType* status, const char* dbName, const IStatus* attStatus)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual void dispose()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Name, typename StatusType, typename Base>
|
||||
|
@ -490,6 +490,8 @@ type
|
||||
IWireCryptPlugin_getSpecificDataPtr = function(this: IWireCryptPlugin; status: IStatus; keyType: PAnsiChar; length: CardinalPtr): BytePtr; cdecl;
|
||||
IWireCryptPlugin_setSpecificDataPtr = procedure(this: IWireCryptPlugin; status: IStatus; keyType: PAnsiChar; length: Cardinal; data: BytePtr); cdecl;
|
||||
ICryptKeyCallback_callbackPtr = function(this: ICryptKeyCallback; dataLength: Cardinal; data: Pointer; bufferLength: Cardinal; buffer: Pointer): Cardinal; cdecl;
|
||||
ICryptKeyCallback_afterAttachPtr = function(this: ICryptKeyCallback; status: IStatus; dbName: PAnsiChar; attStatus: IStatus): Cardinal; cdecl;
|
||||
ICryptKeyCallback_disposePtr = procedure(this: ICryptKeyCallback); cdecl;
|
||||
IKeyHolderPlugin_keyCallbackPtr = function(this: IKeyHolderPlugin; status: IStatus; callback: ICryptKeyCallback): Integer; cdecl;
|
||||
IKeyHolderPlugin_keyHandlePtr = function(this: IKeyHolderPlugin; status: IStatus; keyName: PAnsiChar): ICryptKeyCallback; cdecl;
|
||||
IKeyHolderPlugin_useOnlyOwnKeysPtr = function(this: IKeyHolderPlugin; status: IStatus): Boolean; cdecl;
|
||||
@ -2375,18 +2377,26 @@ type
|
||||
|
||||
CryptKeyCallbackVTable = class(VersionedVTable)
|
||||
callback: ICryptKeyCallback_callbackPtr;
|
||||
afterAttach: ICryptKeyCallback_afterAttachPtr;
|
||||
dispose: ICryptKeyCallback_disposePtr;
|
||||
end;
|
||||
|
||||
ICryptKeyCallback = class(IVersioned)
|
||||
const VERSION = 2;
|
||||
const VERSION = 3;
|
||||
const NO_RETRY = Cardinal(0);
|
||||
const DO_RETRY = Cardinal(1);
|
||||
|
||||
function callback(dataLength: Cardinal; data: Pointer; bufferLength: Cardinal; buffer: Pointer): Cardinal;
|
||||
function afterAttach(status: IStatus; dbName: PAnsiChar; attStatus: IStatus): Cardinal;
|
||||
procedure dispose();
|
||||
end;
|
||||
|
||||
ICryptKeyCallbackImpl = class(ICryptKeyCallback)
|
||||
constructor create;
|
||||
|
||||
function callback(dataLength: Cardinal; data: Pointer; bufferLength: Cardinal; buffer: Pointer): Cardinal; virtual; abstract;
|
||||
function afterAttach(status: IStatus; dbName: PAnsiChar; attStatus: IStatus): Cardinal; virtual;
|
||||
procedure dispose(); virtual;
|
||||
end;
|
||||
|
||||
KeyHolderPluginVTable = class(PluginBaseVTable)
|
||||
@ -8104,6 +8114,27 @@ begin
|
||||
Result := CryptKeyCallbackVTable(vTable).callback(Self, dataLength, data, bufferLength, buffer);
|
||||
end;
|
||||
|
||||
function ICryptKeyCallback.afterAttach(status: IStatus; dbName: PAnsiChar; attStatus: IStatus): Cardinal;
|
||||
begin
|
||||
if (vTable.version < 3) then begin
|
||||
FbException.setVersionError(status, 'ICryptKeyCallback', vTable.version, 3);
|
||||
Result := 0;
|
||||
end
|
||||
else begin
|
||||
Result := CryptKeyCallbackVTable(vTable).afterAttach(Self, status, dbName, attStatus);
|
||||
end;
|
||||
FbException.checkException(status);
|
||||
end;
|
||||
|
||||
procedure ICryptKeyCallback.dispose();
|
||||
begin
|
||||
if (vTable.version < 3) then begin
|
||||
end
|
||||
else begin
|
||||
CryptKeyCallbackVTable(vTable).dispose(Self);
|
||||
end;
|
||||
end;
|
||||
|
||||
function IKeyHolderPlugin.keyCallback(status: IStatus; callback: ICryptKeyCallback): Integer;
|
||||
begin
|
||||
Result := KeyHolderPluginVTable(vTable).keyCallback(Self, status, callback);
|
||||
@ -13432,6 +13463,34 @@ begin
|
||||
end
|
||||
end;
|
||||
|
||||
function ICryptKeyCallbackImpl_afterAttachDispatcher(this: ICryptKeyCallback; status: IStatus; dbName: PAnsiChar; attStatus: IStatus): Cardinal; cdecl;
|
||||
begin
|
||||
Result := 0;
|
||||
try
|
||||
Result := ICryptKeyCallbackImpl(this).afterAttach(status, dbName, attStatus);
|
||||
except
|
||||
on e: Exception do FbException.catchException(status, e);
|
||||
end
|
||||
end;
|
||||
|
||||
function ICryptKeyCallbackImpl.afterAttach(status: IStatus; dbName: PAnsiChar; attStatus: IStatus): Cardinal;
|
||||
begin
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
procedure ICryptKeyCallbackImpl_disposeDispatcher(this: ICryptKeyCallback); cdecl;
|
||||
begin
|
||||
try
|
||||
ICryptKeyCallbackImpl(this).dispose();
|
||||
except
|
||||
on e: Exception do FbException.catchException(nil, e);
|
||||
end
|
||||
end;
|
||||
|
||||
procedure ICryptKeyCallbackImpl.dispose();
|
||||
begin
|
||||
end;
|
||||
|
||||
var
|
||||
ICryptKeyCallbackImpl_vTable: CryptKeyCallbackVTable;
|
||||
|
||||
@ -17517,8 +17576,10 @@ initialization
|
||||
IWireCryptPluginImpl_vTable.setSpecificData := @IWireCryptPluginImpl_setSpecificDataDispatcher;
|
||||
|
||||
ICryptKeyCallbackImpl_vTable := CryptKeyCallbackVTable.create;
|
||||
ICryptKeyCallbackImpl_vTable.version := 2;
|
||||
ICryptKeyCallbackImpl_vTable.version := 3;
|
||||
ICryptKeyCallbackImpl_vTable.callback := @ICryptKeyCallbackImpl_callbackDispatcher;
|
||||
ICryptKeyCallbackImpl_vTable.afterAttach := @ICryptKeyCallbackImpl_afterAttachDispatcher;
|
||||
ICryptKeyCallbackImpl_vTable.dispose := @ICryptKeyCallbackImpl_disposeDispatcher;
|
||||
|
||||
IKeyHolderPluginImpl_vTable := KeyHolderPluginVTable.create;
|
||||
IKeyHolderPluginImpl_vTable.version := 5;
|
||||
|
@ -8393,7 +8393,10 @@ static bool init(CheckStatusWrapper* status, ClntAuthBlock& cBlock, rem_port* po
|
||||
|
||||
port->port_client_crypt_callback = cryptCallback;
|
||||
cBlock.createCryptCallback(&port->port_client_crypt_callback);
|
||||
auto cb = port->port_client_crypt_callback;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
// Make attach packet
|
||||
P_ATCH* attach = &packet->p_atch;
|
||||
packet->p_operation = op;
|
||||
@ -8403,10 +8406,38 @@ static bool init(CheckStatusWrapper* status, ClntAuthBlock& cBlock, rem_port* po
|
||||
attach->p_atch_dpb.cstr_address = dpb.getBuffer();
|
||||
|
||||
send_packet(port, packet);
|
||||
|
||||
try
|
||||
{
|
||||
authReceiveResponse(false, cBlock, port, rdb, status, packet, true);
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
FbLocalStatus stAttach;
|
||||
ex.stuffException(&stAttach);
|
||||
|
||||
const ISC_STATUS* v = stAttach->getErrors();
|
||||
|
||||
if (cb && (fb_utils::containsErrorCode(v, isc_bad_crypt_key) ||
|
||||
fb_utils::containsErrorCode(v, isc_db_crypt_key)) &&
|
||||
(cb->afterAttach(status, file_name.c_str(), &stAttach) == ICryptKeyCallback::DO_RETRY))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
status->init();
|
||||
throw;
|
||||
}
|
||||
|
||||
// response is success
|
||||
if (cb)
|
||||
{
|
||||
cb->afterAttach(status, file_name.c_str(), nullptr);
|
||||
status->init();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
// report primary init error
|
||||
@ -9829,6 +9860,14 @@ Firebird::ICryptKeyCallback* ClntAuthBlock::ClientCrypt::create(const Config* co
|
||||
|
||||
unsigned ClntAuthBlock::ClientCrypt::callback(unsigned dlen, const void* data, unsigned blen, void* buffer)
|
||||
{
|
||||
// if we have a retry iface - use it
|
||||
if (afterIface)
|
||||
{
|
||||
unsigned retlen = afterIface->callback(dlen, data, blen, buffer);
|
||||
HANDSHAKE_DEBUG(fprintf(stderr, "Iface %p returned %d\n", currentIface, retlen));
|
||||
return retlen;
|
||||
}
|
||||
|
||||
HANDSHAKE_DEBUG(fprintf(stderr, "dlen=%d blen=%d\n", dlen, blen));
|
||||
|
||||
int loop = 0;
|
||||
@ -9854,10 +9893,14 @@ unsigned ClntAuthBlock::ClientCrypt::callback(unsigned dlen, const void* data, u
|
||||
unsigned retlen = currentIface->callback(dlen, data, blen, buffer);
|
||||
HANDSHAKE_DEBUG(fprintf(stderr, "Iface %p returned %d\n", currentIface, retlen));
|
||||
if (retlen)
|
||||
{
|
||||
triedPlugins.add(pluginItr);
|
||||
return retlen;
|
||||
}
|
||||
}
|
||||
|
||||
// no success with iface - clear it
|
||||
currentIface->dispose();
|
||||
// appropriate data structures to be released by plugin cleanup code
|
||||
currentIface = nullptr;
|
||||
}
|
||||
@ -9870,3 +9913,48 @@ unsigned ClntAuthBlock::ClientCrypt::callback(unsigned dlen, const void* data, u
|
||||
// no luck with suggested data
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned ClntAuthBlock::ClientCrypt::afterAttach(CheckStatusWrapper* st, const char* dbName, const IStatus* attStatus)
|
||||
{
|
||||
while (triedPlugins.hasData())
|
||||
{
|
||||
if (afterIface)
|
||||
{
|
||||
auto rc = afterIface->afterAttach(st, dbName, attStatus);
|
||||
if (attStatus && (rc == NO_RETRY))
|
||||
{
|
||||
afterIface->dispose();
|
||||
afterIface = nullptr;
|
||||
triedPlugins.remove();
|
||||
continue;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
FbLocalStatus st;
|
||||
afterIface = triedPlugins.get()->chainHandle(&st);
|
||||
check(&st, isc_interface_version_too_old);
|
||||
fb_assert(afterIface);
|
||||
if (!afterIface)
|
||||
triedPlugins.remove();
|
||||
}
|
||||
}
|
||||
|
||||
return NO_RETRY;
|
||||
}
|
||||
|
||||
void ClntAuthBlock::ClientCrypt::destroy()
|
||||
{
|
||||
if (currentIface)
|
||||
{
|
||||
currentIface->dispose();
|
||||
currentIface = nullptr;
|
||||
}
|
||||
|
||||
if (afterIface)
|
||||
{
|
||||
afterIface->dispose();
|
||||
afterIface = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -712,6 +712,7 @@ public:
|
||||
virtual void wakeup(unsigned int length, const void* data) = 0;
|
||||
virtual Firebird::ICryptKeyCallback* getInterface() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual void destroy() = 0;
|
||||
};
|
||||
|
||||
// CryptKey implementation
|
||||
@ -859,21 +860,76 @@ private:
|
||||
unsigned nextKey; // First key to be analyzed
|
||||
|
||||
class ClientCrypt final :
|
||||
public Firebird::VersionedIface<Firebird::ICryptKeyCallbackImpl<ClientCrypt, Firebird::CheckStatusWrapper> >
|
||||
public Firebird::VersionedIface<Firebird::ICryptKeyCallbackImpl<ClientCrypt, Firebird::CheckStatusWrapper> >,
|
||||
public Firebird::GlobalStorage
|
||||
{
|
||||
public:
|
||||
ClientCrypt()
|
||||
: pluginItr(Firebird::IPluginManager::TYPE_KEY_HOLDER, "NoDefault"), currentIface(nullptr)
|
||||
: pluginItr(Firebird::IPluginManager::TYPE_KEY_HOLDER, "NoDefault"),
|
||||
currentIface(nullptr), afterIface(nullptr),
|
||||
triedPlugins(getPool())
|
||||
{ }
|
||||
|
||||
~ClientCrypt()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
Firebird::ICryptKeyCallback* create(const Firebird::Config* conf);
|
||||
|
||||
// Firebird::ICryptKeyCallback implementation
|
||||
unsigned callback(unsigned dataLength, const void* data, unsigned bufferLength, void* buffer);
|
||||
unsigned afterAttach(Firebird::CheckStatusWrapper* st, const char* dbName, const Firebird::IStatus* attStatus);
|
||||
void destroy();
|
||||
|
||||
private:
|
||||
Firebird::GetPlugins<Firebird::IKeyHolderPlugin> pluginItr;
|
||||
typedef Firebird::GetPlugins<Firebird::IKeyHolderPlugin> KeyHolderItr;
|
||||
KeyHolderItr pluginItr;
|
||||
Firebird::ICryptKeyCallback* currentIface;
|
||||
Firebird::ICryptKeyCallback* afterIface;
|
||||
|
||||
class TriedPlugins
|
||||
{
|
||||
typedef Firebird::Pair<Firebird::Left<Firebird::PathName, Firebird::IKeyHolderPlugin*> > TriedPlugin;
|
||||
Firebird::ObjectsArray<TriedPlugin> data;
|
||||
|
||||
public:
|
||||
TriedPlugins(MemoryPool& p)
|
||||
: data(p)
|
||||
{ }
|
||||
|
||||
void add(KeyHolderItr& itr)
|
||||
{
|
||||
for (auto& p : data)
|
||||
{
|
||||
if (p.first == itr.name())
|
||||
return;
|
||||
}
|
||||
|
||||
TriedPlugin tp(itr.name(), itr.plugin());
|
||||
data.add(tp);
|
||||
tp.second->addRef();
|
||||
}
|
||||
|
||||
void remove()
|
||||
{
|
||||
fb_assert(data.hasData());
|
||||
data[0].second->release();
|
||||
data.remove(0);
|
||||
}
|
||||
|
||||
bool hasData() const
|
||||
{
|
||||
return data.hasData();
|
||||
}
|
||||
|
||||
Firebird::IKeyHolderPlugin* get()
|
||||
{
|
||||
return data[0].second;
|
||||
}
|
||||
};
|
||||
|
||||
TriedPlugins triedPlugins;
|
||||
};
|
||||
ClientCrypt clientCrypt;
|
||||
Firebird::ICryptKeyCallback** createdInterface;
|
||||
|
@ -114,33 +114,6 @@ public:
|
||||
: port(prt), replyLength(0), replyData(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 || port->port_type != rem_port::INET)
|
||||
return 0;
|
||||
|
||||
Reference r(*port);
|
||||
|
||||
replyData = buffer;
|
||||
replyLength = 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 replyLength;
|
||||
}
|
||||
|
||||
void wakeup(unsigned int wakeLength, const void* wakeData)
|
||||
{
|
||||
if (replyLength > wakeLength)
|
||||
@ -167,6 +140,34 @@ public:
|
||||
return stopped;
|
||||
}
|
||||
|
||||
// ICryptKeyCallback implementation
|
||||
unsigned int callback(unsigned int dataLength, const void* data,
|
||||
unsigned int bufferLength, void* buffer) override
|
||||
{
|
||||
if (stopped)
|
||||
return 0;
|
||||
|
||||
if (port->port_protocol < PROTOCOL_VERSION13 || port->port_type != rem_port::INET)
|
||||
return 0;
|
||||
|
||||
Reference r(*port);
|
||||
|
||||
replyData = buffer;
|
||||
replyLength = 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 replyLength;
|
||||
}
|
||||
|
||||
private:
|
||||
rem_port* port;
|
||||
Semaphore sem;
|
||||
@ -187,29 +188,11 @@ public:
|
||||
|
||||
~CryptKeyCallback()
|
||||
{
|
||||
dispose();
|
||||
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);
|
||||
loadClientKey();
|
||||
unsigned rc = keyCallback ?
|
||||
keyCallback->callback(dataLength, data, bufferLength, buffer) :
|
||||
// use legacy behavior if holders do wish to accept keys from client
|
||||
networkCallback.callback(dataLength, data, bufferLength, buffer);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void loadClientKey()
|
||||
{
|
||||
if (keyCallback)
|
||||
@ -256,6 +239,43 @@ public:
|
||||
networkCallback.stop();
|
||||
}
|
||||
|
||||
// ICryptKeyCallback implementation
|
||||
unsigned int callback(unsigned int dataLength, const void* data,
|
||||
unsigned int bufferLength, void* buffer) override
|
||||
{
|
||||
if (keyCallback)
|
||||
return keyCallback->callback(dataLength, data, bufferLength, buffer);
|
||||
|
||||
if (networkCallback.isStopped())
|
||||
return 0;
|
||||
|
||||
Reference r(*port);
|
||||
loadClientKey();
|
||||
unsigned rc = keyCallback ?
|
||||
keyCallback->callback(dataLength, data, bufferLength, buffer) :
|
||||
// use legacy behavior if holders do wish to accept keys from client
|
||||
networkCallback.callback(dataLength, data, bufferLength, buffer);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
unsigned afterAttach(Firebird::CheckStatusWrapper* st, const char* dbName,
|
||||
const Firebird::IStatus* attStatus) override
|
||||
{
|
||||
return NO_RETRY;
|
||||
}
|
||||
|
||||
void dispose() override
|
||||
{
|
||||
if (keyCallback)
|
||||
{
|
||||
LocalStatus ls;
|
||||
CheckStatusWrapper st(&ls);
|
||||
keyCallback->dispose();
|
||||
keyCallback = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
rem_port* port;
|
||||
NetworkCallback networkCallback;
|
||||
@ -273,22 +293,27 @@ public:
|
||||
~ServerCallback()
|
||||
{ }
|
||||
|
||||
void wakeup(unsigned int length, const void* data)
|
||||
void wakeup(unsigned int length, const void* data) override
|
||||
{
|
||||
cryptCallback.wakeup(length, data);
|
||||
}
|
||||
|
||||
ICryptKeyCallback* getInterface()
|
||||
ICryptKeyCallback* getInterface() override
|
||||
{
|
||||
cryptCallback.loadClientKey();
|
||||
return &cryptCallback;
|
||||
}
|
||||
|
||||
void stop()
|
||||
void stop() override
|
||||
{
|
||||
cryptCallback.stop();
|
||||
}
|
||||
|
||||
void destroy() override
|
||||
{
|
||||
cryptCallback.dispose();
|
||||
}
|
||||
|
||||
private:
|
||||
CryptKeyCallback cryptCallback;
|
||||
};
|
||||
@ -2494,6 +2519,7 @@ void DatabaseAuth::accept(PACKET* send, Auth::WriterImplementation* authBlock)
|
||||
CheckStatusWrapper status_vector(&ls);
|
||||
|
||||
fb_assert(authPort->port_server_crypt_callback);
|
||||
authPort->port_server_crypt_callback->destroy();
|
||||
provider->setDbCryptCallback(&status_vector, authPort->port_server_crypt_callback->getInterface());
|
||||
|
||||
if (!(status_vector.getState() & Firebird::IStatus::STATE_ERRORS))
|
||||
@ -2512,12 +2538,13 @@ void DatabaseAuth::accept(PACKET* send, Auth::WriterImplementation* authBlock)
|
||||
#endif
|
||||
rdb->rdb_port = authPort;
|
||||
rdb->rdb_iface = iface;
|
||||
|
||||
authPort->port_server_crypt_callback->stop();
|
||||
}
|
||||
}
|
||||
|
||||
CSTRING* const s = &send->p_resp.p_resp_data;
|
||||
authPort->extractNewKeys(s);
|
||||
authPort->port_server_crypt_callback->stop();
|
||||
authPort->send_response(send, 0, s->cstr_length, &status_vector, false);
|
||||
}
|
||||
|
||||
@ -6214,6 +6241,7 @@ ISC_STATUS rem_port::service_attach(const char* service_name,
|
||||
CheckStatusWrapper status_vector(&ls);
|
||||
|
||||
fb_assert(port_server_crypt_callback);
|
||||
port_server_crypt_callback->destroy();
|
||||
provider->setDbCryptCallback(&status_vector, port_server_crypt_callback->getInterface());
|
||||
|
||||
if (!(status_vector.getState() & Firebird::IStatus::STATE_ERRORS))
|
||||
@ -6233,9 +6261,10 @@ ISC_STATUS rem_port::service_attach(const char* service_name,
|
||||
rdb->rdb_port = this;
|
||||
Svc* svc = rdb->rdb_svc = FB_NEW Svc;
|
||||
svc->svc_iface = iface;
|
||||
}
|
||||
}
|
||||
|
||||
port_server_crypt_callback->stop();
|
||||
}
|
||||
}
|
||||
|
||||
return this->send_response(sendL, 0, sendL->p_resp.p_resp_data.cstr_length, &status_vector,
|
||||
false);
|
||||
|
Loading…
Reference in New Issue
Block a user