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