git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC] Single system account for multiple git users
@ 2008-06-30 15:11 Dmitry Potapov
  2008-06-30 15:59 ` Asheesh Laroia
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Dmitry Potapov @ 2008-06-30 15:11 UTC (permalink / raw)
  To: Git Mailing List

Hi,

Using SSH access with restricted git-shell as login shell and using
the script from the update-hook-example.txt works fine, but it requres
that every Git user has a separate system account on the server, which
is often frowned upon by system administrators, who would prefer to have
a single system account for access to Git repo.

I have looked on gitosis, but it requires normal shell account for
the git user, which was vetoed by sysadmin. Also, I found its
configuration more complex than necessary and not flexible enough
to differentiate what branches can have non-fast-forward pushes on
it and what cannot.

In fact, the simple solution for me would be to have authorized_key
for the git user being like this:

environment="GIT_USER=user1" ssh-rsa USER1-SSH-PUBLIC-KEY
environment="GIT_USER=user2" ssh-rsa USER2-SSH-PUBLIC-KEY
...

In this case, with one line change to update-hook-example from
username=$(id -u -n)
to
username="$GIT_USER"
I would get exactly what I want.

However, the environment option in authorized_key works only if
PermitUserEnvironment is set in sshd configuration, and this option
will allow _all_ users to overwrite their environment, which may be
not desirable in some settings for security reasons.

So, instead, I have to write a simple program, which is placed as
the login shell and interprets the given command as user name, sets
GIT_USER to it, and invokes git-shell with SSH_ORIGINAL_COMMAND.
Thus authorized_key looks like that:

command="git-su user1" ssh-rsa USER1-SSH-PUBLIC-KEY
command="git-su user2" ssh-rsa USER2-SSH-PUBLIC-KEY
...

But then I realized that it is simpler and more efficient to add
some built-in command to git-shell to do that.

You can see my patch below. I hope it will be useful for people
who wants to user git on server with a single system account for
all git users.

Dmitry

-- 8< --
From: Dmitry Potapov <dpotapov@gmail.com>
Date: Wed, 25 Jun 2008 08:14:22 +0400
Subject: [PATCH] git-shell: add git-su command

git-su interprets the given command as a user name that must be set to the
GIT_USER environment variable and then executing SSH_ORIGINAL_COMMAND as
it were the command given to git-shell. This allows to have different
values for GIT_USER variable for different ssh public keys, which is
necessary to have a single system for many Git users. With this command
the typical authorized_key will for git user will be look like this:

command="git-su user1" ssh-rsa USER1-SSH-PUBLIC-KEY
command="git-su user2" ssh-rsa USER2-SSH-PUBLIC-KEY
...

The alternative of using the "environment" option in authorized_key may be
problematic as it requires that the PermitUserEnvironment option was set
in sshd_config and by default this option is not enabled, because it may
allow some users to bypass access restrictions.

Signed-off-by: Dmitry Potapov <dpotapov@gmail.com>
---

I moved command parsing logic from main() to a separate function,
(which makes the patch a bit bigger than it actually is) and then
added do_su_cmd(), which reuses this functionality.

 shell.c |   51 ++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/shell.c b/shell.c
index 91ca7de..05bd3cc 100644
--- a/shell.c
+++ b/shell.c
@@ -41,6 +41,19 @@ static int do_cvs_cmd(const char *me, char *arg)
 	return execv_git_cmd(cvsserver_argv);
 }
 
+static int exec_cmd(char *prog);
+
+static int do_su_cmd(const char *me, char *arg)
+{
+	char *cmd = getenv("SSH_ORIGINAL_COMMAND");
+	if (!cmd)
+		die("SSH_ORIGINAL_COMMAND is not set");
+	if (setenv("GIT_USER", arg, 1))
+		die ("setenv failed: %s", strerror(errno));
+	if (unsetenv("SSH_ORIGINAL_COMMAND"))
+		die ("unsetenv failed: %s", strerror(errno));
+	return exec_cmd(cmd);
+}
 
 static struct commands {
 	const char *name;
@@ -49,28 +62,14 @@ static struct commands {
 	{ "git-receive-pack", do_generic_cmd },
 	{ "git-upload-pack", do_generic_cmd },
 	{ "cvs", do_cvs_cmd },
+	{ "git-su", do_su_cmd },
 	{ NULL },
 };
 
-int main(int argc, char **argv)
+static int exec_cmd(char *prog)
 {
-	char *prog;
 	struct commands *cmd;
 
-	/*
-	 * Special hack to pretend to be a CVS server
-	 */
-	if (argc == 2 && !strcmp(argv[1], "cvs server"))
-		argv--;
-
-	/*
-	 * We do not accept anything but "-c" followed by "cmd arg",
-	 * where "cmd" is a very limited subset of git commands.
-	 */
-	else if (argc != 3 || strcmp(argv[1], "-c"))
-		die("What do you think I am? A shell?");
-
-	prog = argv[2];
 	if (!strncmp(prog, "git", 3) && isspace(prog[3]))
 		/* Accept "git foo" as if the caller said "git-foo". */
 		prog[3] = '-';
@@ -91,7 +90,25 @@ int main(int argc, char **argv)
 		default:
 			continue;
 		}
-		exit(cmd->exec(cmd->name, arg));
+		return cmd->exec(cmd->name, arg);
 	}
 	die("unrecognized command '%s'", prog);
 }
+
+int main(int argc, char **argv)
+{
+	/*
+	 * Special hack to pretend to be a CVS server
+	 */
+	if (argc == 2 && !strcmp(argv[1], "cvs server"))
+		argv--;
+
+	/*
+	 * We do not accept anything but "-c" followed by "cmd arg",
+	 * where "cmd" is a very limited subset of git commands.
+	 */
+	else if (argc != 3 || strcmp(argv[1], "-c"))
+		die("What do you think I am? A shell?");
+
+	return exec_cmd(argv[2]);
+}
-- 
1.5.6.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2008-07-02 14:46 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-30 15:11 [RFC] Single system account for multiple git users Dmitry Potapov
2008-06-30 15:59 ` Asheesh Laroia
2008-06-30 16:51   ` Dmitry Potapov
2008-06-30 16:56     ` Jon Loeliger
2008-06-30 17:07       ` Dmitry Potapov
2008-06-30 16:04 ` Jakub Narebski
2008-06-30 17:05   ` Dmitry Potapov
2008-07-01  8:55 ` Melchior FRANZ
2008-07-02 14:45   ` Dmitry Potapov

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 NNTP newsgroup(s).