Commits

Matteo Tomasini committed b7a0ea4

[completed:539] Fixed AuthChecker for wrong beahviour in namespace permissions if group has global grant permissions.

Comments (0)

Files changed (3)

 //
 // You can specify all the values or you can default the Revision and Build Numbers 
 // by using the '*' as shown below:
-[assembly: AssemblyVersion("3.0.5.602")]
-[assembly: AssemblyFileVersion("3.0.5.602")]
+[assembly: AssemblyVersion("3.0.5.603")]
+[assembly: AssemblyFileVersion("3.0.5.603")]

Core-Tests/AuthCheckerTests.cs

 		}
 
 		[Test]
+		public void CheckActionForPage_GrantGroupFullControl_DenyGroupExplicitNamespace_ExceptReadPages() {
+			List<AclEntry> entries = new List<AclEntry>();
+			entries.Add(new AclEntry(Actions.ForGlobals.ResourceMasterPrefix, Actions.FullControl, "G.Group", Value.Grant));
+			entries.Add(new AclEntry(Actions.ForNamespaces.ResourceMasterPrefix + "NS1", Actions.ForNamespaces.ReadPages, "G.Group", Value.Grant));
+			entries.Add(new AclEntry(Actions.ForNamespaces.ResourceMasterPrefix + "NS1", Actions.FullControl, "G.Group", Value.Deny));
+
+			Collectors.SettingsProvider = MockProvider(entries);
+			Assert.IsFalse(AuthChecker.CheckActionForPage(new PageInfo(NameTools.GetFullName("NS1", "Page"), null, DateTime.Now), Actions.ForPages.ModifyPage, "User", new string[] { "Group" }), "Permission should be denied");
+			Assert.IsTrue(AuthChecker.CheckActionForPage(new PageInfo(NameTools.GetFullName("NS1", "Page"), null, DateTime.Now), Actions.ForPages.ReadPage, "User", new string[] { "Group" }), "Permission should be granted");
+		}
+
+		[Test]
+		public void CheckActionForPage_GrantGroupFullControl_DenyGroupNamespaceEscalator_ExceptReadPages() {
+			List<AclEntry> entries = new List<AclEntry>();
+			entries.Add(new AclEntry(Actions.ForGlobals.ResourceMasterPrefix, Actions.FullControl, "G.Group", Value.Grant));
+			entries.Add(new AclEntry(Actions.ForNamespaces.ResourceMasterPrefix, Actions.ForNamespaces.ReadPages, "G.Group", Value.Grant));
+			entries.Add(new AclEntry(Actions.ForNamespaces.ResourceMasterPrefix, Actions.FullControl, "G.Group", Value.Deny));
+
+			Collectors.SettingsProvider = MockProvider(entries);
+			Assert.IsFalse(AuthChecker.CheckActionForPage(new PageInfo(NameTools.GetFullName("NS1", "Page"), null, DateTime.Now), Actions.ForPages.ModifyPage, "User", new string[] { "Group" }), "Permission should be denied");
+			Assert.IsTrue(AuthChecker.CheckActionForPage(new PageInfo(NameTools.GetFullName("NS1", "Page"), null, DateTime.Now), Actions.ForPages.ReadPage, "User", new string[] { "Group" }), "Permission should be granted");
+		}
+
+		[Test]
+		public void CheckActionForPage_DenyGroupFullControl_GrantGroupExplicitNamespace() {
+			List<AclEntry> entries = new List<AclEntry>();
+			entries.Add(new AclEntry(Actions.ForGlobals.ResourceMasterPrefix, Actions.FullControl, "G.Group", Value.Deny));
+			entries.Add(new AclEntry(Actions.ForNamespaces.ResourceMasterPrefix + "NS1", Actions.FullControl, "G.Group", Value.Grant));
+
+			Collectors.SettingsProvider = MockProvider(entries);
+			Assert.IsTrue(AuthChecker.CheckActionForPage(new PageInfo(NameTools.GetFullName("NS1", "Page"), null, DateTime.Now), Actions.ForPages.ModifyPage, "User", new string[] { "Group" }), "Permission should be granted");
+			Assert.IsTrue(AuthChecker.CheckActionForPage(new PageInfo(NameTools.GetFullName("NS1", "Page"), null, DateTime.Now), Actions.ForPages.ReadPage, "User", new string[] { "Group" }), "Permission should be granted");
+		}
+
+		[Test]
+		public void CheckActionForPage_DenyGroupFullControl_GrantGroupNamespaceEscalator() {
+			List<AclEntry> entries = new List<AclEntry>();
+			entries.Add(new AclEntry(Actions.ForGlobals.ResourceMasterPrefix, Actions.FullControl, "G.Group", Value.Deny));
+			entries.Add(new AclEntry(Actions.ForNamespaces.ResourceMasterPrefix, Actions.FullControl, "G.Group", Value.Grant));
+
+			Collectors.SettingsProvider = MockProvider(entries);
+			Assert.IsTrue(AuthChecker.CheckActionForPage(new PageInfo(NameTools.GetFullName("NS1", "Page"), null, DateTime.Now), Actions.ForPages.ModifyPage, "User", new string[] { "Group" }), "Permission should be granted");
+			Assert.IsTrue(AuthChecker.CheckActionForPage(new PageInfo(NameTools.GetFullName("NS1", "Page"), null, DateTime.Now), Actions.ForPages.ReadPage, "User", new string[] { "Group" }), "Permission should be granted");
+		}
+
+		[Test]
+		public void CheckActionForPage_DenyGroupFullControl_GrantGroupReadPagesExplicitNamespace() {
+			List<AclEntry> entries = new List<AclEntry>();
+			entries.Add(new AclEntry(Actions.ForGlobals.ResourceMasterPrefix, Actions.FullControl, "G.Group", Value.Deny));
+			entries.Add(new AclEntry(Actions.ForNamespaces.ResourceMasterPrefix + "NS1", Actions.ForNamespaces.ReadPages, "G.Group", Value.Grant));
+
+			Collectors.SettingsProvider = MockProvider(entries);
+			Assert.IsFalse(AuthChecker.CheckActionForPage(new PageInfo(NameTools.GetFullName("NS1", "Page"), null, DateTime.Now), Actions.ForPages.ModifyPage, "User", new string[] { "Group" }), "Permission should be denied");
+			Assert.IsTrue(AuthChecker.CheckActionForPage(new PageInfo(NameTools.GetFullName("NS1", "Page"), null, DateTime.Now), Actions.ForPages.ReadPage, "User", new string[] { "Group" }), "Permission should be granted");
+		}
+
+		[Test]
+		public void CheckActionForPage_DenyGroupFullControl_GrantGroupReadPagesNamespaceEscalator() {
+			List<AclEntry> entries = new List<AclEntry>();
+			entries.Add(new AclEntry(Actions.ForGlobals.ResourceMasterPrefix, Actions.FullControl, "G.Group", Value.Deny));
+			entries.Add(new AclEntry(Actions.ForNamespaces.ResourceMasterPrefix, Actions.ForNamespaces.ReadPages, "G.Group", Value.Grant));
+
+			Collectors.SettingsProvider = MockProvider(entries);
+			Assert.IsFalse(AuthChecker.CheckActionForPage(new PageInfo(NameTools.GetFullName("NS1", "Page"), null, DateTime.Now), Actions.ForPages.ModifyPage, "User", new string[] { "Group" }), "Permission should be denied");
+			Assert.IsTrue(AuthChecker.CheckActionForPage(new PageInfo(NameTools.GetFullName("NS1", "Page"), null, DateTime.Now), Actions.ForPages.ReadPage, "User", new string[] { "Group" }), "Permission should be granted");
+		}
+
+		[Test]
+		public void CheckActionForPage_DenyGroupFullControl_GrantGroupReadPagesExplicitNamespaceLocalEscalator() {
+			List<AclEntry> entries = new List<AclEntry>();
+			entries.Add(new AclEntry(Actions.ForGlobals.ResourceMasterPrefix, Actions.FullControl, "G.Group", Value.Deny));
+			entries.Add(new AclEntry(Actions.ForNamespaces.ResourceMasterPrefix + "NS1", Actions.ForNamespaces.ManagePages, "G.Group", Value.Grant));
+
+			Collectors.SettingsProvider = MockProvider(entries);
+			Assert.IsTrue(AuthChecker.CheckActionForPage(new PageInfo(NameTools.GetFullName("NS1", "Page"), null, DateTime.Now), Actions.ForPages.ModifyPage, "User", new string[] { "Group" }), "Permission should be granted");
+			Assert.IsTrue(AuthChecker.CheckActionForPage(new PageInfo(NameTools.GetFullName("NS1", "Page"), null, DateTime.Now), Actions.ForPages.ReadPage, "User", new string[] { "Group" }), "Permission should be granted");
+		}
+
+		[Test]
+		public void CheckActionForPage_DenyGroupFullControl_GrantGroupReadPagesNamespaceEscalatorLocalEscalator() {
+			List<AclEntry> entries = new List<AclEntry>();
+			entries.Add(new AclEntry(Actions.ForGlobals.ResourceMasterPrefix, Actions.FullControl, "G.Group", Value.Deny));
+			entries.Add(new AclEntry(Actions.ForNamespaces.ResourceMasterPrefix, Actions.ForNamespaces.ManagePages, "G.Group", Value.Grant));
+
+			Collectors.SettingsProvider = MockProvider(entries);
+			Assert.IsTrue(AuthChecker.CheckActionForPage(new PageInfo(NameTools.GetFullName("NS1", "Page"), null, DateTime.Now), Actions.ForPages.ModifyPage, "User", new string[] { "Group" }), "Permission should be granted");
+			Assert.IsTrue(AuthChecker.CheckActionForPage(new PageInfo(NameTools.GetFullName("NS1", "Page"), null, DateTime.Now), Actions.ForPages.ReadPage, "User", new string[] { "Group" }), "Permission should be granted");
+		}
+
+		[Test]
 		public void CheckActionForPage_GrantUserRootEscalator_DenyGroupExplicitPage() {
 			List<AclEntry> entries = new List<AclEntry>();
 			entries.Add(new AclEntry(Actions.ForNamespaces.ResourceMasterPrefix,
 
 			if(currentUser == "admin") return true;
 
+			return LocalCheckActionForGlobals(action, currentUser, groups) == Authorization.Granted;
+		}
+
+		private static Authorization LocalCheckActionForGlobals(string action, string currentUser, string[] groups) {
 			AclEntry[] entries = SettingsProvider.AclManager.RetrieveEntriesForResource(Actions.ForGlobals.ResourceMasterPrefix);
 			Authorization auth = AclEvaluator.AuthorizeAction(Actions.ForGlobals.ResourceMasterPrefix, action,
 				AuthTools.PrepareUsername(currentUser), AuthTools.PrepareGroups(groups), entries);
 
-			return auth == Authorization.Granted;
+			return auth;
 		}
 
 		/// <summary>
 		/// <param name="action">The action the user is attempting to perform.</param>
 		/// <param name="currentUser">The current user.</param>
 		/// <param name="groups">The groups the user is member of.</param>
+		/// <param name="localEscalator"><c>true</c> is the method is called in a local escalator process.</param>
 		/// <returns><c>true</c> if the action is allowed, <c>false</c> otherwise.</returns>
-		public static bool CheckActionForNamespace(NamespaceInfo nspace, string action, string currentUser, string[] groups) {
+		public static bool CheckActionForNamespace(NamespaceInfo nspace, string action, string currentUser, string[] groups, bool localEscalator = false) {
 			if(action == null) throw new ArgumentNullException("action");
 			if(action.Length == 0) throw new ArgumentException("Action cannot be empty", "action");
 			if(!AuthTools.IsValidAction(action, Actions.ForNamespaces.All)) throw new ArgumentException("Invalid action", "action");
 
 			if(currentUser == "admin") return true;
 
+			return LocalCheckActionForNamespace(nspace, action, currentUser, groups, localEscalator) == Authorization.Granted;
+		}
+
+		private static Authorization LocalCheckActionForNamespace(NamespaceInfo nspace, string action, string currentUser, string[] groups, bool localEscalator = false) {
 			string namespaceName = nspace != null ? nspace.Name : "";
 
 			AclEntry[] entries = SettingsProvider.AclManager.RetrieveEntriesForResource(
 			Authorization auth = AclEvaluator.AuthorizeAction(Actions.ForNamespaces.ResourceMasterPrefix + namespaceName,
 				action, AuthTools.PrepareUsername(currentUser), AuthTools.PrepareGroups(groups), entries);
 
-			if(auth != Authorization.Unknown) return auth == Authorization.Granted;
+			if(localEscalator || auth != Authorization.Unknown) return auth;
 
 			// Try local escalators
 			string[] localEscalators = null;
 			if(Actions.ForNamespaces.LocalEscalators.TryGetValue(action, out localEscalators)) {
 				foreach(string localAction in localEscalators) {
-					bool authorized = CheckActionForNamespace(nspace, localAction, currentUser, groups);
-					if(authorized) return true;
+					Authorization authorization = LocalCheckActionForNamespace(nspace, localAction, currentUser, groups, true);
+					if(authorization != Authorization.Unknown) return authorization;
 				}
 			}
 
 			// Try root escalation
 			if(nspace != null) {
-				bool authorized = CheckActionForNamespace(null, action, currentUser, groups);
-				if(authorized) return true;
+				Authorization authorization = LocalCheckActionForNamespace(null, action, currentUser, groups);
+				if(authorization != Authorization.Unknown) return authorization;
 			}
 
 			// Try global escalators
 			string[] globalEscalators = null;
 			if(Actions.ForNamespaces.GlobalEscalators.TryGetValue(action, out globalEscalators)) {
 				foreach(string globalAction in globalEscalators) {
-					bool authorized = CheckActionForGlobals(globalAction, currentUser, groups);
-					if(authorized) return true;
+					Authorization authorization = LocalCheckActionForGlobals(globalAction, currentUser, groups);
+					if(authorization != Authorization.Unknown) return authorization;
 				}
 			}
 
-			return false;
+			return Authorization.Unknown;
 		}
 
 		/// <summary>
 		/// <param name="action">The action the user is attempting to perform.</param>
 		/// <param name="currentUser">The current user.</param>
 		/// <param name="groups">The groups the user is member of.</param>
+		/// <param name="localEscalator"><c>true</c> is the method is called in a local escalator process.</param>
 		/// <returns><c>true</c> if the action is allowed, <c>false</c> otherwise.</returns>
-		public static bool CheckActionForPage(PageInfo page, string action, string currentUser, string[] groups) {
+		public static bool CheckActionForPage(PageInfo page, string action, string currentUser, string[] groups, bool localEscalator = false) {
 			if(page == null) throw new ArgumentNullException("page");
 
 			if(action == null) throw new ArgumentNullException("action");
 
 			if(currentUser == "admin") return true;
 
+			return LocalCheckActionForPage(page, action, currentUser, groups, localEscalator) == Authorization.Granted;
+		}
+
+		private static Authorization LocalCheckActionForPage(PageInfo page, string action, string currentUser, string[] groups, bool localEscalator = false) {
 			AclEntry[] entries = SettingsProvider.AclManager.RetrieveEntriesForResource(Actions.ForPages.ResourceMasterPrefix + page.FullName);
 			Authorization auth = AclEvaluator.AuthorizeAction(Actions.ForPages.ResourceMasterPrefix + page.FullName, action,
 				AuthTools.PrepareUsername(currentUser), AuthTools.PrepareGroups(groups), entries);
 
-			if(auth != Authorization.Unknown) return auth == Authorization.Granted;
+			if(localEscalator || auth != Authorization.Unknown) return auth;
 
 			// Try local escalators
 			string[] localEscalators = null;
 			if(Actions.ForPages.LocalEscalators.TryGetValue(action, out localEscalators)) {
 				foreach(string localAction in localEscalators) {
-					bool authorized = CheckActionForPage(page, localAction, currentUser, groups);
-					if(authorized) return true;
+					Authorization authorization = LocalCheckActionForPage(page, localAction, currentUser, groups, true);
+					if(authorization != Authorization.Unknown) return authorization;
 				}
 			}
 
 			NamespaceInfo ns = string.IsNullOrEmpty(nsName) ? null : new NamespaceInfo(nsName, null, null);
 			if(Actions.ForPages.NamespaceEscalators.TryGetValue(action, out namespaceEscalators)) {
 				foreach(string namespaceAction in namespaceEscalators) {
-					bool authorized = CheckActionForNamespace(ns, namespaceAction, currentUser, groups);
-					if(authorized) return true;
+					Authorization authorization = LocalCheckActionForNamespace(ns, namespaceAction, currentUser, groups, true);
+					if(authorization != Authorization.Unknown) return authorization;
+					
+					// Try root escalation
+					if(ns != null) {
+						authorization = LocalCheckActionForNamespace(null, namespaceAction, currentUser, groups, true);
+						if(authorization != Authorization.Unknown) return authorization;
+					}
 				}
 			}
 
 			string[] globalEscalators = null;
 			if(Actions.ForPages.GlobalEscalators.TryGetValue(action, out globalEscalators)) {
 				foreach(string globalAction in globalEscalators) {
-					bool authorized = CheckActionForGlobals(globalAction, currentUser, groups);
-					if(authorized) return true;
+					Authorization authorization = LocalCheckActionForGlobals(globalAction, currentUser, groups);
+					if(authorization != Authorization.Unknown) return authorization;
 				}
 			}
 
-			return false;
+			return Authorization.Unknown;
 		}
 
 		/// <summary>