SimpleProtectedNegotiationTokenResponse.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /* Copyright (C) 2017 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.IO;
  10. using Utilities;
  11. namespace SMBLibrary.Authentication
  12. {
  13. public enum NegState : byte
  14. {
  15. AcceptCompleted = 0x00,
  16. AcceptIncomplete = 0x01,
  17. Reject = 0x02,
  18. RequestMic = 0x03,
  19. }
  20. public class TokenResponseEntry
  21. {
  22. public NegState? NegState; // Optional
  23. public byte[] SupportedMechanism; // Optional
  24. public byte[] ResponseToken; // Optional
  25. public byte[] MechanismListMIC; // Optional
  26. }
  27. /// <summary>
  28. /// RFC 4178 - negTokenResp
  29. /// </summary>
  30. public class SimpleProtectedNegotiationTokenResponse : SimpleProtectedNegotiationToken
  31. {
  32. public const byte NegTokenRespTag = 0xA1;
  33. public const byte NegStateTag = 0xA0;
  34. public const byte SupportedMechanismTag = 0xA1;
  35. public const byte ResponseTokenTag = 0xA2;
  36. public const byte MechanismListMICTag = 0xA3;
  37. public List<TokenResponseEntry> Tokens = new List<TokenResponseEntry>();
  38. public SimpleProtectedNegotiationTokenResponse()
  39. {
  40. }
  41. public SimpleProtectedNegotiationTokenResponse(byte[] buffer, int offset)
  42. {
  43. byte tag = ByteReader.ReadByte(buffer, ref offset);
  44. if (tag != NegTokenRespTag)
  45. {
  46. throw new InvalidDataException();
  47. }
  48. int constuctionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
  49. int sequenceEndOffset = offset + constuctionLength;
  50. tag = ByteReader.ReadByte(buffer, ref offset);
  51. if (tag != (byte)DerEncodingTag.Sequence)
  52. {
  53. throw new InvalidDataException();
  54. }
  55. while (offset < sequenceEndOffset)
  56. {
  57. int entryLength = DerEncodingHelper.ReadLength(buffer, ref offset);
  58. int entryEndOffset = offset + entryLength;
  59. TokenResponseEntry entry = new TokenResponseEntry();
  60. while (offset < entryEndOffset)
  61. {
  62. tag = ByteReader.ReadByte(buffer, ref offset);
  63. if (tag == NegStateTag)
  64. {
  65. entry.NegState = ReadNegState(buffer, ref offset);
  66. }
  67. else if (tag == SupportedMechanismTag)
  68. {
  69. entry.SupportedMechanism = ReadSupportedMechanism(buffer, ref offset);
  70. }
  71. else if (tag == ResponseTokenTag)
  72. {
  73. entry.ResponseToken = ReadResponseToken(buffer, ref offset);
  74. }
  75. else if (tag == MechanismListMICTag)
  76. {
  77. entry.MechanismListMIC = ReadMechanismListMIC(buffer, ref offset);
  78. }
  79. else
  80. {
  81. throw new InvalidDataException("Invalid negTokenResp structure");
  82. }
  83. }
  84. Tokens.Add(entry);
  85. }
  86. }
  87. public override byte[] GetBytes()
  88. {
  89. int sequenceLength = 0;
  90. foreach (TokenResponseEntry token in Tokens)
  91. {
  92. int entryLength = GetEntryLength(token);
  93. sequenceLength += DerEncodingHelper.GetLengthFieldSize(entryLength) + entryLength;
  94. }
  95. int constructionLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(1 + sequenceLength);
  96. int bufferSize = 1 + constructionLengthFieldSize + 1 + sequenceLength;
  97. byte[] buffer = new byte[bufferSize];
  98. int offset = 0;
  99. ByteWriter.WriteByte(buffer, ref offset, NegTokenRespTag);
  100. DerEncodingHelper.WriteLength(buffer, ref offset, 1 + sequenceLength);
  101. ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.Sequence);
  102. foreach (TokenResponseEntry token in Tokens)
  103. {
  104. int entryLength = GetEntryLength(token);
  105. DerEncodingHelper.WriteLength(buffer, ref offset, entryLength);
  106. if (token.NegState.HasValue)
  107. {
  108. WriteNegState(buffer, ref offset, token.NegState.Value);
  109. }
  110. if (token.SupportedMechanism != null)
  111. {
  112. WriteSupportedMechanism(buffer, ref offset, token.SupportedMechanism);
  113. }
  114. if (token.ResponseToken != null)
  115. {
  116. WriteResponseToken(buffer, ref offset, token.ResponseToken);
  117. }
  118. if (token.MechanismListMIC != null)
  119. {
  120. WriteMechanismListMIC(buffer, ref offset, token.MechanismListMIC);
  121. }
  122. }
  123. return buffer;
  124. }
  125. private static NegState ReadNegState(byte[] buffer, ref int offset)
  126. {
  127. int length = DerEncodingHelper.ReadLength(buffer, ref offset);
  128. byte tag = ByteReader.ReadByte(buffer, ref offset);
  129. if (tag != (byte)DerEncodingTag.Enum)
  130. {
  131. throw new InvalidDataException();
  132. }
  133. length = DerEncodingHelper.ReadLength(buffer, ref offset);
  134. return (NegState)ByteReader.ReadByte(buffer, ref offset);
  135. }
  136. private static byte[] ReadSupportedMechanism(byte[] buffer, ref int offset)
  137. {
  138. int constructionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
  139. byte tag = ByteReader.ReadByte(buffer, ref offset);
  140. if (tag != (byte)DerEncodingTag.ObjectIdentifier)
  141. {
  142. throw new InvalidDataException();
  143. }
  144. int length = DerEncodingHelper.ReadLength(buffer, ref offset);
  145. return ByteReader.ReadBytes(buffer, ref offset, length);
  146. }
  147. private static byte[] ReadResponseToken(byte[] buffer, ref int offset)
  148. {
  149. int constructionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
  150. byte tag = ByteReader.ReadByte(buffer, ref offset);
  151. if (tag != (byte)DerEncodingTag.ByteArray)
  152. {
  153. throw new InvalidDataException();
  154. }
  155. int length = DerEncodingHelper.ReadLength(buffer, ref offset);
  156. return ByteReader.ReadBytes(buffer, ref offset, length);
  157. }
  158. private static byte[] ReadMechanismListMIC(byte[] buffer, ref int offset)
  159. {
  160. int constructionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
  161. byte tag = ByteReader.ReadByte(buffer, ref offset);
  162. if (tag != (byte)DerEncodingTag.ByteArray)
  163. {
  164. throw new InvalidDataException();
  165. }
  166. int length = DerEncodingHelper.ReadLength(buffer, ref offset);
  167. return ByteReader.ReadBytes(buffer, ref offset, length);
  168. }
  169. private static int GetEntryLength(TokenResponseEntry token)
  170. {
  171. int result = 0;
  172. if (token.NegState.HasValue)
  173. {
  174. int negStateLength = 5;
  175. result += negStateLength;
  176. }
  177. if (token.SupportedMechanism != null)
  178. {
  179. int supportedMechanismLength2FieldSize = DerEncodingHelper.GetLengthFieldSize(token.SupportedMechanism.Length);
  180. int supportedMechanismLength1FieldSize = DerEncodingHelper.GetLengthFieldSize(1 + supportedMechanismLength2FieldSize + token.SupportedMechanism.Length);
  181. int supportedMechanismLength = 1 + supportedMechanismLength1FieldSize + 1 + supportedMechanismLength2FieldSize + token.SupportedMechanism.Length;
  182. result += supportedMechanismLength;
  183. }
  184. if (token.ResponseToken != null)
  185. {
  186. int responseToken2FieldSize = DerEncodingHelper.GetLengthFieldSize(token.ResponseToken.Length);
  187. int responseToken1FieldSize = DerEncodingHelper.GetLengthFieldSize(1 + responseToken2FieldSize + token.ResponseToken.Length);
  188. int responseTokenLength = 1 + responseToken1FieldSize + 1 + responseToken2FieldSize + token.ResponseToken.Length;
  189. result += responseTokenLength;
  190. }
  191. return result;
  192. }
  193. private static void WriteNegState(byte[] buffer, ref int offset, NegState negState)
  194. {
  195. ByteWriter.WriteByte(buffer, ref offset, NegStateTag);
  196. DerEncodingHelper.WriteLength(buffer, ref offset, 3);
  197. ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.Enum);
  198. DerEncodingHelper.WriteLength(buffer, ref offset, 1);
  199. ByteWriter.WriteByte(buffer, ref offset, (byte)negState);
  200. }
  201. private static void WriteSupportedMechanism(byte[] buffer, ref int offset, byte[] supportedMechanism)
  202. {
  203. int supportedMechanismLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(supportedMechanism.Length);
  204. ByteWriter.WriteByte(buffer, ref offset, SupportedMechanismTag);
  205. DerEncodingHelper.WriteLength(buffer, ref offset, 1 + supportedMechanismLengthFieldSize + supportedMechanism.Length);
  206. ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ObjectIdentifier);
  207. DerEncodingHelper.WriteLength(buffer, ref offset, supportedMechanism.Length);
  208. ByteWriter.WriteBytes(buffer, ref offset, supportedMechanism);
  209. }
  210. private static void WriteResponseToken(byte[] buffer, ref int offset, byte[] responseToken)
  211. {
  212. int responseTokenLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(responseToken.Length);
  213. ByteWriter.WriteByte(buffer, ref offset, ResponseTokenTag);
  214. DerEncodingHelper.WriteLength(buffer, ref offset, 1 + responseTokenLengthFieldSize + responseToken.Length);
  215. ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ByteArray);
  216. DerEncodingHelper.WriteLength(buffer, ref offset, responseToken.Length);
  217. ByteWriter.WriteBytes(buffer, ref offset, responseToken);
  218. }
  219. private static void WriteMechanismListMIC(byte[] buffer, ref int offset, byte[] mechanismListMIC)
  220. {
  221. int mechanismListMICLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(mechanismListMIC.Length);
  222. ByteWriter.WriteByte(buffer, ref offset, MechanismListMICTag);
  223. DerEncodingHelper.WriteLength(buffer, ref offset, 1 + mechanismListMICLengthFieldSize + mechanismListMIC.Length);
  224. ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ByteArray);
  225. DerEncodingHelper.WriteLength(buffer, ref offset, mechanismListMIC.Length);
  226. ByteWriter.WriteBytes(buffer, ref offset, mechanismListMIC);
  227. }
  228. }
  229. }