|
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] |