From eb24eafea6eb3cd38d81d53fa5e59b01b835e298 Mon Sep 17 00:00:00 2001 From: Tal Aloni Date: Wed, 24 May 2017 18:37:41 +0300 Subject: [PATCH] GSSAPI: Cases where the preferred authentication mechanism is not supported were not handled correctly --- .../Authentication/GSSAPI/GSSProvider.cs | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/SMBLibrary/Authentication/GSSAPI/GSSProvider.cs b/SMBLibrary/Authentication/GSSAPI/GSSProvider.cs index 50c7ddf..518048f 100644 --- a/SMBLibrary/Authentication/GSSAPI/GSSProvider.cs +++ b/SMBLibrary/Authentication/GSSAPI/GSSProvider.cs @@ -49,12 +49,35 @@ namespace SMBLibrary.Authentication.GSSAPI if (spnegoToken is SimpleProtectedNegotiationTokenInit) { SimpleProtectedNegotiationTokenInit tokenInit = (SimpleProtectedNegotiationTokenInit)spnegoToken; - IGSSMechanism mechanism = FindMechanism(tokenInit.MechanismTypeList); + if (tokenInit.MechanismTypeList.Count == 0) + { + return NTStatus.SEC_E_INVALID_TOKEN; + } + + // RFC 4178: Note that in order to avoid an extra round trip, the first context establishment token + // of the initiator's preferred mechanism SHOULD be embedded in the initial negotiation message. + byte[] preferredMechanism = tokenInit.MechanismTypeList[0]; + IGSSMechanism mechanism = FindMechanism(preferredMechanism); + bool isPreferredMechanism = (mechanism != null); + if (!isPreferredMechanism) + { + mechanism = FindMechanism(tokenInit.MechanismTypeList); + } + if (mechanism != null) { - byte[] mechanismOutput; - NTStatus status = mechanism.AcceptSecurityContext(ref context, tokenInit.MechanismToken, out mechanismOutput); - outputToken = GetSPNEGOTokenResponseBytes(mechanismOutput, status, mechanism.Identifier); + NTStatus status; + if (isPreferredMechanism) + { + byte[] mechanismOutput; + status = mechanism.AcceptSecurityContext(ref context, tokenInit.MechanismToken, out mechanismOutput); + outputToken = GetSPNEGOTokenResponseBytes(mechanismOutput, status, mechanism.Identifier); + } + else + { + status = NTStatus.SEC_I_CONTINUE_NEEDED; + outputToken = GetSPNEGOTokenResponseBytes(null, status, mechanism.Identifier); + } m_contextToMechanism[context] = mechanism; return status; }