CommonSecurityDescriptor!
authorJames Bellinger <jfb@zer7.com>
Tue, 3 Jul 2012 22:28:51 +0000 (18:28 -0400)
committerJames Bellinger <jfb@zer7.com>
Sat, 7 Jul 2012 22:45:06 +0000 (18:45 -0400)
mcs/class/corlib/System.Security.AccessControl/CommonSecurityDescriptor.cs
mcs/class/corlib/Test/System.Security.AccessControl/CommonSecurityDescriptorTest.cs [new file with mode: 0644]
mcs/class/corlib/corlib_test.dll.sources

index 636814a4a93ec51f15ad7aa37e2a139410826e40..ce5fb6cb2d83082fdc56f4c615c3b2d04332dff2 100644 (file)
@@ -3,8 +3,10 @@
 //
 // Author:
 //     Dick Porter  <dick@ximian.com>
+//     James Bellinger  <jfb@zer7.com>
 //
 // Copyright (C) 2006 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2012 James Bellinger
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
+using System;
 using System.Security.Principal;
 
-namespace System.Security.AccessControl {
+namespace System.Security.AccessControl
+{
        public sealed class CommonSecurityDescriptor : GenericSecurityDescriptor
        {
                bool isContainer;
@@ -41,17 +45,17 @@ namespace System.Security.AccessControl {
                
                public CommonSecurityDescriptor (bool isContainer, bool isDS, RawSecurityDescriptor rawSecurityDescriptor)
                {
-                       throw new NotImplementedException ();
+                       Init (isContainer, isDS, rawSecurityDescriptor);
                }
                
                public CommonSecurityDescriptor (bool isContainer, bool isDS, string sddlForm)
                {
-                       throw new NotImplementedException ();
+                       Init (isContainer, isDS, new RawSecurityDescriptor (sddlForm));
                }
                
-               public CommonSecurityDescriptor (bool isContainer, bool isDS, byte[] binaryForm, int offset) 
+               public CommonSecurityDescriptor (bool isContainer, bool isDS, byte[] binaryForm, int offset)
                {
-                       throw new NotImplementedException ();
+                       Init (isContainer, isDS, new RawSecurityDescriptor (binaryForm, offset));
                }
                
                public CommonSecurityDescriptor (bool isContainer, bool isDS,
@@ -61,116 +65,153 @@ namespace System.Security.AccessControl {
                                                 SystemAcl systemAcl,
                                                 DiscretionaryAcl discretionaryAcl)
                {
-                       this.isContainer = isContainer;
-                       this.isDS = isDS;
-                       this.flags = flags;
-                       this.owner = owner;
-                       this.group = group;
-                       this.systemAcl = systemAcl;
-                       this.discretionaryAcl = discretionaryAcl;
-                       
-                       throw new NotImplementedException ();
+                       Init (isContainer, isDS, flags, owner, group, systemAcl, discretionaryAcl);
                }
                
-               public override ControlFlags ControlFlags
+               void Init (bool isContainer, bool isDS, RawSecurityDescriptor rawSecurityDescriptor)
                {
-                       get {
-                               return(flags);
-                       }
+                       if (null == rawSecurityDescriptor)
+                               throw new ArgumentNullException ("rawSecurityDescriptor");
+                               
+                       SystemAcl sacl = null;
+                       if (null != rawSecurityDescriptor.SystemAcl)
+                               sacl = new SystemAcl (isContainer, isDS, rawSecurityDescriptor.SystemAcl);
+                               
+                       DiscretionaryAcl dacl = null;
+                       if (null != rawSecurityDescriptor.DiscretionaryAcl)
+                               dacl = new DiscretionaryAcl (isContainer, isDS, rawSecurityDescriptor.DiscretionaryAcl);
+                               
+                       Init (isContainer, isDS,
+                             rawSecurityDescriptor.ControlFlags,
+                             rawSecurityDescriptor.Owner,
+                             rawSecurityDescriptor.Group,
+                             sacl, dacl);
+               }
+               
+               void Init (bool isContainer, bool isDS,
+                          ControlFlags flags,
+                          SecurityIdentifier owner,
+                          SecurityIdentifier group,
+                          SystemAcl systemAcl,
+                          DiscretionaryAcl discretionaryAcl)
+               {
+                       IsContainer = isContainer;
+                       IsDS = isDS;
+                       Owner = owner;
+                       Group = group;
+                       SystemAcl = systemAcl;
+                       DiscretionaryAcl = discretionaryAcl;
+                       
+                       this.flags = flags & ~ControlFlags.SystemAclPresent;
                }
                
-               public DiscretionaryAcl DiscretionaryAcl
-               {
+               public override ControlFlags ControlFlags {
                        get {
-                               return(discretionaryAcl);
+                               ControlFlags realFlags = flags;
+                               
+                               realFlags |= ControlFlags.DiscretionaryAclPresent;
+                               realFlags |= ControlFlags.SelfRelative;
+                               if (SystemAcl != null)
+                                       realFlags |= ControlFlags.SystemAclPresent;
+                                       
+                               return realFlags;
                        }
+               }
+               
+               public DiscretionaryAcl DiscretionaryAcl {
+                       get { return discretionaryAcl; }
                        set {
                                if (value == null) {
-                                       /* FIXME: add a "full access" ACE */
+                                       value = new DiscretionaryAcl (IsContainer, IsDS, 1);
+                                       value.AddAccess (AccessControlType.Allow, new SecurityIdentifier ("WD"), -1,
+                                                       InheritanceFlags.None, PropagationFlags.None);
                                }
                                
+                               CheckAclConsistency (value);
                                discretionaryAcl = value;
                        }
                }
                
-               public override SecurityIdentifier Group
-               {
-                       get {
-                               return(group);
-                       }
-                       set {
-                               group = value;
-                       }
+               public override SecurityIdentifier Group {
+                       get { return group;  }
+                       set { group = value; }
                }
 
-               public bool IsContainer
-               {
-                       get {
-                               return(isContainer);
-                       }
+               public bool IsContainer {
+                       get { return isContainer; }
                }
                
-               public bool IsDiscretionaryAclCanonical
-               {
-                       get {
-                               throw new NotImplementedException ();
-                       }
+               public bool IsDiscretionaryAclCanonical {
+                       get { return DiscretionaryAcl.IsCanonical; }
                }
                
-               public bool IsDS
-               {
-                       get {
-                               return(isDS);
-                       }
+               public bool IsDS {
+                       get { return isDS; }
                }
                
-               public bool IsSystemAclCanonical
-               {
-                       get {
-                               throw new NotImplementedException ();
-                       }
+               public bool IsSystemAclCanonical {
+                       get { return SystemAcl == null || SystemAcl.IsCanonical; }
                }
                
-               public override SecurityIdentifier Owner
-               {
-                       get {
-                               return(owner);
-                       }
-                       set {
-                               owner = value;
-                       }
+               public override SecurityIdentifier Owner {
+                       get { return owner;  }
+                       set { owner = value; }
                }
                
-               public SystemAcl SystemAcl
-               {
-                       get {
-                               return(systemAcl);
-                       }
+               public SystemAcl SystemAcl {
+                       get { return systemAcl;  }
                        set {
+                               if (value != null)
+                                       CheckAclConsistency (value);
+                                       
                                systemAcl = value;
                        }
                }
                
                public void PurgeAccessControl (SecurityIdentifier sid)
                {
-                       throw new NotImplementedException ();
+                       DiscretionaryAcl.Purge (sid);
                }
                
                public void PurgeAudit (SecurityIdentifier sid)
                {
-                       throw new NotImplementedException ();
+                       if (SystemAcl != null)
+                               SystemAcl.Purge (sid);
                }
                
                public void SetDiscretionaryAclProtection (bool isProtected,
                                                           bool preserveInheritance)
                {
-                       throw new NotImplementedException ();
+                       if (!isProtected) {
+                               flags &= ~ControlFlags.DiscretionaryAclProtected;
+                               return;
+                       }
+                       
+                       flags |= ControlFlags.DiscretionaryAclProtected;
+                       if (!preserveInheritance)
+                               DiscretionaryAcl.RemoveInheritedAces ();
                }
                
                public void SetSystemAclProtection (bool isProtected,
                                                    bool preserveInheritance)
                {
-                       throw new NotImplementedException ();
+                       if (!isProtected) {
+                               flags &= ~ControlFlags.SystemAclProtected;
+                               return;
+                       }
+                       
+                       flags |= ControlFlags.SystemAclProtected;
+                       if (!preserveInheritance)
+                               SystemAcl.RemoveInheritedAces ();
+               }
+               
+               void CheckAclConsistency (CommonAcl acl)
+               {
+                       if (IsContainer != acl.IsContainer)
+                               throw new ArgumentExcetion ("IsContainer must match between descriptor and ACL.");
+                       
+                       if (IsDS != acl.IsDS)
+                               throw new ArgumentException ("IsDS must match between descriptor and ACL.");
                }
        }
 }
diff --git a/mcs/class/corlib/Test/System.Security.AccessControl/CommonSecurityDescriptorTest.cs b/mcs/class/corlib/Test/System.Security.AccessControl/CommonSecurityDescriptorTest.cs
new file mode 100644 (file)
index 0000000..d6485ce
--- /dev/null
@@ -0,0 +1,222 @@
+// CommonSecurityDescriptorTest.cs - NUnit Test Cases for CommonSecurityDescriptor
+//
+// Authors:
+//     James Bellinger  <jfb@zer7.com>
+//
+// Copyright (C) 2012 James Bellinger
+
+using System;
+using System.Collections.Generic;
+using System.Security.AccessControl;
+using System.Security.Principal;
+using NUnit.Framework;
+
+namespace MonoTests.System.Security.AccessControl
+{
+       [TestFixture]
+       public class CommonSecurityDescriptorTest
+       {
+               [Test]
+               public void DefaultOwnerAndGroup ()
+               {
+                       CommonSecurityDescriptor csd = new CommonSecurityDescriptor
+                               (false, false, ControlFlags.None, null, null, null, null);
+                       Assert.IsNull (csd.Owner);
+                       Assert.IsNull (csd.Group);
+                       Assert.AreEqual (ControlFlags.DiscretionaryAclPresent
+                                        | ControlFlags.SelfRelative, csd.ControlFlags);
+               }
+
+               [Test, ExpectedException (typeof (ArgumentException))]
+               public void ContainerAndDSConsistencyEnforcedA ()
+               {
+                       SecurityIdentifier userSid = new SecurityIdentifier (WellKnownSidType.LocalSystemSid, null);
+                       SecurityIdentifier groupSid = new SecurityIdentifier (WellKnownSidType.BuiltinAdministratorsSid, null);
+
+                       DiscretionaryAcl dacl = new DiscretionaryAcl (true, true, 0);
+                       new CommonSecurityDescriptor (true, false, ControlFlags.None, userSid, groupSid, null, dacl);
+               }
+
+               [Test, ExpectedException (typeof (ArgumentException))]
+               public void ContainerAndDSConsistencyEnforcedB ()
+               {
+                       SecurityIdentifier userSid = new SecurityIdentifier (WellKnownSidType.LocalSystemSid, null);
+                       SecurityIdentifier groupSid = new SecurityIdentifier (WellKnownSidType.BuiltinAdministratorsSid, null);
+
+                       SystemAcl sacl = new SystemAcl (false, false, 0);
+                       new CommonSecurityDescriptor (true, false, ControlFlags.None, userSid, groupSid, sacl, null);
+               }
+
+               [Test, ExpectedException (typeof (ArgumentException))]
+               public void ContainerAndDSConsistencyEnforcedInSetter ()
+               {
+                       SecurityIdentifier userSid = new SecurityIdentifier (WellKnownSidType.LocalSystemSid, null);
+                       SecurityIdentifier groupSid = new SecurityIdentifier (WellKnownSidType.BuiltinAdministratorsSid, null);
+
+                       CommonSecurityDescriptor csd = new CommonSecurityDescriptor
+                               (true, false, ControlFlags.None, userSid, groupSid, null, null);
+                       csd.DiscretionaryAcl = new DiscretionaryAcl (true, true, 0);
+               }
+
+               [Test]
+               public void DefaultDaclIsAllowEveryoneFullAccess ()
+               {
+                       SecurityIdentifier userSid = new SecurityIdentifier ("SY");
+                       SecurityIdentifier groupSid = new SecurityIdentifier ("BA");
+                       SecurityIdentifier everyoneSid = new SecurityIdentifier ("WD");
+
+                       CommonSecurityDescriptor csd = new CommonSecurityDescriptor
+                               (false, false, ControlFlags.None, userSid, groupSid, null, null);
+
+                       DiscretionaryAcl dacl = csd.DiscretionaryAcl;
+                       Assert.AreEqual (1, dacl.Count);
+
+                       CommonAce ace = (CommonAce)dacl [0];
+                       Assert.AreEqual (-1, ace.AccessMask);
+                       Assert.AreEqual (AceFlags.None, ace.AceFlags);
+                       Assert.AreEqual (AceType.AccessAllowed, ace.AceType);
+                       Assert.AreEqual (20, ace.BinaryLength);
+                       Assert.IsFalse (ace.IsCallback);
+                       Assert.IsFalse (ace.IsInherited);
+                       Assert.AreEqual (0, ace.OpaqueLength);
+                       Assert.AreEqual (ace.SecurityIdentifier, everyoneSid);
+               }
+
+               [Test]
+               public void PurgeDefaultDacl ()
+               {
+                       SecurityIdentifier userSid = new SecurityIdentifier ("SY");
+                       SecurityIdentifier groupSid = new SecurityIdentifier ("BA");
+                       SecurityIdentifier everyoneSid = new SecurityIdentifier ("WD");
+
+                       CommonSecurityDescriptor csd = new CommonSecurityDescriptor
+                               (false, false, ControlFlags.None, userSid, groupSid, null, null);
+
+                       DiscretionaryAcl dacl = csd.DiscretionaryAcl;
+                       Assert.AreEqual (1, dacl.Count);
+
+                       csd.PurgeAccessControl (userSid);
+                       Assert.AreEqual (1, dacl.Count);
+
+                       csd.PurgeAccessControl (everyoneSid);
+                       Assert.AreEqual (0, dacl.Count);
+               }
+
+               [Test]
+               public void PurgeNullSaclWithoutError ()
+               {
+                       SecurityIdentifier userSid = new SecurityIdentifier ("SY");
+                       SecurityIdentifier groupSid = new SecurityIdentifier ("BA");
+
+                       CommonSecurityDescriptor csd = new CommonSecurityDescriptor
+                               (false, false, ControlFlags.None, userSid, groupSid, null, null);
+                       csd.PurgeAudit (userSid);
+                       Assert.IsNull (csd.SystemAcl);
+               }
+
+               [Test]
+               public void OwnerAndGroupAreReferences ()
+               {
+                       SecurityIdentifier userSid = new SecurityIdentifier (WellKnownSidType.LocalSystemSid, null);
+                       SecurityIdentifier groupSid = new SecurityIdentifier (WellKnownSidType.BuiltinAdministratorsSid, null);
+                       CommonSecurityDescriptor csd;
+
+                       csd = new CommonSecurityDescriptor
+                               (false, false, ControlFlags.None, userSid, groupSid, null, null);
+                       Assert.AreSame (groupSid, csd.Group);
+                       Assert.AreSame (userSid, csd.Owner);
+               }
+
+               [Test]
+               public void ProtectionChangesFlags ()
+               {
+                       SecurityIdentifier userSid = new SecurityIdentifier (WellKnownSidType.LocalSystemSid, null);
+                       SecurityIdentifier groupSid = new SecurityIdentifier (WellKnownSidType.BuiltinAdministratorsSid, null);
+                       CommonSecurityDescriptor csd;
+
+                       csd = new CommonSecurityDescriptor
+                               (false, false, ControlFlags.None, userSid, groupSid, null, null);
+                       Assert.AreEqual (ControlFlags.DiscretionaryAclPresent
+                                        | ControlFlags.SelfRelative, csd.ControlFlags);
+
+                       csd.SetDiscretionaryAclProtection (true, false);
+                       Assert.AreEqual (ControlFlags.DiscretionaryAclPresent
+                                        | ControlFlags.DiscretionaryAclProtected
+                                        | ControlFlags.SelfRelative, csd.ControlFlags);
+
+                       csd.SetSystemAclProtection (true, false); // despite not being *present*
+                       Assert.AreEqual (ControlFlags.DiscretionaryAclPresent
+                                        | ControlFlags.DiscretionaryAclProtected
+                                        | ControlFlags.SystemAclProtected
+                                        | ControlFlags.SelfRelative, csd.ControlFlags);
+               }
+
+               [Test]
+               public void DaclPresent ()
+               {
+                       SecurityIdentifier userSid = new SecurityIdentifier (WellKnownSidType.LocalSystemSid, null);
+                       SecurityIdentifier groupSid = new SecurityIdentifier (WellKnownSidType.BuiltinAdministratorsSid, null);
+                       CommonSecurityDescriptor csd;
+
+                       csd = new CommonSecurityDescriptor
+                               (false, false, ControlFlags.None, userSid, groupSid, null, null);
+                       Assert.IsNotNull (csd.DiscretionaryAcl);
+                       Assert.IsTrue (csd.IsDiscretionaryAclCanonical);
+                       Assert.AreEqual (ControlFlags.DiscretionaryAclPresent | ControlFlags.SelfRelative, csd.ControlFlags);
+                       Assert.AreEqual (1, csd.DiscretionaryAcl.Count);
+
+                       csd = new CommonSecurityDescriptor
+                               (false, false, ControlFlags.DiscretionaryAclPresent, userSid, groupSid, null, null);
+
+                       Assert.IsNotNull (csd.DiscretionaryAcl);
+                       Assert.IsTrue (csd.IsDiscretionaryAclCanonical);
+                       Assert.AreEqual (ControlFlags.DiscretionaryAclPresent | ControlFlags.SelfRelative, csd.ControlFlags);
+
+                       DiscretionaryAcl dacl = new DiscretionaryAcl (false, false, 0);
+
+                       csd = new CommonSecurityDescriptor
+                               (false, false, ControlFlags.None, userSid, groupSid, null, dacl);
+                       Assert.AreSame (dacl, csd.DiscretionaryAcl);
+                       Assert.AreEqual (ControlFlags.DiscretionaryAclPresent | ControlFlags.SelfRelative, csd.ControlFlags);
+
+                       csd = new CommonSecurityDescriptor
+                               (false, false, ControlFlags.DiscretionaryAclPresent, userSid, groupSid, null, dacl);
+                       Assert.AreSame (dacl, csd.DiscretionaryAcl);
+                       Assert.AreEqual (ControlFlags.DiscretionaryAclPresent | ControlFlags.SelfRelative, csd.ControlFlags);
+               }
+
+               [Test]
+               public void SaclPresent ()
+               {
+                       SecurityIdentifier userSid = new SecurityIdentifier (WellKnownSidType.LocalSystemSid, null);
+                       SecurityIdentifier groupSid = new SecurityIdentifier (WellKnownSidType.BuiltinAdministratorsSid, null);
+                       SystemAcl sacl = new SystemAcl (false, false, 0);
+                       CommonSecurityDescriptor csd;
+
+                       csd = new CommonSecurityDescriptor
+                               (false, false, ControlFlags.None, userSid, groupSid, null, null);
+                       Assert.IsNull (csd.SystemAcl);
+                       Assert.IsTrue (csd.IsSystemAclCanonical);
+
+                       csd = new CommonSecurityDescriptor
+                               (false, false, ControlFlags.SystemAclPresent, userSid, groupSid, null, null);
+                       Assert.IsNull (csd.SystemAcl);
+                       Assert.IsTrue (csd.IsSystemAclCanonical);
+                       Assert.AreEqual (ControlFlags.DiscretionaryAclPresent | ControlFlags.SelfRelative, csd.ControlFlags);
+
+                       csd = new CommonSecurityDescriptor
+                               (false, false, ControlFlags.None, userSid, groupSid, sacl, null);
+                       Assert.AreSame (sacl, csd.SystemAcl);
+                       Assert.IsTrue (csd.IsSystemAclCanonical);
+                       Assert.AreEqual (0, csd.SystemAcl.Count);
+                       Assert.AreEqual (ControlFlags.DiscretionaryAclPresent
+                                        | ControlFlags.SystemAclPresent
+                                        | ControlFlags.SelfRelative, csd.ControlFlags);
+
+                       csd.SystemAcl = null;
+                       Assert.AreEqual (ControlFlags.DiscretionaryAclPresent
+                                        | ControlFlags.SelfRelative, csd.ControlFlags);
+               }
+       }
+}
+
index 0f9823cf4c04ed092ee9b9820729e340af1fc87c..611e4e60fb3258d82acdd3d24e327979cc0bdf8e 100644 (file)
@@ -207,6 +207,7 @@ System.Security/CodeAccessPermissionTest.cs
 System.Security.AccessControl/AuthorizationRuleTest.cs
 System.Security.AccessControl/CommonAceTest.cs
 System.Security.AccessControl/CommonAclTest.cs
+System.Security.AccessControl/CommonSecurityDescriptorTest.cs
 System.Security.AccessControl/DiscretionaryAclTest.cs
 System.Security.AccessControl/MutexAccessRuleTest.cs
 System.Security.AccessControl/ObjectAceTest.cs