//
// 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;
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,
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.");
}
}
}
--- /dev/null
+// 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);
+ }
+ }
+}
+