NTLM: Bugfix: IndependentNTLMAuthenticationProvider login failed to to modification of message byte arrays

This commit is contained in:
TalAloni 2021-01-23 16:22:16 +02:00
parent ad4c5d1fc6
commit cf12bb722b
3 changed files with 47 additions and 38 deletions

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved. /* Copyright (C) 2014-2020 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
* *
* You can redistribute this program and/or modify it under the terms of * You can redistribute this program and/or modify it under the terms of
* the GNU Lesser Public License as published by the Free Software Foundation, * the GNU Lesser Public License as published by the Free Software Foundation,
@ -33,11 +33,9 @@ namespace SMBLibrary.Win32.Security
} }
} }
public override NTStatus GetChallengeMessage(out object context, NegotiateMessage negotiateMessage, out ChallengeMessage challengeMessage) public override NTStatus GetChallengeMessage(out object context, byte[] negotiateMessageBytes, out byte[] challengeMessageBytes)
{ {
byte[] negotiateMessageBytes = negotiateMessage.GetBytes();
SecHandle serverContext; SecHandle serverContext;
byte[] challengeMessageBytes;
try try
{ {
challengeMessageBytes = SSPIHelper.GetType2Message(negotiateMessageBytes, out serverContext); challengeMessageBytes = SSPIHelper.GetType2Message(negotiateMessageBytes, out serverContext);
@ -45,13 +43,12 @@ namespace SMBLibrary.Win32.Security
catch (Exception) catch (Exception)
{ {
context = null; context = null;
challengeMessage = null; challengeMessageBytes = null;
// We assume that the problem is not with our implementation. // We assume that the problem is not with our implementation.
return NTStatus.SEC_E_INVALID_TOKEN; return NTStatus.SEC_E_INVALID_TOKEN;
} }
context = new AuthContext(serverContext); context = new AuthContext(serverContext);
challengeMessage = new ChallengeMessage(challengeMessageBytes);
return NTStatus.SEC_I_CONTINUE_NEEDED; return NTStatus.SEC_I_CONTINUE_NEEDED;
} }
@ -60,8 +57,18 @@ namespace SMBLibrary.Win32.Security
/// 1. The correct password is blank and 'limitblankpassworduse' is set to 1. /// 1. The correct password is blank and 'limitblankpassworduse' is set to 1.
/// 2. The user is listed in the "Deny access to this computer from the network" list. /// 2. The user is listed in the "Deny access to this computer from the network" list.
/// </summary> /// </summary>
public override NTStatus Authenticate(object context, AuthenticateMessage message) public override NTStatus Authenticate(object context, byte[] authenticateMessageBytes)
{ {
AuthenticateMessage message;
try
{
message = new AuthenticateMessage(authenticateMessageBytes);
}
catch(Exception)
{
return NTStatus.SEC_E_INVALID_TOKEN;
}
AuthContext authContext = context as AuthContext; AuthContext authContext = context as AuthContext;
if (authContext == null) if (authContext == null)
{ {
@ -95,11 +102,10 @@ namespace SMBLibrary.Win32.Security
} }
} }
byte[] messageBytes = message.GetBytes();
bool success; bool success;
try try
{ {
success = SSPIHelper.AuthenticateType3Message(authContext.ServerContext, messageBytes); success = SSPIHelper.AuthenticateType3Message(authContext.ServerContext, authenticateMessageBytes);
} }
catch (Exception) catch (Exception)
{ {

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved. /* Copyright (C) 2014-2020 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
* *
* You can redistribute this program and/or modify it under the terms of * You can redistribute this program and/or modify it under the terms of
* the GNU Lesser Public License as published by the Free Software Foundation, * the GNU Lesser Public License as published by the Free Software Foundation,
@ -61,12 +61,24 @@ namespace SMBLibrary.Authentication.NTLM
m_loginCounter = new LoginCounter(maxLoginAttemptsInWindow, loginWindowDuration); m_loginCounter = new LoginCounter(maxLoginAttemptsInWindow, loginWindowDuration);
} }
public override NTStatus GetChallengeMessage(out object context, NegotiateMessage negotiateMessage, out ChallengeMessage challengeMessage) public override NTStatus GetChallengeMessage(out object context, byte[] negotiateMessageBytes, out byte[] challengeMessageBytes)
{ {
NegotiateMessage negotiateMessage;
try
{
negotiateMessage = new NegotiateMessage(negotiateMessageBytes);
}
catch
{
context = null;
challengeMessageBytes = null;
return NTStatus.SEC_E_INVALID_TOKEN;
}
byte[] serverChallenge = GenerateServerChallenge(); byte[] serverChallenge = GenerateServerChallenge();
context = new AuthContext(serverChallenge); context = new AuthContext(serverChallenge);
challengeMessage = new ChallengeMessage(); ChallengeMessage challengeMessage = new ChallengeMessage();
// https://msdn.microsoft.com/en-us/library/cc236691.aspx // https://msdn.microsoft.com/en-us/library/cc236691.aspx
challengeMessage.NegotiateFlags = NegotiateFlags.TargetTypeServer | challengeMessage.NegotiateFlags = NegotiateFlags.TargetTypeServer |
NegotiateFlags.TargetInfo | NegotiateFlags.TargetInfo |
@ -135,11 +147,22 @@ namespace SMBLibrary.Authentication.NTLM
challengeMessage.ServerChallenge = serverChallenge; challengeMessage.ServerChallenge = serverChallenge;
challengeMessage.TargetInfo = AVPairUtils.GetAVPairSequence(Environment.MachineName, Environment.MachineName); challengeMessage.TargetInfo = AVPairUtils.GetAVPairSequence(Environment.MachineName, Environment.MachineName);
challengeMessage.Version = NTLMVersion.Server2003; challengeMessage.Version = NTLMVersion.Server2003;
challengeMessageBytes = challengeMessage.GetBytes();
return NTStatus.SEC_I_CONTINUE_NEEDED; return NTStatus.SEC_I_CONTINUE_NEEDED;
} }
public override NTStatus Authenticate(object context, AuthenticateMessage message) public override NTStatus Authenticate(object context, byte[] authenticateMessageBytes)
{ {
AuthenticateMessage message;
try
{
message = new AuthenticateMessage(authenticateMessageBytes);
}
catch
{
return NTStatus.SEC_E_INVALID_TOKEN;
}
AuthContext authContext = context as AuthContext; AuthContext authContext = context as AuthContext;
if (authContext == null) if (authContext == null)
{ {

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved. /* Copyright (C) 2014-2020 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
* *
* You can redistribute this program and/or modify it under the terms of * You can redistribute this program and/or modify it under the terms of
* the GNU Lesser Public License as published by the Free Software Foundation, * the GNU Lesser Public License as published by the Free Software Foundation,
@ -25,32 +25,12 @@ namespace SMBLibrary.Authentication.NTLM
MessageTypeName messageType = AuthenticationMessageUtils.GetMessageType(inputToken); MessageTypeName messageType = AuthenticationMessageUtils.GetMessageType(inputToken);
if (messageType == MessageTypeName.Negotiate) if (messageType == MessageTypeName.Negotiate)
{ {
NegotiateMessage negotiateMessage; NTStatus status = GetChallengeMessage(out context, inputToken, out outputToken);
try
{
negotiateMessage = new NegotiateMessage(inputToken);
}
catch
{
return NTStatus.SEC_E_INVALID_TOKEN;
}
ChallengeMessage challengeMessage;
NTStatus status = GetChallengeMessage(out context, negotiateMessage, out challengeMessage);
outputToken = challengeMessage.GetBytes();
return status; return status;
} }
else if (messageType == MessageTypeName.Authenticate) else if (messageType == MessageTypeName.Authenticate)
{ {
AuthenticateMessage authenticateMessage; return Authenticate(context, inputToken);
try
{
authenticateMessage = new AuthenticateMessage(inputToken);
}
catch
{
return NTStatus.SEC_E_INVALID_TOKEN;
}
return Authenticate(context, authenticateMessage);
} }
else else
{ {
@ -58,9 +38,9 @@ namespace SMBLibrary.Authentication.NTLM
} }
} }
public abstract NTStatus GetChallengeMessage(out object context, NegotiateMessage negotiateMessage, out ChallengeMessage challengeMessage); public abstract NTStatus GetChallengeMessage(out object context, byte[] negotiateMessageBytes, out byte[] challengeMessageBytes);
public abstract NTStatus Authenticate(object context, AuthenticateMessage authenticateMessage); public abstract NTStatus Authenticate(object context, byte[] authenticateMessageBytes);
public abstract bool DeleteSecurityContext(ref object context); public abstract bool DeleteSecurityContext(ref object context);