Merge branch 'sg/archive-restrict-remote'
Allow loosening remote "git archive" invocation security check that refuses to serve tree-ish not at the tip of any ref. * sg/archive-restrict-remote: add uploadarchive.allowUnreachable option docs: clarify remote restrictions for git-upload-archive
This commit is contained in:
commit
d552f8df1b
@ -2336,6 +2336,13 @@ transfer.unpackLimit::
|
||||
not set, the value of this variable is used instead.
|
||||
The default value is 100.
|
||||
|
||||
uploadarchive.allowUnreachable::
|
||||
If true, allow clients to use `git archive --remote` to request
|
||||
any tree, whether reachable from the ref tips or not. See the
|
||||
discussion in the `SECURITY` section of
|
||||
linkgit:git-upload-archive[1] for more details. Defaults to
|
||||
`false`.
|
||||
|
||||
uploadpack.hiderefs::
|
||||
String(s) `upload-pack` uses to decide which refs to omit
|
||||
from its initial advertisement. Use more than one
|
||||
|
@ -65,7 +65,10 @@ OPTIONS
|
||||
|
||||
--remote=<repo>::
|
||||
Instead of making a tar archive from the local repository,
|
||||
retrieve a tar archive from a remote repository.
|
||||
retrieve a tar archive from a remote repository. Note that the
|
||||
remote repository may place restrictions on which sha1
|
||||
expressions may be allowed in `<tree-ish>`. See
|
||||
linkgit:git-upload-archive[1] for details.
|
||||
|
||||
--exec=<git-upload-archive>::
|
||||
Used with --remote to specify the path to the
|
||||
|
@ -20,6 +20,38 @@ This command is usually not invoked directly by the end user. The UI
|
||||
for the protocol is on the 'git archive' side, and the program pair
|
||||
is meant to be used to get an archive from a remote repository.
|
||||
|
||||
SECURITY
|
||||
--------
|
||||
|
||||
In order to protect the privacy of objects that have been removed from
|
||||
history but may not yet have been pruned, `git-upload-archive` avoids
|
||||
serving archives for commits and trees that are not reachable from the
|
||||
repository's refs. However, because calculating object reachability is
|
||||
computationally expensive, `git-upload-archive` implements a stricter
|
||||
but easier-to-check set of rules:
|
||||
|
||||
1. Clients may request a commit or tree that is pointed to directly by
|
||||
a ref. E.g., `git archive --remote=origin v1.0`.
|
||||
|
||||
2. Clients may request a sub-tree within a commit or tree using the
|
||||
`ref:path` syntax. E.g., `git archive --remote=origin v1.0:Documentation`.
|
||||
|
||||
3. Clients may _not_ use other sha1 expressions, even if the end
|
||||
result is reachable. E.g., neither a relative commit like `master^`
|
||||
nor a literal sha1 like `abcd1234` is allowed, even if the result
|
||||
is reachable from the refs.
|
||||
|
||||
Note that rule 3 disallows many cases that do not have any privacy
|
||||
implications. These rules are subject to change in future versions of
|
||||
git, and the server accessed by `git archive --remote` may or may not
|
||||
follow these exact rules.
|
||||
|
||||
If the config option `uploadArchive.allowUnreachable` is true, these
|
||||
rules are ignored, and clients may use arbitrary sha1 expressions.
|
||||
This is useful if you do not care about the privacy of unreachable
|
||||
objects, or if your object database is already publicly available for
|
||||
access via non-smart-http.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
<directory>::
|
||||
|
13
archive.c
13
archive.c
@ -17,6 +17,7 @@ static char const * const archive_usage[] = {
|
||||
static const struct archiver **archivers;
|
||||
static int nr_archivers;
|
||||
static int alloc_archivers;
|
||||
static int remote_allow_unreachable;
|
||||
|
||||
void register_archiver(struct archiver *ar)
|
||||
{
|
||||
@ -257,7 +258,7 @@ static void parse_treeish_arg(const char **argv,
|
||||
unsigned char sha1[20];
|
||||
|
||||
/* Remotes are only allowed to fetch actual refs */
|
||||
if (remote) {
|
||||
if (remote && !remote_allow_unreachable) {
|
||||
char *ref = NULL;
|
||||
const char *colon = strchr(name, ':');
|
||||
int refnamelen = colon ? colon - name : strlen(name);
|
||||
@ -401,6 +402,14 @@ static int parse_archive_args(int argc, const char **argv,
|
||||
return argc;
|
||||
}
|
||||
|
||||
static int git_default_archive_config(const char *var, const char *value,
|
||||
void *cb)
|
||||
{
|
||||
if (!strcmp(var, "uploadarchive.allowunreachable"))
|
||||
remote_allow_unreachable = git_config_bool(var, value);
|
||||
return git_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
int write_archive(int argc, const char **argv, const char *prefix,
|
||||
int setup_prefix, const char *name_hint, int remote)
|
||||
{
|
||||
@ -411,7 +420,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
|
||||
if (setup_prefix && prefix == NULL)
|
||||
prefix = setup_git_directory_gently(&nongit);
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
git_config(git_default_archive_config, NULL);
|
||||
init_tar_archiver();
|
||||
init_zip_archiver();
|
||||
|
||||
|
@ -213,6 +213,15 @@ test_expect_success 'clients cannot access unreachable commits' '
|
||||
test_must_fail git archive --remote=. $sha1 >remote.tar
|
||||
'
|
||||
|
||||
test_expect_success 'upload-archive can allow unreachable commits' '
|
||||
test_commit unreachable1 &&
|
||||
sha1=`git rev-parse HEAD` &&
|
||||
git reset --hard HEAD^ &&
|
||||
git archive $sha1 >remote.tar &&
|
||||
test_config uploadarchive.allowUnreachable true &&
|
||||
git archive --remote=. $sha1 >remote.tar
|
||||
'
|
||||
|
||||
test_expect_success 'setup tar filters' '
|
||||
git config tar.tar.foo.command "tr ab ba" &&
|
||||
git config tar.bar.command "tr ab ba" &&
|
||||
|
Loading…
Reference in New Issue
Block a user