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.
Related
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?
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"
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.
Having an issue with a Windows service that needs to monitor/have access to a set of folders, and move files around between those folders.
There's have a bit of boilerplate code that's been used in the past, which will check a given folder for the specific granular permissions for the given user. The odd thing is that I discovered through testing that if I manually deny all permissions on that folder for the account the service is running under, and then run the code, it reports that all is well and the user does in fact have those permissions, even though it's obvious (and demonstrable) that he doesn't.
At first I thought this might be because the service was running under the local System account, but the same issue crops up if it is run with NetworkService as well as with a local user account. This is on Windows 7/2008 R2.
Boilerplate method:
public static void ValidateFolderPermissions(WindowsIdentity userId, string folder, FileSystemRights[] requiredAccessRights)
{
SecurityIdentifier secId;
StringBuilder sb = new StringBuilder();
bool permissionsAreSufficient = false;
bool notAuthorized = false;
String errorMsg = String.Empty;
IdentityReferenceCollection irc = userId.Groups;
foreach (IdentityReference ir in irc)
{
secId = ir.Translate(typeof(SecurityIdentifier)) as SecurityIdentifier;
try
{
DirectoryInfo dInfo = new DirectoryInfo(folder);
DirectorySecurity dSecurity = dInfo.GetAccessControl();
AuthorizationRuleCollection rules = dSecurity.GetAccessRules(true, true, typeof(SecurityIdentifier));
foreach (FileSystemAccessRule ar in rules)
{
if (secId.CompareTo(ar.IdentityReference as SecurityIdentifier) == 0)
{
sb.AppendLine(ar.FileSystemRights.ToString());
foreach (FileSystemRights right in requiredAccessRights)
{
if (right == ar.FileSystemRights)
{
permissionsAreSufficient = true;
break;
}
}
}
}
}
catch (UnauthorizedAccessException)
{
notAuthorized = true;
errorMsg = "user not authorized";
}
catch (SecurityException)
{
// If we failed authorization do not update error
if (!notAuthorized)
errorMsg = "security error";
}
catch (Exception)
{
// If we failed authorization do not update error
if (!notAuthorized)
errorMsg = "invalid folder or folder not accessible";
}
}
if (!permissionsAreSufficient)
{
if (!String.IsNullOrEmpty(errorMsg))
throw new Exception(String.Format("User {0} does not have required access to folder {1}. The error is {2}.", userId.Name, folder, errorMsg));
else
throw new Exception(String.Format("User {0} does not have required access rights to folder {1}.", userId.Name, folder));
}
}
And the calling snippet:
FileSystemRights[] requireAccessRights =
{
FileSystemRights.Delete,
FileSystemRights.Read,
FileSystemRights.FullControl
};
try
{
FolderPermissionValidator.ValidateFolderPermissions(WindowsIdentity.GetCurrent(), inputFolder, requireAccessRights);
Log.Debug("In ServiceConfigurationValidator: {0}, {1}", WindowsIdentity.GetCurrent().Name, inputFolder);
}
catch (Exception ex)
{
Log.Debug("Throwing exception {0}", ex.Message);
}
I don't see anything in ValidateFolderPermissions to check for denials before checking for allowed permissions. If a deny entry prevents access then no amount of allow entries can override it.
This code enumerates the entries in the ACL as FileSystemAccessRule objects, but doesn't bother to check whether AccessControlType is allow or deny.
I also note that the logic returns true if any ACE exactly matches any of the elements of the requiredAccessRights array; I suspect the intended behaviour is that it return true if all of the specified rights are present. This could cause false positives if only some of the requested rights are present, but because it only looks for exact matches it could also cause a false negative, e.g., if the ACE actually gives more rights than are being requested. (Not such a problem in the example given, though, because you're asking for Full Control.)
Another flaw is that it only checks for access entries matching groups the user belongs to; access entries for the user account itself will be ignored. (I'm not sure what the behaviour of WindowsIdentity.Groups is for security primitives such as SYSTEM and NetworkService that are not actual user accounts, although it sounds like that part was working as desired.)
Note that because it is very hard to cope properly with all the possible situations (consider, e.g., an access control entry for Everyone, or for SERVICE) it would be wise to allow the administrator to override the check if it is mistakenly reporting that the account doesn't have the necessary access.
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.