singrdk/base/Libraries/Ntlm/NtlmUtil.sg

158 lines
5.6 KiB
Plaintext

////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: NtlmUtil.sg
//
// Note:
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Diagnostics;
using System.Text;
using Microsoft.Singularity;
using Util = Utils.Util;
namespace System.Security.Protocols.Ntlm
{
public class NtlmUtil
{
public static ushort GetUInt16(byte[]! message, int pos)
{
return (ushort)(message[pos] + (message[pos + 1] << 8));
}
public static byte[]! GetCountedBytesAt(byte[]! message, int pos)
requires pos >= 0;
requires pos < message.Length;
{
int length = GetUInt16(message, pos + 0);
//int maxlength = GetUInt16(message, pos + 2);
int offset = GetUInt16(message, pos + 4);
if (offset >= message.Length)
throw new Exception("String has invalid offset");
if (offset + length > message.Length)
throw new Exception("String has invalid offset / length");
return NtlmUtil.GetSubArray(message, offset, length);
}
public static byte[]! GetSubArray(byte[]! arr, int index, int length)
requires index >= 0;
requires index + length <= arr.Length;
ensures result.Length == length;
{
byte[] result = new byte[length];
Array.Copy(arr, index, result, 0, length);
return result;
}
public static string GetCountedStringAt(byte[]! message, int pos)
requires pos >= 0;
requires pos + sizeof(BufferRegion) <= message.Length;
{
ref BufferRegion region = ref message[pos];
int length = ByteOrder.UInt16LeToHost(region.Length);
// int maxlength = GetUInt16(message, pos + 2);
int offset = ByteOrder.UInt16LeToHost(region.Offset);
if (offset >= message.Length)
throw new Exception("String has invalid offset");
if (offset + length > message.Length)
throw new Exception("String has invalid offset / length");
string result = Encoding.Unicode.GetString(message, offset, length);
return result;
}
#if NOISY
public static void DumpMessage(byte[]! message)
{
DumpMessage(message, message.Length);
}
public static void DumpMessage(byte[]! message, int length)
{
DebugLine("");
DebugLine("NTLM message:");
Util.DumpBuffer(message, 0, length);
if (length < NtlmConstants.HeaderLength) {
DebugLine(" Message is invalid; too short");
return;
}
for (int i = 0; i < NtlmConstants.MessageSignature.Length; i++) {
if (message[i] != NtlmConstants.MessageSignature[i]) {
DebugLine(" Message is invalid; signature does not match");
return;
}
}
NtlmMessageType type = (NtlmMessageType)message[8];
switch (type) {
case NtlmMessageType.Negotiate:
{
DebugLine(" Type: Negotiate");
NtlmNegotiateFlags flags = (NtlmNegotiateFlags)GetUInt16(message, 12);
DebugLine(String.Format(" Flags: 0x{0:x8} {1}", (UInt32)flags, flags.ToString()));
string domain = GetCountedStringAt(message, 0x10);
DebugLine(" Domain: " + domain);
}
break;
case NtlmMessageType.Challenge:
{
DebugLine(" Type: Challenge");
string TargetName = GetCountedStringAt(message, 0x0c);
byte[] Challenge = Util.GetSubArray(message, 0x14, NtlmConstants.ChallengeLength);
DebugLine(" TargetName: " + TargetName);
DebugLine(" Challenge: " + Util.ByteArrayToStringHex(Challenge));
}
break;
case NtlmMessageType.Response:
{
DebugLine(" Type: Response");
byte[] LmChallengeResponse = GetCountedbytesAt(message, 0x0c);
byte[] NtChallengeResponse = GetCountedbytesAt(message, 0x14);
string DomainName = GetCountedStringAt(message, 28);
string UserName = GetCountedStringAt(message, 36);
string Workstation = GetCountedStringAt(message, 42);
DebugLine(" LmChallengeResponse: " + Util.ByteArrayToStringHex(LmChallengeResponse));
DebugLine(" NtChallengeResponse: " + Util.ByteArrayToStringHex(NtChallengeResponse));
DebugLine(" DomainName: " + DomainName);
DebugLine(" UserName: " + UserName);
DebugLine(" Workstation: " + Workstation);
}
break;
default:
DebugLine(" Message is invalid; message type byte is not recognized");
return;
}
DebugLine("");
}
static void DebugLine(string msg)
{
DebugStub.WriteLine("NTLM: " + msg);
}
#endif
}
}