////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: NtlmMessages.cs
//
// Note:
//
// This file contains structures and enumerated types of the NTLM
// authentication protocol.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Runtime.InteropServices;
namespace System.Security.Protocols.Ntlm
{
class NtlmConstants
{
#if false
public static readonly byte[]! MessageSignature = {
(byte)'N',
(byte)'T',
(byte)'L',
(byte)'M',
(byte)'S',
(byte)'S',
(byte)'P',
0
};
#endif
// This is the NTLM message signature, encoded as a little-endian ulong.
public const ulong MessageSignature64Le =
((ulong)'N')
| (((ulong)'T') << 8)
| (((ulong)'L') << 0x10)
| (((ulong)'M') << 0x18)
| (((ulong)'S') << 0x20)
| (((ulong)'S') << 0x28)
| (((ulong)'P') << 0x30)
/* 0x38 position is zero */;
public const int HeaderLength = 0x10;
public const int ChallengeLength = 8;
}
public enum NtlmMessageType
{
Negotiate = 1,
Challenge = 2,
Response = 3,
}
/**
All NTLMSSP messages begin with this header.
*/
[StructLayout(LayoutKind.Sequential, Pack=1)]
pointerfree struct NtlmMessageHeader
{
/**
This value should always be "NTLMSSP\0", encoded as a little-endian 64-bit ulong.
NtlmConstants.MessageSignature64Le encodes this value.
*/
public ulong Signature;
/** A value from NtlmMessageType. */
public uint MessageType;
}
/**
The Negotiate message is the first message in an NTLM exchange.
The client (supplicant) sends this message to the server, requesting a session
and indicating what kind of options this client supports. The OemDomainName
and OemWorkstationName values can be provided for diagnostics and logging,
but the server is under no obligation to trust them.
*/
[StructLayout(LayoutKind.Sequential, Pack=1)]
pointerfree struct NtlmNegotiateMessage
{
public NtlmMessageHeader Header;
public uint NegotiateFlags;
public BufferRegion OemDomainName;
public BufferRegion OemWorkstationName;
public ulong Version;
}
[Flags]
public enum NtlmNegotiateFlags
{
None = 0,
/** Text strings are in unicode */
NegotiateUnicode = 0x00000001,
/** Text strings are in OEM */
NegotiateOem = 0x00000002,
/** Server should return its authentication realm */
RequestTarget = 0x00000004,
/** Request signature capability */
NegotiateSign = 0x00000010,
/** Request confidentiality */
NegotiateSeal = 0x00000020,
/** Use datagram style authentication */
NegotiateDatagram = 0x00000040,
/** Use LM session key for sign/seal */
NegotiateLmKey = 0x00000080,
/** NetWare authentication */
NegotiateNetware = 0x00000100,
/** NTLM authentication */
NegotiateNtlm = 0x00000200,
/** NT authentication only (no LM) */
NegotiateNtOnly = 0x00000400,
/** NULL Sessions on NT 5.0 and beyond */
NegotiateNullSession = 0x00000800,
/** Domain Name supplied on negotiate */
NegotiateOemDomainSupplied = 0x1000,
/** Workstation Name supplied on negotiate */
NegotiateOemWorkstationSupplied = 0x2000,
/** Indicates client/server are same machine */
NegotiateLocalCall = 0x00004000,
/** Sign for all security levels */
NegotiateAlwaysSign = 0x00008000,
}
/**
Describes the header for the NTLM "Challenge" message. This message is also known as an
NTLM "Type 3" message. This message is sent from a server (authenticator) to a client
(supplicant). The server generates a random 8-byte challenge (nonce).
*/
[StructLayout(LayoutKind.Sequential, Pack=1)]
pointerfree struct NtlmChallengeMessage
{
public NtlmMessageHeader Header;
/**
The domain name (realm name) of the server. This value may or may not be present.
If the NtlmNegotiateFlag.RequestTarget flag is set in the Negotiate message, then
the client requests this field, but the server is not obligated to send this value.
*/
public BufferRegion TargetName;
/** The set of negotiation flags that the server has agreed to. */
public uint NegotiateFlags;
/** The 8-byte challenge, encoded as a 64-bit integer. */
public ulong PackedChallenge;
// The contents of the TargetName follow.
}
/**
This structure describes the header for the NTLM "Response" message, also known as the NTLM
"Type 3" message. This message is sent from the client (supplicant) to the server (authenticator),
and is the last message in the exchange. This message proves that the client has valid credentials.
*/
[StructLayout(LayoutKind.Sequential, Pack=1)]
pointerfree struct NtlmResponseMessage
{
public NtlmMessageHeader Header;
/** Describes the size and location of the LAN Manager response. */
public BufferRegion LmChallengeResponse;
/** Describes the size and location of the NT response. */
public BufferRegion NtChallengeResponse;
/** Describes the size and location of the domain name of the authenticating user. */
public BufferRegion DomainName;
/** Describes the size and location of the username of the authenticating user. */
public BufferRegion UserName;
/** Describes the size and location of the workstation name (computer name) of the client's computer. */
public BufferRegion Workstation;
// The contents of the many BufferRegion fields follow.
}
/**
Identifies a region within a buffer. This structure is compatible with the STRING32 structure
used by NT, which is used to describe the offset and length of variable-length strings that are
stored after a fixed-length message header.
NTLM uses this structure to describe the size and location variable-length strings in NTLMSSP messages.
*/
[StructLayout(LayoutKind.Sequential, Pack=1)]
pointerfree struct BufferRegion
{
public ushort Length; // the length in bytes of the string
public ushort MaximumLength; // the maximum number of bytes to write to the buffer (n/a in networking!)
public ushort Offset; // offset within the message of this string
public ushort Reserved; // always zero
public BufferRegion(ushort length, ushort maximumLength, ushort offset)
{
this.Length = length;
this.MaximumLength = maximumLength;
this.Offset = offset;
this.Reserved = 0;
}
}
}