SimpleProtectedNegotiationTokenResponse.cs 11 KB

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