Skip to content

Commit 14c68c0

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 d2c334c commit 14c68c0

File tree

3 files changed

+129
-83
lines changed

3 files changed

+129
-83
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: 114 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -7167,113 +7167,145 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned
71677167

71687168
cBlock.loadClnt(pb, &parSet);
71697169
pb.deleteWithTag(parSet.auth_block);
7170-
authenticateStep0(cBlock);
71717170

71727171
bool needFile = !(flags & ANALYZE_EMP_NAME);
7172+
const PathName save_attach_name(attach_name);
71737173

7174-
#ifdef WIN_NT
7175-
if (ISC_analyze_protocol(PROTOCOL_XNET, attach_name, node_name, NULL, needFile))
7176-
port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY, cBlock.getConfig(), ref_db_name);
7177-
else if (ISC_analyze_protocol(PROTOCOL_WNET, attach_name, node_name, WNET_SEPARATOR, needFile) ||
7178-
ISC_analyze_pclan(attach_name, node_name))
7179-
{
7180-
if (node_name.isEmpty())
7181-
node_name = WNET_LOCALHOST;
7182-
else
7183-
{
7184-
ISC_unescape(node_name);
7185-
ISC_utf8ToSystem(node_name);
7186-
}
7187-
7188-
port = WNET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_USER_VFY,
7189-
cBlock.getConfig(), ref_db_name);
7190-
}
7191-
else
7174+
#ifdef TRUSTED_AUTH
7175+
bool legacySSP = false;
7176+
Auth::setLegacySSP(legacySSP);
71927177
#endif
71937178

7194-
if (ISC_analyze_protocol(PROTOCOL_INET4, attach_name, node_name, INET_SEPARATOR, needFile))
7195-
inet_af = AF_INET;
7196-
else if (ISC_analyze_protocol(PROTOCOL_INET6, attach_name, node_name, INET_SEPARATOR, needFile))
7197-
inet_af = AF_INET6;
7198-
7199-
if (inet_af != AF_UNSPEC ||
7200-
ISC_analyze_protocol(PROTOCOL_INET, attach_name, node_name, INET_SEPARATOR, needFile) ||
7201-
ISC_analyze_tcp(attach_name, node_name, needFile))
7179+
while (true)
72027180
{
7203-
if (node_name.isEmpty())
7204-
node_name = INET_LOCALHOST;
7205-
else
7206-
{
7207-
ISC_unescape(node_name);
7208-
ISC_utf8ToSystem(node_name);
7209-
}
7210-
7211-
port = INET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7212-
cBlock.getConfig(), ref_db_name, cryptCb, inet_af);
7213-
}
7181+
authenticateStep0(cBlock);
72147182

7215-
// We have a local connection string. If it's a file on a network share,
7216-
// try to connect to the corresponding host remotely.
7217-
if (flags & ANALYZE_MOUNTS)
7218-
{
7219-
#ifdef WIN_NT
7220-
if (!port)
7183+
try
72217184
{
7222-
PathName expanded_name = attach_name;
7223-
ISC_expand_share(expanded_name);
7224-
7225-
if (ISC_analyze_pclan(expanded_name, node_name))
7185+
#ifdef WIN_NT
7186+
if (ISC_analyze_protocol(PROTOCOL_XNET, attach_name, node_name, NULL, needFile))
7187+
port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY, cBlock.getConfig(), ref_db_name);
7188+
else if (ISC_analyze_protocol(PROTOCOL_WNET, attach_name, node_name, WNET_SEPARATOR, needFile) ||
7189+
ISC_analyze_pclan(attach_name, node_name))
72267190
{
7227-
ISC_unescape(node_name);
7228-
ISC_utf8ToSystem(node_name);
7191+
if (node_name.isEmpty())
7192+
node_name = WNET_LOCALHOST;
7193+
else
7194+
{
7195+
ISC_unescape(node_name);
7196+
ISC_utf8ToSystem(node_name);
7197+
}
72297198

7230-
port = WNET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY,
7199+
port = WNET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_USER_VFY,
72317200
cBlock.getConfig(), ref_db_name);
72327201
}
7233-
}
7202+
else
72347203
#endif
72357204

7236-
#ifndef NO_NFS
7237-
if (!port)
7238-
{
7239-
PathName expanded_name = attach_name;
7240-
if (ISC_analyze_nfs(expanded_name, node_name))
7205+
if (ISC_analyze_protocol(PROTOCOL_INET4, attach_name, node_name, INET_SEPARATOR, needFile))
7206+
inet_af = AF_INET;
7207+
else if (ISC_analyze_protocol(PROTOCOL_INET6, attach_name, node_name, INET_SEPARATOR, needFile))
7208+
inet_af = AF_INET6;
7209+
7210+
if (inet_af != AF_UNSPEC ||
7211+
ISC_analyze_protocol(PROTOCOL_INET, attach_name, node_name, INET_SEPARATOR, needFile) ||
7212+
ISC_analyze_tcp(attach_name, node_name, needFile))
72417213
{
7242-
ISC_unescape(node_name);
7243-
ISC_utf8ToSystem(node_name);
7214+
if (node_name.isEmpty())
7215+
node_name = INET_LOCALHOST;
7216+
else
7217+
{
7218+
ISC_unescape(node_name);
7219+
ISC_utf8ToSystem(node_name);
7220+
}
72447221

7245-
port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7246-
cBlock.getConfig(), ref_db_name, cryptCb);
7222+
port = INET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7223+
cBlock.getConfig(), ref_db_name, cryptCb, inet_af);
72477224
}
7248-
}
7225+
7226+
// We have a local connection string. If it's a file on a network share,
7227+
// try to connect to the corresponding host remotely.
7228+
if (flags & ANALYZE_MOUNTS)
7229+
{
7230+
#ifdef WIN_NT
7231+
if (!port)
7232+
{
7233+
PathName expanded_name = attach_name;
7234+
ISC_expand_share(expanded_name);
7235+
7236+
if (ISC_analyze_pclan(expanded_name, node_name))
7237+
{
7238+
ISC_unescape(node_name);
7239+
ISC_utf8ToSystem(node_name);
7240+
7241+
port = WNET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY,
7242+
cBlock.getConfig(), ref_db_name);
7243+
}
7244+
}
72497245
#endif
7250-
}
72517246

7252-
if ((flags & ANALYZE_LOOPBACK) && !port)
7253-
{
7254-
// We have a local connection string.
7255-
// If we are in loopback mode attempt connect to a localhost.
7247+
#ifndef NO_NFS
7248+
if (!port)
7249+
{
7250+
PathName expanded_name = attach_name;
7251+
if (ISC_analyze_nfs(expanded_name, node_name))
7252+
{
7253+
ISC_unescape(node_name);
7254+
ISC_utf8ToSystem(node_name);
72567255

7257-
if (node_name.isEmpty())
7258-
{
7259-
#ifdef WIN_NT
7260-
if (!port)
7261-
{
7262-
port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY,
7263-
cBlock.getConfig(), ref_db_name);
7256+
port = INET_analyze(&cBlock, expanded_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
7257+
cBlock.getConfig(), ref_db_name, cryptCb);
7258+
}
7259+
}
7260+
#endif
72647261
}
72657262

7266-
if (!port)
7263+
if ((flags & ANALYZE_LOOPBACK) && !port)
72677264
{
7268-
port = WNET_analyze(&cBlock, attach_name, WNET_LOCALHOST, flags & ANALYZE_USER_VFY,
7269-
cBlock.getConfig(), ref_db_name);
7270-
}
7265+
// We have a local connection string.
7266+
// If we are in loopback mode attempt connect to a localhost.
7267+
7268+
if (node_name.isEmpty())
7269+
{
7270+
#ifdef WIN_NT
7271+
if (!port)
7272+
{
7273+
port = XNET_analyze(&cBlock, attach_name, flags & ANALYZE_USER_VFY,
7274+
cBlock.getConfig(), ref_db_name);
7275+
}
7276+
7277+
if (!port)
7278+
{
7279+
port = WNET_analyze(&cBlock, attach_name, WNET_LOCALHOST, flags & ANALYZE_USER_VFY,
7280+
cBlock.getConfig(), ref_db_name);
7281+
}
72717282
#endif
7272-
if (!port)
7273-
{
7274-
port = INET_analyze(&cBlock, attach_name, INET_LOCALHOST, flags & ANALYZE_USER_VFY, pb,
7275-
cBlock.getConfig(), ref_db_name, cryptCb);
7283+
if (!port)
7284+
{
7285+
port = INET_analyze(&cBlock, attach_name, INET_LOCALHOST, flags & ANALYZE_USER_VFY, pb,
7286+
cBlock.getConfig(), ref_db_name, cryptCb);
7287+
}
7288+
}
72767289
}
7290+
7291+
break;
7292+
}
7293+
catch (const Exception&)
7294+
{
7295+
#ifdef TRUSTED_AUTH
7296+
const char* const pluginName = cBlock.plugins.name();
7297+
if (legacySSP || fb_utils::stricmp(pluginName, "WIN_SSPI") != 0)
7298+
throw;
7299+
7300+
// Retry connect with failed plugin only and using legacy security package
7301+
legacySSP = true;
7302+
Auth::setLegacySSP(legacySSP);
7303+
attach_name = save_attach_name;
7304+
7305+
cBlock.plugins.set(pluginName);
7306+
#else
7307+
throw;
7308+
#endif
72777309
}
72787310
}
72797311

0 commit comments

Comments
 (0)