【问题标题】:Create a SMB share in C# with a security descriptor在 C# 中使用安全描述符创建 SMB 共享
【发布时间】:2019-03-10 07:09:57
【问题描述】:

我正在将我的 SMB 共享信息保存到磁盘,以便以后可以根据需要进行恢复。

为此,我使用MSFT_SMB 类。我在本地机器上获得了所有可用的 SMB 共享并将数据保存到磁盘。像这样获取的安全描述符是字符串格式的。

这是获取所有共享的代码:

      private const string SmbNamespace = "\\\\.\\ROOT\\Microsoft\\Windows\\SMB";
      private const string SmbShareClass = "MSFT_SmbShare";
      private const string CreateShareMethod = "CreateShare";
      private const string GetShareMethod = "GetShare";

          public virtual List<SmbShareInfo> GetAllSmbShares()
      {
          ManagementClass SmbShares = new ManagementClass(SmbNamespace + ":" + SmbShareClass);
          List<SmbShareInfo> sharesPresent = new List<SmbShareInfo>();

          try
          {
              foreach (ManagementObject smbObject in SmbShares.GetInstances())
              {
                  sharesPresent.Add(constructSmbShareInfo(smbObject));
              }
              return sharesPresent;
          }
          catch (ManagementException e)
          {
              throw new Exception(e.ToString());
          }
      }

      private SmbShareInfo constructSmbShareInfo(ManagementObject smbObject)
      {
          return new SmbShareInfo(
              Convert.ToString(smbObject["Name"]),
              Convert.ToString(smbObject["Path"]),
              Convert.ToString(smbObject["Description"]),
              Convert.ToBoolean(smbObject["Special"]),
              Convert.ToUInt32(smbObject["ConcurrentUserLimit"]),
              Convert.ToString(smbObject["SecurityDescriptor"]),
              Convert.ToUInt32(smbObject["ShareType"]),
              Convert.ToUInt32(smbObject["FolderEnumerationMode"]),
              Convert.ToBoolean(smbObject["EncryptData"]),
              Convert.ToUInt32(smbObject["CachingMode"]));
      }

SmbShareInfo 是我定义的用于在本地存储 SMB 共享信息的类。

现在,当我尝试再次(在新的 Windows 机器上)创建共享时,CreateShare 方法需要“共享的安全描述符的名称”。

如何获取安全描述符的“名称”并创建共享?我只有这样的基于字符串的安全描述符:

O:SYG:SYD:(A;;GA;;;BA)(A;;GA;;;BO)(A;;GA;;;IU)

这是我创建共享的代码:

          ManagementObject managementObject = new ManagementClass(SmbNamespace + ":" + SmbShareClass);
          managementObject.Get();

          string[] accountNames = { "Everyone" };
          ManagementBaseObject createShareInParameters = managementObject.GetMethodParameters(CreateShareMethod);
          createShareInParameters["Name"] = fileShare.Name;
          createShareInParameters["Path"] = fileShare.Path;
          createShareInParameters["Description"] = fileShare.Description;
          createShareInParameters["ConcurrentUserLimit"] = fileShare.ConcurrentUserLimit;
          // Enable this
          //createShareInParameters["SecurityDescriptor"] = fileShare.SecurityDescriptor;
          createShareInParameters["FolderEnumerationMode"] = fileShare.FolderEnumerationMode;
          createShareInParameters["EncryptData"] = fileShare.EncryptData;
          createShareInParameters["CachingMode"] = fileShare.CachingMode;
          createShareInParameters["FullAccess"] = accountNames;

          managementObject.InvokeMethod(CreateShareMethod, createShareInParameters, null);

【问题讨论】:

    标签: c# .net wmi smb network-share


    【解决方案1】:

    我的代码有一个错误,除了安全描述符之外,我还使用了属性FullAccess,它的优先级高于安全描述符。这段代码终于奏效了:

    ManagementObject managementObject = new ManagementClass(SmbNamespace + ":" + SmbShareClass); managementObject.Get();

          ManagementBaseObject createShareInParameters = managementObject.GetMethodParameters(CreateShareMethod);
          createShareInParameters["Name"] = fileShare.Name;
          createShareInParameters["Path"] = fileShare.Path;
          createShareInParameters["Description"] = fileShare.Description;
          createShareInParameters["ConcurrentUserLimit"] = fileShare.ConcurrentUserLimit;
          createShareInParameters["SecurityDescriptor"] = fileShare.SecurityDescriptor;
          createShareInParameters["FolderEnumerationMode"] = fileShare.FolderEnumerationMode;
          createShareInParameters["EncryptData"] = fileShare.EncryptData;
          createShareInParameters["CachingMode"] = fileShare.CachingMode;
    
          managementObject.InvokeMethod(CreateShareMethod, createShareInParameters, null);
    

    【讨论】:

      【解决方案2】:

      我意识到你在要求 c#,但让我为你提供一个有趣的替代方案。

      您可以使用 PowerShell 的 Get-SmbShareNew-SmbShare,如果需要,将设置持久化到可能位于中间的配置文件中。与 c# 相比,这将是微不足道的。

      编辑:Get-SmbShareAccess / Grant-SmbShareAccess 用于安全描述 (ACL) 位。

      当然,我不知道您正在制作的项目的全部范围,但系统自动化之类的东西是 PowerShell 的亮点。实际上,PowerShell 主要封装了 c# 库并提供了一个易于使用的 API。

      我是作为一名顽固的 c# 开发人员说的,他最近了解到 powershell 的强大功能(我们的 DevOps 领域需要)。

      我意识到这不是 答案,但可能是适合某些场景的有趣替代方案。

      【讨论】:

        猜你喜欢
        • 2011-02-18
        • 2013-01-03
        • 1970-01-01
        • 2013-07-02
        • 1970-01-01
        • 2011-03-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多