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.
|
not set, the value of this variable is used instead.
|
||||||
The default value is 100.
|
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::
|
uploadpack.hiderefs::
|
||||||
String(s) `upload-pack` uses to decide which refs to omit
|
String(s) `upload-pack` uses to decide which refs to omit
|
||||||
from its initial advertisement. Use more than one
|
from its initial advertisement. Use more than one
|
||||||
|
@ -65,7 +65,10 @@ OPTIONS
|
|||||||
|
|
||||||
--remote=<repo>::
|
--remote=<repo>::
|
||||||
Instead of making a tar archive from the local repository,
|
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>::
|
--exec=<git-upload-archive>::
|
||||||
Used with --remote to specify the path to the
|
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
|
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.
|
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
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
<directory>::
|
<directory>::
|
||||||
|
13
archive.c
13
archive.c
@ -17,6 +17,7 @@ static char const * const archive_usage[] = {
|
|||||||
static const struct archiver **archivers;
|
static const struct archiver **archivers;
|
||||||
static int nr_archivers;
|
static int nr_archivers;
|
||||||
static int alloc_archivers;
|
static int alloc_archivers;
|
||||||
|
static int remote_allow_unreachable;
|
||||||
|
|
||||||
void register_archiver(struct archiver *ar)
|
void register_archiver(struct archiver *ar)
|
||||||
{
|
{
|
||||||
@ -257,7 +258,7 @@ static void parse_treeish_arg(const char **argv,
|
|||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
|
|
||||||
/* Remotes are only allowed to fetch actual refs */
|
/* Remotes are only allowed to fetch actual refs */
|
||||||
if (remote) {
|
if (remote && !remote_allow_unreachable) {
|
||||||
char *ref = NULL;
|
char *ref = NULL;
|
||||||
const char *colon = strchr(name, ':');
|
const char *colon = strchr(name, ':');
|
||||||
int refnamelen = colon ? colon - name : strlen(name);
|
int refnamelen = colon ? colon - name : strlen(name);
|
||||||
@ -401,6 +402,14 @@ static int parse_archive_args(int argc, const char **argv,
|
|||||||
return argc;
|
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 write_archive(int argc, const char **argv, const char *prefix,
|
||||||
int setup_prefix, const char *name_hint, int remote)
|
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)
|
if (setup_prefix && prefix == NULL)
|
||||||
prefix = setup_git_directory_gently(&nongit);
|
prefix = setup_git_directory_gently(&nongit);
|
||||||
|
|
||||||
git_config(git_default_config, NULL);
|
git_config(git_default_archive_config, NULL);
|
||||||
init_tar_archiver();
|
init_tar_archiver();
|
||||||
init_zip_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_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' '
|
test_expect_success 'setup tar filters' '
|
||||||
git config tar.tar.foo.command "tr ab ba" &&
|
git config tar.tar.foo.command "tr ab ba" &&
|
||||||
git config tar.bar.command "tr ab ba" &&
|
git config tar.bar.command "tr ab ba" &&
|
||||||
|
Loading…
Reference in New Issue
Block a user