I have the following method in a dialog in my application that is intended to determine if a user has write access to a folder:
private bool UserCanWriteToFolder( FileSystemNode node ) {
try {
WindowsIdentity currentUser = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal( currentUser );
DirectoryInfo directoryInfo = new DirectoryInfo( node.FullPath );
DirectorySecurity acl = directoryInfo.GetAccessControl( AccessControlSections.All );
AuthorizationRuleCollection rules = acl.GetAccessRules( true, true, typeof( NTAccount ) );
foreach ( AuthorizationRule rule in rules ) {
FileSystemAccessRule fsAccessRule = rule as FileSystemAccessRule;
if ( fsAccessRule == null )
continue;
if ( ( fsAccessRule.FileSystemRights & FileSystemRights.WriteData ) > 0 ) {
NTAccount ntAccount = rule.IdentityReference as NTAccount;
if ( ntAccount == null )
continue;
if ( principal.IsInRole( ntAccount.Value ) )
return true;
}
}
} catch ( Exception ) {
return false;
}
return false;
}
This logic works, but there is a problem.
My user is in the Administrators group. When I choose the C:\Windows folder, this method returns true, yet, when my program tries to write to the C:\Windows folder, the program throws an UnauthorizedAccessException. Obviously there's something different about that folder that my code isn't taking into account.
Here's the output of iacls for the C:\Windows folder on my machine:
C:\Windows NT SERVICE\TrustedInstaller:(F)
NT SERVICE\TrustedInstaller:(CI)(IO)(F)
NT AUTHORITY\SYSTEM:(M)
NT AUTHORITY\SYSTEM:(OI)(CI)(IO)(F)
BUILTIN\Administrators:(M)
BUILTIN\Administrators:(OI)(CI)(IO)(F)
BUILTIN\Users:(RX)
BUILTIN\Users:(OI)(CI)(IO)(GR,GE)
CREATOR OWNER:(OI)(CI)(IO)(F)
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(RX)
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(OI)(CI)(IO)(GR,GE)
Successfully processed 1 files; Failed processing 0 files
Unfortunately, I don't know which line in the ACL is the one that's causing the UnauthorizedAccessException to be thrown. Can someone point out the problem to me?
I've decided to abandon the above code. When I start the program as a normal user, the line that retrieves the ACL throws a
PrivilegeNotHeldException
. Specifically, the message text readsAt this point, what I'm going to do is try to create a temporary file in the selected folder. If that succeeds, I'll delete it and return true. If that fails (an exception is thrown), I'll return false. In any case, I have to catch any exceptions that occur when actually writing to the folder and display a useful error message, since, as has been said in the comments, the security could change between this method exits and the write is performed.