无法正确获取ACL

时间:2013-03-14 11:55:53

标签: c# pinvoke

我正在尝试获取共享文件夹的ACL。获取安全描述符的代码如下:

private static SECURITY_DESCRIPTOR GetSecurityDescriptor(string path)
{
    var sdUtil = new ADsSecurityUtility();
    Byte[] temp = (Byte[])sdUtil.GetSecurityDescriptor(path, (int)ADS_PATHTYPE_ENUM.ADS_PATH_FILESHARE, (int)ADS_SD_FORMAT_ENUM.ADS_SD_FORMAT_RAW);
    IntPtr ptr = (IntPtr)0;
    SECURITY_DESCRIPTOR sd;
    try
    {
        ptr = Marshal.AllocHGlobal(temp.Length);
        Marshal.Copy(temp, 0, ptr, temp.Length);
        sd = (SECURITY_DESCRIPTOR)Marshal.PtrToStructure(ptr, typeof(SECURITY_DESCRIPTOR));
        return sd;
    }
    catch (Exception)
    {
        throw new Exception("Couldn't get security descriptor");
    }
    finally
    {
        Marshal.FreeHGlobal(ptr);
    }
}

SD还可以,我没问题。 然后我试图从SD获得DACL和SACL。

private static List<ACL> GetAcls(SECURITY_DESCRIPTOR sd)
{
    List<ACL> result = new List<ACL>(2);
    ACL temp = new ACL();
    int daclPresent = 0;
    int daclDefaulted = 0;
    try
    {
        int res = PInvoke.GetSecurityDescriptorDacl(ref sd, ref daclPresent, ref temp, ref daclDefaulted);
        result.Add(temp);
        temp = new ACL();
    }
    catch (Exception) { }
    try
    {
        int res = PInvoke.GetSecurityDescriptorSacl(ref sd, ref daclPresent, ref temp, ref daclDefaulted);
        result.Add(temp);
    }
    catch (Exception) { }
    return result;
}

外部函数定义如下:

    [DllImport("advapi32.dll")]
    public static extern int GetSecurityDescriptorDacl(
        [MarshalAs(UnmanagedType.Struct)] ref SECURITY_DESCRIPTOR pSecurityDescriptor,
        ref int lpbDaclPresent,
        [MarshalAs(UnmanagedType.Struct)] ref ACL pDacl,
        ref int lpbDaclDefaulted
    );

    [DllImport("advapi32.dll")]
    public static extern int GetSecurityDescriptorSacl(
        [MarshalAs(UnmanagedType.Struct)] ref SECURITY_DESCRIPTOR pSecurityDescriptor,
        ref int lpbDaclPresent,
        [MarshalAs(UnmanagedType.Struct)] ref ACL pDacl,
        ref int lpbDaclDefaulted
    );

当我检查SD实例的属性时,我看到以下内容:

sd.Dacl
{Permission.ACL}
    AceCount: 83886080
    AclRevision: 169
    AclSize: 1281
    Sbz1: 0
    Sbz2: 21

sd.Sacl
{Permission.ACL}
    AceCount: 6
    AclRevision: 20
    AclSize: 9961474
    Sbz1: 0
    Sbz2: 2359297

总ACL中包含6个ACE。所以似乎SACL包含所有这些。但是,MS不建议使用这些属性。而应使用GetSecurityDescriptorDacl和GetSecurityDescriptorSacl。所以我用它们。并且看到DACL中的ACE数量为0,SACL中的ACE数量也为0.

所以问题是:如何从安全描述符中正确获取所有ACE?

1 个答案:

答案 0 :(得分:0)

您必须将SECURITY_DESCRIPTOR视为不透明句柄。你不能像在线上那样投射到一个:

   sd = (SECURITY_DESCRIPTOR)Marshal.PtrToStructure(ptr, 
          typeof(SECURITY_DESCRIPTOR)); 

当您进行上述演员表时,您丢失了所有的所有者,组,DACL和SACL信息,因为您有一个自我相对的SECURITY_DESCRIPTOR,但您没有整理数据以及您对结构的定义。

只需更改各种API调用的声明(即GetSecurityDescriptorDacl等),即可获取byte []而不是ref SECURITY_DESCRIPTOR,并传入从ADsSecurityUtility收到的byte []。