mirror of
https://github.com/TalAloni/SMBLibrary.git
synced 2025-04-30 02:37:49 +02:00
Added support for GSSAPI tokens
This commit is contained in:
parent
aaef6f2fc3
commit
cf9aba4a31
11 changed files with 658 additions and 20 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
|
/* Copyright (C) 2014-2017 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,
|
||||||
|
@ -16,6 +16,8 @@ namespace SMBLibrary.Authentication
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AuthenticateMessage
|
public class AuthenticateMessage
|
||||||
{
|
{
|
||||||
|
public const string ValidSignature = "NTLMSSP\0";
|
||||||
|
|
||||||
public string Signature; // 8 bytes
|
public string Signature; // 8 bytes
|
||||||
public MessageTypeName MessageType;
|
public MessageTypeName MessageType;
|
||||||
public byte[] LmChallengeResponse;
|
public byte[] LmChallengeResponse;
|
||||||
|
@ -30,7 +32,7 @@ namespace SMBLibrary.Authentication
|
||||||
|
|
||||||
public AuthenticateMessage()
|
public AuthenticateMessage()
|
||||||
{
|
{
|
||||||
Signature = AuthenticationMessageUtils.ValidSignature;
|
Signature = ValidSignature;
|
||||||
MessageType = MessageTypeName.Authenticate;
|
MessageType = MessageTypeName.Authenticate;
|
||||||
DomainName = String.Empty;
|
DomainName = String.Empty;
|
||||||
UserName = String.Empty;
|
UserName = String.Empty;
|
||||||
|
@ -66,7 +68,7 @@ namespace SMBLibrary.Authentication
|
||||||
|
|
||||||
int payloadLength = LmChallengeResponse.Length + NtChallengeResponse.Length + DomainName.Length * 2 + UserName.Length * 2 + WorkStation.Length * 2 + EncryptedRandomSessionKey.Length;
|
int payloadLength = LmChallengeResponse.Length + NtChallengeResponse.Length + DomainName.Length * 2 + UserName.Length * 2 + WorkStation.Length * 2 + EncryptedRandomSessionKey.Length;
|
||||||
byte[] buffer = new byte[fixedLength + payloadLength];
|
byte[] buffer = new byte[fixedLength + payloadLength];
|
||||||
ByteWriter.WriteAnsiString(buffer, 0, AuthenticationMessageUtils.ValidSignature, 8);
|
ByteWriter.WriteAnsiString(buffer, 0, ValidSignature, 8);
|
||||||
LittleEndianWriter.WriteUInt32(buffer, 8, (uint)MessageType);
|
LittleEndianWriter.WriteUInt32(buffer, 8, (uint)MessageType);
|
||||||
LittleEndianWriter.WriteUInt32(buffer, 60, (uint)NegotiateFlags);
|
LittleEndianWriter.WriteUInt32(buffer, 60, (uint)NegotiateFlags);
|
||||||
if ((NegotiateFlags & NegotiateFlags.NegotiateVersion) > 0)
|
if ((NegotiateFlags & NegotiateFlags.NegotiateVersion) > 0)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
|
/* Copyright (C) 2014-2017 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,
|
||||||
|
@ -13,8 +13,6 @@ namespace SMBLibrary.Authentication
|
||||||
{
|
{
|
||||||
public class AuthenticationMessageUtils
|
public class AuthenticationMessageUtils
|
||||||
{
|
{
|
||||||
public const string ValidSignature = "NTLMSSP\0";
|
|
||||||
|
|
||||||
public static string ReadAnsiStringBufferPointer(byte[] buffer, int offset)
|
public static string ReadAnsiStringBufferPointer(byte[] buffer, int offset)
|
||||||
{
|
{
|
||||||
byte[] bytes = ReadBufferPointer(buffer, offset);
|
byte[] bytes = ReadBufferPointer(buffer, offset);
|
||||||
|
@ -52,8 +50,12 @@ namespace SMBLibrary.Authentication
|
||||||
|
|
||||||
public static bool IsSignatureValid(byte[] messageBytes)
|
public static bool IsSignatureValid(byte[] messageBytes)
|
||||||
{
|
{
|
||||||
|
if (messageBytes.Length < 8)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
string signature = ByteReader.ReadAnsiString(messageBytes, 0, 8);
|
string signature = ByteReader.ReadAnsiString(messageBytes, 0, 8);
|
||||||
return (signature == ValidSignature);
|
return (signature == AuthenticateMessage.ValidSignature);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MessageTypeName GetMessageType(byte[] messageBytes)
|
public static MessageTypeName GetMessageType(byte[] messageBytes)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
|
/* Copyright (C) 2014-2017 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,
|
||||||
|
@ -27,7 +27,7 @@ namespace SMBLibrary.Authentication
|
||||||
|
|
||||||
public ChallengeMessage()
|
public ChallengeMessage()
|
||||||
{
|
{
|
||||||
Signature = AuthenticationMessageUtils.ValidSignature;
|
Signature = AuthenticateMessage.ValidSignature;
|
||||||
MessageType = MessageTypeName.Challenge;
|
MessageType = MessageTypeName.Challenge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ namespace SMBLibrary.Authentication
|
||||||
|
|
||||||
int payloadLength = TargetName.Length * 2 + TargetInfo.Length;
|
int payloadLength = TargetName.Length * 2 + TargetInfo.Length;
|
||||||
byte[] buffer = new byte[fixedLength + payloadLength];
|
byte[] buffer = new byte[fixedLength + payloadLength];
|
||||||
ByteWriter.WriteAnsiString(buffer, 0, AuthenticationMessageUtils.ValidSignature, 8);
|
ByteWriter.WriteAnsiString(buffer, 0, AuthenticateMessage.ValidSignature, 8);
|
||||||
LittleEndianWriter.WriteUInt32(buffer, 8, (uint)MessageType);
|
LittleEndianWriter.WriteUInt32(buffer, 8, (uint)MessageType);
|
||||||
LittleEndianWriter.WriteUInt32(buffer, 20, (uint)NegotiateFlags);
|
LittleEndianWriter.WriteUInt32(buffer, 20, (uint)NegotiateFlags);
|
||||||
ByteWriter.WriteBytes(buffer, 24, ServerChallenge);
|
ByteWriter.WriteBytes(buffer, 24, ServerChallenge);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
|
/* Copyright (C) 2014-2017 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,7 +25,7 @@ namespace SMBLibrary.Authentication
|
||||||
|
|
||||||
public NegotiateMessage()
|
public NegotiateMessage()
|
||||||
{
|
{
|
||||||
Signature = AuthenticationMessageUtils.ValidSignature;
|
Signature = AuthenticateMessage.ValidSignature;
|
||||||
MessageType = MessageTypeName.Negotiate;
|
MessageType = MessageTypeName.Negotiate;
|
||||||
DomainName = String.Empty;
|
DomainName = String.Empty;
|
||||||
Workstation = String.Empty;
|
Workstation = String.Empty;
|
||||||
|
@ -53,7 +53,7 @@ namespace SMBLibrary.Authentication
|
||||||
}
|
}
|
||||||
int payloadLength = DomainName.Length * 2 + Workstation.Length * 2;
|
int payloadLength = DomainName.Length * 2 + Workstation.Length * 2;
|
||||||
byte[] buffer = new byte[fixedLength + payloadLength];
|
byte[] buffer = new byte[fixedLength + payloadLength];
|
||||||
ByteWriter.WriteAnsiString(buffer, 0, AuthenticationMessageUtils.ValidSignature, 8);
|
ByteWriter.WriteAnsiString(buffer, 0, AuthenticateMessage.ValidSignature, 8);
|
||||||
LittleEndianWriter.WriteUInt32(buffer, 8, (uint)MessageType);
|
LittleEndianWriter.WriteUInt32(buffer, 8, (uint)MessageType);
|
||||||
LittleEndianWriter.WriteUInt32(buffer, 12, (uint)NegotiateFlags);
|
LittleEndianWriter.WriteUInt32(buffer, 12, (uint)NegotiateFlags);
|
||||||
|
|
||||||
|
|
82
SMBLibrary/Authentication/GSSAPI/DerEncodingHelper.cs
Normal file
82
SMBLibrary/Authentication/GSSAPI/DerEncodingHelper.cs
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
/* Copyright (C) 2017 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,
|
||||||
|
* either version 3 of the License, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Utilities;
|
||||||
|
|
||||||
|
namespace SMBLibrary.Authentication
|
||||||
|
{
|
||||||
|
public enum DerEncodingTag : byte
|
||||||
|
{
|
||||||
|
ByteArray = 0x04,
|
||||||
|
ObjectIdentifier = 0x06,
|
||||||
|
Enum = 0x0A,
|
||||||
|
Sequence = 0x30,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DerEncodingHelper
|
||||||
|
{
|
||||||
|
public static int ReadLength(byte[] buffer, ref int offset)
|
||||||
|
{
|
||||||
|
int length = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (length >= 0x80)
|
||||||
|
{
|
||||||
|
int lengthFieldSize = (length & 0x7F);
|
||||||
|
byte[] lengthField = ByteReader.ReadBytes(buffer, ref offset, lengthFieldSize);
|
||||||
|
length = 0;
|
||||||
|
foreach (byte value in lengthField)
|
||||||
|
{
|
||||||
|
length *= Byte.MaxValue;
|
||||||
|
length += value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void WriteLength(byte[] buffer, ref int offset, int length)
|
||||||
|
{
|
||||||
|
if (length >= 0x80)
|
||||||
|
{
|
||||||
|
List<byte> values = new List<byte>();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
byte value = (byte)(length % Byte.MaxValue);
|
||||||
|
values.Add(value);
|
||||||
|
length = value / Byte.MaxValue;
|
||||||
|
}
|
||||||
|
while (length > 0);
|
||||||
|
values.Reverse();
|
||||||
|
byte[] lengthField = values.ToArray();
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, (byte)(0x80 | lengthField.Length));
|
||||||
|
ByteWriter.WriteBytes(buffer, ref offset, lengthField);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, (byte)length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetLengthFieldSize(int length)
|
||||||
|
{
|
||||||
|
if (length >= 0x80)
|
||||||
|
{
|
||||||
|
int result = 1;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
length = length / Byte.MaxValue;
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
while(length > 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
SMBLibrary/Authentication/GSSAPI/GSSAPIHelper.cs
Normal file
62
SMBLibrary/Authentication/GSSAPI/GSSAPIHelper.cs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/* Copyright (C) 2017 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,
|
||||||
|
* either version 3 of the License, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Utilities;
|
||||||
|
|
||||||
|
namespace SMBLibrary.Authentication
|
||||||
|
{
|
||||||
|
public class GSSAPIHelper
|
||||||
|
{
|
||||||
|
public static readonly byte[] NTLMSSPIdentifier = new byte[] { 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// https://msdn.microsoft.com/en-us/library/ms995330.aspx
|
||||||
|
/// </summary>
|
||||||
|
public static byte[] GetNTLMSSPMessage(byte[] tokenBytes)
|
||||||
|
{
|
||||||
|
SimpleProtectedNegotiationToken token = SimpleProtectedNegotiationToken.ReadToken(tokenBytes, 0);
|
||||||
|
if (token != null)
|
||||||
|
{
|
||||||
|
if (token is SimpleProtectedNegotiationTokenInit)
|
||||||
|
{
|
||||||
|
List<TokenInitEntry> tokens = ((SimpleProtectedNegotiationTokenInit)token).Tokens;
|
||||||
|
foreach (TokenInitEntry entry in tokens)
|
||||||
|
{
|
||||||
|
foreach (byte[] identifier in entry.MechanismTypeList)
|
||||||
|
{
|
||||||
|
if (ByteUtils.AreByteArraysEqual(identifier, NTLMSSPIdentifier))
|
||||||
|
{
|
||||||
|
return entry.MechanismToken;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<TokenResponseEntry> tokens = ((SimpleProtectedNegotiationTokenResponse)token).Tokens;
|
||||||
|
if (tokens.Count > 0)
|
||||||
|
{
|
||||||
|
return tokens[0].ResponseToken;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] GetGSSTokenResponseBytesFromNTLMSSPMessage(byte[] messageBytes)
|
||||||
|
{
|
||||||
|
SimpleProtectedNegotiationTokenResponse token = new SimpleProtectedNegotiationTokenResponse();
|
||||||
|
TokenResponseEntry entry = new TokenResponseEntry();
|
||||||
|
entry.NegState = NegState.AcceptIncomplete;
|
||||||
|
entry.SupportedMechanism = NTLMSSPIdentifier;
|
||||||
|
entry.ResponseToken = messageBytes;
|
||||||
|
token.Tokens.Add(entry);
|
||||||
|
return token.GetBytes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/* Copyright (C) 2017 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,
|
||||||
|
* either version 3 of the License, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Utilities;
|
||||||
|
|
||||||
|
namespace SMBLibrary.Authentication
|
||||||
|
{
|
||||||
|
public abstract class SimpleProtectedNegotiationToken
|
||||||
|
{
|
||||||
|
public const byte ApplicationTag = 0x60;
|
||||||
|
|
||||||
|
public static readonly byte[] SPNEGOIdentifier = new byte[] { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02 };
|
||||||
|
|
||||||
|
public abstract byte[] GetBytes();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// https://tools.ietf.org/html/rfc2743
|
||||||
|
/// </summary>
|
||||||
|
public static SimpleProtectedNegotiationToken ReadToken(byte[] tokenBytes, int offset)
|
||||||
|
{
|
||||||
|
byte tag = ByteReader.ReadByte(tokenBytes, ref offset);
|
||||||
|
if (tag == ApplicationTag)
|
||||||
|
{
|
||||||
|
// when an InitToken is sent, it is prepended by an Application Constructed Object specifier (0x60),
|
||||||
|
// and the OID for SPNEGO (see value in OID table above). This is the generic GSSAPI header.
|
||||||
|
int tokenLength = DerEncodingHelper.ReadLength(tokenBytes, ref offset);
|
||||||
|
tag = ByteReader.ReadByte(tokenBytes, ref offset);
|
||||||
|
if (tag == (byte)DerEncodingTag.ObjectIdentifier)
|
||||||
|
{
|
||||||
|
int objectIdentifierLength = DerEncodingHelper.ReadLength(tokenBytes, ref offset);
|
||||||
|
byte[] objectIdentifier = ByteReader.ReadBytes(tokenBytes, ref offset, objectIdentifierLength);
|
||||||
|
if (ByteUtils.AreByteArraysEqual(objectIdentifier, SPNEGOIdentifier))
|
||||||
|
{
|
||||||
|
return new SimpleProtectedNegotiationTokenInit(tokenBytes, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tag == SimpleProtectedNegotiationTokenResponse.NegTokenRespTag)
|
||||||
|
{
|
||||||
|
offset--;
|
||||||
|
return new SimpleProtectedNegotiationTokenResponse(tokenBytes, offset);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,204 @@
|
||||||
|
/* Copyright (C) 2017 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,
|
||||||
|
* either version 3 of the License, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Utilities;
|
||||||
|
|
||||||
|
namespace SMBLibrary.Authentication
|
||||||
|
{
|
||||||
|
public class TokenInitEntry
|
||||||
|
{
|
||||||
|
public List<byte[]> MechanismTypeList = new List<byte[]>(); // Optional
|
||||||
|
// reqFlags - Optional, Unused
|
||||||
|
public byte[] MechanismToken = new byte[0]; // Optional
|
||||||
|
// mechListMIC - Optional, Unused
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// RFC 4178 - negTokenInit
|
||||||
|
/// </summary>
|
||||||
|
public class SimpleProtectedNegotiationTokenInit : SimpleProtectedNegotiationToken
|
||||||
|
{
|
||||||
|
public const byte NegTokenInitTag = 0xA0;
|
||||||
|
public const byte MechanismTypeListTag = 0xA0;
|
||||||
|
public const byte RequiredFlagsTag = 0xA1;
|
||||||
|
public const byte MechanismTokenTag = 0xA2;
|
||||||
|
public const byte MechanismListMICTag = 0xA3;
|
||||||
|
|
||||||
|
public List<TokenInitEntry> Tokens = new List<TokenInitEntry>();
|
||||||
|
|
||||||
|
public SimpleProtectedNegotiationTokenInit(byte[] buffer, int offset)
|
||||||
|
{
|
||||||
|
byte tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag != NegTokenInitTag)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
int constructionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
int sequenceEndOffset = offset + constructionLength;
|
||||||
|
tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag != (byte)DerEncodingTag.Sequence)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
while (offset < sequenceEndOffset)
|
||||||
|
{
|
||||||
|
int entryLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
int entryEndOffset = offset + entryLength;
|
||||||
|
TokenInitEntry entry = new TokenInitEntry();
|
||||||
|
while (offset < entryEndOffset)
|
||||||
|
{
|
||||||
|
tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag == MechanismTypeListTag)
|
||||||
|
{
|
||||||
|
entry.MechanismTypeList = ReadMechanismTypeList(buffer, ref offset);
|
||||||
|
}
|
||||||
|
else if (tag == MechanismTokenTag)
|
||||||
|
{
|
||||||
|
entry.MechanismToken = ReadMechanismToken(buffer, ref offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tokens.Add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override byte[] GetBytes()
|
||||||
|
{
|
||||||
|
int sequenceLength = 0;
|
||||||
|
foreach (TokenInitEntry token in Tokens)
|
||||||
|
{
|
||||||
|
int entryLength = GetEntryLength(token);
|
||||||
|
sequenceLength += DerEncodingHelper.GetLengthFieldSize(entryLength) + entryLength;
|
||||||
|
}
|
||||||
|
int constructionLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(1 + sequenceLength);
|
||||||
|
int bufferSize = 1 + constructionLengthFieldSize + 1 + sequenceLength;
|
||||||
|
byte[] buffer = new byte[bufferSize];
|
||||||
|
int offset = 0;
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, NegTokenInitTag);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, 1 + sequenceLength);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.Sequence);
|
||||||
|
foreach (TokenInitEntry token in Tokens)
|
||||||
|
{
|
||||||
|
int entryLength = GetEntryLength(token);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, entryLength);
|
||||||
|
if (token.MechanismTypeList != null)
|
||||||
|
{
|
||||||
|
WriteMechanismTypeList(buffer, ref offset, token.MechanismTypeList);
|
||||||
|
}
|
||||||
|
if (token.MechanismToken != null)
|
||||||
|
{
|
||||||
|
WriteMechanismToken(buffer, ref offset, token.MechanismToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetEntryLength(TokenInitEntry token)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
if (token.MechanismTypeList != null)
|
||||||
|
{
|
||||||
|
int typeListSequenceLength = GetSequenceLength(token.MechanismTypeList);
|
||||||
|
int constructionLenthFieldSize = DerEncodingHelper.GetLengthFieldSize(1 + typeListSequenceLength);
|
||||||
|
int typeListLength = 1 + constructionLenthFieldSize + 1 + typeListSequenceLength;
|
||||||
|
result += typeListLength;
|
||||||
|
}
|
||||||
|
if (token.MechanismToken != null)
|
||||||
|
{
|
||||||
|
int byteArrayFieldSize = DerEncodingHelper.GetLengthFieldSize(token.MechanismToken.Length);
|
||||||
|
int constructionLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(1 + byteArrayFieldSize + token.MechanismToken.Length);
|
||||||
|
int tokenLength = 1 + constructionLengthFieldSize + 1 + byteArrayFieldSize + token.MechanismToken.Length;
|
||||||
|
result += tokenLength;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<byte[]> ReadMechanismTypeList(byte[] buffer, ref int offset)
|
||||||
|
{
|
||||||
|
List<byte[]> result = new List<byte[]>();
|
||||||
|
int constructionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
int sequenceEndOffset = offset + constructionLength;
|
||||||
|
byte tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag != (byte)DerEncodingTag.Sequence)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
while (offset < sequenceEndOffset)
|
||||||
|
{
|
||||||
|
int entryLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
int entryEndOffset = offset + entryLength;
|
||||||
|
tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag != (byte)DerEncodingTag.ObjectIdentifier)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
int mechanismTypeLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
byte[] mechanismType = ByteReader.ReadBytes(buffer, ref offset, mechanismTypeLength);
|
||||||
|
result.Add(mechanismType);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] ReadMechanismToken(byte[] buffer, ref int offset)
|
||||||
|
{
|
||||||
|
int constructionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
byte tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag != (byte)DerEncodingTag.ByteArray)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
int mechanismTokenLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
byte[] token = ByteReader.ReadBytes(buffer, ref offset, mechanismTokenLength);
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetSequenceLength(List<byte[]> mechanismTypeList)
|
||||||
|
{
|
||||||
|
int sequenceLength = 0;
|
||||||
|
foreach (byte[] mechanismType in mechanismTypeList)
|
||||||
|
{
|
||||||
|
int lengthFieldSize = DerEncodingHelper.GetLengthFieldSize(mechanismType.Length);
|
||||||
|
int entryLength = 1 + lengthFieldSize + mechanismType.Length;
|
||||||
|
sequenceLength += DerEncodingHelper.GetLengthFieldSize(entryLength) + entryLength;
|
||||||
|
}
|
||||||
|
return sequenceLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteMechanismTypeList(byte[] buffer, ref int offset, List<byte[]> mechanismTypeList)
|
||||||
|
{
|
||||||
|
int sequenceLength = GetSequenceLength(mechanismTypeList);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, MechanismTypeListTag);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, 1 + sequenceLength);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.Sequence);
|
||||||
|
foreach (byte[] mechanismType in mechanismTypeList)
|
||||||
|
{
|
||||||
|
int lengthFieldSize = DerEncodingHelper.GetLengthFieldSize(mechanismType.Length);
|
||||||
|
int entryLength = 1 + lengthFieldSize + mechanismType.Length;
|
||||||
|
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, entryLength);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ObjectIdentifier);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, mechanismType.Length);
|
||||||
|
ByteWriter.WriteBytes(buffer, ref offset, mechanismType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteMechanismToken(byte[] buffer, ref int offset, byte[] mechanismToken)
|
||||||
|
{
|
||||||
|
int constructionLength = 1 + DerEncodingHelper.GetLengthFieldSize(mechanismToken.Length) + mechanismToken.Length;
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, MechanismTokenTag);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, constructionLength);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ByteArray);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, mechanismToken.Length);
|
||||||
|
ByteWriter.WriteBytes(buffer, ref offset, mechanismToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,215 @@
|
||||||
|
/* Copyright (C) 2017 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,
|
||||||
|
* either version 3 of the License, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Utilities;
|
||||||
|
|
||||||
|
namespace SMBLibrary.Authentication
|
||||||
|
{
|
||||||
|
public enum NegState : byte
|
||||||
|
{
|
||||||
|
AcceptCompleted = 0x00,
|
||||||
|
AcceptIncomplete = 0x01,
|
||||||
|
Reject = 0x02,
|
||||||
|
RequestMic = 0x03,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TokenResponseEntry
|
||||||
|
{
|
||||||
|
public NegState? NegState; // Optional
|
||||||
|
public byte[] SupportedMechanism; // Optional
|
||||||
|
public byte[] ResponseToken; // Optional
|
||||||
|
// mechListMIC - Optional, Unused
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// RFC 4178 - negTokenInit
|
||||||
|
/// </summary>
|
||||||
|
public class SimpleProtectedNegotiationTokenResponse : SimpleProtectedNegotiationToken
|
||||||
|
{
|
||||||
|
public const byte NegTokenRespTag = 0xA1;
|
||||||
|
public const byte NegStateTag = 0xA0;
|
||||||
|
public const byte SupportedMechanismTag = 0xA1;
|
||||||
|
public const byte ResponseTokenTag = 0xA2;
|
||||||
|
public const byte MechanismListMICTag = 0xA3;
|
||||||
|
|
||||||
|
public List<TokenResponseEntry> Tokens = new List<TokenResponseEntry>();
|
||||||
|
|
||||||
|
public SimpleProtectedNegotiationTokenResponse()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleProtectedNegotiationTokenResponse(byte[] buffer, int offset)
|
||||||
|
{
|
||||||
|
byte tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag != NegTokenRespTag)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
int constuctionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
int sequenceEndOffset = offset + constuctionLength;
|
||||||
|
tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag != (byte)DerEncodingTag.Sequence)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
while (offset < sequenceEndOffset)
|
||||||
|
{
|
||||||
|
int entryLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
int entryEndOffset = offset + entryLength;
|
||||||
|
TokenResponseEntry entry = new TokenResponseEntry();
|
||||||
|
while (offset < entryEndOffset)
|
||||||
|
{
|
||||||
|
tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag == NegStateTag)
|
||||||
|
{
|
||||||
|
entry.NegState = ReadNegState(buffer, ref offset);
|
||||||
|
}
|
||||||
|
else if (tag == SupportedMechanismTag)
|
||||||
|
{
|
||||||
|
entry.SupportedMechanism = ReadSupportedMechanism(buffer, ref offset);
|
||||||
|
}
|
||||||
|
else if (tag == ResponseTokenTag)
|
||||||
|
{
|
||||||
|
entry.ResponseToken = ReadResponseToken(buffer, ref offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tokens.Add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override byte[] GetBytes()
|
||||||
|
{
|
||||||
|
int sequenceLength = 0;
|
||||||
|
foreach (TokenResponseEntry token in Tokens)
|
||||||
|
{
|
||||||
|
int entryLength = GetEntryLength(token);
|
||||||
|
sequenceLength += DerEncodingHelper.GetLengthFieldSize(entryLength) + entryLength;
|
||||||
|
}
|
||||||
|
int constructionLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(1 + sequenceLength);
|
||||||
|
int bufferSize = 1 + constructionLengthFieldSize + 1 + sequenceLength;
|
||||||
|
byte[] buffer = new byte[bufferSize];
|
||||||
|
int offset = 0;
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, NegTokenRespTag);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, 1 + sequenceLength);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.Sequence);
|
||||||
|
foreach (TokenResponseEntry token in Tokens)
|
||||||
|
{
|
||||||
|
int entryLength = GetEntryLength(token);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, entryLength);
|
||||||
|
if (token.NegState.HasValue)
|
||||||
|
{
|
||||||
|
WriteNegState(buffer, ref offset, token.NegState.Value);
|
||||||
|
}
|
||||||
|
if (token.SupportedMechanism != null)
|
||||||
|
{
|
||||||
|
WriteSupportedMechanism(buffer, ref offset, token.SupportedMechanism);
|
||||||
|
}
|
||||||
|
if (token.ResponseToken != null)
|
||||||
|
{
|
||||||
|
WriteResponseToken(buffer, ref offset, token.ResponseToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static NegState ReadNegState(byte[] buffer, ref int offset)
|
||||||
|
{
|
||||||
|
int length = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
byte tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag != (byte)DerEncodingTag.Enum)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
length = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
return (NegState)ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] ReadSupportedMechanism(byte[] buffer, ref int offset)
|
||||||
|
{
|
||||||
|
int constructionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
byte tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag != (byte)DerEncodingTag.ObjectIdentifier)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
int length = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
return ByteReader.ReadBytes(buffer, ref offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] ReadResponseToken(byte[] buffer, ref int offset)
|
||||||
|
{
|
||||||
|
int constructionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
byte tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag != (byte)DerEncodingTag.ByteArray)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
int length = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
return ByteReader.ReadBytes(buffer, ref offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetEntryLength(TokenResponseEntry token)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
if (token.NegState.HasValue)
|
||||||
|
{
|
||||||
|
int negStateLength = 5;
|
||||||
|
result += negStateLength;
|
||||||
|
}
|
||||||
|
if (token.SupportedMechanism != null)
|
||||||
|
{
|
||||||
|
int supportedMechanismLength2FieldSize = DerEncodingHelper.GetLengthFieldSize(token.SupportedMechanism.Length);
|
||||||
|
int supportedMechanismLength1FieldSize = DerEncodingHelper.GetLengthFieldSize(1 + supportedMechanismLength2FieldSize + token.SupportedMechanism.Length);
|
||||||
|
int supportedMechanismLength = 1 + supportedMechanismLength1FieldSize + 1 + supportedMechanismLength2FieldSize + token.SupportedMechanism.Length;
|
||||||
|
result += supportedMechanismLength;
|
||||||
|
}
|
||||||
|
if (token.ResponseToken != null)
|
||||||
|
{
|
||||||
|
int responseToken2FieldSize = DerEncodingHelper.GetLengthFieldSize(token.ResponseToken.Length);
|
||||||
|
int responseToken1FieldSize = DerEncodingHelper.GetLengthFieldSize(1 + responseToken2FieldSize + token.ResponseToken.Length);
|
||||||
|
int responseTokenLength = 1 + responseToken1FieldSize + 1 + responseToken2FieldSize + token.ResponseToken.Length;
|
||||||
|
result += responseTokenLength;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteNegState(byte[] buffer, ref int offset, NegState negState)
|
||||||
|
{
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, NegStateTag);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, 3);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.Enum);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, 1);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, (byte)negState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteSupportedMechanism(byte[] buffer, ref int offset, byte[] supportedMechanism)
|
||||||
|
{
|
||||||
|
int supportedMechanismLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(supportedMechanism.Length);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, SupportedMechanismTag);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, 1 + supportedMechanismLengthFieldSize + supportedMechanism.Length);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ObjectIdentifier);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, supportedMechanism.Length);
|
||||||
|
ByteWriter.WriteBytes(buffer, ref offset, supportedMechanism);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteResponseToken(byte[] buffer, ref int offset, byte[] responseToken)
|
||||||
|
{
|
||||||
|
int responseTokenLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(responseToken.Length);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, ResponseTokenTag);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, 1 + responseTokenLengthFieldSize + responseToken.Length);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ByteArray);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, responseToken.Length);
|
||||||
|
ByteWriter.WriteBytes(buffer, ref offset, responseToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,6 +41,11 @@
|
||||||
<Compile Include="Authentication\AuthenticateMessage\NegotiateMessage.cs" />
|
<Compile Include="Authentication\AuthenticateMessage\NegotiateMessage.cs" />
|
||||||
<Compile Include="Authentication\AuthenticateMessage\NTLMv2ClientChallenge.cs" />
|
<Compile Include="Authentication\AuthenticateMessage\NTLMv2ClientChallenge.cs" />
|
||||||
<Compile Include="Authentication\AuthenticateMessage\Version.cs" />
|
<Compile Include="Authentication\AuthenticateMessage\Version.cs" />
|
||||||
|
<Compile Include="Authentication\GSSAPI\DerEncodingHelper.cs" />
|
||||||
|
<Compile Include="Authentication\GSSAPI\GSSAPIHelper.cs" />
|
||||||
|
<Compile Include="Authentication\GSSAPI\SimpleProtectedNegotiationToken.cs" />
|
||||||
|
<Compile Include="Authentication\GSSAPI\SimpleProtectedNegotiationTokenInit.cs" />
|
||||||
|
<Compile Include="Authentication\GSSAPI\SimpleProtectedNegotiationTokenResponse.cs" />
|
||||||
<Compile Include="Authentication\MD4.cs" />
|
<Compile Include="Authentication\MD4.cs" />
|
||||||
<Compile Include="Authentication\NTAuthentication.cs" />
|
<Compile Include="Authentication\NTAuthentication.cs" />
|
||||||
<Compile Include="Client\SMBClient.cs" />
|
<Compile Include="Client\SMBClient.cs" />
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
|
/* Copyright (C) 2014-2017 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,
|
||||||
|
@ -119,18 +119,32 @@ namespace SMBLibrary.Server
|
||||||
{
|
{
|
||||||
SessionSetupAndXResponseExtended response = new SessionSetupAndXResponseExtended();
|
SessionSetupAndXResponseExtended response = new SessionSetupAndXResponseExtended();
|
||||||
|
|
||||||
bool isValid = AuthenticationMessageUtils.IsSignatureValid(request.SecurityBlob);
|
// [MS-SMB] The Windows GSS implementation supports raw Kerberos / NTLM messages in the SecurityBlob
|
||||||
if (!isValid)
|
byte[] messageBytes = request.SecurityBlob;
|
||||||
|
bool isRawMessage = true;
|
||||||
|
if (!AuthenticationMessageUtils.IsSignatureValid(messageBytes))
|
||||||
|
{
|
||||||
|
messageBytes = GSSAPIHelper.GetNTLMSSPMessage(request.SecurityBlob);
|
||||||
|
isRawMessage = false;
|
||||||
|
}
|
||||||
|
if (!AuthenticationMessageUtils.IsSignatureValid(messageBytes))
|
||||||
{
|
{
|
||||||
header.Status = NTStatus.STATUS_NOT_IMPLEMENTED;
|
header.Status = NTStatus.STATUS_NOT_IMPLEMENTED;
|
||||||
return new ErrorResponse(CommandName.SMB_COM_SESSION_SETUP_ANDX);
|
return new ErrorResponse(CommandName.SMB_COM_SESSION_SETUP_ANDX);
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageTypeName messageType = AuthenticationMessageUtils.GetMessageType(request.SecurityBlob);
|
MessageTypeName messageType = AuthenticationMessageUtils.GetMessageType(messageBytes);
|
||||||
if (messageType == MessageTypeName.Negotiate)
|
if (messageType == MessageTypeName.Negotiate)
|
||||||
{
|
{
|
||||||
byte[] challengeMessageBytes = users.GetChallengeMessageBytes(request.SecurityBlob);
|
byte[] challengeMessageBytes = users.GetChallengeMessageBytes(messageBytes);
|
||||||
response.SecurityBlob = challengeMessageBytes;
|
if (isRawMessage)
|
||||||
|
{
|
||||||
|
response.SecurityBlob = challengeMessageBytes;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response.SecurityBlob = GSSAPIHelper.GetGSSTokenResponseBytesFromNTLMSSPMessage(challengeMessageBytes);
|
||||||
|
}
|
||||||
header.Status = NTStatus.STATUS_MORE_PROCESSING_REQUIRED;
|
header.Status = NTStatus.STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
}
|
}
|
||||||
else // MessageTypeName.Authenticate
|
else // MessageTypeName.Authenticate
|
||||||
|
@ -138,7 +152,7 @@ namespace SMBLibrary.Server
|
||||||
User user;
|
User user;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
user = users.Authenticate(request.SecurityBlob);
|
user = users.Authenticate(messageBytes);
|
||||||
}
|
}
|
||||||
catch(EmptyPasswordNotAllowedException)
|
catch(EmptyPasswordNotAllowedException)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue