From: <ale...@us...> - 2012-02-24 12:39:36
|
Revision: 54041 http://firebird.svn.sourceforge.net/firebird/?rev=54041&view=rev Author: alexpeshkoff Date: 2012-02-24 12:39:27 +0000 (Fri, 24 Feb 2012) Log Message: ----------- Implemented CORE-672: "Over the wire" connection encryption Modified Paths: -------------- firebird/trunk/builds/install/misc/firebird.conf.in firebird/trunk/builds/posix/make.shared.variables firebird/trunk/src/auth/AuthDbg.cpp firebird/trunk/src/auth/AuthDbg.h firebird/trunk/src/auth/SecureRemotePassword/client/SrpClient.cpp firebird/trunk/src/auth/SecureRemotePassword/server/SrpServer.cpp firebird/trunk/src/auth/SecurityDatabase/LegacyClient.cpp firebird/trunk/src/auth/SecurityDatabase/LegacyClient.h firebird/trunk/src/auth/SecurityDatabase/LegacyServer.cpp firebird/trunk/src/auth/SecurityDatabase/LegacyServer.h firebird/trunk/src/auth/trusted/AuthSspi.cpp firebird/trunk/src/auth/trusted/AuthSspi.h firebird/trunk/src/common/classes/ClumpletWriter.cpp firebird/trunk/src/common/classes/ClumpletWriter.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/include/firebird/Auth.h firebird/trunk/src/include/firebird/Plugin.h 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/remot_proto.h firebird/trunk/src/remote/remote.cpp firebird/trunk/src/remote/remote.h firebird/trunk/src/remote/server/server.cpp Added Paths: ----------- firebird/trunk/src/include/firebird/Crypt.h firebird/trunk/src/plugins/crypt/arc4/Arc4.cpp firebird/trunk/src/plugins/crypt/arc4/Arc4.h Modified: firebird/trunk/builds/install/misc/firebird.conf.in =================================================================== --- firebird/trunk/builds/install/misc/firebird.conf.in 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/builds/install/misc/firebird.conf.in 2012-02-24 12:39:27 UTC (rev 54041) @@ -362,7 +362,10 @@ # #TracePlugin = fbtrace +# Crypt plugins are used to crypt data transfered over the wire +#CryptPlugin = Arc4 + # ---------------------------- # # This parameter determines what providers will be used by firebird. Modified: firebird/trunk/builds/posix/make.shared.variables =================================================================== --- firebird/trunk/builds/posix/make.shared.variables 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/builds/posix/make.shared.variables 2012-02-24 12:39:27 UTC (rev 54041) @@ -54,7 +54,8 @@ $(call makeObjects,auth/SecurityDatabase,LegacyServer.cpp) # legacy security database LegacyServer.cpp should become plugin soon Remote_Client:= $(call dirObjects,remote/client) $(call dirObjects,auth/SecureRemotePassword/client) \ - $(call makeObjects,auth/SecurityDatabase,LegacyClient.cpp) + $(call makeObjects,auth/SecurityDatabase,LegacyClient.cpp) \ + $(call dirObjects,plugins/crypt/arc4) Remote_Server_Objects:= $(Remote_Common) $(Remote_Server) Remote_Client_Objects:= $(Remote_Common) $(Remote_Client) Modified: firebird/trunk/src/auth/AuthDbg.cpp =================================================================== --- firebird/trunk/src/auth/AuthDbg.cpp 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/auth/AuthDbg.cpp 2012-02-24 12:39:27 UTC (rev 54041) @@ -56,7 +56,7 @@ : str(getPool()) { } -Result FB_CARG DebugServer::authenticate(Firebird::IStatus* status, IServerBlock* sBlock, +int FB_CARG DebugServer::authenticate(Firebird::IStatus* status, IServerBlock* sBlock, IWriter* writerInterface) { /* try @@ -90,7 +90,7 @@ return AUTH_FAILED; } /* -Result FB_CARG DebugServer::contAuthentication(Firebird::IStatus* status, const unsigned char* data, +int FB_CARG DebugServer::contAuthentication(Firebird::IStatus* status, const unsigned char* data, unsigned int size, IWriter* writerInterface) { try @@ -125,7 +125,7 @@ : str(getPool()) { } -Result FB_CARG DebugClient::authenticate(Firebird::IStatus* status, IClientBlock* cBlock) +int FB_CARG DebugClient::authenticate(Firebird::IStatus* status, IClientBlock* cBlock) { /* try @@ -153,7 +153,7 @@ return AUTH_FAILED; } /* -Result FB_CARG DebugClient::contAuthentication(Firebird::IStatus* status, const unsigned char* data, unsigned int size) +int FB_CARG DebugClient::contAuthentication(Firebird::IStatus* status, const unsigned char* data, unsigned int size) { try { @@ -187,22 +187,6 @@ return 1; } -Result DebugServer::getSessionKey(Firebird::IStatus*, - const unsigned char** key, unsigned int* keyLen) -{ - *key = NULL; - *keyLen = 0; - return AUTH_CONTINUE; -} - -Result DebugClient::getSessionKey(Firebird::IStatus*, - const unsigned char** key, unsigned int* keyLen) -{ - *key = NULL; - *keyLen = 0; - return AUTH_CONTINUE; -} - } // namespace Auth #endif // AUTH_DEBUG Modified: firebird/trunk/src/auth/AuthDbg.h =================================================================== --- firebird/trunk/src/auth/AuthDbg.h 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/auth/AuthDbg.h 2012-02-24 12:39:27 UTC (rev 54041) @@ -51,10 +51,8 @@ public: DebugServer(Firebird::IPluginConfig*); - Result authenticate(Firebird::IStatus* status, IServerBlock* sBlock, - IWriter* writerInterface); - Result getSessionKey(Firebird::IStatus* status, - const unsigned char** key, unsigned int* keyLen); + int authenticate(Firebird::IStatus* status, IServerBlock* sBlock, + IWriter* writerInterface); int release(); private: @@ -66,9 +64,7 @@ public: DebugClient(Firebird::IPluginConfig*); - Result authenticate(Firebird::IStatus* status, IClientBlock* sBlock); - Result getSessionKey(Firebird::IStatus* status, - const unsigned char** key, unsigned int* keyLen); + int authenticate(Firebird::IStatus* status, IClientBlock* sBlock); int release(); private: Modified: firebird/trunk/src/auth/SecureRemotePassword/client/SrpClient.cpp =================================================================== --- firebird/trunk/src/auth/SecureRemotePassword/client/SrpClient.cpp 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/auth/SecureRemotePassword/client/SrpClient.cpp 2012-02-24 12:39:27 UTC (rev 54041) @@ -43,8 +43,7 @@ { } // IClient implementation - Result FB_CARG authenticate(IStatus*, IClientBlock* cb); - Result FB_CARG getSessionKey(IStatus* status, const unsigned char** key, unsigned int* keyLen); + int FB_CARG authenticate(IStatus*, IClientBlock* cb); int FB_CARG release(); private: @@ -53,7 +52,7 @@ UCharBuffer sessionKey; }; -Result SrpClient::authenticate(IStatus* status, IClientBlock* cb) +int SrpClient::authenticate(IStatus* status, IClientBlock* cb) { try { @@ -74,8 +73,8 @@ client = new RemotePassword; client->genClientKey(data); dumpIt("Clnt: clientPubKey", data); - cb->putData(data.length(), data.begin()); - return AUTH_MORE_DATA; + cb->putData(status, data.length(), data.begin()); + return status->isSuccess() ? AUTH_MORE_DATA : AUTH_FAILED; } HANDSHAKE_DEBUG(fprintf(stderr, "Cln SRP2\n")); @@ -110,7 +109,6 @@ msg.printf("Wrong length (%d) of key from server", charSize); (Arg::Gds(isc_random) << msg).raise(); } - key.assign(saltAndKey, charSize); dumpIt("Clnt: key(srvPub)", key); @@ -122,7 +120,19 @@ BigInteger cProof = client->clientProof(cb->getLogin(), salt.c_str(), sessionKey); cProof.getText(data); - cb->putData(data.length(), data.c_str()); + cb->putData(status, data.length(), data.c_str()); + if (!status->isSuccess()) + { + return AUTH_FAILED; + } + + // output the key + FbCryptKey cKey = {"Symmetric", sessionKey.begin(), NULL, sessionKey.getCount(), 0}; + cb->putKey(status, &cKey); + if (!status->isSuccess()) + { + return AUTH_FAILED; + } } catch (const Exception& ex) { @@ -133,20 +143,6 @@ return AUTH_SUCCESS; } - -Result SrpClient::getSessionKey(IStatus*, const unsigned char** key, unsigned int* keyLen) -{ - if (!sessionKey.hasData()) - { - return AUTH_MORE_DATA; - } - - *key = sessionKey.begin(); - *keyLen = sessionKey.getCount(); - - return AUTH_SUCCESS; -} - int SrpClient::release() { if (--refCounter == 0) Modified: firebird/trunk/src/auth/SecureRemotePassword/server/SrpServer.cpp =================================================================== --- firebird/trunk/src/auth/SecureRemotePassword/server/SrpServer.cpp 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/auth/SecureRemotePassword/server/SrpServer.cpp 2012-02-24 12:39:27 UTC (rev 54041) @@ -61,8 +61,7 @@ } // IServer implementation - Result FB_CARG authenticate(IStatus* status, IServerBlock* sBlock, IWriter* writerInterface); - Result FB_CARG getSessionKey(IStatus* status, const unsigned char** key, unsigned int* keyLen); + int FB_CARG authenticate(IStatus* status, IServerBlock* sBlock, IWriter* writerInterface); int FB_CARG release(); private: @@ -77,7 +76,7 @@ const char* secDbName; }; -Result SrpServer::authenticate(IStatus* status, IServerBlock* sb, IWriter* writerInterface) +int SrpServer::authenticate(IStatus* status, IServerBlock* sb, IWriter* writerInterface) { RefPtr<IAttachment> att; RefPtr<ITransaction> tra; @@ -239,13 +238,24 @@ data.append(serverPubKey); dumpIt("Srv: serverPubKey", serverPubKey); dumpIt("Srv: data", data); - sb->putData(data.length(), data.c_str()); + sb->putData(status, data.length(), data.c_str()); + if (!status->isSuccess()) + { + return AUTH_FAILED; + } - // Will be used to produce ISessionKey dumpIt("Srv: clientPubKey", clientPubKey); server->serverSessionKey(sessionKey, clientPubKey.c_str(), verifier); dumpIt("Srv: sessionKey", sessionKey); + // output the key + FbCryptKey cKey = {"Symmetric", sessionKey.begin(), NULL, sessionKey.getCount(), 0}; + sb->putKey(status, &cKey); + if (!status->isSuccess()) + { + return AUTH_FAILED; + } + return AUTH_MORE_DATA; } @@ -286,19 +296,6 @@ return AUTH_FAILED; } -Result SrpServer::getSessionKey(IStatus*, const unsigned char** key, unsigned int* keyLen) -{ - if (!sessionKey.hasData()) - { - return AUTH_MORE_DATA; - } - - *key = sessionKey.begin(); - *keyLen = sessionKey.getCount(); - - return AUTH_SUCCESS; -} - int SrpServer::release() { if (--refCounter == 0) Modified: firebird/trunk/src/auth/SecurityDatabase/LegacyClient.cpp =================================================================== --- firebird/trunk/src/auth/SecurityDatabase/LegacyClient.cpp 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/auth/SecurityDatabase/LegacyClient.cpp 2012-02-24 12:39:27 UTC (rev 54041) @@ -35,7 +35,7 @@ namespace Auth { -Result SecurityDatabaseClient::authenticate(Firebird::IStatus*, IClientBlock* cb) +int SecurityDatabaseClient::authenticate(Firebird::IStatus* status, IClientBlock* cb) { if (!(cb->getLogin() && cb->getPassword())) { @@ -44,19 +44,15 @@ TEXT pwt[Auth::MAX_LEGACY_PASSWORD_LENGTH + 2]; ENC_crypt(pwt, sizeof pwt, cb->getPassword(), Auth::LEGACY_PASSWORD_SALT); - cb->putData(strlen(&pwt[2]), &pwt[2]); + cb->putData(status, strlen(&pwt[2]), &pwt[2]); + if (! status->isSuccess()) + { + return AUTH_FAILED; + } return AUTH_SUCCESS; } -Result SecurityDatabaseClient::getSessionKey(Firebird::IStatus*, - const unsigned char** key, unsigned int* keyLen) -{ - *key = NULL; - *keyLen = 0; - return AUTH_CONTINUE; -} - int SecurityDatabaseClient::release() { if (--refCounter == 0) Modified: firebird/trunk/src/auth/SecurityDatabase/LegacyClient.h =================================================================== --- firebird/trunk/src/auth/SecurityDatabase/LegacyClient.h 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/auth/SecurityDatabase/LegacyClient.h 2012-02-24 12:39:27 UTC (rev 54041) @@ -43,9 +43,7 @@ } // IClient implementation - Result FB_CARG authenticate(Firebird::IStatus*, IClientBlock* data); - Result FB_CARG getSessionKey(Firebird::IStatus* status, - const unsigned char** key, unsigned int* keyLen); + int FB_CARG authenticate(Firebird::IStatus*, IClientBlock* data); int FB_CARG release(); }; Modified: firebird/trunk/src/auth/SecurityDatabase/LegacyServer.cpp =================================================================== --- firebird/trunk/src/auth/SecurityDatabase/LegacyServer.cpp 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/auth/SecurityDatabase/LegacyServer.cpp 2012-02-24 12:39:27 UTC (rev 54041) @@ -127,7 +127,7 @@ class SecurityDatabase : public Firebird::RefCntIface<Firebird::ITimer, FB_TIMER_VERSION> { public: - Result verify(IWriter* authBlock, IServerBlock* sBlock); + int verify(IWriter* authBlock, IServerBlock* sBlock); static int shutdown(const int, const int, void*); @@ -291,7 +291,7 @@ * Public interface */ -Result SecurityDatabase::verify(IWriter* authBlock, IServerBlock* sBlock) +int SecurityDatabase::verify(IWriter* authBlock, IServerBlock* sBlock) { static AmCache useNative = AM_UNKNOWN; @@ -451,7 +451,7 @@ const static unsigned int INIT_KEY = ((~0) - 1); static unsigned int secDbKey = INIT_KEY; -Result SecurityDatabaseServer::authenticate(Firebird::IStatus* status, IServerBlock* sBlock, +int SecurityDatabaseServer::authenticate(Firebird::IStatus* status, IServerBlock* sBlock, IWriter* writerInterface) { status->init(); @@ -501,7 +501,7 @@ fb_assert(instance); - Result rc = instance->verify(writerInterface, sBlock); + int rc = instance->verify(writerInterface, sBlock); TimerInterfacePtr()->start(instance, 10 * 1000 * 1000); return rc; } @@ -512,14 +512,6 @@ } } -Result SecurityDatabaseServer::getSessionKey(Firebird::IStatus*, - const unsigned char** key, unsigned int* keyLen) -{ - *key = NULL; - *keyLen = 0; - return AUTH_CONTINUE; -} - int SecurityDatabaseServer::release() { if (--refCounter == 0) Modified: firebird/trunk/src/auth/SecurityDatabase/LegacyServer.h =================================================================== --- firebird/trunk/src/auth/SecurityDatabase/LegacyServer.h 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/auth/SecurityDatabase/LegacyServer.h 2012-02-24 12:39:27 UTC (rev 54041) @@ -51,9 +51,7 @@ { } // IServer implementation - Result FB_CARG authenticate(Firebird::IStatus* status, IServerBlock* sBlock, IWriter* writerInterface); - Result FB_CARG getSessionKey(Firebird::IStatus* status, - const unsigned char** key, unsigned int* keyLen); + int FB_CARG authenticate(Firebird::IStatus* status, IServerBlock* sBlock, IWriter* writerInterface); int FB_CARG release(); private: Modified: firebird/trunk/src/auth/trusted/AuthSspi.cpp =================================================================== --- firebird/trunk/src/auth/trusted/AuthSspi.cpp 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/auth/trusted/AuthSspi.cpp 2012-02-24 12:39:27 UTC (rev 54041) @@ -344,9 +344,9 @@ : sspiData(getPool()) { } -Result WinSspiServer::authenticate(Firebird::IStatus* status, - IServerBlock* sBlock, - IWriter* writerInterface) +int WinSspiServer::authenticate(Firebird::IStatus* status, + IServerBlock* sBlock, + IWriter* writerInterface) { try { @@ -385,15 +385,6 @@ return AUTH_MORE_DATA; } -Result WinSspiServer::getSessionKey(Firebird::IStatus*, - const unsigned char** key, - unsigned int* keyLen) -{ - *key = NULL; - *keyLen = 0; - return AUTH_CONTINUE; -} - int WinSspiServer::release() { if (--refCounter == 0) @@ -405,8 +396,8 @@ return 1; } -Result WinSspiClient::authenticate(Firebird::IStatus* status, - IClientBlock* cBlock) +int WinSspiClient::authenticate(Firebird::IStatus* status, + IClientBlock* cBlock) { try { @@ -434,15 +425,6 @@ return AUTH_MORE_DATA; } -Result WinSspiClient::getSessionKey(Firebird::IStatus* /*status*/, - const unsigned char** key, - unsigned int* keyLen) -{ - *key = NULL; - *keyLen = 0; - return AUTH_CONTINUE; -} - int WinSspiClient::release() { if (--refCounter == 0) Modified: firebird/trunk/src/auth/trusted/AuthSspi.h =================================================================== --- firebird/trunk/src/auth/trusted/AuthSspi.h 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/auth/trusted/AuthSspi.h 2012-02-24 12:39:27 UTC (rev 54041) @@ -100,8 +100,7 @@ { public: // IServer implementation - Result FB_CARG authenticate(Firebird::IStatus* status, IServerBlock* sBlock, IWriter* writerInterface); - Result FB_CARG getSessionKey(Firebird::IStatus* status, const unsigned char** key, unsigned int* keyLen); + int FB_CARG authenticate(Firebird::IStatus* status, IServerBlock* sBlock, IWriter* writerInterface); int FB_CARG release(); WinSspiServer(Firebird::IPluginConfig*); @@ -115,8 +114,7 @@ { public: // IClient implementation - Result FB_CARG authenticate(Firebird::IStatus* status, IClientBlock* sBlock); - Result FB_CARG getSessionKey(Firebird::IStatus* status, const unsigned char** key, unsigned int* keyLen); + int FB_CARG authenticate(Firebird::IStatus* status, IClientBlock* sBlock); int FB_CARG release(); WinSspiClient(Firebird::IPluginConfig*); Modified: firebird/trunk/src/common/classes/ClumpletWriter.cpp =================================================================== --- firebird/trunk/src/common/classes/ClumpletWriter.cpp 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/common/classes/ClumpletWriter.cpp 2012-02-24 12:39:27 UTC (rev 54041) @@ -69,14 +69,14 @@ { dynamic_buffer.push(isc_spb_version); } - dynamic_buffer.push(tag); - break; + // fall down .... case Tagged: case Tpb: case WideTagged: dynamic_buffer.push(tag); break; default: + fb_assert(tag == 0); break; } } Modified: firebird/trunk/src/common/classes/ClumpletWriter.h =================================================================== --- firebird/trunk/src/common/classes/ClumpletWriter.h 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/common/classes/ClumpletWriter.h 2012-02-24 12:39:27 UTC (rev 54041) @@ -64,7 +64,7 @@ ClumpletWriter(MemoryPool& pool, const ClumpletWriter& from); ClumpletWriter(const ClumpletWriter& from); - void reset(UCHAR tag); + void reset(UCHAR tag = 0); void reset(const UCHAR* buffer, const size_t buffLen); void clear(); Modified: firebird/trunk/src/common/classes/ImplementHelper.h =================================================================== --- firebird/trunk/src/common/classes/ImplementHelper.h 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/common/classes/ImplementHelper.h 2012-02-24 12:39:27 UTC (rev 54041) @@ -119,7 +119,11 @@ ++refCounter; } +#ifdef DEV_BUILD +public: +#else protected: +#endif AtomicCounter refCounter; }; Modified: firebird/trunk/src/common/config/config.cpp =================================================================== --- firebird/trunk/src/common/config/config.cpp 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/common/config/config.cpp 2012-02-24 12:39:27 UTC (rev 54041) @@ -109,6 +109,10 @@ const char* AmTrusted = "trusted"; const char* AmMixed = "mixed"; +const char* WIRE_CRYPT_DISABLED = "DISABLED"; +const char* WIRE_CRYPT_ENABLED = "ENABLED"; +const char* WIRE_CRYPT_REQUIRED = "REQUIRED"; + const Config::ConfigEntry Config::entries[MAX_CONFIG_KEY] = { {TYPE_INTEGER, "TempBlockSize", (ConfigValue) 1048576}, // bytes @@ -169,7 +173,9 @@ {TYPE_STRING, "TracePlugin", (ConfigValue) "fbtrace"}, {TYPE_STRING, "SecurityDatabase", (ConfigValue) "$(root)/security3.fdb"}, // security database name {TYPE_BOOLEAN, "SharedCache", (ConfigValue) true}, - {TYPE_BOOLEAN, "SharedDatabase", (ConfigValue) false} + {TYPE_BOOLEAN, "SharedDatabase", (ConfigValue) false}, + {TYPE_STRING, "WireCrypt", (ConfigValue) NULL}, + {TYPE_STRING, "CryptPlugin", (ConfigValue) "Arc4"} }; /****************************************************************************** @@ -671,9 +677,11 @@ return (const char*) getDefaultConfig()->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]; } - (Firebird::Arg::Gds(isc_random) << "Internal error in getPlugins()").raise(); + (Firebird::Arg::Gds(isc_random) << "Internal error in Config::getPlugins()").raise(); return NULL; // compiler warning silencer } @@ -707,3 +715,9 @@ { return get<const char*>(KEY_SECURITY_DATABASE); } + +const char* Config::getWireCrypt(WireCryptMode wcMode) +{ + const char* rc = getDefaultConfig()->get<const char*>(KEY_WIRE_CRYPT); + return rc ? rc : wcMode == WC_CLIENT ? WIRE_CRYPT_ENABLED : WIRE_CRYPT_REQUIRED; +} Modified: firebird/trunk/src/common/config/config.h =================================================================== --- firebird/trunk/src/common/config/config.h 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/common/config/config.h 2012-02-24 12:39:27 UTC (rev 54041) @@ -75,6 +75,12 @@ enum AmCache {AM_UNKNOWN, AM_DISABLED, AM_ENABLED}; +extern const char* WIRE_CRYPT_DISABLED; +extern const char* WIRE_CRYPT_ENABLED; +extern const char* WIRE_CRYPT_REQUIRED; + +enum WireCryptMode {WC_CLIENT, WC_SERVER}; // Have different defaults + const char* const CONFIG_FILE = "firebird.conf"; class Config : public Firebird::RefCounted, public Firebird::GlobalStorage @@ -133,6 +139,8 @@ KEY_SECURITY_DATABASE, KEY_SHARED_CACHE, KEY_SHARED_DATABASE, + KEY_WIRE_CRYPT, + KEY_PLUG_CRYPT, MAX_CONFIG_KEY // keep it last }; @@ -332,6 +340,8 @@ static const char* getPlugins(unsigned int type); const char* getSecurityDatabase() const; + + static const char* getWireCrypt(WireCryptMode wcMode); }; // Implementation of interface to access master configuration file Modified: firebird/trunk/src/include/firebird/Auth.h =================================================================== --- firebird/trunk/src/include/firebird/Auth.h 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/include/firebird/Auth.h 2012-02-24 12:39:27 UTC (rev 54041) @@ -37,7 +37,10 @@ namespace Auth { -enum Result {AUTH_SUCCESS, AUTH_CONTINUE, AUTH_FAILED, AUTH_MORE_DATA}; +const int AUTH_SUCCESS = 0; +const int AUTH_MORE_DATA = 1; +const int AUTH_CONTINUE = 2; +const int AUTH_FAILED = -1; class IWriter : public Firebird::IVersioned { @@ -54,9 +57,10 @@ public: virtual const char* FB_CARG getLogin() = 0; virtual const unsigned char* FB_CARG getData(unsigned int* length) = 0; - virtual void FB_CARG putData(unsigned int length, const void* data) = 0; + virtual void FB_CARG putData(Firebird::IStatus* status, unsigned int length, const void* data) = 0; + virtual void FB_CARG putKey(Firebird::IStatus* status, Firebird::FbCryptKey* cryptKey) = 0; }; -#define FB_AUTH_SERVER_BLOCK_VERSION (FB_VERSIONED_VERSION + 3) +#define FB_AUTH_SERVER_BLOCK_VERSION (FB_VERSIONED_VERSION + 4) // Representation of auth-related data, passed to client auth plugin class IClientBlock : public Firebird::IRefCounted @@ -65,29 +69,26 @@ virtual const char* FB_CARG getLogin() = 0; virtual const char* FB_CARG getPassword() = 0; virtual const unsigned char* FB_CARG getData(unsigned int* length) = 0; - virtual void FB_CARG putData(unsigned int length, const void* data) = 0; + virtual void FB_CARG putData(Firebird::IStatus* status, unsigned int length, const void* data) = 0; + virtual void FB_CARG putKey(Firebird::IStatus* status, Firebird::FbCryptKey* cryptKey) = 0; }; -#define FB_AUTH_CLIENT_BLOCK_VERSION (FB_VERSIONED_VERSION + 4) +#define FB_AUTH_CLIENT_BLOCK_VERSION (FB_VERSIONED_VERSION + 5) // server part of authentication plugin class IServer : public Firebird::IPluginBase { public: - virtual Result FB_CARG authenticate(Firebird::IStatus* status, IServerBlock* sBlock, IWriter* writerInterface) = 0; - virtual Result FB_CARG getSessionKey(Firebird::IStatus* status, - const unsigned char** key, unsigned int* keyLen) = 0; + virtual int FB_CARG authenticate(Firebird::IStatus* status, IServerBlock* sBlock, IWriter* writerInterface) = 0; }; -#define FB_AUTH_SERVER_VERSION (FB_PLUGIN_VERSION + 2) +#define FB_AUTH_SERVER_VERSION (FB_PLUGIN_VERSION + 1) // .. and corresponding client class IClient : public Firebird::IPluginBase { public: - virtual Result FB_CARG authenticate(Firebird::IStatus* status, IClientBlock* cBlock) = 0; - virtual Result FB_CARG getSessionKey(Firebird::IStatus* status, - const unsigned char** key, unsigned int* keyLen) = 0; + virtual int FB_CARG authenticate(Firebird::IStatus* status, IClientBlock* cBlock) = 0; }; -#define FB_AUTH_CLIENT_VERSION (FB_PLUGIN_VERSION + 2) +#define FB_AUTH_CLIENT_VERSION (FB_PLUGIN_VERSION + 1) class IUserField : public Firebird::IVersioned { Added: firebird/trunk/src/include/firebird/Crypt.h =================================================================== --- firebird/trunk/src/include/firebird/Crypt.h (rev 0) +++ firebird/trunk/src/include/firebird/Crypt.h 2012-02-24 12:39:27 UTC (rev 54041) @@ -0,0 +1,53 @@ +/* + * 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 Alexander Peshkov + * for the Firebird Open Source RDBMS project. + * + * Copyright (c) 2012 Alex Peshkov <pes...@ma...> + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#ifndef FIREBIRD_CRYPT_PLUGIN_H +#define FIREBIRD_CRYPT_PLUGIN_H + +#include "./Plugin.h" + +namespace Firebird { + +class ICrypt : public IRefCounted +{ +public: + virtual void FB_CARG transform(IStatus* status, unsigned int length, void* to, const void* from) = 0; +}; + +#define FB_CRYPT_VERSION (FB_REFCOUNTED_VERSION + 1) + +class ICryptPlugin : public IPluginBase +{ +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; +}; + +#define FB_CRYPT_PLUGIN_VERSION (FB_PLUGIN_VERSION + 3) + +} // namespace Firebird + + +#endif // FIREBIRD_CRYPT_PLUGIN_H Property changes on: firebird/trunk/src/include/firebird/Crypt.h ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:eol-style + native Modified: firebird/trunk/src/include/firebird/Plugin.h =================================================================== --- firebird/trunk/src/include/firebird/Plugin.h 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/include/firebird/Plugin.h 2012-02-24 12:39:27 UTC (rev 54041) @@ -198,6 +198,16 @@ #define FB_PLUGIN_MANAGER_VERSION (FB_VERSIONED_VERSION + 6) +struct FbCryptKey +{ + const char* type; // If NULL type is auth plugin name + const void* encryptKey; + const void* decryptKey; // May be NULL for symmetric keys + unsigned int encryptLength; + unsigned int decryptLength; // Ignored when decryptKey is NULL +}; + + typedef void PluginEntrypoint(IMaster* masterInterface); namespace PluginType { @@ -215,15 +225,6 @@ static const unsigned int MaxType = 17; // keep in sync please }; -class ICrypt : public IPluginBase -{ -public: - virtual void FB_CARG setKey(IStatus* status, unsigned int length, const void* key) = 0; - virtual void FB_CARG transform(IStatus* status, unsigned int length, void* to, const void* from) = 0; -}; -#define FB_CRYPT_VERSION (FB_PLUGIN_VERSION + 2) - } // namespace Firebird - #endif // FIREBIRD_PLUGIN_API_H Added: firebird/trunk/src/plugins/crypt/arc4/Arc4.cpp =================================================================== --- firebird/trunk/src/plugins/crypt/arc4/Arc4.cpp (rev 0) +++ firebird/trunk/src/plugins/crypt/arc4/Arc4.cpp 2012-02-24 12:39:27 UTC (rev 54041) @@ -0,0 +1,179 @@ +/* + * PROGRAM: Firebird authentication. + * MODULE: SrpClient.cpp + * DESCRIPTION: SPR authentication 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 "firebird.h" + +#include "./Arc4.h" +#include "../common/classes/ImplementHelper.h" + +using namespace Firebird; + +namespace +{ + +class Cypher : public RefCntIface<ICrypt, FB_CRYPT_VERSION> +{ +public: + Cypher() + : s1(0), s2(0) + { + for (unsigned int n = 0; n < sizeof(state); ++n) + { + state[n] = n; + } + } + + void setKey(unsigned int l, const unsigned char* key) + { + for (unsigned int k1 = 0, k2 = 0; k1 < sizeof(state); ++k1) + { + k2 = (k2 + key[k1 % l] + state[k1]) & 0xff; + swap(state[k1], state[k2]); + } + } + + // ICrypt implementation + void FB_CARG transform(IStatus* status, unsigned int length, void* to, const void* from) + { + status->init(); + + unsigned char* t = reinterpret_cast<unsigned char*>(to); + const unsigned char* f = reinterpret_cast<const unsigned char*>(from); + while(length--) + { + s2 += state[++s1]; + swap(state[s1], state[s2]); + unsigned char k = state[s1] + state[s2]; + k = state[k]; + *t++ = k ^ *f++; + } + } + + int release() + { + if (--refCounter == 0) + { + delete this; + return 0; + } + return 1; + } + +private: + unsigned char state[256]; + unsigned char s1; + unsigned char s2; + + void swap(unsigned char& c1, unsigned char& c2) + { + unsigned char temp = c1; + c1 = c2; + c2 = temp; + } +}; + +} // anonymous namespace + + +namespace Crypt { + +class Arc4 : public StdPlugin<ICryptPlugin, FB_CRYPT_PLUGIN_VERSION> +{ +public: + explicit Arc4(IPluginConfig*) + { } + + // ICryptPlugin implementation + const char* FB_CARG getKnownTypes(IStatus* status); + ICrypt* FB_CARG getEncrypt(IStatus* status, FbCryptKey* key); + ICrypt* FB_CARG getDecrypt(IStatus* status, FbCryptKey* key); + int FB_CARG release(); + +private: + ICrypt* createCypher(IStatus* status, unsigned int l, const void* key); +}; + +int Arc4::release() +{ + if (--refCounter == 0) + { + delete this; + return 0; + } + return 1; +} + +ICrypt* Arc4::getEncrypt(IStatus* status, FbCryptKey* key) +{ + return createCypher(status, key->encryptLength, key->encryptKey); +} + +ICrypt* Arc4::getDecrypt(IStatus* status, FbCryptKey* key) +{ + const void* k = key->decryptKey; + unsigned int l = key->decryptLength; + if (!k) + { + k = key->encryptKey; + l = key->encryptLength; + } + return createCypher(status, l, k); +} + +ICrypt* Arc4::createCypher(IStatus* status, unsigned int l, const void* key) +{ + status->init(); + try + { + Cypher* rc = new Cypher; + rc->setKey(l, reinterpret_cast<const unsigned char*>(key)); + return rc; + } + catch (const Exception& ex) + { + ex.stuffException(status); + } + return NULL; +} + +const char* Arc4::getKnownTypes(IStatus* status) +{ + status->init(); + return "Symmetric"; +} + + +namespace +{ + SimpleFactory<Arc4> factory; +} + +void registerArc4(IPluginManager* iPlugin) +{ + iPlugin->registerPluginFactory(PluginType::Crypt, "Arc4", &factory); +} + +} // namespace Crypt Property changes on: firebird/trunk/src/plugins/crypt/arc4/Arc4.cpp ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:eol-style + native Added: firebird/trunk/src/plugins/crypt/arc4/Arc4.h =================================================================== --- firebird/trunk/src/plugins/crypt/arc4/Arc4.h (rev 0) +++ firebird/trunk/src/plugins/crypt/arc4/Arc4.h 2012-02-24 12:39:27 UTC (rev 54041) @@ -0,0 +1,38 @@ +/* + * PROGRAM: Firebird authentication. + * MODULE: SrpClient.h + * DESCRIPTION: SPR authentication 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): ______________________________________. + */ + +#ifndef CRYPT_ARC4_H +#define CRYPT_ARC4_H + +#include "firebird/Crypt.h" + +namespace Crypt { + +void registerArc4(Firebird::IPluginManager* iPlugin); + +} // namespace Auth + +#endif // CRYPT_ARC4_H Property changes on: firebird/trunk/src/plugins/crypt/arc4/Arc4.h ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:eol-style + native Modified: firebird/trunk/src/remote/client/interface.cpp =================================================================== --- firebird/trunk/src/remote/client/interface.cpp 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/remote/client/interface.cpp 2012-02-24 12:39:27 UTC (rev 54041) @@ -66,6 +66,7 @@ #include "../auth/SecurityDatabase/LegacyClient.h" #include "../auth/SecureRemotePassword/client/SrpClient.h" #include "../auth/trusted/AuthSspi.h" +#include "../plugins/crypt/arc4/Arc4.h" #ifdef HAVE_UNISTD_H @@ -529,6 +530,8 @@ #ifdef TRUSTED_AUTH Auth::registerTrustedClient(iPlugin); #endif + + Crypt::registerArc4(iPlugin); } } // namespace Remote @@ -593,7 +596,7 @@ static void authFillParametersBlock(ClntAuthBlock& authItr, ClumpletWriter& dpb, const ParametersSet* tags, rem_port* port); static void authReceiveResponse(ClntAuthBlock& authItr, rem_port* port, Rdb* rdb, - IStatus* status, PACKET* packet); + IStatus* status, PACKET* packet, bool checkKeys); static AtomicCounter remote_event_id; @@ -4562,21 +4565,24 @@ cBlock.load(dpb, &dpbParam); authenticateStep0(cBlock); + rem_port* port = NULL; + #ifdef WIN_NT if (ISC_analyze_protocol(PROTOCOL_XNET, file_name, node_name)) { - return XNET_analyze(&cBlock, file_name, uv_flag); + port = XNET_analyze(&cBlock, file_name, uv_flag); } - if (ISC_analyze_protocol(PROTOCOL_WNET, file_name, node_name) || + else if (ISC_analyze_protocol(PROTOCOL_WNET, file_name, node_name) || ISC_analyze_pclan(file_name, node_name)) { if (node_name.isEmpty()) { node_name = WNET_LOCALHOST; } - return WNET_analyze(&cBlock, file_name, node_name.c_str(), uv_flag); + port = WNET_analyze(&cBlock, file_name, node_name.c_str(), uv_flag); } + else #endif if (ISC_analyze_protocol(PROTOCOL_INET, file_name, node_name) || @@ -4586,13 +4592,17 @@ { node_name = INET_LOCALHOST; } - return INET_analyze(&cBlock, file_name, node_name.c_str(), uv_flag, dpb); + port = INET_analyze(&cBlock, file_name, node_name.c_str(), uv_flag, dpb); } // We have a local connection string. If it's a file on a network share, // try to connect to the corresponding host remotely. - rem_port* port = NULL; + if (port) + { + cBlock.tryNewKeys(port); + return port; + } #ifdef WIN_NT PathName expanded_name = file_name; @@ -4640,6 +4650,10 @@ } } + if (port) + { + cBlock.tryNewKeys(port); + } return port; } @@ -5410,7 +5424,7 @@ // Probably communicate with services auth fb_assert(cBlock); HANDSHAKE_DEBUG(fprintf(stderr, "info() calls authReceiveResponse\n")); - authReceiveResponse(*cBlock, rdb->rdb_port, rdb, status, packet); + authReceiveResponse(*cBlock, rdb->rdb_port, rdb, status, packet, false); } else { @@ -5440,9 +5454,11 @@ if (port->port_protocol >= PROTOCOL_VERSION13 || REMOTE_legacy_auth(cBlock.plugins.name(), port->port_protocol)) { + // OK to use plugin cBlock.resetDataFromPlugin(); - // OK to use plugin - switch(cBlock.plugins.plugin()->authenticate(&s, &cBlock)) + int authRc = cBlock.plugins.plugin()->authenticate(&s, &cBlock); + cBlock.tryNewKeys(port); + switch(authRc) { case Auth::AUTH_SUCCESS: case Auth::AUTH_MORE_DATA: @@ -5460,8 +5476,35 @@ } } +static CSTRING* REMOTE_dup_string(CSTRING* from) +{ + if (from && from->cstr_length) + { + CSTRING* rc = FB_NEW(*getDefaultMemoryPool()) CSTRING; + memset(rc, 0, sizeof(CSTRING)); + rc->cstr_length = from->cstr_length; + rc->cstr_address = FB_NEW(*getDefaultMemoryPool()) UCHAR[rc->cstr_length]; + memcpy(rc->cstr_address, from->cstr_address, rc->cstr_length); + return rc; + } + + return NULL; +} + +static void REMOTE_free_string(CSTRING* tmp) +{ + if (tmp) + { + if (tmp->cstr_address) + { + delete[] tmp->cstr_address; + } + delete tmp; + } +} + static void authReceiveResponse(ClntAuthBlock& cBlock, rem_port* port, Rdb* rdb, - IStatus* status, PACKET* packet) + IStatus* status, PACKET* packet, bool checkKeys) { LocalStatus s; @@ -5484,13 +5527,30 @@ case op_cont_auth: d = &packet->p_auth_cont.p_data; n = &packet->p_auth_cont.p_name; + port->addServerKeys(&packet->p_auth_cont.p_keys); HANDSHAKE_DEBUG(fprintf(stderr, "RR:CA d=%d n=%d '%.*s' 0x%x\n", d->cstr_length, n->cstr_length, n->cstr_length, n->cstr_address, n->cstr_address ? n->cstr_address[0] : 0)); break; + case op_crypt: + fb_assert(!checkKeys); + { + HANDSHAKE_DEBUG(fprintf(stderr, "RR: Crypt answer\n")); + CSTRING* tmpKeys = REMOTE_dup_string(&packet->p_crypt.p_key); + // it was start crypt packet, receive next one + receive_response(status, rdb, packet); + // now try to start crypt + if (tmpKeys) + { + port->addServerKeys(tmpKeys); + REMOTE_free_string(tmpKeys); + } + } + return; + default: HANDSHAKE_DEBUG(fprintf(stderr, "RR: Default answer\n")); - REMOTE_check_response(status, rdb, packet); + REMOTE_check_response(status, rdb, packet, checkKeys); // successfully attached HANDSHAKE_DEBUG(fprintf(stderr, "RR: OK!\n")); rdb->rdb_id = packet->p_resp.p_resp_object; @@ -5528,6 +5588,7 @@ { break; } + cBlock.tryNewKeys(port); // send answer (may be empty) to server if (port->port_protocol >= PROTOCOL_VERSION13) @@ -5620,7 +5681,7 @@ send_packet(port, packet); - authReceiveResponse(cBlock, port, rdb, status, packet); + authReceiveResponse(cBlock, port, rdb, status, packet, true); } catch (const Exception&) { @@ -6519,7 +6580,7 @@ try { - authReceiveResponse(cBlock, rdb->rdb_port, rdb, status, packet); + authReceiveResponse(cBlock, rdb->rdb_port, rdb, status, packet, true); } catch (const Exception&) { @@ -6788,10 +6849,17 @@ return *length ? dataForPlugin.begin() : NULL; } -void ClntAuthBlock::putData(unsigned int length, const void* data) +void ClntAuthBlock::putData(IStatus* status, unsigned int length, const void* data) { - void* to = dataFromPlugin.getBuffer(length); - memcpy(to, data, length); + try + { + void* to = dataFromPlugin.getBuffer(length); + memcpy(to, data, length); + } + catch (const Exception& ex) + { + ex.stuffException(status); + } } int ClntAuthBlock::release() @@ -6828,3 +6896,49 @@ userName = port->port_user_name; password = port->port_password; } + +void ClntAuthBlock::putKey(IStatus* status, FbCryptKey* cryptKey) +{ + status->init(); + try + { + const char* t = cryptKey->type; + if (!t) + { + fb_assert(plugins.hasData()); + t = plugins.name(); + } + + InternalCryptKey* k = FB_NEW(*getDefaultMemoryPool()) + InternalCryptKey(t, cryptKey->encryptKey, cryptKey->encryptLength, + cryptKey->decryptKey, cryptKey->decryptLength); + cryptKeys.add(k); + } + catch (const Exception& ex) + { + ex.stuffException(status); + } +} + +void ClntAuthBlock::tryNewKeys(rem_port* port) +{ + for (unsigned k = 0; k < cryptKeys.getCount(); ++k) + { + if (port->tryNewKey(cryptKeys[k])) + { + releaseKeys(k); + cryptKeys.clear(); + return; + } + } + + cryptKeys.clear(); +} + +void ClntAuthBlock::releaseKeys(unsigned from) +{ + while (from < cryptKeys.getCount()) + { + delete cryptKeys[from++]; + } +} Modified: firebird/trunk/src/remote/inet.cpp =================================================================== --- firebird/trunk/src/remote/inet.cpp 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/remote/inet.cpp 2012-02-24 12:39:27 UTC (rev 54041) @@ -607,6 +607,7 @@ cBlock->storeDataForPlugin(packet->p_acpd.p_acpt_data.cstr_length, packet->p_acpd.p_acpt_data.cstr_address); cBlock->authComplete = packet->p_acpd.p_acpt_authenticated; + port->addServerKeys(&packet->p_acpd.p_acpt_keys); } break; @@ -622,7 +623,7 @@ try { Firebird::LocalStatus warning; // Ignore connect warnings for a while - REMOTE_check_response(&warning, rdb, packet); + REMOTE_check_response(&warning, rdb, packet, false); } catch(const Firebird::Exception&) { @@ -2871,6 +2872,7 @@ int n = 0; int inetErrNo; + LocalStatus st; for (;;) { @@ -2944,9 +2946,17 @@ } n = recv(port->port_handle, reinterpret_cast<char*>(buffer), buffer_length, 0); - // ->decrypt inetErrNo = INET_ERRNO; + if (n > 0 && port->port_recv_cipher) + { + port->port_recv_cipher->transform(&st, n, buffer, buffer); + if (!st.isSuccess()) + { + status_exception::raise(st.get()); + } + } + if (n != -1 || !INTERRUPT_ERROR(inetErrNo)) break; } @@ -3010,11 +3020,25 @@ * **************************************/ + SSHORT length = buffer_length; const char* data = buffer; - SSHORT length = buffer_length; - // ->encrypt + // encrypt + HalfStaticArray<char, BUFFER_TINY> b; + if (port->port_send_cipher) + { + LocalStatus st; + char* d = b.getBuffer(buffer_length); + port->port_send_cipher->transform(&st, buffer_length, d, data); + if (!st.isSuccess()) + { + status_exception::raise(st.get()); + } + + data = d; + } + while (length) { #ifdef DEBUG Modified: firebird/trunk/src/remote/protocol.cpp =================================================================== --- firebird/trunk/src/remote/protocol.cpp 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/remote/protocol.cpp 2012-02-24 12:39:27 UTC (rev 54041) @@ -336,7 +336,7 @@ MAP(xdr_cstring, accept_with_data->p_acpt_data); MAP(xdr_cstring, accept_with_data->p_acpt_plugin); MAP(xdr_u_short, accept_with_data->p_acpt_authenticated); - //??? fprintf(stderr, "data length %d\n", accept_with_data->p_acpt_data.cstr_length); + MAP(xdr_cstring, accept_with_data->p_acpt_keys); DEBUG_PRINTSIZE(xdrs, p->p_operation); return P_TRUE(xdrs, p); @@ -749,6 +749,7 @@ MAP(xdr_cstring, auth->p_data); MAP(xdr_cstring, auth->p_name); MAP(xdr_cstring, auth->p_list); + MAP(xdr_cstring, auth->p_keys); DEBUG_PRINTSIZE(xdrs, p->p_operation); return P_TRUE(xdrs, p); @@ -763,6 +764,16 @@ return P_TRUE(xdrs, p); } + case op_crypt: + { + P_CRYPT* crypt = &p->p_crypt; + MAP(xdr_cstring, crypt->p_plugin); + MAP(xdr_cstring, crypt->p_key); + DEBUG_PRINTSIZE(xdrs, p->p_operation); + + return P_TRUE(xdrs, p); + } + ///case op_insert: default: #ifdef DEV_BUILD Modified: firebird/trunk/src/remote/protocol.h =================================================================== --- firebird/trunk/src/remote/protocol.h 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/remote/protocol.h 2012-02-24 12:39:27 UTC (rev 54041) @@ -277,6 +277,8 @@ op_abort_aux_connection = 95, // Async operation - stop waiting for async connection to arrive + op_crypt = 96, + op_max }; @@ -390,6 +392,7 @@ CSTRING p_acpt_data; // Returned auth data CSTRING p_acpt_plugin; // Plugin to continue with USHORT p_acpt_authenticated; // Auth complete in single step (few! strange...) + CSTRING p_acpt_keys; // Keys known to the server }; typedef p_acpd P_ACPD; @@ -610,6 +613,7 @@ CSTRING p_data; // Specific data CSTRING p_name; // Plugin name CSTRING p_list; // Plugin list + CSTRING p_keys; // Keys available on server } P_AUTH_CONT; struct p_update_account @@ -632,6 +636,11 @@ USHORT p_co_kind; // Kind of cancelation } P_CANCEL_OP; +typedef struct p_crypt +{ + CSTRING p_plugin; // Crypt plugin name + CSTRING p_key; // Key name / keys available on server +} P_CRYPT; // Generalize packet (sic!) @@ -675,6 +684,7 @@ p_authenticate p_authenticate_user; P_CANCEL_OP p_cancel_op; // Cancel operation P_AUTH_CONT p_auth_cont; // Request more auth data + P_CRYPT p_crypt; // Start wire crypt public: packet() Modified: firebird/trunk/src/remote/remot_proto.h =================================================================== --- firebird/trunk/src/remote/remot_proto.h 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/remote/remot_proto.h 2012-02-24 12:39:27 UTC (rev 54041) @@ -61,7 +61,7 @@ Firebird::RefPtr<Config> REMOTE_get_config(const Firebird::PathName* dbName); void REMOTE_parseList(Remote::ParsedList&, Firebird::PathName); void REMOTE_makeList(Firebird::PathName& list, const Remote::ParsedList& parsed); -void REMOTE_check_response(Firebird::IStatus* warning, Rdb* rdb, PACKET* packet); +void REMOTE_check_response(Firebird::IStatus* warning, Rdb* rdb, PACKET* packet, bool checkKeys = false); #define HANDSHAKE_DEBUG(A) Modified: firebird/trunk/src/remote/remote.cpp =================================================================== --- firebird/trunk/src/remote/remote.cpp 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/remote/remote.cpp 2012-02-24 12:39:27 UTC (rev 54041) @@ -46,10 +46,70 @@ IMPLEMENT_TRACE_ROUTINE(remote_trace, "REMOTE") #endif + +const ParametersSet dpbParam = {isc_dpb_dummy_packet_interval, + isc_dpb_user_name, + isc_dpb_auth_block, + isc_dpb_password, + isc_dpb_password_enc, + isc_dpb_trusted_auth, + isc_dpb_auth_plugin_name, + isc_dpb_auth_plugin_list, + isc_dpb_specific_auth_data, + isc_dpb_address_path, + isc_dpb_process_id, + isc_dpb_process_name, + isc_dpb_encrypt_key}; + +const ParametersSet spbParam = {isc_spb_dummy_packet_interval, + isc_spb_user_name, + isc_spb_auth_block, + isc_spb_password, + isc_spb_password_enc, + isc_spb_trusted_auth, + isc_spb_auth_plugin_name, + isc_spb_auth_plugin_list, + isc_spb_specific_auth_data, + isc_spb_address_path, + isc_spb_process_id, + isc_spb_process_name, + 0}; + +const ParametersSet spbStartParam = {0, + 0, + isc_spb_auth_block, + 0, + 0, + isc_spb_trusted_auth, + isc_spb_auth_plugin_name, + isc_spb_auth_plugin_list, + isc_spb_specific_auth_data, + 0, + 0, + 0, + 0}; // Need new parameter here + +const ParametersSet spbInfoParam = {0, + 0, + isc_info_svc_auth_block, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0}; + + const SLONG DUMMY_INTERVAL = 60; // seconds const int ATTACH_FAILURE_SPACE = 16 * 1024; // bytes +static Firebird::MakeUpgradeInfo<> upInfo; + void REMOTE_cleanup_transaction( Rtr* transaction) { /************************************** @@ -812,8 +872,18 @@ delete port_packet_vector; #endif - delete port_crypt_keys; + while (port_crypt_keys.hasData()) + { + delete port_crypt_keys.pop(); + } + if (port_send_cipher) + port_send_cipher->release(); + if (port_recv_cipher) + port_recv_cipher->release(); + if (port_crypt_plugin) + Firebird::PluginManagerInterfacePtr()->releasePlugin(port_crypt_plugin); + #ifdef DEV_BUILD --portCounter; #endif @@ -1028,7 +1098,7 @@ } } -void REMOTE_check_response(Firebird::IStatus* warning, Rdb* rdb, PACKET* packet) +void REMOTE_check_response(Firebird::IStatus* warning, Rdb* rdb, PACKET* packet, bool checkKeys) { /************************************** * @@ -1041,6 +1111,22 @@ * **************************************/ + rdb->rdb_port->checkResponse(warning, packet, checkKeys); +} + +void rem_port::checkResponse(Firebird::IStatus* warning, PACKET* packet, bool checkKeys) +{ +/************************************** + * + * R E M O T E _ c h e c k _ r e s p o n s e + * + ************************************** + * + * Functional description + * Check response to a remote call. + * + **************************************/ + // Get status vector const ISC_STATUS success_vector[] = {isc_arg_gds, FB_SUCCESS, isc_arg_end}; @@ -1053,7 +1139,6 @@ // Translate any gds codes into local operating specific codes Firebird::SimpleStatusVector newVector; - rem_port* port = rdb->rdb_port; while (*vector != isc_arg_end) { @@ -1083,8 +1168,12 @@ const ISC_STATUS pktErr = vector[1]; if (pktErr == isc_shutdown || pktErr == isc_att_shutdown) { - port->port_flags |= PORT_rdb_shutdown; + port_flags |= PORT_rdb_shutdown; } + else if (checkKeys) + { + addServerKeys(&packet->p_resp.p_resp_data); + } if ((packet->p_operation == op_response || packet->p_operation == op_response_piggyback) && !vector[1]) @@ -1101,58 +1190,129 @@ Firebird::status_exception::raise(vector); } -const ParametersSet dpbParam = {isc_dpb_dummy_packet_interval, - isc_dpb_user_name, - isc_dpb_auth_block, - isc_dpb_password, - isc_dpb_password_enc, - isc_dpb_trusted_auth, - isc_dpb_auth_plugin_name, - isc_dpb_auth_plugin_list, - isc_dpb_specific_auth_data, - isc_dpb_address_path, - isc_dpb_process_id, - isc_dpb_process_name, - isc_dpb_encrypt_key}; +void rem_port::addServerKeys(CSTRING* passedStr) +{ + Firebird::ClumpletReader newKeys(Firebird::ClumpletReader::UnTagged, + passedStr->cstr_address, passedStr->cstr_length); -const ParametersSet spbParam = {isc_spb_dummy_packet_interval, - isc_spb_user_name, - isc_spb_auth_block, - isc_spb_password, - isc_spb_password_enc, - isc_spb_trusted_auth, - isc_spb_auth_plugin_name, - isc_spb_auth_plugin_list, - isc_spb_specific_auth_data, - isc_spb_address_path, - isc_spb_process_id, - isc_spb_process_name, - 0}; + for (newKeys.rewind(); !newKeys.isEof(); newKeys.moveNext()) + { + KnownServerKey key; + fb_assert(newKeys.getClumpTag() == TAG_KEY_TYPE); + newKeys.getPath(key.type); + newKeys.moveNext(); + if (newKeys.isEof()) + { + break; + } + fb_assert(newKeys.getClumpTag() == TAG_KEY_PLUGINS); + newKeys.getPath(key.plugins); + key.plugins += ' '; + key.plugins.insert(0, " "); -const ParametersSet spbStartParam = {0, - 0, - isc_spb_auth_block, - 0, - 0, - isc_spb_trusted_auth, - isc_spb_auth_plugin_name, - isc_spb_auth_plugin_list, - isc_spb_specific_auth_data, - 0, - 0, - 0, - 0}; // Need new parameter here + for (unsigned k = 0; k < port_crypt_keys.getCount(); ++k) + { + if (tryKeyType(key, port_crypt_keys[k])) + { + return; + } + } -const ParametersSet spbInfoParam = {0, - 0, - isc_info_svc_auth_block, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0}; + port_known_server_keys.add(key); + } +} + +bool rem_port::tryNewKey(InternalCryptKey* cryptKey) +{ + for (unsigned t = 0; t < port_known_server_keys.getCount(); ++t) + { + if (tryKeyType(port_known_server_keys[t], cryptKey)) + { + return true; + } + } + + port_crypt_keys.push(cryptKey); + return false; +} + +static void setCStr(CSTRING& to, const char* from) +{ + to.cstr_address = reinterpret_cast<UCHAR*>(const_cast<char*>(from)); + to.cstr_length = strlen(from); + to.cstr_allocated = 0; +} + +bool rem_port::tryKeyType(const KnownServerKey& srvKey, InternalCryptKey* cryptKey) +{ + if (port_crypt_complete) + { + return true; + } + + if (srvKey.type != cryptKey->type) + { + return false; + } + + if (Config::getWireCrypt(WC_CLIENT) == WIRE_CRYPT_DISABLED) + { + port_crypt_complete = true; + return true; + } + + // we got correct key's type pair + // check what about crypt plugin for it + Remote::ParsedList clientPlugins; + REMOTE_parseList(clientPlugins, Config::getPlugins(Firebird::PluginType::Crypt)); + for (unsigned n = 0; n < clientPlugins.getCount(); ++n) + { + Firebird::PathName p(clientPlugins[n]); + if (srvKey.plugins.find(" " + p + " ") != Firebird::PathName::npos) + { + Firebird::GetPlugins<Firebird::ICryptPlugin> + cp(Firebird::PluginType::Crypt, FB_CRYPT_PLUGIN_VERSION, upInfo, p.c_str()); + if (cp.hasData()) + { + // looks like we've found correct crypt plugin and key for it + Firebird::ICryptPlugin* plugin = cp.plugin(); + Firebird::LocalStatus st; + + // Install decrypting cipher + port_recv_cipher = plugin->getDecrypt(&st, cryptKey); + if (!st.isSuccess()) + { + Firebird::status_exception::raise(st.get()); + } + + // Now it's time to notify server about choice done + PACKET crypt; + crypt.p_operation = op_crypt; + setCStr(crypt.p_crypt.p_key, cryptKey->type); + setCStr(crypt.p_crypt.p_plugin, p.c_str()); + send(&crypt); + + // Validate answer - decryptor is installed, therefore OK to do + receive(&crypt); + checkResponse(&st, &crypt); + + // Install encrypting cipher + port_send_cipher = plugin->getEncrypt(&st, cryptKey); + if (!st.isSuccess()) + { + port_recv_cipher->release(); + port_recv_cipher = NULL; + Firebird::status_exception::raise(st.get()); + } + + port_crypt_plugin = plugin; + port_crypt_plugin->addRef(); + port_crypt_complete = true; + // fprintf(stderr, "Installed cipher %s key %s\n", cp.name(), cryptKey->type); + return true; + } + } + } + + return false; +} Modified: firebird/trunk/src/remote/remote.h =================================================================== --- firebird/trunk/src/remote/remote.h 2012-02-24 12:27:36 UTC (rev 54040) +++ firebird/trunk/src/remote/remote.h 2012-02-24 12:39:27 UTC (rev 54041) @@ -46,6 +46,7 @@ #include "firebird/Provider.h" #include "firebird/Auth.h" +#include "firebird/Crypt.h" #ifndef WIN_NT #include <signal.h> @@ -89,7 +90,6 @@ class IEventCallback; } struct rem_port; -class RemCryptKey; typedef Firebird::AutoPtr<UCHAR, Firebird::ArrayDelete<UCHAR> > UCharArrayAutoPtr; @@ -590,9 +590,44 @@ { public: virtual ~ServerAuthBase(); - virtual bool authenticate(rem_port* port, PACKET* send) = 0; + virtual bool authenticate(PACKET* send) = 0; }; +// Helper class to work with public structure FbCryptKey +class InternalCryptKey : public Firebird::FbCryptKey +{ +public: + InternalCryptKey(const char* p_type, const void* p_enc, unsigned int p_eLen, + const void* p_dec = NULL, unsigned int p_dLen = 0) + { + type = p_type; + encryptKey = keyDup(p_enc, p_eLen); + encryptLength = p_eLen; + decryptKey = p_dec ? keyDup(p_dec, p_dLen) : NULL; + decryptLength = p_dLen; + } + + ~InternalCryptKey() + { + keyFree(decryptKey); + keyFree(encryptKey); + } + +private: + void* keyDup(const void* k, unsigned int l) + { + void* rc = FB_NEW(*getDefaultMemoryPool()) char[l]; + memcpy(rc, k, l); + return rc; + } + + void keyFree(const void* k) + { + delete[] ((char*) k); + } +}; + + typedef Firebird::GetPlugins<Auth::IClient> AuthClientPlugins; // Representation of authentication data, visible for plugin @@ -604,6 +639,8 @@ Firebird::string userName, password; // Used by plugin, taken from DPB // These two are legacy encrypted password, trusted auth data and so on - what plugin needs Firebird::UCharBuffer dataForPlugin, dataFromPlugin; + Firebird::HalfStaticArray<InternalCryptKey*, 1> cryptKeys; // Wire crypt keys that came from plugin(s) last time + unsigned nextKey; // First key to be analyzed bool hasCryptKey; // DPB contains disk crypt key, may be passed only over encrypted wire @@ -613,6 +650,10 @@ bool firstTime; // Invoked first time after reset explicit ClntAuthBlock(const Firebird::PathName* fileName); + ~ClntAuthBlock() + { + releaseKeys(0); + } void storeDataForPlugin(unsigned int length, const unsigned char* data); void resetDataFromPlugin(); @@ -626,13 +667,16 @@ void saveServiceDataTo(rem_port*); void loadServiceDataFrom(rem_port*); Firebird::PathName getPluginName(); + void tryNewKeys(rem_port*); + void releaseKeys(unsigned from); // Auth::IClientBlock implementation int FB_CARG release(); const char* FB_CARG getLogin(); const char* FB_CARG getPassword(); const unsigned char* FB_CARG getData(unsigned int* length); - void FB_CARG putData(unsigned int length, const void* data); + void FB_CARG putData(Firebird::IStatus* status, unsigned int length, const void* data); + void FB_CARG putKey(Firebird::IStatus* status, Firebird::FbCryptKey* cryptKey); }; // Representation of authentication data, visible for plugin @@ -642,23 +686,27 @@ class SrvAuthBlock : public Firebird::StdPlugin<Auth::IServerBlock, FB_AUTH_SERVER_BLOCK_VERSION> { private: + rem_port* port; Firebird::string userName; Firebird::PathName pluginName, pluginList; - // These two may be legacy encrypted password, trusted auth data and so on Firebird::UCharBuffer dataForPlugin, dataFromPlugin; - Firebird::PathName dbPath; + Firebird::ClumpletWriter lastExtractedKeys; + Firebird::ObjectsArray<Firebird::PathName> newKeys; bool flComplete, firstTime; public: AuthServerPlugins* plugins; Auth::WriterImplementation authBlockWriter; - SrvAuthBlock() - : userName(getPool()), pluginName(getPool()), pluginList(getPool()), + SrvAuthBlock(rem_port* p_port) + : port(p_port), + userName(getPool()), pluginName(getPool()), pluginList(getPool()), dataForPlugin(getPool()), dataFromPlugin(getPool()), dbPath(getPool()), + lastExtractedKeys(getPool(), Firebird::ClumpletReader::UnTagged, MAX_DPB_SIZE), + newKeys(getPool()), flComplete(false), firstTime(true), plugins(NULL) { } @@ -685,15 +733,44 @@ void createPluginsItr(); void setDataForPlugin(const p_auth_continue* data); void reset(); + bool extractNewKeys(CSTRING* to); // Auth::IServerBlock implementation int FB_CARG release(); const char* FB_CARG getLogin(); const unsigned char* FB_CARG getData(unsigned int* length); - void FB_CARG putData(unsigned int length, const void* data); + void FB_CARG putData(Firebird::IStatus* status, unsigned int length, const void* data); + void FB_CARG putKey(Firebird::IStatus* status, Firebird::FbCr... [truncated message content] |