summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorNico Sallembien2010-02-09 18:01:27 (EST)
committer Nico Sallembien2010-02-11 16:01:27 (EST)
commit19126f70e9e5645278b38239c01d990c32d44af2 (patch)
tree4b95459f1665f605c68dd309624fe4c2b7561c62
parente54d33b6873f0b392640f9200398861210ac9374 (diff)
downloadjgit-19126f70e9e5645278b38239c01d990c32d44af2.zip
jgit-19126f70e9e5645278b38239c01d990c32d44af2.tar.gz
jgit-19126f70e9e5645278b38239c01d990c32d44af2.tar.bz2
Allow users of ReceivePack access to the objects being sentrefs/changes/82/282/7
When implementing branch read access, we need to prove that the newly created reference(s) point to objects that the user can see. There are two ways that an object is reachable: 1) It's reachable from a branch or change the user can see 2) It was uploaded as part of the pack file the user sent us This change adds additional methods in ReceivePack that will allow a server to check the above conditions, in order to ensure that a user is not trying to create a reference that they cannot see, or that a malicious user isn't attempting to forge the SHA-1 of an object that they cannot see in order to base a change off of it. Change-Id: Ieba75b4f0331e06a03417c37f4ae1ebca4fbee5a
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/IndexPack.java77
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java49
2 files changed, 121 insertions, 5 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/IndexPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/IndexPack.java
index 7c94767..23faa42 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/IndexPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/IndexPack.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2009, Google Inc.
+ * Copyright (C) 2008-2010, Google Inc.
* Copyright (C) 2007-2008, Robin Rosenberg <robin.rosenberg@dewire.com>
* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
* and other copyright owners as documented in the project's IP log.
@@ -54,7 +54,10 @@ import java.io.RandomAccessFile;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.zip.CRC32;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
@@ -158,6 +161,8 @@ public class IndexPack {
private boolean keepEmpty;
+ private boolean needBaseObjectIds;
+
private int outputVersion;
private final File dstPack;
@@ -168,6 +173,8 @@ public class IndexPack {
private PackedObjectInfo[] entries;
+ private Set<ObjectId> newObjectIds;
+
private int deltaCount;
private int entryCount;
@@ -176,6 +183,8 @@ public class IndexPack {
private ObjectIdSubclassMap<DeltaChain> baseById;
+ private Set<ObjectId> baseIds;
+
private LongMap<UnresolvedDelta> baseByPos;
private byte[] objectData;
@@ -268,6 +277,54 @@ public class IndexPack {
}
/**
+ * Configure this index pack instance to keep track of new objects.
+ * <p>
+ * By default an index pack doesn't save the new objects that were created
+ * when it was instantiated. Setting this flag to {@code true} allows the
+ * caller to use {@link #getNewObjectIds()} to retrieve that list.
+ *
+ * @param b {@code true} to enable keeping track of new objects.
+ */
+ public void setNeedNewObjectIds(boolean b) {
+ if (b)
+ newObjectIds = new HashSet<ObjectId>();
+ else
+ newObjectIds = null;
+ }
+
+ private boolean needNewObjectIds() {
+ return newObjectIds != null;
+ }
+
+ /**
+ * Configure this index pack instance to keep track of the objects assumed
+ * for delta bases.
+ * <p>
+ * By default an index pack doesn't save the objects that were used as delta
+ * bases. Setting this flag to {@code true} will allow the caller to
+ * use {@link #getBaseObjectIds()} to retrieve that list.
+ *
+ * @param b {@code true} to enable keeping track of delta bases.
+ */
+ public void setNeedBaseObjectIds(boolean b) {
+ this.needBaseObjectIds = b;
+ }
+
+ /** @return the new objects that were sent by the user */
+ public Set<ObjectId> getNewObjectIds() {
+ return newObjectIds == null ?
+ Collections.<ObjectId>emptySet() : newObjectIds;
+ }
+
+ /**
+ * @return the set of objects the incoming pack assumed for delta purposes
+ */
+ public Set<ObjectId> getBaseObjectIds() {
+ return baseIds == null ?
+ Collections.<ObjectId>emptySet() : baseIds;
+ }
+
+ /**
* Configure the checker used to validate received objects.
* <p>
* Usually object checking isn't necessary, as Git implementations only
@@ -333,6 +390,12 @@ public class IndexPack {
if (packOut == null)
throw new IOException("need packOut");
resolveDeltas(progress);
+ if (needBaseObjectIds) {
+ baseIds = new HashSet<ObjectId>();
+ for (DeltaChain c : baseById) {
+ baseIds.add(c);
+ }
+ }
if (entryCount < objectCount) {
if (!fixThin) {
throw new IOException("pack has "
@@ -453,7 +516,7 @@ public class IndexPack {
verifySafeObject(tempObjectId, type, data);
oe = new PackedObjectInfo(pos, crc32, tempObjectId);
- entries[entryCount++] = oe;
+ addObjectAndTrack(oe);
}
resolveChildDeltas(pos, type, data, oe);
@@ -749,7 +812,7 @@ public class IndexPack {
verifySafeObject(tempObjectId, type, data);
final int crc32 = (int) crc.getValue();
- entries[entryCount++] = new PackedObjectInfo(pos, crc32, tempObjectId);
+ addObjectAndTrack(new PackedObjectInfo(pos, crc32, tempObjectId));
}
private void verifySafeObject(final AnyObjectId id, final int type,
@@ -1112,4 +1175,10 @@ public class IndexPack {
if (!dstPack.delete())
dstPack.deleteOnExit();
}
-}
+
+ private void addObjectAndTrack(PackedObjectInfo oe) {
+ entries[entryCount++] = oe;
+ if (needNewObjectIds())
+ newObjectIds.add(oe);
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
index 4d63ee6..8d75f3c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
@@ -153,6 +153,8 @@ public class ReceivePack {
private PrintWriter msgs;
+ private IndexPack ip;
+
/** The refs we advertised as existing at the start of the connection. */
private Map<String, Ref> refs;
@@ -171,6 +173,10 @@ public class ReceivePack {
/** Lock around the received pack file, while updating refs. */
private PackLock packLock;
+ private boolean needNewObjectIds;
+
+ private boolean needBaseObjectIds;
+
/**
* Create a new pack receive for an open repository.
*
@@ -237,6 +243,45 @@ public class ReceivePack {
}
/**
+ * Configure this receive pack instance to keep track of the objects assumed
+ * for delta bases.
+ * <p>
+ * By default a receive pack doesn't save the objects that were used as
+ * delta bases. Setting this flag to {@code true} will allow the caller to
+ * use {@link #getBaseObjectIds()} to retrieve that list.
+ *
+ * @param b {@code true} to enable keeping track of delta bases.
+ */
+ public void setNeedBaseObjectIds(boolean b) {
+ this.needBaseObjectIds = b;
+ }
+
+ /**
+ * @return the set of objects the incoming pack assumed for delta purposes
+ */
+ public final Set<ObjectId> getBaseObjectIds() {
+ return ip.getBaseObjectIds();
+ }
+
+ /**
+ * Configure this receive pack instance to keep track of new objects.
+ * <p>
+ * By default a receive pack doesn't save the new objects that were created
+ * when it was instantiated. Setting this flag to {@code true} allows the
+ * caller to use {@link #getNewObjectIds()} to retrieve that list.
+ *
+ * @param b {@code true} to enable keeping track of new objects.
+ */
+ public void setNeedNewObjectIds(boolean b) {
+ this.needNewObjectIds = b;
+ }
+
+ /** @return the new objects that were sent by the user */
+ public final Set<ObjectId> getNewObjectIds() {
+ return ip.getNewObjectIds();
+ }
+
+ /**
* @return true if this class expects a bi-directional pipe opened between
* the client and itself. The default is true.
*/
@@ -685,8 +730,10 @@ public class ReceivePack {
if (timeoutIn != null)
timeoutIn.setTimeout(10 * timeout * 1000);
- final IndexPack ip = IndexPack.create(db, rawIn);
+ ip = IndexPack.create(db, rawIn);
ip.setFixThin(true);
+ ip.setNeedNewObjectIds(needNewObjectIds);
+ ip.setNeedBaseObjectIds(needBaseObjectIds);
ip.setObjectChecking(isCheckReceivedObjects());
ip.index(NullProgressMonitor.INSTANCE);