遇到一个在枚举中未定义的FileSystemRights值

11

我编写了一个应用程序,它检查目录上的所有文件系统权限。

一个目录具有多个访问规则(类型为FileSystemAccessRule)。

每个访问规则都有一个属性FileSystemRights,它是一个标志枚举。

在运行此程序时,我不断遇到一个FileSystemRights值为268435456(十六进制为0x10000000)。

这个值在枚举中根本不存在!它实际上比最高的单个标志值(Synchronize,其值为0x100000)还要高。

有人知道这是什么吗?

3个回答

14
请查看此页面:http://cjwdev.wordpress.com/2011/06/28/permissions-not-included-in-net-accessrule-filesystemrights-enum/ 来自该页面:
使用.NET,你可能认为确定分配给目录/文件的权限应该很容易,因为定义了一个FileSystemRights枚举,似乎包含每个文件/目录可能具有的所有权限,并调用AccessRule.FileSystemRights返回这些值的组合。但是,您很快就会遇到一些权限,其中此属性中的值与FileSystemRights Enum中的任何值都不匹配(我希望他们不要将某些属性命名为类型相同的名称,但是嘿)。这样做的最终结果是,对于某些文件/目录,您根本无法确定已分配哪些权限。如果您执行AccessRule.FileSystemRights.ToString,则对于这些值,您只会看到一个数字,而不是描述(例如Modify,Delete,FullControl等)。您可能会看到的常见数字包括:-1610612736、-536805376和268435456。要弄清楚这些权限实际上是什么,您需要查看在将该数字视为32个单独位而不是整数(因为整数长度为32位)时设置了哪些位,并将它们与此图进行比较:http://msdn.microsoft.com/en-us/library/aa374896(v=vs.85).aspx。因此,例如,-1610612736设置了第一位和第三位,这意味着它是GENERIC_READ与GENERIC_EXECUTE的组合。因此,现在可以将这些通用权限转换为它们对应的特定文件系统权限。您可以在此处查看每个通用权限映射到哪些权限:http://msdn.microsoft.com/en-us/library/aa364399.aspx。请注意,STANDARD_RIGHTS_READ、STANDARD_RIGHTS_EXECUTE和STANDARD_RIGHTS_WRITE都是相同的东西(我不知道为什么,对我来说似乎很奇怪),并且实际上都等于FileSystemRights.ReadPermissions值。

3
在某些情况下,FileSystemRights 的位被设置为不包含任何有意义的信息,可以被删除。有些格式不被 FileSystemRights 类支持,但可以转换(NTFS 驱动程序了解这两种格式)。Microsoft 有几份相关文件:

基于此,方法 FileSystemRightsCorrector() 可以清理此数据并使其“可读”。有一个参数 bool removeSynchronizePermission = false 应该使用默认值,除非您需要将此标志也删除。

    public static FileSystemRights FileSystemRightsCorrector(FileSystemRights fsRights, bool removeSynchronizePermission = false)
    {
        // from: https://msdn.microsoft.com/en-us/library/aa374896%28v=vs.85%29.aspx
        const int C_BitGenericRead = (1 << 31);
        const int C_BitGenericWrite = (1 << 30);
        const int C_BitGenericExecute = (1 << 29);
        const int C_BitGenericAll = (1 << 28);


        // https://msdn.microsoft.com/en-us/library/aa364399.aspx
        // FILE_GENERIC_READ = FILE_READ_ATTRIBUTES | FILE_READ_DATA | FILE_READ_EA | STANDARD_RIGHTS_READ | SYNCHRONIZE 
        // FILE_GENERIC_WRITE = FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA | FILE_WRITE_EA | STANDARD_RIGHTS_WRITE | SYNCHRONIZE
        // FILE_GENERIC_EXECUTE  = FILE_EXECUTE | FILE_READ_ATTRIBUTES | STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE 

        //from Winnt.h
        //#define STANDARD_RIGHTS_READ             (READ_CONTROL)
        //#define STANDARD_RIGHTS_WRITE            (READ_CONTROL)
        //#define STANDARD_RIGHTS_EXECUTE          (READ_CONTROL)

        // from: https://msdn.microsoft.com/en-us/library/windows/desktop/aa379607%28v=vs.85%29.aspx
        // READ_CONTROL = "The right to read the information in the object's security descriptor,"
        // ==> STANDARD_RIGHTS_READ, STANDARD_RIGHTS_WRITE, STANDARD_RIGHTS_EXECUTE == FileSystemRights.ReadPermissions

        // translation for the generic rights to the FileSystemRights enum
        const FileSystemRights C_FsrGenericRead = FileSystemRights.ReadAttributes | FileSystemRights.ReadData | FileSystemRights.ReadExtendedAttributes | FileSystemRights.ReadPermissions | FileSystemRights.Synchronize;
        const FileSystemRights C_FsrGenericWrite = FileSystemRights.AppendData | FileSystemRights.WriteAttributes | FileSystemRights.WriteData | FileSystemRights.WriteExtendedAttributes | FileSystemRights.ReadPermissions | FileSystemRights.Synchronize;
        const FileSystemRights C_FsrGenericExecute = FileSystemRights.ExecuteFile | FileSystemRights.ReadAttributes | FileSystemRights.ReadPermissions | FileSystemRights.Synchronize;

        if (((int)fsRights & C_BitGenericRead) != 0)
        {
            fsRights |= C_FsrGenericRead;
        }

        if (((int)fsRights & C_BitGenericWrite) != 0)
        {
            fsRights |= C_FsrGenericWrite;
        }

        if (((int)fsRights & C_BitGenericExecute) != 0)
        {
            fsRights |= C_FsrGenericExecute;
        }

        if (((int)fsRights & C_BitGenericAll) != 0)
        {
            fsRights |= FileSystemRights.FullControl;
        }

        // delete the 4 highest bits if present
        fsRights = (FileSystemRights)((int)fsRights & ~(C_BitGenericRead | C_BitGenericWrite | C_BitGenericExecute | C_BitGenericAll));

        // For some purpouses the Synchronize flag needs to be deleted.
        // If you don't have trouble with that flag leave it untouched!
        if (removeSynchronizePermission == true)
        {
            fsRights = (FileSystemRights)((int)fsRights & ~((int)FileSystemRights.Synchronize));
        }

        return fsRights;
    }

1
我在现场遇到了GENERIC_ACCESS设置错误,所以你的解决方法只能有限地发挥作用...显然,.NET Framework没有准备好创建可以在现实环境下完全运行的ACE(根据我的观察,这些ACE也可以被相应的类所读取)。 - 0xC0000022L
从未见过这个。它在哪个.h文件中定义? - marsh-wiggle
抱歉,我指的是 GENERIC_ALL (0x10000000)。也就是说,我看到过使用通用形式而不是具体形式的ACE的ACL。但是,FileSystemAccessRule 的(公共)构造函数会防止您使用枚举定义范围之外的任何内容 ☹ - 0xC0000022L
找到了实际解决问题的方法,显然你的解决方案确实可行,但它事先混淆了访问掩码(这就是我想避免的)。 - 0xC0000022L
1
对我来说,这个解决方案是有效的... - 0xC0000022L
@0xC0000022L 做得好! - marsh-wiggle

2

1
这是错误的。通用访问掩码和标准访问掩码之间有区别,你忽略了这一点,并假装它们是相同的。它们不是。FullControl 对应于 0x1F01FF,请查阅相关资料。然而,268435456 == 0x10000000 == GENERIC_ALL 是对第一个值的符号名称。意义是相同的,如果你将 GENERIC_ALL 通过 MapGenericMask 运行到文件中,你最终会得到 0x1F01FF,但它们仍然_不相同_。虽然这可能看起来像是吹毛求疵,但在安全方面,这些细节确实很重要。 - 0xC0000022L

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接