1

we have created an application which provides the ability to set a recursive "Deny" on a windows folder for a certain Active Directory group. Basically the same as going into the properties dialog in windows explorer and clicking on security and the adding an AD group with the permission of Deny. We are using this code:

public void DenyAccessInherited(string DomainAndSamAccountName)
    {
        SetPermissionAndInherit(this.FolderPath, 
            NTFSPermission.PropagationFlags.CONTAINER_AND_OBJECT_INHERIT_ACE,
            NTFSPermission.NTFSPermission_FULL_CONTROL, NTFSPermission.ACETypes.ADS_ACETYPE_ACCESS_DENIED,
            DomainAndSamAccountName);
    }

public static void SetPermissionAndInherit(string FolderPath, PropagationFlags Inheritance, int Permission, ACETypes ACETypeAccessAllowedDenied, string DomainAndUsername)
    {
        AccessControlList dacl = new AccessControlList();
        SecurityDescriptor sd = new SecurityDescriptor();
        AccessControlEntry newAce = new AccessControlEntry();
        ADsSecurityUtility sdUtil = new ADsSecurityUtility();

        OnProgress(DomainAndUsername, FolderPath);
        sd = sdUtil.GetSecurityDescriptor(FolderPath, ADS_PATH_FILE, ADS_SD_FORMAT_IID);
        dacl = sd.DiscretionaryAcl;

        RemoveTrusteeFromDACL(dacl, DomainAndUsername);

        newAce.Trustee = DomainAndUsername;
        newAce.AccessMask = Permission;

        newAce.AceFlags = (int)Inheritance;
        newAce.AceType = (int)ACETypeAccessAllowedDenied;
        dacl.AddAce(newAce);

        sdUtil.SetSecurityDescriptor(FolderPath, ADS_PATH_FILE, sd, ADS_SD_FORMAT_IID);

        foreach (string File in Directory.GetFiles(FolderPath))
        {
            SetACE(File, DomainAndUsername, Permission, PropagationFlags.INHERITED_ACE, ACETypeAccessAllowedDenied);
        }
        foreach (string SubFolderPath in Directory.GetDirectories(FolderPath))
        {
            SetInheritedPermission(SubFolderPath, DomainAndUsername, Permission, ACETypeAccessAllowedDenied);
        }
    }

private static void SetInheritedPermission(string FolderPath, string DomainAndUsername, int PermissionFlags, ACETypes AccessFlags)
    {
        AccessControlList dacl = new AccessControlList();
        SecurityDescriptor sd = new SecurityDescriptor();
        AccessControlEntry newAce = new AccessControlEntry();
        ADsSecurityUtility sdUtil = new ADsSecurityUtility();

        SetACE(FolderPath, DomainAndUsername, PermissionFlags, (PropagationFlags)(PropagationFlags.CONTAINER_AND_OBJECT_INHERIT_ACE | PropagationFlags.INHERITED_ACE), AccessFlags);
        foreach (string File in Directory.GetFiles(FolderPath))
        {
            SetACE(File, DomainAndUsername, PermissionFlags, PropagationFlags.INHERITED_ACE, AccessFlags);
        }
        foreach (string SubFolderPath in Directory.GetDirectories(FolderPath))
        {
            SetInheritedPermission(SubFolderPath, DomainAndUsername, PermissionFlags, AccessFlags);
        }
    }


private static void SetACE(string FileOrFolder, string DomainAndUsername, int PermissionFlags, PropagationFlags InheritanceFlags, ACETypes AccessFlags)
    {
        AccessControlList dacl = new AccessControlList();
        SecurityDescriptor sd = new SecurityDescriptor();
        AccessControlEntry newAce = new AccessControlEntry();
        ADsSecurityUtility sdUtil = new ADsSecurityUtility(); sd = sdUtil.GetSecurityDescriptor(FileOrFolder, ADS_PATH_FILE, ADS_SD_FORMAT_IID);
        sd.Control = sd.Control;
        OnProgress(DomainAndUsername, FileOrFolder);

        dacl = sd.DiscretionaryAcl;
        RemoveTrusteeFromDACL(dacl, DomainAndUsername);

        newAce.Trustee = DomainAndUsername;
        newAce.AccessMask = PermissionFlags;

        newAce.AceFlags = (int)InheritanceFlags;
        newAce.AceType = (int)AccessFlags;
        dacl.AddAce(newAce);

        sdUtil.SetSecurityDescriptor(FileOrFolder, ADS_PATH_FILE, sd, ADS_SD_FORMAT_IID);
    }

Now we have encountered a large folder with lots of html documents, about 12000 files, and the method above is very slow. It takes about 7 minutes to process the file security. However, when managing security through windows explorer/security it only takes about 20 seconds so there must be some way to optimize this in C#.

Edit: When I leave out the recursion and only set the SecurityDescriptor on the top folder, none of the files below it have the deny for the AD group, only the top folder.

hoetz
  • 2,368
  • 4
  • 26
  • 58

2 Answers2

2

I solved it. I completely dumped the above code and went another way:

public override void DenyAccessInherited(string FolderPath,string DomainAndSamAccountName)
    {
        using (Impersonator imp = new Impersonator(this.connection.GetSamAccountName(), this.connection.GetDomain(), this.connection.Password))
        {
            FileSystemAccessRule rule = new FileSystemAccessRule(DomainAndSamAccountName, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, System.Security.AccessControl.PropagationFlags.InheritOnly, AccessControlType.Deny);
            DirectoryInfo di = new DirectoryInfo(FolderPath);
            DirectorySecurity security = di.GetAccessControl(AccessControlSections.All);
            bool modified;
            security.ModifyAccessRule(AccessControlModification.Add, rule, out modified);
            if (modified)
                di.SetAccessControl(security);

        }
    }

This is very slim and very fast.

hoetz
  • 2,368
  • 4
  • 26
  • 58
0

Nested folders and files should inherit parent's security settings so you don't need to set it recursively for all. Try to set it only for root folder.

lorond
  • 3,856
  • 2
  • 37
  • 52
  • I tried commenting out the foreach blocks but when I do that, start the method and look up the security in windows explorer, only the top folder has the Deny set for the AD group, all the files below and in sub folders do not contain the permission for the group. – hoetz Apr 16 '12 at 13:19
  • 1
    It's weird. However using System.Security.AccessControl it work fine: http://pastebin.com/E2usDKts – lorond Apr 16 '12 at 14:53
  • Yes crazy, I just tried dumping all the code from my question and just used DirectorySecurity.ModifyAccessRule and it worked. I will post an answer with my final code soon. – hoetz Apr 16 '12 at 15:10
  • Also is `PropagationFlags.INHERITED_ACE` is correct? Maybe `PropagationFlags.INHERIT_ACE` instead (without -ED)? INHERITED_ACE marks as your ACE inherited from something else, but not to be inherited by childred. Of course if thouse flags named same as microsoft does. – lorond Apr 16 '12 at 15:20