I've written an application that examines all of the file system permissions on a directory.
A directory has a number of access rules (of type FileSystemAccessRule
).
Each access rule has a property FileSystemRights
, which is a flag enumeration.
When running this, I keep encountering a FileSystemRights
value of 268435456
(which comes to 0x10000000
in hexadecimal).
This value just doesn't appear in enumeration! It's actually higher than the highest single flag value (Synchronize
, having a value of 0x100000
).
Does anyone know what this is?
See http://cjwdev.wordpress.com/2011/06/28/permissions-not-included-in-net-accessrule-filesystemrights-enum/
From that page:
Using .NET you may think that determining which permissions are
assigned to a directory/file should be quite easy, as there is a
FileSystemRights Enum defined that seems to contain every possible
permission that a file/directory can have and calling
AccessRule.FileSystemRights returns a combination of these values.
However, you will soon come across some permissions where the value in
this property does not match any of the values in the FileSystemRights
Enum (I do wish they wouldn’t name some properties with the same name
as a Type but hey).
The end result of this is that for some files/directories you simply
cannot determine which permissions are assigned to them. If you do
AccessRule.FileSystemRights.ToString then for these values all you see
is a number rather than a description (e.g Modify, Delete, FullControl
etc). Common numbers you might see are:
-1610612736, –536805376, and 268435456
To work out what these permissions actually are, you need to look at
which bits are set when you treat that number as 32 separate bits
rather than as an Integer (as Integers are 32 bits long), and compare
them to this diagram:
http://msdn.microsoft.com/en-us/library/aa374896(v=vs.85).aspx
So for example, -1610612736 has the first bit and the third bit set,
which means it is GENERIC_READ combined with GENERIC_EXECUTE. So now
you can convert these generic permissions into the specific file
system permissions that they correspond to.
You can see which permissions each generic permission maps to here:
http://msdn.microsoft.com/en-us/library/aa364399.aspx. Just be aware
that STANDARD_RIGHTS_READ, STANDARD_RIGHTS_EXECUTE and
STANDARD_RIGHTS_WRITE are all the same thing (no idea why, seems
strange to me) and actually all equal the
FileSystemRights.ReadPermissions value.
from https://social.technet.microsoft.com/Forums/windowsserver/en-US/5211a077-63fc-4016-b750-25bf26b3ad15/why-does-getacl-return-filesystemrights-that-are-invalid-in-filesystemaccesrule-used-with-setacl?forum=winserverpowershell
268435456 - FullControl
-536805376 - Modify, Synchronize
-1610612736 - ReadAndExecute, Synchronize
(to save you some math)
Here is my solution for correcting the FileSystemRights so they fit to the enumeration.
There are several documents about that. The references are included in the code.
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 purposes the "Synchronize" flag must be deleted
if (removeSynchronizePermission == true)
{
fsRights = (FileSystemRights)((int)fsRights & ~((int)FileSystemRights.Synchronize));
}
return fsRights;
}