Procházet zdrojové kódy

Implemented SystemAcl. Common shared functionality moved to CommonAcl. Only missing implementation now is RemoveAccess/RemoveAudit.

Unit tests included - for SystemAcl they are based on DiscretionaryAcl's mostly,
with one extra and one somewhat changed since AuditFlags merge together unlike Allow/Deny.

Anyway, it should be practical to implement CommonSecurityDescriptor and friends with these classes working.
James Bellinger před 13 roky
rodič
revize
3a7601b97c

+ 206 - 4
mcs/class/corlib/System.Security.AccessControl/CommonAcl.cs

@@ -241,10 +241,17 @@ namespace System.Security.AccessControl
 			
 			if (aceFlags1 != aceFlags2) {
 				if (accessMask1 != accessMask2) return null;
-				if ((aceFlags1 & ~(AceFlags.ContainerInherit|AceFlags.ObjectInherit)) !=
-				    (aceFlags2 & ~(AceFlags.ContainerInherit|AceFlags.ObjectInherit))) return null;
-				aceFlagsNew = aceFlags1|aceFlags2;
-				accessMaskNew = accessMask1;
+				if ((aceFlags1 & ~(AceFlags.ContainerInherit|AceFlags.ObjectInherit)) ==
+				    (aceFlags2 & ~(AceFlags.ContainerInherit|AceFlags.ObjectInherit))) {
+					aceFlagsNew = aceFlags1|aceFlags2; // merge InheritanceFlags
+					accessMaskNew = accessMask1;
+				} else if ((aceFlags1 & ~(AceFlags.SuccessfulAccess|AceFlags.FailedAccess)) ==
+					   (aceFlags2 & ~(AceFlags.SuccessfulAccess|AceFlags.FailedAccess))) {
+					aceFlagsNew = aceFlags1|aceFlags2; // merge AuditFlags
+					accessMaskNew = accessMask1;
+				} else {
+					return null;
+				}
 			} else {
 				aceFlagsNew = aceFlags1;
 				accessMaskNew = accessMask1|accessMask2;
@@ -315,6 +322,201 @@ namespace System.Security.AccessControl
 				}
 			}
 		}
+		
+		// DiscretionaryAcl/SystemAcl shared implementation below...
+		internal void AddAce (AceQualifier aceQualifier,
+				      SecurityIdentifier sid, int accessMask,
+				      InheritanceFlags inheritanceFlags,
+				      PropagationFlags propagationFlags,
+				      AuditFlags auditFlags)
+		{
+			QualifiedAce ace = AddAceGetQualifiedAce (aceQualifier, sid, accessMask,
+								  inheritanceFlags, propagationFlags, auditFlags);
+			AddAce (ace);
+		}
+		
+		internal void AddAce (AceQualifier aceQualifier,
+				      SecurityIdentifier sid, int accessMask,
+				      InheritanceFlags inheritanceFlags,
+				      PropagationFlags propagationFlags,
+				      AuditFlags auditFlags,
+				      ObjectAceFlags objectFlags,
+				      Guid objectType,
+				      Guid inheritedObjectType)
+		{
+			QualifiedAce ace = AddAceGetQualifiedAce (aceQualifier, sid, accessMask,
+								  inheritanceFlags, propagationFlags, auditFlags,
+								  objectFlags, objectType, inheritedObjectType);
+			AddAce (ace);
+		}
+		
+		QualifiedAce AddAceGetQualifiedAce (AceQualifier aceQualifier,
+						    SecurityIdentifier sid, int accessMask,
+						    InheritanceFlags inheritanceFlags,
+						    PropagationFlags propagationFlags,
+						    AuditFlags auditFlags,
+						    ObjectAceFlags objectFlags,
+						    Guid objectType,
+						    Guid inheritedObjectType)
+		{
+			if (!IsDS)
+				throw new InvalidOperationException ("For this overload, IsDS must be true.");
+				
+			if (ObjectAceFlags.None == objectFlags)
+				return AddAceGetQualifiedAce (aceQualifier, sid, accessMask,
+							      inheritanceFlags, propagationFlags, auditFlags);
+			
+			AceFlags flags = GetAceFlags (inheritanceFlags, propagationFlags, auditFlags);
+			return new ObjectAce (flags, aceQualifier, accessMask, sid,
+					      objectFlags, objectType, inheritedObjectType, false, null);
+		}
+		
+		QualifiedAce AddAceGetQualifiedAce (AceQualifier aceQualifier,
+						    SecurityIdentifier sid, int accessMask,
+						    InheritanceFlags inheritanceFlags,
+						    PropagationFlags propagationFlags,
+						    AuditFlags auditFlags)
+		{
+			AceFlags flags = GetAceFlags (inheritanceFlags, propagationFlags, auditFlags);
+			return new CommonAce (flags, aceQualifier, accessMask, sid, false, null);
+		}
+		
+		void AddAce (QualifiedAce newAce)
+		{
+			RequireCanonicity ();
+				
+			int pos = GetAceInsertPosition (newAce.AceQualifier);
+			raw_acl.InsertAce (pos, newAce);
+			CleanAndRetestCanonicity ();
+		}
+		
+		internal abstract int GetAceInsertPosition (AceQualifier aceQualifier);
+		
+		AceFlags GetAceFlags (InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags auditFlags)
+		{
+			if (InheritanceFlags.None != inheritanceFlags && !IsContainer)
+				throw new ArgumentException ("Flags only work with containers.", "inheritanceFlags");
+			
+			if (InheritanceFlags.None == inheritanceFlags && PropagationFlags.None != propagationFlags)
+				throw new ArgumentException ("Propagation flags need inheritance flags.", "propagationFlags");
+			
+			AceFlags flags = AceFlags.None;
+			if (0 != (InheritanceFlags.ContainerInherit & inheritanceFlags))
+				flags |= AceFlags.ContainerInherit;
+			if (0 != (InheritanceFlags.ObjectInherit & inheritanceFlags))
+				flags |= AceFlags.ObjectInherit;
+			if (0 != (PropagationFlags.InheritOnly & propagationFlags))
+				flags |= AceFlags.InheritOnly;
+			if (0 != (PropagationFlags.NoPropagateInherit & propagationFlags))
+				flags |= AceFlags.NoPropagateInherit;
+			if (0 != (AuditFlags.Success & auditFlags))
+				flags |= AceFlags.SuccessfulAccess;
+			if (0 != (AuditFlags.Failure & auditFlags))
+				flags |= AceFlags.FailedAccess;
+			return flags;
+		}
+		
+		internal void RemoveAceSpecific (AceQualifier aceQualifier,
+						 SecurityIdentifier sid,
+						 int accessMask,
+						 InheritanceFlags inheritanceFlags,
+						 PropagationFlags propagationFlags,
+						 AuditFlags auditFlags)
+		{
+			RequireCanonicity ();
+			RemoveAces<CommonAce> (ace =>
+			{
+				if (ace.AccessMask != accessMask) return false;
+				if (ace.AceQualifier != aceQualifier) return false;
+				if (ace.SecurityIdentifier != sid) return false;
+				if (ace.InheritanceFlags != inheritanceFlags) return false;
+				if (InheritanceFlags.None != inheritanceFlags)
+					if (ace.PropagationFlags != propagationFlags) return false;
+				if (ace.AuditFlags != auditFlags) return false;
+				return true;
+			});
+			CleanAndRetestCanonicity ();
+		}
+		
+		internal void RemoveAceSpecific (AceQualifier aceQualifier,
+						 SecurityIdentifier sid,
+						 int accessMask,
+						 InheritanceFlags inheritanceFlags,
+						 PropagationFlags propagationFlags,
+						 AuditFlags auditFlags,
+						 ObjectAceFlags objectFlags,
+						 Guid objectType,
+						 Guid inheritedObjectType)
+		{
+			if (!IsDS)
+				throw new InvalidOperationException ("For this overload, IsDS must be true.");
+				
+			if (ObjectAceFlags.None == objectFlags) {
+				RemoveAceSpecific (aceQualifier, sid, accessMask, inheritanceFlags, propagationFlags, auditFlags);
+				return;
+			}
+
+			RequireCanonicity ();
+			RemoveAces<ObjectAce> (ace =>
+			{
+				if (ace.AccessMask != accessMask) return false;
+				if (ace.AceQualifier != aceQualifier) return false;
+				if (ace.SecurityIdentifier != sid) return false;
+				if (ace.InheritanceFlags != inheritanceFlags) return false;
+				if (InheritanceFlags.None != inheritanceFlags)
+					if (ace.PropagationFlags != propagationFlags) return false;
+				if (ace.AuditFlags != auditFlags) return false;
+				if (ace.ObjectAceFlags != objectFlags) return false;
+				if (0 != (objectFlags & ObjectAceFlags.ObjectAceTypePresent))
+					if (ace.ObjectAceType != objectType) return false;
+				if (0 != (objectFlags & ObjectAceFlags.InheritedObjectAceTypePresent))
+					if (ace.InheritedObjectAceType != objectType) return false;
+				return true;
+			});
+			CleanAndRetestCanonicity ();
+		}
+		
+		internal void SetAce (AceQualifier aceQualifier,
+				      SecurityIdentifier sid,
+				      int accessMask,
+				      InheritanceFlags inheritanceFlags,
+				      PropagationFlags propagationFlags,
+				      AuditFlags auditFlags)
+		{
+			QualifiedAce ace = AddAceGetQualifiedAce (aceQualifier, sid, accessMask,
+								  inheritanceFlags, propagationFlags, auditFlags);
+			SetAce (ace);
+		}
+		
+		internal void SetAce (AceQualifier aceQualifier,
+				      SecurityIdentifier sid,
+				      int accessMask,
+				      InheritanceFlags inheritanceFlags,
+				      PropagationFlags propagationFlags,
+				      AuditFlags auditFlags,
+				      ObjectAceFlags objectFlags,
+				      Guid objectType,
+				      Guid inheritedObjectType)
+		{
+			QualifiedAce ace = AddAceGetQualifiedAce (aceQualifier, sid, accessMask,
+								  inheritanceFlags, propagationFlags, auditFlags,
+								  objectFlags, objectType, inheritedObjectType);
+			SetAce (ace);
+		}
+		
+		void SetAce (QualifiedAce newAce)
+		{
+			RequireCanonicity ();
+			
+			RemoveAces<QualifiedAce> (oldAce =>
+			{
+				return oldAce.AceQualifier == newAce.AceQualifier &&
+				       oldAce.SecurityIdentifier == newAce.SecurityIdentifier;
+			});
+			CleanAndRetestCanonicity ();
+						
+			AddAce (newAce);
+		}
 	}
 }
 

+ 36 - 142
mcs/class/corlib/System.Security.AccessControl/DiscretionaryAcl.cs

@@ -55,9 +55,8 @@ namespace System.Security.AccessControl
 				       InheritanceFlags inheritanceFlags,
 				       PropagationFlags propagationFlags)
 		{
-			QualifiedAce ace = AddAccessGetQualifiedAce (accessType, sid, accessMask,
-								     inheritanceFlags, propagationFlags);
-			AddAccess (ace);
+			AddAce (GetAceQualifier (accessType), sid, accessMask,
+				inheritanceFlags, propagationFlags, AuditFlags.None);
 		}
 		
 		public void AddAccess (AccessControlType accessType,
@@ -68,54 +67,9 @@ namespace System.Security.AccessControl
 				       Guid objectType,
 				       Guid inheritedObjectType)
 		{
-			QualifiedAce ace = AddAccessGetQualifiedAce (accessType, sid, accessMask,
-								     inheritanceFlags, propagationFlags,
-								     objectFlags, objectType, inheritedObjectType);
-			AddAccess (ace);
-		}
-
-		QualifiedAce AddAccessGetQualifiedAce (AccessControlType accessType,
-						       SecurityIdentifier sid, int accessMask,
-						       InheritanceFlags inheritanceFlags,
-						       PropagationFlags propagationFlags,
-						       ObjectAceFlags objectFlags,
-						       Guid objectType,
-						       Guid inheritedObjectType)
-		{
-			if (!IsDS)
-				throw new InvalidOperationException ("For this overload, IsDS must be true.");
-				
-			if (ObjectAceFlags.None == objectFlags)
-				return AddAccessGetQualifiedAce (accessType, sid, accessMask, inheritanceFlags, propagationFlags);
-			
-			AceQualifier qualifier = GetAceQualifier (accessType);
-			AceFlags flags = GetAceFlags (inheritanceFlags, propagationFlags);
-			return new ObjectAce (flags, qualifier, accessMask, sid,
-					      objectFlags, objectType, inheritedObjectType, false, null);
-		}
-		
-		QualifiedAce AddAccessGetQualifiedAce (AccessControlType accessType,
-						       SecurityIdentifier sid, int accessMask,
-						       InheritanceFlags inheritanceFlags,
-						       PropagationFlags propagationFlags)
-		{
-			AceQualifier qualifier = GetAceQualifier (accessType);
-			AceFlags flags = GetAceFlags (inheritanceFlags, propagationFlags);
-			return new CommonAce (flags, qualifier, accessMask, sid, false, null);
-		}
-		
-		void AddAccess (QualifiedAce newAce)
-		{
-			RequireCanonicity ();
-				
-			int pos; // Canonical order is explicit deny, explicit allow, inherited.
-			if (AceQualifier.AccessAllowed == newAce.AceQualifier)
-				pos = GetCanonicalExplicitDenyAceCount ();
-			else
-				pos = 0;
-			
-			raw_acl.InsertAce (pos, newAce);
-			CleanAndRetestCanonicity ();
+			AddAce (GetAceQualifier (accessType), sid, accessMask,
+				inheritanceFlags, propagationFlags, AuditFlags.None,
+				objectFlags, objectType, inheritedObjectType);
 		}
 		
 		public bool RemoveAccess (AccessControlType accessType,
@@ -145,19 +99,8 @@ namespace System.Security.AccessControl
 						  InheritanceFlags inheritanceFlags,
 						  PropagationFlags propagationFlags)
 		{
-			RequireCanonicity ();
-			AceQualifier qualifier = GetAceQualifier (accessType);
-			RemoveAces<CommonAce> (ace =>
-			{
-				if (ace.AccessMask != accessMask) return false;
-				if (ace.AceQualifier != qualifier) return false;
-				if (ace.SecurityIdentifier != sid) return false;
-				if (ace.InheritanceFlags != inheritanceFlags) return false;
-				if (InheritanceFlags.None != inheritanceFlags)
-					if (ace.PropagationFlags != propagationFlags) return false;
-				return true;
-			});
-			CleanAndRetestCanonicity ();
+			RemoveAceSpecific (GetAceQualifier (accessType), sid, accessMask,
+					   inheritanceFlags, propagationFlags, AuditFlags.None);
 		}
 		
 		public void RemoveAccessSpecific (AccessControlType accessType,
@@ -169,32 +112,9 @@ namespace System.Security.AccessControl
 						  Guid objectType,
 						  Guid inheritedObjectType)
 		{
-			if (!IsDS)
-				throw new InvalidOperationException ("For this overload, IsDS must be true.");
-				
-			if (ObjectAceFlags.None == objectFlags) {
-				RemoveAccessSpecific (accessType, sid, accessMask, inheritanceFlags, propagationFlags);
-				return;
-			}
-
-			RequireCanonicity ();
-			AceQualifier qualifier = GetAceQualifier (accessType);
-			RemoveAces<ObjectAce> (ace =>
-			{
-				if (ace.AccessMask != accessMask) return false;
-				if (ace.AceQualifier != qualifier) return false;
-				if (ace.SecurityIdentifier != sid) return false;
-				if (ace.InheritanceFlags != inheritanceFlags) return false;
-				if (InheritanceFlags.None != inheritanceFlags)
-					if (ace.PropagationFlags != propagationFlags) return false;
-				if (ace.ObjectAceFlags != objectFlags) return false;
-				if (0 != (objectFlags & ObjectAceFlags.ObjectAceTypePresent))
-					if (ace.ObjectAceType != objectType) return false;
-				if (0 != (objectFlags & ObjectAceFlags.InheritedObjectAceTypePresent))
-					if (ace.InheritedObjectAceType != objectType) return false;
-				return true;
-			});
-			CleanAndRetestCanonicity ();
+			RemoveAceSpecific (GetAceQualifier (accessType), sid, accessMask,
+					   inheritanceFlags, propagationFlags, AuditFlags.None,
+					   objectFlags, objectType, inheritedObjectType);
 		}
 		
 		public void SetAccess (AccessControlType accessType,
@@ -203,9 +123,8 @@ namespace System.Security.AccessControl
 				       InheritanceFlags inheritanceFlags,
 				       PropagationFlags propagationFlags)
 		{
-			QualifiedAce ace = AddAccessGetQualifiedAce (accessType, sid, accessMask,
-								     inheritanceFlags, propagationFlags);
-			SetAccess (ace);
+			SetAce (GetAceQualifier (accessType), sid, accessMask,
+				inheritanceFlags, propagationFlags, AuditFlags.None);
 		}
 		
 		public void SetAccess (AccessControlType accessType,
@@ -217,26 +136,11 @@ namespace System.Security.AccessControl
 				       Guid objectType,
 				       Guid inheritedObjectType)
 		{
-			QualifiedAce ace = AddAccessGetQualifiedAce (accessType, sid, accessMask,
-								     inheritanceFlags, propagationFlags,
-								     objectFlags, objectType, inheritedObjectType);
-			SetAccess (ace);
-		}
-
-		void SetAccess (QualifiedAce newAce)
-		{
-			RequireCanonicity ();
-			
-			RemoveAces<QualifiedAce> (oldAce =>
-			{
-				return oldAce.AceQualifier == newAce.AceQualifier &&
-				       oldAce.SecurityIdentifier == newAce.SecurityIdentifier;
-			});
-			CleanAndRetestCanonicity ();
-						
-			AddAccess (newAce);
+			SetAce (GetAceQualifier (accessType), sid, accessMask,
+				inheritanceFlags, propagationFlags, AuditFlags.None,
+				objectFlags, objectType, inheritedObjectType);
 		}
-
+		
 		internal override void ApplyCanonicalSortToExplicitAces ()
 		{
 			int explicitCount = GetCanonicalExplicitAceCount ();
@@ -246,37 +150,13 @@ namespace System.Security.AccessControl
 			ApplyCanonicalSortToExplicitAces (explicitDenys, explicitCount - explicitDenys);
 		}
 		
-		internal override bool IsAceMeaningless (GenericAce ace)
+		internal override int GetAceInsertPosition (AceQualifier aceQualifier)
 		{
-			if (base.IsAceMeaningless (ace)) return true;
-			
-			QualifiedAce qace = ace as QualifiedAce;
-			if (null != qace) {
-				return !(AceQualifier.AccessAllowed == qace.AceQualifier ||
-				         AceQualifier.AccessDenied  == qace.AceQualifier);
-			}
-
-			return false;
-		}
-		
-		AceFlags GetAceFlags (InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
-		{
-			if (InheritanceFlags.None != inheritanceFlags && !IsContainer)
-				throw new ArgumentException ("Flags only work with containers.", "inheritanceFlags");
-			
-			if (InheritanceFlags.None == inheritanceFlags && PropagationFlags.None != propagationFlags)
-				throw new ArgumentException ("Propagation flags need inheritance flags.", "propagationFlags");
-			
-			AceFlags flags = AceFlags.None;
-			if (0 != ((InheritanceFlags.ContainerInherit) & inheritanceFlags))
-				flags |= AceFlags.ContainerInherit;
-			if (0 != ((InheritanceFlags.ObjectInherit) & inheritanceFlags))
-				flags |= AceFlags.ObjectInherit;
-			if (0 != ((PropagationFlags.InheritOnly) & propagationFlags))
-				flags |= AceFlags.InheritOnly;
-			if (0 != ((PropagationFlags.NoPropagateInherit) & propagationFlags))
-				flags |= AceFlags.NoPropagateInherit;
-			return flags;
+			// Canonical order for DACLs is explicit deny, explicit allow, inherited.
+			if (AceQualifier.AccessAllowed == aceQualifier)
+				return GetCanonicalExplicitDenyAceCount ();
+			else
+				return 0;
 		}
 		
 		static AceQualifier GetAceQualifier (AccessControlType accessType)
@@ -288,6 +168,20 @@ namespace System.Security.AccessControl
 			else
 				throw new ArgumentOutOfRangeException ("accessType");
 		}
+		
+		internal override bool IsAceMeaningless (GenericAce ace)
+		{
+			if (base.IsAceMeaningless (ace)) return true;
+			if (AuditFlags.None != ace.AuditFlags) return true;
+			
+			QualifiedAce qace = ace as QualifiedAce;
+			if (null != qace) {
+				if (!(AceQualifier.AccessAllowed == qace.AceQualifier ||
+				      AceQualifier.AccessDenied  == qace.AceQualifier)) return true;
+			}
+
+			return false;
+		}
 	}
 }
 

+ 33 - 10
mcs/class/corlib/System.Security.AccessControl/SystemAcl.cs

@@ -4,8 +4,10 @@
 // Authors:
 //	Dick Porter  <[email protected]>
 //	Atsushi Enomoto  <[email protected]>
+//	James Bellinger  <[email protected]>
 //
 // Copyright (C) 2006-2007 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
@@ -53,8 +55,8 @@ namespace System.Security.AccessControl
 				      InheritanceFlags inheritanceFlags,
 				      PropagationFlags propagationFlags)
 		{
-			// CommonAce?
-			throw new NotImplementedException ();
+			AddAce (AceQualifier.SystemAudit, sid, accessMask,
+				inheritanceFlags, propagationFlags, auditFlags);
 		}
 		
 		public void AddAudit (AuditFlags auditFlags,
@@ -65,8 +67,9 @@ namespace System.Security.AccessControl
 				      Guid objectType,
 				      Guid inheritedObjectType)
 		{
-			// ObjectAce?
-			throw new NotImplementedException ();
+			AddAce (AceQualifier.SystemAudit, sid, accessMask,
+				inheritanceFlags, propagationFlags, auditFlags,
+				objectFlags, objectType, inheritedObjectType);
 		}
 		
 		public bool RemoveAudit (AuditFlags auditFlags,
@@ -96,7 +99,9 @@ namespace System.Security.AccessControl
 						 InheritanceFlags inheritanceFlags,
 						 PropagationFlags propagationFlags)
 		{
-			throw new NotImplementedException ();
+			RemoveAceSpecific (AceQualifier.SystemAudit, sid, accessMask,
+					   inheritanceFlags, propagationFlags, auditFlags);
+
 		}
 		
 		public void RemoveAuditSpecific (AuditFlags auditFlags,
@@ -108,7 +113,10 @@ namespace System.Security.AccessControl
 						 Guid objectType,
 						 Guid inheritedObjectType)
 		{
-			throw new NotImplementedException ();
+			RemoveAceSpecific (AceQualifier.SystemAudit, sid, accessMask,
+					   inheritanceFlags, propagationFlags, auditFlags,
+					   objectFlags, objectType, inheritedObjectType);
+
 		}
 		
 		public void SetAudit (AuditFlags auditFlags,
@@ -117,7 +125,8 @@ namespace System.Security.AccessControl
 				      InheritanceFlags inheritanceFlags,
 				      PropagationFlags propagationFlags)
 		{
-			throw new NotImplementedException ();
+			SetAce (AceQualifier.SystemAudit, sid, accessMask,
+				inheritanceFlags, propagationFlags, auditFlags);
 		}
 		
 		public void SetAudit (AuditFlags auditFlags,
@@ -129,7 +138,9 @@ namespace System.Security.AccessControl
 				      Guid objectType,
 				      Guid inheritedObjectType)
 		{
-			throw new NotImplementedException ();
+			SetAce (AceQualifier.SystemAudit, sid, accessMask,
+				inheritanceFlags, propagationFlags, auditFlags,
+				objectFlags, objectType, inheritedObjectType);
 		}
 		
 		internal override void ApplyCanonicalSortToExplicitAces ()
@@ -138,18 +149,30 @@ namespace System.Security.AccessControl
 			ApplyCanonicalSortToExplicitAces (0, explicitCount);
 		}
 		
+		internal override int GetAceInsertPosition (AceQualifier aceQualifier)
+		{
+			return 0;
+		}
+		
 		internal override bool IsAceMeaningless (GenericAce ace)
 		{
 			if (base.IsAceMeaningless (ace)) return true;
+			if (!IsValidAuditFlags (ace.AuditFlags)) return true;
 			
 			QualifiedAce qace = ace as QualifiedAce;
 			if (null != qace) {
-				return !(AceQualifier.SystemAudit == qace.AceQualifier ||
-				         AceQualifier.SystemAlarm == qace.AceQualifier);
+				if (!(AceQualifier.SystemAudit == qace.AceQualifier ||
+				      AceQualifier.SystemAlarm == qace.AceQualifier)) return true;
 			}
 			
 			return false;
 		}
+		
+		static bool IsValidAuditFlags (AuditFlags auditFlags)
+		{
+			return auditFlags != AuditFlags.None &&
+			       auditFlags == ((AuditFlags.Success|AuditFlags.Failure) & auditFlags);
+		}
 	}
 }
 

+ 182 - 0
mcs/class/corlib/Test/System.Security.AccessControl/SystemAclTest.cs

@@ -0,0 +1,182 @@
+// SystemAclTest.cs - NUnit Test Cases for SystemAcl
+//
+// Authors:
+//	James Bellinger  <[email protected]>
+//
+// 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 SystemAclTest
+	{
+		[Test]
+		public void StartsEmpty ()
+		{
+			Assert.AreEqual (0, new SystemAcl (false, false, 0).Count);
+			//Assert.AreEqual (0, new SystemAcl (false, false, null).Count);
+			// ^ MS.NET has a bug here and throws, contrary to their own documentation.
+		}
+
+		[Test]
+		public void AddAuditMergesFlags ()
+		{
+			SecurityIdentifier sid = new SecurityIdentifier ("BA");
+			SystemAcl sacl = new SystemAcl (false, false, 0);
+
+			sacl.AddAudit (AuditFlags.Success, sid, 1, InheritanceFlags.None, PropagationFlags.None);
+			sacl.AddAudit (AuditFlags.Failure, sid, 1, InheritanceFlags.None, PropagationFlags.None);
+			Assert.AreEqual (1, sacl.Count);
+
+			CommonAce ace = (CommonAce)sacl [0];
+			Assert.AreEqual (AuditFlags.Success|AuditFlags.Failure, ace.AuditFlags);
+		}
+
+		[Test]
+		public void AddAuditCommonAce ()
+		{
+			SecurityIdentifier sid = new SecurityIdentifier ("BA");
+			SystemAcl sacl = new SystemAcl (false, false, 0);
+
+			sacl.AddAudit (AuditFlags.Success, sid, 1, InheritanceFlags.None, PropagationFlags.None);
+			Assert.AreEqual (1, sacl.Count);
+
+			CommonAce ace = (CommonAce)sacl [0];
+			Assert.AreEqual (AuditFlags.Success, ace.AuditFlags);
+			Assert.AreEqual (1, ace.AccessMask);
+			Assert.AreEqual ("S-1-5-32-544", ace.SecurityIdentifier.Value);
+			Assert.IsFalse (ace.IsInherited);
+		}
+
+		[Test]
+		public void AddAuditCommonAceUsingDSOverload ()
+		{
+			SecurityIdentifier sid = new SecurityIdentifier ("BA");
+			SystemAcl sacl = new SystemAcl (false, true, 0);
+
+			sacl.AddAudit (AuditFlags.Failure, sid, 1, InheritanceFlags.None, PropagationFlags.None,
+			               ObjectAceFlags.None, Guid.NewGuid (), Guid.NewGuid ());
+			Assert.AreEqual (1, sacl.Count);
+
+			CommonAce ace = (CommonAce)sacl [0];
+			Assert.AreEqual (AuditFlags.Failure, ace.AuditFlags);
+			Assert.AreEqual (1, ace.AccessMask);
+			Assert.AreEqual ("S-1-5-32-544", ace.SecurityIdentifier.Value);
+			Assert.IsFalse (ace.IsInherited);
+		}
+
+		[Test]
+		public void AddAuditObjectAceAndCommonAce ()
+		{
+			SecurityIdentifier sid = new SecurityIdentifier ("BA");
+			SystemAcl sacl = new SystemAcl (false, true, 0);
+
+			sacl.AddAudit (AuditFlags.Success, sid, 1, InheritanceFlags.None, PropagationFlags.None,
+			               ObjectAceFlags.ObjectAceTypePresent, Guid.NewGuid (), Guid.Empty);
+			sacl.AddAudit (AuditFlags.Success, sid, 1, InheritanceFlags.None, PropagationFlags.None,
+				       ObjectAceFlags.None, Guid.Empty, Guid.Empty);
+			Assert.AreEqual (2, sacl.Count);
+
+			CommonAce cace = (CommonAce)sacl [0];
+			Assert.AreEqual (1, cace.AccessMask);
+			Assert.AreEqual ("S-1-5-32-544", cace.SecurityIdentifier.Value);
+			Assert.IsFalse (cace.IsCallback);
+			Assert.IsFalse (cace.IsInherited);
+
+			ObjectAce oace = (ObjectAce)sacl [1];
+			Assert.AreEqual (1, oace.AccessMask);
+			Assert.AreEqual ("S-1-5-32-544", oace.SecurityIdentifier.Value);
+			Assert.IsFalse (oace.IsCallback);
+			Assert.IsFalse (oace.IsInherited);
+
+			sacl.AddAudit (AuditFlags.Success, sid, 2, InheritanceFlags.None, PropagationFlags.None,
+				       ObjectAceFlags.None, Guid.Empty, Guid.Empty);
+			Assert.AreEqual (2, sacl.Count);
+
+			CommonAce cace2 = (CommonAce)sacl [0];
+			Assert.AreEqual (3, cace2.AccessMask);
+		}
+
+		[Test]
+		public void RemoveSpecific ()
+		{
+			SecurityIdentifier sid = new SecurityIdentifier ("BA");
+			SystemAcl sacl = new SystemAcl (false, false, 0);
+
+			RemoveSpecificBegin (sid, sacl, InheritanceFlags.None);
+			sacl.RemoveAuditSpecific (AuditFlags.Success, sid, 3, InheritanceFlags.None, PropagationFlags.None);
+			Assert.AreEqual (0, sacl.Count);
+		}
+
+		[Test]
+		public void RemoveSpecificUsingDSOverload ()
+		{
+			SecurityIdentifier sid = new SecurityIdentifier ("BA");
+			SystemAcl sacl = new SystemAcl (false, true, 0);
+
+			RemoveSpecificBegin (sid, sacl, InheritanceFlags.None);
+			sacl.RemoveAuditSpecific (AuditFlags.Success, sid, 3, InheritanceFlags.None, PropagationFlags.None,
+			                          ObjectAceFlags.ObjectAceTypePresent, Guid.Empty, Guid.Empty);
+			Assert.AreEqual (1, sacl.Count);
+			sacl.RemoveAuditSpecific (AuditFlags.Success, sid, 3, InheritanceFlags.None, PropagationFlags.None,
+			                          ObjectAceFlags.None, Guid.Empty, Guid.Empty);
+			Assert.AreEqual (0, sacl.Count);
+		}
+
+		void RemoveSpecificBegin (SecurityIdentifier sid, SystemAcl sacl, InheritanceFlags inheritanceFlags)
+		{
+			SecurityIdentifier otherSid = new SecurityIdentifier ("BU");
+
+			sacl.AddAudit (AuditFlags.Success, sid, 3, inheritanceFlags, PropagationFlags.None);
+			Assert.AreEqual (1, sacl.Count);
+			sacl.RemoveAuditSpecific (AuditFlags.Failure, sid, 1, inheritanceFlags, PropagationFlags.None);
+			Assert.AreEqual (1, sacl.Count);
+			sacl.RemoveAuditSpecific (AuditFlags.Success, otherSid, 1, inheritanceFlags, PropagationFlags.None);
+			Assert.AreEqual (1, sacl.Count);
+			sacl.RemoveAuditSpecific (AuditFlags.Success, sid, 1, inheritanceFlags, PropagationFlags.None);
+			Assert.AreEqual (1, sacl.Count);
+			Assert.AreEqual (3, ((CommonAce)sacl [0]).AccessMask);
+			sacl.RemoveAuditSpecific (AuditFlags.Success, sid, 3,
+			                          inheritanceFlags ^ InheritanceFlags.ContainerInherit,
+			                          PropagationFlags.None);
+			Assert.AreEqual (1, sacl.Count);
+		}
+
+		[Test]
+		public void SetAudit ()
+		{
+			SecurityIdentifier adminSid = new SecurityIdentifier ("BA"); // S-1-5-32-544
+			SecurityIdentifier userSid = new SecurityIdentifier ("BU"); // S-1-5-32-545
+
+			SystemAcl sacl = new SystemAcl (true, false, 0);
+			sacl.SetAudit (AuditFlags.Success, adminSid, 1, InheritanceFlags.ObjectInherit, PropagationFlags.None);
+			sacl.SetAudit (AuditFlags.Success, userSid, 2, InheritanceFlags.None, PropagationFlags.None);
+			Assert.AreEqual (2, sacl.Count);
+
+			CommonAce ace = (CommonAce)sacl [0];
+			Assert.AreEqual (adminSid, ace.SecurityIdentifier);
+			Assert.AreEqual (1, ace.AccessMask);
+
+			sacl.SetAudit (AuditFlags.Success, adminSid, 4, InheritanceFlags.ObjectInherit, PropagationFlags.None);
+			Assert.AreNotEqual (4, ace.AccessMask);
+			ace = (CommonAce)sacl [0];
+			Assert.AreEqual (4, ace.AccessMask);
+
+			sacl.SetAudit (AuditFlags.Failure, adminSid, 4, InheritanceFlags.ObjectInherit, PropagationFlags.None);
+			Assert.AreEqual (2, sacl.Count);
+			ace = (CommonAce)sacl [0];
+			Assert.AreEqual (AuditFlags.Failure, ace.AuditFlags);
+			Assert.AreEqual (adminSid, ace.SecurityIdentifier);
+			ace = (CommonAce)sacl [1];
+			Assert.AreEqual (AuditFlags.Success, ace.AuditFlags);
+			Assert.AreEqual (userSid, ace.SecurityIdentifier);
+		}
+	}
+}
+

+ 1 - 0
mcs/class/corlib/corlib_test.dll.sources

@@ -213,6 +213,7 @@ System.Security.AccessControl/ObjectAceTest.cs
 System.Security.AccessControl/ObjectSecurity_TTest.cs
 System.Security.AccessControl/RawAclTest.cs
 System.Security.AccessControl/RawSecurityDescriptorTest.cs
+System.Security.AccessControl/SystemAclTest.cs
 System.Security.Cryptography/AllTests2.cs
 System.Security.Cryptography/AsymmetricAlgorithmTest.cs
 System.Security.Cryptography/CipherModeTest.cs