[PATCH] shell: add base path and ~ expansion support.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



By default, paths that are forwarded to git-shell when users try to
pull from an ssh:// URI are relative to the server's root folder (/).
Add support for an environment variable, GIT_SHELL_BASE_PATH, to
allow sysadmins to make these paths relative to somewhere else
(e.g. /srv/git). Expand a leading "~/" to the value of $HOME.
Allow an additional leading slash to specify a path relative to the
root folder (/).

This change does not improve security in the slightest, just makes
ssh:// URIs prettier.

Signed-off-by: Dan Charney <git@xxxxxxxxxxx>
---

I should point out that I've not tested the the behavior with the "cvs emulator" mode, in large part because CVS remains thoroughly baffling to me. Despite many attempts to learn how to use it, I never did move beyond the "copy and paste somebody else's pre-written commands" phase.

This is my first attempt at contributing to a project this big, and this is the first time this year I've written any C. Free to tear me a new one if I've done something stupid :-)

Documentation/git-shell.txt |   25 ++++++++++++++++++++++++-
shell.c                     |   37 ++++++++++++++++++++++++++++++++++++-
2 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-shell.txt b/Documentation/git-shell.txt
index 9b92506..280282e 100644
--- a/Documentation/git-shell.txt
+++ b/Documentation/git-shell.txt
@@ -22,13 +22,36 @@ is started in interactive mode when no arguments are given; in this
case, COMMAND_DIR must exist, and any of the executables in it can be
invoked.

-'cvs server' is a special command which executes git-cvsserver.
+'cvs server' is a special command which executes git-cvsserver. If 
+"$GIT_SHELL_BASE_PATH" is set, it will be passed to git-cvsserver as
+the --base-path parameter.

COMMAND_DIR is the path "$HOME/git-shell-commands". The user must have
read and execute permissions to the directory in order to execute the
programs in it. The programs are executed with a cwd of $HOME, and
<argument> is parsed as a command-line string.

+PATH MAPPING
+------------
+
+If the environment variable "$GIT_SHELL_BASE_PATH" is set and the shell
+is not in interactive mode, $GIT_SHELL_BASE_PATH will be prepended to
+the front the <argument> passed to <command>. This is analogous to
+the --base-path switch from link:git-daemon[1] - if your environment
+variables include GIT_SHELL_BASE_PATH=/srv/git on example.com, and later
+someone pulls ssh://example.com/my.git, it will be interpreted as 
+/srv/git/my.git. This feature does not restrict clients to subfolders
+of the base path; path elements such as .. are allowed.
+
+If the environment variable "$HOME" is set, git-shell will replace a leading
+"~/" in the <argument> with the value of "$HOME". 
+
+Example::
+	If GIT_SHELL_BASE_PATH=/srv/git and HOME=/home/joeuser, then::
+		ssh://example.com/some.git	will map to /srv/git/some.git
+		ssh://example.com/~/my.git	will map to /home/joeuser/my.git
+		ssh://example.com//var/git/x.git	will map to /var/git/x.git
+
GIT
---
Part of the linkgit:git[1] suite
diff --git a/shell.c b/shell.c
index abb8622..e250b2a 100644
--- a/shell.c
+++ b/shell.c
@@ -6,6 +6,37 @@

#define COMMAND_DIR "git-shell-commands"
#define HELP_COMMAND COMMAND_DIR "/help"
+#define BASE_PATH_VARIABLE "GIT_SHELL_BASE_PATH"
+#define DEFAULT_PATH "/"
+
+static const char *adjust_argument_path(const char *arg) 
+{
+	struct strbuf path = STRBUF_INIT;
+	const char *env;
+	const char *prefix_variable = NULL;
+
+	if (arg == NULL || arg[0] != '/')
+		prefix_variable = BASE_PATH_VARIABLE;
+	else if (arg[1] == '/')
+		++arg;
+	else if (arg[1] == '~' && arg[2] == '/') {
+		prefix_variable = "HOME";
+		arg += 2;
+	} else 
+		prefix_variable = BASE_PATH_VARIABLE;
+
+	if (NULL != prefix_variable) {
+		env = getenv(prefix_variable);
+		if (NULL != env) 
+			strbuf_addstr(&path, env);
+	}
+
+	if (NULL != arg)
+		strbuf_addstr(&path, arg);
+	if (NULL == path.buf || path.buf[0] == '\0')
+		return DEFAULT_PATH;
+	return path.buf;
+}

static int do_generic_cmd(const char *me, char *arg)
{
@@ -18,7 +49,7 @@ static int do_generic_cmd(const char *me, char *arg)
		die("bad command");

	my_argv[0] = me + 4;
-	my_argv[1] = arg;
+	my_argv[1] = adjust_argument_path(arg);
	my_argv[2] = NULL;

	return execv_git_cmd(my_argv);
@@ -30,6 +61,10 @@ static int do_cvs_cmd(const char *me, char *arg)
		"cvsserver", "server", NULL
	};

+	const char *base_path;
+	base_path = adjust_argument_path(NULL);
+	setenv("GIT_CVSSERVER_BASE_PATH", base_path, 1);
+
	if (!arg || strcmp(arg, "server"))
		die("git-cvsserver only handles server: %s", arg);

-- 
1.7.4

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]