Home All Groups Group Topic Archive Search About

.NET 2.0: SetAccessControl wipe out inherited ACEs

Author
20 Sep 2006 2:49 PM
jzhu
I'd like to update the DACL of a directory on either a local or remote
machine. When I use the UNC directory path (e.g., "\\machine\share\...") on
an XP, SetAccessControl will wipe out the inherited ACEs. If I use a plain
directory path (e.g., "C:\directory\..."), the API works fine.

Has anyone else seen this problem? Any help is appreciated.

(I tried interop with Win32 APIs and has no problem with the UNC directory
path. But I'd rather using the .NET new API. I Also tried WMI to work around
the problem and found out its "ChangeSecurityPermissions" API won't apply
inherited rule at all: When adding a new ACE with container and object
inherit flags set, the API will add the ACE directly (no as "inherited") to
every sub directores or files.)

Here is a sample code to show the problem of SetAccessControl:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;                        // DirectoryInfo
using System.Security.AccessControl;    // DirectorySecurity
using System.Security.Principal;        // IdentityReference

namespace UpdateDaclTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // Test setup:
            // "ATestShare" is declared as a share for a directory "C:\ATestShare".
            // The share's permission is set as "Full Control" to "Everyone".

            // Using the following path will wipe out inherited ACEs from
            // the directory and its sub directories and files.
            string path = @"\\myMachine\ATestShare";

            // Using the following works as expected.
            //string path = @"C:\ATestShare";

            DirectoryInfo info = new DirectoryInfo(path);
            DirectorySecurity security =
info.GetAccessControl(AccessControlSections.All);
            InheritanceFlags flags = InheritanceFlags.ContainerInherit |
InheritanceFlags.ObjectInherit;
            SecurityIdentifier sid = new
SecurityIdentifier(WellKnownSidType.BuiltinBackupOperatorsSid, null);
            security.AddAccessRule(new FileSystemAccessRule(
                sid, FileSystemRights.Modify, flags,
                PropagationFlags.None, AccessControlType.Allow));
            info.SetAccessControl(security);
        }
    }
}

Author
24 Sep 2006 3:21 AM
Joseph Bittman MVP MCSD
Sept. 23, 2006

Hey... you definitely can do this within the new API - your code just
didn't set a certain value....

On your ObjectSecurity object (instance classes are DirectorySecurity and
FileSecurity).... you need to specify the SetAccessRuleProtection method
with whether or not to allow inheritance from parent directories... if you
specify no, then you lose your inheritance... which is your case.

http://msdn2.microsoft.com/en-us/library/system.security.accesscontrol.objectsecurity.setaccessruleprotection.aspx

Basically, it is of this nature:

DirectorySecurity.SetAccessRuleProtection(boolean,boolean)

One of the booleans specifies whether to allow inheritance *in the
future*.... that is, any new changes to the inheritance ACEs, whether or not
they should be accepted.

And the other boolean specifies .... whether to take or erase the current
inheritance settings. So you could say, "I want to get the current
inheritance settings, and keep them, but if they ever change... I never want
to accept the changes".... This is ignored if the other boolean is false.

So:

true,false = do not accept inheritance settings currently... and do not
inherit in the future
true,true = do not accept inheritance in the future, but take the current
inheritance ACEs now
false,false = allow inheritance and future changes
false, true = allow inheritance and future changes

Hope this helps!
--

                       Joseph Bittman
     Microsoft Certified Solution Developer
Microsoft Most Valuable Professional -- DPM

Blog/Web Site: http://CactiDevelopers.ResDev.Net/
Show quoteHide quote
"jzhu" <j***@discussions.microsoft.com> wrote in message
news:958F9D07-C9D1-4B3D-8D44-0865858B84DF@microsoft.com...
> I'd like to update the DACL of a directory on either a local or remote
> machine. When I use the UNC directory path (e.g., "\\machine\share\...")
> on
> an XP, SetAccessControl will wipe out the inherited ACEs. If I use a plain
> directory path (e.g., "C:\directory\..."), the API works fine.
>
> Has anyone else seen this problem? Any help is appreciated.
>
> (I tried interop with Win32 APIs and has no problem with the UNC directory
> path. But I'd rather using the .NET new API. I Also tried WMI to work
> around
> the problem and found out its "ChangeSecurityPermissions" API won't apply
> inherited rule at all: When adding a new ACE with container and object
> inherit flags set, the API will add the ACE directly (no as "inherited")
> to
> every sub directores or files.)
>
> Here is a sample code to show the problem of SetAccessControl:
>
> using System;
> using System.Collections.Generic;
> using System.Text;
> using System.IO; // DirectoryInfo
> using System.Security.AccessControl; // DirectorySecurity
> using System.Security.Principal; // IdentityReference
>
> namespace UpdateDaclTest
> {
> class Program
> {
> static void Main(string[] args)
> {
> // Test setup:
> // "ATestShare" is declared as a share for a directory "C:\ATestShare".
> // The share's permission is set as "Full Control" to "Everyone".
>
> // Using the following path will wipe out inherited ACEs from
> // the directory and its sub directories and files.
> string path = @"\\myMachine\ATestShare";
>
> // Using the following works as expected.
> //string path = @"C:\ATestShare";
>
> DirectoryInfo info = new DirectoryInfo(path);
> DirectorySecurity security =
> info.GetAccessControl(AccessControlSections.All);
> InheritanceFlags flags = InheritanceFlags.ContainerInherit |
> InheritanceFlags.ObjectInherit;
> SecurityIdentifier sid = new
> SecurityIdentifier(WellKnownSidType.BuiltinBackupOperatorsSid, null);
> security.AddAccessRule(new FileSystemAccessRule(
> sid, FileSystemRights.Modify, flags,
> PropagationFlags.None, AccessControlType.Allow));
> info.SetAccessControl(security);
> }
> }
> }
>
>
>
Author
27 Sep 2006 7:24 PM
jzhu
Thanks for your reply, but your answer does not address the problem.

The access rules are not protected in the first place
(AreAccessRulesProtected is false), so you don't need to mess with
SetAccessRuleProtection and inherited rules should flow from the parent. As
my sample shows, the "share" way doesn't work, but the "direct" way works as
expected.

If you use SetAccessRuleProtection(true, true), then you will stop the flow
of rules from parents. The rules are copied, but without the inherited flags
set. That's not what I want to do here.

Just construct a share and use the sample to see the behavior.

Show quoteHide quote
"Joseph Bittman MVP MCSD" wrote:

> Sept. 23, 2006
>
>  Hey... you definitely can do this within the new API - your code just
> didn't set a certain value....
>
> On your ObjectSecurity object (instance classes are DirectorySecurity and
> FileSecurity).... you need to specify the SetAccessRuleProtection method
> with whether or not to allow inheritance from parent directories... if you
> specify no, then you lose your inheritance... which is your case.
>
> http://msdn2.microsoft.com/en-us/library/system.security.accesscontrol.objectsecurity.setaccessruleprotection.aspx
>
> Basically, it is of this nature:
>
> DirectorySecurity.SetAccessRuleProtection(boolean,boolean)
>
> One of the booleans specifies whether to allow inheritance *in the
> future*.... that is, any new changes to the inheritance ACEs, whether or not
> they should be accepted.
>
> And the other boolean specifies .... whether to take or erase the current
> inheritance settings. So you could say, "I want to get the current
> inheritance settings, and keep them, but if they ever change... I never want
> to accept the changes".... This is ignored if the other boolean is false.
>
> So:
>
> true,false = do not accept inheritance settings currently... and do not
> inherit in the future
> true,true = do not accept inheritance in the future, but take the current
> inheritance ACEs now
> false,false = allow inheritance and future changes
> false, true = allow inheritance and future changes
>
> Hope this helps!
> --
>
>                        Joseph Bittman
>      Microsoft Certified Solution Developer
> Microsoft Most Valuable Professional -- DPM
>