Skip to content

Commit d1502b5

Browse files
committed
Merge pull request #8274 from FirebirdSQL/work/win_sspi_reconnect
If client fails to connect using Win_SSPI plugin with Negotiate security package, try again using NTLM security package.
1 parent 4e3508a commit d1502b5

File tree

3 files changed

+110
-64
lines changed

3 files changed

+110
-64
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: 95 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -7404,91 +7404,123 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned
74047404

74057405
cBlock.loadClnt(pb, &parSet);
74067406
pb.deleteWithTag(parSet.auth_block);
7407-
authenticateStep0(cBlock);
74087407

74097408
bool needFile = !(flags & ANALYZE_EMP_NAME);
7409+
const PathName save_attach_name(attach_name);
74107410

7411-
#ifdef WIN_NT
7412-
if (ISC_analyze_protocol(PROTOCOL_XNET, attach_name, node_name, NULL, needFile))
7413-
port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY, cBlock.getConfig(), ref_db_name);
7414-
else
7411+
#ifdef TRUSTED_AUTH
7412+
bool legacySSP = false;
7413+
Auth::setLegacySSP(legacySSP);
74157414
#endif
74167415

7417-
if (ISC_analyze_protocol(PROTOCOL_INET4, attach_name, node_name, INET_SEPARATOR, needFile))
7418-
inet_af = AF_INET;
7419-
else if (ISC_analyze_protocol(PROTOCOL_INET6, attach_name, node_name, INET_SEPARATOR, needFile))
7420-
inet_af = AF_INET6;
7421-
7422-
if (inet_af != AF_UNSPEC ||
7423-
ISC_analyze_protocol(PROTOCOL_INET, attach_name, node_name, INET_SEPARATOR, needFile) ||
7424-
ISC_analyze_tcp(attach_name, node_name, needFile))
7416+
while (true)
74257417
{
7426-
if (node_name.isEmpty())
7427-
node_name = INET_LOCALHOST;
7428-
else
7418+
authenticateStep0(cBlock);
7419+
7420+
try
74297421
{
7430-
ISC_unescape(node_name);
7431-
ISC_utf8ToSystem(node_name);
7432-
}
7422+
#ifdef WIN_NT
7423+
if (ISC_analyze_protocol(PROTOCOL_XNET, attach_name, node_name, NULL, needFile))
7424+
port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY, cBlock.getConfig(), ref_db_name);
7425+
else
7426+
#endif
74337427

7434-
port = INET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7435-
cBlock.getConfig(), ref_db_name, cryptCb, inet_af);
7436-
}
7428+
if (ISC_analyze_protocol(PROTOCOL_INET4, attach_name, node_name, INET_SEPARATOR, needFile))
7429+
inet_af = AF_INET;
7430+
else if (ISC_analyze_protocol(PROTOCOL_INET6, attach_name, node_name, INET_SEPARATOR, needFile))
7431+
inet_af = AF_INET6;
74377432

7438-
// We have a local connection string. If it's a file on a network share,
7439-
// try to connect to the corresponding host remotely.
7440-
if (flags & ANALYZE_MOUNTS)
7441-
{
7442-
#ifdef WIN_NT
7443-
if (!port)
7444-
{
7445-
PathName expanded_name = attach_name;
7446-
if (ISC_analyze_pclan(expanded_name, node_name))
7433+
if (inet_af != AF_UNSPEC ||
7434+
ISC_analyze_protocol(PROTOCOL_INET, attach_name, node_name, INET_SEPARATOR, needFile) ||
7435+
ISC_analyze_tcp(attach_name, node_name, needFile))
74477436
{
7448-
ISC_unescape(node_name);
7449-
ISC_utf8ToSystem(node_name);
7437+
if (node_name.isEmpty())
7438+
node_name = INET_LOCALHOST;
7439+
else
7440+
{
7441+
ISC_unescape(node_name);
7442+
ISC_utf8ToSystem(node_name);
7443+
}
74507444

7451-
port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7452-
cBlock.getConfig(), ref_db_name, cryptCb);
7445+
port = INET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7446+
cBlock.getConfig(), ref_db_name, cryptCb, inet_af);
74537447
}
7454-
}
7448+
7449+
// We have a local connection string. If it's a file on a network share,
7450+
// try to connect to the corresponding host remotely.
7451+
if (flags & ANALYZE_MOUNTS)
7452+
{
7453+
#ifdef WIN_NT
7454+
if (!port)
7455+
{
7456+
PathName expanded_name = attach_name;
7457+
if (ISC_analyze_pclan(expanded_name, node_name))
7458+
{
7459+
ISC_unescape(node_name);
7460+
ISC_utf8ToSystem(node_name);
7461+
7462+
port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7463+
cBlock.getConfig(), ref_db_name, cryptCb);
7464+
}
7465+
}
74557466
#endif
74567467

74577468
#ifndef NO_NFS
7458-
if (!port)
7459-
{
7460-
PathName expanded_name = attach_name;
7461-
if (ISC_analyze_nfs(expanded_name, node_name))
7462-
{
7463-
ISC_unescape(node_name);
7464-
ISC_utf8ToSystem(node_name);
7469+
if (!port)
7470+
{
7471+
PathName expanded_name = attach_name;
7472+
if (ISC_analyze_nfs(expanded_name, node_name))
7473+
{
7474+
ISC_unescape(node_name);
7475+
ISC_utf8ToSystem(node_name);
74657476

7466-
port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7467-
cBlock.getConfig(), ref_db_name, cryptCb);
7468-
}
7469-
}
7477+
port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7478+
cBlock.getConfig(), ref_db_name, cryptCb);
7479+
}
7480+
}
74707481
#endif
7471-
}
7482+
}
74727483

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

7478-
if (node_name.isEmpty())
7479-
{
7489+
if (node_name.isEmpty())
7490+
{
74807491
#ifdef WIN_NT
7481-
if (!port)
7482-
{
7483-
port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY,
7484-
cBlock.getConfig(), ref_db_name);
7485-
}
7492+
if (!port)
7493+
{
7494+
port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY,
7495+
cBlock.getConfig(), ref_db_name);
7496+
}
74867497
#endif
7487-
if (!port)
7488-
{
7489-
port = INET_analyze(&cBlock, attach_name, INET_LOCALHOST, flags & ANALYZE_USER_VFY, pb,
7490-
cBlock.getConfig(), ref_db_name, cryptCb);
7498+
if (!port)
7499+
{
7500+
port = INET_analyze(&cBlock, attach_name, INET_LOCALHOST, flags & ANALYZE_USER_VFY, pb,
7501+
cBlock.getConfig(), ref_db_name, cryptCb);
7502+
}
7503+
}
74917504
}
7505+
7506+
break;
7507+
}
7508+
catch (const Exception&)
7509+
{
7510+
#ifdef TRUSTED_AUTH
7511+
const char* const pluginName = cBlock.plugins.name();
7512+
if (legacySSP || fb_utils::stricmp(pluginName, "WIN_SSPI") != 0)
7513+
throw;
7514+
7515+
// Retry connect with failed plugin only and using legacy security package
7516+
legacySSP = true;
7517+
Auth::setLegacySSP(legacySSP);
7518+
attach_name = save_attach_name;
7519+
7520+
cBlock.plugins.set(pluginName);
7521+
#else
7522+
throw;
7523+
#endif
74927524
}
74937525
}
74947526

0 commit comments

Comments
 (0)