context: // 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 WinrtCifs.Netbios;
  using WinrtCifs.Util;
  using WinrtCifs.Util.Sharpen;
  
  namespace WinrtCifs.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)
  				{
  
gt: 					flags |= NtlmsspNegotiateTargetInfo;