ServerServiceHelper.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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 SMBLibrary.RPC;
  10. using SMBLibrary.Services;
  11. using Utilities;
  12. namespace SMBLibrary.Client
  13. {
  14. public class ServerServiceHelper
  15. {
  16. public static List<string> ListShares(INTFileStore namedPipeShare, ShareType? shareType, out NTStatus status)
  17. {
  18. object pipeHandle;
  19. FileStatus fileStatus;
  20. status = namedPipeShare.CreateFile(out pipeHandle, out fileStatus, ServerService.ServicePipeName, (AccessMask)(FileAccessMask.FILE_READ_DATA | FileAccessMask.FILE_WRITE_DATA), 0, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_OPEN, 0, null);
  21. if (status != NTStatus.STATUS_SUCCESS)
  22. {
  23. return null;
  24. }
  25. BindPDU bindPDU = new BindPDU();
  26. bindPDU.Flags = PacketFlags.FirstFragment | PacketFlags.LastFragment;
  27. bindPDU.DataRepresentation.CharacterFormat = CharacterFormat.ASCII;
  28. bindPDU.DataRepresentation.ByteOrder = ByteOrder.LittleEndian;
  29. bindPDU.DataRepresentation.FloatingPointRepresentation = FloatingPointRepresentation.IEEE;
  30. bindPDU.MaxTransmitFragmentSize = 5680;
  31. bindPDU.MaxReceiveFragmentSize = 5680;
  32. ContextElement serverServiceContext = new ContextElement();
  33. serverServiceContext.AbstractSyntax = new SyntaxID(ServerService.ServiceInterfaceGuid, ServerService.ServiceVersion);
  34. serverServiceContext.TransferSyntaxList.Add(new SyntaxID(RemoteServiceHelper.NDRTransferSyntaxIdentifier, RemoteServiceHelper.NDRTransferSyntaxVersion));
  35. bindPDU.ContextList.Add(serverServiceContext);
  36. byte[] input = bindPDU.GetBytes();
  37. byte[] output;
  38. status = namedPipeShare.DeviceIOControl(pipeHandle, (uint)IoControlCode.FSCTL_PIPE_TRANSCEIVE, input, out output, 4096);
  39. if (status != NTStatus.STATUS_SUCCESS)
  40. {
  41. return null;
  42. }
  43. BindAckPDU bindAckPDU = RPCPDU.GetPDU(output, 0) as BindAckPDU;
  44. if (bindAckPDU == null)
  45. {
  46. status = NTStatus.STATUS_NOT_SUPPORTED;
  47. return null;
  48. }
  49. NetrShareEnumRequest shareEnumRequest = new NetrShareEnumRequest();
  50. shareEnumRequest.InfoStruct = new ShareEnum();
  51. shareEnumRequest.InfoStruct.Level = 1;
  52. shareEnumRequest.InfoStruct.Info = new ShareInfo1Container();
  53. shareEnumRequest.PreferedMaximumLength = UInt32.MaxValue;
  54. shareEnumRequest.ServerName = "*";
  55. RequestPDU requestPDU = new RequestPDU();
  56. requestPDU.Flags = PacketFlags.FirstFragment | PacketFlags.LastFragment;
  57. requestPDU.DataRepresentation.CharacterFormat = CharacterFormat.ASCII;
  58. requestPDU.DataRepresentation.ByteOrder = ByteOrder.LittleEndian;
  59. requestPDU.DataRepresentation.FloatingPointRepresentation = FloatingPointRepresentation.IEEE;
  60. requestPDU.OpNum = (ushort)ServerServiceOpName.NetrShareEnum;
  61. requestPDU.Data = shareEnumRequest.GetBytes();
  62. requestPDU.AllocationHint = (uint)requestPDU.Data.Length;
  63. input = requestPDU.GetBytes();
  64. int maxOutputLength = bindAckPDU.MaxTransmitFragmentSize;
  65. status = namedPipeShare.DeviceIOControl(pipeHandle, (uint)IoControlCode.FSCTL_PIPE_TRANSCEIVE, input, out output, maxOutputLength);
  66. if (status != NTStatus.STATUS_SUCCESS)
  67. {
  68. return null;
  69. }
  70. ResponsePDU responsePDU = RPCPDU.GetPDU(output, 0) as ResponsePDU;
  71. if (responsePDU == null)
  72. {
  73. status = NTStatus.STATUS_NOT_SUPPORTED;
  74. return null;
  75. }
  76. byte[] responseData = responsePDU.Data;
  77. while ((responsePDU.Flags & PacketFlags.LastFragment) == 0)
  78. {
  79. status = namedPipeShare.ReadFile(out output, pipeHandle, 0, maxOutputLength);
  80. if (status != NTStatus.STATUS_SUCCESS)
  81. {
  82. return null;
  83. }
  84. responsePDU = RPCPDU.GetPDU(output, 0) as ResponsePDU;
  85. if (responsePDU == null)
  86. {
  87. status = NTStatus.STATUS_NOT_SUPPORTED;
  88. return null;
  89. }
  90. responseData = ByteUtils.Concatenate(responseData, responsePDU.Data);
  91. }
  92. NetrShareEnumResponse shareEnumResponse = new NetrShareEnumResponse(responseData);
  93. ShareInfo1Container shareInfo1 = shareEnumResponse.InfoStruct.Info as ShareInfo1Container;
  94. if (shareInfo1 == null)
  95. {
  96. if (shareEnumResponse.Result == Win32Error.ERROR_ACCESS_DENIED)
  97. {
  98. status = NTStatus.STATUS_ACCESS_DENIED;
  99. }
  100. else
  101. {
  102. status = NTStatus.STATUS_NOT_SUPPORTED;
  103. }
  104. return null;
  105. }
  106. List<string> result = new List<string>();
  107. foreach (ShareInfo1Entry entry in shareInfo1.Entries)
  108. {
  109. if (!shareType.HasValue || shareType.Value == entry.ShareType.ShareType)
  110. {
  111. result.Add(entry.NetName.Value);
  112. }
  113. }
  114. return result;
  115. }
  116. }
  117. }