git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 04/10] git-shell: allow running git-cvsserver, not just cvs

From
MOMatthew Ogilvie <mmogilvi_git@miniinfo.net>
Date
Jan 24, 2009, 23:43 UTC
Message-ID
<1232840601-24696-5-git-send-email-mmogilvi_git@miniinfo.net>
In-Reply-To
<1232840601-24696-4-git-send-email-mmogilvi_git@miniinfo.net>

Add the ability to ask a git-shell restricted account to explicitly run git-cvsserver, instead of requesting a fake "cvs". With this, an account could be reconfigured to use/not use git-shell without requiring changes to client side configuration. It also avoids confusing users about which way cvs should be configured; if cvs is accessing a git repository, always set CVS_SERVER=git-cvsserver.

Signed-off-by: Matthew Ogilvie <mmogilvi_git@miniinfo.net>
---

-------------- Question 1:

There is a surprising shortage of solid information about the best way(s) restrict what commands can be run by ssh accounts, both in general and for git specifically. Is putting git-shell in /etc/passwd the best way? Are there other ways, just as good or better?

Perhaps someone who really knows could add something to the git-shell.txt man page describing the possible way(s) to configure an account to be restricted to git-shell.

-------------- Question 2:

As near as I can tell, git-shell as run by sshd is typically invoked such that it ends up with an argv with 3 arguments of the form ("git-shell","-c","command arguments"). But the (argc==2 "cvs server") special case near line 69 of shell.c appears to allow the middle argument ("-c") to be missing, but only for "cvs server".

My question is, why was this special case put there? Is a remnant of an imperfect ad-hoc test framework someone used, or is there a legitimate configuration where the "-c" is missing?

It seems to me that either this missing "-c" case should be eliminated, or it should be made more general: If some configuration of sshd leaves out the "-c", then it probably leaves it out for anything you try to invoke, not just "cvs server".

-------------- Hints about testing:

In addition to the test cases that are included in the patch, I tested this by setting up an extra user account with the following shell script set as the shell in /etc/passwd (yes, a shell script is my shell...). This allows me to tweak enviornment variables, log how it is invoked, maybe tee off the stdin/stdout, etc:

---CUT--- #!/bin/sh

log() { echo "$1" >> remote.log }

log "------------"
log ""
log "cmd:$0"
for arg in "$@" ; do
  log "arg:$arg"
done

PATH="/path/to/version/to/test:$PATH" log "path: $PATH" #tee input.out | git-shell "$@" | tee output.out exec git-shell "$@" ---CUT---

But note that you probably do NOT want to route through a wrapper like this for production...

-- Matthew Ogilvie [mmogilvi_git@miniinfo.net]

 Documentation/git-cvsserver.txt |    7 ++-
 Documentation/git-shell.txt     |    5 +-
 shell.c                         |    1 +
 t/t9400-git-cvsserver-server.sh |   88 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 97 insertions(+), 4 deletions(-)
diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index 785779e..e32ad7b 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -113,9 +113,12 @@ cvs -d ":ext;CVS_SERVER=git cvsserver:user@server/path/repo.git" co <HEAD_name>
 ------
 This has the advantage that it will be saved in your 'CVS/Root' files and
 you don't need to worry about always setting the correct environment
-variable.  SSH users restricted to 'git-shell' don't need to override the default
-with CVS_SERVER (and shouldn't) as 'git-shell' understands `cvs` to mean
+variable.  SSH users restricted to 'git-shell' do not need to
+override CVS_SERVER as 'git-cvsserver' because
+'git-shell' understands `cvs` to mean
 'git-cvsserver' and pretends that the other end runs the real 'cvs' better.
+But restricted users can still override it for consistency and to avoid
+reconfiguration if they are later promoted to full SSH access.
 --
 2. For each repo that you want accessible from CVS you need to edit config in
    the repo and add the following section.
diff --git a/Documentation/git-shell.txt b/Documentation/git-shell.txt
index 3f8d973..68cb834 100644
--- a/Documentation/git-shell.txt
+++ b/Documentation/git-shell.txt
@@ -18,8 +18,9 @@ of server-side GIT commands implementing the pull/push functionality.
 The commands can be executed only by the '-c' option; the shell is not
 interactive.
 
-Currently, only three commands are permitted to be called, 'git-receive-pack'
-'git-upload-pack' with a single required argument or 'cvs server' (to invoke
+Currently, only four commands are permitted to be called, 'git-receive-pack'
+'git-upload-pack' with a single required argument,
+'git-cvsserver server', or 'cvs server' (to invoke
 'git-cvsserver').
 
 Author
diff --git a/shell.c b/shell.c
index e339369..6ed960f 100644
--- a/shell.c
+++ b/shell.c
@@ -40,6 +40,7 @@ static struct commands {
 } cmd_list[] = {
 	{ "git-receive-pack", do_generic_cmd },
 	{ "git-upload-pack", do_generic_cmd },
+	{ "git-cvsserver", do_cvs_cmd },
 	{ "cvs", do_cvs_cmd },
 	{ NULL },
 };
diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh
index 6a37f71..b23a774 100755
--- a/t/t9400-git-cvsserver-server.sh
+++ b/t/t9400-git-cvsserver-server.sh
@@ -501,4 +501,92 @@ test_expect_success 'cvs annotate' '
     test_cmp ../expect ../actual
 '
 
+#------------
+# access server through git-shell:
+#------------
+
+cd "$WORKDIR"
+test_expect_success 'setup fake_ssh' '
+    cd cvswork &&
+    ( echo "#!/bin/sh" &&
+      echo "echo \"cmd:\$*\" >> fake_ssh_sh.log" &&
+      echo "if test x\"\$1 \$2 \$3\" = x\"-l user machine\" ; then" &&
+      echo "  shift ; shift ; shift" &&
+      echo "  exec /bin/sh -c \"\$*\"" &&
+      echo "fi" &&
+      echo "echo FAIL" &&
+      echo "exit 1"
+    ) > fake_ssh_sh &&
+    ( echo "#!/bin/sh" &&
+      echo "echo \"cmd:\$*\" >> fake_ssh_git-shell.log" &&
+      echo "if test x\"\$1 \$2 \$3\" = x\"-l user machine\" ; then" &&
+      echo "  shift ; shift ; shift" &&
+      echo "  exec git-shell -c \"\$*\""
+      echo "fi" &&
+      echo "echo FAIL" &&
+      echo "exit 1"
+    ) > fake_ssh_git-shell &&
+    chmod +x fake_ssh_sh fake_ssh_git-shell
+'
+
+cd "$WORKDIR"
+test_expect_success 'fake_ssh ... sh git-cvsserver' '
+    ( cd cvswork &&
+      CVS_SERVER="git-cvsserver" &&
+      CVS_RSH="./fake_ssh_sh" &&
+      CVSROOT=":ext:user@machine$SERVERDIR" &&
+      export CVS_SERVER CVS_RSH CVSROOT &&
+      GIT_CONFIG="$git_config" cvs -d "$CVSROOT" up -p status.file > ../out &&
+      cmp status.file ../out
+    )
+'
+
+cd "$WORKDIR"
+test_expect_success 'fake_ssh ... sh git cvsserver' '
+    ( cd cvswork &&
+      CVS_SERVER="git cvsserver" &&
+      CVS_RSH="./fake_ssh_sh" &&
+      CVSROOT=":ext:user@machine$SERVERDIR" &&
+      export CVS_SERVER CVS_RSH CVSROOT &&
+      GIT_CONFIG="$git_config" cvs -d "$CVSROOT" up -p status.file > ../out &&
+      cmp status.file ../out
+    )
+'
+
+cd "$WORKDIR"
+test_expect_success 'fake_ssh ... git-shell git-cvsserver' '
+    ( cd cvswork &&
+      CVS_SERVER="git-cvsserver" &&
+      CVS_RSH="./fake_ssh_git-shell" &&
+      CVSROOT=":ext:user@machine$SERVERDIR" &&
+      export CVS_SERVER CVS_RSH CVSROOT &&
+      GIT_CONFIG="$git_config" cvs -d "$CVSROOT" up -p status.file > ../out &&
+      cmp status.file ../out
+    )
+'
+
+cd "$WORKDIR"
+test_expect_success 'fake_ssh ... git-shell git cvsserver' '
+    ( cd cvswork &&
+      CVS_SERVER="git cvsserver" &&
+      CVS_RSH="./fake_ssh_git-shell" &&
+      CVSROOT=":ext:user@machine$SERVERDIR" &&
+      export CVS_SERVER CVS_RSH CVSROOT &&
+      GIT_CONFIG="$git_config" cvs -d "$CVSROOT" up -p status.file > ../out &&
+      cmp status.file ../out
+    )
+'
+
+cd "$WORKDIR"
+test_expect_success 'fake_ssh ... git-shell cvs' '
+    ( cd cvswork &&
+      CVS_SERVER="cvs" &&
+      CVS_RSH="./fake_ssh_git-shell" &&
+      CVSROOT=":ext:user@machine$SERVERDIR" &&
+      export CVS_SERVER CVS_RSH CVSROOT &&
+      GIT_CONFIG="$git_config" cvs -d "$CVSROOT" up -p status.file > ../out &&
+      cmp status.file ../out
+    )
+'
+
 test_done
-- 
1.6.1.81.g9833d.dirty
Previous: Matthew OgilvieNext: Matthew Ogilvie
Message 5 of 16 in “Misc. cvsserver, dashless, and test suite patches”
  1. 00/10 Misc. cvsserver, dashless, and test suite patchesMatthew Ogilvie, Jan 24, 2009
  2. 01/10 cvsserver: removed unused sha1Or-k mode from kopts_from_pathMatthew Ogilvie, Jan 24, 2009
  3. 02/10 cvsserver: add comments about database schema/usageMatthew Ogilvie, Jan 24, 2009
  4. 03/10 cvsserver: remove unused functions _headrev and gethistoryMatthew Ogilvie, Jan 24, 2009
  5. 04/10 git-shell: allow running git-cvsserver, not just cvsMatthew Ogilvie, Jan 24, 2009
  6. 05/10 cvsserver: run dashless "git command"s to access plumbingMatthew Ogilvie, Jan 24, 2009
  7. 06/10 t2300: use documented technique to invoke git-sh-setupMatthew Ogilvie, Jan 24, 2009
  8. 07/10 t3409: use dashless "git commit" instead of "git-commit"Matthew Ogilvie, Jan 24, 2009
  9. 08/10 run test suite without dashed git-commands in PATHMatthew Ogilvie, Jan 24, 2009
  10. 09/10 Revert "adapt git-cvsserver manpage to dash-free syntax"Matthew Ogilvie, Jan 24, 2009
  11. 10/10 cvsserver doc: emphasize using CVS_SERVER= phrase within CVSROOTMatthew Ogilvie, Jan 24, 2009
  12. Johannes SchindelinJan 25, 2009
  13. Matthew OgilvieJan 26, 2009
  14. Johannes SchindelinJan 26, 2009
  15. Matthew OgilvieJan 27, 2009
  16. Johannes SchindelinJan 25, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.