//////////////////////////////////////////////////////////////////////////////// // // 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; } } }