summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuca Milanesio <luca.milanesio@gmail.com>2020-11-13 00:12:38 +0000
committerLuca Milanesio <luca.milanesio@gmail.com>2020-11-13 18:02:24 +0000
commite2349f7fd5926e56accd4c790a7628dd6da2e639 (patch)
tree277b39220cdfe7bfbd54956a44e0329c87eac70e
parent67103ad9ef9d0e2ba85220f91e016e1e5a38f601 (diff)
Workaround Gitiles bug on All-Users visibility
Gitiles has special FilteredRepository wrapper that allows to carefully hide refs based on the project's ACLs. There is however an optimisation that skips the filtering in case a user has READ permissions on every ACLs patterns. When the target repository is All-Users, the optimisation turns into a security issue because it allows seeing everything that belongs to everyone: - draft comments - PII of all users - external ids - draft edits Block Gitiles or any other part of Gerrit to abuse of this power when the target repository is All-Users, where nobody can be authorised to skip the ACLs evaluation. Cover the additional special case of the All-Users project access with two explicit positive and negative tests, so that the security check is covered. Bug: Issue 13621 Change-Id: Ia6ea1a9fd5473adff534204aea7d8f25324a45b7 (cherry picked from commit 45071d6977932bca5a1427c8abad24710fed2e33)
-rw-r--r--java/com/google/gerrit/server/permissions/ProjectControl.java8
-rw-r--r--javatests/com/google/gerrit/server/permissions/RefControlTest.java30
2 files changed, 37 insertions, 1 deletions
diff --git a/java/com/google/gerrit/server/permissions/ProjectControl.java b/java/com/google/gerrit/server/permissions/ProjectControl.java
index f2f7e8bed2..20eeaa69dc 100644
--- a/java/com/google/gerrit/server/permissions/ProjectControl.java
+++ b/java/com/google/gerrit/server/permissions/ProjectControl.java
@@ -36,6 +36,7 @@ import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.GroupMembership;
+import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GitReceivePackGroups;
import com.google.gerrit.server.config.GitUploadPackGroups;
import com.google.gerrit.server.git.GitRepositoryManager;
@@ -76,6 +77,7 @@ class ProjectControl {
private final ChangeControl.Factory changeControlFactory;
private final PermissionCollection.Factory permissionFilter;
private final DefaultRefFilter.Factory refFilterFactory;
+ private final AllUsersName allUsersName;
private List<SectionMatcher> allSections;
private Map<String, RefControl> refControls;
@@ -91,6 +93,7 @@ class ProjectControl {
RefVisibilityControl refVisibilityControl,
GitRepositoryManager repositoryManager,
DefaultRefFilter.Factory refFilterFactory,
+ AllUsersName allUsersName,
@Assisted CurrentUser who,
@Assisted ProjectState ps) {
this.changeControlFactory = changeControlFactory;
@@ -101,6 +104,7 @@ class ProjectControl {
this.refVisibilityControl = refVisibilityControl;
this.repositoryManager = repositoryManager;
this.refFilterFactory = refFilterFactory;
+ this.allUsersName = allUsersName;
user = who;
state = ps;
}
@@ -176,7 +180,9 @@ class ProjectControl {
}
boolean allRefsAreVisible(Set<String> ignore) {
- return user.isInternalUser() || canPerformOnAllRefs(Permission.READ, ignore);
+ return user.isInternalUser()
+ || (!getProject().getNameKey().equals(allUsersName)
+ && canPerformOnAllRefs(Permission.READ, ignore));
}
/** Can the user run upload pack? */
diff --git a/javatests/com/google/gerrit/server/permissions/RefControlTest.java b/javatests/com/google/gerrit/server/permissions/RefControlTest.java
index e529745462..04b84b6f75 100644
--- a/javatests/com/google/gerrit/server/permissions/RefControlTest.java
+++ b/javatests/com/google/gerrit/server/permissions/RefControlTest.java
@@ -101,6 +101,14 @@ public class RefControlTest extends GerritBaseTests {
assertThat(u.isOwner()).named("not owner").isFalse();
}
+ private void assertAllRefsAreVisible(ProjectControl u) {
+ assertThat(u.allRefsAreVisible(Collections.emptySet())).named("all refs visible").isTrue();
+ }
+
+ private void assertAllRefsAreNotVisible(ProjectControl u) {
+ assertThat(u.allRefsAreVisible(Collections.emptySet())).named("all refs NOT visible").isFalse();
+ }
+
private void assertNotOwner(String ref, ProjectControl u) {
assertThat(u.controlForRef(ref).isOwner()).named("NOT OWN " + ref).isFalse();
}
@@ -339,6 +347,27 @@ public class RefControlTest extends GerritBaseTests {
}
@Test
+ public void allRefsAreVisibleForRegularProject() throws Exception {
+ allow(local, READ, DEVS, "refs/*");
+ allow(local, READ, DEVS, "refs/groups/*");
+ allow(local, READ, DEVS, "refs/users/default");
+
+ assertAllRefsAreVisible(user(local, DEVS));
+ }
+
+ @Test
+ public void allRefsAreNotVisibleForAllUsers() throws Exception {
+ ProjectConfig allUsers = projectConfigFactory.create(allUsersName);
+ allUsers.load(newRepository(allUsersName));
+
+ allow(allUsers, READ, DEVS, "refs/*");
+ allow(allUsers, READ, DEVS, "refs/groups/*");
+ allow(allUsers, READ, DEVS, "refs/users/default");
+
+ assertAllRefsAreNotVisible(user(allUsers, DEVS));
+ }
+
+ @Test
public void branchDelegation1() throws Exception {
allow(local, OWNER, ADMIN, "refs/*");
allow(local, OWNER, DEVS, "refs/heads/x/*");
@@ -999,6 +1028,7 @@ public class RefControlTest extends GerritBaseTests {
refVisibilityControl,
repoManager,
refFilterFactory,
+ allUsersName,
new MockUser(name, memberOf),
newProjectState(local));
}