UnauthorizedAccessException When trying get access rules using DirectorySecurity library - c#

I am trying to get a particular folder write access for users using a method that gets access rules and checks wheather the logged in user has write access for that folder. But when trying to do this I am getting an error stating UnauthorizedException.I have checked the folder access and everything looks good.I Below is the screenshot of the error:
private bool AccessPackerPlanTemplate()
{
bool result = true;
UserBUList userBUList = new UserBUList();
try
{
string PackerPlanTemplate = System.Configuration.ConfigurationSettings.AppSettings["PackerPlanTemplate"];
userBUList.UserName = (HttpContext.Current.User.Identity).Name.Split('\\')[1].ToString();
string path = PackerPlanTemplate;
string NtAccountName = userBUList.UserName;
DirectoryInfo di = new DirectoryInfo(path);
DirectorySecurity acl = di.GetAccessControl(AccessControlSections.All); //I AM GETTING ERROR ON THIS LINE
System.Security.AccessControl.AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount));
//Go through the rules returned from the DirectorySecurity
foreach (System.Security.AccessControl.AuthorizationRule rule in rules)
{
//If we find one that matches the identity we are looking for
if (rule.IdentityReference.Value.Equals(NtAccountName, StringComparison.CurrentCultureIgnoreCase))
{
//Cast to a FileSystemAccessRule to check for access rights
if ((((FileSystemAccessRule)rule).FileSystemRights & FileSystemRights.WriteData) > 0)
{
result = true ;
}
}
}
}
catch (UnauthorizedAccessException)
{
result = false;
}
return result;
}
Does somebody has any suggestion regarding Where am I going wrong? Is there a better way to do this?

Related

C# How to get Read/Write permissions of another user? [duplicate]

This question already has answers here:
C# Test if user has write access to a folder
(19 answers)
Closed 7 years ago.
I need to check the Read/Write permissions on a certain path. But the big problem is, I don't want to check my own instead I want to check them for another user.
This checks the user who runs the program.
System.Security.Principal.NTAccount
How am I able to check for example the user "OTHERUSER"?
This is my code so far.
private Boolean CheckZugriff(string str_projektpfad)
{
str_projektpfad = Path.GetDirectoryName(str_projektpfad);
bool isWriteAccess = false;
try
{
AuthorizationRuleCollection collection = Directory.GetAccessControl(str_projektpfad).GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
foreach (FileSystemAccessRule rule in collection)
{
if (rule.AccessControlType == AccessControlType.Allow)
{
isWriteAccess = true;
break;
}
}
}
catch (UnauthorizedAccessException ex)
{
isWriteAccess = false;
}
catch (Exception ex)
{
isWriteAccess = false;
}
if (!isWriteAccess)
{
//handle notifications
}
return isWriteAccess;
}
Found two things that may help you...
1) This code checks what permissions set for the folder for all users:
string directory = "your path";
DirectoryInfo di = new DirectoryInfo(directory);
DirectorySecurity ds = di.GetAccessControl();
2) This code checks if your user has administrator rights :
bool isElevated;
WindowsIdentity identity = new WindowsIdentity("user principal name goes here");
WindowsPrincipal principal = new WindowsPrincipal(identity);
isElevated = principal.IsInRole(WindowsBuiltInRole.Administrator);
It's logical that if user is not an admin and there is no rule set for him - he cannot access the folder. Not sure if it address your problem but hope it helps.

what is the best way to check in C# .NET if a directory has access to list files or a unauthorized access exception would rise

how would I check in the best way in .NET 2.0 C# if I have access to a specified directory
for listing top directory files e.g. a system directory or system volume information folder etc.
My code for it looks now like this, but I think it is not the best way to check for it since it produces an exception each time which is handled by the check function and returning based on it a result.
I would like to use a function which doesn't throw an error to check if in the specified directory is access to list files or maybe my code can be improved or optimized. I might have to check through a thousand directories if exists an access or not. Raising thousand exceptions might cause a problem, but I don't know.
//here my code using System.IO;
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(DirectoryCanListFiles("C:\\Windows\\Prefetch").ToString());
}
public static bool DirectoryCanListFiles(string DirectoryPath)
{
try
{
Directory.GetFiles(DirectoryPath, "*", SearchOption.TopDirectoryOnly);
}
catch { return false; }
return true;
}
The best way to check the permission, is try to access the direcoty (read/write/list) & catch the UnauthorizedAccessException.
However for some reason out there, if you want to check permissions, following code should satisfy your need.
You need to read Access Rules for the directory.
private bool DirectoryCanListFiles(string folder)
{
bool hasAccess = false;
//Step 1. Get the userName for which, this app domain code has been executing
string executingUser = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
NTAccount acc = new NTAccount(executingUser);
SecurityIdentifier secId = acc.Translate(typeof(SecurityIdentifier)) as SecurityIdentifier;
DirectorySecurity dirSec = Directory.GetAccessControl(folder);
//Step 2. Get directory permission details for each user/group
AuthorizationRuleCollection authRules = dirSec.GetAccessRules(true, true, typeof(SecurityIdentifier));
foreach (FileSystemAccessRule ar in authRules)
{
if (secId.CompareTo(ar.IdentityReference as SecurityIdentifier) == 0)
{
var fileSystemRights = ar.FileSystemRights;
Console.WriteLine(fileSystemRights);
//Step 3. Check file system rights here, read / write as required
if (fileSystemRights == FileSystemRights.Read ||
fileSystemRights == FileSystemRights.ReadAndExecute ||
fileSystemRights == FileSystemRights.ReadData ||
fileSystemRights == FileSystemRights.ListDirectory)
{
hasAccess = true;
}
}
}
return hasAccess;
}

compare windows file (or folder) permissions

I occasionally migrate some website from one web server to another.
After copying all files from the old server to the new server, it takes me quite some time to get (re)acquainted with which folders or files need to be writable by IIS. (Sounds familiar, by the way ? :) )
I have written a WinForms application that allows me to select a starting directory. The application should (recursively) compare if the security permissions of each file/directory are equal to that of its parent directory.
I want to use this application on the old server to scan for directories with different permissions.
Example: C:\MySites\Uploads does not have the same permissions set as its parent directory. (This folder was writable for the IIS user 'IUSR', while its parent folder was only readable.)
The application is almost complete in the sense that I manage to traverse all directories and files. I just need to compare their permissions!
Can you please help? Here is an excerpt of where I need your help.
string results = "";
string parentFolderPath = "c:\\someParentDir";
string childItemPath = "c:\\someParentDir\\SomeChildDir.ext";
DirectorySecurity parentFolderAccessControl = Directory.GetAccessControl(parentFolderPath);
DirectorySecurity childItemAccessControl = Directory.GetAccessControl(childItemPath);
if (!parentFolderAccessControl.Equals(childItemAccessControl)) // <-- D'oh here
{
results += childItemPath + " does not have the same permissions set as its parent directory.\n";
}
The if is always true, because the DirectorySecurities are never equal. (I understand why that is: reference to different memory allocations ... blah blah.) But what would be the best way to compare the DirectorySecurities?
This actually became much more complex while I was working it out, because Windows rights can:
split up into Allow and Deny
Fragmented over multiple entries (multiple entries per user per Allow/Deny)
Eventually, this is what I made out of it:
private bool compareAccessControls(
DirectorySecurity parentAccessControl,
DirectorySecurity childAccessControl,
out Dictionary<IdentityReference, FileSystemRights> accessAllowRulesGainedByChild,
out Dictionary<IdentityReference, FileSystemRights> accessDenyRulesGainedByChild,
out Dictionary<IdentityReference, FileSystemRights> accessAllowRulesGainedByParent,
out Dictionary<IdentityReference, FileSystemRights> accessDenyRulesGainedByParent
)
{
// combine parent access rules
Dictionary<IdentityReference, FileSystemRights> combinedParentAccessAllowRules = new Dictionary<IdentityReference, FileSystemRights>();
Dictionary<IdentityReference, FileSystemRights> combinedParentAccessDenyRules = new Dictionary<IdentityReference, FileSystemRights>();
foreach (FileSystemAccessRule parentAccessRule in parentAccessControl.GetAccessRules(true, true, typeof(NTAccount)))
{
if (parentAccessRule.AccessControlType == AccessControlType.Allow)
if (combinedParentAccessAllowRules.ContainsKey(parentAccessRule.IdentityReference))
combinedParentAccessAllowRules[parentAccessRule.IdentityReference] = combinedParentAccessAllowRules[parentAccessRule.IdentityReference] | parentAccessRule.FileSystemRights;
else
combinedParentAccessAllowRules.Add(parentAccessRule.IdentityReference, parentAccessRule.FileSystemRights);
else
if (combinedParentAccessDenyRules.ContainsKey(parentAccessRule.IdentityReference))
combinedParentAccessDenyRules[parentAccessRule.IdentityReference] = combinedParentAccessDenyRules[parentAccessRule.IdentityReference] | parentAccessRule.FileSystemRights;
else
combinedParentAccessDenyRules.Add(parentAccessRule.IdentityReference, parentAccessRule.FileSystemRights);
}
// combine child access rules
Dictionary<IdentityReference, FileSystemRights> combinedChildAccessAllowRules = new Dictionary<IdentityReference, FileSystemRights>();
Dictionary<IdentityReference, FileSystemRights> combinedChildAccessDenyRules = new Dictionary<IdentityReference, FileSystemRights>();
foreach (FileSystemAccessRule childAccessRule in childAccessControl.GetAccessRules(true, true, typeof(NTAccount)))
{
if (childAccessRule.AccessControlType == AccessControlType.Allow)
if (combinedChildAccessAllowRules.ContainsKey(childAccessRule.IdentityReference))
combinedChildAccessAllowRules[childAccessRule.IdentityReference] = combinedChildAccessAllowRules[childAccessRule.IdentityReference] | childAccessRule.FileSystemRights;
else
combinedChildAccessAllowRules.Add(childAccessRule.IdentityReference, childAccessRule.FileSystemRights);
else
if (combinedChildAccessDenyRules.ContainsKey(childAccessRule.IdentityReference))
combinedChildAccessDenyRules[childAccessRule.IdentityReference] = combinedChildAccessDenyRules[childAccessRule.IdentityReference] | childAccessRule.FileSystemRights;
else
combinedChildAccessDenyRules.Add(childAccessRule.IdentityReference, childAccessRule.FileSystemRights);
}
// compare combined rules
accessAllowRulesGainedByChild = new Dictionary<IdentityReference, FileSystemRights>();
foreach (KeyValuePair<IdentityReference, FileSystemRights> combinedChildAccessAllowRule in combinedChildAccessAllowRules)
{
if (combinedParentAccessAllowRules.ContainsKey(combinedChildAccessAllowRule.Key))
{
FileSystemRights accessAllowRuleGainedByChild = combinedChildAccessAllowRule.Value & ~combinedParentAccessAllowRules[combinedChildAccessAllowRule.Key];
if (accessAllowRuleGainedByChild != default(FileSystemRights))
accessAllowRulesGainedByChild.Add(combinedChildAccessAllowRule.Key, accessAllowRuleGainedByChild);
}
else
{
accessAllowRulesGainedByChild.Add(combinedChildAccessAllowRule.Key, combinedChildAccessAllowRule.Value);
}
}
accessDenyRulesGainedByChild = new Dictionary<IdentityReference, FileSystemRights>();
foreach (KeyValuePair<IdentityReference, FileSystemRights> combinedChildAccessDenyRule in combinedChildAccessDenyRules)
{
if (combinedParentAccessDenyRules.ContainsKey(combinedChildAccessDenyRule.Key))
{
FileSystemRights accessDenyRuleGainedByChild = combinedChildAccessDenyRule.Value & ~combinedParentAccessDenyRules[combinedChildAccessDenyRule.Key];
if (accessDenyRuleGainedByChild != default(FileSystemRights))
accessDenyRulesGainedByChild.Add(combinedChildAccessDenyRule.Key, accessDenyRuleGainedByChild);
}
else
{
accessDenyRulesGainedByChild.Add(combinedChildAccessDenyRule.Key, combinedChildAccessDenyRule.Value);
}
}
accessAllowRulesGainedByParent = new Dictionary<IdentityReference, FileSystemRights>();
foreach (KeyValuePair<IdentityReference, FileSystemRights> combinedParentAccessAllowRule in combinedParentAccessAllowRules)
{
if (combinedChildAccessAllowRules.ContainsKey(combinedParentAccessAllowRule.Key))
{
FileSystemRights accessAllowRuleGainedByParent = combinedParentAccessAllowRule.Value & ~combinedChildAccessAllowRules[combinedParentAccessAllowRule.Key];
if (accessAllowRuleGainedByParent != default(FileSystemRights))
accessAllowRulesGainedByParent.Add(combinedParentAccessAllowRule.Key, accessAllowRuleGainedByParent);
}
else
{
accessAllowRulesGainedByParent.Add(combinedParentAccessAllowRule.Key, combinedParentAccessAllowRule.Value);
}
}
accessDenyRulesGainedByParent = new Dictionary<IdentityReference, FileSystemRights>();
foreach (KeyValuePair<IdentityReference, FileSystemRights> combinedParentAccessDenyRule in combinedParentAccessDenyRules)
{
if (combinedChildAccessDenyRules.ContainsKey(combinedParentAccessDenyRule.Key))
{
FileSystemRights accessDenyRuleGainedByParent = combinedParentAccessDenyRule.Value & ~combinedChildAccessDenyRules[combinedParentAccessDenyRule.Key];
if (accessDenyRuleGainedByParent != default(FileSystemRights))
accessDenyRulesGainedByParent.Add(combinedParentAccessDenyRule.Key, accessDenyRuleGainedByParent);
}
else
{
accessDenyRulesGainedByParent.Add(combinedParentAccessDenyRule.Key, combinedParentAccessDenyRule.Value);
}
}
if (accessAllowRulesGainedByChild.Count > 0 || accessDenyRulesGainedByChild.Count > 0 || accessAllowRulesGainedByParent.Count > 0 || accessDenyRulesGainedByParent.Count > 0)
return false;
else
return true;
}
You cannot use Equals() since this method is inherited from Object.
You need to find a identifying attribute on that DirectorySecurity class. I think
String GetSecurityDescriptorSddlForm()
should do your job. You can invoke Equals() on that.
Edit: Well sorry, this method needs a parameter for invocation. Try finding another attribute on the DirectorySecurity which is better for comparison.
Edit2: I'm not familar with .NET Security Framework and Right-Management, but something like this should be your approach. You can do != resp: == on FileSystemAccessRule.FileSystemRights because that attribute is an enum (internally an int).
ArrayList notIdenticalList = new ArrayList();
DirectorySecurity parentFolderAccessControl = Directory.GetAccessControl(null);
DirectorySecurity childItemAccessControl = Directory.GetAccessControl(null);
foreach (FileSystemAccessRule parentRule in parentFolderAccessControl.GetAccessRules(true, true, typeof(NTAccount)))
{
foreach (FileSystemAccessRule childRule in childItemAccessControl.GetAccessRules(true, true, typeof(NTAccount)))
{
if (parentRule.FileSystemRights != childRule.FileSystemRights)
{
// add to not identical-list
notIdenticalList.Add(fileToAdd...);
break;
}
}
}

Check if directory is accessible in C#? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
.NET - Check if directory is accessible without exception handling
Im making a small file explorer in Visual Studio 2010 with NET 3.5 and C#, and I have this function to check if a directory is accessible:
RealPath=#"c:\System Volume Information";
public bool IsAccessible()
{
//get directory info
DirectoryInfo realpath = new DirectoryInfo(RealPath);
try
{
//if GetDirectories works then is accessible
realpath.GetDirectories();
return true;
}
catch (Exception)
{
//if exception is not accesible
return false;
}
}
But I think with big directories it could be slow trying to get all sub directories to check if directory is accesible.
Im using this function to prevent errors when trying to explore protected folders or cd/dvd drives without disc ("Device Not Ready" error).
Is there a better way (faster) to check if directory is accessible by the application (preferably in NET 3.5)?
According to MSDN, Directory.Exists should return false if you don't have read access to the directory. However, you can use Directory.GetAccessControl for this. Example:
public static bool CanRead(string path)
{
try
{
var readAllow = false;
var readDeny = false;
var accessControlList = Directory.GetAccessControl(path);
if(accessControlList == null)
return false;
//get the access rules that pertain to a valid SID/NTAccount.
var accessRules = accessControlList.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
if(accessRules ==null)
return false;
//we want to go over these rules to ensure a valid SID has access
foreach (FileSystemAccessRule rule in accessRules)
{
if ((FileSystemRights.Read & rule.FileSystemRights) != FileSystemRights.Read) continue;
if (rule.AccessControlType == AccessControlType.Allow)
readAllow = true;
else if (rule.AccessControlType == AccessControlType.Deny)
readDeny = true;
}
return readAllow && !readDeny;
}
catch(UnauthorizedAccessException ex)
{
return false;
}
}
Update
As mentioned in some comments, this may return an incorrect value in a case where a valid SID in an external DOMAIN has access. In order to check if the current user has access, you need something like:
foreach...
if (WindowsIdentity.GetCurrent().User.Value.equals(rule.IdentityReference.Value))
This will confirm if the SID of the current user matches the access rule identity reference but may throw a SecurityException as well.
I think you are looking for the GetAccessControl method, the System.IO.File.GetAccessControl method returns a FileSecurity object that encapsulates the access control for a file.

Checking for shared folder write access for current user

I have following method to check current user have write access to given network location
DirectorySecurity shareSecurity = new DirectoryInfo(this.GetFileServerRootPath).GetAccessControl();
foreach (FileSystemAccessRule fsRule in shareSecurity.GetAccessRules(true, true, typeof(NTAccount)))
{
// check write permission for current user
if (AccessControlType.Allow == fsRule.AccessControlType &&
FileSystemRights.Write == (fsRule.FileSystemRights & FileSystemRights.Write))
{
if (null != fsRule.IdentityReference &&
fsRule.IdentityReference.Value == WindowsIdentity.GetCurrent().Name)
{
return true;
}
}
}
return false;
but problem is when folder permission given to user group, above method is failed.
I don't want to check the permissions by writing a file and decide the write access permissions.
is there any way to find current user in the IdentityReference.Value? or suggestions to overcome this issue?
This may work for you:
FileIOPermission writePermission = new FileIOPermission(FileIOPermissionAccess.Write, this.GetFileServerRootPath);
try
{
writePermission.Demand();
return true;
}
catch (SecurityException s)
{
return false;
}
Just curious - why not just try/catch your write operation?
May be you should use DirectoryInfo on that directory to get its security policies.

Categories