|
From: <ale...@us...> - 2016-02-03 13:20:44
|
Revision: 62916
http://sourceforge.net/p/firebird/code/62916
Author: alexpeshkoff
Date: 2016-02-03 13:20:41 +0000 (Wed, 03 Feb 2016)
Log Message:
-----------
Implemented CORE-5100: Improve control over database crypt keys
Modified Paths:
--------------
firebird/trunk/examples/dbcrypt/CryptKeyHolder.cpp
firebird/trunk/examples/dbcrypt/DbCrypt.cpp
firebird/trunk/lang_helpers/gds_codes.ftn
firebird/trunk/lang_helpers/gds_codes.pas
firebird/trunk/src/common/classes/ClumpletReader.cpp
firebird/trunk/src/common/classes/ClumpletReader.h
firebird/trunk/src/common/classes/ClumpletWriter.cpp
firebird/trunk/src/common/classes/ClumpletWriter.h
firebird/trunk/src/dsql/DdlNodes.epp
firebird/trunk/src/dsql/DdlNodes.h
firebird/trunk/src/dsql/parse.y
firebird/trunk/src/include/firebird/FirebirdInterface.idl
firebird/trunk/src/include/firebird/IdlFbInterfaces.h
firebird/trunk/src/include/gen/codetext.h
firebird/trunk/src/include/gen/iberror.h
firebird/trunk/src/include/gen/msgs.h
firebird/trunk/src/include/gen/sql_code.h
firebird/trunk/src/include/gen/sql_state.h
firebird/trunk/src/jrd/CryptoManager.cpp
firebird/trunk/src/jrd/CryptoManager.h
firebird/trunk/src/jrd/ods.h
firebird/trunk/src/msgs/facilities2.sql
firebird/trunk/src/msgs/messages2.sql
firebird/trunk/src/msgs/system_errors2.sql
firebird/trunk/src/utilities/gstat/ppg.cpp
Modified: firebird/trunk/examples/dbcrypt/CryptKeyHolder.cpp
===================================================================
--- firebird/trunk/examples/dbcrypt/CryptKeyHolder.cpp 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/examples/dbcrypt/CryptKeyHolder.cpp 2016-02-03 13:20:41 UTC (rev 62916)
@@ -85,7 +85,7 @@
{
public:
explicit CryptKeyHolder(IPluginConfig* cnf) throw()
- : callbackInterface(this), config(cnf), key(0), owner(NULL)
+ : callbackInterface(this), named(NULL), config(cnf), key(0), owner(NULL)
{
config->addRef();
}
@@ -139,12 +139,12 @@
{
public:
explicit CallbackInterface(CryptKeyHolder* p)
- : parent(p)
+ : holder(p)
{ }
unsigned int callback(unsigned int, const void*, unsigned int length, void* buffer)
{
- UCHAR k = parent->getKey();
+ UCHAR k = holder->getKey();
if (!k)
{
return 0;
@@ -157,16 +157,38 @@
return 1;
}
- IPluginModule* getModule()
+ private:
+ CryptKeyHolder* holder;
+ };
+
+ class NamedCallback : public ICryptKeyCallbackImpl<NamedCallback, CheckStatusWrapper>
+ {
+ public:
+ NamedCallback(NamedCallback *n, const char* nm, UCHAR k)
+ : next(n), key(k)
{
- return &module;
+ strncpy(name, nm, sizeof(name));
+ name[sizeof(name) - 1] = 0;
}
- private:
- CryptKeyHolder* parent;
+ unsigned int callback(unsigned int, const void*, unsigned int length, void* buffer)
+ {
+ memcpy(buffer, &key, 1);
+ return 1;
+ }
+
+ ~NamedCallback()
+ {
+ delete next;
+ }
+
+ char name[32];
+ NamedCallback* next;
+ UCHAR key;
};
CallbackInterface callbackInterface;
+ NamedCallback *named;
IPluginConfig* config;
UCHAR key;
@@ -174,18 +196,21 @@
AtomicCounter refCounter;
IReferenceCounted* owner;
- void noKeyError(CheckStatusWrapper* status);
+ IConfigEntry* getEntry(CheckStatusWrapper* status, const char* entryName);
};
-void CryptKeyHolder::noKeyError(CheckStatusWrapper* status)
+IConfigEntry* CryptKeyHolder::getEntry(CheckStatusWrapper* status, const char* entryName)
{
- ISC_STATUS_ARRAY vector;
- vector[0] = isc_arg_gds;
- vector[1] = isc_random;
- vector[2] = isc_arg_string;
- vector[3] = (ISC_STATUS) "Key not set";
- vector[4] = isc_arg_end;
- status->setErrors(vector);
+ IConfig* def = config->getDefaultConfig(status);
+ if (status->getState() & Firebird::IStatus::STATE_ERRORS)
+ return NULL;
+
+ IConfigEntry* confEntry = def->find(status, entryName);
+ def->release();
+ if (status->getState() & Firebird::IStatus::STATE_ERRORS)
+ return NULL;
+
+ return confEntry;
}
int CryptKeyHolder::keyCallback(CheckStatusWrapper* status, ICryptKeyCallback* callback)
@@ -195,15 +220,8 @@
if (key != 0)
return 1;
- IConfig* def = config->getDefaultConfig(status);
- if (status->getState() & Firebird::IStatus::STATE_ERRORS)
- return 1;
+ IConfigEntry* confEntry = getEntry(status, "Auto");
- IConfigEntry* confEntry = def->find(status, "Auto");
- def->release();
- if (status->getState() & Firebird::IStatus::STATE_ERRORS)
- return 1;
-
if (confEntry)
{
FB_BOOLEAN b = confEntry->getBoolValue();
@@ -226,12 +244,33 @@
ICryptKeyCallback* CryptKeyHolder::keyHandle(CheckStatusWrapper* status, const char* keyName)
{
- if (strcmp(keyName, "sample") != 0)
+ if (keyName[0] == 0)
+ return &callbackInterface;
+
+ for (NamedCallback* n = named; n; n = n->next)
{
- return NULL;
+ if (strcmp(keyName, n->name) == 0)
+ return n;
}
- return &callbackInterface;
+ char kn[40];
+ strcpy(kn, "Key");
+ strncat(kn, keyName, sizeof(kn));
+ kn[sizeof(kn) - 1] = 0;
+
+ IConfigEntry* confEntry = getEntry(status, kn);
+ if (confEntry)
+ {
+ UCHAR k = confEntry->getIntValue();
+ confEntry->release();
+ if (k > 0 && k < 256)
+ {
+ named = new NamedCallback(named, keyName, static_cast<UCHAR>(k));
+ return named;
+ }
+ }
+
+ return NULL;
}
class Factory : public IPluginFactoryImpl<Factory, CheckStatusWrapper>
Modified: firebird/trunk/examples/dbcrypt/DbCrypt.cpp
===================================================================
--- firebird/trunk/examples/dbcrypt/DbCrypt.cpp 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/examples/dbcrypt/DbCrypt.cpp 2016-02-03 13:20:41 UTC (rev 62916)
@@ -95,7 +95,8 @@
// ICryptPlugin implementation
void encrypt(CheckStatusWrapper* status, unsigned int length, const void* from, void* to);
void decrypt(CheckStatusWrapper* status, unsigned int length, const void* from, void* to);
- void setKey(CheckStatusWrapper* status, unsigned int length, IKeyHolderPlugin** sources);
+ void setKey(CheckStatusWrapper* status, const char* keyName,
+ unsigned int length, IKeyHolderPlugin** sources);
int release()
{
@@ -129,6 +130,7 @@
private:
IPluginConfig* config;
+ char savedKeyName[32];
UCHAR key;
AtomicCounter refCounter;
@@ -139,11 +141,20 @@
void DbCrypt::noKeyError(CheckStatusWrapper* status)
{
+ char msg[100];
+ strcpy(msg, "Crypt key ");
+ if (savedKeyName[0])
+ {
+ strcat(msg, savedKeyName);
+ strcat(msg, " ");
+ }
+ strcat(msg, "not set");
+
ISC_STATUS_ARRAY vector;
vector[0] = isc_arg_gds;
vector[1] = isc_random;
vector[2] = isc_arg_string;
- vector[3] = (ISC_STATUS)"Key not set";
+ vector[3] = (ISC_STATUS)msg;
vector[4] = isc_arg_end;
status->setErrors(vector);
}
@@ -186,13 +197,17 @@
}
}
-void DbCrypt::setKey(CheckStatusWrapper* status, unsigned int length, IKeyHolderPlugin** sources)
+void DbCrypt::setKey(CheckStatusWrapper* status, const char* keyName,
+ unsigned int length, IKeyHolderPlugin** sources)
{
status->init();
if (key != 0)
return;
+ strncpy(savedKeyName, keyName ? keyName : "", sizeof(savedKeyName));
+ savedKeyName[sizeof(savedKeyName) - 1] = 0;
+
IConfig* def = config->getDefaultConfig(status);
if (status->getState() & Firebird::IStatus::STATE_ERRORS)
return;
@@ -230,7 +245,7 @@
for (unsigned n = 0; n < length; ++n)
{
- ICryptKeyCallback* callback = sources[n]->keyHandle(status, "sample");
+ ICryptKeyCallback* callback = sources[n]->keyHandle(status, savedKeyName);
if (status->getState() & Firebird::IStatus::STATE_ERRORS)
return;
Modified: firebird/trunk/lang_helpers/gds_codes.ftn
===================================================================
--- firebird/trunk/lang_helpers/gds_codes.ftn 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/lang_helpers/gds_codes.ftn 2016-02-03 13:20:41 UTC (rev 62916)
@@ -1626,6 +1626,10 @@
PARAMETER (GDS__login_error = 335545106)
INTEGER*4 GDS__already_opened
PARAMETER (GDS__already_opened = 335545107)
+ INTEGER*4 GDS__bad_crypt_key
+ PARAMETER (GDS__bad_crypt_key = 335545108)
+ INTEGER*4 GDS__encrypt_error
+ PARAMETER (GDS__encrypt_error = 335545109)
INTEGER*4 GDS__gfix_db_name
PARAMETER (GDS__gfix_db_name = 335740929)
INTEGER*4 GDS__gfix_invalid_sw
Modified: firebird/trunk/lang_helpers/gds_codes.pas
===================================================================
--- firebird/trunk/lang_helpers/gds_codes.pas 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/lang_helpers/gds_codes.pas 2016-02-03 13:20:41 UTC (rev 62916)
@@ -1621,6 +1621,10 @@
gds_login_error = 335545106;
isc_already_opened = 335545107;
gds_already_opened = 335545107;
+ isc_bad_crypt_key = 335545108;
+ gds_bad_crypt_key = 335545108;
+ isc_encrypt_error = 335545109;
+ gds_encrypt_error = 335545109;
isc_gfix_db_name = 335740929;
gds_gfix_db_name = 335740929;
isc_gfix_invalid_sw = 335740930;
Modified: firebird/trunk/src/common/classes/ClumpletReader.cpp
===================================================================
--- firebird/trunk/src/common/classes/ClumpletReader.cpp 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/common/classes/ClumpletReader.cpp 2016-02-03 13:20:41 UTC (rev 62916)
@@ -29,6 +29,7 @@
#include "firebird.h"
#include "../common/classes/ClumpletReader.h"
+#include "../common/classes/MetaName.h"
#include "fb_exception.h"
#include "../jrd/ibase.h"
@@ -784,6 +785,14 @@
return str;
}
+MetaName& ClumpletReader::getString(MetaName& str) const
+{
+ const UCHAR* ptr = getBytes();
+ const FB_SIZE_T length = getClumpLength();
+ str.assign(reinterpret_cast<const char*>(ptr), length);
+ return str;
+}
+
PathName& ClumpletReader::getPath(PathName& str) const
{
const UCHAR* ptr = getBytes();
Modified: firebird/trunk/src/common/classes/ClumpletReader.h
===================================================================
--- firebird/trunk/src/common/classes/ClumpletReader.h 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/common/classes/ClumpletReader.h 2016-02-03 13:20:41 UTC (rev 62916)
@@ -40,6 +40,8 @@
namespace Firebird {
+class MetaName;
+
// This class provides read access for clumplet structure
// Note: it doesn't make a copy of buffer it reads
class ClumpletReader : protected AutoStorage
@@ -100,6 +102,7 @@
bool getBoolean() const;
SINT64 getBigInt() const;
string& getString(string& str) const;
+ MetaName& getString(MetaName& str) const;
PathName& getPath(PathName& str) const;
void getData(UCharBuffer& data) const;
const UCHAR* getBytes() const;
Modified: firebird/trunk/src/common/classes/ClumpletWriter.cpp
===================================================================
--- firebird/trunk/src/common/classes/ClumpletWriter.cpp 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/common/classes/ClumpletWriter.cpp 2016-02-03 13:20:41 UTC (rev 62916)
@@ -30,6 +30,7 @@
#include "firebird.h"
#include "../common/classes/ClumpletWriter.h"
+#include "../common/classes/MetaName.h"
#include "fb_exception.h"
#include "../jrd/ibase.h"
@@ -183,7 +184,7 @@
}
else
{
- UCHAR tag = (kind == SpbStart || kind == UnTagged || kind == WideUnTagged) ? getBufferTag() : 0;
+ UCHAR tag = (kind == SpbStart || kind == UnTagged || kind == WideUnTagged) ? 0 : getBufferTag();
initNewBuffer(tag);
}
rewind();
@@ -250,16 +251,26 @@
insertString(tag, str.c_str(), str.length());
}
-void ClumpletWriter::insertPath(UCHAR tag, const PathName& str)
+void ClumpletWriter::insertString(UCHAR tag, const MetaName& str)
{
insertString(tag, str.c_str(), str.length());
}
+void ClumpletWriter::insertString(UCHAR tag, const char* str)
+{
+ insertString(tag, str, strlen(str));
+}
+
void ClumpletWriter::insertString(UCHAR tag, const char* str, FB_SIZE_T length)
{
insertBytesLengthCheck(tag, str, length);
}
+void ClumpletWriter::insertPath(UCHAR tag, const PathName& str)
+{
+ insertString(tag, str.c_str(), str.length());
+}
+
void ClumpletWriter::insertBytes(UCHAR tag, const void* bytes, FB_SIZE_T length)
{
insertBytesLengthCheck(tag, bytes, length);
Modified: firebird/trunk/src/common/classes/ClumpletWriter.h
===================================================================
--- firebird/trunk/src/common/classes/ClumpletWriter.h 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/common/classes/ClumpletWriter.h 2016-02-03 13:20:41 UTC (rev 62916)
@@ -73,7 +73,9 @@
void insertBigInt(UCHAR tag, const SINT64 value);
void insertBytes(UCHAR tag, const void* bytes, FB_SIZE_T length);
void insertString(UCHAR tag, const string& str);
+ void insertString(UCHAR tag, const MetaName& str);
void insertPath(UCHAR tag, const PathName& str);
+ void insertString(UCHAR tag, const char* str);
void insertString(UCHAR tag, const char* str, FB_SIZE_T length);
void insertByte(UCHAR tag, const UCHAR byte);
void insertTag(UCHAR tag);
Modified: firebird/trunk/src/dsql/DdlNodes.epp
===================================================================
--- firebird/trunk/src/dsql/DdlNodes.epp 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/dsql/DdlNodes.epp 2016-02-03 13:20:41 UTC (rev 62916)
@@ -11577,6 +11577,7 @@
NODE_PRINT(printer, setDefaultCollation);
NODE_PRINT(printer, files);
NODE_PRINT(printer, cryptPlugin);
+ NODE_PRINT(printer, keyName);
return "AlterDatabaseNode";
}
@@ -11660,7 +11661,7 @@
if (clauses & CLAUSE_CRYPT)
{
Database* const db = tdbb->getDatabase();
- db->dbb_crypto_manager->prepareChangeCryptState(tdbb, cryptPlugin);
+ db->dbb_crypto_manager->prepareChangeCryptState(tdbb, cryptPlugin, keyName);
DFW_post_work(transaction, dfw_db_crypt, cryptPlugin.c_str(), 0);
}
Modified: firebird/trunk/src/dsql/DdlNodes.h
===================================================================
--- firebird/trunk/src/dsql/DdlNodes.h 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/dsql/DdlNodes.h 2016-02-03 13:20:41 UTC (rev 62916)
@@ -2228,7 +2228,8 @@
setDefaultCharSet(p),
setDefaultCollation(p),
files(p),
- cryptPlugin(p)
+ cryptPlugin(p),
+ keyName(p)
{
}
@@ -2263,6 +2264,7 @@
Firebird::MetaName setDefaultCollation;
Firebird::Array<NestConst<DbFileClause> > files;
Firebird::MetaName cryptPlugin;
+ Firebird::MetaName keyName;
};
Modified: firebird/trunk/src/dsql/parse.y
===================================================================
--- firebird/trunk/src/dsql/parse.y 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/dsql/parse.y 2016-02-03 13:20:41 UTC (rev 62916)
@@ -3961,7 +3961,7 @@
{ $alterDatabaseNode->clauses |= AlterDatabaseNode::CLAUSE_END_BACKUP; }
| SET DEFAULT CHARACTER SET symbol_character_set_name
{ $alterDatabaseNode->setDefaultCharSet = *$5; }
- | ENCRYPT WITH valid_symbol_name
+ | ENCRYPT WITH valid_symbol_name crypt_key_clause($alterDatabaseNode)
{
setClauseFlag($alterDatabaseNode->clauses, AlterDatabaseNode::CLAUSE_CRYPT, "CRYPT");
$alterDatabaseNode->cryptPlugin = *$3;
@@ -3974,6 +3974,12 @@
{ $alterDatabaseNode->linger = 0; }
;
+%type crypt_key_clause(<alterDatabaseNode>)
+crypt_key_clause($alterDatabaseNode)
+ : /* nothing */
+ | KEY valid_symbol_name
+ { $alterDatabaseNode->keyName = *$2; }
+ ;
// ALTER TRIGGER
Modified: firebird/trunk/src/include/firebird/FirebirdInterface.idl
===================================================================
--- firebird/trunk/src/include/firebird/FirebirdInterface.idl 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/include/firebird/FirebirdInterface.idl 2016-02-03 13:20:41 UTC (rev 62916)
@@ -720,11 +720,11 @@
interface DbCryptPlugin : PluginBase
{
// When database crypt plugin is loaded, setKey() is called to provide information
- // about key holders, available for a given database.
+ // about key holders, available for a given database and key name for database.
// It's supposed that crypt plugin will invoke keyHandle() function from them
// to access callback interface for getting actual crypt key.
// If crypt plugin fails to find appropriate key in sources, it should raise error.
- void setKey(Status status, uint length, KeyHolderPlugin* sources);
+ void setKey(Status status, const string keyName, uint length, KeyHolderPlugin* sources);
void encrypt(Status status, uint length, const void* from, void* to);
void decrypt(Status status, uint length, const void* from, void* to);
}
Modified: firebird/trunk/src/include/firebird/IdlFbInterfaces.h
===================================================================
--- firebird/trunk/src/include/firebird/IdlFbInterfaces.h 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/include/firebird/IdlFbInterfaces.h 2016-02-03 13:20:41 UTC (rev 62916)
@@ -2871,7 +2871,7 @@
public:
struct VTable : public IPluginBase::VTable
{
- void (CLOOP_CARG *setKey)(IDbCryptPlugin* self, IStatus* status, unsigned length, IKeyHolderPlugin** sources) throw();
+ void (CLOOP_CARG *setKey)(IDbCryptPlugin* self, IStatus* status, const char* keyName, unsigned length, IKeyHolderPlugin** sources) 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();
};
@@ -2889,10 +2889,10 @@
public:
static const unsigned VERSION = 4;
- template <typename StatusType> void setKey(StatusType* status, unsigned length, IKeyHolderPlugin** sources)
+ template <typename StatusType> void setKey(StatusType* status, const char* keyName, unsigned length, IKeyHolderPlugin** sources)
{
StatusType::clearException(status);
- static_cast<VTable*>(this->cloopVTable)->setKey(this, status, length, sources);
+ static_cast<VTable*>(this->cloopVTable)->setKey(this, status, keyName, length, sources);
StatusType::checkException(status);
}
@@ -11093,13 +11093,13 @@
this->cloopVTable = &vTable;
}
- static void CLOOP_CARG cloopsetKeyDispatcher(IDbCryptPlugin* self, IStatus* status, unsigned length, IKeyHolderPlugin** sources) throw()
+ static void CLOOP_CARG cloopsetKeyDispatcher(IDbCryptPlugin* self, IStatus* status, const char* keyName, unsigned length, IKeyHolderPlugin** sources) throw()
{
StatusType status2(status);
try
{
- static_cast<Name*>(self)->Name::setKey(&status2, length, sources);
+ static_cast<Name*>(self)->Name::setKey(&status2, keyName, length, sources);
}
catch (...)
{
@@ -11199,7 +11199,7 @@
{
}
- virtual void setKey(StatusType* status, unsigned length, IKeyHolderPlugin** sources) = 0;
+ virtual void setKey(StatusType* status, const char* keyName, unsigned length, IKeyHolderPlugin** sources) = 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;
};
Modified: firebird/trunk/src/include/gen/codetext.h
===================================================================
--- firebird/trunk/src/include/gen/codetext.h 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/include/gen/codetext.h 2016-02-03 13:20:41 UTC (rev 62916)
@@ -809,6 +809,8 @@
{"map_down", 335545105},
{"login_error", 335545106},
{"already_opened", 335545107},
+ {"bad_crypt_key", 335545108},
+ {"encrypt_error", 335545109},
{"gfix_db_name", 335740929},
{"gfix_invalid_sw", 335740930},
{"gfix_incmp_sw", 335740932},
Modified: firebird/trunk/src/include/gen/iberror.h
===================================================================
--- firebird/trunk/src/include/gen/iberror.h 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/include/gen/iberror.h 2016-02-03 13:20:41 UTC (rev 62916)
@@ -843,6 +843,8 @@
const ISC_STATUS isc_map_down = 335545105L;
const ISC_STATUS isc_login_error = 335545106L;
const ISC_STATUS isc_already_opened = 335545107L;
+const ISC_STATUS isc_bad_crypt_key = 335545108L;
+const ISC_STATUS isc_encrypt_error = 335545109L;
const ISC_STATUS isc_gfix_db_name = 335740929L;
const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
@@ -1306,7 +1308,7 @@
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
-const ISC_STATUS isc_err_max = 1250;
+const ISC_STATUS isc_err_max = 1252;
#else /* c definitions */
@@ -2119,6 +2121,8 @@
#define isc_map_down 335545105L
#define isc_login_error 335545106L
#define isc_already_opened 335545107L
+#define isc_bad_crypt_key 335545108L
+#define isc_encrypt_error 335545109L
#define isc_gfix_db_name 335740929L
#define isc_gfix_invalid_sw 335740930L
#define isc_gfix_incmp_sw 335740932L
@@ -2582,7 +2586,7 @@
#define isc_trace_switch_param_miss 337182758L
#define isc_trace_param_act_notcompat 337182759L
#define isc_trace_mandatory_switch_miss 337182760L
-#define isc_err_max 1250
+#define isc_err_max 1252
#endif
Modified: firebird/trunk/src/include/gen/msgs.h
===================================================================
--- firebird/trunk/src/include/gen/msgs.h 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/include/gen/msgs.h 2016-02-03 13:20:41 UTC (rev 62916)
@@ -812,6 +812,8 @@
{335545105, "Some database(s) were shutdown when trying to read mapping data"}, /* map_down */
{335545106, "Error occurred during login, please check server firebird.log for details"}, /* login_error */
{335545107, "Database already opened with engine instance, incompatible with current"}, /* already_opened */
+ {335545108, "Invalid crypt key @1"}, /* bad_crypt_key */
+ {335545109, "Page requires encyption but crypt plugin is missing"}, /* encrypt_error */
{335740929, "data base file name (@1) already given"}, /* gfix_db_name */
{335740930, "invalid switch @1"}, /* gfix_invalid_sw */
{335740932, "incompatible switch combination"}, /* gfix_incmp_sw */
Modified: firebird/trunk/src/include/gen/sql_code.h
===================================================================
--- firebird/trunk/src/include/gen/sql_code.h 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/include/gen/sql_code.h 2016-02-03 13:20:41 UTC (rev 62916)
@@ -808,6 +808,8 @@
{335545105, -901}, /* 785 map_down */
{335545106, -902}, /* 786 login_error */
{335545107, -902}, /* 787 already_opened */
+ {335545108, -902}, /* 788 bad_crypt_key */
+ {335545109, -901}, /* 789 encrypt_error */
{335740929, -901}, /* 1 gfix_db_name */
{335740930, -901}, /* 2 gfix_invalid_sw */
{335740932, -901}, /* 4 gfix_incmp_sw */
Modified: firebird/trunk/src/include/gen/sql_state.h
===================================================================
--- firebird/trunk/src/include/gen/sql_state.h 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/include/gen/sql_state.h 2016-02-03 13:20:41 UTC (rev 62916)
@@ -743,7 +743,7 @@
{335545040, "22001"}, // 720 cp_name_too_long
{335545041, "42818"}, // 721 cp_process_active
{335545042, "42818"}, // 722 cp_already_crypted
- {335545043, "39000"}, // 723 decrypt_error
+ {335545043, "XX000"}, // 723 decrypt_error
{335545044, "39000"}, // 724 no_providers
{335545045, "42818"}, // 725 null_spb
{335545046, "42000"}, // 726 max_args_exceeded
@@ -808,6 +808,8 @@
{335545105, "08004"}, // 785 map_down
{335545106, "08006"}, // 786 login_error
{335545107, "08006"}, // 787 already_opened
+ {335545108, "08006"}, // 788 bad_crypt_key
+ {335545109, "XX000"}, // 789 encrypt_error
{335740929, "00000"}, // 1 gfix_db_name
{335740930, "00000"}, // 2 gfix_invalid_sw
{335740932, "00000"}, // 4 gfix_incmp_sw
Modified: firebird/trunk/src/jrd/CryptoManager.cpp
===================================================================
--- firebird/trunk/src/jrd/CryptoManager.cpp 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/jrd/CryptoManager.cpp 2016-02-03 13:20:41 UTC (rev 62916)
@@ -48,6 +48,8 @@
#include "../common/isc_proto.h"
#include "../common/classes/GetPlugins.h"
#include "../common/classes/RefMutex.h"
+#include "../common/classes/ClumpletWriter.h"
+#include "../common/sha.h"
using namespace Firebird;
@@ -83,23 +85,16 @@
return header;
}
- // This routine is looking for a clumplet on header page but is not ready to handle continuation
- // Fortunately, modern pages of size 4k and bigger can contain everything on one page.
- bool searchEntry(UCHAR type, UCHAR& out_len, const UCHAR* &entry)
+ // This routine is getting clumplets from header page but is not ready to handle continuation
+ // Fortunately, modern pages of size 4k and bigger can fit everything on one page.
+ void getClumplets(ClumpletWriter& writer)
{
- const UCHAR* end = ((const UCHAR*) header) + header->hdr_page_size;
- for (const UCHAR* p = header->hdr_data; (p < end - 2) && (*p != Ods::HDR_end); p += 2u + p[1])
- {
- if (*p == type)
- {
- out_len = p[1];
- entry = p + 2;
- if (entry + out_len > end)
- out_len = end - entry;
- return true;
- }
- }
- return false;
+ const UCHAR* p = header->hdr_data;
+ const UCHAR* const end = reinterpret_cast<const UCHAR*>(header) + header->hdr_page_size;
+ while ((p < end - 2) && (*p != Ods::HDR_end))
+ p += 2u + p[1];
+
+ writer.reset(header->hdr_data, p - header->hdr_data);
}
private:
@@ -112,7 +107,8 @@
public:
CchHdr(Jrd::thread_db* p_tdbb, USHORT lockType)
: window(Jrd::HEADER_PAGE_NUMBER),
- tdbb(p_tdbb)
+ tdbb(p_tdbb),
+ wrtFlag(false)
{
void* h = CCH_FETCH(tdbb, &window, lockType, pag_header);
if (!h)
@@ -124,10 +120,30 @@
Ods::header_page* write()
{
- CCH_MARK_MUST_WRITE(tdbb, &window);
+ if (!wrtFlag)
+ {
+ CCH_MARK_MUST_WRITE(tdbb, &window);
+ wrtFlag = true;
+ }
return const_cast<Ods::header_page*>(operator->());
}
+ void setClumplets(const ClumpletWriter& writer)
+ {
+ Ods::header_page* hdr = write();
+ UCHAR* const to = hdr->hdr_data;
+ UCHAR* const end = reinterpret_cast<UCHAR*>(hdr) + hdr->hdr_page_size;
+ const unsigned limit = (end - to) - 1;
+
+ const unsigned length = writer.getBufferLength();
+ fb_assert(length <= limit);
+ if (length > limit)
+ (Arg::Gds(isc_random) << "HDR page clumplets overflow").raise();
+
+ memcpy(to, writer.getBuffer(), length);
+ to[length] = Ods::HDR_end;
+ }
+
~CchHdr()
{
CCH_RELEASE(tdbb, &window);
@@ -136,6 +152,7 @@
private:
Jrd::WIN window;
Jrd::thread_db* tdbb;
+ bool wrtFlag;
};
class PhysHdr : public Header
@@ -222,6 +239,7 @@
CryptoManager::CryptoManager(thread_db* tdbb)
: PermanentStorage(*tdbb->getDatabase()->dbb_permanent),
sync(this),
+ keyName(getPool()),
keyHolderPlugins(getPool()),
cryptThreadId(0),
cryptPlugin(NULL),
@@ -310,9 +328,27 @@
PhysHdr hdr(tdbb);
crypt = hdr->hdr_flags & Ods::hdr_encrypted;
process = hdr->hdr_flags & Ods::hdr_crypt_process;
- if (crypt || process)
+
+ if ((crypt || process) && !cryptPlugin)
{
+ ClumpletWriter hc(ClumpletWriter::UnTagged, hdr->hdr_page_size);
+ hdr.getClumplets(hc);
+ if (hc.find(Ods::HDR_crypt_key))
+ hc.getString(keyName);
+ else
+ keyName = "";
+
loadPlugin(hdr->hdr_crypt_plugin);
+
+ string valid;
+ calcValidation(valid);
+ if (hc.find(Ods::HDR_crypt_hash))
+ {
+ string hash;
+ hc.getString(hash);
+ if (hash != valid)
+ (Arg::Gds(isc_bad_crypt_key) << keyName).raise();
+ }
}
}
@@ -337,12 +373,13 @@
// do not assign cryptPlugin directly before key init complete
IDbCryptPlugin* p = cryptControl.plugin();
- keyHolderPlugins.init(p);
+ keyHolderPlugins.init(p, keyName.c_str());
cryptPlugin = p;
cryptPlugin->addRef();
}
- void CryptoManager::prepareChangeCryptState(thread_db* tdbb, const Firebird::MetaName& plugName)
+ void CryptoManager::prepareChangeCryptState(thread_db* tdbb, const MetaName& plugName,
+ const MetaName& key)
{
if (plugName.length() > MAX_PLUGIN_NAME_LEN)
{
@@ -371,13 +408,29 @@
if (cryptPlugin)
(Arg::Gds(isc_cp_already_crypted)).raise();
+ keyName = key;
loadPlugin(plugName.c_str());
}
}
}
- void CryptoManager::changeCryptState(thread_db* tdbb, const Firebird::string& plugName)
+ void CryptoManager::calcValidation(string& valid)
{
+ // crypt verifier
+ const char* sample = "0123456789ABCDEF";
+ char result[16];
+ FbLocalStatus sv;
+ cryptPlugin->encrypt(&sv, sizeof(result), sample, result);
+ if (sv->getState() & IStatus::STATE_ERRORS)
+ Arg::StatusVector(&sv).raise();
+
+ // calculate it's hash
+ const string verifier(result, sizeof(result));
+ Sha1::hashBased64(valid, verifier);
+ }
+
+ void CryptoManager::changeCryptState(thread_db* tdbb, const string& plugName)
+ {
if (plugName.length() > 31)
{
(Arg::Gds(isc_cp_name_too_long) << Arg::Num(31)).raise();
@@ -423,17 +476,31 @@
// Write modified header page
Ods::header_page* header = hdr.write();
+ ClumpletWriter hc(ClumpletWriter::UnTagged, header->hdr_page_size);
+ hdr.getClumplets(hc);
+
if (crypt)
{
header->hdr_flags |= Ods::hdr_encrypted;
plugName.copyTo(header->hdr_crypt_plugin, sizeof(header->hdr_crypt_plugin));
+ string hash;
+ calcValidation(hash);
+ hc.insertString(Ods::HDR_crypt_hash, hash);
}
else
{
header->hdr_flags &= ~Ods::hdr_encrypted;
+ hc.deleteWithTag(Ods::HDR_crypt_hash);
}
- // Set hdr_crypt_page for crypt thread
+ if (crypt && keyName.hasData())
+ hc.insertString(Ods::HDR_crypt_key, keyName);
+ else
+ hc.deleteWithTag(Ods::HDR_crypt_key);
+
+ hdr.setClumplets(hc);
+
+ // Setup hdr_crypt_page for crypt thread
header->hdr_crypt_page = 1;
header->hdr_flags |= Ods::hdr_crypt_process;
process = true;
@@ -848,8 +915,7 @@
fb_assert(cryptPlugin);
if (!cryptPlugin)
{
- (Arg::Gds(isc_decrypt_error) <<
- Arg::Gds(isc_random) << "Missing crypt plugin").copyTo(sv);
+ Arg::Gds(isc_encrypt_error).copyTo(sv);
return FAILED_CRYPT;
}
@@ -950,7 +1016,7 @@
{
IKeyHolderPlugin* keyPlugin = keyControl.plugin();
FbLocalStatus st;
- if (keyPlugin->keyCallback(&st, att->att_crypt_callback) == 1) //// FIXME: 1 ???
+ if (keyPlugin->keyCallback(&st, att->att_crypt_callback) > 0)
{
// holder accepted attachment's key
HolderAttachments* ha = NULL;
@@ -992,7 +1058,7 @@
}
}
- void CryptoManager::KeyHolderPlugins::init(IDbCryptPlugin* crypt)
+ void CryptoManager::KeyHolderPlugins::init(IDbCryptPlugin* crypt, const char* keyName)
{
MutexLockGuard g(holdersMutex, FB_FUNCTION);
@@ -1005,7 +1071,7 @@
}
FbLocalStatus st;
- crypt->setKey(&st, length, vector);
+ crypt->setKey(&st, keyName, length, vector);
st.check();
}
Modified: firebird/trunk/src/jrd/CryptoManager.h
===================================================================
--- firebird/trunk/src/jrd/CryptoManager.h 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/jrd/CryptoManager.h 2016-02-03 13:20:41 UTC (rev 62916)
@@ -35,6 +35,7 @@
#include "../common/classes/fb_string.h"
#include "../common/classes/objects_array.h"
#include "../common/classes/condition.h"
+#include "../common/classes/MetaName.h"
#include "../common/ThreadStart.h"
#include "../jrd/ods.h"
#include "../jrd/status.h"
@@ -259,7 +260,8 @@
void shutdown(thread_db* tdbb);
- void prepareChangeCryptState(thread_db* tdbb, const Firebird::MetaName& plugName);
+ void prepareChangeCryptState(thread_db* tdbb, const Firebird::MetaName& plugName,
+ const Firebird::MetaName& key);
void changeCryptState(thread_db* tdbb, const Firebird::string& plugName);
void attach(thread_db* tdbb, Attachment* att);
void detach(thread_db* tdbb, Attachment* att);
@@ -334,7 +336,7 @@
void attach(Attachment* att, Config* config);
void detach(Attachment* att);
- void init(Firebird::IDbCryptPlugin* crypt);
+ void init(Firebird::IDbCryptPlugin* crypt, const char* keyName);
private:
Firebird::Mutex holdersMutex;
@@ -351,12 +353,14 @@
void loadPlugin(const char* pluginName);
ULONG getLastPage(thread_db* tdbb);
void writeDbHeader(thread_db* tdbb, ULONG runpage);
+ void calcValidation(Firebird::string& valid);
void lockAndReadHeader(thread_db* tdbb, unsigned flags = 0);
static const unsigned CRYPT_HDR_INIT = 0x01;
static const unsigned CRYPT_HDR_NOWAIT = 0x02;
BarSync sync;
+ Firebird::MetaName keyName;
ULONG currentPage;
Firebird::Mutex pluginLoadMtx, cryptThreadMtx;
KeyHolderPlugins keyHolderPlugins;
Modified: firebird/trunk/src/jrd/ods.h
===================================================================
--- firebird/trunk/src/jrd/ods.h 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/jrd/ods.h 2016-02-03 13:20:41 UTC (rev 62916)
@@ -429,7 +429,9 @@
const UCHAR HDR_password_file_key = 5; // Key to compare to password db
const UCHAR HDR_difference_file = 6; // Delta file that is used during backup lock
const UCHAR HDR_backup_guid = 7; // UID generated on each switch into backup mode
-const UCHAR HDR_max = 8; // Maximum HDR_clump value
+const UCHAR HDR_crypt_key = 8; // Name of a key used to crypt database
+const UCHAR HDR_crypt_hash = 9; // Validator of key correctness
+const UCHAR HDR_max = 10; // Maximum HDR_clump value
// Header page flags
Modified: firebird/trunk/src/msgs/facilities2.sql
===================================================================
--- firebird/trunk/src/msgs/facilities2.sql 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/msgs/facilities2.sql 2016-02-03 13:20:41 UTC (rev 62916)
@@ -1,7 +1,7 @@
/* MAX_NUMBER is the next number to be used, always one more than the highest message number. */
set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES (?, ?, ?, ?);
--
-('2015-12-30 17:52:25', 'JRD', 0, 788)
+('2016-02-03 14:51:49', 'JRD', 0, 790)
('2015-03-17 18:33:00', 'QLI', 1, 533)
('2015-01-07 18:01:51', 'GFIX', 3, 134)
('1996-11-07 13:39:40', 'GPRE', 4, 1)
Modified: firebird/trunk/src/msgs/messages2.sql
===================================================================
--- firebird/trunk/src/msgs/messages2.sql 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/msgs/messages2.sql 2016-02-03 13:20:41 UTC (rev 62916)
@@ -895,6 +895,8 @@
('map_down', NULL, 'Mapping.cpp', NULL, 0, 785, NULL, 'Some database(s) were shutdown when trying to read mapping data', NULL, NULL);
('login_error', NULL, 'server.cpp', NULL, 0, 786, NULL, 'Error occurred during login, please check server firebird.log for details', NULL, NULL);
('already_opened', 'lockDatabaseFile', 'unix.cpp', NULL, 0, 787, NULL, 'Database already opened with engine instance, incompatible with current', NULL, NULL);
+('bad_crypt_key', NULL, 'CryptoManager.cpp', NULL, 0, 788, NULL, 'Invalid crypt key @1', NULL, NULL);
+('encrypt_error', NULL, 'CryptoManager.cpp', NULL, 0, 789, NULL, 'Page requires encyption but crypt plugin is missing', NULL, NULL);
-- QLI
(NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL);
(NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL);
Modified: firebird/trunk/src/msgs/system_errors2.sql
===================================================================
--- firebird/trunk/src/msgs/system_errors2.sql 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/msgs/system_errors2.sql 2016-02-03 13:20:41 UTC (rev 62916)
@@ -729,7 +729,7 @@
(-104, '22', '001', 0, 720, 'cp_name_too_long', NULL, NULL)
(-901, '42', '818', 0, 721, 'cp_process_active', NULL, NULL)
(-901, '42', '818', 0, 722, 'cp_already_crypted', NULL, NULL)
-(-902, '39', '000', 0, 723, 'decrypt_error', NULL, NULL)
+(-902, 'XX', '000', 0, 723, 'decrypt_error', NULL, NULL)
(-902, '39', '000', 0, 724, 'no_providers', NULL, NULL)
(-104, '42', '818', 0, 725, 'null_spb', NULL, NULL)
(-833, '42', '000', 0, 726, 'max_args_exceeded', NULL, NULL)
@@ -794,6 +794,8 @@
(-901, '08', '004', 0, 785, 'map_down', NULL, NULL)
(-902, '08', '006', 0, 786, 'login_error', NULL, NULL)
(-902, '08', '006', 0, 787, 'already_opened', NULL, NULL)
+(-902, '08', '006', 0, 788, 'bad_crypt_key', NULL, NULL)
+(-901, 'XX', '000', 0, 789, 'encrypt_error', NULL, NULL)
-- GFIX
(-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL)
(-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL)
Modified: firebird/trunk/src/utilities/gstat/ppg.cpp
===================================================================
--- firebird/trunk/src/utilities/gstat/ppg.cpp 2016-02-03 11:06:43 UTC (rev 62915)
+++ firebird/trunk/src/utilities/gstat/ppg.cpp 2016-02-03 13:20:41 UTC (rev 62916)
@@ -281,6 +281,14 @@
break;
}
+ case HDR_crypt_key:
+ uSvc->printf(false, "\tEncryption key name:\t%*.*s\n", p[1], p[1], p + 2);
+ break;
+
+ case HDR_crypt_hash:
+ uSvc->printf(false, "\tKey hash:\t%*.*s\n", p[1], p[1], p + 2);
+ break;
+
default:
if (*p > HDR_max)
uSvc->printf(false, "\tUnrecognized option %d, length %d\n", p[0], p[1]);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|