You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			274 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C#
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			274 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C#
		
	
	
		
			Executable File
		
	
	
	
	
| using System;
 | |
| using System.IO;
 | |
| using System.Net;
 | |
| using System.Net.NetworkInformation;
 | |
| using System.Security.Cryptography;
 | |
| using System.Text;
 | |
| using Mono.Security;
 | |
| using Mono.Security.Protocol.Ntlm;
 | |
| 
 | |
| namespace System.ServiceModel.Security
 | |
| {
 | |
| 	internal abstract class SspiSession
 | |
| 	{
 | |
| 		internal static readonly byte [] NtlmSSP = new byte [] {
 | |
| 			0x4E, 0x54, 0x4C, 0x4D, 0x53, 0x53, 0x50, 0x00};
 | |
| 
 | |
| 		public long Challenge, Context, ClientOSVersion, ServerOSVersion;
 | |
| 		public string ServerName, DomainName, DnsHostName, DnsDomainName;
 | |
| 
 | |
| 		public bool Verify (byte [] expected, byte [] actual, int offset, int length)
 | |
| 		{
 | |
| 			if (expected.Length != length)
 | |
| 				return false;
 | |
| 			for (int i = 0; i < length; i++)
 | |
| 				if (expected [i] != actual [i + offset])
 | |
| 					return false;
 | |
| 			return true;
 | |
| 		}
 | |
| 
 | |
| 		public SspiSecurityBufferStruct ReadSecurityBuffer (BinaryReader reader)
 | |
| 		{
 | |
| 			return new SspiSecurityBufferStruct (
 | |
| 				reader.ReadInt16 (),
 | |
| 				reader.ReadInt16 (),
 | |
| 				reader.ReadInt32 ());
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	internal struct SspiSecurityBufferStruct
 | |
| 	{
 | |
| 		public SspiSecurityBufferStruct (short length, short allocatedSpace, int offset)
 | |
| 		{
 | |
| 			Length = length;
 | |
| 			AllocatedSpace = allocatedSpace;
 | |
| 			Offset = offset;
 | |
| 		}
 | |
| 
 | |
| 		public readonly short Length;
 | |
| 		public readonly short AllocatedSpace;
 | |
| 		public readonly int Offset;
 | |
| 	}
 | |
| 
 | |
| 	internal class SspiClientSession : SspiSession
 | |
| 	{
 | |
| 		Type2Message type2;
 | |
| 		Type3Message type3;
 | |
| 
 | |
| 		// Class(60) {
 | |
| 		//   OID(spnego),
 | |
| 		//   Class(A0) {
 | |
| 		//     Class(30) {
 | |
| 		//       Class(A0) {
 | |
| 		//         Class(30) { OID,OID,OID} },
 | |
| 		//       Class(A2) { OctetStream } } } }
 | |
| 		public byte [] ProcessSpnegoInitialContextTokenRequest ()
 | |
| 		{
 | |
| 			Type1Message type1 = new Type1Message (NtlmVersion.Version3);
 | |
| 			type1.Flags = unchecked ((NtlmFlags) 0xE21882B7);
 | |
| 			type1.Domain = "WORKGROUP"; // FIXME: remove it
 | |
| 
 | |
| 			ASN1 asn = new ASN1 (0x60);
 | |
| 			ASN1 asn2 = new ASN1 (0xA0);
 | |
| 			ASN1 asn21 = new ASN1 (0x30);
 | |
| 			ASN1 asn211 = new ASN1 (0xA0);
 | |
| 			ASN1 asn2111 = new ASN1 (0x30);
 | |
| 			asn211.Add (asn2111);
 | |
| 			asn2111.Add (ASN1Convert.FromOid (Constants.OidNtlmSsp));
 | |
| 			asn2111.Add (ASN1Convert.FromOid (Constants.OidKerberos5));
 | |
| 			asn2111.Add (ASN1Convert.FromOid (Constants.OidMIT));
 | |
| 			ASN1 asn212 = new ASN1 (0xA2);
 | |
| 			ASN1 asn2121 = new ASN1 (0x4);
 | |
| 			asn2121.Value = type1.GetBytes ();
 | |
| 			asn212.Add (asn2121);
 | |
| 			asn21.Add (asn211);
 | |
| 			asn21.Add (asn212);
 | |
| 			asn2.Add (asn21);
 | |
| 			asn.Add (ASN1Convert.FromOid (Constants.OidSpnego));
 | |
| 			asn.Add (asn2);
 | |
| 			return asn.GetBytes ();
 | |
| 		}
 | |
| 
 | |
| 		// Example buffer:
 | |
| 		// A18181 307F A003
 | |
| 		//   0A0101
 | |
| 		//   A10C 060A2B06010401823702020A
 | |
| 		//   A26A 0468 NTLM
 | |
| 		//   NTLM = 4E544C4D53535000 0200000004000400 3800000035829AE2
 | |
| 		//    0D1A7FF0F171F339 0000000000000000 2C002C003C000000
 | |
| 		//    0501280A0000000F 5000430002000400 5000430001000400
 | |
| 		//    5000430004000400 5000430003000400 5000430006000400
 | |
| 		//    0100000000000000
 | |
| 		public void ProcessSpnegoInitialContextTokenResponse (byte [] raw)
 | |
| 		{
 | |
| 			ASN1 asn1 = new ASN1 (raw);
 | |
| 			// FIXME: check OIDs and structure
 | |
| 			ProcessMessageType2 (asn1 [0] [2] [0].Value);
 | |
| 		}
 | |
| 
 | |
| 		// Class { Class { Class { OctetStream } } }
 | |
| 		public byte [] ProcessSpnegoProcessContextToken (string user, string pass)
 | |
| 		{
 | |
| 			ASN1 asn = new ASN1 (0xA1);
 | |
| 			ASN1 asn2 = new ASN1 (0x30);
 | |
| 			ASN1 asn3 = new ASN1 (0xA2);
 | |
| 			asn3.Add (new ASN1 (0x04, ProcessMessageType3 (user, pass)));
 | |
| 			asn2.Add (asn3);
 | |
| 			asn.Add (asn2);
 | |
| 			return asn.GetBytes ();
 | |
| 		}
 | |
| 
 | |
| 		public byte [] ProcessMessageType1 ()
 | |
| 		{
 | |
| 			Type1Message type1 = new Type1Message (NtlmVersion.Version3);
 | |
| 			type1.Flags = unchecked ((NtlmFlags) 0xE21882B7);
 | |
| 			return type1.GetBytes ();
 | |
| 		}
 | |
| 
 | |
| 		string TargetName;
 | |
| 
 | |
| 		public void ProcessMessageType2 (byte [] raw)
 | |
| 		{
 | |
| 			type2 = new Type2Message (raw);
 | |
| 		}
 | |
| 
 | |
| 		public byte [] ProcessMessageType3 (string user, string password)
 | |
| 		{
 | |
| 			TargetName = Environment.MachineName;
 | |
| 			ServerName = Environment.MachineName;
 | |
| 			// FIXME
 | |
| 			DomainName = ServerName;// IPGlobalProperties.GetIPGlobalProperties ().DomainName;
 | |
| 			DnsHostName = Dns.GetHostName ();
 | |
| 			DnsDomainName = DnsHostName; // FIXME
 | |
| 
 | |
| 			type3 = new Type3Message (NtlmVersion.Version3);
 | |
| 			type3.Flags = (NtlmFlags) (unchecked ((int) 0xE2188235));
 | |
| 			type3.Domain = DomainName;
 | |
| 			type3.Host = DnsHostName;
 | |
| 			type3.Challenge = type2.Nonce;
 | |
| 			type3.Username = user;
 | |
| 			type3.Password = password;
 | |
| 
 | |
| 			return type3.GetBytes ();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	internal class SspiServerSession : SspiSession
 | |
| 	{
 | |
| 		public string TargetName;
 | |
| 		public long SuppliedDomain, SuppliedWorkstation;
 | |
| 		Type1Message type1;
 | |
| 		Type2Message type2;
 | |
| 		Type3Message type3;
 | |
| 
 | |
| 		// Example buffer:
 | |
| 		// 6069 0606 2B0601050502 A05F 305D A024 3022
 | |
| 		//	  060A 2B06010401823702020A
 | |
| 		//	  0609 2A864882F712010202
 | |
| 		//	  0609 2A864886F712010202
 | |
| 		// A235 0433 NTLM
 | |
| 		// NTLM = 4E544C4D53535000 01000000 B7B218E2 090009002A000000
 | |
| 		//  0200020028000000 0501280A0000000F 5043 574F524B47524F5550
 | |
| 		public void ProcessSpnegoInitialContextTokenRequest (byte [] raw)
 | |
| 		{
 | |
| 			ASN1 asn1 = new ASN1 (raw);
 | |
| 			// FIXME: check OIDs
 | |
| 			ProcessMessageType1 (asn1 [1] [0] [1] [0].Value);
 | |
| 		}
 | |
| 
 | |
| 		// Class {
 | |
| 		//   Class {
 | |
| 		//     Class { Enum },
 | |
| 		//     Class { OID(NTLMSSP) },
 | |
| 		//     Class { OctetStream } } }
 | |
| 		public byte [] ProcessSpnegoInitialContextTokenResponse ()
 | |
| 		{
 | |
| 			ASN1 top = new ASN1 (0xA1);
 | |
| 			ASN1 asn = new ASN1 (0x30);
 | |
| 			ASN1 asn1 = new ASN1 (0xA0);
 | |
| 			// FIXME: what is this enum?
 | |
| 			asn1.Add (new ASN1 (0x0A, new byte [] {1})); // Enum whatever
 | |
| 			ASN1 asn2 = new ASN1 (0xA1);
 | |
| 			asn2.Add (ASN1Convert.FromOid (Constants.OidNtlmSsp));
 | |
| 			ASN1 asn3 = new ASN1 (0xA2);
 | |
| 			asn3.Add (new ASN1 (0x04, ProcessMessageType2 ()));
 | |
| 			asn.Add (asn1);
 | |
| 			asn.Add (asn2);
 | |
| 			asn.Add (asn3);
 | |
| 			top.Add (asn);
 | |
| 			return top.GetBytes ();
 | |
| 		}
 | |
| 
 | |
| 		// Example buffer:
 | |
| 		// A181A7
 | |
| 		//   3081A4
 | |
| 		//     A281A1
 | |
| 		//       04819E
 | |
| 		// 4E544C4D53535000 03000000 
 | |
| 		// 180018005E000000 1800180076000000 0400040048000000
 | |
| 		// 0E000E004C000000 040004005A000000 100010008E000000
 | |
| 		// 358218E2 0501280A0000000F
 | |
| 		// 50004300 6100740073007500730068006900 50004300
 | |
| 		// [8 bytes LM] [16 bytes of 0s]
 | |
| 		// [24 bytes of NTLM]
 | |
| 		// C94EE2ADE7E32244 BD60D3B33609C167
 | |
| 		public void ProcessSpnegoProcessContextToken (byte [] raw)
 | |
| 		{
 | |
| 			ASN1 asn1 = new ASN1 (raw);
 | |
| 			// FIXME: check structure
 | |
| 			ProcessMessageType3 (asn1 [0] [0] [0].Value);
 | |
| 		}
 | |
| 
 | |
| 		public void ProcessMessageType1 (byte [] raw)
 | |
| 		{
 | |
| 			type1 = new Type1Message (raw, NtlmVersion.Version3);
 | |
| 		}
 | |
| 
 | |
| 		public byte [] ProcessMessageType2 ()
 | |
| 		{
 | |
| 			byte [] bytes = new byte [8];
 | |
| 			RandomNumberGenerator.Create ().GetNonZeroBytes (bytes);
 | |
| 			Challenge = bytes [0] << 24 + bytes [1] << 16 + bytes [2] << 8 + bytes [3];
 | |
| 			Context = 0; // FIXME
 | |
| 			ServerOSVersion = 0x0F00000A28010500; // FIXME
 | |
| 			TargetName = Environment.MachineName;
 | |
| 			ServerName = Environment.MachineName;
 | |
| 			// FIXME
 | |
| 			DomainName = ServerName;// IPGlobalProperties.GetIPGlobalProperties ().DomainName;
 | |
| 			DnsHostName = Dns.GetHostName ();
 | |
| 			DnsDomainName = DnsHostName; // FIXME
 | |
| 
 | |
| 			type2 = new Type2Message (NtlmVersion.Version3);
 | |
| 			type2.Flags = (NtlmFlags) (unchecked ((int) 0xE21882B7));
 | |
| 			type2.TargetName = TargetName;
 | |
| 			type2.Target.ServerName = ServerName;
 | |
| 			type2.Target.DomainName = DomainName;
 | |
| 			type2.Target.DnsHostName = DnsHostName;
 | |
| 			type2.Target.DnsDomainName = DnsDomainName;
 | |
| 			return type2.GetBytes ();
 | |
| 		}
 | |
| 
 | |
| 		public void ProcessMessageType3 (byte [] raw)
 | |
| 		{
 | |
| 			/*
 | |
| 			MemoryStream ms = new MemoryStream (raw);
 | |
| 			if (!Verify (NtlmSSP, raw, 0, 8))
 | |
| 				throw new SecurityNegotiationException ("Expected NTLM SSPI header not found");
 | |
| 			BinaryReader reader = new BinaryReader (ms);
 | |
| 			reader.ReadInt64 (); // skip 8 bytes
 | |
| 			if (reader.ReadInt32 () != 3)
 | |
| 				throw new SecurityNegotiationException ("SSPI type 3 message is expected");
 | |
| 			SspiSecurityBufferStruct lmResInfo = ReadSecurityBuffer (reader);
 | |
| 			SspiSecurityBufferStruct ntlmResInfo = ReadSecurityBuffer (reader);
 | |
| 			SspiSecurityBufferStruct targetNameInfo = ReadSecurityBuffer (reader);
 | |
| 			SspiSecurityBufferStruct userNameInfo = ReadSecurityBuffer (reader);
 | |
| 			SspiSecurityBufferStruct wsNameInfo = ReadSecurityBuffer (reader);
 | |
| 			SspiSecurityBufferStruct sessionKeyInfo = ReadSecurityBuffer (reader);
 | |
| 			int flags = reader.ReadInt32 ();
 | |
| 			ServerOSVersion = reader.ReadInt64 ();
 | |
| 			*/
 | |
| 			type3 = new Type3Message (raw, NtlmVersion.Version3);
 | |
| 		}
 | |
| 	}
 | |
| }
 |