Improved SupplementalCredentials serialization and tests

This commit is contained in:
Michael Grafnetter 2018-09-26 14:57:14 +02:00
parent 331d9abbab
commit 3271ce6cfc
4 changed files with 81 additions and 14 deletions

View File

@ -65,5 +65,42 @@
// Check binary equality
Assert.AreEqual(blob.ToHex(), newBlob.ToHex());
}
[TestMethod]
public void KerberosCredential_W2k3_Vector1()
{
byte[] blob = "030000000200000030003000500000000000000000000000030000000800000080000000000000000000000001000000080000008800000000000000000000000000000000000000000000000000000043004f004e0054004f0053004f002e0043004f004d00410064006d0069006e006900730074007200610074006f007200aed02c52204ca2ceaed02c52204ca2ce00000000000000000000000000000000".HexToBinary();
var credential = new KerberosCredential(blob);
// Check that the structure has been parsed correctly.
Assert.AreEqual("CONTOSO.COMAdministrator", credential.DefaultSalt);
Assert.AreEqual(2, credential.Credentials.Length);
Assert.AreEqual(KerberosKeyType.DES_CBC_MD5, credential.Credentials[0].KeyType);
// Serialize the structure
byte[] newBlob = credential.ToByteArray();
// Note that we are not expecting binary equality, because Windows Server 2003 used to add some redundand padding to the end of the structure.
Assert.AreEqual(blob.Length - 20, newBlob.Length);
}
[TestMethod]
public void KerberosCredential_W2k3_Vector2()
{
byte[] blob = "03000000020002004a004a007800000000000000000000000300000008000000c200000000000000000000000100000008000000ca00000000000000000000000300000008000000d200000000000000000000000100000008000000da00000000000000000000000000000000000000000000000000000043004f004e0054004f0053004f002e0043004f004d0068006f0073007400770069006e0032006b00330072003200650065002e0063006f006e0074006f0073006f002e0063006f006d00d9b33eb064e385dfd9b33eb064e385dff191e9a7b561525df191e9a7b561525d00000000000000000000000000000000".HexToBinary();
var credential = new KerberosCredential(blob);
// Check that the structure has been parsed correctly.
Assert.AreEqual("CONTOSO.COMhostwin2k3r2ee.contoso.com", credential.DefaultSalt);
Assert.AreEqual(2, credential.Credentials.Length);
Assert.AreEqual(KerberosKeyType.DES_CBC_MD5, credential.Credentials[0].KeyType);
Assert.AreEqual(2, credential.OldCredentials.Length);
// Serialize the structure
byte[] newBlob = credential.ToByteArray();
// Note that we are not expecting binary equality, because Windows Server 2003 used to add some redundand padding to the end of the structure.
Assert.AreEqual(blob.Length - 20, newBlob.Length);
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -111,11 +111,8 @@
currentKeyValueOffset += credential.Key.Length;
}
// Add optional padding
for (short i = credentialCount; i < RequiredCredentialCount; i++)
{
writer.Write(Enumerable.Repeat(Byte.MinValue, KerberosKeyData.StructureSize).ToArray());
}
// Add padding (just to get the same result as Windows Server 2008)
writer.Write(Enumerable.Repeat(Byte.MinValue, KerberosKeyData.StructureSize).ToArray());
// DefaultSalt (variable): The default salt value.
if (defaultSaltLength > 0)

View File

@ -4,13 +4,15 @@
using DSInternals.Common.Properties;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Security;
using System.Text;
// https://msdn.microsoft.com/en-us/library/cc245500.aspx
/// <summary>
/// Stored credentials for use in authenticating.
/// </summary>
/// <see>https://msdn.microsoft.com/en-us/library/cc245500.aspx</see>
public class SupplementalCredentials
{
private const int Reserved4Size = 96;
@ -72,6 +74,12 @@
private set;
}
protected byte Reserved5
{
get;
private set;
}
public SupplementalCredentials(byte[] blob)
{
// Empty structures can be 13 and 111 bytes long, perhaps even something in between
@ -118,7 +126,8 @@
this.ReadProperties(reader);
// This value SHOULD<20> be set to zero and MUST be ignored by the recipient.
byte reserved5 = reader.ReadByte();
// We have sometimes seen values different than 0.
this.Reserved5 = reader.ReadByte();
}
}
}
@ -183,7 +192,7 @@
WriteProperties(writer);
// Reserved5 (1 byte): This value SHOULD<20> be set to zero and MUST be ignored by the recipient.
writer.Write(Byte.MinValue);
writer.Write(this.Reserved5);
// We finally know the length of the entire structure, so we can go back and put in the right value
writer.Seek(LengthOffset, SeekOrigin.Begin);
@ -328,7 +337,9 @@
writer.Write((short)encodedValue.Length);
// Reserved(2 bytes): This value MUST be ignored by the recipient and MAY < 22 > be set to arbitrary values on update.
writer.Write(UInt16.MinValue);
// In observed cases, Windows uses 2 for the packages list and 1 for other packages
short reserved = (short)(name == PropertyPackages ? 2 : 1);
writer.Write(reserved);
// PropertyName(variable): The name of this property as a UTF - 16 encoded string.
writer.Write(encodedName);