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

View file

@ -289,7 +289,7 @@ namespace SMBLibrary.Client
} }
else // m_securityBlob != null 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) if (negotiateMessage == null)
{ {
return NTStatus.SEC_E_INVALID_TOKEN; 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"); 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) if (negotiateMessage == null)
{ {
return NTStatus.SEC_E_INVALID_TOKEN; return NTStatus.SEC_E_INVALID_TOKEN;