git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Jeff King <peff@peff.net>
To: git@vger.kernel.org
Subject: [PATCH 4/4] config: allow including config from repository blobs
Date: Thu, 26 Jan 2012 02:42:08 -0500	[thread overview]
Message-ID: <20120126074208.GD30474@sigill.intra.peff.net> (raw)
In-Reply-To: <20120126073547.GA28689@sigill.intra.peff.net>

One often-requested feature is to allow projects to ship
suggested config to people who clone. The most obvious way
of implementing this would be to respect .gitconfig files
within the working tree. However, this has two problems:

  1. Because git configuration can cause the execution of
     arbitrary code, that creates a potential security problem.
     While you may be comfortable running "make" on a newly
     cloned project, you at least have the opportunity to
     inspect the downloaded contents.  But by automatically
     respecting downloaded git configuration, you cannot
     even safely use git to inspect those contents!

  2. Configuration options tend not to be tied to a specific
     version of the project. So if you are using "git
     checkout" to sight-see to an older revision, you
     probably still want to be using the most recent version
     of the suggested config.

Instead, this patch lets you include configuration directly
from a blob in the repository (using the usual object name
lookup rules). This avoids (2) by pointing directly to a tag
or branch tip. It is still possible to be dangerous as in
(1) above, but the danger can be avoided by not pointing
directly into remote blobs (and the documentation warns of
this and gives a safe example).

Signed-off-by: Jeff King <peff@peff.net>
---
 Documentation/config.txt  |   41 ++++++++++++++++++++++++++++++++++++++++-
 config.c                  |   25 ++++++++++++++++++++++++-
 t/t1305-config-include.sh |   38 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index e55dae1..38e83df 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -93,7 +93,14 @@ included file is expanded immediately, as if its contents had been
 found at the location of the include directive. If the value of the
 `include.path` variable is a relative path, the path is considered to be
 relative to the configuration file in which the include directive was
-found. See below for examples.
+found.
+
+You can also include configuration from a blob stored in your repository
+by setting the special `include.ref` variable to the name of an object
+containing your configuration data (in the same format as a regular
+config file).
+
+See below for examples.
 
 Example
 ~~~~~~~
@@ -120,6 +127,38 @@ Example
 	[include]
 		path = /path/to/foo.inc ; include by absolute path
 		path = foo ; expand "foo" relative to the current file
+		ref = config:.gitconfig ; look on "config" branch
+		ref = origin/master:.gitconfig ; this is unsafe! see below
+
+
+Security Considerations
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Because git configuration may cause git to execute arbitrary shell
+commands, it is important to verify any configuration you receive over
+the network. In particular, it is not a good idea to point `include.ref`
+directly at a remote tracking branch like `origin/master:shared-config`.
+After a fetch, you have no way of inspecting the shared-config you have
+just received without running git (and thus respecting the downloaded
+config). Instead, you can create a local tag representing the last
+verified version of the config, and only update the tag after inspecting
+any new content.
+
+For example:
+
+	# initially, look at their suggested config
+	git show origin/master:shared-config
+
+	# if it looks good to you, point a local ref at it
+	git tag config origin/master
+	git config include.ref config:shared-config
+
+	# much later, fetch any changes and examine them
+	git fetch origin
+	git diff config origin/master -- shared-config
+
+	# If the changes look OK, update your local version
+	git tag -f config origin/master
 
 Variables
 ~~~~~~~~~
diff --git a/config.c b/config.c
index 49a3d1a..c41fb3b 100644
--- a/config.c
+++ b/config.c
@@ -941,7 +941,7 @@ static int handle_path_include(const char *path, void *data)
 	 */
 	if (!is_absolute_path(path)) {
 		char *slash;
-		if (!cf)
+		if (!cf || !cf->f)
 			return error("relative config includes must come from files");
 		strbuf_addstr(&buf, absolute_path(cf->name));
 		slash = find_last_dir_sep(buf.buf);
@@ -958,6 +958,27 @@ static int handle_path_include(const char *path, void *data)
 	return ret;
 }
 
+static int handle_ref_include(const char *ref, void *data)
+{
+	unsigned char sha1[20];
+	char *buf;
+	unsigned long size;
+	enum object_type type;
+	int ret;
+
+	if (get_sha1(ref, sha1))
+		return 0;
+	buf = read_sha1_file(sha1, &type, &size);
+	if (!buf)
+		return error("unable to read include ref '%s'", ref);
+	if (type != OBJ_BLOB)
+		return error("include ref '%s' is not a blob", ref);
+
+	ret = git_config_from_buffer(git_config_include, data, ref, buf, size);
+	free(buf);
+	return ret;
+}
+
 int git_config_include(const char *name, const char *value, void *vdata)
 {
 	const struct git_config_include_data *data = vdata;
@@ -978,6 +999,8 @@ int git_config_include(const char *name, const char *value, void *vdata)
 
 	if (!strcmp(type, "path"))
 		ret = handle_path_include(value, vdata);
+	else if (!strcmp(type, "ref"))
+		ret = handle_ref_include(value, vdata);
 
 	return ret;
 }
diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh
index 4db3091..31d3b9b 100755
--- a/t/t1305-config-include.sh
+++ b/t/t1305-config-include.sh
@@ -95,4 +95,42 @@ test_expect_success 'relative includes from command line fail' '
 	test_must_fail git -c include.path=one config test.one
 '
 
+test_expect_success 'include from ref' '
+	echo "[test]one = 1" >one &&
+	git add one &&
+	git commit -m one &&
+	rm one &&
+	echo "[include]ref = HEAD:one" >base &&
+	echo 1 >expect &&
+	git config -f base test.one >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'relative file include from ref fails' '
+	echo "[test]two = 2" >two &&
+	echo "[include]path = two" >one &&
+	git add one &&
+	git commit -m one &&
+	echo "[include]ref = HEAD:one" >base &&
+	test_must_fail git config -f base test.two
+'
+
+test_expect_success 'non-existent include refs are ignored' '
+	cat >base <<-\EOF &&
+	[include]ref = my-missing-config-branch:foo.cfg
+	[test]value = yes
+	EOF
+	echo yes >expect &&
+	git config -f base test.value >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'non-blob include refs fail' '
+	cat >base <<-\EOF &&
+	[include]ref = HEAD
+	[test]value = yes
+	EOF
+	test_must_fail git config -f base test.value
+'
+
 test_done
-- 
1.7.9.rc2.293.gaae2

  parent reply	other threads:[~2012-01-26  7:42 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-26  7:35 [RFC/PATCH 0/4] config include directives Jeff King
2012-01-26  7:37 ` [PATCH 1/4] config: add include directive Jeff King
2012-01-26  9:16   ` Johannes Sixt
2012-01-26 16:54     ` Jeff King
2012-01-26 20:42       ` Junio C Hamano
2012-01-26 22:25         ` Jeff King
2012-01-26 22:43           ` Jeff King
2012-01-26 20:58   ` Junio C Hamano
2012-01-26 22:51     ` Jeff King
2012-01-27  5:23       ` Junio C Hamano
2012-01-27  5:55         ` Jeff King
2012-01-27 17:03       ` Jens Lehmann
2012-01-27  0:02   ` Ævar Arnfjörð Bjarmason
2012-01-27  0:32     ` Jeff King
2012-01-27  9:33       ` Ævar Arnfjörð Bjarmason
2012-01-27  5:07   ` Michael Haggerty
2012-01-27  5:54     ` Jeff King
2012-01-26  7:38 ` [PATCH 2/4] config: factor out config file stack management Jeff King
2012-01-26  7:40 ` [PATCH 3/4] config: support parsing config data from buffers Jeff King
2012-01-26  7:42 ` Jeff King [this message]
2012-01-26  9:25   ` [PATCH 4/4] config: allow including config from repository blobs Johannes Sixt
2012-01-26 17:22     ` Jeff King
2012-01-27  3:47     ` Nguyen Thai Ngoc Duy
2012-01-27  5:57       ` Jeff King
2012-01-26 21:14   ` Junio C Hamano
2012-01-26 23:00     ` Jeff King
2012-01-27  0:35       ` Junio C Hamano
2012-01-27  0:49         ` Jeff King
2012-01-27  5:30           ` Junio C Hamano
2012-01-27  5:42             ` Jeff King
2012-01-27  7:27               ` Johannes Sixt
2012-01-27 23:10                 ` Junio C Hamano
2012-01-27  4:01   ` Nguyen Thai Ngoc Duy
2012-01-27  5:59     ` Jeff King
2012-01-27  9:51 ` [RFC/PATCH 0/4] config include directives Ævar Arnfjörð Bjarmason
2012-01-27 17:34   ` Jeff King

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120126074208.GD30474@sigill.intra.peff.net \
    --to=peff@peff.net \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).