SessionPacket.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /* Copyright (C) 2014-2020 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.NetBios
  12. {
  13. /// <summary>
  14. /// [RFC 1002] 4.3.1. SESSION PACKET
  15. /// [MS-SMB2] 2.1 Transport - Direct TCP transport packet
  16. /// </summary>
  17. /// <remarks>
  18. /// We extend this implementation to support Direct TCP transport packet which utilize the unused session packet flags to extend the maximum trailer length.
  19. /// </remarks>
  20. public abstract class SessionPacket
  21. {
  22. public const int HeaderLength = 4;
  23. public const int MaxSessionPacketLength = 131075;
  24. public const int MaxDirectTcpPacketLength = 16777215;
  25. public SessionPacketTypeName Type;
  26. private int TrailerLength; // Session packet: 17 bits, Direct TCP transport packet: 3 bytes
  27. public byte[] Trailer;
  28. public SessionPacket()
  29. {
  30. }
  31. public SessionPacket(byte[] buffer, int offset)
  32. {
  33. Type = (SessionPacketTypeName)ByteReader.ReadByte(buffer, offset + 0);
  34. TrailerLength = ByteReader.ReadByte(buffer, offset + 1) << 16 | BigEndianConverter.ToUInt16(buffer, offset + 2);
  35. Trailer = ByteReader.ReadBytes(buffer, offset + 4, TrailerLength);
  36. }
  37. public virtual byte[] GetBytes()
  38. {
  39. TrailerLength = this.Trailer.Length;
  40. byte flags = Convert.ToByte(TrailerLength >> 16);
  41. byte[] buffer = new byte[HeaderLength + Trailer.Length];
  42. ByteWriter.WriteByte(buffer, 0, (byte)Type);
  43. ByteWriter.WriteByte(buffer, 1, flags);
  44. BigEndianWriter.WriteUInt16(buffer, 2, (ushort)(TrailerLength & 0xFFFF));
  45. ByteWriter.WriteBytes(buffer, 4, Trailer);
  46. return buffer;
  47. }
  48. public virtual int Length
  49. {
  50. get
  51. {
  52. return HeaderLength + Trailer.Length;
  53. }
  54. }
  55. public static int GetSessionPacketLength(byte[] buffer, int offset)
  56. {
  57. int trailerLength = ByteReader.ReadByte(buffer, offset + 1) << 16 | BigEndianConverter.ToUInt16(buffer, offset + 2);
  58. return 4 + trailerLength;
  59. }
  60. public static SessionPacket GetSessionPacket(byte[] buffer, int offset)
  61. {
  62. SessionPacketTypeName type = (SessionPacketTypeName)ByteReader.ReadByte(buffer, offset);
  63. switch (type)
  64. {
  65. case SessionPacketTypeName.SessionMessage:
  66. return new SessionMessagePacket(buffer, offset);
  67. case SessionPacketTypeName.SessionRequest:
  68. return new SessionRequestPacket(buffer, offset);
  69. case SessionPacketTypeName.PositiveSessionResponse:
  70. return new PositiveSessionResponsePacket(buffer, offset);
  71. case SessionPacketTypeName.NegativeSessionResponse:
  72. return new NegativeSessionResponsePacket(buffer, offset);
  73. case SessionPacketTypeName.RetargetSessionResponse:
  74. return new SessionRetargetResponsePacket(buffer, offset);
  75. case SessionPacketTypeName.SessionKeepAlive:
  76. return new SessionKeepAlivePacket(buffer, offset);
  77. default:
  78. throw new InvalidDataException("Invalid NetBIOS session packet type: 0x" + ((byte)type).ToString("X2"));
  79. }
  80. }
  81. }
  82. }