| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- 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);
- }
- }
- }
|