diff --git a/src/auth/trusted/AuthSspi.cpp b/src/auth/trusted/AuthSspi.cpp index 1af4f72762..515271b1ec 100644 --- a/src/auth/trusted/AuthSspi.cpp +++ b/src/auth/trusted/AuthSspi.cpp @@ -67,6 +67,15 @@ namespace namespace Auth { + +static thread_local bool legacySSP = false; + +void setLegacySSP(bool value) +{ + legacySSP = value; +} + + HINSTANCE AuthSspi::library = 0; bool AuthSspi::initEntries() @@ -109,7 +118,8 @@ AuthSspi::AuthSspi() groupNames(*getDefaultMemoryPool()), sessionKey(*getDefaultMemoryPool()) { TimeStamp timeOut; - hasCredentials = initEntries() && (fAcquireCredentialsHandle(0, NEGOSSP_NAME_A, + hasCredentials = initEntries() && (fAcquireCredentialsHandle(0, + legacySSP ? NTLMSP_NAME_A : NEGOSSP_NAME_A, SECPKG_CRED_BOTH, 0, 0, 0, 0, &secHndl, &timeOut) == SEC_E_OK); } diff --git a/src/auth/trusted/AuthSspi.h b/src/auth/trusted/AuthSspi.h index 92030bbb12..8988a0d6b5 100644 --- a/src/auth/trusted/AuthSspi.h +++ b/src/auth/trusted/AuthSspi.h @@ -145,6 +145,10 @@ private: void registerTrustedClient(Firebird::IPluginManager* iPlugin); void registerTrustedServer(Firebird::IPluginManager* iPlugin); +// Set per-thread flag that specify which security package should be used by +// newly created plugin instances: true - use NTLM, false - use Negotiate. +void setLegacySSP(bool value); + } // namespace Auth #endif // TRUSTED_AUTH diff --git a/src/remote/client/interface.cpp b/src/remote/client/interface.cpp index 22bd0f8ace..195de4bbf7 100644 --- a/src/remote/client/interface.cpp +++ b/src/remote/client/interface.cpp @@ -7405,91 +7405,123 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned cBlock.loadClnt(pb, &parSet); pb.deleteWithTag(parSet.auth_block); - authenticateStep0(cBlock); bool needFile = !(flags & ANALYZE_EMP_NAME); + const PathName save_attach_name(attach_name); -#ifdef WIN_NT - if (ISC_analyze_protocol(PROTOCOL_XNET, attach_name, node_name, NULL, needFile)) - port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY, cBlock.getConfig(), ref_db_name); - else +#ifdef TRUSTED_AUTH + bool legacySSP = false; + Auth::setLegacySSP(legacySSP); #endif - if (ISC_analyze_protocol(PROTOCOL_INET4, attach_name, node_name, INET_SEPARATOR, needFile)) - inet_af = AF_INET; - else if (ISC_analyze_protocol(PROTOCOL_INET6, attach_name, node_name, INET_SEPARATOR, needFile)) - inet_af = AF_INET6; - - if (inet_af != AF_UNSPEC || - ISC_analyze_protocol(PROTOCOL_INET, attach_name, node_name, INET_SEPARATOR, needFile) || - ISC_analyze_tcp(attach_name, node_name, needFile)) + while (true) { - if (node_name.isEmpty()) - node_name = INET_LOCALHOST; - else + authenticateStep0(cBlock); + + try { - ISC_unescape(node_name); - ISC_utf8ToSystem(node_name); - } - - port = INET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb, - cBlock.getConfig(), ref_db_name, cryptCb, inet_af); - } - - // 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 - if (!port) - { - PathName expanded_name = attach_name; - if (ISC_analyze_pclan(expanded_name, node_name)) - { - ISC_unescape(node_name); - ISC_utf8ToSystem(node_name); + if (ISC_analyze_protocol(PROTOCOL_XNET, attach_name, node_name, NULL, needFile)) + port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY, cBlock.getConfig(), ref_db_name); + else +#endif - port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb, - cBlock.getConfig(), ref_db_name, cryptCb); + if (ISC_analyze_protocol(PROTOCOL_INET4, attach_name, node_name, INET_SEPARATOR, needFile)) + inet_af = AF_INET; + else if (ISC_analyze_protocol(PROTOCOL_INET6, attach_name, node_name, INET_SEPARATOR, needFile)) + inet_af = AF_INET6; + + if (inet_af != AF_UNSPEC || + ISC_analyze_protocol(PROTOCOL_INET, attach_name, node_name, INET_SEPARATOR, needFile) || + ISC_analyze_tcp(attach_name, node_name, needFile)) + { + if (node_name.isEmpty()) + node_name = INET_LOCALHOST; + else + { + ISC_unescape(node_name); + ISC_utf8ToSystem(node_name); + } + + port = INET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb, + cBlock.getConfig(), ref_db_name, cryptCb, inet_af); } - } + + // 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 + if (!port) + { + PathName expanded_name = attach_name; + if (ISC_analyze_pclan(expanded_name, node_name)) + { + ISC_unescape(node_name); + ISC_utf8ToSystem(node_name); + + port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb, + cBlock.getConfig(), ref_db_name, cryptCb); + } + } #endif #ifndef NO_NFS - if (!port) - { - PathName expanded_name = attach_name; - if (ISC_analyze_nfs(expanded_name, node_name)) - { - ISC_unescape(node_name); - ISC_utf8ToSystem(node_name); + if (!port) + { + 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(), flags & ANALYZE_USER_VFY, pb, - cBlock.getConfig(), ref_db_name, cryptCb); - } - } + port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb, + cBlock.getConfig(), ref_db_name, cryptCb); + } + } #endif - } + } - if ((flags & ANALYZE_LOOPBACK) && !port) - { - // We have a local connection string. - // If we are in loopback mode attempt connect to a localhost. + if ((flags & ANALYZE_LOOPBACK) && !port) + { + // We have a local connection string. + // If we are in loopback mode attempt connect to a localhost. - if (node_name.isEmpty()) - { + if (node_name.isEmpty()) + { #ifdef WIN_NT - if (!port) - { - port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY, - cBlock.getConfig(), ref_db_name); - } + if (!port) + { + port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY, + cBlock.getConfig(), ref_db_name); + } #endif - if (!port) - { - port = INET_analyze(&cBlock, attach_name, INET_LOCALHOST, flags & ANALYZE_USER_VFY, pb, - cBlock.getConfig(), ref_db_name, cryptCb); + if (!port) + { + port = INET_analyze(&cBlock, attach_name, INET_LOCALHOST, flags & ANALYZE_USER_VFY, pb, + cBlock.getConfig(), ref_db_name, cryptCb); + } + } } + + break; + } + catch (const Exception&) + { +#ifdef TRUSTED_AUTH + const char* const pluginName = cBlock.plugins.name(); + if (legacySSP || fb_utils::stricmp(pluginName, "WIN_SSPI") != 0) + throw; + + // Retry connect with failed plugin only and using legacy security package + legacySSP = true; + Auth::setLegacySSP(legacySSP); + attach_name = save_attach_name; + + cBlock.plugins.set(pluginName); +#else + throw; +#endif } }