merge common implementations and server implementations

This commit is contained in:
Luke Pulverenti
2017-08-16 02:43:41 -04:00
parent e3531534b8
commit bfcd1b520f
389 changed files with 1212 additions and 1626 deletions

View File

@@ -0,0 +1,197 @@
// This code is derived from jcifs smb client library <jcifs at samba dot org>
// Ported by J. Arturo <webmaster at komodosoft dot net>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
namespace SharpCifs.Ntlmssp
{
/// <summary>Flags used during negotiation of NTLMSSP authentication.</summary>
/// <remarks>Flags used during negotiation of NTLMSSP authentication.</remarks>
public abstract class NtlmFlags
{
/// <summary>Indicates whether Unicode strings are supported or used.</summary>
/// <remarks>Indicates whether Unicode strings are supported or used.</remarks>
public const int NtlmsspNegotiateUnicode = unchecked(0x00000001);
/// <summary>Indicates whether OEM strings are supported or used.</summary>
/// <remarks>Indicates whether OEM strings are supported or used.</remarks>
public const int NtlmsspNegotiateOem = unchecked(0x00000002);
/// <summary>
/// Indicates whether the authentication target is requested from
/// the server.
/// </summary>
/// <remarks>
/// Indicates whether the authentication target is requested from
/// the server.
/// </remarks>
public const int NtlmsspRequestTarget = unchecked(0x00000004);
/// <summary>
/// Specifies that communication across the authenticated channel
/// should carry a digital signature (message integrity).
/// </summary>
/// <remarks>
/// Specifies that communication across the authenticated channel
/// should carry a digital signature (message integrity).
/// </remarks>
public const int NtlmsspNegotiateSign = unchecked(0x00000010);
/// <summary>
/// Specifies that communication across the authenticated channel
/// should be encrypted (message confidentiality).
/// </summary>
/// <remarks>
/// Specifies that communication across the authenticated channel
/// should be encrypted (message confidentiality).
/// </remarks>
public const int NtlmsspNegotiateSeal = unchecked(0x00000020);
/// <summary>Indicates datagram authentication.</summary>
/// <remarks>Indicates datagram authentication.</remarks>
public const int NtlmsspNegotiateDatagramStyle = unchecked(0x00000040);
/// <summary>
/// Indicates that the LAN Manager session key should be used for
/// signing and sealing authenticated communication.
/// </summary>
/// <remarks>
/// Indicates that the LAN Manager session key should be used for
/// signing and sealing authenticated communication.
/// </remarks>
public const int NtlmsspNegotiateLmKey = unchecked(0x00000080);
public const int NtlmsspNegotiateNetware = unchecked(0x00000100);
/// <summary>Indicates support for NTLM authentication.</summary>
/// <remarks>Indicates support for NTLM authentication.</remarks>
public const int NtlmsspNegotiateNtlm = unchecked(0x00000200);
/// <summary>
/// Indicates whether the OEM-formatted domain name in which the
/// client workstation has membership is supplied in the Type-1 message.
/// </summary>
/// <remarks>
/// Indicates whether the OEM-formatted domain name in which the
/// client workstation has membership is supplied in the Type-1 message.
/// This is used in the negotation of local authentication.
/// </remarks>
public const int NtlmsspNegotiateOemDomainSupplied = unchecked(0x00001000);
/// <summary>
/// Indicates whether the OEM-formatted workstation name is supplied
/// in the Type-1 message.
/// </summary>
/// <remarks>
/// Indicates whether the OEM-formatted workstation name is supplied
/// in the Type-1 message. This is used in the negotiation of local
/// authentication.
/// </remarks>
public const int NtlmsspNegotiateOemWorkstationSupplied = unchecked(0x00002000);
/// <summary>
/// Sent by the server to indicate that the server and client are
/// on the same machine.
/// </summary>
/// <remarks>
/// Sent by the server to indicate that the server and client are
/// on the same machine. This implies that the server will include
/// a local security context handle in the Type 2 message, for
/// use in local authentication.
/// </remarks>
public const int NtlmsspNegotiateLocalCall = unchecked(0x00004000);
/// <summary>
/// Indicates that authenticated communication between the client
/// and server should carry a "dummy" digital signature.
/// </summary>
/// <remarks>
/// Indicates that authenticated communication between the client
/// and server should carry a "dummy" digital signature.
/// </remarks>
public const int NtlmsspNegotiateAlwaysSign = unchecked(0x00008000);
/// <summary>
/// Sent by the server in the Type 2 message to indicate that the
/// target authentication realm is a domain.
/// </summary>
/// <remarks>
/// Sent by the server in the Type 2 message to indicate that the
/// target authentication realm is a domain.
/// </remarks>
public const int NtlmsspTargetTypeDomain = unchecked(0x00010000);
/// <summary>
/// Sent by the server in the Type 2 message to indicate that the
/// target authentication realm is a server.
/// </summary>
/// <remarks>
/// Sent by the server in the Type 2 message to indicate that the
/// target authentication realm is a server.
/// </remarks>
public const int NtlmsspTargetTypeServer = unchecked(0x00020000);
/// <summary>
/// Sent by the server in the Type 2 message to indicate that the
/// target authentication realm is a share (presumably for share-level
/// authentication).
/// </summary>
/// <remarks>
/// Sent by the server in the Type 2 message to indicate that the
/// target authentication realm is a share (presumably for share-level
/// authentication).
/// </remarks>
public const int NtlmsspTargetTypeShare = unchecked(0x00040000);
/// <summary>
/// Indicates that the NTLM2 signing and sealing scheme should be used
/// for protecting authenticated communications.
/// </summary>
/// <remarks>
/// Indicates that the NTLM2 signing and sealing scheme should be used
/// for protecting authenticated communications. This refers to a
/// particular session security scheme, and is not related to the use
/// of NTLMv2 authentication.
/// </remarks>
public const int NtlmsspNegotiateNtlm2 = unchecked(0x00080000);
public const int NtlmsspRequestInitResponse = unchecked(0x00100000);
public const int NtlmsspRequestAcceptResponse = unchecked(0x00200000);
public const int NtlmsspRequestNonNtSessionKey = unchecked(0x00400000
);
/// <summary>
/// Sent by the server in the Type 2 message to indicate that it is
/// including a Target Information block in the message.
/// </summary>
/// <remarks>
/// Sent by the server in the Type 2 message to indicate that it is
/// including a Target Information block in the message. The Target
/// Information block is used in the calculation of the NTLMv2 response.
/// </remarks>
public const int NtlmsspNegotiateTargetInfo = unchecked(0x00800000);
/// <summary>Indicates that 128-bit encryption is supported.</summary>
/// <remarks>Indicates that 128-bit encryption is supported.</remarks>
public const int NtlmsspNegotiate128 = unchecked(0x20000000);
public const int NtlmsspNegotiateKeyExch = unchecked(0x40000000);
/// <summary>Indicates that 56-bit encryption is supported.</summary>
/// <remarks>Indicates that 56-bit encryption is supported.</remarks>
public const int NtlmsspNegotiate56 = unchecked((int)(0x80000000));
}
}

View File

@@ -0,0 +1,140 @@
// This code is derived from jcifs smb client library <jcifs at samba dot org>
// Ported by J. Arturo <webmaster at komodosoft dot net>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
namespace SharpCifs.Ntlmssp
{
/// <summary>Abstract superclass for all NTLMSSP messages.</summary>
/// <remarks>Abstract superclass for all NTLMSSP messages.</remarks>
public abstract class NtlmMessage : NtlmFlags
{
/// <summary>The NTLMSSP "preamble".</summary>
/// <remarks>The NTLMSSP "preamble".</remarks>
protected internal static readonly byte[] NtlmsspSignature = { unchecked(
(byte)('N')), unchecked((byte)('T')), unchecked((byte)('L')),
unchecked((byte)('M')), unchecked((byte)('S')), unchecked((byte
)('S')), unchecked((byte)('P')), unchecked(0) };
private static readonly string OemEncoding = Config.DefaultOemEncoding;
protected internal static readonly string UniEncoding = "UTF-16LE";
private int _flags;
/// <summary>Returns the flags currently in use for this message.</summary>
/// <remarks>Returns the flags currently in use for this message.</remarks>
/// <returns>
/// An <code>int</code> containing the flags in use for this
/// message.
/// </returns>
public virtual int GetFlags()
{
return _flags;
}
/// <summary>Sets the flags for this message.</summary>
/// <remarks>Sets the flags for this message.</remarks>
/// <param name="flags">The flags for this message.</param>
public virtual void SetFlags(int flags)
{
this._flags = flags;
}
/// <summary>Returns the status of the specified flag.</summary>
/// <remarks>Returns the status of the specified flag.</remarks>
/// <param name="flag">The flag to test (i.e., <code>NTLMSSP_NEGOTIATE_OEM</code>).</param>
/// <returns>A <code>boolean</code> indicating whether the flag is set.</returns>
public virtual bool GetFlag(int flag)
{
return (GetFlags() & flag) != 0;
}
/// <summary>Sets or clears the specified flag.</summary>
/// <remarks>Sets or clears the specified flag.</remarks>
/// <param name="flag">
/// The flag to set/clear (i.e.,
/// <code>NTLMSSP_NEGOTIATE_OEM</code>).
/// </param>
/// <param name="value">
/// Indicates whether to set (<code>true</code>) or
/// clear (<code>false</code>) the specified flag.
/// </param>
public virtual void SetFlag(int flag, bool value)
{
SetFlags(value ? (GetFlags() | flag) : (GetFlags() & (unchecked((int)(0xffffffff)
) ^ flag)));
}
internal static int ReadULong(byte[] src, int index)
{
return (src[index] & unchecked(0xff)) | ((src[index + 1] & unchecked(0xff)) << 8) | ((src[index + 2] & unchecked(0xff)) << 16) | ((src[index
+ 3] & unchecked(0xff)) << 24);
}
internal static int ReadUShort(byte[] src, int index)
{
return (src[index] & unchecked(0xff)) | ((src[index + 1] & unchecked(0xff)) << 8);
}
internal static byte[] ReadSecurityBuffer(byte[] src, int index)
{
int length = ReadUShort(src, index);
int offset = ReadULong(src, index + 4);
byte[] buffer = new byte[length];
Array.Copy(src, offset, buffer, 0, length);
return buffer;
}
internal static void WriteULong(byte[] dest, int offset, int value)
{
dest[offset] = unchecked((byte)(value & unchecked(0xff)));
dest[offset + 1] = unchecked((byte)(value >> 8 & unchecked(0xff)));
dest[offset + 2] = unchecked((byte)(value >> 16 & unchecked(0xff)));
dest[offset + 3] = unchecked((byte)(value >> 24 & unchecked(0xff)));
}
internal static void WriteUShort(byte[] dest, int offset, int value)
{
dest[offset] = unchecked((byte)(value & unchecked(0xff)));
dest[offset + 1] = unchecked((byte)(value >> 8 & unchecked(0xff)));
}
internal static void WriteSecurityBuffer(byte[] dest, int offset, int bodyOffset,
byte[] src)
{
int length = (src != null) ? src.Length : 0;
if (length == 0)
{
return;
}
WriteUShort(dest, offset, length);
WriteUShort(dest, offset + 2, length);
WriteULong(dest, offset + 4, bodyOffset);
Array.Copy(src, 0, dest, bodyOffset, length);
}
internal static string GetOemEncoding()
{
return OemEncoding;
}
/// <summary>Returns the raw byte representation of this message.</summary>
/// <remarks>Returns the raw byte representation of this message.</remarks>
/// <returns>A <code>byte[]</code> containing the raw message material.</returns>
public abstract byte[] ToByteArray();
}
}

View File

@@ -0,0 +1,249 @@
// This code is derived from jcifs smb client library <jcifs at samba dot org>
// Ported by J. Arturo <webmaster at komodosoft dot net>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.IO;
using SharpCifs.Netbios;
using SharpCifs.Util;
using SharpCifs.Util.Sharpen;
namespace SharpCifs.Ntlmssp
{
/// <summary>Represents an NTLMSSP Type-1 message.</summary>
/// <remarks>Represents an NTLMSSP Type-1 message.</remarks>
public class Type1Message : NtlmMessage
{
private static readonly int DefaultFlags;
private static readonly string DefaultDomain;
private static readonly string DefaultWorkstation;
private string _suppliedDomain;
private string _suppliedWorkstation;
static Type1Message()
{
DefaultFlags = NtlmsspNegotiateNtlm | (Config.GetBoolean("jcifs.smb.client.useUnicode"
, true) ? NtlmsspNegotiateUnicode : NtlmsspNegotiateOem);
DefaultDomain = Config.GetProperty("jcifs.smb.client.domain", null);
string defaultWorkstation = null;
try
{
defaultWorkstation = NbtAddress.GetLocalHost().GetHostName();
}
catch (UnknownHostException)
{
}
DefaultWorkstation = defaultWorkstation;
}
/// <summary>
/// Creates a Type-1 message using default values from the current
/// environment.
/// </summary>
/// <remarks>
/// Creates a Type-1 message using default values from the current
/// environment.
/// </remarks>
public Type1Message() : this(GetDefaultFlags(), GetDefaultDomain(), GetDefaultWorkstation
())
{
}
/// <summary>Creates a Type-1 message with the specified parameters.</summary>
/// <remarks>Creates a Type-1 message with the specified parameters.</remarks>
/// <param name="flags">The flags to apply to this message.</param>
/// <param name="suppliedDomain">The supplied authentication domain.</param>
/// <param name="suppliedWorkstation">The supplied workstation name.</param>
public Type1Message(int flags, string suppliedDomain, string suppliedWorkstation)
{
SetFlags(GetDefaultFlags() | flags);
SetSuppliedDomain(suppliedDomain);
if (suppliedWorkstation == null)
{
suppliedWorkstation = GetDefaultWorkstation();
}
SetSuppliedWorkstation(suppliedWorkstation);
}
/// <summary>Creates a Type-1 message using the given raw Type-1 material.</summary>
/// <remarks>Creates a Type-1 message using the given raw Type-1 material.</remarks>
/// <param name="material">The raw Type-1 material used to construct this message.</param>
/// <exception cref="System.IO.IOException">If an error occurs while parsing the material.
/// </exception>
public Type1Message(byte[] material)
{
Parse(material);
}
/// <summary>Returns the supplied authentication domain.</summary>
/// <remarks>Returns the supplied authentication domain.</remarks>
/// <returns>A <code>String</code> containing the supplied domain.</returns>
public virtual string GetSuppliedDomain()
{
return _suppliedDomain;
}
/// <summary>Sets the supplied authentication domain for this message.</summary>
/// <remarks>Sets the supplied authentication domain for this message.</remarks>
/// <param name="suppliedDomain">The supplied domain for this message.</param>
public virtual void SetSuppliedDomain(string suppliedDomain)
{
this._suppliedDomain = suppliedDomain;
}
/// <summary>Returns the supplied workstation name.</summary>
/// <remarks>Returns the supplied workstation name.</remarks>
/// <returns>A <code>String</code> containing the supplied workstation name.</returns>
public virtual string GetSuppliedWorkstation()
{
return _suppliedWorkstation;
}
/// <summary>Sets the supplied workstation name for this message.</summary>
/// <remarks>Sets the supplied workstation name for this message.</remarks>
/// <param name="suppliedWorkstation">The supplied workstation for this message.</param>
public virtual void SetSuppliedWorkstation(string suppliedWorkstation)
{
this._suppliedWorkstation = suppliedWorkstation;
}
public override byte[] ToByteArray()
{
try
{
string suppliedDomain = GetSuppliedDomain();
string suppliedWorkstation = GetSuppliedWorkstation();
int flags = GetFlags();
bool hostInfo = false;
byte[] domain = new byte[0];
if (!string.IsNullOrEmpty(suppliedDomain))
{
hostInfo = true;
flags |= NtlmsspNegotiateOemDomainSupplied;
domain = Runtime.GetBytesForString(suppliedDomain.ToUpper(), GetOemEncoding
());
}
else
{
flags &= (NtlmsspNegotiateOemDomainSupplied ^ unchecked((int)(0xffffffff)));
}
byte[] workstation = new byte[0];
if (!string.IsNullOrEmpty(suppliedWorkstation))
{
hostInfo = true;
flags |= NtlmsspNegotiateOemWorkstationSupplied;
workstation = Runtime.GetBytesForString(suppliedWorkstation.ToUpper(), GetOemEncoding
());
}
else
{
flags &= (NtlmsspNegotiateOemWorkstationSupplied ^ unchecked((int)(0xffffffff
)));
}
byte[] type1 = new byte[hostInfo ? (32 + domain.Length + workstation.Length) : 16
];
Array.Copy(NtlmsspSignature, 0, type1, 0, 8);
WriteULong(type1, 8, 1);
WriteULong(type1, 12, flags);
if (hostInfo)
{
WriteSecurityBuffer(type1, 16, 32, domain);
WriteSecurityBuffer(type1, 24, 32 + domain.Length, workstation);
}
return type1;
}
catch (IOException ex)
{
throw new InvalidOperationException(ex.Message);
}
}
public override string ToString()
{
string suppliedDomain = GetSuppliedDomain();
string suppliedWorkstation = GetSuppliedWorkstation();
return "Type1Message[suppliedDomain=" + (suppliedDomain ?? "null"
) + ",suppliedWorkstation=" + (suppliedWorkstation ?? "null"
) + ",flags=0x" + Hexdump.ToHexString(GetFlags(), 8) + "]";
}
/// <summary>
/// Returns the default flags for a generic Type-1 message in the
/// current environment.
/// </summary>
/// <remarks>
/// Returns the default flags for a generic Type-1 message in the
/// current environment.
/// </remarks>
/// <returns>An <code>int</code> containing the default flags.</returns>
public static int GetDefaultFlags()
{
return DefaultFlags;
}
/// <summary>Returns the default domain from the current environment.</summary>
/// <remarks>Returns the default domain from the current environment.</remarks>
/// <returns>A <code>String</code> containing the default domain.</returns>
public static string GetDefaultDomain()
{
return DefaultDomain;
}
/// <summary>Returns the default workstation from the current environment.</summary>
/// <remarks>Returns the default workstation from the current environment.</remarks>
/// <returns>A <code>String</code> containing the default workstation.</returns>
public static string GetDefaultWorkstation()
{
return DefaultWorkstation;
}
/// <exception cref="System.IO.IOException"></exception>
private void Parse(byte[] material)
{
for (int i = 0; i < 8; i++)
{
if (material[i] != NtlmsspSignature[i])
{
throw new IOException("Not an NTLMSSP message.");
}
}
if (ReadULong(material, 8) != 1)
{
throw new IOException("Not a Type 1 message.");
}
int flags = ReadULong(material, 12);
string suppliedDomain = null;
if ((flags & NtlmsspNegotiateOemDomainSupplied) != 0)
{
byte[] domain = ReadSecurityBuffer(material, 16);
suppliedDomain = Runtime.GetStringForBytes(domain, GetOemEncoding());
}
string suppliedWorkstation = null;
if ((flags & NtlmsspNegotiateOemWorkstationSupplied) != 0)
{
byte[] workstation = ReadSecurityBuffer(material, 24);
suppliedWorkstation = Runtime.GetStringForBytes(workstation, GetOemEncoding
());
}
SetFlags(flags);
SetSuppliedDomain(suppliedDomain);
SetSuppliedWorkstation(suppliedWorkstation);
}
}
}

View File

@@ -0,0 +1,438 @@
// This code is derived from jcifs smb client library <jcifs at samba dot org>
// Ported by J. Arturo <webmaster at komodosoft dot net>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.IO;
using SharpCifs.Netbios;
using SharpCifs.Util;
using SharpCifs.Util.Sharpen;
namespace SharpCifs.Ntlmssp
{
/// <summary>Represents an NTLMSSP Type-2 message.</summary>
/// <remarks>Represents an NTLMSSP Type-2 message.</remarks>
public class Type2Message : NtlmMessage
{
private static readonly int DefaultFlags;
private static readonly string DefaultDomain;
private static readonly byte[] DefaultTargetInformation;
private byte[] _challenge;
private string _target;
private byte[] _context;
private byte[] _targetInformation;
static Type2Message()
{
DefaultFlags = NtlmsspNegotiateNtlm | (Config.GetBoolean("jcifs.smb.client.useUnicode"
, true) ? NtlmsspNegotiateUnicode : NtlmsspNegotiateOem);
DefaultDomain = Config.GetProperty("jcifs.smb.client.domain", null);
byte[] domain = new byte[0];
if (DefaultDomain != null)
{
try
{
domain = Runtime.GetBytesForString(DefaultDomain, UniEncoding);
}
catch (IOException)
{
}
}
int domainLength = domain.Length;
byte[] server = new byte[0];
try
{
string host = NbtAddress.GetLocalHost().GetHostName();
if (host != null)
{
try
{
server = Runtime.GetBytesForString(host, UniEncoding);
}
catch (IOException)
{
}
}
}
catch (UnknownHostException)
{
}
int serverLength = server.Length;
byte[] targetInfo = new byte[(domainLength > 0 ? domainLength + 4 : 0) + (serverLength
> 0 ? serverLength + 4 : 0) + 4];
int offset = 0;
if (domainLength > 0)
{
WriteUShort(targetInfo, offset, 2);
offset += 2;
WriteUShort(targetInfo, offset, domainLength);
offset += 2;
Array.Copy(domain, 0, targetInfo, offset, domainLength);
offset += domainLength;
}
if (serverLength > 0)
{
WriteUShort(targetInfo, offset, 1);
offset += 2;
WriteUShort(targetInfo, offset, serverLength);
offset += 2;
Array.Copy(server, 0, targetInfo, offset, serverLength);
}
DefaultTargetInformation = targetInfo;
}
/// <summary>
/// Creates a Type-2 message using default values from the current
/// environment.
/// </summary>
/// <remarks>
/// Creates a Type-2 message using default values from the current
/// environment.
/// </remarks>
public Type2Message() : this(GetDefaultFlags(), null, null)
{
}
/// <summary>
/// Creates a Type-2 message in response to the given Type-1 message
/// using default values from the current environment.
/// </summary>
/// <remarks>
/// Creates a Type-2 message in response to the given Type-1 message
/// using default values from the current environment.
/// </remarks>
/// <param name="type1">The Type-1 message which this represents a response to.</param>
public Type2Message(Type1Message type1) : this(type1, null, null)
{
}
/// <summary>Creates a Type-2 message in response to the given Type-1 message.</summary>
/// <remarks>Creates a Type-2 message in response to the given Type-1 message.</remarks>
/// <param name="type1">The Type-1 message which this represents a response to.</param>
/// <param name="challenge">The challenge from the domain controller/server.</param>
/// <param name="target">The authentication target.</param>
public Type2Message(Type1Message type1, byte[] challenge, string target) : this(GetDefaultFlags
(type1), challenge, (type1 != null && target == null && type1.GetFlag(NtlmsspRequestTarget
)) ? GetDefaultDomain() : target)
{
}
/// <summary>Creates a Type-2 message with the specified parameters.</summary>
/// <remarks>Creates a Type-2 message with the specified parameters.</remarks>
/// <param name="flags">The flags to apply to this message.</param>
/// <param name="challenge">The challenge from the domain controller/server.</param>
/// <param name="target">The authentication target.</param>
public Type2Message(int flags, byte[] challenge, string target)
{
SetFlags(flags);
SetChallenge(challenge);
SetTarget(target);
if (target != null)
{
SetTargetInformation(GetDefaultTargetInformation());
}
}
/// <summary>Creates a Type-2 message using the given raw Type-2 material.</summary>
/// <remarks>Creates a Type-2 message using the given raw Type-2 material.</remarks>
/// <param name="material">The raw Type-2 material used to construct this message.</param>
/// <exception cref="System.IO.IOException">If an error occurs while parsing the material.
/// </exception>
public Type2Message(byte[] material)
{
Parse(material);
}
/// <summary>Returns the challenge for this message.</summary>
/// <remarks>Returns the challenge for this message.</remarks>
/// <returns>A <code>byte[]</code> containing the challenge.</returns>
public virtual byte[] GetChallenge()
{
return _challenge;
}
/// <summary>Sets the challenge for this message.</summary>
/// <remarks>Sets the challenge for this message.</remarks>
/// <param name="challenge">The challenge from the domain controller/server.</param>
public virtual void SetChallenge(byte[] challenge)
{
this._challenge = challenge;
}
/// <summary>Returns the authentication target.</summary>
/// <remarks>Returns the authentication target.</remarks>
/// <returns>A <code>String</code> containing the authentication target.</returns>
public virtual string GetTarget()
{
return _target;
}
/// <summary>Sets the authentication target.</summary>
/// <remarks>Sets the authentication target.</remarks>
/// <param name="target">The authentication target.</param>
public virtual void SetTarget(string target)
{
this._target = target;
}
/// <summary>Returns the target information block.</summary>
/// <remarks>Returns the target information block.</remarks>
/// <returns>
/// A <code>byte[]</code> containing the target information block.
/// The target information block is used by the client to create an
/// NTLMv2 response.
/// </returns>
public virtual byte[] GetTargetInformation()
{
return _targetInformation;
}
/// <summary>Sets the target information block.</summary>
/// <remarks>
/// Sets the target information block.
/// The target information block is used by the client to create
/// an NTLMv2 response.
/// </remarks>
/// <param name="targetInformation">The target information block.</param>
public virtual void SetTargetInformation(byte[] targetInformation)
{
this._targetInformation = targetInformation;
}
/// <summary>Returns the local security context.</summary>
/// <remarks>Returns the local security context.</remarks>
/// <returns>
/// A <code>byte[]</code> containing the local security
/// context. This is used by the client to negotiate local
/// authentication.
/// </returns>
public virtual byte[] GetContext()
{
return _context;
}
/// <summary>Sets the local security context.</summary>
/// <remarks>
/// Sets the local security context. This is used by the client
/// to negotiate local authentication.
/// </remarks>
/// <param name="context">The local security context.</param>
public virtual void SetContext(byte[] context)
{
this._context = context;
}
public override byte[] ToByteArray()
{
try
{
string targetName = GetTarget();
byte[] challenge = GetChallenge();
byte[] context = GetContext();
byte[] targetInformation = GetTargetInformation();
int flags = GetFlags();
byte[] target = new byte[0];
if ((flags & NtlmsspRequestTarget) != 0)
{
if (!string.IsNullOrEmpty(targetName))
{
target = (flags & NtlmsspNegotiateUnicode) != 0 ? Runtime.GetBytesForString
(targetName, UniEncoding) : Runtime.GetBytesForString(targetName.ToUpper
(), GetOemEncoding());
}
else
{
flags &= (unchecked((int)(0xffffffff)) ^ NtlmsspRequestTarget);
}
}
if (targetInformation != null)
{
flags |= NtlmsspNegotiateTargetInfo;
// empty context is needed for padding when t.i. is supplied.
if (context == null)
{
context = new byte[8];
}
}
int data = 32;
if (context != null)
{
data += 8;
}
if (targetInformation != null)
{
data += 8;
}
byte[] type2 = new byte[data + target.Length + (targetInformation != null ? targetInformation
.Length : 0)];
Array.Copy(NtlmsspSignature, 0, type2, 0, 8);
WriteULong(type2, 8, 2);
WriteSecurityBuffer(type2, 12, data, target);
WriteULong(type2, 20, flags);
Array.Copy(challenge ?? new byte[8], 0, type2, 24, 8);
if (context != null)
{
Array.Copy(context, 0, type2, 32, 8);
}
if (targetInformation != null)
{
WriteSecurityBuffer(type2, 40, data + target.Length, targetInformation);
}
return type2;
}
catch (IOException ex)
{
throw new InvalidOperationException(ex.Message);
}
}
public override string ToString()
{
string target = GetTarget();
byte[] challenge = GetChallenge();
byte[] context = GetContext();
byte[] targetInformation = GetTargetInformation();
return "Type2Message[target=" + target + ",challenge=" + (challenge == null ? "null"
: "<" + challenge.Length + " bytes>") + ",context=" + (context == null ? "null"
: "<" + context.Length + " bytes>") + ",targetInformation=" + (targetInformation
== null ? "null" : "<" + targetInformation.Length + " bytes>") + ",flags=0x" +
Hexdump.ToHexString(GetFlags(), 8) + "]";
}
/// <summary>
/// Returns the default flags for a generic Type-2 message in the
/// current environment.
/// </summary>
/// <remarks>
/// Returns the default flags for a generic Type-2 message in the
/// current environment.
/// </remarks>
/// <returns>An <code>int</code> containing the default flags.</returns>
public static int GetDefaultFlags()
{
return DefaultFlags;
}
/// <summary>
/// Returns the default flags for a Type-2 message created in response
/// to the given Type-1 message in the current environment.
/// </summary>
/// <remarks>
/// Returns the default flags for a Type-2 message created in response
/// to the given Type-1 message in the current environment.
/// </remarks>
/// <returns>An <code>int</code> containing the default flags.</returns>
public static int GetDefaultFlags(Type1Message type1)
{
if (type1 == null)
{
return DefaultFlags;
}
int flags = NtlmsspNegotiateNtlm;
int type1Flags = type1.GetFlags();
flags |= ((type1Flags & NtlmsspNegotiateUnicode) != 0) ? NtlmsspNegotiateUnicode
: NtlmsspNegotiateOem;
if ((type1Flags & NtlmsspRequestTarget) != 0)
{
string domain = GetDefaultDomain();
if (domain != null)
{
flags |= NtlmsspRequestTarget | NtlmsspTargetTypeDomain;
}
}
return flags;
}
/// <summary>Returns the default domain from the current environment.</summary>
/// <remarks>Returns the default domain from the current environment.</remarks>
/// <returns>A <code>String</code> containing the domain.</returns>
public static string GetDefaultDomain()
{
return DefaultDomain;
}
public static byte[] GetDefaultTargetInformation()
{
return DefaultTargetInformation;
}
/// <exception cref="System.IO.IOException"></exception>
private void Parse(byte[] material)
{
for (int i = 0; i < 8; i++)
{
if (material[i] != NtlmsspSignature[i])
{
throw new IOException("Not an NTLMSSP message.");
}
}
if (ReadULong(material, 8) != 2)
{
throw new IOException("Not a Type 2 message.");
}
int flags = ReadULong(material, 20);
SetFlags(flags);
string target = null;
byte[] bytes = ReadSecurityBuffer(material, 12);
if (bytes.Length != 0)
{
target = Runtime.GetStringForBytes(bytes, ((flags & NtlmsspNegotiateUnicode
) != 0) ? UniEncoding : GetOemEncoding());
}
SetTarget(target);
for (int i1 = 24; i1 < 32; i1++)
{
if (material[i1] != 0)
{
byte[] challenge = new byte[8];
Array.Copy(material, 24, challenge, 0, 8);
SetChallenge(challenge);
break;
}
}
int offset = ReadULong(material, 16);
// offset of targetname start
if (offset == 32 || material.Length == 32)
{
return;
}
for (int i2 = 32; i2 < 40; i2++)
{
if (material[i2] != 0)
{
byte[] context = new byte[8];
Array.Copy(material, 32, context, 0, 8);
SetContext(context);
break;
}
}
if (offset == 40 || material.Length == 40)
{
return;
}
bytes = ReadSecurityBuffer(material, 40);
if (bytes.Length != 0)
{
SetTargetInformation(bytes);
}
}
}
}

View File

@@ -0,0 +1,677 @@
// This code is derived from jcifs smb client library <jcifs at samba dot org>
// Ported by J. Arturo <webmaster at komodosoft dot net>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.IO;
using SharpCifs.Netbios;
using SharpCifs.Smb;
using SharpCifs.Util;
using SharpCifs.Util.Sharpen;
namespace SharpCifs.Ntlmssp
{
/// <summary>Represents an NTLMSSP Type-3 message.</summary>
/// <remarks>Represents an NTLMSSP Type-3 message.</remarks>
public class Type3Message : NtlmMessage
{
internal const long MillisecondsBetween1970And1601 = 11644473600000L;
private static readonly int DefaultFlags;
private static readonly string DefaultDomain;
private static readonly string DefaultUser;
private static readonly string DefaultPassword;
private static readonly string DefaultWorkstation;
private static readonly int LmCompatibility;
//private static readonly SecureRandom RANDOM = new SecureRandom();
private byte[] _lmResponse;
private byte[] _ntResponse;
private string _domain;
private string _user;
private string _workstation;
private byte[] _masterKey;
private byte[] _sessionKey;
static Type3Message()
{
DefaultFlags = NtlmsspNegotiateNtlm | (Config.GetBoolean("jcifs.smb.client.useUnicode"
, true) ? NtlmsspNegotiateUnicode : NtlmsspNegotiateOem);
DefaultDomain = Config.GetProperty("jcifs.smb.client.domain", null);
DefaultUser = Config.GetProperty("jcifs.smb.client.username", null);
DefaultPassword = Config.GetProperty("jcifs.smb.client.password", null);
string defaultWorkstation = null;
try
{
defaultWorkstation = NbtAddress.GetLocalHost().GetHostName();
}
catch (UnknownHostException)
{
}
DefaultWorkstation = defaultWorkstation;
LmCompatibility = Config.GetInt("jcifs.smb.lmCompatibility", 3);
}
/// <summary>
/// Creates a Type-3 message using default values from the current
/// environment.
/// </summary>
/// <remarks>
/// Creates a Type-3 message using default values from the current
/// environment.
/// </remarks>
public Type3Message()
{
SetFlags(GetDefaultFlags());
SetDomain(GetDefaultDomain());
SetUser(GetDefaultUser());
SetWorkstation(GetDefaultWorkstation());
}
/// <summary>
/// Creates a Type-3 message in response to the given Type-2 message
/// using default values from the current environment.
/// </summary>
/// <remarks>
/// Creates a Type-3 message in response to the given Type-2 message
/// using default values from the current environment.
/// </remarks>
/// <param name="type2">The Type-2 message which this represents a response to.</param>
public Type3Message(Type2Message type2)
{
SetFlags(GetDefaultFlags(type2));
SetWorkstation(GetDefaultWorkstation());
string domain = GetDefaultDomain();
SetDomain(domain);
string user = GetDefaultUser();
SetUser(user);
string password = GetDefaultPassword();
switch (LmCompatibility)
{
case 0:
case 1:
{
SetLmResponse(GetLMResponse(type2, password));
SetNtResponse(GetNTResponse(type2, password));
break;
}
case 2:
{
byte[] nt = GetNTResponse(type2, password);
SetLmResponse(nt);
SetNtResponse(nt);
break;
}
case 3:
case 4:
case 5:
{
byte[] clientChallenge = new byte[8];
//RANDOM.NextBytes(clientChallenge);
SetLmResponse(GetLMv2Response(type2, domain, user, password, clientChallenge));
break;
}
default:
{
SetLmResponse(GetLMResponse(type2, password));
SetNtResponse(GetNTResponse(type2, password));
break;
}
}
}
/// <summary>Creates a Type-3 message in response to the given Type-2 message.</summary>
/// <remarks>Creates a Type-3 message in response to the given Type-2 message.</remarks>
/// <param name="type2">The Type-2 message which this represents a response to.</param>
/// <param name="password">The password to use when constructing the response.</param>
/// <param name="domain">The domain in which the user has an account.</param>
/// <param name="user">The username for the authenticating user.</param>
/// <param name="workstation">
/// The workstation from which authentication is
/// taking place.
/// </param>
public Type3Message(Type2Message type2, string password, string domain, string user
, string workstation, int flags)
{
SetFlags(flags | GetDefaultFlags(type2));
if (workstation == null)
{
workstation = GetDefaultWorkstation();
}
SetWorkstation(workstation);
SetDomain(domain);
SetUser(user);
switch (LmCompatibility)
{
case 0:
case 1:
{
if ((GetFlags() & NtlmsspNegotiateNtlm2) == 0)
{
SetLmResponse(GetLMResponse(type2, password));
SetNtResponse(GetNTResponse(type2, password));
}
else
{
// NTLM2 Session Response
byte[] clientChallenge = new byte[24];
//RANDOM.NextBytes(clientChallenge);
Arrays.Fill(clientChallenge, 8, 24, unchecked((byte)unchecked(0x00)));
// NTLMv1 w/ NTLM2 session sec and key exch all been verified with a debug build of smbclient
byte[] responseKeyNt = NtlmPasswordAuthentication.NtowFv1(password);
byte[] ntlm2Response = NtlmPasswordAuthentication.GetNtlm2Response(responseKeyNt,
type2.GetChallenge(), clientChallenge);
SetLmResponse(clientChallenge);
SetNtResponse(ntlm2Response);
if ((GetFlags() & NtlmsspNegotiateSign) == NtlmsspNegotiateSign)
{
byte[] sessionNonce = new byte[16];
Array.Copy(type2.GetChallenge(), 0, sessionNonce, 0, 8);
Array.Copy(clientChallenge, 0, sessionNonce, 8, 8);
Md4 md4 = new Md4();
md4.Update(responseKeyNt);
byte[] userSessionKey = md4.Digest();
Hmact64 hmac = new Hmact64(userSessionKey);
hmac.Update(sessionNonce);
byte[] ntlm2SessionKey = hmac.Digest();
if ((GetFlags() & NtlmsspNegotiateKeyExch) != 0)
{
_masterKey = new byte[16];
//RANDOM.NextBytes(masterKey);
byte[] exchangedKey = new byte[16];
Rc4 rc4 = new Rc4(ntlm2SessionKey);
rc4.Update(_masterKey, 0, 16, exchangedKey, 0);
SetSessionKey(exchangedKey);
}
else
{
_masterKey = ntlm2SessionKey;
SetSessionKey(_masterKey);
}
}
}
break;
}
case 2:
{
byte[] nt = GetNTResponse(type2, password);
SetLmResponse(nt);
SetNtResponse(nt);
break;
}
case 3:
case 4:
case 5:
{
byte[] responseKeyNt1 = NtlmPasswordAuthentication.NtowFv2(domain, user, password
);
byte[] clientChallenge1 = new byte[8];
//RANDOM.NextBytes(clientChallenge_1);
SetLmResponse(GetLMv2Response(type2, domain, user, password, clientChallenge1));
byte[] clientChallenge2 = new byte[8];
//RANDOM.NextBytes(clientChallenge2);
SetNtResponse(GetNtlMv2Response(type2, responseKeyNt1, clientChallenge2));
if ((GetFlags() & NtlmsspNegotiateSign) == NtlmsspNegotiateSign)
{
Hmact64 hmac = new Hmact64(responseKeyNt1);
hmac.Update(_ntResponse, 0, 16);
// only first 16 bytes of ntResponse
byte[] userSessionKey = hmac.Digest();
if ((GetFlags() & NtlmsspNegotiateKeyExch) != 0)
{
_masterKey = new byte[16];
//RANDOM.NextBytes(masterKey);
byte[] exchangedKey = new byte[16];
Rc4 rc4 = new Rc4(userSessionKey);
rc4.Update(_masterKey, 0, 16, exchangedKey, 0);
SetSessionKey(exchangedKey);
}
else
{
_masterKey = userSessionKey;
SetSessionKey(_masterKey);
}
}
break;
}
default:
{
SetLmResponse(GetLMResponse(type2, password));
SetNtResponse(GetNTResponse(type2, password));
break;
}
}
}
/// <summary>Creates a Type-3 message with the specified parameters.</summary>
/// <remarks>Creates a Type-3 message with the specified parameters.</remarks>
/// <param name="flags">The flags to apply to this message.</param>
/// <param name="lmResponse">The LanManager/LMv2 response.</param>
/// <param name="ntResponse">The NT/NTLMv2 response.</param>
/// <param name="domain">The domain in which the user has an account.</param>
/// <param name="user">The username for the authenticating user.</param>
/// <param name="workstation">
/// The workstation from which authentication is
/// taking place.
/// </param>
public Type3Message(int flags, byte[] lmResponse, byte[] ntResponse, string domain
, string user, string workstation)
{
SetFlags(flags);
SetLmResponse(lmResponse);
SetNtResponse(ntResponse);
SetDomain(domain);
SetUser(user);
SetWorkstation(workstation);
}
/// <summary>Creates a Type-3 message using the given raw Type-3 material.</summary>
/// <remarks>Creates a Type-3 message using the given raw Type-3 material.</remarks>
/// <param name="material">The raw Type-3 material used to construct this message.</param>
/// <exception cref="System.IO.IOException">If an error occurs while parsing the material.
/// </exception>
public Type3Message(byte[] material)
{
Parse(material);
}
/// <summary>Returns the LanManager/LMv2 response.</summary>
/// <remarks>Returns the LanManager/LMv2 response.</remarks>
/// <returns>A <code>byte[]</code> containing the LanManager response.</returns>
public virtual byte[] GetLMResponse()
{
return _lmResponse;
}
/// <summary>Sets the LanManager/LMv2 response for this message.</summary>
/// <remarks>Sets the LanManager/LMv2 response for this message.</remarks>
/// <param name="lmResponse">The LanManager response.</param>
public virtual void SetLmResponse(byte[] lmResponse)
{
this._lmResponse = lmResponse;
}
/// <summary>Returns the NT/NTLMv2 response.</summary>
/// <remarks>Returns the NT/NTLMv2 response.</remarks>
/// <returns>A <code>byte[]</code> containing the NT/NTLMv2 response.</returns>
public virtual byte[] GetNTResponse()
{
return _ntResponse;
}
/// <summary>Sets the NT/NTLMv2 response for this message.</summary>
/// <remarks>Sets the NT/NTLMv2 response for this message.</remarks>
/// <param name="ntResponse">The NT/NTLMv2 response.</param>
public virtual void SetNtResponse(byte[] ntResponse)
{
this._ntResponse = ntResponse;
}
/// <summary>Returns the domain in which the user has an account.</summary>
/// <remarks>Returns the domain in which the user has an account.</remarks>
/// <returns>A <code>String</code> containing the domain for the user.</returns>
public virtual string GetDomain()
{
return _domain;
}
/// <summary>Sets the domain for this message.</summary>
/// <remarks>Sets the domain for this message.</remarks>
/// <param name="domain">The domain.</param>
public virtual void SetDomain(string domain)
{
this._domain = domain;
}
/// <summary>Returns the username for the authenticating user.</summary>
/// <remarks>Returns the username for the authenticating user.</remarks>
/// <returns>A <code>String</code> containing the user for this message.</returns>
public virtual string GetUser()
{
return _user;
}
/// <summary>Sets the user for this message.</summary>
/// <remarks>Sets the user for this message.</remarks>
/// <param name="user">The user.</param>
public virtual void SetUser(string user)
{
this._user = user;
}
/// <summary>Returns the workstation from which authentication is being performed.</summary>
/// <remarks>Returns the workstation from which authentication is being performed.</remarks>
/// <returns>A <code>String</code> containing the workstation.</returns>
public virtual string GetWorkstation()
{
return _workstation;
}
/// <summary>Sets the workstation for this message.</summary>
/// <remarks>Sets the workstation for this message.</remarks>
/// <param name="workstation">The workstation.</param>
public virtual void SetWorkstation(string workstation)
{
this._workstation = workstation;
}
/// <summary>
/// The real session key if the regular session key is actually
/// the encrypted version used for key exchange.
/// </summary>
/// <remarks>
/// The real session key if the regular session key is actually
/// the encrypted version used for key exchange.
/// </remarks>
/// <returns>A <code>byte[]</code> containing the session key.</returns>
public virtual byte[] GetMasterKey()
{
return _masterKey;
}
/// <summary>Returns the session key.</summary>
/// <remarks>Returns the session key.</remarks>
/// <returns>A <code>byte[]</code> containing the session key.</returns>
public virtual byte[] GetSessionKey()
{
return _sessionKey;
}
/// <summary>Sets the session key.</summary>
/// <remarks>Sets the session key.</remarks>
/// <param name="sessionKey">The session key.</param>
public virtual void SetSessionKey(byte[] sessionKey)
{
this._sessionKey = sessionKey;
}
public override byte[] ToByteArray()
{
try
{
int flags = GetFlags();
bool unicode = (flags & NtlmsspNegotiateUnicode) != 0;
string oem = unicode ? null : GetOemEncoding();
string domainName = GetDomain();
byte[] domain = null;
if (!string.IsNullOrEmpty(domainName))
{
domain = unicode ? Runtime.GetBytesForString(domainName, UniEncoding) :
Runtime.GetBytesForString(domainName, oem);
}
int domainLength = (domain != null) ? domain.Length : 0;
string userName = GetUser();
byte[] user = null;
if (!string.IsNullOrEmpty(userName))
{
user = unicode ? Runtime.GetBytesForString(userName, UniEncoding) : Runtime.GetBytesForString
(userName.ToUpper(), oem);
}
int userLength = (user != null) ? user.Length : 0;
string workstationName = GetWorkstation();
byte[] workstation = null;
if (!string.IsNullOrEmpty(workstationName))
{
workstation = unicode ? Runtime.GetBytesForString(workstationName, UniEncoding
) : Runtime.GetBytesForString(workstationName.ToUpper(), oem);
}
int workstationLength = (workstation != null) ? workstation.Length : 0;
byte[] lmResponse = GetLMResponse();
int lmLength = (lmResponse != null) ? lmResponse.Length : 0;
byte[] ntResponse = GetNTResponse();
int ntLength = (ntResponse != null) ? ntResponse.Length : 0;
byte[] sessionKey = GetSessionKey();
int keyLength = (sessionKey != null) ? sessionKey.Length : 0;
byte[] type3 = new byte[64 + domainLength + userLength + workstationLength + lmLength
+ ntLength + keyLength];
Array.Copy(NtlmsspSignature, 0, type3, 0, 8);
WriteULong(type3, 8, 3);
int offset = 64;
WriteSecurityBuffer(type3, 12, offset, lmResponse);
offset += lmLength;
WriteSecurityBuffer(type3, 20, offset, ntResponse);
offset += ntLength;
WriteSecurityBuffer(type3, 28, offset, domain);
offset += domainLength;
WriteSecurityBuffer(type3, 36, offset, user);
offset += userLength;
WriteSecurityBuffer(type3, 44, offset, workstation);
offset += workstationLength;
WriteSecurityBuffer(type3, 52, offset, sessionKey);
WriteULong(type3, 60, flags);
return type3;
}
catch (IOException ex)
{
throw new InvalidOperationException(ex.Message);
}
}
public override string ToString()
{
string user = GetUser();
string domain = GetDomain();
string workstation = GetWorkstation();
byte[] lmResponse = GetLMResponse();
byte[] ntResponse = GetNTResponse();
byte[] sessionKey = GetSessionKey();
return "Type3Message[domain=" + domain + ",user=" + user + ",workstation=" + workstation
+ ",lmResponse=" + (lmResponse == null ? "null" : "<" + lmResponse.Length + " bytes>"
) + ",ntResponse=" + (ntResponse == null ? "null" : "<" + ntResponse.Length + " bytes>"
) + ",sessionKey=" + (sessionKey == null ? "null" : "<" + sessionKey.Length + " bytes>"
) + ",flags=0x" + Hexdump.ToHexString(GetFlags(), 8) + "]";
}
/// <summary>
/// Returns the default flags for a generic Type-3 message in the
/// current environment.
/// </summary>
/// <remarks>
/// Returns the default flags for a generic Type-3 message in the
/// current environment.
/// </remarks>
/// <returns>An <code>int</code> containing the default flags.</returns>
public static int GetDefaultFlags()
{
return DefaultFlags;
}
/// <summary>
/// Returns the default flags for a Type-3 message created in response
/// to the given Type-2 message in the current environment.
/// </summary>
/// <remarks>
/// Returns the default flags for a Type-3 message created in response
/// to the given Type-2 message in the current environment.
/// </remarks>
/// <returns>An <code>int</code> containing the default flags.</returns>
public static int GetDefaultFlags(Type2Message type2)
{
if (type2 == null)
{
return DefaultFlags;
}
int flags = NtlmsspNegotiateNtlm;
flags |= ((type2.GetFlags() & NtlmsspNegotiateUnicode) != 0) ? NtlmsspNegotiateUnicode
: NtlmsspNegotiateOem;
return flags;
}
/// <summary>
/// Constructs the LanManager response to the given Type-2 message using
/// the supplied password.
/// </summary>
/// <remarks>
/// Constructs the LanManager response to the given Type-2 message using
/// the supplied password.
/// </remarks>
/// <param name="type2">The Type-2 message.</param>
/// <param name="password">The password.</param>
/// <returns>A <code>byte[]</code> containing the LanManager response.</returns>
public static byte[] GetLMResponse(Type2Message type2, string password)
{
if (type2 == null || password == null)
{
return null;
}
return NtlmPasswordAuthentication.GetPreNtlmResponse(password, type2.GetChallenge
());
}
public static byte[] GetLMv2Response(Type2Message type2, string domain, string user
, string password, byte[] clientChallenge)
{
if (type2 == null || domain == null || user == null || password == null || clientChallenge
== null)
{
return null;
}
return NtlmPasswordAuthentication.GetLMv2Response(domain, user, password, type2.GetChallenge
(), clientChallenge);
}
public static byte[] GetNtlMv2Response(Type2Message type2, byte[] responseKeyNt,
byte[] clientChallenge)
{
if (type2 == null || responseKeyNt == null || clientChallenge == null)
{
return null;
}
long nanos1601 = (Runtime.CurrentTimeMillis() + MillisecondsBetween1970And1601
) * 10000L;
return NtlmPasswordAuthentication.GetNtlMv2Response(responseKeyNt, type2.GetChallenge
(), clientChallenge, nanos1601, type2.GetTargetInformation());
}
/// <summary>
/// Constructs the NT response to the given Type-2 message using
/// the supplied password.
/// </summary>
/// <remarks>
/// Constructs the NT response to the given Type-2 message using
/// the supplied password.
/// </remarks>
/// <param name="type2">The Type-2 message.</param>
/// <param name="password">The password.</param>
/// <returns>A <code>byte[]</code> containing the NT response.</returns>
public static byte[] GetNTResponse(Type2Message type2, string password)
{
if (type2 == null || password == null)
{
return null;
}
return NtlmPasswordAuthentication.GetNtlmResponse(password, type2.GetChallenge());
}
/// <summary>Returns the default domain from the current environment.</summary>
/// <remarks>Returns the default domain from the current environment.</remarks>
/// <returns>The default domain.</returns>
public static string GetDefaultDomain()
{
return DefaultDomain;
}
/// <summary>Returns the default user from the current environment.</summary>
/// <remarks>Returns the default user from the current environment.</remarks>
/// <returns>The default user.</returns>
public static string GetDefaultUser()
{
return DefaultUser;
}
/// <summary>Returns the default password from the current environment.</summary>
/// <remarks>Returns the default password from the current environment.</remarks>
/// <returns>The default password.</returns>
public static string GetDefaultPassword()
{
return DefaultPassword;
}
/// <summary>Returns the default workstation from the current environment.</summary>
/// <remarks>Returns the default workstation from the current environment.</remarks>
/// <returns>The default workstation.</returns>
public static string GetDefaultWorkstation()
{
return DefaultWorkstation;
}
/// <exception cref="System.IO.IOException"></exception>
private void Parse(byte[] material)
{
for (int i = 0; i < 8; i++)
{
if (material[i] != NtlmsspSignature[i])
{
throw new IOException("Not an NTLMSSP message.");
}
}
if (ReadULong(material, 8) != 3)
{
throw new IOException("Not a Type 3 message.");
}
byte[] lmResponse = ReadSecurityBuffer(material, 12);
int lmResponseOffset = ReadULong(material, 16);
byte[] ntResponse = ReadSecurityBuffer(material, 20);
int ntResponseOffset = ReadULong(material, 24);
byte[] domain = ReadSecurityBuffer(material, 28);
int domainOffset = ReadULong(material, 32);
byte[] user = ReadSecurityBuffer(material, 36);
int userOffset = ReadULong(material, 40);
byte[] workstation = ReadSecurityBuffer(material, 44);
int workstationOffset = ReadULong(material, 48);
int flags;
string charset;
byte[] _sessionKey = null;
if (lmResponseOffset == 52 || ntResponseOffset == 52 || domainOffset == 52 || userOffset
== 52 || workstationOffset == 52)
{
flags = NtlmsspNegotiateNtlm | NtlmsspNegotiateOem;
charset = GetOemEncoding();
}
else
{
_sessionKey = ReadSecurityBuffer(material, 52);
flags = ReadULong(material, 60);
charset = ((flags & NtlmsspNegotiateUnicode) != 0) ? UniEncoding : GetOemEncoding
();
}
SetSessionKey(_sessionKey);
SetFlags(flags);
SetLmResponse(lmResponse);
SetNtResponse(ntResponse);
SetDomain(Runtime.GetStringForBytes(domain, charset));
SetUser(Runtime.GetStringForBytes(user, charset));
SetWorkstation(Runtime.GetStringForBytes(workstation, charset));
}
}
}