I'm using this code snippet to turn inheritance on and off on a pre-determined folder.
I'm also using it to allow permissions to be added explicitly.
Although I believe the code works fine when the folder has only explicit permissions. As soon as I try to add a user/group when there are inherited permissions the code duplicates the inherited permissions so that I now have both inherited and explicit permissions which are identical. The user/group I'm trying to add doesn't get added.
<pre lang="xml">public class fsAccessLayer
{
public fsAccessLayer()
{
}
private List<ace> _dacl;
private string _cachedPath = "root";
private bool _isInheriting = false;
private bool _updating = false;
public bool IsInheriting
{
get { return this._isInheriting; }
set { this._isInheriting = value; }
}
private string _errorMessage;
public string ErrorMessage
{
get { return this._errorMessage; }
set { this._errorMessage = value; }
}
public List<ace> Dacl
{
get { return _dacl; }
set { _dacl = value; }
}
public void AddAce(string user, string access)
{
ace entry = new ace();
entry.UserAccount = user;
entry.IsInherited = false;
entry.Access = access;
_dacl.Add(entry);
}
public string[] GetDirectories(string folder)
{
DirectorySecurity dirSecurity = null;
string[] folders = null;
List<string> result = null;
_errorMessage = null;
try
{
folders = Directory.GetDirectories(folder);
}
catch (UnauthorizedAccessException ex)
{
_errorMessage = "You are not authorised to access this folder.";
throw new Exception(_errorMessage, ex);
}
catch (DirectoryNotFoundException ex)
{
_errorMessage = "Trouble locating the folder. Please try again.";
throw new Exception(_errorMessage, ex);
}
catch (Exception ex)
{
_errorMessage = ex.Message;
throw new Exception(_errorMessage, ex);
}
result = new List<string>();
foreach (string fld in folders)
{
try
{
dirSecurity = Directory.GetAccessControl(fld);
result.Add(fld);
}
catch (Exception ex)
{
}
}
return result.ToArray();
}
public List<ace> GetDacl(string path, string sortExpression)
{
List<ace> _dacl = GetDacl(path);
if (null != _dacl)
switch (sortExpression)
{
case "UserAccount":
_dacl.Sort(new UserAccountComparer());
break;
case "UserAccount DESC":
_dacl.Sort(new UserAccountDescComparer());
break;
case "Access":
_dacl.Sort(new AccessComparer());
break;
case "Access DESC":
_dacl.Sort(new AccessDescComparer());
break;
default:
break;
}
return _dacl;
}
public List<ace> GetDacl(string path)
{
if (null == path) return null;
if (_cachedPath.CompareTo(path) == 0 && _dacl.Count > 0) return _dacl;
_cachedPath = path;
return GetDacl();
}
public List<ace> GetDacl()
{
if (_updating) return null;
DirectoryInfo targetDirectory = null;
DirectorySecurity dirSecurity = null;
AuthorizationRuleCollection dirRules = null;
try
{
targetDirectory = new DirectoryInfo(_cachedPath);
dirSecurity = targetDirectory.GetAccessControl(AccessControlSections.Access);
dirRules = dirSecurity.GetAccessRules(true, true, typeof(NTAccount));
}
catch (Exception ex)
{
_errorMessage = ex.Message;
return null;
}
string acct = null;
_dacl.Clear();
_isInheriting = false;
foreach (AuthorizationRule rule in dirRules)
{
acct = rule.IdentityReference.Value;
if (acct.Contains("Administrators")) continue;
if (acct.Contains("File-Managers")) continue;
ace entry = new ace();
entry.Rule = (FileSystemAccessRule)rule;
_isInheriting |= rule.IsInherited;
foreach (ace item in _dacl)
{
if (item.UserAccount == entry.UserAccount)
{
if (item.Rule.FileSystemRights < entry.Rule.FileSystemRights)
item.Rule = entry.Rule;
entry = null;
break;
}
}
if (null != entry)
_dacl.Add(entry);
}
return _dacl;
}
public void UpdateDacl()
{
_updating = true;
_errorMessage = string.Empty;
DirectorySecurity dirSecurity = new DirectorySecurity();
if (IsInheriting == false)
{
dirSecurity = Directory.GetAccessControl(_cachedPath);
dirSecurity.SetAccessRuleProtection(true, true);
foreach (ace entry in _dacl)
{
if (entry.Rule == null)
{
NTAccount acct = new NTAccount(entry.UserAccount);
IdentityReference id = acct.Translate(typeof(SecurityIdentifier));
dirSecurity.PurgeAccessRules(id);
}
else
dirSecurity.ResetAccessRule(entry.Rule);
}
Directory.SetAccessControl(_cachedPath, dirSecurity);
}
else if (IsInheriting == true)
{
dirSecurity.SetAccessRuleProtection(false, false);
Directory.SetAccessControl(_cachedPath, dirSecurity);
foreach (ace entry in _dacl)
if (entry.Rule == null)
{
NTAccount acct = new NTAccount(entry.UserAccount);
IdentityReference id = acct.Translate(typeof(SecurityIdentifier));
dirSecurity.PurgeAccessRules(id);
}
else
dirSecurity.ResetAccessRule(entry.Rule);
}
Directory.SetAccessControl(_cachedPath, dirSecurity);
_updating = false;
GetDacl();
if (Updated != null)
Updated(null,new EventArgs());
}
I've included more of the code above to show where the isinherited value comes from. I believe the code pulls it from the current value associated with the DACL "rule.isinherited". However there is also a tick box that users can turn on/off inherited permissions. The idea being when inheritance is on permissions are inherited from above but explicit permissions can be added as well. When inheritance is turned off only explicit permissions can be manipuulated.
[edit]Re-formatted to include indentation - OriginalGriff[/edit]