Client: Support anonymous login

This commit is contained in:
Tal Aloni 2023-07-27 23:14:11 +03:00
parent 4c3d3b542f
commit dd026cf704
3 changed files with 35 additions and 12 deletions

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2017-2018 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
/* Copyright (C) 2017-2023 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
*
* 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,
@ -15,7 +15,7 @@ namespace SMBLibrary.Client
{
public class NTLMAuthenticationHelper
{
public static byte[] GetNegotiateMessage(byte[] securityBlob, string domainName, AuthenticationMethod authenticationMethod)
public static byte[] GetNegotiateMessage(byte[] securityBlob, string domainName, string userName, string password, AuthenticationMethod authenticationMethod)
{
bool useGSSAPI = false;
if (securityBlob.Length > 0)
@ -46,9 +46,13 @@ namespace SMBLibrary.Client
NegotiateFlags.AlwaysSign |
NegotiateFlags.Version |
NegotiateFlags.Use128BitEncryption |
NegotiateFlags.KeyExchange |
NegotiateFlags.Use56BitEncryption;
if (!(userName == String.Empty && password == String.Empty))
{
negotiateMessage.NegotiateFlags |= NegotiateFlags.KeyExchange;
}
if (authenticationMethod == AuthenticationMethod.NTLMv1)
{
negotiateMessage.NegotiateFlags |= NegotiateFlags.LanManagerSessionKey;
@ -139,6 +143,11 @@ namespace SMBLibrary.Client
authenticateMessage.NegotiateFlags |= NegotiateFlags.ExtendedSessionSecurity;
}
if (userName == String.Empty && password == String.Empty)
{
authenticateMessage.NegotiateFlags |= NegotiateFlags.Anonymous;
}
authenticateMessage.UserName = userName;
authenticateMessage.DomainName = domainName;
authenticateMessage.WorkStation = Environment.MachineName;
@ -146,7 +155,13 @@ namespace SMBLibrary.Client
byte[] keyExchangeKey;
if (authenticationMethod == AuthenticationMethod.NTLMv1 || authenticationMethod == AuthenticationMethod.NTLMv1ExtendedSessionSecurity)
{
if (authenticationMethod == AuthenticationMethod.NTLMv1)
// https://msdn.microsoft.com/en-us/library/cc236699.aspx
if (userName == String.Empty && password == String.Empty)
{
authenticateMessage.LmChallengeResponse = new byte[1];
authenticateMessage.NtChallengeResponse = new byte[0];
}
else if (authenticationMethod == AuthenticationMethod.NTLMv1)
{
authenticateMessage.LmChallengeResponse = NTLMCryptography.ComputeLMv1Response(challengeMessage.ServerChallenge, password);
authenticateMessage.NtChallengeResponse = NTLMCryptography.ComputeNTLMv1Response(challengeMessage.ServerChallenge, password);
@ -156,25 +171,33 @@ namespace SMBLibrary.Client
authenticateMessage.LmChallengeResponse = ByteUtils.Concatenate(clientChallenge, new byte[16]);
authenticateMessage.NtChallengeResponse = NTLMCryptography.ComputeNTLMv1ExtendedSessionSecurityResponse(challengeMessage.ServerChallenge, clientChallenge, password);
}
// https://msdn.microsoft.com/en-us/library/cc236699.aspx
sessionBaseKey = new MD4().GetByteHashFromBytes(NTLMCryptography.NTOWFv1(password));
byte[] lmowf = NTLMCryptography.LMOWFv1(password);
keyExchangeKey = NTLMCryptography.KXKey(sessionBaseKey, authenticateMessage.NegotiateFlags, authenticateMessage.LmChallengeResponse, challengeMessage.ServerChallenge, lmowf);
}
else // NTLMv2
{
// https://msdn.microsoft.com/en-us/library/cc236700.aspx
NTLMv2ClientChallenge clientChallengeStructure = new NTLMv2ClientChallenge(time, clientChallenge, challengeMessage.TargetInfo, spn);
byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded();
byte[] ntProofStr = NTLMCryptography.ComputeNTLMv2Proof(challengeMessage.ServerChallenge, clientChallengeStructurePadded, password, userName, domainName);
if (userName == String.Empty && password == String.Empty)
{
authenticateMessage.LmChallengeResponse = new byte[1];
authenticateMessage.NtChallengeResponse = new byte[0];
}
else
{
authenticateMessage.LmChallengeResponse = NTLMCryptography.ComputeLMv2Response(challengeMessage.ServerChallenge, clientChallenge, password, userName, challengeMessage.TargetName);
authenticateMessage.NtChallengeResponse = ByteUtils.Concatenate(ntProofStr, clientChallengeStructurePadded);
}
// https://msdn.microsoft.com/en-us/library/cc236700.aspx
byte[] responseKeyNT = NTLMCryptography.NTOWFv2(password, userName, domainName);
sessionBaseKey = new HMACMD5(responseKeyNT).ComputeHash(ntProofStr);
keyExchangeKey = sessionBaseKey;
}
authenticateMessage.Version = NTLMVersion.Server2003;
// https://msdn.microsoft.com/en-us/library/cc236676.aspx

View file

@ -289,7 +289,7 @@ namespace SMBLibrary.Client
}
else // m_securityBlob != null
{
byte[] negotiateMessage = NTLMAuthenticationHelper.GetNegotiateMessage(m_securityBlob, domainName, authenticationMethod);
byte[] negotiateMessage = NTLMAuthenticationHelper.GetNegotiateMessage(m_securityBlob, domainName, userName, password, authenticationMethod);
if (negotiateMessage == null)
{
return NTStatus.SEC_E_INVALID_TOKEN;

View file

@ -214,7 +214,7 @@ namespace SMBLibrary.Client
throw new InvalidOperationException("A connection must be successfully established before attempting login");
}
byte[] negotiateMessage = NTLMAuthenticationHelper.GetNegotiateMessage(m_securityBlob, domainName, authenticationMethod);
byte[] negotiateMessage = NTLMAuthenticationHelper.GetNegotiateMessage(m_securityBlob, domainName, userName, password, authenticationMethod);
if (negotiateMessage == null)
{
return NTStatus.SEC_E_INVALID_TOKEN;