TreeConnectHelper.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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.Text;
  10. using SMBLibrary.SMB1;
  11. using Utilities;
  12. namespace SMBLibrary.Server.SMB1
  13. {
  14. public class TreeConnectHelper
  15. {
  16. internal static SMB1Command GetTreeConnectResponse(SMB1Header header, TreeConnectAndXRequest request, SMB1ConnectionState state, ShareCollection shares)
  17. {
  18. bool isExtended = (request.Flags & TreeConnectFlags.ExtendedResponse) > 0;
  19. string relativePath = ServerPathUtils.GetRelativeServerPath(request.Path);
  20. if (String.Equals(relativePath, "\\IPC$", StringComparison.InvariantCultureIgnoreCase))
  21. {
  22. ushort? treeID = state.AddConnectedTree(relativePath);
  23. if (!treeID.HasValue)
  24. {
  25. header.Status = NTStatus.STATUS_INSUFF_SERVER_RESOURCES;
  26. return new ErrorResponse(CommandName.SMB_COM_TREE_CONNECT_ANDX);
  27. }
  28. header.TID = treeID.Value;
  29. if (isExtended)
  30. {
  31. return CreateTreeConnectResponseExtended(ServiceName.NamedPipe);
  32. }
  33. else
  34. {
  35. return CreateTreeConnectResponse(ServiceName.NamedPipe);
  36. }
  37. }
  38. else
  39. {
  40. FileSystemShare share = shares.GetShareFromRelativePath(relativePath);
  41. if (share == null)
  42. {
  43. header.Status = NTStatus.STATUS_OBJECT_PATH_NOT_FOUND;
  44. return new ErrorResponse(CommandName.SMB_COM_TREE_CONNECT_ANDX);
  45. }
  46. else
  47. {
  48. string userName = state.GetConnectedUserName(header.UID);
  49. if (!share.HasReadAccess(userName))
  50. {
  51. header.Status = NTStatus.STATUS_ACCESS_DENIED;
  52. return new ErrorResponse(CommandName.SMB_COM_TREE_CONNECT_ANDX);
  53. }
  54. else
  55. {
  56. ushort? treeID = state.AddConnectedTree(relativePath);
  57. if (!treeID.HasValue)
  58. {
  59. header.Status = NTStatus.STATUS_INSUFF_SERVER_RESOURCES;
  60. return new ErrorResponse(CommandName.SMB_COM_TREE_CONNECT_ANDX);
  61. }
  62. header.TID = treeID.Value;
  63. if (isExtended)
  64. {
  65. return CreateTreeConnectResponseExtended(ServiceName.DiskShare);
  66. }
  67. else
  68. {
  69. return CreateTreeConnectResponse(ServiceName.DiskShare);
  70. }
  71. }
  72. }
  73. }
  74. }
  75. private static TreeConnectAndXResponse CreateTreeConnectResponse(ServiceName serviceName)
  76. {
  77. TreeConnectAndXResponse response = new TreeConnectAndXResponse();
  78. response.OptionalSupport = OptionalSupportFlags.SMB_SUPPORT_SEARCH_BITS;
  79. response.NativeFileSystem = String.Empty;
  80. response.Service = serviceName;
  81. return response;
  82. }
  83. private static TreeConnectAndXResponseExtended CreateTreeConnectResponseExtended(ServiceName serviceName)
  84. {
  85. TreeConnectAndXResponseExtended response = new TreeConnectAndXResponseExtended();
  86. response.OptionalSupport = OptionalSupportFlags.SMB_SUPPORT_SEARCH_BITS;
  87. response.MaximalShareAccessRights.File = FileAccessMask.FILE_READ_DATA | FileAccessMask.FILE_WRITE_DATA | FileAccessMask.FILE_APPEND_DATA |
  88. FileAccessMask.FILE_READ_EA | FileAccessMask.FILE_WRITE_EA |
  89. FileAccessMask.FILE_EXECUTE |
  90. FileAccessMask.FILE_READ_ATTRIBUTES | FileAccessMask.FILE_WRITE_ATTRIBUTES |
  91. FileAccessMask.DELETE | FileAccessMask.READ_CONTROL | FileAccessMask.WRITE_DAC | FileAccessMask.WRITE_OWNER | FileAccessMask.SYNCHRONIZE;
  92. response.GuestMaximalShareAccessRights.File = FileAccessMask.FILE_READ_DATA | FileAccessMask.FILE_WRITE_DATA |
  93. FileAccessMask.FILE_READ_EA | FileAccessMask.FILE_WRITE_EA |
  94. FileAccessMask.FILE_READ_ATTRIBUTES | FileAccessMask.FILE_WRITE_ATTRIBUTES |
  95. FileAccessMask.READ_CONTROL | FileAccessMask.SYNCHRONIZE;
  96. response.NativeFileSystem = String.Empty;
  97. response.Service = serviceName;
  98. return response;
  99. }
  100. internal static SMB1Command GetTreeDisconnectResponse(SMB1Header header, TreeDisconnectRequest request, SMB1ConnectionState state)
  101. {
  102. if (!state.IsTreeConnected(header.TID))
  103. {
  104. header.Status = NTStatus.STATUS_SMB_BAD_TID;
  105. return new ErrorResponse(CommandName.SMB_COM_TREE_DISCONNECT);
  106. }
  107. state.RemoveConnectedTree(header.TID);
  108. return new TreeDisconnectResponse();
  109. }
  110. }
  111. }