From: <ale...@us...> - 2012-05-31 16:53:57
|
Revision: 54574 http://firebird.svn.sourceforge.net/firebird/?rev=54574&view=rev Author: alexpeshkoff Date: 2012-05-31 16:53:42 +0000 (Thu, 31 May 2012) Log Message: ----------- Implemented CORE-3861: Make it possible to encrypt database Also some cleanups, the most important are: - meaningful ctor on Jrd::Lock, helping to avoid code dup - avoid unneeded h-file dependencies, making boot build engine dependent Modified Paths: -------------- firebird/trunk/builds/posix/Makefile.in firebird/trunk/builds/posix/Makefile.in.plugins_examples firebird/trunk/builds/posix/firebird.vers firebird/trunk/builds/posix/make.defaults firebird/trunk/builds/posix/make.shared.variables firebird/trunk/builds/win32/defs/firebird.def firebird/trunk/src/auth/SecureRemotePassword/manage/SrpManagement.cpp firebird/trunk/src/auth/SecureRemotePassword/server/SrpServer.cpp firebird/trunk/src/common/IntlUtil.cpp firebird/trunk/src/common/TextType.cpp firebird/trunk/src/common/TextType.h firebird/trunk/src/common/classes/GetPlugins.h firebird/trunk/src/common/classes/ImplementHelper.h firebird/trunk/src/common/config/config.cpp firebird/trunk/src/common/config/config.h firebird/trunk/src/common/isc.cpp firebird/trunk/src/common/isc_file.cpp firebird/trunk/src/common/sdl.cpp firebird/trunk/src/dsql/BoolNodes.cpp firebird/trunk/src/dsql/DdlNodes.epp firebird/trunk/src/dsql/DdlNodes.h firebird/trunk/src/dsql/ExprNodes.cpp firebird/trunk/src/dsql/parse.y firebird/trunk/src/gpre/boot/gpre_meta_boot.cpp firebird/trunk/src/include/consts_pub.h firebird/trunk/src/include/firebird/Crypt.h firebird/trunk/src/include/firebird/Interface.h firebird/trunk/src/include/firebird/Plugin.h firebird/trunk/src/include/firebird/Provider.h firebird/trunk/src/include/gen/ids.h firebird/trunk/src/jrd/Attachment.cpp firebird/trunk/src/jrd/Attachment.h firebird/trunk/src/jrd/Collation.cpp firebird/trunk/src/jrd/Collation.h firebird/trunk/src/jrd/Database.cpp firebird/trunk/src/jrd/Database.h firebird/trunk/src/jrd/DatabaseSnapshot.cpp firebird/trunk/src/jrd/EngineInterface.h firebird/trunk/src/jrd/Function.epp firebird/trunk/src/jrd/GlobalRWLock.cpp firebird/trunk/src/jrd/GlobalRWLock.h firebird/trunk/src/jrd/IntlManager.cpp firebird/trunk/src/jrd/JrdStatement.cpp firebird/trunk/src/jrd/Optimizer.cpp firebird/trunk/src/jrd/RecordNumber.h firebird/trunk/src/jrd/SysFunction.cpp firebird/trunk/src/jrd/VirtualTable.cpp firebird/trunk/src/jrd/blb.h firebird/trunk/src/jrd/btr.cpp firebird/trunk/src/jrd/cch.cpp firebird/trunk/src/jrd/cmp.cpp firebird/trunk/src/jrd/cvt2.cpp firebird/trunk/src/jrd/dfw.epp firebird/trunk/src/jrd/dfw_proto.h firebird/trunk/src/jrd/extds/InternalDS.cpp firebird/trunk/src/jrd/ibase.h firebird/trunk/src/jrd/idx.cpp firebird/trunk/src/jrd/intl.cpp firebird/trunk/src/jrd/intl_classes.h firebird/trunk/src/jrd/intl_proto.h firebird/trunk/src/jrd/jrd.cpp firebird/trunk/src/jrd/lck.cpp firebird/trunk/src/jrd/lck.h firebird/trunk/src/jrd/lck_proto.h firebird/trunk/src/jrd/met.epp firebird/trunk/src/jrd/names.h firebird/trunk/src/jrd/nbak.cpp firebird/trunk/src/jrd/ods.h firebird/trunk/src/jrd/opt.cpp firebird/trunk/src/jrd/os/posix/unix.cpp firebird/trunk/src/jrd/pag.cpp firebird/trunk/src/jrd/recsrc/HashJoin.cpp firebird/trunk/src/jrd/relations.h firebird/trunk/src/jrd/rlck.cpp firebird/trunk/src/jrd/sdw.cpp firebird/trunk/src/jrd/svc.cpp firebird/trunk/src/jrd/svc.h firebird/trunk/src/jrd/tpc.cpp firebird/trunk/src/jrd/tra.cpp firebird/trunk/src/jrd/tra.h firebird/trunk/src/jrd/val.h firebird/trunk/src/msgs/facilities2.sql firebird/trunk/src/msgs/messages2.sql firebird/trunk/src/plugins/crypt/arc4/Arc4.cpp firebird/trunk/src/remote/client/interface.cpp firebird/trunk/src/remote/inet.cpp firebird/trunk/src/remote/protocol.cpp firebird/trunk/src/remote/protocol.h firebird/trunk/src/remote/remote.cpp firebird/trunk/src/remote/remote.h firebird/trunk/src/remote/server/server.cpp firebird/trunk/src/utilities/fbsvcmgr/fbsvcmgr.cpp firebird/trunk/src/utilities/gstat/dba.epp firebird/trunk/src/utilities/gstat/dbaswi.h firebird/trunk/src/utilities/gstat/ppg.cpp firebird/trunk/src/utilities/ntrace/TracePluginImpl.h firebird/trunk/src/yvalve/MasterImplementation.cpp firebird/trunk/src/yvalve/MasterImplementation.h firebird/trunk/src/yvalve/YObjects.h firebird/trunk/src/yvalve/gds.cpp firebird/trunk/src/yvalve/keywords.cpp firebird/trunk/src/yvalve/why.cpp firebird/trunk/src/yvalve/why_proto.h Added Paths: ----------- firebird/trunk/examples/dbcrypt/ firebird/trunk/examples/dbcrypt/CryptApplication.cpp firebird/trunk/examples/dbcrypt/CryptKeyHolder.cpp firebird/trunk/examples/dbcrypt/DbCrypt.cpp firebird/trunk/examples/dbcrypt/ReadMe.txt firebird/trunk/src/jrd/CryptoManager.cpp firebird/trunk/src/jrd/CryptoManager.h Modified: firebird/trunk/builds/posix/Makefile.in =================================================================== --- firebird/trunk/builds/posix/Makefile.in 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/builds/posix/Makefile.in 2012-05-31 16:53:42 UTC (rev 54574) @@ -359,10 +359,10 @@ # .PHONY: udr legacy_user_management trace auth_debug -makePluginName= $(PLUGINS)/$(LIB_PREFIX)$(1).$(SHRLIB_EXT) UDR_PLUGIN = $(call makePluginName,udr_engine) LEGACY_USER_MANAGER = $(call makePluginName,Legacy_UserManager) SRP_USER_MANAGER = $(call makePluginName,Srp) +FBTRACE = $(call makePluginName,fbtrace) AUTH_DEBUGGER = $(call makePluginName,Auth_Debug) BUILD_DEBUG:= @@ -446,6 +446,7 @@ $(BUILD_FILE): $(BUILD_Objects) $(COMMON_LIB) $(EXE_LINK) $(EXE_LINK_OPTIONS) $^ -o $@ $(FIREBIRD_LIBRARY_LINK) $(LINK_LIBS) + #--------------------------------------------------------------------------- # This target builds the include files for distribution with the release Modified: firebird/trunk/builds/posix/Makefile.in.plugins_examples =================================================================== --- firebird/trunk/builds/posix/Makefile.in.plugins_examples 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/builds/posix/Makefile.in.plugins_examples 2012-05-31 16:53:42 UTC (rev 54574) @@ -27,8 +27,15 @@ # Contributor(s): # Adriano dos Santos Fernandes # -ROOT=../.. +ROOT=$(shell cd ../..; pwd) + +ifeq ($(IsDeveloper), Y) + DefaultTarget := Debug +else + DefaultTarget := Release +endif + CPPFLAGS+= -I$(FIREBIRD)/include include $(ROOT)/gen/make.defaults @@ -38,26 +45,23 @@ @SET_MAKE@ -PLUGINS= $(FIREBIRD)/plugins +# Override make.defaults +LINK_PLUGIN_SYMBOLS = $(call LIB_LINK_MAPFILE,../$(PLUGIN_VERS)) -UDR_Files = UdrCppExample.cpp -UDR_Sources = $(addprefix ../examples/udr/, $(UDR_Files)) -UDR_Objects = $(addprefix $(OBJ)/, $(addsuffix .o, $(basename $(UDR_Sources)))) +.PHONY: all udrcpp_example dc_example kh_example -AllObjects = $(UDR_Objects) -Dependencies = $(AllObjects:.o=.d) +all: udrcpp_example dc_example kh_example -.PHONY: all udrcpp_example +UDR_Objects = $(call makeObjects,../examples/udr,UdrCppExample.cpp) +UDR_Plugin = $(PLUGINS)/udr/$(LIB_PREFIX)udrcpp_example.$(SHRLIB_EXT) +AllObjects = $(UDR_Objects) -all: udrcpp_example +udrcpp_example: $(UDR_Plugin) - -udrcpp_example: $(PLUGINS)/udr/$(LIB_PREFIX)udrcpp_example.$(SHRLIB_EXT) - -$(PLUGINS)/udr/$(LIB_PREFIX)udrcpp_example.$(SHRLIB_EXT): $(UDR_Objects) +$(UDR_Plugin): $(UDR_Objects) ifeq ($(PLATFORM),DARWIN) $(LIB_LINK) $(LIB_BUNDLE_OPTIONS) -o $@ $^ @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ \ $(FIREBIRD_LIBRARY_LINK) @@ -67,6 +71,28 @@ $(FIREBIRD_LIBRARY_LINK) endif + +DC_Objects = $(call makeObjects,../examples/dbcrypt,DbCrypt.cpp) +DC_Plugin = $(call makePluginName,DbCrypt_example) +AllObjects += $(DC_Objects) + +dc_example: $(DC_Plugin) + +$(DC_Plugin): $(DC_Objects) + $(LINK_PLUGIN) $(call LIB_LINK_SONAME,$(notdir $@).0) -o $@ $^ $(LINK_PLUG_LIBS) $(FIREBIRD_LIBRARY_LINK) + + +KH_Objects = $(call makeObjects,../examples/dbcrypt,CryptKeyHolder.cpp) +KH_Plugin = $(call makePluginName,CryptKeyHolder_example) +AllObjects += $(KH_Objects) + +kh_example: $(KH_Plugin) + +$(KH_Plugin): $(KH_Objects) + $(LINK_PLUGIN) $(call LIB_LINK_SONAME,$(notdir $@).0) -o $@ $^ $(LINK_PLUG_LIBS) $(FIREBIRD_LIBRARY_LINK) + + include $(ROOT)/gen/make.shared.targets +Dependencies = $(AllObjects:.o=.d) -include $(Dependencies) Modified: firebird/trunk/builds/posix/firebird.vers =================================================================== --- firebird/trunk/builds/posix/firebird.vers 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/builds/posix/firebird.vers 2012-05-31 16:53:42 UTC (rev 54574) @@ -345,6 +345,8 @@ fb_get_database_handle fb_get_transaction_handle +fb_database_crypt_callback + # Other misc functions isc_ftof Modified: firebird/trunk/builds/posix/make.defaults =================================================================== --- firebird/trunk/builds/posix/make.defaults 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/builds/posix/make.defaults 2012-05-31 16:53:42 UTC (rev 54574) @@ -336,7 +336,6 @@ FBTRACEMGR = $(BIN)/fbtracemgr$(EXEC_EXT) GSTAT = $(BIN)/gstat$(EXEC_EXT) NBACKUP = $(BIN)/nbackup$(EXEC_EXT) -FBTRACE = $(PLUGINS)/$(LIB_PREFIX)fbtrace.$(SHRLIB_EXT) LOCKPRINT = $(BIN)/fb_lock_print$(EXEC_EXT) GSEC = $(BIN)/gsec$(EXEC_EXT) GFIX = $(BIN)/gfix$(EXEC_EXT) Modified: firebird/trunk/builds/posix/make.shared.variables =================================================================== --- firebird/trunk/builds/posix/make.shared.variables 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/builds/posix/make.shared.variables 2012-05-31 16:53:42 UTC (rev 54574) @@ -15,7 +15,9 @@ dirObjects= $(call dirMaster,$(1)) $(call dirOs,$(1)) $(call dirFallBack,$(1)) +makePluginName= $(PLUGINS)/$(LIB_PREFIX)$(1).$(SHRLIB_EXT) + # Collect all object files here AllObjects= Modified: firebird/trunk/builds/win32/defs/firebird.def =================================================================== --- firebird/trunk/builds/win32/defs/firebird.def 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/builds/win32/defs/firebird.def 2012-05-31 16:53:42 UTC (rev 54574) @@ -354,6 +354,7 @@ fb_get_master_interface fb_get_database_handle fb_get_transaction_handle + fb_database_crypt_callback gds__trace gds__trace_raw Added: firebird/trunk/examples/dbcrypt/CryptApplication.cpp =================================================================== --- firebird/trunk/examples/dbcrypt/CryptApplication.cpp (rev 0) +++ firebird/trunk/examples/dbcrypt/CryptApplication.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -0,0 +1,217 @@ +/* + * PROGRAM: Firebird samples. + * MODULE: CryptApplication.cpp + * DESCRIPTION: Sample of passing a key to crypt plugin + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Alex Peshkov + * for the Firebird Open Source RDBMS project. + * + * Copyright (c) 2012 Alex Peshkov <peshkoff at mail.ru> + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <ibase.h> +#include <firebird/Crypt.h> +#include <firebird/Provider.h> + +using namespace Firebird; + +class CryptKey : public ICryptKeyCallback +{ +public: + unsigned int FB_CARG callback(unsigned int, const void*, unsigned int length, void* buffer) + { + if (length > 0 && buffer) + { + char k = 0x5a; + memcpy(buffer, &k, 1); + fprintf(stderr, "\nTransfered key to server\n"); + } + return 1; + } + + int FB_CARG getVersion() + { + return FB_CRYPT_CALLBACK_VERSION; + } + + IPluginModule* FB_CARG getModule() + { + return NULL; // OK for application, not for plugin + } +}; + +class App +{ +public: + App() : + master(fb_get_master_interface()), status(master->getStatus()), + p(NULL), att(NULL), tra(NULL) + { } + + ~App() + { + if (tra) + { + tra->rollback(status); + if (!status->isSuccess()) + { + print("rollback"); + tra->release(); + } + } + if (att) + { + att->detach(status); + if (!status->isSuccess()) + { + print("detach"); + att->release(); + } + } + if (p) + { + p->release(); + } + status->dispose(); + } + + enum Action {NONE, ENC, DEC}; + + void Execute(const char* dbName, const Action a) + { + status->init(); + + p = master->getDispatcher(); + + p->setDbCryptCallback(status, &key); + if (!status->isSuccess()) + throw "setDbCryptCallback"; + + char s[256]; + sprintf(s, "localhost:%s", dbName); + att = p->attachDatabase(status, s, 0, NULL); + if (!status->isSuccess()) + throw "attachDatabase"; + + if (a != NONE) + { + tra = att->startTransaction(status, 0, NULL); + if (!status->isSuccess()) + throw "startTransaction"; + } + + if (a == ENC) + { + att->execute(status, tra, 0, + "ALTER DATABASE ENCRYPT WITH \"DbCrypt_example\"", 3, 0, NULL, NULL); + if (!status->isSuccess()) + throw "execute"; + } + if (a == DEC) + { + att->execute(status, tra, 0, "ALTER DATABASE DECRYPT", 3, 0, NULL, NULL); + if (!status->isSuccess()) + throw "execute"; + } + + if (tra) + { + tra->commit(status); + if (!status->isSuccess()) + throw "commit"; + tra = NULL; + } + + printf("Providing key for crypt plugin - press enter to continue ..."); + getchar(); + + att->detach(status); + if (!status->isSuccess()) + throw "detach"; + att = NULL; + + p->release(); + p = NULL; + } + + void print(const char* where) + { + fprintf(stderr, "Error in %s: ", where); + isc_print_status(status->get()); + } + +private: + IMaster* master; + IStatus* status; + IProvider* p; + IAttachment* att; + ITransaction* tra; + + CryptKey key; +}; + +int usage() +{ + fprintf(stderr, "Usage: CryptApplication [ -e | -d ] { db-name }\n"); + return 2; +} + +int main(int ac, char** av) +{ + App::Action act = App::NONE; + + if (ac < 2 || ac > 3) + return usage(); + if (ac == 3) + { + if (av[1][0] != '-') + return usage(); + switch(av[1][1]) + { + case 'e': + act = App::ENC; + break; + case 'd': + act = App::DEC; + break; + default: + return usage(); + } + av++; + } + + setenv("ISC_USER", "sysdba", 0); + setenv("ISC_PASSWORD", "masterkey", 0); + + App app; + try + { + app.Execute(av[1], act); + } + catch(const char* where) + { + app.print(where); + return 1; + } + + return 0; +} Property changes on: firebird/trunk/examples/dbcrypt/CryptApplication.cpp ___________________________________________________________________ Added: svn:mime-type + text/x-c++src Added: svn:eol-style + native Added: firebird/trunk/examples/dbcrypt/CryptKeyHolder.cpp =================================================================== --- firebird/trunk/examples/dbcrypt/CryptKeyHolder.cpp (rev 0) +++ firebird/trunk/examples/dbcrypt/CryptKeyHolder.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -0,0 +1,278 @@ +/* + * PROGRAM: Firebird samples. + * MODULE: CryptKeyHolder.cpp + * DESCRIPTION: Sample of how key holder may be written. + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Alex Peshkov + * for the Firebird Open Source RDBMS project. + * + * Copyright (c) 2012 Alex Peshkov <peshkoff at mail.ru> + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#include <stdio.h> +#include <string.h> + +#include "firebird.h" +#include "firebird/Crypt.h" + +#include "../common/classes/fb_atomic.h" + +using namespace Firebird; + +namespace +{ + +IMaster* master = NULL; +IPluginManager* pluginManager = NULL; + +class PluginModule : public IPluginModule +{ +public: + PluginModule() + : flag(false) + { } + + void registerMe() + { + pluginManager->registerModule(this); + flag = true; + } + + ~PluginModule() + { + if (flag) + { + pluginManager->unregisterModule(this); + doClean(); + } + } + + int FB_CARG getVersion() + { + return FB_PLUGIN_MODULE_VERSION; + } + + IPluginModule* FB_CARG getModule() + { + return this; + } + + void FB_CARG doClean() + { + flag = false; + } + +private: + bool flag; +}; + +PluginModule module; + +class CryptKeyHolder : public IKeyHolderPlugin +{ +public: + explicit CryptKeyHolder(IPluginConfig* cnf) + : callbackInterface(this), config(cnf), key(0), owner(NULL) + { + config->addRef(); + } + + ~CryptKeyHolder() + { + config->release(); + } + + // IKeyHolderPlugin implementation + virtual int FB_CARG keyCallback(IStatus* status, ICryptKeyCallback* callback); + virtual ICryptKeyCallback* FB_CARG keyHandle(IStatus* status, const char* keyName); + + int FB_CARG release() + { + if (--refCounter == 0) + { + delete this; + return 0; + } + return 1; + } + + void FB_CARG addRef() + { + ++refCounter; + } + + int FB_CARG getVersion() + { + return FB_KEYHOLDER_PLUGIN_VERSION; + } + + IPluginModule* FB_CARG getModule() + { + return &module; + } + + void FB_CARG setOwner(Firebird::IRefCounted* o) + { + owner = o; + } + + IRefCounted* FB_CARG getOwner() + { + return owner; + } + + UCHAR getKey() + { + return key; + } + +private: + class CallbackInterface : public ICryptKeyCallback + { + public: + CallbackInterface(CryptKeyHolder* p) + : parent(p) + { } + + unsigned int FB_CARG callback(unsigned int, const void*, unsigned int length, void* buffer) + { + UCHAR k = parent->getKey(); + if (!k) + { + return 0; + } + + if (length > 0 && buffer) + { + memcpy(buffer, &k, 1); + } + return 1; + } + + int FB_CARG getVersion() + { + return FB_CRYPT_CALLBACK_VERSION; + } + + IPluginModule* FB_CARG getModule() + { + return &module; + } + + private: + CryptKeyHolder* parent; + }; + + CallbackInterface callbackInterface; + + IPluginConfig* config; + UCHAR key; + + AtomicCounter refCounter; + IRefCounted* owner; + + void noKeyError(IStatus* status); +}; + +void CryptKeyHolder::noKeyError(IStatus* status) +{ + 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->set(vector); +} + +int FB_CARG CryptKeyHolder::keyCallback(IStatus* status, ICryptKeyCallback* callback) +{ + status->init(); + + if (key != 0) + { + return 1; + } + + IConfig* def = config->getDefaultConfig(); + IConfigEntry* confEntry = def->find("Auto"); + def->release(); + if (confEntry) + { + char v = *(confEntry->getValue()); + confEntry->release(); + if (v == '1' || v == 'y' || v == 'Y' || v == 't' || v == 'T') + { + key = 0x5a; + return 1; + } + } + + if (callback && callback->callback(0, NULL, 1, &key) != 1) + { + key = 0; + return 0; + } + + return 1; +} + +ICryptKeyCallback* FB_CARG CryptKeyHolder::keyHandle(IStatus* status, const char* keyName) +{ + if (strcmp(keyName, "sample") != 0) + { + return NULL; + } + + return &callbackInterface; +} + +class Factory : public IPluginFactory +{ +public: + int FB_CARG getVersion() + { + return FB_PLUGIN_FACTORY_VERSION; + } + + IPluginModule* FB_CARG getModule() + { + return &module; + } + + IPluginBase* FB_CARG createPlugin(IPluginConfig* factoryParameter) + { + CryptKeyHolder* p = new CryptKeyHolder(factoryParameter); + p->addRef(); + return p; + } +}; + +Factory factory; + +} // anonymous namespace + +extern "C" void FB_PLUGIN_ENTRY_POINT(Firebird::IMaster* m) +{ + master = m; + pluginManager = master->getPluginManager(); + + module.registerMe(); + pluginManager->registerPluginFactory(PluginType::KeyHolder, "CryptKeyHolder_example", + &factory); +} Property changes on: firebird/trunk/examples/dbcrypt/CryptKeyHolder.cpp ___________________________________________________________________ Added: svn:mime-type + text/x-c++src Added: svn:eol-style + native Added: firebird/trunk/examples/dbcrypt/DbCrypt.cpp =================================================================== --- firebird/trunk/examples/dbcrypt/DbCrypt.cpp (rev 0) +++ firebird/trunk/examples/dbcrypt/DbCrypt.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -0,0 +1,266 @@ +/* + * PROGRAM: Firebird samples. + * MODULE: DbCrypt.cpp + * DESCRIPTION: Sample of how diskcrypt may be written. + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Alex Peshkov + * for the Firebird Open Source RDBMS project. + * + * Copyright (c) 2012 Alex Peshkov <peshkoff at mail.ru> + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#include "firebird.h" +#include "firebird/Crypt.h" + +#include "../common/classes/fb_atomic.h" + +using namespace Firebird; + +namespace +{ + +IMaster* master = NULL; +IPluginManager* pluginManager = NULL; + +class PluginModule : public IPluginModule +{ +public: + PluginModule() + : flag(false) + { } + + void registerMe() + { + pluginManager->registerModule(this); + flag = true; + } + + ~PluginModule() + { + if (flag) + { + pluginManager->unregisterModule(this); + doClean(); + } + } + + int FB_CARG getVersion() + { + return FB_PLUGIN_MODULE_VERSION; + } + + IPluginModule* FB_CARG getModule() + { + return this; + } + + void FB_CARG doClean() + { + flag = false; + } + +private: + bool flag; +}; + +PluginModule module; + +class DbCrypt : public IDbCryptPlugin +{ +public: + explicit DbCrypt(IPluginConfig* cnf) + : config(cnf), key(0), owner(NULL) + { + config->addRef(); + } + + ~DbCrypt() + { + config->release(); + } + + // ICryptPlugin implementation + void FB_CARG encrypt(IStatus* status, unsigned int length, const void* from, void* to); + void FB_CARG decrypt(IStatus* status, unsigned int length, const void* from, void* to); + void FB_CARG setKey(IStatus* status, unsigned int length, IKeyHolderPlugin** sources); + + int FB_CARG release() + { + if (--refCounter == 0) + { + delete this; + return 0; + } + return 1; + } + + void FB_CARG addRef() + { + ++refCounter; + } + + int FB_CARG getVersion() + { + return FB_DBCRYPT_PLUGIN_VERSION; + } + + IPluginModule* FB_CARG getModule() + { + return &module; + } + + void FB_CARG setOwner(Firebird::IRefCounted* o) + { + owner = o; + } + + IRefCounted* FB_CARG getOwner() + { + return owner; + } + +private: + IPluginConfig* config; + UCHAR key; + + AtomicCounter refCounter; + IRefCounted* owner; + + void noKeyError(IStatus* status); +}; + +void DbCrypt::noKeyError(IStatus* status) +{ + 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->set(vector); +} + +void FB_CARG DbCrypt::encrypt(IStatus* status, unsigned int length, const void* from, void* to) +{ + status->init(); + + if (!key) + { + noKeyError(status); + return; + } + + const UCHAR* f = static_cast<const UCHAR*>(from); + UCHAR* t = static_cast<UCHAR*>(to); + while(length--) + { + *t++ = (*f++) + key; + } +} + +void FB_CARG DbCrypt::decrypt(IStatus* status, unsigned int length, const void* from, void* to) +{ + status->init(); + + if (!key) + { + noKeyError(status); + return; + } + + const UCHAR* f = static_cast<const UCHAR*>(from); + UCHAR* t = static_cast<UCHAR*>(to); + while(length--) + { + *t++ = (*f++) - key; + } +} + +void FB_CARG DbCrypt::setKey(IStatus* status, unsigned int length, IKeyHolderPlugin** sources) +{ + status->init(); + + if (key != 0) + return; + + IConfig* def = config->getDefaultConfig(); + IConfigEntry* confEntry = def->find("Auto"); + def->release(); + if (confEntry) + { + char v = *(confEntry->getValue()); + confEntry->release(); + if (v == '1' || v == 'y' || v == 'Y' || v == 't' || v == 'T') + { + key = 0x5a; + return; + } + } + + for (unsigned n = 0; n < length; ++n) + { + ICryptKeyCallback* callback = sources[n]->keyHandle(status, "sample"); + if (!status->isSuccess()) + { + return; + } + + if (callback && callback->callback(0, NULL, 1, &key) == 1) + { + return; + } + } + + key = 0; + noKeyError(status); +} + +class Factory : public IPluginFactory +{ +public: + int FB_CARG getVersion() + { + return FB_PLUGIN_FACTORY_VERSION; + } + + IPluginModule* FB_CARG getModule() + { + return &module; + } + + IPluginBase* FB_CARG createPlugin(IPluginConfig* factoryParameter) + { + DbCrypt* p = new DbCrypt(factoryParameter); + p->addRef(); + return p; + } +}; + +Factory factory; + +} // anonymous namespace + +extern "C" void FB_PLUGIN_ENTRY_POINT(Firebird::IMaster* m) +{ + master = m; + pluginManager = master->getPluginManager(); + + module.registerMe(); + pluginManager->registerPluginFactory(PluginType::DbCrypt, "DbCrypt_example", + &factory); +} Property changes on: firebird/trunk/examples/dbcrypt/DbCrypt.cpp ___________________________________________________________________ Added: svn:mime-type + text/x-c++src Added: svn:eol-style + native Added: firebird/trunk/examples/dbcrypt/ReadMe.txt =================================================================== --- firebird/trunk/examples/dbcrypt/ReadMe.txt (rev 0) +++ firebird/trunk/examples/dbcrypt/ReadMe.txt 2012-05-31 16:53:42 UTC (rev 54574) @@ -0,0 +1,2 @@ +All files in this directory are trivial samples. +They do not perform any real data encryption and should not be used in production! Property changes on: firebird/trunk/examples/dbcrypt/ReadMe.txt ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:eol-style + native Modified: firebird/trunk/src/auth/SecureRemotePassword/manage/SrpManagement.cpp =================================================================== --- firebird/trunk/src/auth/SecureRemotePassword/manage/SrpManagement.cpp 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/auth/SecureRemotePassword/manage/SrpManagement.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -216,8 +216,7 @@ dpb.insertString(isc_dpb_trusted_role, ADMIN_ROLE, strlen(ADMIN_ROLE)); } - Firebird::RefPtr<Firebird::IProvider> p(Firebird::MasterInterfacePtr()->getDispatcher()); - p->release(); + Firebird::DispatcherPtr p; att = p->attachDatabase(status, secDbName, dpb.getBufferLength(), dpb.getBuffer()); if (!status->isSuccess()) { Modified: firebird/trunk/src/auth/SecureRemotePassword/server/SrpServer.cpp =================================================================== --- firebird/trunk/src/auth/SecureRemotePassword/server/SrpServer.cpp 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/auth/SecureRemotePassword/server/SrpServer.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -123,8 +123,7 @@ const char* str = "SYSDBA"; dpb.insertString(isc_dpb_user_name, str, strlen(str)); - RefPtr<IProvider> p(MasterInterfacePtr()->getDispatcher()); - p->release(); + DispatcherPtr p; att = p->attachDatabase(status, secDbName, dpb.getBufferLength(), dpb.getBuffer()); if (!status->isSuccess()) Modified: firebird/trunk/src/common/IntlUtil.cpp =================================================================== --- firebird/trunk/src/common/IntlUtil.cpp 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/common/IntlUtil.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -27,6 +27,7 @@ #include "firebird.h" #include "../common/IntlUtil.h" #include "../common/unicode_util.h" +#include "../jrd/intl.h" #include "../jrd/intl_classes.h" #include "../intl/country_codes.h" #include "../common/classes/auto.h" Modified: firebird/trunk/src/common/TextType.cpp =================================================================== --- firebird/trunk/src/common/TextType.cpp 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/common/TextType.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -93,7 +93,6 @@ #include "firebird.h" #include "gen/iberror.h" -#include "../jrd/jrd.h" #include "../jrd/intl_classes.h" #include "../common/IntlUtil.h" #include "../common/classes/Aligner.h" @@ -380,5 +379,14 @@ return srcLen / getCharSet()->minBytesPerChar(); } +BYTE TextType::getCanonicalWidth() const +{ + return tt->texttype_canonical_width; +} +USHORT TextType::getFlags() const +{ + return tt->texttype_flags; +} + } // namespace Jrd Modified: firebird/trunk/src/common/TextType.h =================================================================== --- firebird/trunk/src/common/TextType.h 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/common/TextType.h 2012-05-31 16:53:42 UTC (rev 54574) @@ -30,6 +30,8 @@ #ifndef JRD_TEXTTYPE_H #define JRD_TEXTTYPE_H +#include "../common/classes/MetaName.h" + struct texttype; namespace Jrd { @@ -85,16 +87,9 @@ return cs; } - BYTE getCanonicalWidth() const - { - return tt->texttype_canonical_width; - } + BYTE getCanonicalWidth() const; + USHORT getFlags() const; - USHORT getFlags() const - { - return tt->texttype_flags; - } - public: Firebird::MetaName name; Modified: firebird/trunk/src/common/classes/GetPlugins.h =================================================================== --- firebird/trunk/src/common/classes/GetPlugins.h 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/common/classes/GetPlugins.h 2012-05-31 16:53:42 UTC (rev 54574) @@ -47,7 +47,7 @@ { LocalStatus status; pluginSet = pluginInterface->getPlugins(&status, interfaceType, - (namesList ? namesList : Config::getPlugins(interfaceType)), + (namesList ? namesList : Config::getDefaultConfig()->getPlugins(interfaceType)), desiredVersion, ui, NULL); if (!pluginSet) @@ -67,7 +67,7 @@ { LocalStatus status; pluginSet = pluginInterface->getPlugins(&status, interfaceType, - (namesList ? namesList : Config::getPlugins(interfaceType)), + (namesList ? namesList : knownConfig->getPlugins(interfaceType)), desiredVersion, ui, new FirebirdConf(knownConfig)); if (!pluginSet) Modified: firebird/trunk/src/common/classes/ImplementHelper.h =================================================================== --- firebird/trunk/src/common/classes/ImplementHelper.h 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/common/classes/ImplementHelper.h 2012-05-31 16:53:42 UTC (rev 54574) @@ -232,6 +232,21 @@ }; +// Dispatcher access +class DispatcherPtr : public AccessAutoInterface<IProvider> +{ +public: + DispatcherPtr() + : AccessAutoInterface<IProvider>(getMasterInterface()->getDispatcher()) + { } + + ~DispatcherPtr() + { + (*this)->release(); + } +}; + + // When process exits, dynamically loaded modules (for us plugin modules) // are unloaded first. As the result all global variables in plugin are already destroyed // when yvalve is starting fb_shutdown(). This causes almost unavoidable segfault. Modified: firebird/trunk/src/common/config/config.cpp =================================================================== --- firebird/trunk/src/common/config/config.cpp 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/common/config/config.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -175,7 +175,9 @@ {TYPE_BOOLEAN, "SharedCache", (ConfigValue) true}, {TYPE_BOOLEAN, "SharedDatabase", (ConfigValue) false}, {TYPE_STRING, "WireCrypt", (ConfigValue) NULL}, - {TYPE_STRING, "CryptPlugin", (ConfigValue) "Arc4"} + {TYPE_STRING, "WireCryptPlugin", (ConfigValue) "Arc4"}, + {TYPE_STRING, "DbCryptPlugin", (ConfigValue) ""}, + {TYPE_STRING, "KeyHolderPlugin", (ConfigValue) ""} }; /****************************************************************************** @@ -663,22 +665,26 @@ #endif } -const char* Config::getPlugins(unsigned int type) +const char* Config::getPlugins(unsigned int type) const { switch (type) { case Firebird::PluginType::Provider: - return (const char*) getDefaultConfig()->values[KEY_PLUG_PROVIDERS]; + return (const char*) values[KEY_PLUG_PROVIDERS]; case Firebird::PluginType::AuthServer: - return (const char*) getDefaultConfig()->values[KEY_PLUG_AUTH_SERVER]; + return (const char*) values[KEY_PLUG_AUTH_SERVER]; case Firebird::PluginType::AuthClient: - return (const char*) getDefaultConfig()->values[KEY_PLUG_AUTH_CLIENT]; + return (const char*) values[KEY_PLUG_AUTH_CLIENT]; case Firebird::PluginType::AuthUserManagement: - return (const char*) getDefaultConfig()->values[KEY_PLUG_AUTH_MANAGE]; + return (const char*) values[KEY_PLUG_AUTH_MANAGE]; case Firebird::PluginType::Trace: - return (const char*) getDefaultConfig()->values[KEY_PLUG_TRACE]; - case Firebird::PluginType::Crypt: - return (const char*) getDefaultConfig()->values[KEY_PLUG_CRYPT]; + return (const char*) values[KEY_PLUG_TRACE]; + case Firebird::PluginType::WireCrypt: + return (const char*) values[KEY_PLUG_WIRE_CRYPT]; + case Firebird::PluginType::DbCrypt: + return (const char*) values[KEY_PLUG_DB_CRYPT]; + case Firebird::PluginType::KeyHolder: + return (const char*) values[KEY_PLUG_KEY_HOLDER]; } (Firebird::Arg::Gds(isc_random) << "Internal error in Config::getPlugins()").raise(); Modified: firebird/trunk/src/common/config/config.h =================================================================== --- firebird/trunk/src/common/config/config.h 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/common/config/config.h 2012-05-31 16:53:42 UTC (rev 54574) @@ -140,7 +140,9 @@ KEY_SHARED_CACHE, KEY_SHARED_DATABASE, KEY_WIRE_CRYPT, - KEY_PLUG_CRYPT, + KEY_PLUG_WIRE_CRYPT, + KEY_PLUG_DB_CRYPT, + KEY_PLUG_KEY_HOLDER, MAX_CONFIG_KEY // keep it last }; @@ -337,7 +339,7 @@ static bool getMultiClientServer(); - static const char* getPlugins(unsigned int type); + const char* getPlugins(unsigned int type) const; const char* getSecurityDatabase() const; Modified: firebird/trunk/src/common/isc.cpp =================================================================== --- firebird/trunk/src/common/isc.cpp 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/common/isc.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -42,7 +42,6 @@ #include "gen/iberror.h" #include "../jrd/ibase.h" -#include "../jrd/jrd.h" #include "../jrd/scl.h" #include "../yvalve/gds_proto.h" #include "../common/isc_proto.h" Modified: firebird/trunk/src/common/isc_file.cpp =================================================================== --- firebird/trunk/src/common/isc_file.cpp 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/common/isc_file.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -47,7 +47,6 @@ #include <string.h> #include <ctype.h> #include "gen/iberror.h" -#include "../jrd/jrd.h" #include "../yvalve/gds_proto.h" #include "../common/isc_proto.h" #include "../common/isc_f_proto.h" @@ -1296,9 +1295,9 @@ /************************************** * * g e t _ m o u n t s ( S Y S T E M _ V ) - * ( E P S O N ) - * ( M 8 8 K ) - * ( U N I X W A R E ) + * ( E P S O N ) + * ( M 8 8 K ) + * ( U N I X W A R E ) * ************************************** * @@ -1401,7 +1400,9 @@ const char* start = device; if (n<5) - return false; + { + return false; + } const char* iflag = strchr(device, ':'); if (iflag) Modified: firebird/trunk/src/common/sdl.cpp =================================================================== --- firebird/trunk/src/common/sdl.cpp 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/common/sdl.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -23,7 +23,6 @@ #include "firebird.h" #include <string.h> -#include "../jrd/jrd.h" #include "../jrd/ibase.h" #include "../jrd/val.h" #include "../common/sdl.h" Modified: firebird/trunk/src/dsql/BoolNodes.cpp =================================================================== --- firebird/trunk/src/dsql/BoolNodes.cpp 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/dsql/BoolNodes.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -34,6 +34,7 @@ #include "../jrd/intl_proto.h" #include "../jrd/mov_proto.h" #include "../jrd/par_proto.h" +#include "../jrd/Collation.h" #include "../dsql/ddl_proto.h" #include "../dsql/errd_proto.h" #include "../dsql/gen_proto.h" Modified: firebird/trunk/src/dsql/DdlNodes.epp =================================================================== --- firebird/trunk/src/dsql/DdlNodes.epp 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/dsql/DdlNodes.epp 2012-05-31 16:53:42 UTC (rev 54574) @@ -9946,6 +9946,22 @@ if (!tdbb->getAttachment()->locksmith()) status_exception::raise(Arg::Gds(isc_adm_task_denied)); + if (cryptPlugin.hasData()) + { + DFW_post_work(transaction, dfw_db_crypt, cryptPlugin.c_str(), 0); + } + + if (clauses & CLAUSE_DECRYPT) + { + DFW_post_work(transaction, dfw_db_crypt, "", 0); + } + + if (!(clauses & RDB_DATABASE_MASK)) + { + // No clauses requiring rdb$database present - work is done + return; + } + // run all statements under savepoint control AutoSavePoint savePoint(tdbb, transaction); Modified: firebird/trunk/src/dsql/DdlNodes.h =================================================================== --- firebird/trunk/src/dsql/DdlNodes.h 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/dsql/DdlNodes.h 2012-05-31 16:53:42 UTC (rev 54574) @@ -1950,10 +1950,13 @@ class AlterDatabaseNode : public DdlNode { public: - static const unsigned CLAUSE_BEGIN_BACKUP = 0x01; - static const unsigned CLAUSE_END_BACKUP = 0x02; - static const unsigned CLAUSE_DROP_DIFFERENCE = 0x04; + static const unsigned CLAUSE_BEGIN_BACKUP = 0x01; + static const unsigned CLAUSE_END_BACKUP = 0x02; + static const unsigned CLAUSE_DROP_DIFFERENCE = 0x04; + static const unsigned CLAUSE_DECRYPT = 0x08; + static const unsigned RDB_DATABASE_MASK = CLAUSE_BEGIN_BACKUP | CLAUSE_END_BACKUP | CLAUSE_DROP_DIFFERENCE; + public: AlterDatabaseNode(MemoryPool& p) : DdlNode(p), @@ -1963,7 +1966,8 @@ differenceFile(p), setDefaultCharSet(p), setDefaultCollation(p), - files(p) + files(p), + cryptPlugin(p) { } @@ -1996,6 +2000,7 @@ Firebird::MetaName setDefaultCharSet; Firebird::MetaName setDefaultCollation; Firebird::Array<NestConst<DbFileClause> > files; + Firebird::MetaName cryptPlugin; }; Modified: firebird/trunk/src/dsql/ExprNodes.cpp =================================================================== --- firebird/trunk/src/dsql/ExprNodes.cpp 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/dsql/ExprNodes.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -56,6 +56,7 @@ #include "../dsql/utld_proto.h" #include "../dsql/DSqlDataTypeUtil.h" #include "../jrd/DataTypeUtil.h" +#include "../jrd/Collation.h" using namespace Firebird; using namespace Jrd; Modified: firebird/trunk/src/dsql/parse.y =================================================================== --- firebird/trunk/src/dsql/parse.y 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/dsql/parse.y 2012-05-31 16:53:42 UTC (rev 54574) @@ -547,6 +547,8 @@ %token <legacyStr> BODY %token <legacyStr> CONTINUE %token <legacyStr> DDL +%token <legacyStr> DECRYPT +%token <legacyStr> ENCRYPT %token <legacyStr> ENGINE %token <legacyStr> NAME %token <legacyStr> OVER @@ -3546,6 +3548,10 @@ { $alterDatabaseNode->clauses |= AlterDatabaseNode::CLAUSE_END_BACKUP; } | SET DEFAULT CHARACTER SET symbol_character_set_name { $alterDatabaseNode->setDefaultCharSet = toName($5); } + | ENCRYPT WITH valid_symbol_name + { $alterDatabaseNode->cryptPlugin = toName($3); } + | DECRYPT + { $alterDatabaseNode->clauses |= AlterDatabaseNode::CLAUSE_DECRYPT; } ; @@ -6842,6 +6848,8 @@ | BODY | CONTINUE | DDL + | DECRYPT + | ENCRYPT | ENGINE | IDENTITY | NAME Modified: firebird/trunk/src/gpre/boot/gpre_meta_boot.cpp =================================================================== --- firebird/trunk/src/gpre/boot/gpre_meta_boot.cpp 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/gpre/boot/gpre_meta_boot.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -744,6 +744,11 @@ fb_assert(false); return NULL; } + + virtual int FB_CARG same(IVersioned* /*first*/, IVersioned* /*second*/) + { + return 0; + } }; Modified: firebird/trunk/src/include/consts_pub.h =================================================================== --- firebird/trunk/src/include/consts_pub.h 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/include/consts_pub.h 2012-05-31 16:53:42 UTC (rev 54574) @@ -505,6 +505,7 @@ #define isc_spb_sts_record_versions 0x20 #define isc_spb_sts_table 0x40 #define isc_spb_sts_nocreation 0x80 +#define isc_spb_sts_encryption 0x100 /***********************************/ /* Server configuration key values */ Modified: firebird/trunk/src/include/firebird/Crypt.h =================================================================== --- firebird/trunk/src/include/firebird/Crypt.h 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/include/firebird/Crypt.h 2012-05-31 16:53:42 UTC (rev 54574) @@ -27,26 +27,71 @@ namespace Firebird { -class ICrypt : public IRefCounted +// Part 1. Network crypt. + +// Plugins of this type are used to crypt data, sent over the wire +// Plugin must support encrypt and decrypt operations +// Interface of plugin is the same for both client and server, +// and it may have differerent or same implementations for client and server +class IWireCryptPlugin : public IPluginBase { public: - virtual void FB_CARG transform(IStatus* status, unsigned int length, const void* from, void* to) = 0; + // getKnownTypes() function must return list of acceptable keys' types + // special type 'builtin' means that crypt plugin knows itself where to get the key from + virtual const char* FB_CARG getKnownTypes(IStatus* status) = 0; + virtual void FB_CARG setKey(IStatus* status, FbCryptKey* key) = 0; + virtual void FB_CARG encrypt(IStatus* status, unsigned int length, const void* from, void* to) = 0; + virtual void FB_CARG decrypt(IStatus* status, unsigned int length, const void* from, void* to) = 0; }; -#define FB_CRYPT_VERSION (FB_REFCOUNTED_VERSION + 1) +#define FB_WIRECRYPT_PLUGIN_VERSION (FB_PLUGIN_VERSION + 4) -class ICryptPlugin : public IPluginBase +// Part 2. Database crypt. + +// This interface is used to transfer some data (related with crypt keys) +// between different components of firebird +class ICryptKeyCallback : public IVersioned { public: - // getKnownTypes() function must return list of acceptable keys' types - // special type 'builtin' means that crypt plugin knows itself where to get the key from - virtual const char* FB_CARG getKnownTypes(IStatus* status) = 0; - virtual ICrypt* FB_CARG getEncrypt(IStatus* status, FbCryptKey* key) = 0; - virtual ICrypt* FB_CARG getDecrypt(IStatus* status, FbCryptKey* key) = 0; + virtual unsigned int FB_CARG callback(unsigned int dataLength, const void* data, + unsigned int bufferLength, void* buffer) = 0; }; -#define FB_CRYPT_PLUGIN_VERSION (FB_PLUGIN_VERSION + 3) +#define FB_CRYPT_CALLBACK_VERSION (FB_VERSIONED_VERSION + 1) +// Key holder accepts key(s) from attachment at database attach time +// (or gets them it some other arbitrary way) +// and sends it to database crypt plugin on request +class IKeyHolderPlugin : public IPluginBase +{ +public: + // keyCallback() is called when new attachment is probably ready to provide keys + // to key holder plugin, ICryptKeyCallback interface is provided by attachment + virtual int FB_CARG keyCallback(IStatus* status, ICryptKeyCallback* callback) = 0; + // Crypt plugin calls keyHandle() whne it needs a key, stored in key holder + // Key is not returned directly - instead of it callback interface is returned + // Missing key with given name is not an error condition for keyHandle() + // It should just return NULL in this case + virtual ICryptKeyCallback* FB_CARG keyHandle(IStatus* status, const char* keyName) = 0; +}; + +#define FB_KEYHOLDER_PLUGIN_VERSION (FB_PLUGIN_VERSION + 2) + +class IDbCryptPlugin : public IPluginBase +{ +public: + // When database crypt plugin is loaded, setKey() is called to provide information + // about key holders, available for givaen 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 + virtual void FB_CARG setKey(IStatus* status, unsigned int length, IKeyHolderPlugin** sources) = 0; + virtual void FB_CARG encrypt(IStatus* status, unsigned int length, const void* from, void* to) = 0; + virtual void FB_CARG decrypt(IStatus* status, unsigned int length, const void* from, void* to) = 0; +}; + +#define FB_DBCRYPT_PLUGIN_VERSION (FB_PLUGIN_VERSION + 3) + } // namespace Firebird Modified: firebird/trunk/src/include/firebird/Interface.h =================================================================== --- firebird/trunk/src/include/firebird/Interface.h 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/include/firebird/Interface.h 2012-05-31 16:53:42 UTC (rev 54574) @@ -113,8 +113,11 @@ virtual IDtc* FB_CARG getDtc() = 0; virtual IAttachment* registerAttachment(IProvider* provider, IAttachment* attachment) = 0; virtual ITransaction* registerTransaction(IAttachment* attachment, ITransaction* transaction) = 0; + + // This function is required to compare interfaces based on vtables of them + virtual int FB_CARG same(IVersioned* first, IVersioned* second) = 0; }; -#define FB_MASTER_VERSION (FB_VERSIONED_VERSION + 9) +#define FB_MASTER_VERSION (FB_VERSIONED_VERSION + 10) } // namespace Firebird Modified: firebird/trunk/src/include/firebird/Plugin.h =================================================================== --- firebird/trunk/src/include/firebird/Plugin.h 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/include/firebird/Plugin.h 2012-05-31 16:53:42 UTC (rev 54574) @@ -220,9 +220,11 @@ static const unsigned int AuthUserManagement = 13; static const unsigned int ExternalEngine = 14; static const unsigned int Trace = 15; - static const unsigned int Crypt = 16; + static const unsigned int WireCrypt = 16; + static const unsigned int DbCrypt = 17; + static const unsigned int KeyHolder = 18; - static const unsigned int MaxType = 17; // keep in sync please + static const unsigned int MaxType = 19; // keep in sync please }; } // namespace Firebird Modified: firebird/trunk/src/include/firebird/Provider.h =================================================================== --- firebird/trunk/src/include/firebird/Provider.h 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/include/firebird/Provider.h 2012-05-31 16:53:42 UTC (rev 54574) @@ -36,6 +36,7 @@ // This interfaces are implemented by yvalve code and by each of providers. class IAttachment; // Forward +class ICryptKeyCallback; // From Crypt.h struct FbMessage { @@ -235,10 +236,11 @@ virtual IAttachment* FB_CARG createDatabase(IStatus* status, const char* fileName, unsigned int dpbLength, const unsigned char* dpb) = 0; virtual IService* FB_CARG attachServiceManager(IStatus* status, const char* service, - unsigned int spbLength, const unsigned char* spb) = 0; + unsigned int spbLength, const unsigned char* spb) = 0; virtual void FB_CARG shutdown(IStatus* status, unsigned int timeout, const int reason) = 0; + virtual void FB_CARG setDbCryptCallback(IStatus* status, ICryptKeyCallback* cryptCallback) = 0; }; -#define FB_PROVIDER_VERSION (FB_PLUGIN_VERSION + 4) +#define FB_PROVIDER_VERSION (FB_PLUGIN_VERSION + 5) // DtcStart - structure to start transaction over >1 attachments (former TEB) struct DtcStart Modified: firebird/trunk/src/include/gen/ids.h =================================================================== --- firebird/trunk/src/include/gen/ids.h 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/include/gen/ids.h 2012-05-31 16:53:42 UTC (rev 54574) @@ -479,6 +479,7 @@ const USHORT f_mon_db_pages = 16; const USHORT f_mon_db_stat_id = 17; const USHORT f_mon_db_backup_state = 18; + const USHORT f_mon_db_crypt_page = 19; // Relation 34 (MON$ATTACHMENTS) Modified: firebird/trunk/src/jrd/Attachment.cpp =================================================================== --- firebird/trunk/src/jrd/Attachment.cpp 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/jrd/Attachment.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -368,11 +368,7 @@ Lock* long_lock = att_long_locks; while (long_lock) { - Lock* next = long_lock->lck_next; - long_lock->lck_attachment = NULL; - long_lock->lck_next = NULL; - long_lock->lck_prior = NULL; - long_lock = next; + long_lock = long_lock->detach(); } att_long_locks = NULL; } Modified: firebird/trunk/src/jrd/Attachment.h =================================================================== --- firebird/trunk/src/jrd/Attachment.h 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/jrd/Attachment.h 2012-05-31 16:53:42 UTC (rev 54574) @@ -44,6 +44,10 @@ class Connection; } +namespace Firebird { + class ICryptKeyCallback; +} + class CharSetContainer; namespace Jrd @@ -273,6 +277,7 @@ Firebird::Array<JrdStatement*> att_internal; // internal statements Firebird::Array<JrdStatement*> att_dyn_req; // internal dyn statements + Firebird::ICryptKeyCallback* att_crypt_callback; // callback for DB crypt jrd_req* findSystemRequest(thread_db* tdbb, USHORT id, USHORT which); Modified: firebird/trunk/src/jrd/Collation.cpp =================================================================== --- firebird/trunk/src/jrd/Collation.cpp 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/jrd/Collation.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -99,6 +99,7 @@ #include "../jrd/intl_classes.h" #include "../jrd/lck_proto.h" #include "../jrd/intl_classes.h" +#include "../jrd/Collation.h" #include "../common/TextType.h" #include "../jrd/SimilarToMatcher.h" Modified: firebird/trunk/src/jrd/Collation.h =================================================================== --- firebird/trunk/src/jrd/Collation.h 2012-05-31 12:55:40 UTC (rev 54573) +++ firebird/trunk/src/jrd/Collation.h 2012-05-31 16:53:42 UTC (rev 54574) @@ -36,6 +36,7 @@ namespace Jrd { class Lock; +class BaseSubstringSimilarMatcher; class Collation : public TextType { Added: firebird/trunk/src/jrd/CryptoManager.cpp =================================================================== --- firebird/trunk/src/jrd/CryptoManager.cpp (rev 0) +++ firebird/trunk/src/jrd/CryptoManager.cpp 2012-05-31 16:53:42 UTC (rev 54574) @@ -0,0 +1,728 @@ +/* + * PROGRAM: JRD access method + * MODULE: CryptoManager.cpp + * DESCRIPTION: Database encryption + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Alex Peshkov + * for the Firebird Open Source RDBMS project. + * + * Copyright (c) 2008 Alex Peshkov <peshkoff at mail.ru> + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + * + * + */ + +#include "firebird.h" +#include "firebird/Crypt.h" +#include "gen/iberror.h" +#include "../jrd/CryptoManager.h" + +#include "../common/classes/alloc.h" +#include "../jrd/Database.h" +#include "../jrd/ods.h" +#include "../common/ThreadStart.h" +#include "../jrd/os/pio_proto.h" +#include "../common/StatusArg.h" +#include "../common/StatusHolder.h" +#include "../jrd/lck.h" +#include "../jrd/jrd.h" +#include "../jrd/pag.h" +#include "../jrd/nbak.h" +#include "../jrd/cch_proto.h" +#include "../jrd/lck_proto.h" +#include "../jrd/pag_proto.h" +#include "../common/isc_proto.h" +#include "../common/classes/GetPlugins.h" + +using namespace Firebird; + +namespace { + class SpareBuffer + { + public: + Ods::pag* get() + { + return buffer; + } + + private: + Ods::pag buffer[MAX_PAGE_SIZE / sizeof(Ods::pag)]; + }; + + THREAD_ENTRY_DECLARE cryptThreadStatic(THREAD_ENTRY_PARAM p) + { + Jrd::CryptoManager* cryptoManager = (Jrd::CryptoManager*)p; + cryptoManager->cryptThread(); + + return 0; + } + + class Header + { + public: + Header(Jrd::thread_db* p_tdbb, USHORT lockType) + : tdbb(p_tdbb), + window(Jrd::HEADER_PAGE_NUMBER), + header((Ods::header_page*) CCH_FETCH(tdbb, &window, lockType, pag_header)) + { + if (!header) + { + (Arg::Gds(isc_random) << "Header page fetch failed").raise(); + } + } + + Ods::header_page* write() + { + CCH_MARK_MUST_WRITE(tdbb, &window); + return header; + } + + void depends(Stack<ULONG>& pages) + { + while(pages.hasData()) + { + CCH_precedence(tdbb, &window, pages.pop()); + } + } + + const Ods::header_page* operator->() const + { + return header; + } + + operator const Ods::header_page*() const + { + return header; + } + + ~Header() + { + CCH_RELEASE(tdbb, &window); + } + + private: + Jrd::thread_db* tdbb; + Jrd::WIN window; + Ods::header_page* header; + }; + + class NoEntrypoint + { + public: + virtual void FB_CARG noEntrypoint(IStatus* s) + { + s->set(Arg::Gds(isc_wish_list).value()); + } + }; + + MakeUpgradeInfo<NoEntrypoint> upInfo; +} + +namespace Jrd { + + CryptoManager::CryptoManager(thread_db* tdbb) + : PermanentStorage(*tdbb->getDatabase()->dbb_permanent), + keyHolderPlugins(getPool()), + cryptThreadId(0), + cryptPlugin(NULL), + dbb(*tdbb->getDatabase()), + needLock(true), + crypt(false), + process(false), + down(false) + { + stateLock = FB_NEW_RPT(getPool(), 0) + Lock(tdbb, LCK_crypt_status, this, blockingAstChangeCryptState); + threadLock = FB_NEW_RPT(getPool(), 0) Lock(tdbb, LCK_crypt); + + takeStateLock(tdbb); + } + + CryptoManager::~CryptoManager() + { + } + + void CryptoManager::terminateCryptThread(thread_db*) + { + if (cryptThreadId) + { + down = true; + Thread::waitForCompletion(cryptThreadId); + cryptThreadId = 0; + } + } + + void CryptoManager::shutdown(thread_db* tdbb) + { + terminateCryptThread(tdbb); + + if (cryptPlugin) + { + PluginManagerInterfacePtr()->releasePlugin(cryptPlugin); + cryptPlugin = NULL; + } + + if (stateLock) + { + LCK_release(tdbb, stateLock); + stateLock = NULL; + } + } + + void CryptoManager::takeStateLock(thread_db* tdbb) + { + fb_assert(stateLock); + fb_assert(tdbb->getAttachment()); + + if (needLock) + { + if (!LCK_lock(tdbb, stateLock, LCK_SR, LCK_WAIT)) + { + fb_assert(tdbb->tdbb_status_vector[1]); + ERR_punt(); + } + + fb_utils::init_status(tdbb->tdbb_status_vector); + + needLock = false; + } + } + + void CryptoManager::loadPlugin(const char* pluginName) + { + MutexLockGuard guard(pluginLoadMtx); + + if (cryptPlugin) + { + return; + } + + GetPlugins<IDbCryptPlugin> cryptControl(PluginType::DbCrypt, FB_DBCRYPT_PLUGIN_VERSION, + upInfo, dbb.dbb_config, pluginName); + if (!cryptControl.hasData()) + { + (Arg::Gds(isc_random) << + "Invalid crypt plugin name").raise(); + } + + // do not assign cryptPlugin directly before key init complete + IDbCryptPlugin* p = cryptControl.plugin(); + keyHolderPlugins.init(p); + cryptPlugin = p; + cryptPlugin->addRef(); + } + + void CryptoManager::changeCryptState(thread_db* tdbb, const Firebird::string& plugName) + { + if (plugName.length() > 31) + { + (Arg::Gds(isc_random) << + "Crypt plugin name should not be >31 bytes").raise(); + } + + bool newCryptState = plugName.hasData(); + { // window scope + Header hdr(tdbb, LCK_write); + + // Check header page for flags + if (hdr->hdr_flags & Ods::hdr_crypt_process) + { + (Arg::Gds(isc_random) << + "Crypt failed - already crypting database").raise(); + } + + bool headerCryptState = hdr->hdr_flags & Ods::hdr_encrypted; + if (headerCryptState == newCryptState) + { + (Arg::Gds(isc_random) << + "Crypt failed - database is already in requested state").raise(); + } + + fb_assert(stateLock); + // Take exclusive stateLock + bool ret = needLock ? LCK_lock(tdbb, stateLock, LCK_PW, LCK_WAIT) : + LCK_convert(tdbb, stateLock, LCK_PW, LCK_WAIT); + if (!ret) + { + fb_assert(tdbb->tdbb_status_vector[1]); + ERR_punt(); + } + fb_utils::init_status(tdbb->tdbb_status_vector); + needLock = false; + + // Load plugin + if (newCryptState) + { + loadPlugin(plugName.c_str()); + } + crypt = newCryptState; + + // Write modified header page + Ods::header_page* header = hdr.write(); + if (crypt) + { + header->hdr_flags |= Ods::hdr_encrypted; + plugName.copyTo(header->hdr_crypt_plugin, sizeof header->hdr_crypt_plugin); + } + else + { + header->hdr_flags &= ~Ods::hdr_encrypted; + } + header->hdr_flags |= Ods::hdr_crypt_process; + process = true; + } + + // Trigger lock on ChangeCryptState + if (!LCK_convert(tdbb, stateLock, LCK_EX, LCK_WAIT)) + { + ERR_punt(); + } + + if (!LCK_convert(tdbb, stateLock, LCK_SR, LCK_WAIT)) + { + ERR_punt(); + } + fb_utils::init_status(tdbb->tdbb_status_vector); + + // Now we may set hdr_crypt_page for crypt thread + { // window scope + Header hdr(tdbb, LCK_write); + Ods::header_page* header = hdr.write(); + header->hdr_crypt_page = 1; + } + + startCryptThread(tdbb); + } + + void CryptoManager::blockingAstChangeCryptState() + { + AsyncContextHolder tdbb(&dbb); + + fb_assert(stateLock); + LCK_release(tdbb, stateLock); + needLock = true; + } + + void CryptoManager::startCryptThread(thread_db* tdbb) + { + // Take exclusive threadLock + // If can't take that lock - nothing to do, cryptThread already runs somewhere + if (LCK_lock(tdbb, threadLock, LCK_EX, LCK_NO_WAIT)) + { + // Cleanup resources + terminateCryptThread(tdbb); + down = false; + + // Determine current page from the header + Header hdr(tdbb, LCK_read); + process = hdr->hdr_flags & Ods::h... [truncated message content] |