diff --git a/src/auth/trusted/AuthSspi.cpp b/src/auth/trusted/AuthSspi.cpp index f72c349235..1af4f72762 100644 --- a/src/auth/trusted/AuthSspi.cpp +++ b/src/auth/trusted/AuthSspi.cpp @@ -367,7 +367,8 @@ bool AuthSspi::getLogin(string& login, bool& wh, GroupsList& grNames) WinSspiServer::WinSspiServer(Firebird::IPluginConfig*) - : sspiData(getPool()) + : sspiData(getPool()), + done(false) { } int WinSspiServer::authenticate(Firebird::CheckStatusWrapper* status, @@ -376,17 +377,18 @@ int WinSspiServer::authenticate(Firebird::CheckStatusWrapper* status, { try { - const bool wasActive = sspi.isActive(); - sspiData.clear(); unsigned int length; const unsigned char* bytes = sBlock->getData(&length); sspiData.add(bytes, length); + if (done && !length && !sspi.isActive()) + return AUTH_SUCCESS; + if (!sspi.accept(sspiData)) return AUTH_CONTINUE; - if (wasActive && !sspi.isActive()) + if (!sspi.isActive()) { bool wheel = false; string login; @@ -445,7 +447,9 @@ int WinSspiServer::authenticate(Firebird::CheckStatusWrapper* status, return AUTH_FAILED; } - return AUTH_SUCCESS; + done = true; + if (sspiData.isEmpty()) + return AUTH_SUCCESS; } sBlock->putData(status, sspiData.getCount(), sspiData.begin()); @@ -456,7 +460,7 @@ int WinSspiServer::authenticate(Firebird::CheckStatusWrapper* status, return AUTH_FAILED; } - return AUTH_MORE_DATA; + return done ? AUTH_SUCCESS_WITH_DATA : AUTH_MORE_DATA; } diff --git a/src/auth/trusted/AuthSspi.h b/src/auth/trusted/AuthSspi.h index 9e3f254b5f..92030bbb12 100644 --- a/src/auth/trusted/AuthSspi.h +++ b/src/auth/trusted/AuthSspi.h @@ -124,6 +124,7 @@ public: private: AuthSspi::DataHolder sspiData; AuthSspi sspi; + bool done; }; class WinSspiClient : diff --git a/src/include/firebird/FirebirdInterface.idl b/src/include/firebird/FirebirdInterface.idl index c0e1173854..8a0a1ad2c1 100644 --- a/src/include/firebird/FirebirdInterface.idl +++ b/src/include/firebird/FirebirdInterface.idl @@ -769,6 +769,7 @@ interface Auth : PluginBase const int AUTH_SUCCESS = 0; const int AUTH_MORE_DATA = 1; const int AUTH_CONTINUE = 2; + const int AUTH_SUCCESS_WITH_DATA = 3; } interface Writer : Versioned diff --git a/src/include/firebird/IdlFbInterfaces.h b/src/include/firebird/IdlFbInterfaces.h index 4b3ce64041..11e294944e 100644 --- a/src/include/firebird/IdlFbInterfaces.h +++ b/src/include/firebird/IdlFbInterfaces.h @@ -3063,6 +3063,7 @@ namespace Firebird static CLOOP_CONSTEXPR int AUTH_SUCCESS = 0; static CLOOP_CONSTEXPR int AUTH_MORE_DATA = 1; static CLOOP_CONSTEXPR int AUTH_CONTINUE = 2; + static CLOOP_CONSTEXPR int AUTH_SUCCESS_WITH_DATA = 3; }; #define FIREBIRD_IWRITER_VERSION 2u diff --git a/src/include/gen/Firebird.pas b/src/include/gen/Firebird.pas index cfc85eec32..ccca8f1943 100644 --- a/src/include/gen/Firebird.pas +++ b/src/include/gen/Firebird.pas @@ -1971,6 +1971,7 @@ type const AUTH_SUCCESS = Integer(0); const AUTH_MORE_DATA = Integer(1); const AUTH_CONTINUE = Integer(2); + const AUTH_SUCCESS_WITH_DATA = Integer(3); end; diff --git a/src/remote/server/server.cpp b/src/remote/server/server.cpp index 668bf50a93..fe48fed63c 100644 --- a/src/remote/server/server.cpp +++ b/src/remote/server/server.cpp @@ -657,7 +657,10 @@ public: } // if we asked for more data but received nothing switch to next plugin - const bool forceNext = (flags & AUTH_CONTINUE) && (!authPort->port_srv_auth_block->hasDataForPlugin()); + const bool forceNext = (flags & AUTH_CONTINUE) && + (!authPort->port_srv_auth_block->hasDataForPlugin()) && + (!authPort->port_srv_auth_block->authCompleted()); + HANDSHAKE_DEBUG(fprintf(stderr, "Srv: authenticate: ServerAuth calls plug %s\n", forceNext ? "forced-NEXT" : authItr->name())); int authResult = forceNext ? IAuth::AUTH_CONTINUE : @@ -686,6 +689,11 @@ public: authServer = NULL; continue; + case IAuth::AUTH_SUCCESS_WITH_DATA: + HANDSHAKE_DEBUG(fprintf(stderr, "Srv: authenticate: success with data\n")); + fb_assert(!authPort->port_srv_auth_block->authCompleted()); + // fall thru + case IAuth::AUTH_MORE_DATA: HANDSHAKE_DEBUG(fprintf(stderr, "Srv: authenticate: plugin wants more data\n")); if (authPort->port_protocol < PROTOCOL_VERSION11) @@ -739,6 +747,13 @@ public: if (send->p_acpt.p_acpt_type & pflag_compress) authPort->port_flags |= PORT_compressed; memset(&send->p_auth_cont, 0, sizeof send->p_auth_cont); + + if (authResult == IAuth::AUTH_SUCCESS_WITH_DATA) + { + authPort->port_srv_auth_block->authCompleted(true); + HANDSHAKE_DEBUG(fprintf(stderr, "Srv: authenticate: success with data, completed\n")); + } + return false; case IAuth::AUTH_FAILED: