1 // DiscretionaryAclTest.cs - NUnit Test Cases for DiscretionaryAcl
2 //
3 // Authors:
4 //	James Bellinger  <jfb@zer7.com>
5 //
6 // Copyright (C) 2012 James Bellinger
7 
8 using System;
9 using System.Collections.Generic;
10 using System.Security.AccessControl;
11 using System.Security.Principal;
12 using NUnit.Framework;
13 
14 namespace MonoTests.System.Security.AccessControl
15 {
16 	[TestFixture]
17 	public class DiscretionaryAclTest
18 	{
19 		[Test]
StartsEmpty()20 		public void StartsEmpty ()
21 		{
22 			Assert.AreEqual (0, new DiscretionaryAcl (false, false, 0).Count);
23 			Assert.AreEqual (0, new DiscretionaryAcl (false, false, null).Count);
24 
25 		}
26 
27 		[Test]
AddAccessCommonAce()28 		public void AddAccessCommonAce ()
29 		{
30 			SecurityIdentifier sid = new SecurityIdentifier ("BA");
31 			DiscretionaryAcl dacl = new DiscretionaryAcl (false, false, 0);
32 
33 			dacl.AddAccess (AccessControlType.Allow, sid, 1, InheritanceFlags.None, PropagationFlags.None);
34 			Assert.AreEqual (1, dacl.Count);
35 
36 			CommonAce ace = (CommonAce)dacl[0];
37 			Assert.AreEqual (1, ace.AccessMask);
38 			Assert.AreEqual ("S-1-5-32-544", ace.SecurityIdentifier.Value);
39 			Assert.IsFalse (ace.IsInherited);
40 		}
41 
42 		[Test]
AddAccessCommonAceUsingDSOverload()43 		public void AddAccessCommonAceUsingDSOverload ()
44 		{
45 			SecurityIdentifier sid = new SecurityIdentifier ("BA");
46 			DiscretionaryAcl dacl = new DiscretionaryAcl (false, true, 0);
47 
48 			dacl.AddAccess (AccessControlType.Allow, sid, 1, InheritanceFlags.None, PropagationFlags.None,
49 			                ObjectAceFlags.None, Guid.NewGuid (), Guid.NewGuid ());
50 			Assert.AreEqual (1, dacl.Count);
51 
52 			CommonAce ace = (CommonAce)dacl [0];
53 			Assert.AreEqual (1, ace.AccessMask);
54 			Assert.AreEqual ("S-1-5-32-544", ace.SecurityIdentifier.Value);
55 			Assert.IsFalse (ace.IsInherited);
56 		}
57 
58 		[Test, ExpectedException (typeof (InvalidOperationException))]
AddAccessObjectAceNonDSFailsEvenIfObjectAceFlagsNoneImplyingCommonAce()59 		public void AddAccessObjectAceNonDSFailsEvenIfObjectAceFlagsNoneImplyingCommonAce ()
60 		{
61 			SecurityIdentifier sid = new SecurityIdentifier ("BA");
62 			DiscretionaryAcl dacl = new DiscretionaryAcl (false, false, 0);
63 
64 			dacl.AddAccess (AccessControlType.Allow, sid, 1, InheritanceFlags.None, PropagationFlags.None,
65 			                ObjectAceFlags.None, Guid.Empty, Guid.Empty);
66 		}
67 
68 		[Test, ExpectedException (typeof (InvalidOperationException))]
AddAccessFailsOnNonCanonical()69 		public void AddAccessFailsOnNonCanonical ()
70 		{
71 			SecurityIdentifier sid = new SecurityIdentifier ("BU");
72 
73 			RawAcl acl = new RawAcl (RawAcl.AclRevision, 0);
74 			acl.InsertAce (0, new CommonAce (AceFlags.None, AceQualifier.AccessAllowed, 1, sid, false, null));
75 			acl.InsertAce (1, new CommonAce (AceFlags.None, AceQualifier.AccessDenied, 1, sid, false, null));
76 
77 			DiscretionaryAcl dacl = new DiscretionaryAcl (false, false, acl);
78 			Assert.IsFalse (dacl.IsCanonical);
79 			Assert.AreEqual (2, dacl.Count);
80 
81 			dacl.AddAccess (AccessControlType.Allow, sid, 1, InheritanceFlags.None, PropagationFlags.None);
82 		}
83 
84 		[Test, ExpectedException (typeof (ArgumentException))]
InheritanceFlagsRequireContainer()85 		public void InheritanceFlagsRequireContainer ()
86 		{
87 			SecurityIdentifier sid = new SecurityIdentifier ("BU");
88 			DiscretionaryAcl dacl = new DiscretionaryAcl (false, false, 0);
89 			dacl.AddAccess (AccessControlType.Allow, sid, 3, InheritanceFlags.ContainerInherit, PropagationFlags.None);
90 		}
91 
92 		[Test, ExpectedException (typeof (ArgumentException))]
PropagationFlagsRequireInheritanceFlagsForAdd()93 		public void PropagationFlagsRequireInheritanceFlagsForAdd ()
94 		{
95 			SecurityIdentifier sid = new SecurityIdentifier ("BU");
96 			DiscretionaryAcl dacl = new DiscretionaryAcl (true, false, 0);
97 			dacl.AddAccess (AccessControlType.Allow, sid, 3, InheritanceFlags.None, PropagationFlags.InheritOnly);
98 		}
99 
100 		[Test]
AddAccessObjectAceAndCommonAce()101 		public void AddAccessObjectAceAndCommonAce ()
102 		{
103 			SecurityIdentifier sid = new SecurityIdentifier ("BA");
104 			DiscretionaryAcl dacl = new DiscretionaryAcl (false, true, 0);
105 
106 			dacl.AddAccess (AccessControlType.Allow, sid, 1, InheritanceFlags.None, PropagationFlags.None,
107 			                ObjectAceFlags.ObjectAceTypePresent, Guid.NewGuid (), Guid.Empty);
108 			dacl.AddAccess (AccessControlType.Allow, sid, 1, InheritanceFlags.None, PropagationFlags.None,
109 					ObjectAceFlags.None, Guid.Empty, Guid.Empty);
110 			Assert.AreEqual (2, dacl.Count);
111 
112 			CommonAce cace = (CommonAce)dacl [0];
113 			Assert.AreEqual (1, cace.AccessMask);
114 			Assert.AreEqual ("S-1-5-32-544", cace.SecurityIdentifier.Value);
115 			Assert.IsFalse (cace.IsCallback);
116 			Assert.IsFalse (cace.IsInherited);
117 
118 			ObjectAce oace = (ObjectAce)dacl [1];
119 			Assert.AreEqual (1, oace.AccessMask);
120 			Assert.AreEqual ("S-1-5-32-544", oace.SecurityIdentifier.Value);
121 			Assert.IsFalse (oace.IsCallback);
122 			Assert.IsFalse (oace.IsInherited);
123 
124 			dacl.AddAccess (AccessControlType.Allow, sid, 2, InheritanceFlags.None, PropagationFlags.None,
125 					ObjectAceFlags.None, Guid.Empty, Guid.Empty);
126 			Assert.AreEqual (2, dacl.Count);
127 
128 			CommonAce cace2 = (CommonAce)dacl [0];
129 			Assert.AreEqual (3, cace2.AccessMask);
130 		}
131 
132 		[Test, ExpectedException (typeof (ArgumentOutOfRangeException))]
InvalidAccessControlType()133 		public void InvalidAccessControlType ()
134 		{
135 			// This is also testing the fact that the AccessControlType is checked before the
136 			// InheritanceFlags are validated -- IsContainer is false here, so if the InheritanceFlags
137 			// were checked first, ArgumentException would be thrown instead.
138 			SecurityIdentifier sid = new SecurityIdentifier ("BA");
139 			DiscretionaryAcl dacl = new DiscretionaryAcl (false, false, 0);
140 			dacl.AddAccess ((AccessControlType)43210, sid, 1, InheritanceFlags.ContainerInherit, PropagationFlags.None);
141 		}
142 
143 		[Test]
RemoveSpecific()144 		public void RemoveSpecific ()
145 		{
146 			SecurityIdentifier sid = new SecurityIdentifier ("BA");
147 			DiscretionaryAcl dacl = new DiscretionaryAcl (false, false, 0);
148 
149 			RemoveSpecificBegin (sid, dacl, InheritanceFlags.None);
150 			dacl.RemoveAccessSpecific (AccessControlType.Allow, sid, 3, InheritanceFlags.None, PropagationFlags.None);
151 			Assert.AreEqual (0, dacl.Count);
152 		}
153 
154 		[Test]
RemoveSpecificUsingDSOverload()155 		public void RemoveSpecificUsingDSOverload ()
156 		{
157 			SecurityIdentifier sid = new SecurityIdentifier ("BA");
158 			DiscretionaryAcl dacl = new DiscretionaryAcl (false, true, 0);
159 
160 			RemoveSpecificBegin (sid, dacl, InheritanceFlags.None);
161 			dacl.RemoveAccessSpecific (AccessControlType.Allow, sid, 3, InheritanceFlags.None, PropagationFlags.None,
162 			                           ObjectAceFlags.ObjectAceTypePresent, Guid.Empty, Guid.Empty);
163 			Assert.AreEqual (1, dacl.Count);
164 			dacl.RemoveAccessSpecific (AccessControlType.Allow, sid, 3, InheritanceFlags.None, PropagationFlags.None,
165 			                           ObjectAceFlags.None, Guid.Empty, Guid.Empty);
166 			Assert.AreEqual (0, dacl.Count);
167 		}
168 
169 		[Test]
RemoveSpecificIsContainer()170 		public void RemoveSpecificIsContainer ()
171 		{
172 			SecurityIdentifier sid = new SecurityIdentifier ("BA");
173 			DiscretionaryAcl dacl = new DiscretionaryAcl (true, false, 0);
174 
175 			RemoveSpecificBegin (sid, dacl, InheritanceFlags.ObjectInherit);
176 			dacl.RemoveAccessSpecific (AccessControlType.Allow, sid, 3, InheritanceFlags.ObjectInherit, PropagationFlags.None);
177 			Assert.AreEqual (0, dacl.Count);
178 		}
179 
180 		[Test]
RemoveSpecificIgnoresPropagationFlagsWhenMatchingInheritanceFlagsNone()181 		public void RemoveSpecificIgnoresPropagationFlagsWhenMatchingInheritanceFlagsNone()
182 		{
183 			SecurityIdentifier sid = new SecurityIdentifier ("BA");
184 			DiscretionaryAcl dacl = new DiscretionaryAcl (false, false, 0);
185 
186 			RemoveSpecificBegin (sid, dacl, InheritanceFlags.None);
187 			dacl.RemoveAccessSpecific (AccessControlType.Allow, sid, 3,
188 			                           InheritanceFlags.None, PropagationFlags.InheritOnly);
189 			Assert.AreEqual (0, dacl.Count);
190 		}
191 
RemoveSpecificBegin(SecurityIdentifier sid, DiscretionaryAcl dacl, InheritanceFlags inheritanceFlags)192 		void RemoveSpecificBegin (SecurityIdentifier sid, DiscretionaryAcl dacl, InheritanceFlags inheritanceFlags)
193 		{
194 			SecurityIdentifier otherSid = new SecurityIdentifier ("BU");
195 
196 			dacl.AddAccess (AccessControlType.Allow, sid, 3, inheritanceFlags, PropagationFlags.None);
197 			Assert.AreEqual (1, dacl.Count);
198 			dacl.RemoveAccessSpecific (AccessControlType.Deny, sid, 1, inheritanceFlags, PropagationFlags.None);
199 			Assert.AreEqual (1, dacl.Count);
200 			dacl.RemoveAccessSpecific (AccessControlType.Allow, otherSid, 1, inheritanceFlags, PropagationFlags.None);
201 			Assert.AreEqual (1, dacl.Count);
202 			dacl.RemoveAccessSpecific (AccessControlType.Allow, sid, 1, inheritanceFlags, PropagationFlags.None);
203 			Assert.AreEqual (1, dacl.Count);
204 			Assert.AreEqual (3, ((CommonAce)dacl [0]).AccessMask);
205 			dacl.RemoveAccessSpecific (AccessControlType.Allow, sid, 3,
206 			                           inheritanceFlags ^ InheritanceFlags.ContainerInherit,
207 			                           PropagationFlags.None);
208 			Assert.AreEqual (1, dacl.Count);
209 		}
210 
211 		[Test]
PropagationFlagsDoNotRequireInheritanceFlagsForRemoveSpecific()212 		public void PropagationFlagsDoNotRequireInheritanceFlagsForRemoveSpecific ()
213 		{
214 			SecurityIdentifier sid = new SecurityIdentifier ("BU");
215 			DiscretionaryAcl dacl = new DiscretionaryAcl (false, false, 0);
216 			dacl.RemoveAccessSpecific (AccessControlType.Allow, sid, 3,
217 			                           InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly);
218 		}
219 
220 		[Test]
SetAccess()221 		public void SetAccess ()
222 		{
223 			SecurityIdentifier adminSid = new SecurityIdentifier ("BA"); // S-1-5-32-544
224 			SecurityIdentifier userSid = new SecurityIdentifier ("BU"); // S-1-5-32-545
225 
226 			DiscretionaryAcl dacl = new DiscretionaryAcl (true, false, 0);
227 			dacl.SetAccess (AccessControlType.Allow, adminSid, 1, InheritanceFlags.ObjectInherit, PropagationFlags.None);
228 			dacl.SetAccess (AccessControlType.Allow, userSid, 2, InheritanceFlags.None, PropagationFlags.None);
229 			Assert.AreEqual (2, dacl.Count);
230 
231 			CommonAce ace = (CommonAce)dacl [0];
232 			Assert.AreEqual (adminSid, ace.SecurityIdentifier);
233 			Assert.AreEqual (1, ace.AccessMask);
234 
235 			dacl.SetAccess (AccessControlType.Allow, adminSid, 4, InheritanceFlags.ObjectInherit, PropagationFlags.None);
236 			Assert.AreNotEqual (4, ace.AccessMask); // remove and add, not modify, despite AccessMask having a setter
237 			ace = (CommonAce)dacl [0];
238 			Assert.AreEqual (4, ace.AccessMask);
239 
240 			dacl.SetAccess (AccessControlType.Deny, adminSid, 4, InheritanceFlags.ObjectInherit, PropagationFlags.None);
241 			Assert.AreEqual (3, dacl.Count);
242 			ace = (CommonAce)dacl [0];
243 			Assert.AreEqual (AceQualifier.AccessDenied, ace.AceQualifier);
244 			ace = (CommonAce)dacl [1];
245 			Assert.AreEqual (AceQualifier.AccessAllowed, ace.AceQualifier);
246 		}
247 	}
248 }
249 
250