|
From: <ale...@us...> - 2013-10-16 12:53:10
|
Revision: 58698
http://sourceforge.net/p/firebird/code/58698
Author: alexpeshkoff
Date: 2013-10-16 12:53:04 +0000 (Wed, 16 Oct 2013)
Log Message:
-----------
Fix found by Jim Starkey man-in-themiddle attack on ATTACH packet.
That packet may contain database name, command line for service and/or some other important and critical information.
To avoid such attack wire encryption is started before attaching database or service manager, right after connect.
Also should fix a number of issues found in Alpha1 regarding services attach.
Modified Paths:
--------------
firebird/trunk/doc/README.services_extension
firebird/trunk/lang_helpers/gds_codes.ftn
firebird/trunk/lang_helpers/gds_codes.pas
firebird/trunk/src/auth/SecureRemotePassword/client/SrpClient.cpp
firebird/trunk/src/auth/SecureRemotePassword/manage/SrpManagement.cpp
firebird/trunk/src/auth/SecureRemotePassword/server/SrpServer.cpp
firebird/trunk/src/auth/SecureRemotePassword/srp.cpp
firebird/trunk/src/auth/SecureRemotePassword/srp.h
firebird/trunk/src/auth/SecurityDatabase/LegacyManagement.epp
firebird/trunk/src/auth/SecurityDatabase/LegacyServer.cpp
firebird/trunk/src/burp/burp.cpp
firebird/trunk/src/common/IntlParametersBlock.cpp
firebird/trunk/src/common/classes/ClumpletReader.cpp
firebird/trunk/src/common/classes/ClumpletReader.h
firebird/trunk/src/common/classes/array.h
firebird/trunk/src/common/classes/fb_string.h
firebird/trunk/src/common/config/config.cpp
firebird/trunk/src/common/config/config.h
firebird/trunk/src/include/consts_pub.h
firebird/trunk/src/include/gen/codetext.h
firebird/trunk/src/include/gen/iberror.h
firebird/trunk/src/include/gen/msgs.h
firebird/trunk/src/include/gen/sql_code.h
firebird/trunk/src/include/gen/sql_state.h
firebird/trunk/src/jrd/jrd.cpp
firebird/trunk/src/jrd/svc.cpp
firebird/trunk/src/msgs/facilities2.sql
firebird/trunk/src/msgs/messages2.sql
firebird/trunk/src/msgs/system_errors2.sql
firebird/trunk/src/remote/client/interface.cpp
firebird/trunk/src/remote/inet.cpp
firebird/trunk/src/remote/inet_proto.h
firebird/trunk/src/remote/os/win32/wnet.cpp
firebird/trunk/src/remote/os/win32/wnet_proto.h
firebird/trunk/src/remote/os/win32/xnet.cpp
firebird/trunk/src/remote/os/win32/xnet_proto.h
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
firebird/trunk/src/utilities/fbsvcmgr/fbsvcmgr.cpp
firebird/trunk/src/utilities/gsec/gsec.cpp
firebird/trunk/src/yvalve/YObjects.h
firebird/trunk/src/yvalve/utl.cpp
firebird/trunk/src/yvalve/why.cpp
Modified: firebird/trunk/doc/README.services_extension
===================================================================
--- firebird/trunk/doc/README.services_extension 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/doc/README.services_extension 2013-10-16 12:53:04 UTC (rev 58698)
@@ -191,3 +191,35 @@
A sample of how services API should be used for remote backup and restore can be
found in source code of fbsvcmgr.
+
+
+5) Services API extension - using services with non-default security database.
+(Alex Peshkov, pes...@ma..., 2013)
+
+If one wants to use services API to access database which is configured to use
+non-default security database new SPB item isc_spb_expected_db should be used
+when attaching to services manager. Value of this item is a database which is
+expected to be accessed.
+
+Formally this does not raise backward incompatibility - as long as one does not
+use new FB3 feature (multiple security databases) he has no problems with old
+programs using services API. In a case when one has really big need to use old
+program for a database with non-default configuration there is a workaround:
+setting environment variable FB_EXPECTED_DB which will be added to SPB
+automatically.
+
+Example. Imagine we have the following lines in databases.conf:
+employee = $(dir_sampledb)/employee.fdb
+{
+ SecurityDatabase = employee
+}
+i.e. employee database is configured as security database for itself.
+
+To access it using fbsvcmgr one should use the following command line:
+fbsvcmgr host:service_mgr user sysdba password xxx expected_db employee action_db_stats dbname employee sts_data_pages
+
+or in advance set FB_EXPECTED_DB:
+export FB_EXPECTED_DB=employee
+fbsvcmgr host:service_mgr user sysdba password xxx action_db_stats dbname employee sts_data_pages
+
+Certainly any other database action can be used here.
Modified: firebird/trunk/lang_helpers/gds_codes.ftn
===================================================================
--- firebird/trunk/lang_helpers/gds_codes.ftn 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/lang_helpers/gds_codes.ftn 2013-10-16 12:53:04 UTC (rev 58698)
@@ -1530,6 +1530,28 @@
PARAMETER (GDS__protect_ownership = 335545058)
INTEGER*4 GDS__badvarnum
PARAMETER (GDS__badvarnum = 335545059)
+ INTEGER*4 GDS__sec_context
+ PARAMETER (GDS__sec_context = 335545060)
+ INTEGER*4 GDS__multi_segment
+ PARAMETER (GDS__multi_segment = 335545061)
+ INTEGER*4 GDS__login_changed
+ PARAMETER (GDS__login_changed = 335545062)
+ INTEGER*4 GDS__auth_handshake_limit
+ PARAMETER (GDS__auth_handshake_limit = 335545063)
+ INTEGER*4 GDS__wirecrypt_incompatible
+ PARAMETER (GDS__wirecrypt_incompatible = 335545064)
+ INTEGER*4 GDS__miss_wirecrypt
+ PARAMETER (GDS__miss_wirecrypt = 335545065)
+ INTEGER*4 GDS__wirecrypt_key
+ PARAMETER (GDS__wirecrypt_key = 335545066)
+ INTEGER*4 GDS__wirecrypt_plugin
+ PARAMETER (GDS__wirecrypt_plugin = 335545067)
+ INTEGER*4 GDS__secdb_name
+ PARAMETER (GDS__secdb_name = 335545068)
+ INTEGER*4 GDS__auth_data
+ PARAMETER (GDS__auth_data = 335545069)
+ INTEGER*4 GDS__auth_datalength
+ PARAMETER (GDS__auth_datalength = 335545070)
INTEGER*4 GDS__gfix_db_name
PARAMETER (GDS__gfix_db_name = 335740929)
INTEGER*4 GDS__gfix_invalid_sw
Modified: firebird/trunk/lang_helpers/gds_codes.pas
===================================================================
--- firebird/trunk/lang_helpers/gds_codes.pas 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/lang_helpers/gds_codes.pas 2013-10-16 12:53:04 UTC (rev 58698)
@@ -772,6 +772,17 @@
gds_include_miss = 335545057;
gds_protect_ownership = 335545058;
gds_badvarnum = 335545059;
+ gds_sec_context = 335545060;
+ gds_multi_segment = 335545061;
+ gds_login_changed = 335545062;
+ gds_auth_handshake_limit = 335545063;
+ gds_wirecrypt_incompatible = 335545064;
+ gds_miss_wirecrypt = 335545065;
+ gds_wirecrypt_key = 335545066;
+ gds_wirecrypt_plugin = 335545067;
+ gds_secdb_name = 335545068;
+ gds_auth_data = 335545069;
+ gds_auth_datalength = 335545070;
gds_gfix_db_name = 335740929;
gds_gfix_invalid_sw = 335740930;
gds_gfix_incmp_sw = 335740932;
Modified: firebird/trunk/src/auth/SecureRemotePassword/client/SrpClient.cpp
===================================================================
--- firebird/trunk/src/auth/SecureRemotePassword/client/SrpClient.cpp 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/auth/SecureRemotePassword/client/SrpClient.cpp 2013-10-16 12:53:04 UTC (rev 58698)
@@ -79,17 +79,18 @@
}
HANDSHAKE_DEBUG(fprintf(stderr, "Cli: SRP phase2\n"));
- unsigned int length;
+ unsigned length;
const unsigned char* saltAndKey = cb->getData(&length);
if (!saltAndKey || length == 0)
{
- (Arg::Gds(isc_random) << "Missing data from server").raise();
+ Arg::Gds(isc_auth_data).raise();
}
- if (length > (RemotePassword::SRP_SALT_SIZE + RemotePassword::SRP_KEY_SIZE + 2) * 2)
+ const unsigned expectedLength =
+ (RemotePassword::SRP_SALT_SIZE + RemotePassword::SRP_KEY_SIZE + 2) * 2;
+ if (length > expectedLength)
{
- string msg;
- msg.printf("Wrong length (%d) of data from server", length);
- (Arg::Gds(isc_random) << msg).raise();
+ (Arg::Gds(isc_auth_datalength) << Arg::Num(length) <<
+ Arg::Num(expectedLength) << "data").raise();
}
string salt, key;
@@ -97,9 +98,8 @@
charSize += ((unsigned) *saltAndKey++) << 8;
if (charSize > RemotePassword::SRP_SALT_SIZE * 2)
{
- string msg;
- msg.printf("Wrong length (%d) of salt from server", charSize);
- (Arg::Gds(isc_random) << msg).raise();
+ (Arg::Gds(isc_auth_datalength) << Arg::Num(charSize) <<
+ Arg::Num(RemotePassword::SRP_SALT_SIZE * 2) << "salt").raise();
}
salt.assign(saltAndKey, charSize);
dumpIt("Clnt: salt", salt);
@@ -108,11 +108,10 @@
charSize = *saltAndKey++;
charSize += ((unsigned) *saltAndKey++) << 8;
- if (charSize + 2 != length)
+ if (charSize != length - 2)
{
- string msg;
- msg.printf("Wrong length (%d) of key from server", charSize);
- (Arg::Gds(isc_random) << msg).raise();
+ (Arg::Gds(isc_auth_datalength) << Arg::Num(charSize) <<
+ Arg::Num(length - 2) << "key").raise();
}
key.assign(saltAndKey, charSize);
dumpIt("Clnt: key(srvPub)", key);
Modified: firebird/trunk/src/auth/SecureRemotePassword/manage/SrpManagement.cpp
===================================================================
--- firebird/trunk/src/auth/SecureRemotePassword/manage/SrpManagement.cpp 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/auth/SecureRemotePassword/manage/SrpManagement.cpp 2013-10-16 12:53:04 UTC (rev 58698)
@@ -183,7 +183,7 @@
if (!(secDbName && secDbName[0]))
{
- (Firebird::Arg::Gds(isc_random) << "Error getting security database name").raise();
+ Firebird::Arg::Gds(isc_secdb_name).raise();
}
Firebird::ClumpletWriter dpb(Firebird::ClumpletReader::dpbList, MAX_DPB_SIZE);
Modified: firebird/trunk/src/auth/SecureRemotePassword/server/SrpServer.cpp
===================================================================
--- firebird/trunk/src/auth/SecureRemotePassword/server/SrpServer.cpp 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/auth/SecureRemotePassword/server/SrpServer.cpp 2013-10-16 12:53:04 UTC (rev 58698)
@@ -99,6 +99,7 @@
unsigned int length;
const unsigned char* val = sb->getData(&length);
clientPubKey.assign(val, length);
+ dumpBin("Srv: clientPubKey", clientPubKey);
if (!clientPubKey.hasData())
{
@@ -116,7 +117,7 @@
secDbName = config->asString(secDbKey);
if (!(secDbName && secDbName[0]))
{
- (Arg::Gds(isc_random) << "Error getting security database name").raise();
+ Arg::Gds(isc_secdb_name).raise();
}
ClumpletWriter dpb(ClumpletReader::dpbList, MAX_DPB_SIZE);
@@ -221,14 +222,13 @@
data += char(serverPubKey.length() >> 8);
data.append(serverPubKey);
dumpIt("Srv: serverPubKey", serverPubKey);
- dumpIt("Srv: data", data);
+ dumpBin("Srv: data", data);
sb->putData(status, data.length(), data.c_str());
if (!status->isSuccess())
{
return AUTH_FAILED;
}
- dumpIt("Srv: clientPubKey", clientPubKey);
server->serverSessionKey(sessionKey, clientPubKey.c_str(), verifier);
dumpIt("Srv: sessionKey", sessionKey);
Modified: firebird/trunk/src/auth/SecureRemotePassword/srp.cpp
===================================================================
--- firebird/trunk/src/auth/SecureRemotePassword/srp.cpp 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/auth/SecureRemotePassword/srp.cpp 2013-10-16 12:53:04 UTC (rev 58698)
@@ -213,6 +213,14 @@
fprintf(stderr, "%s: '%s'\n", name, str.c_str());
}
+void dumpBin(const char* name, const Firebird::string& str)
+{
+ fprintf(stderr, "%s (%ld)\n", name, str.length());
+ for (size_t x=0; x<str.length(); ++x)
+ fprintf(stderr, "%02x ", str[x]);
+ fprintf(stderr, "\n");
+}
+
void dumpIt(const char* name, const BigInteger& bi)
{
string x;
Modified: firebird/trunk/src/auth/SecureRemotePassword/srp.h
===================================================================
--- firebird/trunk/src/auth/SecureRemotePassword/srp.h 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/auth/SecureRemotePassword/srp.h 2013-10-16 12:53:04 UTC (rev 58698)
@@ -120,10 +120,12 @@
void dumpIt(const char* name, const Firebird::BigInteger& bi);
void dumpIt(const char* name, const Firebird::UCharBuffer& data);
void dumpIt(const char* name, const Firebird::string& str);
+void dumpBin(const char* name, const Firebird::string& str);
#else
void static inline dumpIt(const char* /*name*/, const Firebird::BigInteger& /*bi*/) { }
void static inline dumpIt(const char* /*name*/, const Firebird::UCharBuffer& /*data*/) { }
void static inline dumpIt(const char* /*name*/, const Firebird::string& /*str*/) { }
+void static inline dumpBin(const char* /*name*/, const Firebird::string& /*str*/) { }
#endif
Modified: firebird/trunk/src/auth/SecurityDatabase/LegacyManagement.epp
===================================================================
--- firebird/trunk/src/auth/SecurityDatabase/LegacyManagement.epp 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/auth/SecurityDatabase/LegacyManagement.epp 2013-10-16 12:53:04 UTC (rev 58698)
@@ -143,7 +143,7 @@
if (!(secDbName && secDbName[0]))
{
- (Firebird::Arg::Gds(isc_random) << "Error getting security database name").raise();
+ Firebird::Arg::Gds(isc_secdb_name).raise();
}
Firebird::ClumpletWriter dpb(Firebird::ClumpletReader::dpbList, MAX_DPB_SIZE);
Modified: firebird/trunk/src/auth/SecurityDatabase/LegacyServer.cpp
===================================================================
--- firebird/trunk/src/auth/SecurityDatabase/LegacyServer.cpp 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/auth/SecurityDatabase/LegacyServer.cpp 2013-10-16 12:53:04 UTC (rev 58698)
@@ -267,6 +267,10 @@
// Attach as SYSDBA
dpb.insertString(isc_dpb_trusted_auth, SYSDBA_USER_NAME, strlen(SYSDBA_USER_NAME));
+ // Do not use other providers except current engine
+ const char* providers = "Providers=" CURRENT_ENGINE;
+ dpb.insertString(isc_dpb_config, providers, strlen(providers));
+
isc_db_handle tempHandle = 0;
isc_attach_database(status, 0, secureDbName, &tempHandle,
dpb.getBufferLength(), reinterpret_cast<const char*>(dpb.getBuffer()));
@@ -307,7 +311,9 @@
return AUTH_CONTINUE;
}
- string login(sBlock->getLogin());
+ const char* user = sBlock->getLogin();
+ string login(user ? user : "");
+
unsigned length;
const unsigned char* data = sBlock->getData(&length);
string passwordEnc;
@@ -468,7 +474,7 @@
const char* tmp = config->asString(secDbKey);
if (!tmp)
{
- (Arg::Gds(isc_random) << "Error getting security database name").raise();
+ Arg::Gds(isc_secdb_name).raise();
}
secDbName = tmp;
Modified: firebird/trunk/src/burp/burp.cpp
===================================================================
--- firebird/trunk/src/burp/burp.cpp 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/burp/burp.cpp 2013-10-16 12:53:04 UTC (rev 58698)
@@ -106,7 +106,7 @@
static ULONG get_size(const SCHAR*, burp_fil*);
static gbak_action open_files(const TEXT *, const TEXT**, bool, USHORT,
const Firebird::ClumpletWriter&);
-static int api_gbak(Firebird::UtilSvc*, const Switches& switches);
+static int svc_api_gbak(Firebird::UtilSvc*, const Switches& switches);
static void burp_output(bool err, const SCHAR*, ...) ATTRIBUTE_FORMAT(2,3);
static void burp_usage(const Switches& switches);
static Switches::in_sw_tab_t* findSwitchOrThrow(Switches& switches, Firebird::string& sw);
@@ -149,11 +149,11 @@
}
-static int api_gbak(Firebird::UtilSvc* uSvc, const Switches& switches)
+static int svc_api_gbak(Firebird::UtilSvc* uSvc, const Switches& switches)
{
/**********************************************
*
- * a p i _ g b a k
+ * s v c _ a p i _ g b a k
*
**********************************************
*
@@ -172,12 +172,18 @@
Firebird::UtilSvc::ArgvType& argv = uSvc->argv;
const int argc = uSvc->argv.getCount();
+ Firebird::string files[2];
+ unsigned fileIndex = 0;
for (int itr = 1; itr < argc; ++itr)
{
const Switches::in_sw_tab_t* inSw = switches.findSwitch(argv[itr]);
if (! inSw)
{
+ if (argv[itr][0] && fileIndex < 2)
+ {
+ files[fileIndex++] = argv[itr];
+ }
continue;
}
@@ -249,6 +255,8 @@
}
}
+ Firebird::string* dbName = flag_restore ? &files[1] : &files[0];
+
ISC_STATUS_ARRAY status;
FB_API_HANDLE svc_handle = 0;
@@ -269,6 +277,10 @@
{
spb.insertString(isc_spb_password, pswd);
}
+ if (dbName->hasData())
+ {
+ spb.insertString(isc_spb_expected_db, *dbName);
+ }
#ifdef TRUSTED_AUTH
if (flag_trusted)
{
@@ -450,7 +462,7 @@
// test for "-service" switch
if (switches.exists(IN_SW_BURP_SE, argv.begin(), 1, argc))
- return api_gbak(uSvc, switches);
+ return svc_api_gbak(uSvc, switches);
uSvc->started();
Modified: firebird/trunk/src/common/IntlParametersBlock.cpp
===================================================================
--- firebird/trunk/src/common/IntlParametersBlock.cpp 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/common/IntlParametersBlock.cpp 2013-10-16 12:53:04 UTC (rev 58698)
@@ -186,6 +186,7 @@
case isc_spb_trusted_auth:
case isc_spb_trusted_role:
case isc_spb_process_name:
+ case isc_spb_expected_db:
return TAG_STRING;
case isc_spb_command_line:
Modified: firebird/trunk/src/common/classes/ClumpletReader.cpp
===================================================================
--- firebird/trunk/src/common/classes/ClumpletReader.cpp 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/common/classes/ClumpletReader.cpp 2013-10-16 12:53:04 UTC (rev 58698)
@@ -877,4 +877,31 @@
return true;
}
+#ifdef AUTH_BLOCK_DEBUG
+void dumpAuthBlock(const char* text, ClumpletReader* pb, unsigned char param)
+{
+ fprintf(stderr, "AuthBlock in %s:", text);
+ if (pb->find(param))
+ {
+ Firebird::AuthReader::AuthBlock tmp;
+ tmp.assign(pb->getBytes(), pb->getClumpLength());
+ Firebird::AuthReader rdr(tmp);
+ string name, method;
+ PathName secureDb;
+ bool x = false;
+ while (rdr.getInfo(&name, &method, &secureDb))
+ {
+ fprintf(stderr, " %s::%s::%s", name.c_str(), method.c_str(), secureDb.c_str());
+ x = true;
+ rdr.moveNext();
+ }
+ fprintf(stderr, "%s\n", x ? "" : " <empty>");
+ }
+ else
+ {
+ fprintf(stderr, " <missing>\n");
+ }
+}
+#endif
+
} // namespace
Modified: firebird/trunk/src/common/classes/ClumpletReader.h
===================================================================
--- firebird/trunk/src/common/classes/ClumpletReader.h 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/common/classes/ClumpletReader.h 2013-10-16 12:53:04 UTC (rev 58698)
@@ -201,6 +201,13 @@
bool getInfo(string* name, string* method, PathName* secDb);
};
+//#define AUTH_BLOCK_DEBUG
+#ifdef AUTH_BLOCK_DEBUG
+void dumpAuthBlock(const char* text, ClumpletReader* pb, unsigned char param);
+#else
+static inline void dumpAuthBlock(const char*, ClumpletReader*, unsigned char) { }
+#endif
+
} // namespace Firebird
#endif // CLUMPLETREADER_H
Modified: firebird/trunk/src/common/classes/array.h
===================================================================
--- firebird/trunk/src/common/classes/array.h 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/common/classes/array.h 2013-10-16 12:53:04 UTC (rev 58698)
@@ -140,8 +140,15 @@
}
public:
- typedef T* iterator;
- typedef const T* const_iterator;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T value_type;
+ typedef pointer iterator;
+ typedef const_pointer const_iterator;
Array<T, Storage>& operator =(const Array<T, Storage>& source)
{
Modified: firebird/trunk/src/common/classes/fb_string.h
===================================================================
--- firebird/trunk/src/common/classes/fb_string.h 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/common/classes/fb_string.h 2013-10-16 12:53:04 UTC (rev 58698)
@@ -228,6 +228,10 @@
{
return stringLength;
}
+ size_type getCount() const
+ {
+ return stringLength;
+ }
// Almost same as c_str(), but return 0, not "",
// when string has no data. Useful when interacting
// with old code, which does check for NULL.
@@ -245,6 +249,10 @@
void reserve(size_type n = 0);
void resize(const size_type n, char_type c = ' ');
+ void grow(const size_type n)
+ {
+ resize(n);
+ }
pointer getBuffer(size_t l)
{
Modified: firebird/trunk/src/common/config/config.cpp
===================================================================
--- firebird/trunk/src/common/config/config.cpp 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/common/config/config.cpp 2013-10-16 12:53:04 UTC (rev 58698)
@@ -121,9 +121,6 @@
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] =
{
@@ -677,7 +674,7 @@
return (const char*) values[KEY_PLUG_KEY_HOLDER];
}
- (Firebird::Arg::Gds(isc_random) << "Internal error in Config::getPlugins()").raise();
+ (Firebird::Arg::Gds(isc_random) << "Internal error in Config::getPlugins(): unknown plugin type requested").raise();
return NULL; // compiler warning silencer
}
@@ -717,8 +714,19 @@
return get<const char*>(KEY_SECURITY_DATABASE);
}
-const char* Config::getWireCrypt(WireCryptMode wcMode) const
+int Config::getWireCrypt(WireCryptMode wcMode) const
{
- const char* rc = get<const char*>(KEY_WIRE_CRYPT);
- return rc ? rc : wcMode == WC_CLIENT ? WIRE_CRYPT_ENABLED : WIRE_CRYPT_REQUIRED;
+ const char* wc = get<const char*>(KEY_WIRE_CRYPT);
+ if (!wc)
+ {
+ return wcMode == WC_CLIENT ? WIRE_CRYPT_ENABLED : WIRE_CRYPT_REQUIRED;
+ }
+
+ Firebird::NoCaseString wireCrypt(wc);
+ if (wireCrypt == "DISABLED")
+ return WIRE_CRYPT_DISABLED;
+ else if (wireCrypt == "ENABLED")
+ return WIRE_CRYPT_ENABLED;
+ else // the safest choice
+ return WIRE_CRYPT_REQUIRED;
}
Modified: firebird/trunk/src/common/config/config.h
===================================================================
--- firebird/trunk/src/common/config/config.h 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/common/config/config.h 2013-10-16 12:53:04 UTC (rev 58698)
@@ -75,9 +75,9 @@
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;
+const int WIRE_CRYPT_DISABLED = 0;
+const int WIRE_CRYPT_ENABLED = 1;
+const int WIRE_CRYPT_REQUIRED = 2;
enum WireCryptMode {WC_CLIENT, WC_SERVER}; // Have different defaults
@@ -335,7 +335,7 @@
const char* getSecurityDatabase() const;
- const char* getWireCrypt(WireCryptMode wcMode) const;
+ int getWireCrypt(WireCryptMode wcMode) const;
};
// Implementation of interface to access master configuration file
Modified: firebird/trunk/src/include/consts_pub.h
===================================================================
--- firebird/trunk/src/include/consts_pub.h 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/include/consts_pub.h 2013-10-16 12:53:04 UTC (rev 58698)
@@ -282,6 +282,7 @@
#define isc_spb_host_name 121
#define isc_spb_os_user 122
#define isc_spb_config 123
+#define isc_spb_expected_db 124
#define isc_spb_connect_timeout isc_dpb_connect_timeout
#define isc_spb_dummy_packet_interval isc_dpb_dummy_packet_interval
Modified: firebird/trunk/src/include/gen/codetext.h
===================================================================
--- firebird/trunk/src/include/gen/codetext.h 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/include/gen/codetext.h 2013-10-16 12:53:04 UTC (rev 58698)
@@ -761,6 +761,17 @@
{"include_miss", 335545057},
{"protect_ownership", 335545058},
{"badvarnum", 335545059},
+ {"sec_context", 335545060},
+ {"multi_segment", 335545061},
+ {"login_changed", 335545062},
+ {"auth_handshake_limit", 335545063},
+ {"wirecrypt_incompatible", 335545064},
+ {"miss_wirecrypt", 335545065},
+ {"wirecrypt_key", 335545066},
+ {"wirecrypt_plugin", 335545067},
+ {"secdb_name", 335545068},
+ {"auth_data", 335545069},
+ {"auth_datalength", 335545070},
{"gfix_db_name", 335740929},
{"gfix_invalid_sw", 335740930},
{"gfix_incmp_sw", 335740932},
Modified: firebird/trunk/src/include/gen/iberror.h
===================================================================
--- firebird/trunk/src/include/gen/iberror.h 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/include/gen/iberror.h 2013-10-16 12:53:04 UTC (rev 58698)
@@ -795,6 +795,17 @@
const ISC_STATUS isc_include_miss = 335545057L;
const ISC_STATUS isc_protect_ownership = 335545058L;
const ISC_STATUS isc_badvarnum = 335545059L;
+const ISC_STATUS isc_sec_context = 335545060L;
+const ISC_STATUS isc_multi_segment = 335545061L;
+const ISC_STATUS isc_login_changed = 335545062L;
+const ISC_STATUS isc_auth_handshake_limit = 335545063L;
+const ISC_STATUS isc_wirecrypt_incompatible = 335545064L;
+const ISC_STATUS isc_miss_wirecrypt = 335545065L;
+const ISC_STATUS isc_wirecrypt_key = 335545066L;
+const ISC_STATUS isc_wirecrypt_plugin = 335545067L;
+const ISC_STATUS isc_secdb_name = 335545068L;
+const ISC_STATUS isc_auth_data = 335545069L;
+const ISC_STATUS isc_auth_datalength = 335545070L;
const ISC_STATUS isc_gfix_db_name = 335740929L;
const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
@@ -1239,7 +1250,7 @@
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
-const ISC_STATUS isc_err_max = 1183;
+const ISC_STATUS isc_err_max = 1194;
#else /* c definitions */
@@ -2004,6 +2015,17 @@
#define isc_include_miss 335545057L
#define isc_protect_ownership 335545058L
#define isc_badvarnum 335545059L
+#define isc_sec_context 335545060L
+#define isc_multi_segment 335545061L
+#define isc_login_changed 335545062L
+#define isc_auth_handshake_limit 335545063L
+#define isc_wirecrypt_incompatible 335545064L
+#define isc_miss_wirecrypt 335545065L
+#define isc_wirecrypt_key 335545066L
+#define isc_wirecrypt_plugin 335545067L
+#define isc_secdb_name 335545068L
+#define isc_auth_data 335545069L
+#define isc_auth_datalength 335545070L
#define isc_gfix_db_name 335740929L
#define isc_gfix_invalid_sw 335740930L
#define isc_gfix_incmp_sw 335740932L
@@ -2448,7 +2470,7 @@
#define isc_trace_switch_param_miss 337182758L
#define isc_trace_param_act_notcompat 337182759L
#define isc_trace_mandatory_switch_miss 337182760L
-#define isc_err_max 1183
+#define isc_err_max 1194
#endif
Modified: firebird/trunk/src/include/gen/msgs.h
===================================================================
--- firebird/trunk/src/include/gen/msgs.h 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/include/gen/msgs.h 2013-10-16 12:53:04 UTC (rev 58698)
@@ -764,6 +764,17 @@
{335545057, "File to include not found"}, /* include_miss */
{335545058, "Only the owner can change the ownership"}, /* protect_ownership */
{335545059, "undefined variable number"}, /* badvarnum */
+ {335545060, "Missing security context for database @1"}, /* sec_context */
+ {335545061, "Missing segment @1 in multisegment connect block parameter"}, /* multi_segment */
+ {335545062, "Different logins in connect and attach packets - client library error"}, /* login_changed */
+ {335545063, "Exceeded exchange limit during authentication handshake"}, /* auth_handshake_limit */
+ {335545064, "Incompatible wire encryption levels requested on client and server"}, /* wirecrypt_incompatible */
+ {335545065, "Client attempted to attach unencrypted but wire encryption is required"}, /* miss_wirecrypt */
+ {335545066, "Client attempted to start wire encryption using unknown key @1"}, /* wirecrypt_key */
+ {335545067, "Client attempted to start wire encryption using unsupported plugin @1"}, /* wirecrypt_plugin */
+ {335545068, "Error getting security database name from configuration file"}, /* secdb_name */
+ {335545069, "Client authentication plugin is missing required data from server"}, /* auth_data */
+ {335545070, "Client authentication plugin expected @2 bytes of @3 from server, got @1"}, /* auth_datalength */
{335740929, "data base file name (@1) already given"}, /* gfix_db_name */
{335740930, "invalid switch @1"}, /* gfix_invalid_sw */
{335740932, "incompatible switch combination"}, /* gfix_incmp_sw */
Modified: firebird/trunk/src/include/gen/sql_code.h
===================================================================
--- firebird/trunk/src/include/gen/sql_code.h 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/include/gen/sql_code.h 2013-10-16 12:53:04 UTC (rev 58698)
@@ -760,6 +760,17 @@
{335545057, -902}, /* 737 include_miss */
{335545058, -552}, /* 738 protect_ownership */
{335545059, -901}, /* 739 badvarnum */
+ {335545060, -902}, /* 740 sec_context */
+ {335545061, -902}, /* 741 multi_segment */
+ {335545062, -902}, /* 742 login_changed */
+ {335545063, -902}, /* 743 auth_handshake_limit */
+ {335545064, -902}, /* 744 wirecrypt_incompatible */
+ {335545065, -902}, /* 745 miss_wirecrypt */
+ {335545066, -902}, /* 746 wirecrypt_key */
+ {335545067, -902}, /* 747 wirecrypt_plugin */
+ {335545068, -902}, /* 748 secdb_name */
+ {335545069, -902}, /* 749 auth_data */
+ {335545070, -902}, /* 750 auth_datalength */
{335740929, -901}, /* 1 gfix_db_name */
{335740930, -901}, /* 2 gfix_invalid_sw */
{335740932, -901}, /* 4 gfix_incmp_sw */
Modified: firebird/trunk/src/include/gen/sql_state.h
===================================================================
--- firebird/trunk/src/include/gen/sql_state.h 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/include/gen/sql_state.h 2013-10-16 12:53:04 UTC (rev 58698)
@@ -760,6 +760,17 @@
{335545057, "XX000"}, // 737 include_miss
{335545058, "28000"}, // 738 protect_ownership
{335545059, "HY000"}, // 739 badvarnum
+ {335545060, "28000"}, // 740 sec_context
+ {335545061, "28000"}, // 741 multi_segment
+ {335545062, "28000"}, // 742 login_changed
+ {335545063, "28000"}, // 743 auth_handshake_limit
+ {335545064, "28000"}, // 744 wirecrypt_incompatible
+ {335545065, "28000"}, // 745 miss_wirecrypt
+ {335545066, "28000"}, // 746 wirecrypt_key
+ {335545067, "28000"}, // 747 wirecrypt_plugin
+ {335545068, "28000"}, // 748 secdb_name
+ {335545069, "28000"}, // 749 auth_data
+ {335545070, "28000"}, // 750 auth_datalength
{335740929, "00000"}, // 1 gfix_db_name
{335740930, "00000"}, // 2 gfix_invalid_sw
{335740932, "00000"}, // 4 gfix_incmp_sw
Modified: firebird/trunk/src/jrd/jrd.cpp
===================================================================
--- firebird/trunk/src/jrd/jrd.cpp 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/jrd/jrd.cpp 2013-10-16 12:53:04 UTC (rev 58698)
@@ -946,7 +946,7 @@
static bool shutdown_database(Database*, const bool);
static void strip_quotes(string&);
static void purge_attachment(thread_db*, JAttachment*, const bool);
-static void getUserInfo(UserId&, const DatabaseOptions&, const RefPtr<Config>*);
+static void getUserInfo(UserId&, const DatabaseOptions&, const char*, const RefPtr<Config>*);
static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM);
@@ -955,7 +955,7 @@
m_filename(filename),
m_options(options)
{
- getUserInfo(m_id, *m_options, NULL);
+ getUserInfo(m_id, *m_options, m_filename, NULL);
}
@@ -1276,7 +1276,7 @@
}
// Check for correct credentials supplied
- getUserInfo(userId, options, &config);
+ getUserInfo(userId, options, org_filename.c_str(), &config);
}
catch (const Exception& ex)
{
@@ -2363,7 +2363,7 @@
}
// Check for correct credentials supplied
- getUserInfo(userId, options, &config);
+ getUserInfo(userId, options, org_filename.c_str(), &config);
}
catch (const Exception& ex)
{
@@ -5462,6 +5462,7 @@
}
ClumpletReader rdr(ClumpletReader::dpbList, dpb, dpb_length, dpbErrorRaise);
+ dumpAuthBlock("DatabaseOptions::get()", &rdr, isc_dpb_auth_block);
dpb_utf8_filename = rdr.find(isc_dpb_utf8_filename);
@@ -6941,7 +6942,8 @@
@param
**/
-static void getUserInfo(UserId& user, const DatabaseOptions& options, const RefPtr<Config>* config)
+static void getUserInfo(UserId& user, const DatabaseOptions& options,
+ const char* dbName, const RefPtr<Config>* config)
{
bool wheel = false;
int id = -1, group = -1; // CVC: This var contained trash
@@ -6974,7 +6976,7 @@
{
if (config && (secureDb != (*config)->getSecurityDatabase()))
{
- (Arg::Gds(isc_login) << Arg::Gds(isc_random) << "No SecDb match").raise();
+ (Arg::Gds(isc_sec_context) << dbName).raise();
}
}
else
Modified: firebird/trunk/src/jrd/svc.cpp
===================================================================
--- firebird/trunk/src/jrd/svc.cpp 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/jrd/svc.cpp 2013-10-16 12:53:04 UTC (rev 58698)
@@ -756,6 +756,7 @@
// Process the service parameter block.
ClumpletReader spb(ClumpletReader::spbList, spb_data, spb_length, spbVersionError);
+ dumpAuthBlock("Jrd::Service() ctor", &spb, isc_spb_auth_block);
getOptions(spb);
// Perhaps checkout the user in the security database.
Modified: firebird/trunk/src/msgs/facilities2.sql
===================================================================
--- firebird/trunk/src/msgs/facilities2.sql 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/msgs/facilities2.sql 2013-10-16 12:53:04 UTC (rev 58698)
@@ -1,7 +1,7 @@
/* MAX_NUMBER is the next number to be used, always one more than the highest message number. */
set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES (?, ?, ?, ?);
--
-('2013-09-04 11:02:00', 'JRD', 0, 740)
+('2013-10-15 17:48:59', 'JRD', 0, 751)
('2012-01-23 20:10:30', 'QLI', 1, 532)
('2009-07-16 05:26:11', 'GFIX', 3, 121)
('1996-11-07 13:39:40', 'GPRE', 4, 1)
Modified: firebird/trunk/src/msgs/messages2.sql
===================================================================
--- firebird/trunk/src/msgs/messages2.sql 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/msgs/messages2.sql 2013-10-16 12:53:04 UTC (rev 58698)
@@ -847,6 +847,17 @@
('include_miss', NULL, 'config_file.cpp', NULL, 0, 737, NULL, 'File to include not found', NULL, NULL);
('protect_ownership', 'check_owner', 'vio.cpp', NULL, 0, 738, NULL, 'Only the owner can change the ownership', NULL, NULL);
('badvarnum', NULL, NULL, NULL, 0, 739, NULL, 'undefined variable number', NULL, NULL);
+('sec_context', 'getUserInfo', 'jrd.cpp', NULL, 0, 740, NULL, 'Missing security context for database @1', NULL, NULL);
+('multi_segment', 'getMultiPartConnectParameter', 'server.cpp', NULL, 0, 741, NULL, 'Missing segment @1 in multisegment connect block parameter', NULL, NULL);
+('login_changed', 'ServerAuth::ServerAuth', 'server.cpp', NULL, 0, 742, NULL, 'Different logins in connect and attach packets - client library error', NULL, NULL);
+('auth_handshake_limit', 'ServerAuth::authenticate', 'server.cpp', NULL, 0, 743, NULL, 'Exceeded exchange limit during authentication handshake', NULL, NULL);
+('wirecrypt_incompatible', 'requiredEncryption', 'server.cpp', NULL, 0, 744, NULL, 'Incompatible wire encryption levels requested on client and server', NULL, NULL);
+('miss_wirecrypt', NULL, 'server.cpp', NULL, 0, 745, NULL, 'Client attempted to attach unencrypted but wire encryption is required', NULL, NULL);
+('wirecrypt_key', 'start_crypt', 'server.cpp', NULL, 0, 746, NULL, 'Client attempted to start wire encryption using unknown key @1', NULL, NULL);
+('wirecrypt_plugin', 'start_crypt', 'server.cpp', NULL, 0, 747, NULL, 'Client attempted to start wire encryption using unsupported plugin @1', NULL, NULL);
+('secdb_name', NULL, NULL, NULL, 0, 748, NULL, 'Error getting security database name from configuration file', NULL, NULL);
+('auth_data', NULL, NULL, NULL, 0, 749, NULL, 'Client authentication plugin is missing required data from server', NULL, NULL);
+('auth_datalength', NULL, NULL, NULL, 0, 750, NULL, 'Client authentication plugin expected @2 bytes of @3 from server, got @1', NULL, NULL);
-- QLI
(NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL);
(NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL);
Modified: firebird/trunk/src/msgs/system_errors2.sql
===================================================================
--- firebird/trunk/src/msgs/system_errors2.sql 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/msgs/system_errors2.sql 2013-10-16 12:53:04 UTC (rev 58698)
@@ -746,6 +746,17 @@
(-902, 'XX', '000', 0, 737, 'include_miss', NULL, NULL)
(-552, '28', '000', 0, 738, 'protect_ownership', NULL, NULL)
(-901, 'HY', '000', 0, 739, 'badvarnum', NULL, NULL)
+(-902, '28', '000', 0, 740, 'sec_context', NULL, NULL);
+(-902, '28', '000', 0, 741, 'multi_segment', NULL, NULL);
+(-902, '28', '000', 0, 742, 'login_changed', NULL, NULL);
+(-902, '28', '000', 0, 743, 'auth_handshake_limit', NULL, NULL);
+(-902, '28', '000', 0, 744, 'wirecrypt_incompatible', NULL, NULL);
+(-902, '28', '000', 0, 745, 'miss_wirecrypt', NULL, NULL);
+(-902, '28', '000', 0, 746, 'wirecrypt_key', NULL, NULL);
+(-902, '28', '000', 0, 747, 'wirecrypt_plugin', NULL, NULL);
+(-902, '28', '000', 0, 748, 'secdb_name', NULL, NULL);
+(-902, '28', '000', 0, 749, 'auth_data', NULL, NULL);
+(-902, '28', '000', 0, 750, 'auth_datalength', NULL, NULL);
-- GFIX
(-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL)
(-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL)
Modified: firebird/trunk/src/remote/client/interface.cpp
===================================================================
--- firebird/trunk/src/remote/client/interface.cpp 2013-10-16 00:27:45 UTC (rev 58697)
+++ firebird/trunk/src/remote/client/interface.cpp 2013-10-16 12:53:04 UTC (rev 58698)
@@ -661,8 +661,8 @@
static Rvnt* add_event(rem_port*);
static void add_other_params(rem_port*, ClumpletWriter&, const ParametersSet&);
static void add_working_directory(ClumpletWriter&, const PathName&);
-static rem_port* analyze(ClntAuthBlock&, PathName&, bool, ClumpletWriter&, PathName&, bool);
-static rem_port* analyze_service(ClntAuthBlock&, PathName&, bool, ClumpletReader&, bool);
+static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned flags,
+ ClumpletWriter& pb, const ParametersSet& parSet, PathName& node_name, PathName* ref_db_name);
static void batch_gds_receive(rem_port*, struct rmtque *, USHORT);
static void batch_dsql_fetch(rem_port*, struct rmtque *, USHORT);
static void clear_queue(rem_port*);
@@ -674,7 +674,7 @@
static Rvnt* find_event(rem_port*, SLONG);
static bool get_new_dpb(ClumpletWriter&, const ParametersSet&);
static void info(IStatus*, Rdb*, P_OP, USHORT, USHORT, USHORT,
- const UCHAR*, USHORT, const UCHAR*, ULONG, UCHAR*, ClntAuthBlock* cBlock = NULL);
+ const UCHAR*, USHORT, const UCHAR*, ULONG, UCHAR*);
static void init(IStatus*, ClntAuthBlock&, rem_port*, P_OP, PathName&,
ClumpletWriter&, IntlParametersBlock&, ICryptKeyCallback* cryptCallback);
static Rtr* make_transaction(Rdb*, USHORT);
@@ -702,14 +702,17 @@
static void unsupported();
static void zap_packet(PACKET *);
static void cleanDpb(Firebird::ClumpletWriter&, const ParametersSet*);
-
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, bool checkKeys);
+static void authReceiveResponse(bool havePacket, ClntAuthBlock& authItr, rem_port* port,
+ Rdb* rdb, IStatus* status, PACKET* packet, bool checkKeys);
static AtomicCounter remote_event_id;
+static const unsigned ANALYZE_UV = 0x01;
+static const unsigned ANALYZE_LOOPBACK = 0x02;
+static const unsigned ANALYZE_MOUNTS = 0x03;
+
inline static void reset(IStatus* status) throw()
{
status->init();
@@ -753,13 +756,17 @@
reset(status);
ClumpletWriter newDpb(ClumpletReader::dpbList, MAX_DPB_SIZE, dpb, dpb_length);
- const bool user_verification = get_new_dpb(newDpb, dpbParam);
+ unsigned flags = ANALYZE_MOUNTS;
+ if (get_new_dpb(newDpb, dpbParam))
+ flags |= ANALYZE_UV;
+ if (loopback)
+ flags |= ANALYZE_LOOPBACK;
PathName expanded_name(filename);
PathName node_name;
ClntAuthBlock cBlock(&expanded_name, &newDpb, &dpbParam);
- rem_port* port = analyze(cBlock, expanded_name, user_verification, newDpb, node_name, loopback);
+ rem_port* port = analyze(cBlock, expanded_name, flags, newDpb, dpbParam, node_name, NULL);
if (!port)
{
@@ -770,13 +777,13 @@
RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
// The client may have set a parameter for dummy_packet_interval. Add that to the
- // the DPB so the server can pay attention to it. Note: allocation code must
- // ensure sufficient space has been added.
+ // the DPB so the server can pay attention to it.
add_other_params(port, newDpb, dpbParam);
add_working_directory(newDpb, node_name);
IntlDpb intl;
+ HANDSHAKE_DEBUG(fprintf(stderr, "Cli: call init for DB='%s'\n", expanded_name.c_str()));
init(status, cBlock, port, op_attach, expanded_name, newDpb, intl, cryptCallback);
Attachment* a = new Attachment(port->port_context, filename);
@@ -1336,13 +1343,17 @@
ClumpletWriter newDpb(ClumpletReader::dpbList, MAX_DPB_SIZE,
reinterpret_cast<const UCHAR*>(dpb), dpb_length);
- const bool user_verification = get_new_dpb(newDpb, dpbParam);
+ unsigned flags = ANALYZE_MOUNTS;
+ if (get_new_dpb(newDpb, dpbParam))
+ flags |= ANALYZE_UV;
+ if (loopback)
+ flags |= ANALYZE_LOOPBACK;
PathName expanded_name(filename);
PathName node_name;
ClntAuthBlock cBlock(&expanded_name, &newDpb, &dpbParam);
- rem_port* port = analyze(cBlock, expanded_name, user_verification, newDpb, node_name, loopback);
+ rem_port* port = analyze(cBlock, expanded_name, flags, newDpb, dpbParam, node_name, NULL);
if (!port)
{
@@ -4560,15 +4571,26 @@
{
reset(status);
- PathName expanded_name(service);
+ PathName node_name, expanded_name(service);
ClumpletWriter newSpb(ClumpletReader::spbList, MAX_DPB_SIZE, spb, spbLength);
const bool user_verification = get_new_dpb(newSpb, spbParam);
ClntAuthBlock cBlock(NULL, &newSpb, &spbParam);
- cBlock.loadClnt(newSpb, &spbParam);
- rem_port* port = analyze_service(cBlock, expanded_name, user_verification, newSpb, loopback);
+ unsigned flags = 0;
+ if (get_new_dpb(newSpb, spbParam))
+ flags |= ANALYZE_UV;
+ if (loopback)
+ flags |= ANALYZE_LOOPBACK;
+ PathName refDbName;
+ if (newSpb.find(isc_spb_expected_db))
+ {
+ newSpb.getPath(refDbName);
+ }
+
+ rem_port* port = analyze(cBlock, expanded_name, flags, newSpb, spbParam, node_name, &refDbName);
+
RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
Rdb* rdb = port->port_context;
@@ -4581,8 +4603,6 @@
IntlSpb intl;
init(status, cBlock, port, op_service_attach, expanded_name, newSpb, intl, cryptCallback);
- cBlock.saveServiceDataTo(port);
-
Firebird::IService* s = new Service(rdb);
s->addRef();
return s;
@@ -4718,12 +4738,9 @@
rem_port* port = rdb->rdb_port;
RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
- ClntAuthBlock cBlock(NULL, NULL, NULL);
- cBlock.loadServiceDataFrom(port);
-
info(status, rdb, op_service_info, rdb->rdb_id, 0,
sendLength, sendItems, receiveLength, receiveItems,
- bufferLength, buffer, &cBlock);
+ bufferLength, buffer);
}
catch (const Exception& ex)
{
@@ -5322,13 +5339,34 @@
}
-static rem_port* analyze(ClntAuthBlock& cBlock,
- PathName& file_name,
- bool uv_flag,
- ClumpletWriter& dpb,
- PathName& node_name,
- bool loopback)
+static void secureAuthentication(ClntAuthBlock& cBlock, rem_port* port)
{
+ HANDSHAKE_DEBUG(fprintf(stderr, "Cli: secureAuthentication\n"));
+
+ if (!port)
+ return;
+
+ Rdb* rdb = port->port_context;
+ fb_assert(rdb);
+ PACKET* packet = &rdb->rdb_packet;
+
+ HANDSHAKE_DEBUG(fprintf(stderr, "Cli: secureAuthentication: port OK, op=%d\n", packet->p_operation));
+
+ if (packet->p_operation == op_cond_accept)
+ {
+ LocalStatus st;
+ authReceiveResponse(true, cBlock, port, rdb, &st, packet, true);
+ if (!st.isSuccess())
+ {
+ status_exception::raise(st.get());
+ }
+ }
+}
+
+
+static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned flags,
+ ClumpletWriter& pb, const ParametersSet& parSet, PathName& node_name, PathName* ref_db_name)
+{
/**************************************
*
* a n a l y z e
@@ -5336,9 +5374,9 @@
**************************************
*
* Functional description
- * Analyze a file specification and determine whether
+ * Analyze an attach specification and determine whether
* a remote server is required, and if so, what protocol
- * to use. If the database can be accessed via the
+ * to use. If the target can be accessed via the
* remote subsystem, return address of a port block
* with which to communicate with the server.
* Otherwise, return NULL.
@@ -5347,196 +5385,140 @@
*
**************************************/
- // Analyze the file name to see if a remote connection is required. If not,
- // quietly (sic) return.
+ rem_port* port = NULL;
- cBlock.loadClnt(dpb, &dpbParam);
+ try
+ {
+ cBlock.loadClnt(pb, &parSet);
authenticateStep0(cBlock);
- rem_port* port = NULL;
#ifdef WIN_NT
- if (ISC_analyze_protocol(PROTOCOL_XNET, file_name, node_name))
+ if (ISC_analyze_protocol(PROTOCOL_XNET, attach_name, node_name))
{
- port = XNET_analyze(&cBlock, file_name, uv_flag, cBlock.getConfig());
+ port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_UV, cBlock.getConfig(), ref_db_name);
}
- else if (ISC_analyze_protocol(PROTOCOL_WNET, file_name, node_name) ||
- ISC_analyze_pclan(file_name, node_name))
+ else if (ISC_analyze_protocol(PROTOCOL_WNET, attach_name, node_name) ||
+ ISC_analyze_pclan(attach_name, node_name))
{
if (node_name.isEmpty())
+ {
node_name = WNET_LOCALHOST;
+ }
else
{
ISC_unescape(node_name);
ISC_utf8ToSystem(node_name);
}
-
- port = WNET_analyze(&cBlock, file_name, node_name.c_str(), uv_flag, cBlock.getConfig());
+ port = WNET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_UV,
+ cBlock.getConfig(), ref_db_name);
}
else
#endif
- if (ISC_analyze_protocol(PROTOCOL_INET, file_name, node_name) ||
- ISC_analyze_tcp(file_name, node_name))
+ if (ISC_analyze_protocol(PROTOCOL_INET, attach_name, node_name) ||
+ ISC_analyze_tcp(attach_name, node_name))
{
if (node_name.isEmpty())
+ {
node_name = INET_LOCALHOST;
+ }
else
{
ISC_unescape(node_name);
ISC_utf8ToSystem(node_name);
}
-
- port = INET_analyze(&cBlock, file_name, node_name.c_str(), uv_flag, dpb, cBlock.getConfig());
+ port = INET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_UV, pb,
+ cBlock.getConfig(), ref_db_name);
}
// We have a local connection string. If it's a file on a network share,
// try to connect to the corresponding host remotely.
+ if (flags & ANALYZE_MOUNTS)
+ {
#ifdef WIN_NT
- PathName expanded_name = file_name;
- ISC_expand_share(expanded_name);
+ if (!port)
+ {
+ PathName expanded_name = attach_name;
+ ISC_expand_share(expanded_name);
- if (ISC_analyze_pclan(expanded_name, node_name))
- {
- ISC_unescape(node_name);
- ISC_utf8ToSystem(node_name);
+ if (ISC_analyze_pclan(expanded_name, node_name))
+ {
+ ISC_unescape(node_name);
+ ISC_utf8ToSystem(node_name);
- port = WNET_analyze(&cBlock, expanded_name, node_name.c_str(), uv_flag, cBlock.getConfig());
- }
+ port = WNET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_UV,
+ cBlock.getConfig(), ref_db_name);
+ }
+ }
#endif
#ifndef NO_NFS
- if (!port)
- {
- PathName expanded_name = file_name;
- if (ISC_analyze_nfs(expanded_name, node_name))
+ if (!port)
{
- ISC_unescape(node_name);
- ISC_utf8ToSystem(node_name);
+ PathName expanded_name = attach_name;
+ if (ISC_analyze_nfs(expanded_name, node_name))
+ {
+ ISC_unescape(node_name);
+ ISC_utf8ToSystem(node_name);
- port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), uv_flag, dpb, cBlock.getConfig());
+ port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_UV, pb,
+ cBlock.getConfig(), ref_db_name);
+ }
}
+#endif
}
-#endif
- if (loopback)
+ if ((flags & ANALYZE_LOOPBACK) && !port)
{
- // We still have a local connection string but failed to connect so far.
- // If we're a pure client, attempt connect to the localhost.
+ // We have a local connection string.
+ // If we are in loopback mode attempt connect to a localhost.
if (node_name.isEmpty())
{
#ifdef WIN_NT
if (!port)
{
- port = XNET_analyze(&cBlock, file_name, uv_flag, cBlock.getConfig());
+ port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_UV, cBlock.getConfig(), ref_db_name);
}
if (!port)
{
- port = WNET_analyze(&cBlock, file_name, WNET_LOCALHOST, uv_flag, cBlock.getConfig());
+ port = WNET_analyze(&cBlock, attach_name, WNET_LOCALHOST, flags & ANALYZE_UV,
+ cBlock.getConfig(), ref_db_name);
}
#endif
if (!port)
{
- port = INET_analyze(&cBlock, file_name, INET_LOCALHOST, uv_flag, dpb, cBlock.getConfig());
+ port = INET_analyze(&cBlock, attach_name, INET_LOCALHOST, flags & ANALYZE_UV, pb,
+ cBlock.getConfig(), ref_db_name);
}
}
}
-
- return port;
-}
-
-
-static rem_port* analyze_service(ClntAuthBlock& cBlock,
- PathName& service_name,
- bool uv_flag,
- ClumpletReader& spb,
- bool loopback)
-{
-/**************************************
- *
- * a n a l y z e _ s e r v i c e
- *
- **************************************
- *
- * Functional description
- * Analyze a service specification and determine whether
- * a remote server is required, and if so, what protocol
- * to use. If the database can be accessed via the
- * remote subsystem, return address of a port block
- * with which to communicate with the server.
- * Otherwise, return NULL.
- *
- **************************************/
- // Analyze the service name to see if a remote connection is required. If not,
- // quietly (sic) return.
-
- PathName node_name;
-
-#if defined(WIN_NT)
- if (ISC_analyze_protocol(PROTOCOL_XNET, service_name, node_name))
+ if (!port)
{
- return XNET_analyze(NULL, service_name, uv_flag, cBlock.getConfig());
+ Arg::Gds(isc_unavailable).raise();
}
- if (ISC_analyze_protocol(PROTOCOL_WNET, service_name, node_name) ||
- ISC_analyze_pclan(service_name, node_name))
+ secureAuthentication(cBlock, port);
+ }
+ catch (const status_exception& ex)
+ {
+ const ISC_STATUS* s = ex.value();
+ if (s[1] != isc_unavailable)
{
- if (node_name.isEmpty())
- {
- node_name = WNET_LOCALHOST;
- }
- return WNET_analyze(NULL, service_name, node_name.c_str(), uv_flag, cBlock.getConfig());
+ (Arg::Gds(isc_unavailable) << Arg::StatusVector(s)).raise();
}
-#endif
-
- if (ISC_analyze_protocol(PROTOCOL_INET, service_name, node_name) ||
- ISC_analyze_tcp(service_name, node_name))
+ else
{
- if (node_name.isEmpty())
- {
- node_name = INET_LOCALHOST;
- }
- return INET_analyze(NULL, service_name, node_name.c_str(), uv_flag, spb, cBlock.getConfig());
+ throw;
}
+ }
- rem_port* port = NULL;
+ return port;
+}
- if (loopback)
- {
- // We have a local connection string. If we're a pure client,
- // attempt connect to a localhost.
-
- if (node_name.isEmpty())
- {
-#if defined(WIN_NT)
- if (!port)
- {
- port = XNET_analyze(NULL, service_name, uv_flag, cBlock.getConfig());
- }
-
- if (!port)
- {
- port = WNET_analyze(NULL, service_name, WNET_LOCALHOST, uv_flag, cBlock.getConfig());
- }
-#endif
- if (!port)
- {
- port = INET_analyze(NULL, service_name, INET_LOCALHOST, uv_flag, spb, cBlock.getConfig());
- }
- }
- }
-
- if (!port)
- {
- Arg::Gds(isc_unavailable).raise();
- }
-
- return port;
-}
-
static void clear_stmt_que(rem_port* port, Rsr* statement)
{
/**************************************
@@ -6095,8 +6077,7 @@
USHORT recv_item_length,
const UCHAR* recv_items,
ULONG buffer_length,
- UCHAR* buffer,
- ClntAuthBlock* cBlock)
+ UCHAR* buffer)
{
/**************************************
*
@@ -6136,18 +6117,7 @@
try
{
- if (operation == op_service_info)
- {
- // Probably communicate with services auth
- fb_assert(cBlock);
- HANDSHAKE_DEBUG(fprintf(stderr, "Cli: info() calls authReceiveResponse\n"));
- authReceiveResponse(*cBlock, rdb->rdb_port, rdb, status, packet, false);
- }
- else
- {
- // Just get response from server
- receive_response(status, rdb, packet);
- }
+ receive_response(status, rdb, packet);
}
catch (const Exception&)
{
@@ -6162,6 +6132,11 @@
static void authFillParametersBlock(ClntAuthBlock& cBlock, ClumpletWriter& dpb,
const ParametersSet* tags, rem_port* port)
{
+ if (cBlock.authComplete)
+ {
+ return; // Already authenticated
+ }
+
LocalStatus s;
cBlock.resetDataFromPlugin();
@@ -6231,15 +6206,23 @@
}
}
-static void authReceiveResponse(ClntAuthBlock& cBlock, rem_port* port, Rdb* rdb,
- IStatus* status, PACKET* packet, bool checkKeys)
+static void authReceiveResponse(bool havePacket, ClntAuthBlock& cBlock, rem_port* port,
+ Rdb* rdb, IStatus* status, PACKET* packet, bool checkKeys)
{
LocalStatus s;
for (;;)
{
// Get response
- receive_packet(port, packet);
+ if (!havePacket)
+ {
+ receive_packet(port, packet);
+ }
+ else
+ {
+ fb_assert(packet->p_operation == op_cond_accept);
+ }
+ havePacket = false; // havePacket means first packet is already received
// Check response
cstring* n = NULL;
@@ -6256,11 +6239,20 @@
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, "Cli: authReceiveResponse: ont_auth d=%d n=%d '%.*s' 0x%x\n",
+ HANDSHAKE_DEBUG(fprintf(stderr, "Cli: authReceiveResponse: cont_auth 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_cond_accept:
+ d = &packet->p_acpd.p_acpt_data;
+ n = &packet->p_acpd.p_acpt_plugin;
+ port->addServerKeys(&packet->p_acpd.p_acpt_keys);
+ HANDSHAKE_DEBUG(fprintf(stderr, "Cli: authReceiveResponse: cond_accept 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);
{
@@ -6285,6 +6277,7 @@
REMOTE_check_response(status, rdb, packet, checkKeys);
// successfully attached
HANDSHAKE_DEBUG(fprintf(stderr, "Cli: authReceiveResponse: OK!\n"));
+ cBlock.authComplete = true;
rdb->rdb_id = packet->p_resp.p_resp_object;
// try to start crypt
@@ -6392,7 +6385,7 @@
send_packet(port, packet);
- authReceiveResponse(cBlock, port, rdb, status, packet, true);
+ authReceiveResponse(false, cBlock, port, rdb, status, packet, true);
}
catch (const Exception&)
{
@@ -6681,67 +6674,71 @@
// Receive responses for all deferred packets that were already sent
Rdb* rdb = port->port_context;
- while (port->port_deferred_packets->getCount())
+
+ if (port->port_deferred_packets)
{
- rem_que_packet* const p = port->port_deferred_packets->begin();
- if (!p->sent)
- break;
+ while (port->port_deferred_packets->getCount())
+ {
+ rem_que_packet* const p = port->port_deferred_packets->begin();
+ if (!p->sent)
+ break;
- OBJCT stmt_id = 0;
- bool bCheckResponse = false, bFreeStmt = false;
+ OBJCT stmt_id = 0;
+ bool bCheckResponse = false, bFreeStmt = false;
- if (p->packet.p_operation == op_execute)
- {
- stmt_id = p->packet.p_sqldata.p_sqldata_statement;
- bCheckResponse = true;
- }
- else if (p->packet.p_operation == op_free_statement)
- {
- stmt_id = p->packet.p_sqlfree.p_sqlfree_statement;
- bFreeStmt = (p->packet.p_sqlfree.p_sqlfree_option == DSQL_drop);
- }
+ if (p->packet.p_operation == op_execute)
+ {
+ stmt_id = p->packet.p_sqldata.p_sqldata_statement;
+ bCheckResponse = true;
+ }
+ else if (p->packet.p_operation == op_free_statement)
+ {
+ stmt_id = p->packet.p_sqlfree.p_sqlfree_statement;
+ bFreeStmt = (p->packet.p_sqlfree.p_sqlfree_option == DSQL_drop);
+ }
- receive_packet_with_callback(port, &p->packet);
+ receive_packet_with_callback(port, &p->packet);
- Rsr* statement = NULL;
- if (bCheckResponse || bFreeStmt)
- {
- statement = port->port_objects[stmt_id];
- }
-
- if (bCheckResponse)
- {
- bool bAssign = true;
- try
+ Rsr* statement = NULL;
+ if (bCheckResponse || bFreeStmt)
{
- LocalStatus status;
- REMOTE_check_response(&status, rdb, &p->packet);
- statement->saveException(status.get(), false);
+ statement = port->port_objects[stmt_id];
}
- catch (const Exception& ex)
+
+ if (bCheckResponse)
{
- // save error within the corresponding statement
- statement->saveException(ex, false);
- bAssign = false;
+ bool bAssign = true;
+ try
+ {
+ LocalStatus status;
+ REMOTE_check_response(&status, rdb, &p->packet);
+ statement->saveException(status.get(), false);
+ }
+ catch (const Exception& ex)
+ {
+ // save error within the corresponding statement
+ statement->saveException(ex, false);
+ bAssign = false;
+ }
+
+ if (bAssign)
+ {
+ // assign statement to transaction
+ const OBJCT tran_id = p->packet.p_sqldata.p_sqldata_transaction;
+ Rtr* transaction = port->port_objects[tran_id];
+ statement->rsr_rtr = transaction;
+ }
}
- if (bAssign)
+ if (bFreeStmt && p->packet.p_resp.p_resp_object == INVALID_OBJECT)
{
- // assign statement to transaction
- const OBJCT tran_id = p->packet.p_sqldata.p_sqldata_transaction;
- Rtr* transaction = port->port_objects[tran_id];
- statement->rsr_rtr = transaction;
+ release_sql_request(statement);
}
- }
- if (bFreeStmt && p->packet.p_resp.p_resp_object == INVALID_OBJECT)
- {
- release_sql_request(statement);
+ // free only part of packet we worked...
[truncated message content] |