mirror of
https://github.com/TalAloni/SMBLibrary.git
synced 2025-08-13 18:59:18 +02:00
Improved GSS implementation
This commit is contained in:
parent
cd11c57cc4
commit
d16092ed38
3 changed files with 48 additions and 40 deletions
|
@ -11,12 +11,23 @@ using Utilities;
|
||||||
|
|
||||||
namespace SMBLibrary.Authentication.GSSAPI
|
namespace SMBLibrary.Authentication.GSSAPI
|
||||||
{
|
{
|
||||||
|
public class GSSContext
|
||||||
|
{
|
||||||
|
internal IGSSMechanism Mechanism;
|
||||||
|
internal object MechanismContext;
|
||||||
|
|
||||||
|
internal GSSContext(IGSSMechanism mechanism, object mechanismContext)
|
||||||
|
{
|
||||||
|
Mechanism = mechanism;
|
||||||
|
MechanismContext = mechanismContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class GSSProvider
|
public class GSSProvider
|
||||||
{
|
{
|
||||||
public static readonly byte[] NTLMSSPIdentifier = new byte[] { 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a };
|
public static readonly byte[] NTLMSSPIdentifier = new byte[] { 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a };
|
||||||
|
|
||||||
private List<IGSSMechanism> m_mechanisms;
|
private List<IGSSMechanism> m_mechanisms;
|
||||||
private Dictionary<object, IGSSMechanism> m_contextToMechanism = new Dictionary<object, IGSSMechanism>();
|
|
||||||
|
|
||||||
public GSSProvider(IGSSMechanism mechanism)
|
public GSSProvider(IGSSMechanism mechanism)
|
||||||
{
|
{
|
||||||
|
@ -40,7 +51,7 @@ namespace SMBLibrary.Authentication.GSSAPI
|
||||||
return SimpleProtectedNegotiationToken.GetTokenBytes(token);
|
return SimpleProtectedNegotiationToken.GetTokenBytes(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NTStatus AcceptSecurityContext(ref object context, byte[] inputToken, out byte[] outputToken)
|
public NTStatus AcceptSecurityContext(ref GSSContext context, byte[] inputToken, out byte[] outputToken)
|
||||||
{
|
{
|
||||||
outputToken = null;
|
outputToken = null;
|
||||||
SimpleProtectedNegotiationToken spnegoToken = SimpleProtectedNegotiationToken.ReadToken(inputToken, 0);
|
SimpleProtectedNegotiationToken spnegoToken = SimpleProtectedNegotiationToken.ReadToken(inputToken, 0);
|
||||||
|
@ -67,10 +78,11 @@ namespace SMBLibrary.Authentication.GSSAPI
|
||||||
if (mechanism != null)
|
if (mechanism != null)
|
||||||
{
|
{
|
||||||
NTStatus status;
|
NTStatus status;
|
||||||
|
context = new GSSContext(mechanism, null);
|
||||||
if (isPreferredMechanism)
|
if (isPreferredMechanism)
|
||||||
{
|
{
|
||||||
byte[] mechanismOutput;
|
byte[] mechanismOutput;
|
||||||
status = mechanism.AcceptSecurityContext(ref context, tokenInit.MechanismToken, out mechanismOutput);
|
status = mechanism.AcceptSecurityContext(ref context.MechanismContext, tokenInit.MechanismToken, out mechanismOutput);
|
||||||
outputToken = GetSPNEGOTokenResponseBytes(mechanismOutput, status, mechanism.Identifier);
|
outputToken = GetSPNEGOTokenResponseBytes(mechanismOutput, status, mechanism.Identifier);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -78,23 +90,20 @@ namespace SMBLibrary.Authentication.GSSAPI
|
||||||
status = NTStatus.SEC_I_CONTINUE_NEEDED;
|
status = NTStatus.SEC_I_CONTINUE_NEEDED;
|
||||||
outputToken = GetSPNEGOTokenResponseBytes(null, status, mechanism.Identifier);
|
outputToken = GetSPNEGOTokenResponseBytes(null, status, mechanism.Identifier);
|
||||||
}
|
}
|
||||||
m_contextToMechanism[context] = mechanism;
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
return NTStatus.SEC_E_SECPKG_NOT_FOUND;
|
return NTStatus.SEC_E_SECPKG_NOT_FOUND;
|
||||||
}
|
}
|
||||||
else // SimpleProtectedNegotiationTokenResponse
|
else // SimpleProtectedNegotiationTokenResponse
|
||||||
{
|
{
|
||||||
IGSSMechanism mechanism;
|
if (context == null)
|
||||||
if (!m_contextToMechanism.TryGetValue(context, out mechanism))
|
|
||||||
{
|
{
|
||||||
// We assume that the problem is not with our implementation and that the client has sent
|
|
||||||
// SimpleProtectedNegotiationTokenResponse without first sending SimpleProtectedNegotiationTokenInit.
|
|
||||||
return NTStatus.SEC_E_INVALID_TOKEN;
|
return NTStatus.SEC_E_INVALID_TOKEN;
|
||||||
}
|
}
|
||||||
|
IGSSMechanism mechanism = context.Mechanism;
|
||||||
SimpleProtectedNegotiationTokenResponse tokenResponse = (SimpleProtectedNegotiationTokenResponse)spnegoToken;
|
SimpleProtectedNegotiationTokenResponse tokenResponse = (SimpleProtectedNegotiationTokenResponse)spnegoToken;
|
||||||
byte[] mechanismOutput;
|
byte[] mechanismOutput;
|
||||||
NTStatus status = mechanism.AcceptSecurityContext(ref context, tokenResponse.ResponseToken, out mechanismOutput);
|
NTStatus status = mechanism.AcceptSecurityContext(ref context.MechanismContext, tokenResponse.ResponseToken, out mechanismOutput);
|
||||||
outputToken = GetSPNEGOTokenResponseBytes(mechanismOutput, status, null);
|
outputToken = GetSPNEGOTokenResponseBytes(mechanismOutput, status, null);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -109,11 +118,17 @@ namespace SMBLibrary.Authentication.GSSAPI
|
||||||
IGSSMechanism ntlmAuthenticationProvider = FindMechanism(NTLMSSPIdentifier);
|
IGSSMechanism ntlmAuthenticationProvider = FindMechanism(NTLMSSPIdentifier);
|
||||||
if (ntlmAuthenticationProvider != null)
|
if (ntlmAuthenticationProvider != null)
|
||||||
{
|
{
|
||||||
NTStatus status = ntlmAuthenticationProvider.AcceptSecurityContext(ref context, inputToken, out outputToken);
|
|
||||||
if (messageType == MessageTypeName.Negotiate)
|
if (messageType == MessageTypeName.Negotiate)
|
||||||
{
|
{
|
||||||
m_contextToMechanism[context] = ntlmAuthenticationProvider;
|
context = new GSSContext(ntlmAuthenticationProvider, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (context == null)
|
||||||
|
{
|
||||||
|
return NTStatus.SEC_E_INVALID_TOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTStatus status = ntlmAuthenticationProvider.AcceptSecurityContext(ref context.MechanismContext, inputToken, out outputToken);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -125,53 +140,44 @@ namespace SMBLibrary.Authentication.GSSAPI
|
||||||
return NTStatus.SEC_E_INVALID_TOKEN;
|
return NTStatus.SEC_E_INVALID_TOKEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object GetContextAttribute(object context, GSSAttributeName attributeName)
|
public object GetContextAttribute(GSSContext context, GSSAttributeName attributeName)
|
||||||
{
|
{
|
||||||
IGSSMechanism mechanism;
|
if (context == null)
|
||||||
if (!m_contextToMechanism.TryGetValue(context, out mechanism))
|
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return mechanism.GetContextAttribute(context, attributeName);
|
IGSSMechanism mechanism = context.Mechanism;
|
||||||
|
return mechanism.GetContextAttribute(context.MechanismContext, attributeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DeleteSecurityContext(ref object context)
|
public bool DeleteSecurityContext(ref GSSContext context)
|
||||||
{
|
{
|
||||||
bool result = false;
|
|
||||||
if (context != null)
|
if (context != null)
|
||||||
{
|
{
|
||||||
IGSSMechanism mechanism;
|
IGSSMechanism mechanism = context.Mechanism;
|
||||||
if (m_contextToMechanism.TryGetValue(context, out mechanism))
|
return mechanism.DeleteSecurityContext(ref context.MechanismContext);
|
||||||
{
|
|
||||||
object contextReference = context;
|
|
||||||
result = mechanism.DeleteSecurityContext(ref context);
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
m_contextToMechanism.Remove(contextReference);
|
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper method for legacy implementation.
|
/// Helper method for legacy implementation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public NTStatus GetNTLMChallengeMessage(out object context, NegotiateMessage negotiateMessage, out ChallengeMessage challengeMessage)
|
public NTStatus GetNTLMChallengeMessage(out GSSContext context, NegotiateMessage negotiateMessage, out ChallengeMessage challengeMessage)
|
||||||
{
|
{
|
||||||
context = null;
|
|
||||||
challengeMessage = null;
|
|
||||||
IGSSMechanism ntlmAuthenticationProvider = FindMechanism(NTLMSSPIdentifier);
|
IGSSMechanism ntlmAuthenticationProvider = FindMechanism(NTLMSSPIdentifier);
|
||||||
if (ntlmAuthenticationProvider != null)
|
if (ntlmAuthenticationProvider != null)
|
||||||
{
|
{
|
||||||
|
context = new GSSContext(ntlmAuthenticationProvider, null);
|
||||||
byte[] outputToken;
|
byte[] outputToken;
|
||||||
NTStatus result = ntlmAuthenticationProvider.AcceptSecurityContext(ref context, negotiateMessage.GetBytes(), out outputToken);
|
NTStatus result = ntlmAuthenticationProvider.AcceptSecurityContext(ref context.MechanismContext, negotiateMessage.GetBytes(), out outputToken);
|
||||||
challengeMessage = new ChallengeMessage(outputToken);
|
challengeMessage = new ChallengeMessage(outputToken);
|
||||||
m_contextToMechanism.Add(context, ntlmAuthenticationProvider);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
context = null;
|
||||||
|
challengeMessage = null;
|
||||||
return NTStatus.SEC_E_SECPKG_NOT_FOUND;
|
return NTStatus.SEC_E_SECPKG_NOT_FOUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,13 +185,13 @@ namespace SMBLibrary.Authentication.GSSAPI
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper method for legacy implementation.
|
/// Helper method for legacy implementation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public NTStatus NTLMAuthenticate(object context, AuthenticateMessage authenticateMessage)
|
public NTStatus NTLMAuthenticate(GSSContext context, AuthenticateMessage authenticateMessage)
|
||||||
{
|
{
|
||||||
IGSSMechanism ntlmAuthenticationProvider = FindMechanism(NTLMSSPIdentifier);
|
if (context != null && ByteUtils.AreByteArraysEqual(context.Mechanism.Identifier, NTLMSSPIdentifier))
|
||||||
if (ntlmAuthenticationProvider != null)
|
|
||||||
{
|
{
|
||||||
|
IGSSMechanism mechanism = context.Mechanism;
|
||||||
byte[] outputToken;
|
byte[] outputToken;
|
||||||
NTStatus result = ntlmAuthenticationProvider.AcceptSecurityContext(ref context, authenticateMessage.GetBytes(), out outputToken);
|
NTStatus result = mechanism.AcceptSecurityContext(ref context.MechanismContext, authenticateMessage.GetBytes(), out outputToken);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -8,6 +8,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using SMBLibrary.Authentication.GSSAPI;
|
||||||
using SMBLibrary.NetBios;
|
using SMBLibrary.NetBios;
|
||||||
using Utilities;
|
using Utilities;
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ namespace SMBLibrary.Server
|
||||||
public BlockingQueue<SessionPacket> SendQueue;
|
public BlockingQueue<SessionPacket> SendQueue;
|
||||||
protected LogDelegate LogToServerHandler;
|
protected LogDelegate LogToServerHandler;
|
||||||
public SMBDialect Dialect;
|
public SMBDialect Dialect;
|
||||||
public object AuthenticationContext;
|
public GSSContext AuthenticationContext;
|
||||||
|
|
||||||
public ConnectionState(LogDelegate logToServerHandler)
|
public ConnectionState(LogDelegate logToServerHandler)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using SMBLibrary.Authentication.GSSAPI;
|
||||||
|
|
||||||
namespace SMBLibrary
|
namespace SMBLibrary
|
||||||
{
|
{
|
||||||
|
@ -15,10 +16,10 @@ namespace SMBLibrary
|
||||||
private string m_userName;
|
private string m_userName;
|
||||||
private string m_machineName;
|
private string m_machineName;
|
||||||
private IPEndPoint m_clientEndPoint;
|
private IPEndPoint m_clientEndPoint;
|
||||||
public object AuthenticationContext;
|
public GSSContext AuthenticationContext;
|
||||||
public object AccessToken;
|
public object AccessToken;
|
||||||
|
|
||||||
public SecurityContext(string userName, string machineName, IPEndPoint clientEndPoint, object authenticationContext, object accessToken)
|
public SecurityContext(string userName, string machineName, IPEndPoint clientEndPoint, GSSContext authenticationContext, object accessToken)
|
||||||
{
|
{
|
||||||
m_userName = userName;
|
m_userName = userName;
|
||||||
m_machineName = machineName;
|
m_machineName = machineName;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue