From f5d4134bc9a77dc2ccc6a3708c82f2bdcdf9b8b5 Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Tue, 2 Dec 2003 03:38:55 +0000 Subject: 2003-12-01 Sebastien Pouliot * ChallengeResponse.cs: New. Implements the NTLM (v1) Challenge Response. * MessageBase.cs: New. Abstract base class for NTLM messages. * NtlmFlags.cs: New. All known flags for NTLM. * Type1Message.cs: New. Negotiation message. * Type2Message.cs: New. Challenge message. * Type3Message.cs: New. Authentication message. svn path=/trunk/mcs/; revision=20676 --- .../ChallengeResponse.cs | 161 +++++++++++++++ .../Mono.Security.Protocol.Ntlm/ChangeLog | 8 + .../Mono.Security.Protocol.Ntlm/MessageBase.cs | 79 ++++++++ .../Mono.Security.Protocol.Ntlm/NtlmFlags.cs | 43 ++++ .../Mono.Security.Protocol.Ntlm/Type1Message.cs | 106 ++++++++++ .../Mono.Security.Protocol.Ntlm/Type2Message.cs | 93 +++++++++ .../Mono.Security.Protocol.Ntlm/Type3Message.cs | 223 +++++++++++++++++++++ 7 files changed, 713 insertions(+) create mode 100755 mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/ChallengeResponse.cs create mode 100755 mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/ChangeLog create mode 100755 mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/MessageBase.cs create mode 100755 mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/NtlmFlags.cs create mode 100755 mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/Type1Message.cs create mode 100755 mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/Type2Message.cs create mode 100755 mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/Type3Message.cs (limited to 'mcs/class') diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/ChallengeResponse.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/ChallengeResponse.cs new file mode 100755 index 00000000000..ec8559228e9 --- /dev/null +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/ChallengeResponse.cs @@ -0,0 +1,161 @@ + +// Adapted from http://www.innovation.ch/java/ntlm.html +// http://davenport.sourceforge.net/ntlm.html + +using System; +using System.Security.Cryptography; +using System.Text; + +using Mono.Security.Cryptography; + +namespace Mono.Security.Protocol.Ntlm { + + public class ChallengeResponse : IDisposable { + + static private byte[] magic = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 }; + + private bool _disposed; + private byte[] _challenge; + private byte[] _lmpwd; + private byte[] _ntpwd; + + // constructors + + public ChallengeResponse () + { + _disposed = false; + _lmpwd = new byte [21]; + _ntpwd = new byte [21]; + } + + public ChallengeResponse (string password, byte[] challenge) : this () + { + Password = password; + Challenge = challenge; + } + + ~ChallengeResponse () + { + if (!_disposed) + Dispose (); + } + + // properties + + public string Password { + set { + if (value == null) + throw new ArgumentNullException ("Password"); + if (_disposed) + throw new ObjectDisposedException ("too late"); + // create Lan Manager password + DES des = DES.Create (); + des.Mode = CipherMode.ECB; + des.Key = PasswordToKey (value, 0); + ICryptoTransform ct = des.CreateEncryptor (); + ct.TransformBlock (magic, 0, 8, _lmpwd, 0); + des.Key = PasswordToKey (value, 7); + ct = des.CreateEncryptor (); + ct.TransformBlock (magic, 0, 8, _lmpwd, 8); + // create NT password + MD4 md4 = MD4.Create (); + byte[] hash = md4.ComputeHash (Encoding.Unicode.GetBytes (value)); + Buffer.BlockCopy (hash, 0, _ntpwd, 0, 16); + } + } + + public byte[] Challenge { + set { + if (value == null) + throw new ArgumentNullException ("Challenge"); + if (_disposed) + throw new ObjectDisposedException ("too late"); + // we don't want the caller to modify the value afterward + _challenge = (byte[]) value.Clone (); + } + } + + public byte[] LM { + get { + if (_disposed) + throw new ObjectDisposedException ("too late"); + + return GetResponse (_lmpwd); + } + } + + public byte[] NT { + get { + if (_disposed) + throw new ObjectDisposedException ("too late"); + + return GetResponse (_ntpwd); + } + } + + // IDisposable method + + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + + private void Dispose (bool disposing) + { + if (!_disposed) { + // cleanup our stuff + Array.Clear (_lmpwd, 0, _lmpwd.Length); + Array.Clear (_ntpwd, 0, _ntpwd.Length); + if (_challenge != null) + Array.Clear (_challenge, 0, _challenge.Length); + _disposed = true; + } + } + + // private methods + + private byte[] GetResponse (byte[] pwd) + { + byte[] response = new byte [24]; + DES des = DES.Create (); + des.Mode = CipherMode.ECB; + des.Key = PrepareDESKey (pwd, 0); + ICryptoTransform ct = des.CreateEncryptor (); + ct.TransformBlock (_challenge, 0, 8, response, 0); + des.Key = PrepareDESKey (pwd, 7); + ct = des.CreateEncryptor (); + ct.TransformBlock (_challenge, 0, 8, response, 8); + des.Key = PrepareDESKey (pwd, 14); + ct = des.CreateEncryptor (); + ct.TransformBlock (_challenge, 0, 8, response, 16); + return response; + } + + private byte[] PrepareDESKey (byte[] key56bits, int position) + { + // convert to 8 bytes + byte[] key = new byte [8]; + key [0] = key56bits [position]; + key [1] = (byte) ((key56bits [position] << 7) | (key56bits [position + 1] >> 1)); + key [2] = (byte) ((key56bits [position + 1] << 6) | (key56bits [position + 2] >> 2)); + key [3] = (byte) ((key56bits [position + 2] << 5) | (key56bits [position + 3] >> 3)); + key [4] = (byte) ((key56bits [position + 3] << 4) | (key56bits [position + 4] >> 4)); + key [5] = (byte) ((key56bits [position + 4] << 3) | (key56bits [position + 5] >> 5)); + key [6] = (byte) ((key56bits [position + 5] << 2) | (key56bits [position + 6] >> 6)); + key [7] = (byte) (key56bits [position + 6] << 1); + return key; + } + + private byte[] PasswordToKey (string password, int position) + { + byte[] key7 = new byte [7]; + int len = Math.Min (password.Length - position, 7); + Encoding.ASCII.GetBytes (password.ToUpper (), position, len, key7, 0); + byte[] key8 = PrepareDESKey (key7, 0); + // cleanup intermediate key material + Array.Clear (key7, 0, key7.Length); + return key8; + } + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/ChangeLog b/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/ChangeLog new file mode 100755 index 00000000000..015965bd4e0 --- /dev/null +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/ChangeLog @@ -0,0 +1,8 @@ +2003-12-01 Sebastien Pouliot + + * ChallengeResponse.cs: New. Implements the NTLM (v1) Challenge Response. + * MessageBase.cs: New. Abstract base class for NTLM messages. + * NtlmFlags.cs: New. All known flags for NTLM. + * Type1Message.cs: New. Negotiation message. + * Type2Message.cs: New. Challenge message. + * Type3Message.cs: New. Authentication message. diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/MessageBase.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/MessageBase.cs new file mode 100755 index 00000000000..39288c26563 --- /dev/null +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/MessageBase.cs @@ -0,0 +1,79 @@ +// +// Mono.Security.Protocol.Ntlm.MessageBase +// abstract class for all NTLM messages +// +// Author: +// Sebastien Pouliot (spouliot@motus.com) +// +// Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com) +// +// References +// a. NTLM Authentication Scheme for HTTP, Ronald Tschalär +// http://www.innovation.ch/java/ntlm.html +// b. The NTLM Authentication Protocol, Copyright © 2003 Eric Glass +// http://davenport.sourceforge.net/ntlm.html +// + +using System; + +namespace Mono.Security.Protocol.Ntlm { + + public abstract class MessageBase { + + static private byte[] header = { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00 }; + + private int _type; + private NtlmFlags _flags; + + protected MessageBase (int messageType) + { + _type = messageType; + } + + public NtlmFlags Flags { + get { return _flags; } + set { _flags = value; } + } + + public int Type { + get { return _type; } + } + + protected byte[] PrepareMessage (int messageSize) + { + byte[] message = new byte [messageSize]; + Buffer.BlockCopy (header, 0, message, 0, 8); + + message [ 8] = (byte) _type; + message [ 9] = (byte)(_type >> 8); + message [10] = (byte)(_type >> 16); + message [11] = (byte)(_type >> 24); + + return message; + } + + protected virtual void Decode (byte[] message) + { + if (message == null) + throw new ArgumentNullException ("message"); + + if (message.Length < 12) + throw new ArgumentOutOfRangeException ("message", message.Length, "minimum is 12 bytes"); + + if (!CheckHeader (message)) + throw new ArgumentException ("Invalid Type" + _type + " message"); + } + + + protected bool CheckHeader (byte[] message) + { + for (int i=0; i < header.Length; i++) { + if (message [i] != header [i]) + return false; + } + return (BitConverter.ToUInt32 (message, 8) == _type); + } + + public abstract byte[] GetBytes (); + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/NtlmFlags.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/NtlmFlags.cs new file mode 100755 index 00000000000..74ed4878157 --- /dev/null +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/NtlmFlags.cs @@ -0,0 +1,43 @@ +// +// Mono.Security.Protocol.Ntlm.NtlmFlags +// +// Author: +// Sebastien Pouliot (spouliot@motus.com) +// +// Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com) +// +// References +// a. NTLM Authentication Scheme for HTTP, Ronald Tschalär +// http://www.innovation.ch/java/ntlm.html +// b. The NTLM Authentication Protocol, Copyright © 2003 Eric Glass +// http://davenport.sourceforge.net/ntlm.html +// + +using System; + +namespace Mono.Security.Protocol.Ntlm { + + [Flags] + public enum NtlmFlags : uint { + // The client sets this flag to indicate that it supports Unicode strings. + NegotiateUnicode = 0x00000001, + // This is set to indicate that the client supports OEM strings. + NegotiateOEM = 0x00000002, + // This requests that the server send the authentication target with the Type 2 reply. + RequestTarget = 0x00000004, + // Indicates that NTLM authentication is supported. + NegotiateNTLM = 0x00000200, + // When set, the client will send with the message the name of the domain in which the workstation has membership. + NegotiateDomainSupplied = 0x00001000, + // Indicates that the client is sending its workstation name with the message. + NegotiateWorkstationSupplied = 0x00002000, + // Indicates that communication between the client and server after authentication should carry a "dummy" signature. + NegotiateAlwaysSign = 0x00008000, + // Indicates that this client supports the NTLM2 signing and sealing scheme; if negotiated, this can also affect the response calculations. + NegotiateNTLM2Key = 0x00080000, + // Indicates that this client supports strong (128-bit) encryption. + Negotiate128 = 0x20000000, + // Indicates that this client supports medium (56-bit) encryption. + Negotiate56 = 0x80000000 + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/Type1Message.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/Type1Message.cs new file mode 100755 index 00000000000..3376456db17 --- /dev/null +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/Type1Message.cs @@ -0,0 +1,106 @@ +// +// Mono.Security.Protocol.Ntlm.Type1Message - Negotiation +// +// Author: +// Sebastien Pouliot (spouliot@motus.com) +// +// Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com) +// +// References +// a. NTLM Authentication Scheme for HTTP, Ronald Tschalär +// http://www.innovation.ch/java/ntlm.html +// b. The NTLM Authentication Protocol, Copyright © 2003 Eric Glass +// http://davenport.sourceforge.net/ntlm.html +// + +using System; +using System.Text; + +namespace Mono.Security.Protocol.Ntlm { + + public class Type1Message : MessageBase { + + //static private byte[] header = { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0xb2, 0x00, 0x00 }; + + private string _host; + private string _domain; + + public Type1Message () : base (1) + { + // default values + _domain = Environment.UserDomainName; + _host = Environment.MachineName; + Flags = (NtlmFlags) 0xb203; + } + + public Type1Message (byte[] message) : base (1) + { + Decode (message); + } + + // properties + + public string Domain { + get { return _domain; } + set { _domain = value; } + } + + public string Host { + get { return _host; } + set { _host = value; } + } + + // methods + + protected override void Decode (byte[] message) + { + base.Decode (message); + + Flags = (NtlmFlags) BitConverter.ToUInt32 (message, 12); + + int dom_len = BitConverter.ToUInt16 (message, 16); + int dom_off = BitConverter.ToUInt16 (message, 20); + _domain = Encoding.ASCII.GetString (message, dom_off, dom_len); + + int host_len = BitConverter.ToUInt16 (message, 24); + _host = Encoding.ASCII.GetString (message, 32, host_len); + } + + public override byte[] GetBytes () + { + short dom_len = (short) _domain.Length; + short host_len = (short) _host.Length; + + byte[] data = PrepareMessage (32 + dom_len + host_len); + + data [12] = (byte) Flags; + data [13] = (byte)((uint)Flags >> 8); + data [14] = (byte)((uint)Flags >> 16); + data [15] = (byte)((uint)Flags >> 24); + + short dom_off = (short)(32 + host_len); + + data [16] = (byte) dom_len; + data [17] = (byte)(dom_len >> 8); + data [18] = data [16]; + data [19] = data [17]; + data [20] = (byte) dom_off; + data [21] = (byte)(dom_off >> 8); + + data [24] = (byte) host_len; + data [25] = (byte)(host_len >> 8); + data [26] = data [24]; + data [27] = data [25]; + data [28] = 0x20; + data [29] = 0x00; + + byte[] host = Encoding.ASCII.GetBytes (_host.ToUpper ()); + Buffer.BlockCopy (host, 0, data, 32, host.Length); + + byte[] domain = Encoding.ASCII.GetBytes (_domain.ToUpper ()); + Buffer.BlockCopy (domain, 0, data, dom_off, domain.Length); + + return data; + } + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/Type2Message.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/Type2Message.cs new file mode 100755 index 00000000000..7e1a513523c --- /dev/null +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/Type2Message.cs @@ -0,0 +1,93 @@ +// +// Mono.Security.Protocol.Ntlm.Type2Message - Challenge +// +// Author: +// Sebastien Pouliot (spouliot@motus.com) +// +// Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com) +// +// References +// a. NTLM Authentication Scheme for HTTP, Ronald Tschalär +// http://www.innovation.ch/java/ntlm.html +// b. The NTLM Authentication Protocol, Copyright © 2003 Eric Glass +// http://davenport.sourceforge.net/ntlm.html +// + +using System; +using System.Security.Cryptography; + +namespace Mono.Security.Protocol.Ntlm { + + public class Type2Message : MessageBase { + + private byte[] _nonce; + private int _options; + + public Type2Message () : base (2) + { + _nonce = new byte [8]; + RandomNumberGenerator rng = RandomNumberGenerator.Create (); + rng.GetBytes (_nonce); + // default values + Flags = (NtlmFlags) 0x8201; + } + + public Type2Message (byte[] message) : base (2) + { + _nonce = new byte [8]; + Decode (message); + } + + ~Type2Message () + { + if (_nonce != null) + Array.Clear (_nonce, 0, _nonce.Length); + } + + // properties + + public byte[] Nonce { + get { return (byte[]) _nonce.Clone (); } + set { + if (value == null) + throw new ArgumentNullException ("Nonce"); + if (value.Length != 8) + throw new ArgumentException ("Invalid Nonce Length"); + _nonce = (byte[]) value.Clone (); + } + } + + // methods + + private void Decode (byte[] message) + { + if (message == null) + throw new ArgumentNullException ("message"); + + if (!CheckHeader (message)) + throw new ArgumentException ("Invalid Type2 message"); + + Flags = (NtlmFlags) BitConverter.ToUInt32 (message, 20); + + Buffer.BlockCopy (message, 24, _nonce, 0, 8); + } + + public override byte[] GetBytes () + { + byte[] data = PrepareMessage (40); + + // message length + short msg_len = (short)data.Length; + data [16] = (byte) msg_len; + data [17] = (byte)(msg_len >> 8); + + // flags + uint f = (uint) Flags; + data [20] = (byte) f; + data [21] = (byte)(f >> 8); + + Buffer.BlockCopy (_nonce, 0, data, 24, _nonce.Length); + return data; + } + } +} diff --git a/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/Type3Message.cs b/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/Type3Message.cs new file mode 100755 index 00000000000..972fa5c3513 --- /dev/null +++ b/mcs/class/Mono.Security/Mono.Security.Protocol.Ntlm/Type3Message.cs @@ -0,0 +1,223 @@ +// +// Mono.Security.Protocol.Ntlm.Type3Message - Authentication +// +// Author: +// Sebastien Pouliot (spouliot@motus.com) +// +// Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com) +// +// References +// a. NTLM Authentication Scheme for HTTP, Ronald Tschalär +// http://www.innovation.ch/java/ntlm.html +// b. The NTLM Authentication Protocol, Copyright © 2003 Eric Glass +// http://davenport.sourceforge.net/ntlm.html +// + +using System; +using System.Text; + +namespace Mono.Security.Protocol.Ntlm { + + public class Type3Message : MessageBase { + + static private byte[] header = { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00 }; + + private byte[] _challenge; + private string _host; + private string _domain; + private string _username; + private string _password; + private byte[] _lm; + private byte[] _nt; + private int _options; + + public Type3Message () : base (3) + { + // default values + _domain = Environment.UserDomainName; + _host = Environment.MachineName; + _username = Environment.UserName; + _options = 0x8201; + } + + public Type3Message (byte[] message) : base (3) + { + Decode (message); + } + + ~Type3Message () + { + if (_challenge != null) + Array.Clear (_challenge, 0, _challenge.Length); + if (_lm != null) + Array.Clear (_lm, 0, _lm.Length); + if (_nt != null) + Array.Clear (_nt, 0, _nt.Length); + } + + // properties + + public byte[] Challenge { + get { + if (_challenge == null) + return null; + return (byte[]) _challenge.Clone (); } + set { + if (value == null) + throw new ArgumentNullException ("Challenge"); + if (value.Length != 8) + throw new ArgumentException ("Invalid Challenge Length"); + _challenge = (byte[]) value.Clone (); + } + } + + public string Domain { + get { return _domain; } + set { _domain = value; } + } + + public string Host { + get { return _host; } + set { _host = value; } + } + + public int Options { + get { return _options; } + set { _options = value; } + } + + public string Password { + get { return _password; } + set { _password = value; } + } + + public string Username { + get { return _username; } + set { _username = value; } + } + + public byte[] LM { + get { return _lm; } + } + + public byte[] NT { + get { return _nt; } + } + + // methods + + private void Decode (byte[] message) + { + if (message == null) + throw new ArgumentNullException ("message"); + + for (int i=0; i < header.Length; i++) { + if (message [i] != header [i]) + throw new ArgumentException ("Invalid Type3 message"); + } + + if (BitConverter.ToUInt16 (message, 56) != message.Length) + throw new ArgumentException ("Invalid Type3 message length"); + + _password = null; + + int dom_len = BitConverter.ToUInt16 (message, 28); + int dom_off = 64; + _domain = Encoding.Unicode.GetString (message, dom_off, dom_len); + + int host_len = BitConverter.ToUInt16 (message, 44); + int host_off = BitConverter.ToUInt16 (message, 48); + _host = Encoding.Unicode.GetString (message, host_off, host_len); + + int user_len = BitConverter.ToUInt16 (message, 36); + int user_off = BitConverter.ToUInt16 (message, 40); + _username = Encoding.Unicode.GetString (message, user_off, user_len); + + _options = BitConverter.ToUInt16 (message, 60); + + _lm = new byte [24]; + int lm_off = BitConverter.ToUInt16 (message, 16); + Buffer.BlockCopy (message, lm_off, _lm, 0, 24); + + _nt = new byte [24]; + int nt_off = BitConverter.ToUInt16 (message, 24); + Buffer.BlockCopy (message, nt_off, _nt, 0, 24); + + if (message.Length >= 64) + Flags = (NtlmFlags) BitConverter.ToUInt32 (message, 60); + } + + public override byte[] GetBytes () + { + byte[] domain = Encoding.Unicode.GetBytes (_domain.ToUpper ()); + byte[] user = Encoding.Unicode.GetBytes (_username); + byte[] host = Encoding.Unicode.GetBytes (_host.ToUpper ()); + + byte[] data = new byte [64 + domain.Length + user.Length + host.Length + 24 + 24]; + Buffer.BlockCopy (header, 0, data, 0, header.Length); + + // LM response + short lmresp_off = (short)(64 + domain.Length + user.Length + host.Length); + data [16] = (byte) lmresp_off; + data [17] = (byte)(lmresp_off >> 8); + + // NT response + short ntresp_off = (short)(lmresp_off + 24); + data [20] = (byte) 0x18; + data [21] = (byte) 0x00; + data [22] = (byte) 0x18; + data [23] = (byte) 0x00; + data [24] = (byte) ntresp_off; + data [25] = (byte)(ntresp_off >> 8); + + // domain + short dom_len = (short)domain.Length; + short dom_off = 64; + data [28] = (byte) dom_len; + data [29] = (byte)(dom_len >> 8); + data [30] = data [28]; + data [31] = data [29]; + data [32] = (byte) dom_off; + data [33] = (byte)(dom_off >> 8); + + // username + short uname_len = (short)user.Length; + short uname_off = (short)(dom_off + dom_len); + data [36] = (byte) uname_len; + data [37] = (byte)(uname_len >> 8); + data [38] = data [36]; + data [39] = data [37]; + data [40] = (byte) uname_off; + data [41] = (byte)(uname_off >> 8); + + // host + short host_len = (short)host.Length; + short host_off = (short)(uname_off + uname_len); + data [44] = (byte) host_len; + data [45] = (byte)(host_len >> 8); + data [46] = data [44]; + data [47] = data [45]; + data [48] = (byte) host_off; + data [49] = (byte)(host_off >> 8); + + // message length + short msg_len = (short)data.Length; + data [56] = (byte) msg_len; + data [57] = (byte)(msg_len >> 8); + + // options flags + data [60] = (byte) _options; + data [61] = (byte)(_options >> 8); + + Buffer.BlockCopy (domain, 0, data, dom_off, domain.Length); + Buffer.BlockCopy (user, 0, data, uname_off, user.Length); + Buffer.BlockCopy (host, 0, data, host_off, host.Length); + + using (ChallengeResponse ntlm = new ChallengeResponse (_password, _challenge)) { + Buffer.BlockCopy (ntlm.LM, 0, data, lmresp_off, 24); + Buffer.BlockCopy (ntlm.NT, 0, data, ntresp_off, 24); + } + return data; + } + } +} -- cgit v1.2.3