I tested FileIOPermission on Windows 7 in .NET 3.5. I was a Windows XP user and got this permission since I was an administrator
I wrote the following code, checking if I can write to C: \ Program Files \ Outlook ......
static void Main(string[] args) { Console.WriteLine("Am I an administrator? " + new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator); // Try and open a file in C:\Program Files\Microsoft Office\Office14\BCSLaunch.dll string path = @"C:\Program Files\Microsoft Office\Office14\BCSLaunch.dll"; try { FileIOPermission ioPerm = new FileIOPermission(FileIOPermissionAccess.Read, path); ioPerm.Demand(); string backupPath = Path.ChangeExtension(path, ".bak"); FileIOPermission writeAccess = new FileIOPermission(FileIOPermissionAccess.AllAccess, backupPath); writeAccess.Demand(); Console.WriteLine("Read access is permitted: {0} => {1}",path,SecurityManager.IsGranted(ioPerm)); Console.WriteLine("Write backup file is permitted: {0} => {1}", backupPath, SecurityManager.IsGranted(writeAccess)); File.Copy(path, backupPath); Console.WriteLine("File copied! {0}",backupPath); Console.WriteLine("Deleting file....."); File.Delete(path); } catch (UnauthorizedAccessException uae) { Console.WriteLine(uae.ToString()); } Console.ReadLine(); }
Thus, the program raises a UnauthorizedAccessException (which I expected), but I donβt understand that Demand() allows the permission, the SecurityManager confirms that the permission is granted, but when I execute File.Copy() I get an exception.
Although I'm glad to see .NET stopping me, why didn't it notify me before when I called Demand() ?
I get the following output:
Am I an administrator? False
Read access is permitted: C: \ Program Files \ Microsoft Office \ Office14 \ BCSLaunch.dll => True
Write backup file is permitted: C: \ Program Files \ Microsoft Office \ Office14 \ BCSLaunch.bak => True
System.UnauthorizedAccessException: Access to the path 'C: \ Program Files \ Microsoft Office \ Office14 \ BCSLaunch.bak' is denied.
at System.IO .__ Error.WinIOError (Int32 errorCode, String maybeFullPath)
at System.IO.File.InternalCopy (String sourceFileName, String destFileName, Boolean overwrite)
at System.IO.File.Copy (String sourceFileName, String destFileName)
at TryAndGetUACPrompt.Program.Main (String [] args) in C: \ Users \ ..............
Please help me understand why I get conflicting information?
-
Update - 19:30 GMT
I looked at the ACL of the source file using the following code:
Console.WriteLine("ACL Permissions for Source...."); FileSecurity fileSecurityForOriginalPath = new FileSecurity(path, AccessControlSections.Access); foreach (FileSystemAccessRule rule in fileSecurityForOriginalPath.GetAccessRules(true,true,typeof(NTAccount))) { Console.WriteLine("{0} => {1}", rule.FileSystemRights, rule.AccessControlType); }
The output is as follows:
ACL Permissions for Source ....
FullControl => Allow
FullControl => Allow
ReadAndExecute, Synchronize => Allow
Therefore, I have access to read it. However, I tried to use this code to view the permissions of the backup path and obviously , I get an exception, because my backup file (destination) does not physically exist, so I can not check the permissions on it.
Then I will try another suggestion to move this check to another method.
Update - 19:45 GMT
I reworked the read / write requirements in another method:
private static FileIOPermission CheckWriteAccess(string backupPath) { FileIOPermission writeAccess = new FileIOPermission(FileIOPermissionAccess.AllAccess, backupPath); writeAccess.Demand(); return writeAccess; } private static FileIOPermission CheckReadAccess(string path) { FileIOPermission ioPerm = new FileIOPermission(FileIOPermissionAccess.Read, path); ioPerm.Demand(); return ioPerm; }
Both of them respond perfectly without exception.
Therefore, if .NET Security increases the DACL, I wonder why it believes that it will be successful, if in fact it is not.
-
Update 19:57 GMT
Ok, I checked Directory permissions and not backupFile (destination file) and got this as output (using foreach in AuthorizationRuleCollection from .GetAccessRules ())
Checking write access in this directory ....
FullControl => Allow
268435456 => Allow
FullControl => Allow
268435456 => Allow
FullControl => Allow
268435456 => Allow
ReadAndExecute, Synchronize => Allow
-1610612736 => Allow
268435456 => Allow
I used Enum.Format(typeof(FileSystemAccessRights),rule,"G") to get the formatting efficiently using ToString (), but I was just not sure that these numbers are correct.
Code for the output of the above:
private static DirectorySecurity CheckWriteAccess(string backupPath) { DirectorySecurity writeAccess = new DirectorySecurity( Path.GetDirectoryName(backupPath),AccessControlSections.Access); Console.WriteLine("Checking write access in this directory...."); foreach (FileSystemAccessRule rule in writeAccess.GetAccessRules(true, true, typeof(NTAccount))) { Console.WriteLine("{0} => {1}", Enum.Format(typeof(FileSystemRights),rule.FileSystemRights,"G"), rule.AccessControlType); } return writeAccess; }