mirror of
https://github.com/TalAloni/SMBLibrary.git
synced 2025-07-25 18:38:14 +02:00
Added NegTokenInit2 implementation
This commit is contained in:
parent
0494fd758f
commit
32edb7993f
3 changed files with 267 additions and 1 deletions
|
@ -6,15 +6,17 @@
|
||||||
*/
|
*/
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
using Utilities;
|
using Utilities;
|
||||||
|
|
||||||
namespace SMBLibrary.Authentication.GSSAPI
|
namespace SMBLibrary.Authentication.GSSAPI
|
||||||
{
|
{
|
||||||
public enum DerEncodingTag : byte
|
public enum DerEncodingTag : byte
|
||||||
{
|
{
|
||||||
ByteArray = 0x04,
|
ByteArray = 0x04, // Octet String
|
||||||
ObjectIdentifier = 0x06,
|
ObjectIdentifier = 0x06,
|
||||||
Enum = 0x0A,
|
Enum = 0x0A,
|
||||||
|
GeneralString = 0x1B,
|
||||||
Sequence = 0x30,
|
Sequence = 0x30,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,5 +80,17 @@ namespace SMBLibrary.Authentication.GSSAPI
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] EncodeGeneralString(string value)
|
||||||
|
{
|
||||||
|
// We do not support character-set designation escape sequences
|
||||||
|
return ASCIIEncoding.ASCII.GetBytes(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string DecodeGeneralString(byte[] bytes)
|
||||||
|
{
|
||||||
|
// We do not support character-set designation escape sequences
|
||||||
|
return ASCIIEncoding.ASCII.GetString(bytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,251 @@
|
||||||
|
/* Copyright (C) 2018 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.GSSAPI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// [MS-SPNG] - NegTokenInit2
|
||||||
|
/// </summary>
|
||||||
|
public class SimpleProtectedNegotiationTokenInit2 : SimpleProtectedNegotiationTokenInit
|
||||||
|
{
|
||||||
|
public const byte NegHintsTag = 0xA3;
|
||||||
|
new public const byte MechanismListMICTag = 0xA4;
|
||||||
|
|
||||||
|
public const byte HintNameTag = 0xA0;
|
||||||
|
public const byte HintAddressTag = 0xA1;
|
||||||
|
|
||||||
|
public string HintName;
|
||||||
|
public byte[] HintAddress;
|
||||||
|
|
||||||
|
public SimpleProtectedNegotiationTokenInit2()
|
||||||
|
{
|
||||||
|
HintName = "not_defined_in_RFC4178@please_ignore";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <param name="offset">The offset following the NegTokenInit2 tag</param>
|
||||||
|
/// <exception cref="System.IO.InvalidDataException"></exception>
|
||||||
|
public SimpleProtectedNegotiationTokenInit2(byte[] buffer, int offset)
|
||||||
|
{
|
||||||
|
int constructionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
byte tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag != (byte)DerEncodingTag.Sequence)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
int sequenceLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
int sequenceEndOffset = offset + sequenceLength;
|
||||||
|
while (offset < sequenceEndOffset)
|
||||||
|
{
|
||||||
|
tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag == MechanismTypeListTag)
|
||||||
|
{
|
||||||
|
MechanismTypeList = ReadMechanismTypeList(buffer, ref offset);
|
||||||
|
}
|
||||||
|
else if (tag == RequiredFlagsTag)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("negTokenInit.ReqFlags is not implemented");
|
||||||
|
}
|
||||||
|
else if (tag == MechanismTokenTag)
|
||||||
|
{
|
||||||
|
MechanismToken = ReadMechanismToken(buffer, ref offset);
|
||||||
|
}
|
||||||
|
else if (tag == NegHintsTag)
|
||||||
|
{
|
||||||
|
HintName = ReadHints(buffer, ref offset, out HintAddress);
|
||||||
|
}
|
||||||
|
else if (tag == MechanismListMICTag)
|
||||||
|
{
|
||||||
|
MechanismListMIC = ReadMechanismListMIC(buffer, ref offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidDataException("Invalid negTokenInit structure");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override byte[] GetBytes()
|
||||||
|
{
|
||||||
|
int sequenceLength = GetTokenFieldsLength();
|
||||||
|
int sequenceLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(sequenceLength);
|
||||||
|
int constructionLength = 1 + sequenceLengthFieldSize + sequenceLength;
|
||||||
|
int constructionLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(constructionLength);
|
||||||
|
int bufferSize = 1 + constructionLengthFieldSize + 1 + sequenceLengthFieldSize + sequenceLength;
|
||||||
|
byte[] buffer = new byte[bufferSize];
|
||||||
|
int offset = 0;
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, NegTokenInitTag);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, constructionLength);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.Sequence);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, sequenceLength);
|
||||||
|
if (MechanismTypeList != null)
|
||||||
|
{
|
||||||
|
WriteMechanismTypeList(buffer, ref offset, MechanismTypeList);
|
||||||
|
}
|
||||||
|
if (MechanismToken != null)
|
||||||
|
{
|
||||||
|
WriteMechanismToken(buffer, ref offset, MechanismToken);
|
||||||
|
}
|
||||||
|
if (HintName != null || HintAddress != null)
|
||||||
|
{
|
||||||
|
WriteHints(buffer, ref offset, HintName, HintAddress);
|
||||||
|
}
|
||||||
|
if (MechanismListMIC != null)
|
||||||
|
{
|
||||||
|
WriteMechanismListMIC(buffer, ref offset, MechanismListMIC);
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override int GetTokenFieldsLength()
|
||||||
|
{
|
||||||
|
int result = base.GetTokenFieldsLength();;
|
||||||
|
if (HintName != null || HintAddress != null)
|
||||||
|
{
|
||||||
|
int hintsSequenceLength = GetHintsSequenceLength(HintName, HintAddress);
|
||||||
|
int hintsSequenceLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(hintsSequenceLength);
|
||||||
|
int hintsSequenceConstructionLength = 1 + hintsSequenceLengthFieldSize + hintsSequenceLength;
|
||||||
|
int hintsSequenceConstructionLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(hintsSequenceConstructionLength);
|
||||||
|
int entryLength = 1 + hintsSequenceConstructionLengthFieldSize + 1 + hintsSequenceLengthFieldSize + hintsSequenceLength;
|
||||||
|
result += entryLength;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static string ReadHints(byte[] buffer, ref int offset, out byte[] hintAddress)
|
||||||
|
{
|
||||||
|
string hintName = null;
|
||||||
|
hintAddress = null;
|
||||||
|
int constructionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
byte tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag != (byte)DerEncodingTag.Sequence)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
int sequenceLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
int sequenceEndOffset = offset + sequenceLength;
|
||||||
|
while (offset < sequenceEndOffset)
|
||||||
|
{
|
||||||
|
tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag == HintNameTag)
|
||||||
|
{
|
||||||
|
hintName = ReadHintName(buffer, ref offset);
|
||||||
|
}
|
||||||
|
else if (tag == HintAddressTag)
|
||||||
|
{
|
||||||
|
hintAddress = ReadHintAddress(buffer, ref offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hintName;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static string ReadHintName(byte[] buffer, ref int offset)
|
||||||
|
{
|
||||||
|
int constructionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
byte tag = ByteReader.ReadByte(buffer, ref offset);
|
||||||
|
if (tag != (byte)DerEncodingTag.GeneralString)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
int hintLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
byte[] hintNameBytes = ByteReader.ReadBytes(buffer, ref offset, hintLength);
|
||||||
|
return DerEncodingHelper.DecodeGeneralString(hintNameBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static byte[] ReadHintAddress(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 hintLength = DerEncodingHelper.ReadLength(buffer, ref offset);
|
||||||
|
return ByteReader.ReadBytes(buffer, ref offset, hintLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static int GetHintsSequenceLength(string hintName, byte[] hintAddress)
|
||||||
|
{
|
||||||
|
int sequenceLength = 0;
|
||||||
|
if (hintName != null)
|
||||||
|
{
|
||||||
|
byte[] hintNameBytes = DerEncodingHelper.EncodeGeneralString(hintName);
|
||||||
|
int lengthFieldSize = DerEncodingHelper.GetLengthFieldSize(hintNameBytes.Length);
|
||||||
|
int constructionLength = 1 + lengthFieldSize + hintNameBytes.Length;
|
||||||
|
int constructionLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(constructionLength);
|
||||||
|
int entryLength = 1 + constructionLengthFieldSize + 1 + lengthFieldSize + hintNameBytes.Length;
|
||||||
|
sequenceLength += entryLength;
|
||||||
|
}
|
||||||
|
if (hintAddress != null)
|
||||||
|
{
|
||||||
|
int lengthFieldSize = DerEncodingHelper.GetLengthFieldSize(hintAddress.Length);
|
||||||
|
int constructionLength = 1 + lengthFieldSize + hintAddress.Length;
|
||||||
|
int constructionLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(constructionLength);
|
||||||
|
int entryLength = 1 + constructionLengthFieldSize + 1 + lengthFieldSize + hintAddress.Length;
|
||||||
|
sequenceLength += entryLength;
|
||||||
|
}
|
||||||
|
return sequenceLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteHints(byte[] buffer, ref int offset, string hintName, byte[] hintAddress)
|
||||||
|
{
|
||||||
|
int sequenceLength = GetHintsSequenceLength(hintName, hintAddress);
|
||||||
|
int sequenceLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(sequenceLength);
|
||||||
|
int constructionLength = 1 + sequenceLengthFieldSize + sequenceLength;
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, NegHintsTag);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, constructionLength);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.Sequence);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, sequenceLength);
|
||||||
|
if (hintName != null)
|
||||||
|
{
|
||||||
|
WriteHintName(buffer, ref offset, hintName);
|
||||||
|
}
|
||||||
|
if (hintAddress != null)
|
||||||
|
{
|
||||||
|
WriteHintAddress(buffer, ref offset, hintAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteHintName(byte[] buffer, ref int offset, string hintName)
|
||||||
|
{
|
||||||
|
byte[] hintNameBytes = DerEncodingHelper.EncodeGeneralString(hintName);
|
||||||
|
int constructionLength = 1 + DerEncodingHelper.GetLengthFieldSize(hintNameBytes.Length) + hintNameBytes.Length;
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, HintNameTag);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, constructionLength);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.GeneralString);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, hintNameBytes.Length);
|
||||||
|
ByteWriter.WriteBytes(buffer, ref offset, hintNameBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteHintAddress(byte[] buffer, ref int offset, byte[] hintAddress)
|
||||||
|
{
|
||||||
|
int constructionLength = 1 + DerEncodingHelper.GetLengthFieldSize(hintAddress.Length) + hintAddress.Length;
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, HintAddressTag);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, constructionLength);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ByteArray);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, hintAddress.Length);
|
||||||
|
ByteWriter.WriteBytes(buffer, ref offset, hintAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
new protected static void WriteMechanismListMIC(byte[] buffer, ref int offset, byte[] mechanismListMIC)
|
||||||
|
{
|
||||||
|
int mechanismListMICLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(mechanismListMIC.Length);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, MechanismListMICTag);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, 1 + mechanismListMICLengthFieldSize + mechanismListMIC.Length);
|
||||||
|
ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ByteArray);
|
||||||
|
DerEncodingHelper.WriteLength(buffer, ref offset, mechanismListMIC.Length);
|
||||||
|
ByteWriter.WriteBytes(buffer, ref offset, mechanismListMIC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,6 +37,7 @@
|
||||||
<Compile Include="Authentication\GSSAPI\SPNEGO\DerEncodingHelper.cs" />
|
<Compile Include="Authentication\GSSAPI\SPNEGO\DerEncodingHelper.cs" />
|
||||||
<Compile Include="Authentication\GSSAPI\SPNEGO\SimpleProtectedNegotiationToken.cs" />
|
<Compile Include="Authentication\GSSAPI\SPNEGO\SimpleProtectedNegotiationToken.cs" />
|
||||||
<Compile Include="Authentication\GSSAPI\SPNEGO\SimpleProtectedNegotiationTokenInit.cs" />
|
<Compile Include="Authentication\GSSAPI\SPNEGO\SimpleProtectedNegotiationTokenInit.cs" />
|
||||||
|
<Compile Include="Authentication\GSSAPI\SPNEGO\SimpleProtectedNegotiationTokenInit2.cs" />
|
||||||
<Compile Include="Authentication\GSSAPI\SPNEGO\SimpleProtectedNegotiationTokenResponse.cs" />
|
<Compile Include="Authentication\GSSAPI\SPNEGO\SimpleProtectedNegotiationTokenResponse.cs" />
|
||||||
<Compile Include="Authentication\LoginCounter.cs" />
|
<Compile Include="Authentication\LoginCounter.cs" />
|
||||||
<Compile Include="Authentication\NTLM\Helpers\AuthenticationMessageUtils.cs" />
|
<Compile Include="Authentication\NTLM\Helpers\AuthenticationMessageUtils.cs" />
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue