Skip to content

Commit f62f133

Browse files
authored
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.
2 parents 36b035c + 3092eee commit f62f133

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
@@ -7405,91 +7405,123 @@ 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);
74117411

7412-
#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
7412+
#ifdef TRUSTED_AUTH
7413+
bool legacySSP = false;
7414+
Auth::setLegacySSP(legacySSP);
74167415
#endif
74177416

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;
7422-
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))
7417+
while (true)
74267418
{
7427-
if (node_name.isEmpty())
7428-
node_name = INET_LOCALHOST;
7429-
else
7419+
authenticateStep0(cBlock);
7420+
7421+
try
74307422
{
7431-
ISC_unescape(node_name);
7432-
ISC_utf8ToSystem(node_name);
7433-
}
7423+
#ifdef WIN_NT
7424+
if (ISC_analyze_protocol(PROTOCOL_XNET, attach_name, node_name, NULL, needFile))
7425+
port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY, cBlock.getConfig(), ref_db_name);
7426+
else
7427+
#endif
74347428

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-
}
7429+
if (ISC_analyze_protocol(PROTOCOL_INET4, attach_name, node_name, INET_SEPARATOR, needFile))
7430+
inet_af = AF_INET;
7431+
else if (ISC_analyze_protocol(PROTOCOL_INET6, attach_name, node_name, INET_SEPARATOR, needFile))
7432+
inet_af = AF_INET6;
74387433

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))
7434+
if (inet_af != AF_UNSPEC ||
7435+
ISC_analyze_protocol(PROTOCOL_INET, attach_name, node_name, INET_SEPARATOR, needFile) ||
7436+
ISC_analyze_tcp(attach_name, node_name, needFile))
74487437
{
7449-
ISC_unescape(node_name);
7450-
ISC_utf8ToSystem(node_name);
7438+
if (node_name.isEmpty())
7439+
node_name = INET_LOCALHOST;
7440+
else
7441+
{
7442+
ISC_unescape(node_name);
7443+
ISC_utf8ToSystem(node_name);
7444+
}
74517445

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

74587469
#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);
7470+
if (!port)
7471+
{
7472+
PathName expanded_name = attach_name;
7473+
if (ISC_analyze_nfs(expanded_name, node_name))
7474+
{
7475+
ISC_unescape(node_name);
7476+
ISC_utf8ToSystem(node_name);
74667477

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-
}
7478+
port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7479+
cBlock.getConfig(), ref_db_name, cryptCb);
7480+
}
7481+
}
74717482
#endif
7472-
}
7483+
}
74737484

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.
7485+
if ((flags & ANALYZE_LOOPBACK) && !port)
7486+
{
7487+
// We have a local connection string.
7488+
// If we are in loopback mode attempt connect to a localhost.
74787489

7479-
if (node_name.isEmpty())
7480-
{
7490+
if (node_name.isEmpty())
7491+
{
74817492
#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-
}
7493+
if (!port)
7494+
{
7495+
port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY,
7496+
cBlock.getConfig(), ref_db_name);
7497+
}
74877498
#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);
7499+
if (!port)
7500+
{
7501+
port = INET_analyze(&cBlock, attach_name, INET_LOCALHOST, flags & ANALYZE_USER_VFY, pb,
7502+
cBlock.getConfig(), ref_db_name, cryptCb);
7503+
}
7504+
}
74927505
}
7506+
7507+
break;
7508+
}
7509+
catch (const Exception&)
7510+
{
7511+
#ifdef TRUSTED_AUTH
7512+
const char* const pluginName = cBlock.plugins.name();
7513+
if (legacySSP || fb_utils::stricmp(pluginName, "WIN_SSPI") != 0)
7514+
throw;
7515+
7516+
// Retry connect with failed plugin only and using legacy security package
7517+
legacySSP = true;
7518+
Auth::setLegacySSP(legacySSP);
7519+
attach_name = save_attach_name;
7520+
7521+
cBlock.plugins.set(pluginName);
7522+
#else
7523+
throw;
7524+
#endif
74937525
}
74947526
}
74957527

0 commit comments

Comments
 (0)