Skip to content

Commit 29197ad

Browse files
committed
If client fails to connect using Win_SSPI plugin with Negotiate security package, try again using NTLM security package.
This allows new client connect to the old server that uses legacy NTLM security package.
1 parent dab712f commit 29197ad

File tree

3 files changed

+104
-65
lines changed

3 files changed

+104
-65
lines changed

src/auth/trusted/AuthSspi.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,15 @@ namespace
6767

6868
namespace Auth {
6969

70+
71+
static thread_local bool legacySSP = false;
72+
73+
void setLegacySSP(bool value)
74+
{
75+
legacySSP = value;
76+
}
77+
78+
7079
HINSTANCE AuthSspi::library = 0;
7180

7281
bool AuthSspi::initEntries()
@@ -109,7 +118,8 @@ AuthSspi::AuthSspi()
109118
groupNames(*getDefaultMemoryPool()), sessionKey(*getDefaultMemoryPool())
110119
{
111120
TimeStamp timeOut;
112-
hasCredentials = initEntries() && (fAcquireCredentialsHandle(0, NEGOSSP_NAME_A,
121+
hasCredentials = initEntries() && (fAcquireCredentialsHandle(0,
122+
legacySSP ? NTLMSP_NAME_A : NEGOSSP_NAME_A,
113123
SECPKG_CRED_BOTH, 0, 0, 0, 0,
114124
&secHndl, &timeOut) == SEC_E_OK);
115125
}

src/auth/trusted/AuthSspi.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,10 @@ class WinSspiClient :
145145
void registerTrustedClient(Firebird::IPluginManager* iPlugin);
146146
void registerTrustedServer(Firebird::IPluginManager* iPlugin);
147147

148+
// Set per-thread flag that specify which security package should be used by
149+
// newly created plugin instances: true - use NTLM, false - use Negotiate.
150+
void setLegacySSP(bool value);
151+
148152
} // namespace Auth
149153

150154
#endif // TRUSTED_AUTH

src/remote/client/interface.cpp

Lines changed: 89 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -7405,91 +7405,116 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned
74057405

74067406
cBlock.loadClnt(pb, &parSet);
74077407
pb.deleteWithTag(parSet.auth_block);
7408-
authenticateStep0(cBlock);
74097408

74107409
bool needFile = !(flags & ANALYZE_EMP_NAME);
7410+
const PathName save_attach_name(attach_name);
7411+
bool legacySSP = false;
7412+
Auth::setLegacySSP(legacySSP);
74117413

7414+
while (true)
7415+
{
7416+
authenticateStep0(cBlock);
7417+
7418+
try
7419+
{
74127420
#ifdef WIN_NT
7413-
if (ISC_analyze_protocol(PROTOCOL_XNET, attach_name, node_name, NULL, needFile))
7414-
port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY, cBlock.getConfig(), ref_db_name);
7415-
else
7421+
if (ISC_analyze_protocol(PROTOCOL_XNET, attach_name, node_name, NULL, needFile))
7422+
port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY, cBlock.getConfig(), ref_db_name);
7423+
else
74167424
#endif
74177425

7418-
if (ISC_analyze_protocol(PROTOCOL_INET4, attach_name, node_name, INET_SEPARATOR, needFile))
7419-
inet_af = AF_INET;
7420-
else if (ISC_analyze_protocol(PROTOCOL_INET6, attach_name, node_name, INET_SEPARATOR, needFile))
7421-
inet_af = AF_INET6;
7426+
if (ISC_analyze_protocol(PROTOCOL_INET4, attach_name, node_name, INET_SEPARATOR, needFile))
7427+
inet_af = AF_INET;
7428+
else if (ISC_analyze_protocol(PROTOCOL_INET6, attach_name, node_name, INET_SEPARATOR, needFile))
7429+
inet_af = AF_INET6;
74227430

7423-
if (inet_af != AF_UNSPEC ||
7424-
ISC_analyze_protocol(PROTOCOL_INET, attach_name, node_name, INET_SEPARATOR, needFile) ||
7425-
ISC_analyze_tcp(attach_name, node_name, needFile))
7426-
{
7427-
if (node_name.isEmpty())
7428-
node_name = INET_LOCALHOST;
7429-
else
7430-
{
7431-
ISC_unescape(node_name);
7432-
ISC_utf8ToSystem(node_name);
7433-
}
7431+
if (inet_af != AF_UNSPEC ||
7432+
ISC_analyze_protocol(PROTOCOL_INET, attach_name, node_name, INET_SEPARATOR, needFile) ||
7433+
ISC_analyze_tcp(attach_name, node_name, needFile))
7434+
{
7435+
if (node_name.isEmpty())
7436+
node_name = INET_LOCALHOST;
7437+
else
7438+
{
7439+
ISC_unescape(node_name);
7440+
ISC_utf8ToSystem(node_name);
7441+
}
74347442

7435-
port = INET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7436-
cBlock.getConfig(), ref_db_name, cryptCb, inet_af);
7437-
}
7443+
port = INET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7444+
cBlock.getConfig(), ref_db_name, cryptCb, inet_af);
7445+
}
74387446

7439-
// We have a local connection string. If it's a file on a network share,
7440-
// try to connect to the corresponding host remotely.
7441-
if (flags & ANALYZE_MOUNTS)
7442-
{
7443-
#ifdef WIN_NT
7444-
if (!port)
7445-
{
7446-
PathName expanded_name = attach_name;
7447-
if (ISC_analyze_pclan(expanded_name, node_name))
7447+
// We have a local connection string. If it's a file on a network share,
7448+
// try to connect to the corresponding host remotely.
7449+
if (flags & ANALYZE_MOUNTS)
74487450
{
7449-
ISC_unescape(node_name);
7450-
ISC_utf8ToSystem(node_name);
7451+
#ifdef WIN_NT
7452+
if (!port)
7453+
{
7454+
PathName expanded_name = attach_name;
7455+
if (ISC_analyze_pclan(expanded_name, node_name))
7456+
{
7457+
ISC_unescape(node_name);
7458+
ISC_utf8ToSystem(node_name);
74517459

7452-
port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7453-
cBlock.getConfig(), ref_db_name, cryptCb);
7454-
}
7455-
}
7460+
port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7461+
cBlock.getConfig(), ref_db_name, cryptCb);
7462+
}
7463+
}
74567464
#endif
74577465

74587466
#ifndef NO_NFS
7459-
if (!port)
7460-
{
7461-
PathName expanded_name = attach_name;
7462-
if (ISC_analyze_nfs(expanded_name, node_name))
7463-
{
7464-
ISC_unescape(node_name);
7465-
ISC_utf8ToSystem(node_name);
7467+
if (!port)
7468+
{
7469+
PathName expanded_name = attach_name;
7470+
if (ISC_analyze_nfs(expanded_name, node_name))
7471+
{
7472+
ISC_unescape(node_name);
7473+
ISC_utf8ToSystem(node_name);
74667474

7467-
port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7468-
cBlock.getConfig(), ref_db_name, cryptCb);
7469-
}
7470-
}
7475+
port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7476+
cBlock.getConfig(), ref_db_name, cryptCb);
7477+
}
7478+
}
74717479
#endif
7472-
}
7480+
}
74737481

7474-
if ((flags & ANALYZE_LOOPBACK) && !port)
7475-
{
7476-
// We have a local connection string.
7477-
// If we are in loopback mode attempt connect to a localhost.
7482+
if ((flags & ANALYZE_LOOPBACK) && !port)
7483+
{
7484+
// We have a local connection string.
7485+
// If we are in loopback mode attempt connect to a localhost.
74787486

7479-
if (node_name.isEmpty())
7480-
{
7487+
if (node_name.isEmpty())
7488+
{
74817489
#ifdef WIN_NT
7482-
if (!port)
7483-
{
7484-
port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY,
7485-
cBlock.getConfig(), ref_db_name);
7486-
}
7490+
if (!port)
7491+
{
7492+
port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY,
7493+
cBlock.getConfig(), ref_db_name);
7494+
}
74877495
#endif
7488-
if (!port)
7489-
{
7490-
port = INET_analyze(&cBlock, attach_name, INET_LOCALHOST, flags & ANALYZE_USER_VFY, pb,
7491-
cBlock.getConfig(), ref_db_name, cryptCb);
7496+
if (!port)
7497+
{
7498+
port = INET_analyze(&cBlock, attach_name, INET_LOCALHOST, flags & ANALYZE_USER_VFY, pb,
7499+
cBlock.getConfig(), ref_db_name, cryptCb);
7500+
}
7501+
}
74927502
}
7503+
7504+
break;
7505+
}
7506+
catch (const Exception&)
7507+
{
7508+
const char* const pluginName = cBlock.plugins.name();
7509+
if (legacySSP || fb_utils::stricmp(pluginName, "WIN_SSPI") != 0)
7510+
throw;
7511+
7512+
// Retry connect with failed plugin only and using legacy security package
7513+
legacySSP = true;
7514+
Auth::setLegacySSP(legacySSP);
7515+
attach_name = save_attach_name;
7516+
7517+
cBlock.plugins.set(pluginName);
74937518
}
74947519
}
74957520

0 commit comments

Comments
 (0)