SimpleProtectedNegotiationTokenResponse.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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. /// <param name="offset">The offset following the NegTokenResp tag</param>
  42. public SimpleProtectedNegotiationTokenResponse(byte[] buffer, int offset)
  43. {
  44. int constuctionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
  45. int sequenceEndOffset = offset + constuctionLength;
  46. byte tag = ByteReader.ReadByte(buffer, ref offset);
  47. if (tag != (byte)DerEncodingTag.Sequence)
  48. {
  49. throw new InvalidDataException();
  50. }
  51. while (offset < sequenceEndOffset)
  52. {
  53. int entryLength = DerEncodingHelper.ReadLength(buffer, ref offset);
  54. int entryEndOffset = offset + entryLength;
  55. TokenResponseEntry entry = new TokenResponseEntry();
  56. while (offset < entryEndOffset)
  57. {
  58. tag = ByteReader.ReadByte(buffer, ref offset);
  59. if (tag == NegStateTag)
  60. {
  61. entry.NegState = ReadNegState(buffer, ref offset);
  62. }
  63. else if (tag == SupportedMechanismTag)
  64. {
  65. entry.SupportedMechanism = ReadSupportedMechanism(buffer, ref offset);
  66. }
  67. else if (tag == ResponseTokenTag)
  68. {
  69. entry.ResponseToken = ReadResponseToken(buffer, ref offset);
  70. }
  71. else if (tag == MechanismListMICTag)
  72. {
  73. entry.MechanismListMIC = ReadMechanismListMIC(buffer, ref offset);
  74. }
  75. else
  76. {
  77. throw new InvalidDataException("Invalid negTokenResp structure");
  78. }
  79. }
  80. Tokens.Add(entry);
  81. }
  82. }
  83. public override byte[] GetBytes()
  84. {
  85. int sequenceLength = 0;
  86. foreach (TokenResponseEntry token in Tokens)
  87. {
  88. int entryLength = GetEntryLength(token);
  89. sequenceLength += DerEncodingHelper.GetLengthFieldSize(entryLength) + entryLength;
  90. }
  91. int constructionLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(1 + sequenceLength);
  92. int bufferSize = 1 + constructionLengthFieldSize + 1 + sequenceLength;
  93. byte[] buffer = new byte[bufferSize];
  94. int offset = 0;
  95. ByteWriter.WriteByte(buffer, ref offset, NegTokenRespTag);
  96. DerEncodingHelper.WriteLength(buffer, ref offset, 1 + sequenceLength);
  97. ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.Sequence);
  98. foreach (TokenResponseEntry token in Tokens)
  99. {
  100. int entryLength = GetEntryLength(token);
  101. DerEncodingHelper.WriteLength(buffer, ref offset, entryLength);
  102. if (token.NegState.HasValue)
  103. {
  104. WriteNegState(buffer, ref offset, token.NegState.Value);
  105. }
  106. if (token.SupportedMechanism != null)
  107. {
  108. WriteSupportedMechanism(buffer, ref offset, token.SupportedMechanism);
  109. }
  110. if (token.ResponseToken != null)
  111. {
  112. WriteResponseToken(buffer, ref offset, token.ResponseToken);
  113. }
  114. if (token.MechanismListMIC != null)
  115. {
  116. WriteMechanismListMIC(buffer, ref offset, token.MechanismListMIC);
  117. }
  118. }
  119. return buffer;
  120. }
  121. private static NegState ReadNegState(byte[] buffer, ref int offset)
  122. {
  123. int length = DerEncodingHelper.ReadLength(buffer, ref offset);
  124. byte tag = ByteReader.ReadByte(buffer, ref offset);
  125. if (tag != (byte)DerEncodingTag.Enum)
  126. {
  127. throw new InvalidDataException();
  128. }
  129. length = DerEncodingHelper.ReadLength(buffer, ref offset);
  130. return (NegState)ByteReader.ReadByte(buffer, ref offset);
  131. }
  132. private static byte[] ReadSupportedMechanism(byte[] buffer, ref int offset)
  133. {
  134. int constructionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
  135. byte tag = ByteReader.ReadByte(buffer, ref offset);
  136. if (tag != (byte)DerEncodingTag.ObjectIdentifier)
  137. {
  138. throw new InvalidDataException();
  139. }
  140. int length = DerEncodingHelper.ReadLength(buffer, ref offset);
  141. return ByteReader.ReadBytes(buffer, ref offset, length);
  142. }
  143. private static byte[] ReadResponseToken(byte[] buffer, ref int offset)
  144. {
  145. int constructionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
  146. byte tag = ByteReader.ReadByte(buffer, ref offset);
  147. if (tag != (byte)DerEncodingTag.ByteArray)
  148. {
  149. throw new InvalidDataException();
  150. }
  151. int length = DerEncodingHelper.ReadLength(buffer, ref offset);
  152. return ByteReader.ReadBytes(buffer, ref offset, length);
  153. }
  154. private static byte[] ReadMechanismListMIC(byte[] buffer, ref int offset)
  155. {
  156. int constructionLength = DerEncodingHelper.ReadLength(buffer, ref offset);
  157. byte tag = ByteReader.ReadByte(buffer, ref offset);
  158. if (tag != (byte)DerEncodingTag.ByteArray)
  159. {
  160. throw new InvalidDataException();
  161. }
  162. int length = DerEncodingHelper.ReadLength(buffer, ref offset);
  163. return ByteReader.ReadBytes(buffer, ref offset, length);
  164. }
  165. private static int GetEntryLength(TokenResponseEntry token)
  166. {
  167. int result = 0;
  168. if (token.NegState.HasValue)
  169. {
  170. int negStateLength = 5;
  171. result += negStateLength;
  172. }
  173. if (token.SupportedMechanism != null)
  174. {
  175. int supportedMechanismLength2FieldSize = DerEncodingHelper.GetLengthFieldSize(token.SupportedMechanism.Length);
  176. int supportedMechanismLength1FieldSize = DerEncodingHelper.GetLengthFieldSize(1 + supportedMechanismLength2FieldSize + token.SupportedMechanism.Length);
  177. int supportedMechanismLength = 1 + supportedMechanismLength1FieldSize + 1 + supportedMechanismLength2FieldSize + token.SupportedMechanism.Length;
  178. result += supportedMechanismLength;
  179. }
  180. if (token.ResponseToken != null)
  181. {
  182. int responseToken2FieldSize = DerEncodingHelper.GetLengthFieldSize(token.ResponseToken.Length);
  183. int responseToken1FieldSize = DerEncodingHelper.GetLengthFieldSize(1 + responseToken2FieldSize + token.ResponseToken.Length);
  184. int responseTokenLength = 1 + responseToken1FieldSize + 1 + responseToken2FieldSize + token.ResponseToken.Length;
  185. result += responseTokenLength;
  186. }
  187. return result;
  188. }
  189. private static void WriteNegState(byte[] buffer, ref int offset, NegState negState)
  190. {
  191. ByteWriter.WriteByte(buffer, ref offset, NegStateTag);
  192. DerEncodingHelper.WriteLength(buffer, ref offset, 3);
  193. ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.Enum);
  194. DerEncodingHelper.WriteLength(buffer, ref offset, 1);
  195. ByteWriter.WriteByte(buffer, ref offset, (byte)negState);
  196. }
  197. private static void WriteSupportedMechanism(byte[] buffer, ref int offset, byte[] supportedMechanism)
  198. {
  199. int supportedMechanismLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(supportedMechanism.Length);
  200. ByteWriter.WriteByte(buffer, ref offset, SupportedMechanismTag);
  201. DerEncodingHelper.WriteLength(buffer, ref offset, 1 + supportedMechanismLengthFieldSize + supportedMechanism.Length);
  202. ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ObjectIdentifier);
  203. DerEncodingHelper.WriteLength(buffer, ref offset, supportedMechanism.Length);
  204. ByteWriter.WriteBytes(buffer, ref offset, supportedMechanism);
  205. }
  206. private static void WriteResponseToken(byte[] buffer, ref int offset, byte[] responseToken)
  207. {
  208. int responseTokenLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(responseToken.Length);
  209. ByteWriter.WriteByte(buffer, ref offset, ResponseTokenTag);
  210. DerEncodingHelper.WriteLength(buffer, ref offset, 1 + responseTokenLengthFieldSize + responseToken.Length);
  211. ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ByteArray);
  212. DerEncodingHelper.WriteLength(buffer, ref offset, responseToken.Length);
  213. ByteWriter.WriteBytes(buffer, ref offset, responseToken);
  214. }
  215. private static void WriteMechanismListMIC(byte[] buffer, ref int offset, byte[] mechanismListMIC)
  216. {
  217. int mechanismListMICLengthFieldSize = DerEncodingHelper.GetLengthFieldSize(mechanismListMIC.Length);
  218. ByteWriter.WriteByte(buffer, ref offset, MechanismListMICTag);
  219. DerEncodingHelper.WriteLength(buffer, ref offset, 1 + mechanismListMICLengthFieldSize + mechanismListMIC.Length);
  220. ByteWriter.WriteByte(buffer, ref offset, (byte)DerEncodingTag.ByteArray);
  221. DerEncodingHelper.WriteLength(buffer, ref offset, mechanismListMIC.Length);
  222. ByteWriter.WriteBytes(buffer, ref offset, mechanismListMIC);
  223. }
  224. }
  225. }