I'm writing an application that is used to search through folders for their permissions and return details such as Rights (eg Full Control, Read), AccessControlType (eg Allow, Deny) and Apply To information (eg This folder, subfolders and files).
Most of this information I am able to obtain using DirectoryInfo's GetAccessControl(DirectorySecurity) method. However, I can't accurately obtain the directory's Apply To information. After much research I came across this StackOverflow Q&A How to change the "Applies To" field under folder auditing options programatically (.NET) which led me to this comprehensive page http://msmvps.com/blogs/p3net/pages/access-control-in-net.aspx but using the rules that both specify, I do not get the same Apply To permissions as I do in Windows Explorer.
(Table from http://msmvps.com/blogs/p3net/pages/access-control-in-net.aspx)
This is the code I use to try and convert a combination of InheritanceFlags and PropogationFlags:
private ApplyToType GetApplyToType(InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
{
if (propagationFlags == PropagationFlags.None &&
inheritanceFlags == InheritanceFlags.None)
return ApplyToType.ThisFolderOnly;
if (propagationFlags == PropagationFlags.None &&
inheritanceFlags == InheritanceFlags.ContainerInherit)
return ApplyToType.ThisFolderAndSubfolders;
if (propagationFlags == PropagationFlags.None &&
inheritanceFlags == InheritanceFlags.ObjectInherit)
return ApplyToType.ThisFolderAndFiles;
if (propagationFlags == PropagationFlags.None &&
inheritanceFlags == (InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit))
return ApplyToType.ThisFolderSubfoldersAndFiles;
if (propagationFlags == PropagationFlags.InheritOnly &&
inheritanceFlags == InheritanceFlags.ContainerInherit)
return ApplyToType.SubfoldersOnly;
if (propagationFlags == PropagationFlags.InheritOnly &&
inheritanceFlags == InheritanceFlags.ObjectInherit)
return ApplyToType.FilesOnly;
if (propagationFlags == PropagationFlags.InheritOnly &&
inheritanceFlags == (InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit))
return ApplyToType.SubfoldersAndFilesOnly;
return ApplyToType.AndreDoesntKnow;
}
And the following code is used to query directories:
var directory = new DirectoryInfo(directoryPath);
var accessControl = directory.GetAccessControl(AccessControlSections.Access);
var rules = accessControl.GetAccessRules(includeExplicit, includeInherited, targetType);
foreach (FileSystemAccessRule rule in rules)
{
var applyToType = GetApplyToType(rule.InheritanceFlags, rule.PropagationFlags);
Console.WriteLine(string.Format("Identity:{0}, Rights:{1}, AccessType:{2}, ApplyTo:{3}", rule.IdentityReference, rule.FileSystemRights, rule.AccessControlType, applyToType));
}
However when I look at these permissions in Windows Explorer I see the following:
And when I use my application to query the same folder, I get:
Identity:BUILTIN\Administrators, Rights:FullControl, AccessType:Allow, ApplyTo:ThisFolderOnly
Identity:BUILTIN\Administrators, Rights:268435456, AccessType:Allow, ApplyTo:SubfoldersAndFilesOnly
Identity:NT AUTHORITY\SYSTEM, Rights:FullControl, AccessType:Allow, ApplyTo:ThisFolderOnly
Identity:NT AUTHORITY\SYSTEM, Rights:268435456, AccessType:Allow, ApplyTo:SubfoldersAndFilesOnly
Identity:BUILTIN\Users, Rights:ReadAndExecute, Synchronize, AccessType:Allow, ApplyTo:ThisFolderSubfoldersAndFiles
Identity:NT AUTHORITY\Authenticated Users, Rights:Modify, Synchronize, AccessType:Allow, ApplyTo:ThisFolderOnly
Identity:NT AUTHORITY\Authenticated Users, Rights:-536805376, AccessType:Allow, ApplyTo:SubfoldersAndFilesOnly
As you can see, using the rules from these other sites, my derived ApplyTo does not match with Windows Explorer ApplyTo.
Is there more to it than this? What am I doing wrong? What else do I need to resolve the same ApplyTo rules that Windows Explorer reports?
I should also mention that these results were from my development PC which is running Windows 7 x64. According to our users, on their work environment (Windows XP x86), they observe the correct behavior. I don't know enough about Windows permissions to know whether there are differences in them between Windows 7 x64 and Window XP x86.
All of this looks correct to me. The one thing I would try is, over the years, I've learned not to check flags with just
propagationFlags == PropagationFlags.None
Isntead, I tend to use
(propagationFlags & PropagationFlags.None) == PropagationFlags.None
This makes my code more resilient if new flags show up on the bit fields as new versions of APIs come around.
This principle applies even with the more complicated expressions, such as
(inheritanceFlags & (InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit)) == (InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit)
That's the one thing I would try right away.