// Example from http://www.innovation.ch/java/ntlm.html public void Encode1 () { Type2Message msg = new Type2Message (); Assert.AreEqual (2, msg.Type, "Type"); msg.Nonce = nonce; Assert.AreEqual ("4E-54-4C-4D-53-53-50-00-02-00-00-00-00-00-00-00-28-00-00-00-01-82-00-00-53-72-76-4E-6F-6E-63-65-00-00-00-00-00-00-00-00", BitConverter.ToString (msg.GetBytes ()), "GetBytes"); }
// Example from http://www.innovation.ch/java/ntlm.html public void Decode1 () { byte[] data = { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x82, 0x00, 0x00, 0x53, 0x72, 0x76, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; Type2Message msg = new Type2Message (data); Assert.AreEqual ((NtlmFlags)0x8201, msg.Flags, "Flags"); Assert.AreEqual (BitConverter.ToString (nonce), BitConverter.ToString (msg.Nonce), "Nonce"); Assert.AreEqual (2, msg.Type, "Type"); }
// Example from http://davenport.sourceforge.net/ntlm.html#type2MessageExample public void Decode2 () { byte[] data = { 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x02, 0x81, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x62, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x41, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x44, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x41, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x53, 0x00, 0x45, 0x00, 0x52, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x04, 0x00, 0x14, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x03, 0x00, 0x22, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00 }; Type2Message msg = new Type2Message (data); Assert.AreEqual ((NtlmFlags)0x00810201, msg.Flags, "Flags"); Assert.AreEqual ("01-23-45-67-89-AB-CD-EF", BitConverter.ToString (msg.Nonce), "Nonce"); Assert.AreEqual (2, msg.Type, "Type"); }
public Authorization Authenticate (string challenge, WebRequest webRequest, ICredentials credentials) { HttpWebRequest request = webRequest as HttpWebRequest; if (request == null) return null; NetworkCredential cred = credentials.GetCredential (request.RequestUri, "NTLM"); if (cred == null) return null; string userName = cred.UserName; string domain = cred.Domain; string password = cred.Password; if (userName == null || userName == "") return null; domain = domain != null && domain.Length > 0 ? domain : request.Headers ["Host"]; bool completed = false; if (message == null) { Type1Message type1 = new Type1Message (); type1.Domain = domain; message = type1; } else if (message.Type == 1) { // Should I check the credentials? if (challenge == null) { message = null; return null; } Type2Message type2 = new Type2Message (Convert.FromBase64String (challenge)); if (password == null) password = ""; Type3Message type3 = new Type3Message (); type3.Domain = domain; type3.Username = userName; type3.Challenge = type2.Nonce; type3.Password = password; message = type3; completed = true; } else { // Should I check the credentials? // type must be 3 here if (challenge == null || challenge == String.Empty) { Type1Message type1 = new Type1Message (); type1.Domain = domain; message = type1; } else { completed = true; } } string token = "NTLM " + Convert.ToBase64String (message.GetBytes ()); return new Authorization (token, completed); }
public Type3Message (Type2Message type2) : base (3) { _type2 = type2; _level = DefaultAuthLevel; _challenge = (byte[]) type2.Nonce.Clone (); _domain = type2.TargetName; _host = Environment.MachineName; _username = Environment.UserName; Flags = (NtlmFlags) 0x8200; if ((type2.Flags & NtlmFlags.NegotiateUnicode) != 0) Flags |= NtlmFlags.NegotiateUnicode; else Flags |= NtlmFlags.NegotiateOem; if ((type2.Flags & NtlmFlags.NegotiateNtlm2Key) != 0) Flags |= NtlmFlags.NegotiateNtlm2Key; }
public static void Compute(Type2Message type2, NtlmAuthLevel level, string username, string password, out byte[] lm, out byte[] ntlm) { lm = null; switch (level) { case NtlmAuthLevel.LM_and_NTLM: lm = Compute_LM(password, type2.Nonce); ntlm = Compute_NTLM(password, type2.Nonce); break; case NtlmAuthLevel.LM_and_NTLM_and_try_NTLMv2_Session: if ((type2.Flags & NtlmFlags.NegotiateNtlm2Key) == 0) { goto case NtlmAuthLevel.LM_and_NTLM; } Compute_NTLMv2_Session(password, type2.Nonce, out lm, out ntlm); break; case NtlmAuthLevel.NTLM_only: if ((type2.Flags & NtlmFlags.NegotiateNtlm2Key) != 0) { Compute_NTLMv2_Session(password, type2.Nonce, out lm, out ntlm); } else { ntlm = Compute_NTLM(password, type2.Nonce); } break; case NtlmAuthLevel.NTLMv2_only: ntlm = Compute_NTLMv2(type2, username, password); break; default: throw new InvalidOperationException(); } }
public static void Compute (Type2Message type2, NtlmAuthLevel level, string username, string password, string domain, out byte[] lm, out byte[] ntlm) { lm = null; switch (level) { case NtlmAuthLevel.LM_and_NTLM: lm = Compute_LM (password, type2.Nonce); ntlm = Compute_NTLM (password, type2.Nonce); break; case NtlmAuthLevel.LM_and_NTLM_and_try_NTLMv2_Session: if ((type2.Flags & NtlmFlags.NegotiateNtlm2Key) == 0) goto case NtlmAuthLevel.LM_and_NTLM; Compute_NTLMv2_Session (password, type2.Nonce, out lm, out ntlm); break; case NtlmAuthLevel.NTLM_only: if ((type2.Flags & NtlmFlags.NegotiateNtlm2Key) != 0) Compute_NTLMv2_Session (password, type2.Nonce, out lm, out ntlm); else ntlm = Compute_NTLM (password, type2.Nonce); break; case NtlmAuthLevel.NTLMv2_only: ntlm = Compute_NTLMv2 (type2, username, password, domain); break; default: throw new InvalidOperationException (); } }
static byte[] Compute_NTLMv2 (Type2Message type2, string username, string password, string domain) { var ntlm_hash = Compute_NTLM_Password (password); var ubytes = Encoding.Unicode.GetBytes (username.ToUpperInvariant ()); var tbytes = Encoding.Unicode.GetBytes (domain); var bytes = new byte [ubytes.Length + tbytes.Length]; ubytes.CopyTo (bytes, 0); Array.Copy (tbytes, 0, bytes, ubytes.Length, tbytes.Length); var md5 = new HMACMD5 (ntlm_hash); var ntlm_v2_hash = md5.ComputeHash (bytes); Array.Clear (ntlm_hash, 0, ntlm_hash.Length); md5.Clear (); var ntlm_v2_md5 = new HMACMD5 (ntlm_v2_hash); var now = DateTime.Now; var timestamp = now.Ticks - 504911232000000000; var nonce = new byte [8]; var rng = RandomNumberGenerator.Create (); rng.GetBytes (nonce); byte[] blob = new byte [28 + type2.TargetInfo.Length]; blob[0] = 0x01; blob[1] = 0x01; Buffer.BlockCopy (BitConverterLE.GetBytes (timestamp), 0, blob, 8, 8); Buffer.BlockCopy (nonce, 0, blob, 16, 8); Buffer.BlockCopy (type2.TargetInfo, 0, blob, 28, type2.TargetInfo.Length); var challenge = type2.Nonce; var hashInput = new byte [challenge.Length + blob.Length]; challenge.CopyTo (hashInput, 0); blob.CopyTo (hashInput, challenge.Length); var blobHash = ntlm_v2_md5.ComputeHash (hashInput); var response = new byte [blob.Length + blobHash.Length]; blobHash.CopyTo (response, 0); blob.CopyTo (response, blobHash.Length); Array.Clear (ntlm_v2_hash, 0, ntlm_v2_hash.Length); ntlm_v2_md5.Clear (); Array.Clear (nonce, 0, nonce.Length); Array.Clear (blob, 0, blob.Length); Array.Clear (hashInput, 0, hashInput.Length); Array.Clear (blobHash, 0, blobHash.Length); return response; }
public void Run(string username, string password) { Console.WriteLine ("========="); helper.StandardInput.WriteLine ("SF NTLMSSP_FEATURE_SESSION_KEY"); var sf_response = helper.StandardOutput.ReadLine (); Console.WriteLine (sf_response); if (sf_response != "OK") throw new InvalidDataException (sf_response); var pw_bytes = Encoding.ASCII.GetBytes (password); helper.StandardInput.WriteLine ("PW " + Convert.ToBase64String (pw_bytes)); var pw_result = helper.StandardOutput.ReadLine (); if (pw_result != "OK") throw new InvalidDataException (pw_result); var type1 = new Type1Message (); type1.Flags |= NtlmFlags.NegotiateNtlm2Key; helper.StandardInput.WriteLine ("KK " + Convert.ToBase64String (type1.GetBytes ())); var type1_res = helper.StandardOutput.ReadLine (); if (!type1_res.StartsWith ("TT ")) throw new InvalidDataException (); var type2 = new Type2Message (Convert.FromBase64String (type1_res.Substring (3))); Console.WriteLine ("TYPE2: {0:x} {1}", type2.Flags, type2.Flags); var type3 = new Type3Message (type2); type3.Domain = "SOL"; type3.Host = "PROVCON-FAUST"; type3.Username = username; type3.Password = password; var bytes = type3.GetBytes (); helper.StandardInput.WriteLine ("KK {0}", Convert.ToBase64String (bytes)); var response2 = helper.StandardOutput.ReadLine (); Console.WriteLine (response2); if (!response2.StartsWith ("AF ")) throw new InvalidDataException (response2); }
public override void Negotiate(byte[] clientResponse, out byte[] serverChallenge) { #if MONO_SECURITY_DLL var type1 = new Type1Message(clientResponse); var type2 = new Type2Message(); if ((int)(type1.Flags & NtlmFlags.NegotiateUnicode) != 0) type2.Flags |= NtlmFlags.NegotiateUnicode; else if ((int)(type1.Flags & NtlmFlags.NegotiateOem) != 0) type2.Flags |= NtlmFlags.NegotiateOem; type2.Nonce = Nonce.Create(8, false); serverChallenge = type2.GetBytes(); #else var type1 = Activator.CreateInstance(typeOfType1Message, clientResponse); var type2 = Activator.CreateInstance(typeOfType2Message); var type1Flags = (int)typeOfType1Message.GetProperty("Flags").GetValue(type1, null); var type2Flags = 0x00000200; // NegotiateNtlm if ((type1Flags & 0x00000001) != 0) // NegotiateUnicode type2Flags |= 0x00000001; else if ((type1Flags & 0x00000002) != 0) // NegotiateOem type2Flags |= 0x00000002; typeOfType2Message.GetProperty("Flags").SetValue(type2, type2Flags, null); typeOfType2Message.GetProperty("Nonce").SetValue(type2, Nonce.Generate(8, false), null); serverChallenge = (byte[])typeOfType2Message.GetMethod("GetBytes").Invoke(type2, null); #endif }
static void Compute_Type3() { Decode_Type3 (type3_message); Console.WriteLine (); var bytes = Convert.FromBase64String (type2_message); var message = new Type2Message (bytes); Compute_Type3 (message); }
static void Dump(Type2Message type2, Type3Message type3, out long timestamp, out byte[] nonce, out byte[] namesBlob) { Console.WriteLine (); Console.WriteLine ("DUMP:"); Console.WriteLine ("====="); var ntlm_hash = ChallengeResponse2.Compute_NTLM_Password ("yeknom"); Utils.HexDump ("NTLM HASH", ntlm_hash); var ubytes = Encoding.Unicode.GetBytes ("TEST"); var tbytes = Encoding.Unicode.GetBytes ("PROVCON-FAUST"); var bytes = new byte [ubytes.Length + tbytes.Length]; ubytes.CopyTo (bytes, 0); Array.Copy (tbytes, 0, bytes, ubytes.Length, tbytes.Length); var md5 = new HMACMD5 (ntlm_hash); var ntlmv2_hash = md5.ComputeHash (bytes); Utils.HexDump ("NTLM V2 HASH", ntlmv2_hash); var ntlmv2_md5 = new HMACMD5 (ntlmv2_hash); Utils.HexDump (type3.NT); var br = new BinaryReader (new MemoryStream (type3.NT)); var hash = br.ReadBytes (16); Utils.HexDump (hash); if (br.ReadInt32 () != 0x0101) throw new InvalidDataException (); if (br.ReadInt32 () != 0) throw new InvalidDataException (); timestamp = br.ReadInt64 (); var ticks = timestamp + 504911232000000000; Console.WriteLine ("TIMESTAMP: {0} {1}", timestamp, new DateTime (ticks)); nonce = br.ReadBytes (8); Utils.HexDump ("NONCE", nonce); br.ReadInt32 (); var pos = br.BaseStream.Position; while (true) { var type = br.ReadInt16 (); var length = br.ReadInt16 (); Console.WriteLine ("NAMES BLOB: {0:x} {1:x}", type, length); if (type == 0) break; var contents = br.ReadBytes (length); Utils.HexDump (contents); } namesBlob = new byte [br.BaseStream.Position - pos]; Array.Copy (type3.NT, pos, namesBlob, 0, namesBlob.Length); var blob = new byte [type3.NT.Length - 16]; Array.Copy (type3.NT, 16, blob, 0, blob.Length); Utils.HexDump ("TYPE 2 CHALLENGE", type2.Nonce); var buffer = new byte [type2.Nonce.Length + blob.Length]; type2.Nonce.CopyTo (buffer, 0); blob.CopyTo (buffer, type2.Nonce.Length); Utils.HexDump (blob); var test = ntlmv2_md5.ComputeHash (buffer); Utils.HexDump ("THE HASH", test); var ok = Utils.Compare (hash, test); Console.WriteLine (ok); Console.WriteLine (); Console.WriteLine ("=========="); Console.WriteLine (); }
static void Compute_Type3(Type2Message type2) { Type3Message type3 = new Type3Message (); type3.Domain = ""; type3.Host = "PROVCON-FAUST"; type3.Username = "******"; type3.Challenge = type2.Nonce; type3.Password = "******"; HexDump ("CHALLENGE", type2.Nonce); var bytes = type3.GetBytes (); var message = new Type3Message (bytes); HexDump ("LM", message.LM); HexDump ("NT", message.NT); }
public void ProcessMessageType2 (byte [] raw) { type2 = new Type2Message (raw); }
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 (); }
protected internal int ProcessAuthentication () { int pdu_size = Comm.GetTdsShort (); byte[] msg2 = Comm.GetBytes (pdu_size, true); Type2Message t2 = new Type2Message (msg2); // 0x0001 Negotiate Unicode // 0x0200 Negotiate NTLM // 0x8000 Negotiate Always Sign Type3Message t3 = new Type3Message (t2); t3.Domain = this.connectionParms.DefaultDomain; t3.Host = this.connectionParms.Hostname; t3.Username = this.connectionParms.User; t3.Password = GetPlainPassword(this.connectionParms.Password); Comm.StartPacket (TdsPacketType.SspAuth); // 0x11 Comm.Append (t3.GetBytes ()); try { Comm.SendPacket (); } catch (IOException ex) { connected = false; throw new TdsInternalException ("Server closed the connection.", ex); } return 1; // TDS_SUCCEED }
protected internal int ProcessAuthentication () { int pdu_size = Comm.GetTdsShort (); byte[] msg2 = Comm.GetBytes (pdu_size, true); Type2Message t2 = new Type2Message (msg2); // 0x0001 Negotiate Unicode // 0x0200 Negotiate NTLM // 0x8000 Negotiate Always Sign Type3Message t3 = new Type3Message (); t3.Challenge = t2.Nonce; t3.Domain = this.connectionParms.DefaultDomain; t3.Host = this.connectionParms.Hostname; t3.Username = this.connectionParms.User; t3.Password = this.connectionParms.Password; Comm.StartPacket (TdsPacketType.SspAuth); // 0x11 Comm.Append (t3.GetBytes ()); Comm.SendPacket (); return 1; // TDS_SUCCEED }
static void Decode_Type2(string text) { var bytes = Convert.FromBase64String (text); HexDump (bytes); var message = new Type2Message (bytes); Console.WriteLine ("TYPE 2: {0:x} {1:x}", message.Type, message.Flags); }
public void Nonce_Null () { Type2Message msg = new Type2Message (); msg.Nonce = null; }
public Authorization Authenticate(string challenge, WebRequest request, ICredentials credentials) { if (!challenge.StartsWith ("NTLM")) return null; Console.WriteLine ("AUTHENTICATE: {0} {1}", challenge, request); pipe.StandardInput.WriteLine ("TT{0}", challenge.Substring (4)); var result = pipe.StandardOutput.ReadLine (); Console.WriteLine (result); if (result.StartsWith ("YR ")) return ntlm.Authenticate (challenge, request, credentials); if (!result.StartsWith ("AF ")) return null; var t2_bytes = Convert.FromBase64String (challenge.Substring (5)); var type2 = new Type2Message (t2_bytes); Utils.HexDump (t2_bytes); Console.WriteLine ("TYPE2: {0}", type2.TargetName); var bytes = Convert.FromBase64String (result.Substring (3)); var type3 = new Type3Message (bytes); long timestamp; byte[] nonce, namesBlob; Dump (type2, type3, out timestamp, out nonce, out namesBlob); byte[] nt = ChallengeResponse2.Compute_NTLMv2 ( type2, "test", "yeknom", timestamp, nonce); var ok = Utils.Compare (type3.NT, nt); Console.WriteLine ("COMPARE: {0} - {1:x}", ok, type3.Flags); type3.NT = nt; // Dump (type2, type3); type3.Flags = (NtlmFlags)0x00088201; var bytes2 = type3.GetBytes2 (); var auth = ntlm.Authenticate (challenge, request, credentials); Console.WriteLine (auth.Message); var bytes3 = Convert.FromBase64String (auth.Message.Substring (5)); var test = new Type3Message (bytes3); Console.WriteLine ("TEST: {0:x} - {1} {2}", test.Flags, bytes2.Length, bytes3.Length); Console.WriteLine ("TEST #1: {0} {1} {2} - {3} {4} {5}", type3.Host, type3.Domain, type3.Username, test.Host, test.Domain, test.Username); Console.WriteLine ("TEST #2: {0} {1} {2}", test.LM != null, test.NT.Length, type3.NT.Length); // test.NT = type3.NT; // test.Host = type3.Host; test.Domain = type3.Domain; // test.Flags = type3.Flags; var bytes4 = test.GetBytes2 (); // Utils.HexDump (bytes); // Utils.HexDump (bytes2); // Utils.Compare (bytes2, bytes3); // auth = new Authorization ("NTLM " + Convert.ToBase64String (bytes4)); Console.WriteLine (auth.Message); return auth; }
public void Nonce_InvalidLength () { Type2Message msg = new Type2Message (); msg.Nonce = new byte [9]; }
public Authorization Authenticate (string challenge, WebRequest webRequest, ICredentials credentials) { HttpWebRequest request = webRequest as HttpWebRequest; if (request == null) return null; NetworkCredential cred = credentials.GetCredential (request.RequestUri, "NTLM"); if (cred == null) return null; string userName = cred.UserName; string domain = cred.Domain; string password = cred.Password; if (userName == null || userName == "") return null; if (String.IsNullOrEmpty (domain)) { int idx = userName.IndexOf ('\\'); if (idx == -1) { idx = userName.IndexOf ('/'); } if (idx >= 0) { domain = userName.Substring (0, idx); userName = userName.Substring (idx + 1); } } bool completed = false; if (message == null) { Type1Message type1 = new Type1Message (); type1.Domain = domain; type1.Host = ""; // MS does not send it type1.Flags |= NtlmFlags.NegotiateNtlm2Key; message = type1; } else if (message.Type == 1) { // Should I check the credentials? if (challenge == null) { message = null; return null; } Type2Message type2 = new Type2Message (Convert.FromBase64String (challenge)); if (password == null) password = ""; Type3Message type3 = new Type3Message (type2); type3.Username = userName; type3.Password = password; type3.Domain = domain; message = type3; completed = true; } else { // Should I check the credentials? // type must be 3 here if (challenge == null || challenge == String.Empty) { Type1Message type1 = new Type1Message (); type1.Domain = domain; type1.Host = ""; // MS does not send it message = type1; } else { completed = true; } } string token = "NTLM " + Convert.ToBase64String (message.GetBytes ()); return new Authorization (token, completed); }
protected override SaslExchangeStatus Exchange(ByteString serverChallenge, out ByteString clientResponse) { if (Credential == null) throw new SaslException("Credential property must be set"); clientResponse = null; switch (step) { case 0: { // send NTLM negotiate message (Type 1) const NtlmFlags type1Flags = NtlmFlags.RequestTarget | NtlmFlags.NegotiateNtlm | NtlmFlags.NegotiateUnicode | NtlmFlags.NegotiateOem | NtlmFlags.NegotiateDomainSupplied | NtlmFlags.NegotiateWorkstationSupplied; var type1 = new Type1Message(); type1.Flags = type1Flags; type1.Host = TargetHost ?? string.Empty; // ? type1.Domain = Credential.Domain ?? string.Empty; clientResponse = new ByteString(type1.GetBytes()); step++; return SaslExchangeStatus.Continuing; } case 1: { // receive NTLM challenge message (Type 2) and send NTLM authenticate message (Type 3) if (string.IsNullOrEmpty(Credential.UserName) || string.IsNullOrEmpty(Credential.Password)) return SaslExchangeStatus.Failed; var type2 = new Type2Message(serverChallenge.ByteArray); var type3 = new Type3Message(); type3.Flags = NtlmFlags.NegotiateNtlm | NtlmFlags.NegotiateUnicode; // XXX type3.Host = TargetHost ?? string.Empty; // ? type3.Domain = Credential.Domain ?? string.Empty; type3.Challenge = type2.Nonce; type3.Password = Credential.Password; type3.Username = Credential.UserName; clientResponse = new ByteString(type3.GetBytes()); step++; return SaslExchangeStatus.Succeeded; } default: clientResponse = null; return SaslExchangeStatus.Failed; // unexpected server challenge } }