Merge "Disallow ref creation when passed object is neither Commit or Tag"
diff --git a/java/com/google/gerrit/server/project/CreateRefControl.java b/java/com/google/gerrit/server/project/CreateRefControl.java
index ab134b5..c3d3978 100644
--- a/java/com/google/gerrit/server/project/CreateRefControl.java
+++ b/java/com/google/gerrit/server/project/CreateRefControl.java
@@ -112,7 +112,9 @@
RefPermission.READ.describeForException()));
throw e;
}
- } else if (object instanceof RevTag) {
+ return;
+ }
+ if (object instanceof RevTag) {
RevTag tag = (RevTag) object;
try (RevWalk rw = new RevWalk(repo)) {
rw.parseBody(tag);
@@ -145,7 +147,11 @@
} else {
forRef.check(RefPermission.CREATE_TAG);
}
+ return;
}
+ throw new AuthException(
+ String.format(
+ "Ref creation not allowed. Object %s is neither Commit or Tag.", object.getId()));
}
/**
diff --git a/javatests/com/google/gerrit/acceptance/git/PushPermissionsIT.java b/javatests/com/google/gerrit/acceptance/git/PushPermissionsIT.java
index f94aa12..fa6d2e4 100644
--- a/javatests/com/google/gerrit/acceptance/git/PushPermissionsIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/PushPermissionsIT.java
@@ -45,6 +45,7 @@
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteRefUpdate;
@@ -405,6 +406,33 @@
assertThat(r).hasProcessed(ImmutableMap.of("refs", 1));
}
+ @Test
+ public void pushTreeIsNotAllowed() throws Exception {
+ RevCommit commit = testRepo.branch("HEAD").commit().create();
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(allow(Permission.CREATE).ref("refs/*").group(REGISTERED_USERS))
+ .add(allow(Permission.PUSH).ref("refs/*").group(REGISTERED_USERS))
+ .update();
+
+ // We use "refs/main" instead of "refs/heads/main", because the latter only allows commits.
+ {
+ // An extra colon (:) makes it a tree reference
+ PushResult r = push(commit.getId().getName() + "::refs/main");
+ RemoteRefUpdate refUpdate = r.getRemoteUpdates().stream().findFirst().get();
+ assertThat(refUpdate.getStatus()).isEqualTo(Status.REJECTED_OTHER_REASON);
+ assertThat(refUpdate.getMessage()).contains("is neither Commit or Tag");
+ }
+
+ {
+ PushResult r = push(commit.getTree().getId().getName() + ":refs/main");
+ RemoteRefUpdate refUpdate = r.getRemoteUpdates().stream().findFirst().get();
+ assertThat(refUpdate.getStatus()).isEqualTo(Status.REJECTED_OTHER_REASON);
+ assertThat(refUpdate.getMessage()).contains("is neither Commit or Tag");
+ }
+ }
+
private static void removeAllBranchPermissions(ProjectConfig cfg, String... permissions) {
for (AccessSection s : cfg.getAccessSections()) {
if (s.getName().startsWith("refs/heads/")