ReadWriteResponseHelper.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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 System.Text;
  11. using SMBLibrary.RPC;
  12. using SMBLibrary.SMB1;
  13. using SMBLibrary.Services;
  14. using Utilities;
  15. namespace SMBLibrary.Server.SMB1
  16. {
  17. public class ReadWriteResponseHelper
  18. {
  19. internal static SMB1Command GetReadResponse(SMB1Header header, ReadRequest request, ISMBShare share, SMB1ConnectionState state)
  20. {
  21. SMB1Session session = state.GetSession(header.UID);
  22. OpenFileObject openFile = session.GetOpenFileObject(request.FID);
  23. if (openFile == null)
  24. {
  25. header.Status = NTStatus.STATUS_INVALID_HANDLE;
  26. return null;
  27. }
  28. if (share is FileSystemShare)
  29. {
  30. if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, openFile.Path))
  31. {
  32. header.Status = NTStatus.STATUS_ACCESS_DENIED;
  33. return new ErrorResponse(request.CommandName);
  34. }
  35. }
  36. byte[] data;
  37. header.Status = share.FileStore.ReadFile(out data, openFile.Handle, request.ReadOffsetInBytes, request.CountOfBytesToRead);
  38. if (header.Status != NTStatus.STATUS_SUCCESS)
  39. {
  40. return new ErrorResponse(request.CommandName);
  41. }
  42. ReadResponse response = new ReadResponse();
  43. response.Bytes = data;
  44. response.CountOfBytesReturned = (ushort)data.Length;
  45. return response;
  46. }
  47. internal static SMB1Command GetReadResponse(SMB1Header header, ReadAndXRequest request, ISMBShare share, SMB1ConnectionState state)
  48. {
  49. SMB1Session session = state.GetSession(header.UID);
  50. OpenFileObject openFile = session.GetOpenFileObject(request.FID);
  51. if (openFile == null)
  52. {
  53. header.Status = NTStatus.STATUS_INVALID_HANDLE;
  54. return null;
  55. }
  56. if (share is FileSystemShare)
  57. {
  58. if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, openFile.Path))
  59. {
  60. header.Status = NTStatus.STATUS_ACCESS_DENIED;
  61. return new ErrorResponse(request.CommandName);
  62. }
  63. }
  64. uint maxCount = request.MaxCount;
  65. if ((share is FileSystemShare) && state.LargeRead)
  66. {
  67. maxCount = request.MaxCountLarge;
  68. }
  69. byte[] data;
  70. header.Status = share.FileStore.ReadFile(out data, openFile.Handle, (long)request.Offset, (int)maxCount);
  71. if (header.Status != NTStatus.STATUS_SUCCESS)
  72. {
  73. return new ErrorResponse(request.CommandName);
  74. }
  75. ReadAndXResponse response = new ReadAndXResponse();
  76. if (share is FileSystemShare)
  77. {
  78. // If the client reads from a disk file, this field MUST be set to -1 (0xFFFF)
  79. response.Available = 0xFFFF;
  80. }
  81. response.Data = data;
  82. return response;
  83. }
  84. internal static SMB1Command GetWriteResponse(SMB1Header header, WriteRequest request, ISMBShare share, SMB1ConnectionState state)
  85. {
  86. SMB1Session session = state.GetSession(header.UID);
  87. OpenFileObject openFile = session.GetOpenFileObject(request.FID);
  88. if (openFile == null)
  89. {
  90. header.Status = NTStatus.STATUS_INVALID_HANDLE;
  91. return new ErrorResponse(request.CommandName);
  92. }
  93. if (share is FileSystemShare)
  94. {
  95. if (!((FileSystemShare)share).HasWriteAccess(session.SecurityContext, openFile.Path))
  96. {
  97. header.Status = NTStatus.STATUS_ACCESS_DENIED;
  98. return new ErrorResponse(request.CommandName);
  99. }
  100. }
  101. int numberOfBytesWritten;
  102. header.Status = share.FileStore.WriteFile(out numberOfBytesWritten, openFile.Handle, request.WriteOffsetInBytes, request.Data);
  103. if (header.Status != NTStatus.STATUS_SUCCESS)
  104. {
  105. return new ErrorResponse(request.CommandName);
  106. }
  107. WriteResponse response = new WriteResponse();
  108. response.CountOfBytesWritten = (ushort)numberOfBytesWritten;
  109. return response;
  110. }
  111. internal static SMB1Command GetWriteResponse(SMB1Header header, WriteAndXRequest request, ISMBShare share, SMB1ConnectionState state)
  112. {
  113. SMB1Session session = state.GetSession(header.UID);
  114. OpenFileObject openFile = session.GetOpenFileObject(request.FID);
  115. if (openFile == null)
  116. {
  117. header.Status = NTStatus.STATUS_INVALID_HANDLE;
  118. return new ErrorResponse(request.CommandName);
  119. }
  120. if (share is FileSystemShare)
  121. {
  122. if (!((FileSystemShare)share).HasWriteAccess(session.SecurityContext, openFile.Path))
  123. {
  124. header.Status = NTStatus.STATUS_ACCESS_DENIED;
  125. return new ErrorResponse(request.CommandName);
  126. }
  127. }
  128. int numberOfBytesWritten;
  129. header.Status = share.FileStore.WriteFile(out numberOfBytesWritten, openFile.Handle, (long)request.Offset, request.Data);
  130. if (header.Status != NTStatus.STATUS_SUCCESS)
  131. {
  132. return new ErrorResponse(request.CommandName);
  133. }
  134. WriteAndXResponse response = new WriteAndXResponse();
  135. response.Count = (uint)numberOfBytesWritten;
  136. if (share is FileSystemShare)
  137. {
  138. // If the client wrote to a disk file, this field MUST be set to 0xFFFF.
  139. response.Available = 0xFFFF;
  140. }
  141. return response;
  142. }
  143. }
  144. }