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

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.

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.

Check network file permission in .NET

I have to check if user, that login into system and run the application, have a specified permissions on some file.
User that run the application is in "BUILTIN\Administrators" group.
While file is local all going fine. I use that code (adopted version from that answers Checking for directory and file write permissions in .NET):
private static bool HasPermission(FileSystemRights permission, AuthorizationRuleCollection accessRules )
{
var allow = false;
var inheritedDeny = false;
var inheritedAllow = false;
if (accessRules == null)
return false;
var currentUser = WindowsIdentity.GetCurrent();
var currentPrincipal = new WindowsPrincipal(currentUser);
foreach (FileSystemAccessRule rule in accessRules)
{
if ((permission & rule.FileSystemRights) != permission)
continue;
if (!currentPrincipal.IsInRole(rule.IdentityReference.Value))
{
continue;
}
if (rule.AccessControlType == AccessControlType.Allow)
{
if (rule.IsInherited)
inheritedAllow = true;
else
allow = true;
}
else if (rule.AccessControlType == AccessControlType.Deny)
{
if (!rule.IsInherited)
return false;
inheritedDeny = true;
}
}
var combined = allow || (inheritedAllow && !inheritedDeny);
return combined;
}
But when I try to check permissions on network shared file I have issue.
For example file shared with FullControl access rule for remote computer user, that remote user also in "BUILTIN/Administrators" group. For "Everyone" group user it is ReadOnly file.
So when I check this with my current, local, log in user by using that code:
if (!currentPrincipal.IsInRole(rule.IdentityReference.Value))
{
continue;
}
I do not go inside of IF condition due my log-in user also in "BUILTIN/Administrators" group.
So code returns TRUE, but in real life I have no write access to that file.
How do can I distinct local and remote Administrator's group users?
PS: I do not want to use exceptions to check accessibility, this will be the "last hope code"

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;
}

C# Linq for files user has read access to

How would I use Linq on list.Items = directoryInfo.GetFiles("\\server\share\folder\"); to include only the files the user has read access to?
...
So far only suggestions are using try/catches, or APIs that are obsolete in .NET 4.0? I'd prefer something to read the ACL's and see if the specific user or a group the user is a member of has been granted read access. I'm trying to do this for simplified management of granting reports to users on a website that won't be high traffic, so the logic that "who knows if you can actually read it when you try to open the file" doesn't pertain to this case. I sense that Microsoft should really make this task easier.
You run the risk of a race condition if you check for read permission prior to opening the file.
If you're attempting to read all of the files you have access to in a folder, better to just try opening each one and catch the UnauthorizedAccessException.
See:
how can you easily check if access is denied for a file in .NET?
How do you check for permissions to write to a directory or file?
just try this out .should work .haven't tested though
var fw = from f in new DirectoryInfo("C:\\Users\\User\\Downloads\\").GetFiles()
where SecurityManager.IsGranted(new FileIOPermission
(FileIOPermissionAccess.Write, f.FullName))
select f;
EDIT if it is just read only files then try this
var fe = from f in new DirectoryInfo("C:\\Users\\ashley\\Downloads\\").GetFiles()
where f.IsReadOnly==true
select f
Note: I haven't tested it, but in theory it should work
First, define a predicate to determine read access
bool CanRead(FileInfo file)
{
try {
file.GetAccessControl();
//Read and write access;
return true;
}
catch (UnauthorizedAccessException uae)
{
if (uae.Message.Contains("read-only"))
{
//read-only access
return true;
}
return false;
}
}
Then, it should be a simple case of using a where clause in a linq query
from file in directoryInfo.GetFiles("\\server\share\folder\")
where HaveAccess(f) == true
select f;
Tested and working, but will return false if the file is in use
void Main()
{
var directoryInfo = new DirectoryInfo(#"C:\");
var currentUser = WindowsIdentity.GetCurrent();
var files = directoryInfo.GetFiles(".").Where(f => CanRead(currentUser, f.FullName));
}
private bool CanRead(WindowsIdentity user, string filePath)
{
if(!File.Exists(filePath))
return false;
try
{
var fileSecurity = File.GetAccessControl(filePath, AccessControlSections.Access);
foreach(FileSystemAccessRule fsRule in fileSecurity.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier)))
{
foreach(var usrGroup in user.Groups)
{
if(fsRule.IdentityReference.Value == usrGroup.Value)
return true;
}
}
} catch (InvalidOperationException) {
//File is in use
return false;
}
return false;
}

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