1 // CommonObjectSecurityTest.cs - NUnit Test Cases for CommonObjectSecurity
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 CommonObjectSecurityTest
18 	{
19 		[Test]
Defaults()20 		public void Defaults ()
21 		{
22 			TestSecurity security;
23 
24 			security = new TestSecurity (false);
25 			Assert.IsFalse (security.IsContainerTest);
26 			Assert.IsFalse (security.IsDSTest);
27 
28 			security = new TestSecurity (true);
29 			Assert.IsTrue (security.IsContainerTest);
30 			Assert.IsFalse (security.IsDSTest);
31 		}
32 
33 		[Test]
AddAndGetAccessRulesWorkAndMergeCorrectly()34 		public void AddAndGetAccessRulesWorkAndMergeCorrectly ()
35 		{
36 			var security = new TestSecurity (false);
37 
38 			// CommonObjectSecurity does not appear to care at all about types on MS.NET.
39 			// It just uses AccessMask, and then GetAccessRules uses the factory methods.
40 			// So, the whole API is a mess of strong typing and repeated code backed by nothing.
41 			Assert.IsFalse (security.modify_access_called);
42 
43 			SecurityIdentifier sid = new SecurityIdentifier (WellKnownSidType.WorldSid, null);
44 			security.AddAccessRuleTest (new TestAccessRule<int> (sid, 2, AccessControlType.Allow));
45 			security.AddAccessRuleTest (new TestAccessRule<TestRights> (sid, TestRights.One, AccessControlType.Allow));
46 			security.AddAccessRuleTest (new TestAccessRule<int> (sid, 4, AccessControlType.Allow));
47 
48 			Assert.IsTrue (security.modify_access_called);
49 			Assert.IsFalse (security.modify_access_rule_called);
50 			Assert.IsFalse (security.modify_audit_called);
51 
52 			Assert.IsFalse (security.access_rule_factory_called);
53 			AuthorizationRuleCollection rules1 = security.GetAccessRules (false, true, typeof (SecurityIdentifier));
54 			Assert.IsFalse (security.access_rule_factory_called);
55 			Assert.AreEqual (0, rules1.Count);
56 
57 			Assert.IsFalse (security.access_rule_factory_called);
58 			AuthorizationRuleCollection rules2 = security.GetAccessRules (true, true, typeof (SecurityIdentifier));
59 			Assert.IsTrue (security.access_rule_factory_called);
60 			Assert.AreEqual (1, rules2.Count);
61 
62 			Assert.IsInstanceOfType (typeof (TestAccessRule<TestRights>), rules2[0]);
63 			TestAccessRule<TestRights> rule = (TestAccessRule<TestRights>)rules2[0];
64 			Assert.AreEqual ((TestRights)7, rule.Rights);
65 		}
66 
67 		[Test]
AddAndPurgeWorks()68 		public void AddAndPurgeWorks ()
69 		{
70 			TestSecurity security = new TestSecurity (false);
71 
72 			NTAccount nta1 = new NTAccount(@"BUILTIN\Users");
73 			NTAccount nta2 = new NTAccount(@"BUILTIN\Administrators");
74 			security.AddAccessRuleTest (new TestAccessRule<TestRights> (nta1, TestRights.One,
75 			                                                            AccessControlType.Allow));
76 			security.AddAccessRuleTest (new TestAccessRule<TestRights> (nta2, TestRights.One,
77 			                                                            AccessControlType.Allow));
78 
79 			AuthorizationRuleCollection rules1 = security.GetAccessRules (true, true, typeof (NTAccount));
80 			Assert.AreEqual (2, rules1.Count);
81 
82 			security.PurgeAccessRules (nta1);
83 			AuthorizationRuleCollection rules2 = security.GetAccessRules (true, true, typeof (NTAccount));
84 			Assert.AreEqual (1, rules2.Count);
85 			Assert.IsInstanceOfType (typeof (TestAccessRule<TestRights>), rules2[0]);
86 			TestAccessRule<TestRights> rule = (TestAccessRule<TestRights>)rules2[0];
87 			Assert.AreEqual (nta2, rule.IdentityReference);
88 		}
89 
90 		[Test]
ResetAccessRuleCausesExactlyOneModifyAccessCall()91 		public void ResetAccessRuleCausesExactlyOneModifyAccessCall ()
92 		{
93 			TestSecurity security = new TestSecurity (false);
94 			SecurityIdentifier sid = new SecurityIdentifier ("WD");
95 			security.ResetAccessRuleTest (new TestAccessRule<TestRights> (sid, TestRights.One,
96 			                                                              AccessControlType.Allow));
97 			Assert.AreEqual (1, security.modify_access_called_count);
98 		}
99 
100 		class TestAccessRule<T> : AccessRule
101 		{
TestAccessRule(IdentityReference identity, T rules, AccessControlType type)102 			public TestAccessRule (IdentityReference identity, T rules,
103 			                       AccessControlType type)
104 				: this (identity, rules, InheritanceFlags.None, PropagationFlags.None, type)
105 			{
106 			}
107 
TestAccessRule(IdentityReference identity, T rules, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type)108 			public TestAccessRule (IdentityReference identity, T rules,
109 			                       InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags,
110 			                       AccessControlType type)
111 				: base (identity, (int)(object)rules, false, inheritanceFlags, propagationFlags, type)
112 			{
113 			}
114 
115 			public T Rights {
116 				get { return (T)(object)AccessMask; }
117 			}
118 		}
119 
120 		class TestAuditRule<T> : AuditRule
121 		{
TestAuditRule(IdentityReference identity, T rules, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags auditFlags)122 			public TestAuditRule (IdentityReference identity, T rules,
123 			                      InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags,
124 			                      AuditFlags auditFlags)
125 				: base (identity, (int)(object)rules, false, inheritanceFlags, propagationFlags, auditFlags)
126 			{
127 			}
128 		}
129 
130 		enum TestRights
131 		{
132 			One = 1
133 		}
134 
135 		class TestSecurity : CommonObjectSecurity
136 		{
137 			public bool access_rule_factory_called;
138 			public bool audit_rule_factory_called;
139 			public bool modify_access_called;
140 			public int modify_access_called_count;
141 			public bool modify_access_rule_called;
142 			public bool modify_audit_called;
143 			public bool modify_audit_rule_called;
144 
TestSecurity(bool isContainer)145 			public TestSecurity (bool isContainer)
146 				: base (isContainer)
147 			{
148 			}
149 
150 			public bool IsContainerTest {
151 				get { return IsContainer; }
152 			}
153 
154 			public bool IsDSTest {
155 				get { return IsDS; }
156 			}
157 
AddAccessRuleTest(AccessRule rule)158 			public void AddAccessRuleTest (AccessRule rule)
159 			{
160 				AddAccessRule (rule);
161 			}
162 
AddAuditRuleTest(AuditRule rule)163 			public void AddAuditRuleTest (AuditRule rule)
164 			{
165 				AddAuditRule (rule);
166 			}
167 
RemoveAccessRuleTest(AccessRule rule)168 			public bool RemoveAccessRuleTest (AccessRule rule)
169 			{
170 				return RemoveAccessRule (rule);
171 			}
172 
RemoveAccessRuleAllTest(AccessRule rule)173 			public void RemoveAccessRuleAllTest (AccessRule rule)
174 			{
175 				RemoveAccessRuleAll (rule);
176 			}
177 
RemoveAccessRuleSpecificTest(AccessRule rule)178 			public void RemoveAccessRuleSpecificTest (AccessRule rule)
179 			{
180 				RemoveAccessRuleSpecific (rule);
181 			}
182 
ResetAccessRuleTest(AccessRule rule)183 			public void ResetAccessRuleTest (AccessRule rule)
184 			{
185 				ResetAccessRule (rule);
186 			}
187 
AccessRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type)188 			public override AccessRule AccessRuleFactory (IdentityReference identityReference,
189 			                                              int accessMask, bool isInherited,
190 			                                              InheritanceFlags inheritanceFlags,
191 			                                              PropagationFlags propagationFlags,
192 			                                              AccessControlType type)
193 			{
194 				access_rule_factory_called = true;
195 				return new TestAccessRule<TestRights> (identityReference, (TestRights)accessMask,
196 								       inheritanceFlags, propagationFlags, type);
197 			}
198 
AuditRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags)199 			public override AuditRule AuditRuleFactory (IdentityReference identityReference,
200 				                                    int accessMask, bool isInherited,
201 				                                    InheritanceFlags inheritanceFlags,
202 			                                            PropagationFlags propagationFlags,
203 			                                            AuditFlags flags)
204 			{
205 				audit_rule_factory_called = true;
206 				return new TestAuditRule<TestRights> (identityReference, (TestRights)accessMask,
207 				                                      inheritanceFlags, propagationFlags, flags);
208 			}
209 
ModifyAccessRule(AccessControlModification modification, AccessRule rule, out bool modified)210 			public override bool ModifyAccessRule (AccessControlModification modification,
211 			                                       AccessRule rule, out bool modified)
212 			{
213 				modify_access_rule_called = true;
214 				return base.ModifyAccessRule (modification, rule, out modified);
215 			}
216 
ModifyAccess(AccessControlModification modification, AccessRule rule, out bool modified)217 			protected override bool ModifyAccess (AccessControlModification modification,
218 			                                      AccessRule rule, out bool modified)
219 			{
220 				modify_access_called = true;
221 				modify_access_called_count ++;
222 				return base.ModifyAccess (modification, rule, out modified);
223 			}
224 
ModifyAuditRule(AccessControlModification modification, AuditRule rule, out bool modified)225 			public override bool ModifyAuditRule (AccessControlModification modification,
226 			                                      AuditRule rule, out bool modified)
227 			{
228 				modify_audit_rule_called = true;
229 				return base.ModifyAuditRule (modification, rule, out modified);
230 			}
231 
ModifyAudit(AccessControlModification modification, AuditRule rule, out bool modified)232 			protected override bool ModifyAudit (AccessControlModification modification,
233 			                                     AuditRule rule, out bool modified)
234 			{
235 				modify_audit_called = true;
236 				return base.ModifyAudit (modification, rule, out modified);
237 			}
238 
239 			public override Type AccessRightType {
240 				get { return typeof (TestRights); }
241 			}
242 
243 			public override Type AccessRuleType {
244 				get { return typeof (TestAccessRule<TestRights>); }
245 			}
246 
247 			public override Type AuditRuleType {
248 				get { return typeof (TestAuditRule<TestRights>); }
249 			}
250 		}
251 	}
252 }
253 
254