CreateRequest.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /* Copyright (C) 2018 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 CREATE Request
  14. /// </summary>
  15. public class CreateRequest : SMB2Command
  16. {
  17. public const int FixedLength = 56;
  18. public const int DeclaredSize = 57;
  19. private ushort StructureSize;
  20. public byte SecurityFlags; // Reserved
  21. public OplockLevel RequestedOplockLevel;
  22. public ImpersonationLevel ImpersonationLevel;
  23. public ulong SmbCreateFlags;
  24. public ulong Reserved;
  25. public AccessMask DesiredAccess;
  26. public FileAttributes FileAttributes;
  27. public ShareAccess ShareAccess;
  28. public CreateDisposition CreateDisposition;
  29. public CreateOptions CreateOptions;
  30. private ushort NameOffset;
  31. private ushort NameLength;
  32. private uint CreateContextsOffset; // 8-byte aligned
  33. private uint CreateContextsLength;
  34. public string Name;
  35. public List<CreateContext> CreateContexts = new List<CreateContext>();
  36. public CreateRequest() : base(SMB2CommandName.Create)
  37. {
  38. StructureSize = DeclaredSize;
  39. }
  40. public CreateRequest(byte[] buffer, int offset) : base(buffer, offset)
  41. {
  42. StructureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0);
  43. SecurityFlags = ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 2);
  44. RequestedOplockLevel = (OplockLevel)ByteReader.ReadByte(buffer, offset + SMB2Header.Length + 3);
  45. ImpersonationLevel = (ImpersonationLevel)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 4);
  46. SmbCreateFlags = LittleEndianConverter.ToUInt64(buffer, offset + SMB2Header.Length + 8);
  47. Reserved = LittleEndianConverter.ToUInt64(buffer, offset + SMB2Header.Length + 16);
  48. DesiredAccess = (AccessMask)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 24);
  49. FileAttributes = (FileAttributes)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 28);
  50. ShareAccess = (ShareAccess)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 32);
  51. CreateDisposition = (CreateDisposition)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 36);
  52. CreateOptions = (CreateOptions)LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 40);
  53. NameOffset = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 44);
  54. NameLength = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 46);
  55. CreateContextsOffset = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 48);
  56. CreateContextsLength = LittleEndianConverter.ToUInt32(buffer, offset + SMB2Header.Length + 52);
  57. Name = ByteReader.ReadUTF16String(buffer, offset + NameOffset, NameLength / 2);
  58. if (CreateContextsLength > 0)
  59. {
  60. CreateContexts = CreateContext.ReadCreateContextList(buffer, (int)CreateContextsOffset);
  61. }
  62. }
  63. public override void WriteCommandBytes(byte[] buffer, int offset)
  64. {
  65. // [MS-SMB2] The NameOffset field SHOULD be set to the offset of the Buffer field from the beginning of the SMB2 header.
  66. // Note: Windows 8.1 / 10 will return STATUS_INVALID_PARAMETER if NameOffset is set to 0.
  67. NameOffset = SMB2Header.Length + FixedLength;
  68. NameLength = (ushort)(Name.Length * 2);
  69. CreateContextsOffset = 0;
  70. CreateContextsLength = 0;
  71. int paddedNameLength = (int)Math.Ceiling((double)(Name.Length * 2) / 8) * 8;
  72. if (CreateContexts.Count > 0)
  73. {
  74. CreateContextsOffset = (uint)(SMB2Header.Length + FixedLength + paddedNameLength);
  75. CreateContextsLength = (uint)CreateContext.GetCreateContextListLength(CreateContexts);
  76. }
  77. LittleEndianWriter.WriteUInt16(buffer, offset + 0, StructureSize);
  78. ByteWriter.WriteByte(buffer, offset + 2, SecurityFlags);
  79. ByteWriter.WriteByte(buffer, offset + 3, (byte)RequestedOplockLevel);
  80. LittleEndianWriter.WriteUInt32(buffer, offset + 4, (uint)ImpersonationLevel);
  81. LittleEndianWriter.WriteUInt64(buffer, offset + 8, (ulong)SmbCreateFlags);
  82. LittleEndianWriter.WriteUInt64(buffer, offset + 16, (ulong)Reserved);
  83. LittleEndianWriter.WriteUInt32(buffer, offset + 24, (uint)DesiredAccess);
  84. LittleEndianWriter.WriteUInt32(buffer, offset + 28, (uint)FileAttributes);
  85. LittleEndianWriter.WriteUInt32(buffer, offset + 32, (uint)ShareAccess);
  86. LittleEndianWriter.WriteUInt32(buffer, offset + 36, (uint)CreateDisposition);
  87. LittleEndianWriter.WriteUInt32(buffer, offset + 40, (uint)CreateOptions);
  88. LittleEndianWriter.WriteUInt16(buffer, offset + 44, NameOffset);
  89. LittleEndianWriter.WriteUInt16(buffer, offset + 46, NameLength);
  90. LittleEndianWriter.WriteUInt32(buffer, offset + 48, CreateContextsOffset);
  91. LittleEndianWriter.WriteUInt32(buffer, offset + 52, CreateContextsLength);
  92. ByteWriter.WriteUTF16String(buffer, offset + 56, Name);
  93. CreateContext.WriteCreateContextList(buffer, offset + 56 + paddedNameLength, CreateContexts);
  94. }
  95. public override int CommandLength
  96. {
  97. get
  98. {
  99. int bufferLength;
  100. if (CreateContexts.Count == 0)
  101. {
  102. bufferLength = Name.Length * 2;
  103. }
  104. else
  105. {
  106. int paddedNameLength = (int)Math.Ceiling((double)(Name.Length * 2) / 8) * 8;
  107. bufferLength = paddedNameLength + CreateContext.GetCreateContextListLength(CreateContexts);
  108. }
  109. // [MS-SMB2] The Buffer field MUST be at least one byte in length.
  110. return FixedLength + Math.Max(bufferLength, 1);
  111. }
  112. }
  113. }
  114. }