2
0

SigningDigest.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. // This code is derived from jcifs smb client library <jcifs at samba dot org>
  2. // Ported by J. Arturo <webmaster at komodosoft dot net>
  3. //
  4. // This library is free software; you can redistribute it and/or
  5. // modify it under the terms of the GNU Lesser General Public
  6. // License as published by the Free Software Foundation; either
  7. // version 2.1 of the License, or (at your option) any later version.
  8. //
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. // Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public
  15. // License along with this library; if not, write to the Free Software
  16. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. using System;
  18. using SharpCifs.Util;
  19. using SharpCifs.Util.Sharpen;
  20. namespace SharpCifs.Smb
  21. {
  22. /// <summary>To filter 0 len updates and for debugging</summary>
  23. public class SigningDigest
  24. {
  25. internal static LogStream Log = LogStream.GetInstance();
  26. private MessageDigest _digest;
  27. private byte[] _macSigningKey;
  28. private bool _bypass;
  29. private int _updates;
  30. private int _signSequence;
  31. /// <exception cref="SharpCifs.Smb.SmbException"></exception>
  32. public SigningDigest(byte[] macSigningKey, bool bypass)
  33. {
  34. try
  35. {
  36. _digest = MessageDigest.GetInstance("MD5");
  37. }
  38. catch (NoSuchAlgorithmException ex)
  39. {
  40. if (Log.Level > 0)
  41. {
  42. Runtime.PrintStackTrace(ex, Log);
  43. }
  44. throw new SmbException("MD5", ex);
  45. }
  46. this._macSigningKey = macSigningKey;
  47. this._bypass = bypass;
  48. _updates = 0;
  49. _signSequence = 0;
  50. if (Log.Level >= 5)
  51. {
  52. Log.WriteLine("macSigningKey:");
  53. Hexdump.ToHexdump(Log, macSigningKey, 0, macSigningKey.Length);
  54. }
  55. }
  56. /// <exception cref="SharpCifs.Smb.SmbException"></exception>
  57. public SigningDigest(SmbTransport transport, NtlmPasswordAuthentication auth)
  58. {
  59. try
  60. {
  61. _digest = MessageDigest.GetInstance("MD5");
  62. }
  63. catch (NoSuchAlgorithmException ex)
  64. {
  65. if (Log.Level > 0)
  66. {
  67. Runtime.PrintStackTrace(ex, Log);
  68. }
  69. throw new SmbException("MD5", ex);
  70. }
  71. try
  72. {
  73. switch (SmbConstants.LmCompatibility)
  74. {
  75. case 0:
  76. case 1:
  77. case 2:
  78. {
  79. _macSigningKey = new byte[40];
  80. auth.GetUserSessionKey(transport.Server.EncryptionKey, _macSigningKey, 0);
  81. Array.Copy(auth.GetUnicodeHash(transport.Server.EncryptionKey), 0, _macSigningKey
  82. , 16, 24);
  83. break;
  84. }
  85. case 3:
  86. case 4:
  87. case 5:
  88. {
  89. _macSigningKey = new byte[16];
  90. auth.GetUserSessionKey(transport.Server.EncryptionKey, _macSigningKey, 0);
  91. break;
  92. }
  93. default:
  94. {
  95. _macSigningKey = new byte[40];
  96. auth.GetUserSessionKey(transport.Server.EncryptionKey, _macSigningKey, 0);
  97. Array.Copy(auth.GetUnicodeHash(transport.Server.EncryptionKey), 0, _macSigningKey
  98. , 16, 24);
  99. break;
  100. }
  101. }
  102. }
  103. catch (Exception ex)
  104. {
  105. throw new SmbException(string.Empty, ex);
  106. }
  107. if (Log.Level >= 5)
  108. {
  109. Log.WriteLine("LM_COMPATIBILITY=" + SmbConstants.LmCompatibility);
  110. Hexdump.ToHexdump(Log, _macSigningKey, 0, _macSigningKey.Length);
  111. }
  112. }
  113. public virtual void Update(byte[] input, int offset, int len)
  114. {
  115. if (Log.Level >= 5)
  116. {
  117. Log.WriteLine("update: " + _updates + " " + offset + ":" + len);
  118. Hexdump.ToHexdump(Log, input, offset, Math.Min(len, 256));
  119. Log.Flush();
  120. }
  121. if (len == 0)
  122. {
  123. return;
  124. }
  125. _digest.Update(input, offset, len);
  126. _updates++;
  127. }
  128. public virtual byte[] Digest()
  129. {
  130. byte[] b;
  131. b = _digest.Digest();
  132. if (Log.Level >= 5)
  133. {
  134. Log.WriteLine("digest: ");
  135. Hexdump.ToHexdump(Log, b, 0, b.Length);
  136. Log.Flush();
  137. }
  138. _updates = 0;
  139. return b;
  140. }
  141. /// <summary>Performs MAC signing of the SMB.</summary>
  142. /// <remarks>
  143. /// Performs MAC signing of the SMB. This is done as follows.
  144. /// The signature field of the SMB is overwritted with the sequence number;
  145. /// The MD5 digest of the MAC signing key + the entire SMB is taken;
  146. /// The first 8 bytes of this are placed in the signature field.
  147. /// </remarks>
  148. /// <param name="data">The data.</param>
  149. /// <param name="offset">The starting offset at which the SMB header begins.</param>
  150. /// <param name="length">The length of the SMB data starting at offset.</param>
  151. internal virtual void Sign(byte[] data, int offset, int length, ServerMessageBlock
  152. request, ServerMessageBlock response)
  153. {
  154. request.SignSeq = _signSequence;
  155. if (response != null)
  156. {
  157. response.SignSeq = _signSequence + 1;
  158. response.VerifyFailed = false;
  159. }
  160. try
  161. {
  162. Update(_macSigningKey, 0, _macSigningKey.Length);
  163. int index = offset + SmbConstants.SignatureOffset;
  164. for (int i = 0; i < 8; i++)
  165. {
  166. data[index + i] = 0;
  167. }
  168. ServerMessageBlock.WriteInt4(_signSequence, data, index);
  169. Update(data, offset, length);
  170. Array.Copy(Digest(), 0, data, index, 8);
  171. if (_bypass)
  172. {
  173. _bypass = false;
  174. Array.Copy(Runtime.GetBytesForString("BSRSPYL "), 0, data, index,
  175. 8);
  176. }
  177. }
  178. catch (Exception ex)
  179. {
  180. if (Log.Level > 0)
  181. {
  182. Runtime.PrintStackTrace(ex, Log);
  183. }
  184. }
  185. finally
  186. {
  187. _signSequence += 2;
  188. }
  189. }
  190. /// <summary>Performs MAC signature verification.</summary>
  191. /// <remarks>
  192. /// Performs MAC signature verification. This calculates the signature
  193. /// of the SMB and compares it to the signature field on the SMB itself.
  194. /// </remarks>
  195. /// <param name="data">The data.</param>
  196. /// <param name="offset">The starting offset at which the SMB header begins.</param>
  197. /// <param name="length">The length of the SMB data starting at offset.</param>
  198. internal virtual bool Verify(byte[] data, int offset, ServerMessageBlock response
  199. )
  200. {
  201. Update(_macSigningKey, 0, _macSigningKey.Length);
  202. int index = offset;
  203. Update(data, index, SmbConstants.SignatureOffset);
  204. index += SmbConstants.SignatureOffset;
  205. byte[] sequence = new byte[8];
  206. ServerMessageBlock.WriteInt4(response.SignSeq, sequence, 0);
  207. Update(sequence, 0, sequence.Length);
  208. index += 8;
  209. if (response.Command == ServerMessageBlock.SmbComReadAndx)
  210. {
  211. SmbComReadAndXResponse raxr = (SmbComReadAndXResponse)response;
  212. int length = response.Length - raxr.DataLength;
  213. Update(data, index, length - SmbConstants.SignatureOffset - 8);
  214. Update(raxr.B, raxr.Off, raxr.DataLength);
  215. }
  216. else
  217. {
  218. Update(data, index, response.Length - SmbConstants.SignatureOffset - 8);
  219. }
  220. byte[] signature = Digest();
  221. for (int i = 0; i < 8; i++)
  222. {
  223. if (signature[i] != data[offset + SmbConstants.SignatureOffset + i])
  224. {
  225. if (Log.Level >= 2)
  226. {
  227. Log.WriteLine("signature verification failure");
  228. Hexdump.ToHexdump(Log, signature, 0, 8);
  229. Hexdump.ToHexdump(Log, data, offset + SmbConstants.SignatureOffset, 8);
  230. }
  231. return response.VerifyFailed = true;
  232. }
  233. }
  234. return response.VerifyFailed = false;
  235. }
  236. public override string ToString()
  237. {
  238. return "LM_COMPATIBILITY=" + SmbConstants.LmCompatibility + " MacSigningKey=" + Hexdump.ToHexString
  239. (_macSigningKey, 0, _macSigningKey.Length);
  240. }
  241. }
  242. }