SMB1Message.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /* Copyright (C) 2014-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.SMB1
  12. {
  13. /// <summary>
  14. /// Each message has a single header and either a single command or multiple batched (AndX) commands.
  15. /// Multiple command requests or responses can be sent in a single message.
  16. /// </summary>
  17. public class SMB1Message
  18. {
  19. public SMB1Header Header;
  20. public List<SMB1Command> Commands = new List<SMB1Command>();
  21. public SMB1Message()
  22. {
  23. Header = new SMB1Header();
  24. }
  25. public SMB1Message(byte[] buffer)
  26. {
  27. Header = new SMB1Header(buffer);
  28. SMB1Command command = SMB1Command.ReadCommand(buffer, SMB1Header.Length, Header.Command, Header);
  29. Commands.Add(command);
  30. while(command is SMBAndXCommand)
  31. {
  32. SMBAndXCommand andXCommand = (SMBAndXCommand)command;
  33. if (andXCommand.AndXCommand == CommandName.SMB_COM_NO_ANDX_COMMAND)
  34. {
  35. break;
  36. }
  37. command = SMB1Command.ReadCommand(buffer, andXCommand.AndXOffset, andXCommand.AndXCommand, Header);
  38. Commands.Add(command);
  39. }
  40. }
  41. public byte[] GetBytes()
  42. {
  43. if (Commands.Count == 0)
  44. {
  45. throw new ArgumentException("Invalid command sequence");
  46. }
  47. for (int index = 0; index < Commands.Count - 1; index++)
  48. {
  49. if (!(Commands[index] is SMBAndXCommand))
  50. {
  51. throw new ArgumentException("Invalid command sequence");
  52. }
  53. }
  54. SMB1Command lastCommand = Commands[Commands.Count - 1];
  55. if (lastCommand is SMBAndXCommand)
  56. {
  57. ((SMBAndXCommand)lastCommand).AndXCommand = CommandName.SMB_COM_NO_ANDX_COMMAND;
  58. }
  59. List<byte[]> sequence = new List<byte[]>();
  60. int length = SMB1Header.Length;
  61. byte[] commandBytes;
  62. for (int index = 0; index < Commands.Count - 1; index++)
  63. {
  64. SMBAndXCommand andXCommand = (SMBAndXCommand)Commands[index];
  65. andXCommand.AndXCommand = Commands[index + 1].CommandName;
  66. commandBytes = Commands[index].GetBytes(Header.UnicodeFlag);
  67. ushort nextOffset = (ushort)(length + commandBytes.Length);
  68. SMBAndXCommand.WriteAndXOffset(commandBytes, 0, nextOffset);
  69. sequence.Add(commandBytes);
  70. length += commandBytes.Length;
  71. }
  72. commandBytes = lastCommand.GetBytes(Header.UnicodeFlag);
  73. sequence.Add(commandBytes);
  74. length += commandBytes.Length;
  75. Header.Command = Commands[0].CommandName;
  76. byte[] buffer = new byte[length];
  77. Header.WriteBytes(buffer, 0);
  78. int offset = SMB1Header.Length;
  79. foreach (byte[] bytes in sequence)
  80. {
  81. ByteWriter.WriteBytes(buffer, ref offset, bytes);
  82. }
  83. return buffer;
  84. }
  85. public static SMB1Message GetSMB1Message(byte[] buffer)
  86. {
  87. if (!SMB1Header.IsValidSMB1Header(buffer))
  88. {
  89. throw new InvalidDataException("Invalid SMB header signature");
  90. }
  91. return new SMB1Message(buffer);
  92. }
  93. }
  94. }