diff options
author | Junio C Hamano <gitster@pobox.com> | 2007-06-16 01:22:38 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2007-06-16 01:22:38 -0700 |
commit | 57bd934ea69f0151b729b74fd77629b94920cca7 (patch) | |
tree | ec66a0e3b79f26f88ddee1c16859af3c25d1ebca | |
parent | Merge branch 'lh/submodule' (diff) | |
parent | cvsserver: Actually implement --export-all (diff) | |
download | tgif-57bd934ea69f0151b729b74fd77629b94920cca7.tar.xz |
Merge branch 'fl/cvsserver'
* fl/cvsserver:
cvsserver: Actually implement --export-all
cvsserver: Let --base-path and pserver get along just fine
cvsserver: Add some useful commandline options
-rw-r--r-- | Documentation/git-cvsserver.txt | 43 | ||||
-rwxr-xr-x | git-cvsserver.perl | 91 | ||||
-rwxr-xr-x | t/t9400-git-cvsserver-server.sh | 45 |
3 files changed, 171 insertions, 8 deletions
diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt index e5005f02f9..60d0bcf0f3 100644 --- a/Documentation/git-cvsserver.txt +++ b/Documentation/git-cvsserver.txt @@ -7,10 +7,53 @@ git-cvsserver - A CVS server emulator for git SYNOPSIS -------- + +SSH: + [verse] export CVS_SERVER=git-cvsserver 'cvs' -d :ext:user@server/path/repo.git co <HEAD_name> +pserver (/etc/inetd.conf): + +[verse] +cvspserver stream tcp nowait nobody /usr/bin/git-cvsserver git-cvsserver pserver + +Usage: + +[verse] +'git-cvsserver' [options] [pserver|server] [<directory> ...] + +OPTIONS +------- + +All these options obviously only make sense if enforced by the server side. +They have been implemented to resemble the gitlink:git-daemon[1] options as +closely as possible. + +--base-path <path>:: +Prepend 'path' to requested CVSROOT + +--strict-paths:: +Don't allow recursing into subdirectories + +--export-all:: +Don't check for `gitcvs.enabled` in config. You also have to specify a list +of allowed directories (see below) if you want to use this option. + +--version, -V:: +Print version information and exit + +--help, -h, -H:: +Print usage information and exit + +<directory>:: +You can specify a list of allowed directories. If no directories +are given, all are allowed. This is an additional restriction, gitcvs +access still needs to be enabled by the `gitcvs.enabled` config option +unless '--export-all' was given, too. + + DESCRIPTION ----------- diff --git a/git-cvsserver.perl b/git-cvsserver.perl index d41b29f30b..5cbf27eebc 100755 --- a/git-cvsserver.perl +++ b/git-cvsserver.perl @@ -22,6 +22,9 @@ use bytes; use Fcntl; use File::Temp qw/tempdir tempfile/; use File::Basename; +use Getopt::Long qw(:config require_order no_ignore_case); + +my $VERSION = '@@GIT_VERSION@@'; my $log = GITCVS::log->new(); my $cfg; @@ -85,15 +88,57 @@ my $methods = { my $state = { prependdir => '' }; $log->info("--------------- STARTING -----------------"); +my $usage = + "Usage: git-cvsserver [options] [pserver|server] [<directory> ...]\n". + " --base-path <path> : Prepend to requested CVSROOT\n". + " --strict-paths : Don't allow recursing into subdirectories\n". + " --export-all : Don't check for gitcvs.enabled in config\n". + " --version, -V : Print version information and exit\n". + " --help, -h, -H : Print usage information and exit\n". + "\n". + "<directory> ... is a list of allowed directories. If no directories\n". + "are given, all are allowed. This is an additional restriction, gitcvs\n". + "access still needs to be enabled by the gitcvs.enabled config option.\n"; + +my @opts = ( 'help|h|H', 'version|V', + 'base-path=s', 'strict-paths', 'export-all' ); +GetOptions( $state, @opts ) + or die $usage; + +if ($state->{version}) { + print "git-cvsserver version $VERSION\n"; + exit; +} +if ($state->{help}) { + print $usage; + exit; +} + my $TEMP_DIR = tempdir( CLEANUP => 1 ); $log->debug("Temporary directory is '$TEMP_DIR'"); +$state->{method} = 'ext'; +if (@ARGV) { + if ($ARGV[0] eq 'pserver') { + $state->{method} = 'pserver'; + shift @ARGV; + } elsif ($ARGV[0] eq 'server') { + shift @ARGV; + } +} + +# everything else is a directory +$state->{allowed_roots} = [ @ARGV ]; + +# don't export the whole system unless the users requests it +if ($state->{'export-all'} && !@{$state->{allowed_roots}}) { + die "--export-all can only be used together with an explicit whitelist\n"; +} + # if we are called with a pserver argument, # deal with the authentication cat before entering the # main loop -$state->{method} = 'ext'; -if (@ARGV && $ARGV[0] eq 'pserver') { - $state->{method} = 'pserver'; +if ($state->{method} eq 'pserver') { my $line = <STDIN>; chomp $line; unless( $line =~ /^BEGIN (AUTH|VERIFICATION) REQUEST$/) { die "E Do not understand $line - expecting BEGIN AUTH REQUEST\n"; @@ -172,19 +217,48 @@ sub req_Root return 0; } + my $cvsroot = $state->{'base-path'} || ''; + $cvsroot =~ s#/+$##; + $cvsroot .= $data; + if ($state->{CVSROOT} - && ($state->{CVSROOT} ne $data)) { + && ($state->{CVSROOT} ne $cvsroot)) { print "error 1 Conflicting roots specified\n"; return 0; } - $state->{CVSROOT} = $data; + $state->{CVSROOT} = $cvsroot; $ENV{GIT_DIR} = $state->{CVSROOT} . "/"; + + if (@{$state->{allowed_roots}}) { + my $allowed = 0; + foreach my $dir (@{$state->{allowed_roots}}) { + next unless $dir =~ m#^/#; + $dir =~ s#/+$##; + if ($state->{'strict-paths'}) { + if ($ENV{GIT_DIR} =~ m#^\Q$dir\E/?$#) { + $allowed = 1; + last; + } + } elsif ($ENV{GIT_DIR} =~ m#^\Q$dir\E(/?$|/)#) { + $allowed = 1; + last; + } + } + + unless ($allowed) { + print "E $ENV{GIT_DIR} does not seem to be a valid GIT repository\n"; + print "E \n"; + print "error 1 $ENV{GIT_DIR} is not a valid repository\n"; + return 0; + } + } + unless (-d $ENV{GIT_DIR} && -e $ENV{GIT_DIR}.'HEAD') { print "E $ENV{GIT_DIR} does not seem to be a valid GIT repository\n"; - print "E \n"; - print "error 1 $ENV{GIT_DIR} is not a valid repository\n"; + print "E \n"; + print "error 1 $ENV{GIT_DIR} is not a valid repository\n"; return 0; } @@ -207,7 +281,8 @@ sub req_Root my $enabled = ($cfg->{gitcvs}{$state->{method}}{enabled} || $cfg->{gitcvs}{enabled}); - unless ($enabled && $enabled =~ /^\s*(1|true|yes)\s*$/i) { + unless ($state->{'export-all'} || + ($enabled && $enabled =~ /^\s*(1|true|yes)\s*$/i)) { print "E GITCVS emulation needs to be enabled on this repo\n"; print "E the repo config file needs a [gitcvs] section added, and the parameter 'enabled' set to 1\n"; print "E \n"; diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh index 41dcf646d1..b442b5d145 100755 --- a/t/t9400-git-cvsserver-server.sh +++ b/t/t9400-git-cvsserver-server.sh @@ -143,6 +143,51 @@ test_expect_success 'req_Root failure (conflicting roots)' \ 'cat request-conflict | git-cvsserver pserver >log 2>&1 && tail log | grep -q "^error 1 Conflicting roots specified$"' +test_expect_success 'req_Root (strict paths)' \ + 'cat request-anonymous | git-cvsserver --strict-paths pserver $SERVERDIR >log 2>&1 && + tail -n1 log | grep -q "^I LOVE YOU$"' + +test_expect_failure 'req_Root failure (strict-paths)' \ + 'cat request-anonymous | git-cvsserver --strict-paths pserver $WORKDIR >log 2>&1' + +test_expect_success 'req_Root (w/o strict-paths)' \ + 'cat request-anonymous | git-cvsserver pserver $WORKDIR/ >log 2>&1 && + tail -n1 log | grep -q "^I LOVE YOU$"' + +test_expect_failure 'req_Root failure (w/o strict-paths)' \ + 'cat request-anonymous | git-cvsserver pserver $WORKDIR/gitcvs >log 2>&1' + +cat >request-base <<EOF +BEGIN AUTH REQUEST +/gitcvs.git +anonymous + +END AUTH REQUEST +Root /gitcvs.git +EOF + +test_expect_success 'req_Root (base-path)' \ + 'cat request-base | git-cvsserver --strict-paths --base-path $WORKDIR/ pserver $SERVERDIR >log 2>&1 && + tail -n1 log | grep -q "^I LOVE YOU$"' + +test_expect_failure 'req_Root failure (base-path)' \ + 'cat request-anonymous | git-cvsserver --strict-paths --base-path $WORKDIR pserver $SERVERDIR >log 2>&1' + +GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled false || exit 1 + +test_expect_success 'req_Root (export-all)' \ + 'cat request-anonymous | git-cvsserver --export-all pserver $WORKDIR >log 2>&1 && + tail -n1 log | grep -q "^I LOVE YOU$"' + +test_expect_failure 'req_Root failure (export-all w/o whitelist)' \ + 'cat request-anonymous | git-cvsserver --export-all pserver >log 2>&1 + || false' + +test_expect_success 'req_Root (everything together)' \ + 'cat request-base | git-cvsserver --export-all --strict-paths --base-path $WORKDIR/ pserver $SERVERDIR >log 2>&1 && + tail -n1 log | grep -q "^I LOVE YOU$"' + +GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true || exit 1 #-------------- # CONFIG TESTS |