mirror of
https://github.com/TalAloni/SMBLibrary.git
synced 2025-07-24 18:08:16 +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.Collections.Generic;
|
||||
using System.Text;
|
||||
using Utilities;
|
||||
|
||||
namespace SMBLibrary.Authentication.GSSAPI
|
||||
{
|
||||
public enum DerEncodingTag : byte
|
||||
{
|
||||
ByteArray = 0x04,
|
||||
ByteArray = 0x04, // Octet String
|
||||
ObjectIdentifier = 0x06,
|
||||
Enum = 0x0A,
|
||||
GeneralString = 0x1B,
|
||||
Sequence = 0x30,
|
||||
}
|
||||
|
||||
|
@ -78,5 +80,17 @@ namespace SMBLibrary.Authentication.GSSAPI
|
|||
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\SimpleProtectedNegotiationToken.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\LoginCounter.cs" />
|
||||
<Compile Include="Authentication\NTLM\Helpers\AuthenticationMessageUtils.cs" />
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue