Hi I want to check if a particular folder is shared with a user.
for the normal share rights, I can the info by
DirectoryInfo di = new DirectoryInfo(path);
DirectorySecurity acl = di.GetAccessControl(AccessControlSections.All);
AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount));
//Go through the rules returned from the DirectorySecurity
foreach (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)
{
Console.WriteLine(string.Format("{0} has write access to {1}", NtAccountName, path));
}
else
{
Console.WriteLine(string.Format("{0} does not have write access to {1}", NtAccountName, path));
}
}
}
But the problem with this approach is that the if shared the folder using the "Advanced Share" option, as shown in image, it doesn't show any entry into the log.
How to calculate it?
Related
I want to be able to set the persmissions for subfolders and files inside a targeted folder for a specific user.
Up until now i found out how to set the permissions for a specific folder. But not for subfolders and files inside the original folder.
After extensive internet search i could not find any clue on how to tackle this problem. Also the windows doku just shows how to set permission for only a directory.
class DirectoryPermissions
{
public static void DirectoryPermissionsMain(string Directory, string Account, string Rights, int Takeaway, string Domain)
{
try
{
string DirectoryName = Directory;
Console.WriteLine("Adding access control entry for " + DirectoryName);
if(Takeaway == 0 && Rights.Equals("Read")){
AddDirectorySecurity(DirectoryName, Domain + #"\" + Account, FileSystemRights.ReadData, AccessControlType.Allow);
Console.WriteLine("Removing access control entry from " + DirectoryName);
}
MessageBox.Show("Done");
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadLine();
}
// Adds an ACL entry on the specified directory for the specified account.
public static void AddDirectorySecurity(string FileName, string Account, FileSystemRights Rights, AccessControlType ControlType)
{
// Create a new DirectoryInfo object.
DirectoryInfo dInfo = new DirectoryInfo(FileName);
// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = dInfo.GetAccessControl();
// Add the FileSystemAccessRule to the security settings.
dSecurity.AddAccessRule(new FileSystemAccessRule(Account,
Rights,
ControlType));
// Set the new access settings.
dInfo.SetAccessControl(dSecurity);
}
}
I hope one of you can point me in the right direction.
You have to add another AccessRule with InheritanceFlags set to ContainerInherit AND ObjectInherit.
To get the permissions to propgate to child folders, the PropagationFlag is set to Inherit only.
Here's an example below
public void PropogateSecurity(string userid,string directory)
{
var myDirectoryInfo = new DirectoryInfo(directory);
var myDirectorySecurity = myDirectoryInfo.GetAccessControl();
myDirectorySecurity.AddAccessRule(new FileSystemAccessRule(userid, FileSystemRights.Modify, InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));
myDirectorySecurity.AddAccessRule(new FileSystemAccessRule(userid, FileSystemRights.Modify, InheritanceFlags.ObjectInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));
myDirectoryInfo.SetAccessControl(myDirectorySecurity);
}
You can also do this with recursion, but the above would be my preferred method as cleaning up permissions would be annoying.
I can search folder permissions using cacls.exe with command prompt and output them to a text file but I need to display the folder permissions within the C# program so that i can use them in strings etc.
DirectorySecurity dSecurity = Directory.GetAccessControl(#"d:\myfolder");
foreach (FileSystemAccessRule rule in dSecurity.GetAccessRules(true, true, typeof(NTAccount)))
{
if (rule.FileSystemRights == FileSystemRights.Read)
{
Console.WriteLine("Account:{0}", rule.IdentityReference.Value);
}
}
We have a scenario in our client project where the client application saves and tries to fetch files from a shared folder location , which is a virtual shared folder. But we have been facing issues with a specific application user id losing access to that shared folder. So we need help in pre advance checking if the access is present for that user id on that shared folder location . So thinking of an application to be developed in C# or vb.net to check for that user access .
the way I believe best to check the permission, is try to access the directory (read/write/list) & catch the UnauthorizedAccessException.
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;
}
Is it possible in C#/.NET to determine where an inherited System.Security.AccessControl.FileSystemAccessRule was actually inherited from? If so, how do I do that? I want to create an output that is like in the Windows security property, where you can see to which object an inherited ACE was attached to.
You will have to walk through the file or folder's path to find where the rule originated. Here's a crude set of functions that will print all access rules and where the originated from. You can easily modify this to create a more useful API (in other words, not just print to Console).
void PrintAccessRules(string path)
{
var security = File.GetAccessControl(path);
var accessRules = security.GetAccessRules(true, true, typeof(NTAccount));
foreach (var rule in accessRules.Cast<FileSystemAccessRule>())
{
if (!rule.IsInherited)
{
Console.WriteLine("{0} {1} to {2} was set on {3}.", rule.AccessControlType, rule.FileSystemRights, rule.IdentityReference, path);
continue;
}
FindInheritedFrom(rule, Directory.GetParent(path).FullName);
}
}
void FindInheritedFrom(FileSystemAccessRule rule, string path)
{
var security = File.GetAccessControl(path);
var accessRules = security.GetAccessRules(true, true, typeof(NTAccount));
var matching = accessRules.OfType<FileSystemAccessRule>()
.FirstOrDefault(r => r.AccessControlType == rule.AccessControlType && r.FileSystemRights == rule.FileSystemRights && r.IdentityReference == rule.IdentityReference);
if (matching != null)
{
if (matching.IsInherited) FindInheritedFrom(rule, Directory.GetParent(path).FullName);
else Console.WriteLine("{0} {1} to {2} is inherited from {3}", rule.AccessControlType, rule.FileSystemRights, rule.IdentityReference, path);
}
}
For example:
PrintAccessRules(#"C:\projects\mg\lib\repositories.config");
Prints the following for me:
Allow FullControl to SkipTyler\Mike was set on C:\projects\mg\lib\repositories.config.
Allow ReadAndExecute, Synchronize to SkipTyler\Mike is inherited from C:\projects\mg
Allow FullControl to BUILTIN\Administrators is inherited from C:\
Allow FullControl to NT AUTHORITY\SYSTEM is inherited from C:\
Allow ReadAndExecute, Synchronize to BUILTIN\Users is inherited from C:\
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.