NegotiateResponse.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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 Utilities;
  10. namespace SMBLibrary.SMB2
  11. {
  12. /// <summary>
  13. /// SMB2 NEGOTIATE Response
  14. /// </summary>
  15. public class NegotiateResponse : SMB2Command
  16. {
  17. public const int FixedSize = 64;
  18. public const int DeclaredSize = 65;
  19. private ushort StructureSize;
  20. public SecurityMode SecurityMode;
  21. public SMB2Dialect DialectRevision;
  22. private ushort NegotiateContextCount;
  23. public Guid ServerGuid;
  24. public Capabilities Capabilities;
  25. public uint MaxTransactSize;
  26. public uint MaxReadSize;
  27. public uint MaxWriteSize;
  28. public DateTime SystemTime;
  29. public DateTime ServerStartTime;
  30. private ushort SecurityBufferOffset;
  31. private ushort SecurityBufferLength;
  32. private uint NegotiateContextOffset;
  33. public byte[] SecurityBuffer = new byte[0];
  34. public List<NegotiateContext> NegotiateContextList = new List<NegotiateContext>();
  35. public NegotiateResponse() : base(SMB2CommandName.Negotiate)
  36. {
  37. Header.IsResponse = true;
  38. StructureSize = DeclaredSize;
  39. }
  40. public NegotiateResponse(byte[] buffer, int offset) : base(buffer, offset)
  41. {
  42. StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
  43. SecurityMode = (SecurityMode)LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 2);
  44. DialectRevision = (SMB2Dialect)LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 4);
  45. NegotiateContextCount = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 6);
  46. ServerGuid = LittleEndianConverter.ToGuid(buffer, offset + SMB2Header.Length + 8);
  47. Capabilities = (Capabilities)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 24);
  48. MaxTransactSize = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 28);
  49. MaxReadSize = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 32);
  50. MaxWriteSize = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 36);
  51. SystemTime = DateTime.FromFileTimeUtc(LittleEndianConverter.ToInt64(buffer, offset + SMB2Header.Length + 40));
  52. ServerStartTime = DateTime.FromFileTimeUtc(LittleEndianConverter.ToInt64(buffer, offset + SMB2Header.Length + 48));
  53. SecurityBufferOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 56);
  54. SecurityBufferLength = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 58);
  55. NegotiateContextOffset = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 60);
  56. SecurityBuffer = ByteReader.ReadBytes(buffer, offset + SecurityBufferOffset, SecurityBufferLength);
  57. NegotiateContextList = NegotiateContext.ReadNegotiateContextList(buffer, (int)NegotiateContextOffset, NegotiateContextCount);
  58. }
  59. public override void WriteCommandBytes(byte[] buffer, int offset)
  60. {
  61. SecurityBufferOffset = 0;
  62. SecurityBufferLength = (ushort)SecurityBuffer.Length;
  63. int paddedSecurityBufferLength = (int)Math.Ceiling((double)SecurityBufferLength / 8) * 8;
  64. if (SecurityBuffer.Length > 0)
  65. {
  66. SecurityBufferOffset = SMB2Header.Length + FixedSize;
  67. }
  68. NegotiateContextOffset = 0;
  69. NegotiateContextCount = (ushort)NegotiateContextList.Count;
  70. if (NegotiateContextList.Count > 0)
  71. {
  72. // NegotiateContextList must be 8-byte aligned
  73. NegotiateContextOffset = (uint)(SMB2Header.Length + FixedSize + paddedSecurityBufferLength);
  74. }
  75. LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
  76. LittleEndianWriter.WriteUInt16(buffer, offset + 2, (ushort)SecurityMode);
  77. LittleEndianWriter.WriteUInt16(buffer, offset + 4, (ushort)DialectRevision);
  78. LittleEndianWriter.WriteUInt16(buffer, offset + 6, NegotiateContextCount);
  79. LittleEndianWriter.WriteGuidBytes(buffer, offset + 8, ServerGuid);
  80. LittleEndianWriter.WriteUInt32(buffer, offset + 24, (uint)Capabilities);
  81. LittleEndianWriter.WriteUInt32(buffer, offset + 28, MaxTransactSize);
  82. LittleEndianWriter.WriteUInt32(buffer, offset + 32, MaxReadSize);
  83. LittleEndianWriter.WriteUInt32(buffer, offset + 36, MaxWriteSize);
  84. LittleEndianWriter.WriteInt64(buffer, offset + 40, SystemTime.ToFileTimeUtc());
  85. LittleEndianWriter.WriteInt64(buffer, offset + 48, ServerStartTime.ToFileTimeUtc());
  86. LittleEndianWriter.WriteUInt16(buffer, offset + 56, SecurityBufferOffset);
  87. LittleEndianWriter.WriteUInt16(buffer, offset + 58, SecurityBufferLength);
  88. LittleEndianWriter.WriteUInt32(buffer, offset + 60, NegotiateContextOffset);
  89. ByteWriter.WriteBytes(buffer, offset + FixedSize, SecurityBuffer);
  90. NegotiateContext.WriteNegotiateContextList(buffer, offset + FixedSize + paddedSecurityBufferLength, NegotiateContextList);
  91. }
  92. public override int CommandLength
  93. {
  94. get
  95. {
  96. if (NegotiateContextList.Count == 0)
  97. {
  98. return FixedSize + SecurityBuffer.Length;
  99. }
  100. else
  101. {
  102. int paddedSecurityBufferLength = (int)Math.Ceiling((double)SecurityBufferLength / 8) * 8;
  103. return FixedSize + paddedSecurityBufferLength + NegotiateContext.GetNegotiateContextListLength(NegotiateContextList);
  104. }
  105. }
  106. }
  107. }
  108. }