IndependentUserCollection.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
  2. *
  3. * You can redistribute this program and/or modify it under the terms of
  4. * the GNU Lesser Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. */
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Text;
  10. using Utilities;
  11. using SMBLibrary.Authentication;
  12. namespace SMBLibrary.Server
  13. {
  14. public class IndependentUserCollection : UserCollection, INTLMAuthenticationProvider
  15. {
  16. private byte[] m_serverChallenge = new byte[8];
  17. public IndependentUserCollection()
  18. {
  19. }
  20. public IndependentUserCollection(UserCollection users)
  21. {
  22. this.AddRange(users);
  23. }
  24. /// <summary>
  25. /// LM v1 / NTLM v1
  26. /// </summary>
  27. public User AuthenticateV1(string accountNameToAuth, byte[] serverChallenge, byte[] lmResponse, byte[] ntlmResponse)
  28. {
  29. for (int index = 0; index < this.Count; index++)
  30. {
  31. string accountName = this[index].AccountName;
  32. string password = this[index].Password;
  33. if (String.Equals(accountName, accountNameToAuth, StringComparison.InvariantCultureIgnoreCase))
  34. {
  35. byte[] expectedLMResponse = NTAuthentication.ComputeLMv1Response(serverChallenge, password);
  36. if (ByteUtils.AreByteArraysEqual(expectedLMResponse, lmResponse))
  37. {
  38. return this[index];
  39. }
  40. byte[] expectedNTLMResponse = NTAuthentication.ComputeNTLMv1Response(serverChallenge, password);
  41. if (ByteUtils.AreByteArraysEqual(expectedNTLMResponse, ntlmResponse))
  42. {
  43. return this[index];
  44. }
  45. }
  46. }
  47. return null;
  48. }
  49. /// <summary>
  50. /// LM v1 / NTLM v1 Extended Security
  51. /// </summary>
  52. public User AuthenticateV1Extended(string accountNameToAuth, byte[] serverChallenge, byte[] lmResponse, byte[] ntlmResponse)
  53. {
  54. for (int index = 0; index < this.Count; index++)
  55. {
  56. string accountName = this[index].AccountName;
  57. string password = this[index].Password;
  58. if (String.Equals(accountName, accountNameToAuth, StringComparison.InvariantCultureIgnoreCase))
  59. {
  60. byte[] clientChallenge = ByteReader.ReadBytes(lmResponse, 0, 8);
  61. byte[] expectedNTLMv1Response = NTAuthentication.ComputeNTLMv1ExtendedSecurityResponse(serverChallenge, clientChallenge, password);
  62. if (ByteUtils.AreByteArraysEqual(expectedNTLMv1Response, ntlmResponse))
  63. {
  64. return this[index];
  65. }
  66. }
  67. }
  68. return null;
  69. }
  70. /// <summary>
  71. /// LM v2 / NTLM v2
  72. /// </summary>
  73. public User AuthenticateV2(string domainNameToAuth, string accountNameToAuth, byte[] serverChallenge, byte[] lmResponse, byte[] ntlmResponse)
  74. {
  75. for (int index = 0; index < this.Count; index++)
  76. {
  77. string accountName = this[index].AccountName;
  78. string password = this[index].Password;
  79. if (String.Equals(accountName, accountNameToAuth, StringComparison.InvariantCultureIgnoreCase))
  80. {
  81. byte[] _LMv2ClientChallenge = ByteReader.ReadBytes(lmResponse, 16, 8);
  82. byte[] expectedLMv2Response = NTAuthentication.ComputeLMv2Response(serverChallenge, _LMv2ClientChallenge, password, accountName, domainNameToAuth);
  83. if (ByteUtils.AreByteArraysEqual(expectedLMv2Response, lmResponse))
  84. {
  85. return this[index];
  86. }
  87. if (ntlmResponse.Length > 24)
  88. {
  89. NTLMv2ClientChallengeStructure clientChallengeStructure = new NTLMv2ClientChallengeStructure(ntlmResponse, 16);
  90. byte[] clientChallengeStructurePadded = clientChallengeStructure.GetBytesPadded();
  91. byte[] expectedNTLMv2Response = NTAuthentication.ComputeNTLMv2Response(serverChallenge, clientChallengeStructurePadded, password, accountName, domainNameToAuth);
  92. if (ByteUtils.AreByteArraysEqual(expectedNTLMv2Response, ntlmResponse))
  93. {
  94. return this[index];
  95. }
  96. }
  97. }
  98. }
  99. return null;
  100. }
  101. public byte[] GenerateServerChallenge()
  102. {
  103. new Random().NextBytes(m_serverChallenge);
  104. return m_serverChallenge;
  105. }
  106. public ChallengeMessage GetChallengeMessage(byte[] negotiateMessageBytes)
  107. {
  108. byte[] serverChallenge = GenerateServerChallenge();
  109. ChallengeMessage message = new ChallengeMessage();
  110. message.NegotiateFlags = NegotiateFlags.NegotiateUnicode |
  111. NegotiateFlags.RequestTarget |
  112. NegotiateFlags.NegotiateNTLMKey |
  113. NegotiateFlags.NegotiateExtendedSecurity |
  114. NegotiateFlags.NegotiateTargetInfo |
  115. NegotiateFlags.NegotiateVersion |
  116. NegotiateFlags.Negotiate128 |
  117. NegotiateFlags.Negotiate56;
  118. message.TargetName = Environment.MachineName;
  119. message.ServerChallenge = serverChallenge;
  120. message.TargetInfo = AVPairUtils.GetAVPairSequence(Environment.MachineName, Environment.MachineName);
  121. message.Version = Authentication.Version.Server2003;
  122. return message;
  123. }
  124. public byte[] GetChallengeMessageBytes(byte[] negotiateMessageBytes)
  125. {
  126. ChallengeMessage message = GetChallengeMessage(negotiateMessageBytes);
  127. return message.GetBytes();
  128. }
  129. public User Authenticate(byte[] authenticateMessageBytes)
  130. {
  131. AuthenticateMessage message = new AuthenticateMessage(authenticateMessageBytes);
  132. return Authenticate(message);
  133. }
  134. public User Authenticate(AuthenticateMessage message)
  135. {
  136. User user;
  137. if ((message.NegotiateFlags & NegotiateFlags.NegotiateExtendedSecurity) > 0)
  138. {
  139. user = AuthenticateV1Extended(message.UserName, m_serverChallenge, message.LmChallengeResponse, message.NtChallengeResponse);
  140. }
  141. else
  142. {
  143. user = AuthenticateV1(message.UserName, m_serverChallenge, message.LmChallengeResponse, message.NtChallengeResponse);
  144. }
  145. if (user == null)
  146. {
  147. // NTLM v2
  148. user = AuthenticateV2(message.DomainName, message.UserName, m_serverChallenge, message.LmChallengeResponse, message.NtChallengeResponse);
  149. }
  150. return user;
  151. }
  152. public User Authenticate(string accountNameToAuth, byte[] lmResponse, byte[] ntlmResponse)
  153. {
  154. return AuthenticateV1(accountNameToAuth, m_serverChallenge, lmResponse, ntlmResponse);
  155. }
  156. public bool EnableGuestLogin
  157. {
  158. get
  159. {
  160. int index = IndexOf("Guest");
  161. return (index >= 0 && this[index].Password == String.Empty);
  162. }
  163. }
  164. public byte[] ServerChallenge
  165. {
  166. get
  167. {
  168. return m_serverChallenge;
  169. }
  170. }
  171. }
  172. }