Skip to content

Commit 658abd2

Browse files
committed
Fixed #8429: Segfault when already destroyed callback interface is used
1 parent d846342 commit 658abd2

File tree

15 files changed

+454
-33
lines changed

15 files changed

+454
-33
lines changed

doc/Using_OO_API.html

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3629,13 +3629,24 @@ <h1><font size="4" style="font-size: 14pt">Database encryption
36293629
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DO_RETRY -
36303630
retry attach (ignored when function was called without attStatus).</font></p>
36313631
</font></p>
3632+
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">
3633+
int getHashLength(StatusType* status) - returns length of hash of the keys provided by interface.
3634+
Hash is needed to let caller compare interfaces for equality. Empty (no keys)
3635+
interface should return hash length equal to zero.
3636+
</font></p>
3637+
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">
3638+
void getHashData(StatusType* status, void* hash) - places hash of the keys provided by interface
3639+
into memory location defined by parameter <i>hash</i>. Should copy exact number of bytes
3640+
returned by getHashLength() call. Hash algorithm is chosen by plugin author
3641+
(in year 2024 SHA256 appears reasonable choice).
3642+
</font></p>
36323643
</ol>
36333644
<p style="margin-bottom: 0cm"><br/>
36343645

36353646
</p>
36363647
<p style="margin-bottom: 0cm"><a name="DbCryptInfo"></a><font size="4" style="font-size: 14pt">DbCryptInfo
36373648
interface is passed to DbCryptPlugin by engine. Plugin may save this
3638-
interface and use when needed to obtain additional informatio about
3649+
interface and use when needed to obtain additional information about
36393650
database.</font></p>
36403651
<ol>
36413652
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const

examples/dbcrypt/CryptApplication.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,28 @@ class CryptKey : public ICryptKeyCallbackImpl<CryptKey, CheckStatusWrapper>
3636
{
3737
if (length > 0 && buffer)
3838
{
39-
char k = 0x5a;
4039
memcpy(buffer, &k, 1);
4140
fprintf(stderr, "\nTransfered key to server\n");
4241
}
4342
return 1;
4443
}
44+
45+
int getHashLength(Firebird::CheckStatusWrapper* status) override
46+
{
47+
return 1;
48+
}
49+
50+
void getHashData(Firebird::CheckStatusWrapper* status, void* h) override
51+
{
52+
memcpy(h, &k, 1);
53+
}
54+
55+
private:
56+
static const char k;
4557
};
4658

59+
const char CryptKey::k = 0x5a;
60+
4761
class App
4862
{
4963
public:

examples/dbcrypt/CryptKeyHolder.cpp

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class CryptKeyHolder : public IKeyHolderPluginImpl<CryptKeyHolder, CheckStatusWr
7070
public:
7171
explicit CryptKeyHolder(IPluginConfig* cnf) noexcept
7272
: callbackInterface(this), named(NULL), tempStatus(master->getStatus()),
73-
config(cnf), key(0), owner(NULL)
73+
config(cnf), key(0), init(false), owner(NULL)
7474
{
7575
config->addRef();
7676
}
@@ -111,10 +111,13 @@ class CryptKeyHolder : public IKeyHolderPluginImpl<CryptKeyHolder, CheckStatusWr
111111
return owner;
112112
}
113113

114-
ISC_UCHAR getKey()
114+
const ISC_UCHAR& getKey()
115115
{
116-
if (!key)
116+
if (!init)
117+
{
117118
keyCallback(&tempStatus, NULL);
119+
init = true;
120+
}
118121

119122
return key;
120123
}
@@ -140,7 +143,7 @@ class CryptKeyHolder : public IKeyHolderPluginImpl<CryptKeyHolder, CheckStatusWr
140143

141144
unsigned int callback(unsigned int, const void*, unsigned int length, void* buffer) override
142145
{
143-
ISC_UCHAR k = holder->getKey();
146+
const ISC_UCHAR& k = holder->getKey();
144147
if (!k)
145148
{
146149
return 0;
@@ -153,6 +156,36 @@ class CryptKeyHolder : public IKeyHolderPluginImpl<CryptKeyHolder, CheckStatusWr
153156
return 1;
154157
}
155158

159+
int getHashLength(Firebird::CheckStatusWrapper* status) override
160+
{
161+
const ISC_UCHAR& k = holder->getKey();
162+
if (!k)
163+
{
164+
ISC_STATUS err[] = {isc_arg_gds, isc_wish_list};
165+
status->setErrors2(2, err);
166+
167+
return -1;
168+
}
169+
170+
return 1;
171+
}
172+
173+
void getHashData(Firebird::CheckStatusWrapper* status, void* h) override
174+
{
175+
// here key value is returned by hash function as is
176+
// do not do it in production - use some hash function
177+
const ISC_UCHAR& k = holder->getKey();
178+
if (!k)
179+
{
180+
ISC_STATUS err[] = {isc_arg_gds, isc_wish_list};
181+
status->setErrors2(2, err);
182+
183+
return;
184+
}
185+
186+
memcpy(h, &k, 1);
187+
}
188+
156189
private:
157190
CryptKeyHolder* holder;
158191
};
@@ -173,6 +206,18 @@ class CryptKeyHolder : public IKeyHolderPluginImpl<CryptKeyHolder, CheckStatusWr
173206
return 1;
174207
}
175208

209+
int getHashLength(Firebird::CheckStatusWrapper* status) override
210+
{
211+
return 1;
212+
}
213+
214+
void getHashData(Firebird::CheckStatusWrapper* status, void* h) override
215+
{
216+
// here key value is returned by hash function as is
217+
// do not do it in production - use some hash function
218+
memcpy(h, &key, 1);
219+
}
220+
176221
~NamedCallback()
177222
{
178223
delete next;
@@ -189,6 +234,7 @@ class CryptKeyHolder : public IKeyHolderPluginImpl<CryptKeyHolder, CheckStatusWr
189234

190235
IPluginConfig* config;
191236
ISC_UCHAR key;
237+
bool init;
192238

193239
std::atomic_int refCounter;
194240
IReferenceCounted* owner;

src/include/firebird/FirebirdInterface.idl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,7 @@ interface CryptKeyCallback : Versioned
943943
uint callback(uint dataLength, const void* data,
944944
uint bufferLength, void* buffer);
945945

946-
version: // 6.0
946+
version: // 6.0, 5.0.2, 4.0.6
947947
// Result returned by afterAttach()
948948
const uint NO_RETRY = 0; // Returned by old plugins & stub
949949
const uint DO_RETRY = 1;
@@ -957,6 +957,12 @@ version: // 6.0
957957
// interface not needed any more
958958
[stub defaultAction]
959959
void dispose();
960+
961+
version: // 6.0, 5.0.2, 4.0.6
962+
// Produce something to be compared with other interface instance
963+
[notImplemented(-1)]
964+
int getHashLength(Status status);
965+
void getHashData(Status status, void* hash);
960966
}
961967

962968

src/include/firebird/IdlFbInterfaces.h

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3892,7 +3892,7 @@ namespace Firebird
38923892
}
38933893
};
38943894

3895-
#define FIREBIRD_ICRYPT_KEY_CALLBACK_VERSION 3u
3895+
#define FIREBIRD_ICRYPT_KEY_CALLBACK_VERSION 4u
38963896

38973897
class ICryptKeyCallback : public IVersioned
38983898
{
@@ -3902,6 +3902,8 @@ namespace Firebird
39023902
unsigned (CLOOP_CARG *callback)(ICryptKeyCallback* self, unsigned dataLength, const void* data, unsigned bufferLength, void* buffer) CLOOP_NOEXCEPT;
39033903
unsigned (CLOOP_CARG *afterAttach)(ICryptKeyCallback* self, IStatus* status, const char* dbName, const IStatus* attStatus) CLOOP_NOEXCEPT;
39043904
void (CLOOP_CARG *dispose)(ICryptKeyCallback* self) CLOOP_NOEXCEPT;
3905+
int (CLOOP_CARG *getHashLength)(ICryptKeyCallback* self, IStatus* status) CLOOP_NOEXCEPT;
3906+
void (CLOOP_CARG *getHashData)(ICryptKeyCallback* self, IStatus* status, void* hash) CLOOP_NOEXCEPT;
39053907
};
39063908

39073909
protected:
@@ -3948,6 +3950,33 @@ namespace Firebird
39483950
}
39493951
static_cast<VTable*>(this->cloopVTable)->dispose(this);
39503952
}
3953+
3954+
template <typename StatusType> int getHashLength(StatusType* status)
3955+
{
3956+
if (cloopVTable->version < 4)
3957+
{
3958+
StatusType::setVersionError(status, "ICryptKeyCallback", cloopVTable->version, 4);
3959+
StatusType::checkException(status);
3960+
return -1;
3961+
}
3962+
StatusType::clearException(status);
3963+
int ret = static_cast<VTable*>(this->cloopVTable)->getHashLength(this, status);
3964+
StatusType::checkException(status);
3965+
return ret;
3966+
}
3967+
3968+
template <typename StatusType> void getHashData(StatusType* status, void* hash)
3969+
{
3970+
if (cloopVTable->version < 4)
3971+
{
3972+
StatusType::setVersionError(status, "ICryptKeyCallback", cloopVTable->version, 4);
3973+
StatusType::checkException(status);
3974+
return;
3975+
}
3976+
StatusType::clearException(status);
3977+
static_cast<VTable*>(this->cloopVTable)->getHashData(this, status, hash);
3978+
StatusType::checkException(status);
3979+
}
39513980
};
39523981

39533982
#define FIREBIRD_IKEY_HOLDER_PLUGIN_VERSION 5u
@@ -14426,6 +14455,8 @@ namespace Firebird
1442614455
this->callback = &Name::cloopcallbackDispatcher;
1442714456
this->afterAttach = &Name::cloopafterAttachDispatcher;
1442814457
this->dispose = &Name::cloopdisposeDispatcher;
14458+
this->getHashLength = &Name::cloopgetHashLengthDispatcher;
14459+
this->getHashData = &Name::cloopgetHashDataDispatcher;
1442914460
}
1443014461
} vTable;
1443114462

@@ -14471,6 +14502,35 @@ namespace Firebird
1447114502
StatusType::catchException(0);
1447214503
}
1447314504
}
14505+
14506+
static int CLOOP_CARG cloopgetHashLengthDispatcher(ICryptKeyCallback* self, IStatus* status) CLOOP_NOEXCEPT
14507+
{
14508+
StatusType status2(status);
14509+
14510+
try
14511+
{
14512+
return static_cast<Name*>(self)->Name::getHashLength(&status2);
14513+
}
14514+
catch (...)
14515+
{
14516+
StatusType::catchException(&status2);
14517+
return static_cast<int>(0);
14518+
}
14519+
}
14520+
14521+
static void CLOOP_CARG cloopgetHashDataDispatcher(ICryptKeyCallback* self, IStatus* status, void* hash) CLOOP_NOEXCEPT
14522+
{
14523+
StatusType status2(status);
14524+
14525+
try
14526+
{
14527+
static_cast<Name*>(self)->Name::getHashData(&status2, hash);
14528+
}
14529+
catch (...)
14530+
{
14531+
StatusType::catchException(&status2);
14532+
}
14533+
}
1447414534
};
1447514535

1447614536
template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<ICryptKeyCallback> > >
@@ -14494,6 +14554,8 @@ namespace Firebird
1449414554
virtual void dispose()
1449514555
{
1449614556
}
14557+
virtual int getHashLength(StatusType* status) = 0;
14558+
virtual void getHashData(StatusType* status, void* hash) = 0;
1449714559
};
1449814560

1449914561
template <typename Name, typename StatusType, typename Base>

src/include/gen/Firebird.pas

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,8 @@ ISC_TIMESTAMP_TZ_EX = record
492492
ICryptKeyCallback_callbackPtr = function(this: ICryptKeyCallback; dataLength: Cardinal; data: Pointer; bufferLength: Cardinal; buffer: Pointer): Cardinal; cdecl;
493493
ICryptKeyCallback_afterAttachPtr = function(this: ICryptKeyCallback; status: IStatus; dbName: PAnsiChar; attStatus: IStatus): Cardinal; cdecl;
494494
ICryptKeyCallback_disposePtr = procedure(this: ICryptKeyCallback); cdecl;
495+
ICryptKeyCallback_getHashLengthPtr = function(this: ICryptKeyCallback; status: IStatus): Integer; cdecl;
496+
ICryptKeyCallback_getHashDataPtr = procedure(this: ICryptKeyCallback; status: IStatus; hash: Pointer); cdecl;
495497
IKeyHolderPlugin_keyCallbackPtr = function(this: IKeyHolderPlugin; status: IStatus; callback: ICryptKeyCallback): Integer; cdecl;
496498
IKeyHolderPlugin_keyHandlePtr = function(this: IKeyHolderPlugin; status: IStatus; keyName: PAnsiChar): ICryptKeyCallback; cdecl;
497499
IKeyHolderPlugin_useOnlyOwnKeysPtr = function(this: IKeyHolderPlugin; status: IStatus): Boolean; cdecl;
@@ -2380,16 +2382,20 @@ CryptKeyCallbackVTable = class(VersionedVTable)
23802382
callback: ICryptKeyCallback_callbackPtr;
23812383
afterAttach: ICryptKeyCallback_afterAttachPtr;
23822384
dispose: ICryptKeyCallback_disposePtr;
2385+
getHashLength: ICryptKeyCallback_getHashLengthPtr;
2386+
getHashData: ICryptKeyCallback_getHashDataPtr;
23832387
end;
23842388

23852389
ICryptKeyCallback = class(IVersioned)
2386-
const VERSION = 3;
2390+
const VERSION = 4;
23872391
const NO_RETRY = Cardinal(0);
23882392
const DO_RETRY = Cardinal(1);
23892393

23902394
function callback(dataLength: Cardinal; data: Pointer; bufferLength: Cardinal; buffer: Pointer): Cardinal;
23912395
function afterAttach(status: IStatus; dbName: PAnsiChar; attStatus: IStatus): Cardinal;
23922396
procedure dispose();
2397+
function getHashLength(status: IStatus): Integer;
2398+
procedure getHashData(status: IStatus; hash: Pointer);
23932399
end;
23942400

23952401
ICryptKeyCallbackImpl = class(ICryptKeyCallback)
@@ -2398,6 +2404,8 @@ ICryptKeyCallbackImpl = class(ICryptKeyCallback)
23982404
function callback(dataLength: Cardinal; data: Pointer; bufferLength: Cardinal; buffer: Pointer): Cardinal; virtual; abstract;
23992405
function afterAttach(status: IStatus; dbName: PAnsiChar; attStatus: IStatus): Cardinal; virtual;
24002406
procedure dispose(); virtual;
2407+
function getHashLength(status: IStatus): Integer; virtual; abstract;
2408+
procedure getHashData(status: IStatus; hash: Pointer); virtual; abstract;
24012409
end;
24022410

24032411
KeyHolderPluginVTable = class(PluginBaseVTable)
@@ -8151,6 +8159,29 @@ procedure ICryptKeyCallback.dispose();
81518159
end;
81528160
end;
81538161

8162+
function ICryptKeyCallback.getHashLength(status: IStatus): Integer;
8163+
begin
8164+
if (vTable.version < 4) then begin
8165+
FbException.setVersionError(status, 'ICryptKeyCallback', vTable.version, 4);
8166+
Result := -1;
8167+
end
8168+
else begin
8169+
Result := CryptKeyCallbackVTable(vTable).getHashLength(Self, status);
8170+
end;
8171+
FbException.checkException(status);
8172+
end;
8173+
8174+
procedure ICryptKeyCallback.getHashData(status: IStatus; hash: Pointer);
8175+
begin
8176+
if (vTable.version < 4) then begin
8177+
FbException.setVersionError(status, 'ICryptKeyCallback', vTable.version, 4);
8178+
end
8179+
else begin
8180+
CryptKeyCallbackVTable(vTable).getHashData(Self, status, hash);
8181+
end;
8182+
FbException.checkException(status);
8183+
end;
8184+
81548185
function IKeyHolderPlugin.keyCallback(status: IStatus; callback: ICryptKeyCallback): Integer;
81558186
begin
81568187
Result := KeyHolderPluginVTable(vTable).keyCallback(Self, status, callback);
@@ -13507,6 +13538,25 @@ procedure ICryptKeyCallbackImpl.dispose();
1350713538
begin
1350813539
end;
1350913540

13541+
function ICryptKeyCallbackImpl_getHashLengthDispatcher(this: ICryptKeyCallback; status: IStatus): Integer; cdecl;
13542+
begin
13543+
Result := 0;
13544+
try
13545+
Result := ICryptKeyCallbackImpl(this).getHashLength(status);
13546+
except
13547+
on e: Exception do FbException.catchException(status, e);
13548+
end
13549+
end;
13550+
13551+
procedure ICryptKeyCallbackImpl_getHashDataDispatcher(this: ICryptKeyCallback; status: IStatus; hash: Pointer); cdecl;
13552+
begin
13553+
try
13554+
ICryptKeyCallbackImpl(this).getHashData(status, hash);
13555+
except
13556+
on e: Exception do FbException.catchException(status, e);
13557+
end
13558+
end;
13559+
1351013560
var
1351113561
ICryptKeyCallbackImpl_vTable: CryptKeyCallbackVTable;
1351213562

@@ -17592,10 +17642,12 @@ initialization
1759217642
IWireCryptPluginImpl_vTable.setSpecificData := @IWireCryptPluginImpl_setSpecificDataDispatcher;
1759317643

1759417644
ICryptKeyCallbackImpl_vTable := CryptKeyCallbackVTable.create;
17595-
ICryptKeyCallbackImpl_vTable.version := 3;
17645+
ICryptKeyCallbackImpl_vTable.version := 4;
1759617646
ICryptKeyCallbackImpl_vTable.callback := @ICryptKeyCallbackImpl_callbackDispatcher;
1759717647
ICryptKeyCallbackImpl_vTable.afterAttach := @ICryptKeyCallbackImpl_afterAttachDispatcher;
1759817648
ICryptKeyCallbackImpl_vTable.dispose := @ICryptKeyCallbackImpl_disposeDispatcher;
17649+
ICryptKeyCallbackImpl_vTable.getHashLength := @ICryptKeyCallbackImpl_getHashLengthDispatcher;
17650+
ICryptKeyCallbackImpl_vTable.getHashData := @ICryptKeyCallbackImpl_getHashDataDispatcher;
1759917651

1760017652
IKeyHolderPluginImpl_vTable := KeyHolderPluginVTable.create;
1760117653
IKeyHolderPluginImpl_vTable.version := 5;

0 commit comments

Comments
 (0)