Browse Source

cvsserver: Add some useful commandline options

Make git-cvsserver understand some options inspired by
git-daemon, namely --base-path, --export-all, --strict-paths.

Also allow the caller to specify a whitelist of allowed
directories, again similar to git-daemon.

While already adding option parsing also support the common
--help and --version options.

Rationale:

While the gitcvs.enabled configuration option already
offers means to limit git-cvsserver access to a repository,
there are some use cases where other methods of access
control prove to be more useful.

E.g. if setting up a pserver for a collection of public
repositories one might want limit the exported repositories
to exactly the directory this collection is located whithout
having to worry about other repositories that might lie around
with the configuration variable set (never trust your users ;)

Signed-off-by: Frank Lichtenheld <frank@lichtenheld.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Frank Lichtenheld 18 years ago committed by Junio C Hamano
parent
commit
693b63273e
  1. 42
      Documentation/git-cvsserver.txt
  2. 79
      git-cvsserver.perl
  3. 28
      t/t9400-git-cvsserver-server.sh

42
Documentation/git-cvsserver.txt

@ -7,10 +7,52 @@ git-cvsserver - A CVS server emulator for git @@ -7,10 +7,52 @@ 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

--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
-----------


79
git-cvsserver.perl

@ -22,6 +22,9 @@ use bytes; @@ -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,52 @@ my $methods = { @@ -85,15 +88,52 @@ 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 ];

# 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";
@ -178,13 +218,40 @@ sub req_Root @@ -178,13 +218,40 @@ sub req_Root
return 0;
}

$state->{CVSROOT} = $data;
$state->{CVSROOT} = $state->{'base-path'} || '';
$state->{CVSROOT} =~ s#/+$##;
$state->{CVSROOT} .= $data;

$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;
}


28
t/t9400-git-cvsserver-server.sh

@ -143,6 +143,34 @@ test_expect_success 'req_Root failure (conflicting roots)' \ @@ -143,6 +143,34 @@ 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
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'

#--------------
# CONFIG TESTS

Loading…
Cancel
Save