Merge branch 'ab/cvsserver'

* ab/cvsserver:
  git-cvsserver: test for pserver authentication support
  git-cvsserver: document making a password without htpasswd
  git-cvsserver: Improved error handling for pserver
  git-cvsserver: indent & clean up authdb code
  git-cvsserver: use a password file cvsserver pserver
  git-cvsserver: authentication support for pserver
This commit is contained in:
Junio C Hamano 2010-06-13 11:22:42 -07:00
commit a5080d8e10
3 changed files with 135 additions and 12 deletions

View File

@ -72,9 +72,6 @@ plugin. Most functionality works fine with both of these clients.
LIMITATIONS LIMITATIONS
----------- -----------
Currently cvsserver works over SSH connections for read/write clients, and
over pserver for anonymous CVS access.
CVS clients cannot tag, branch or perform GIT merges. CVS clients cannot tag, branch or perform GIT merges.
'git-cvsserver' maps GIT branches to CVS modules. This is very different 'git-cvsserver' maps GIT branches to CVS modules. This is very different
@ -84,7 +81,7 @@ one or more directories.
INSTALLATION INSTALLATION
------------ ------------
1. If you are going to offer anonymous CVS access via pserver, add a line in 1. If you are going to offer CVS access via pserver, add a line in
/etc/inetd.conf like /etc/inetd.conf like
+ +
-- --
@ -101,6 +98,38 @@ looks like
cvspserver stream tcp nowait nobody /usr/bin/git-cvsserver git-cvsserver pserver cvspserver stream tcp nowait nobody /usr/bin/git-cvsserver git-cvsserver pserver
------ ------
Only anonymous access is provided by pserve by default. To commit you
will have to create pserver accounts, simply add a gitcvs.authdb
setting in the config file of the repositories you want the cvsserver
to allow writes to, for example:
------
[gitcvs]
authdb = /etc/cvsserver/passwd
------
The format of these files is username followed by the crypted password,
for example:
------
myuser:$1Oyx5r9mdGZ2
myuser:$1$BA)@$vbnMJMDym7tA32AamXrm./
------
You can use the 'htpasswd' facility that comes with Apache to make these
files, but Apache's MD5 crypt method differs from the one used by most C
library's crypt() function, so don't use the -m option.
Alternatively you can produce the password with perl's crypt() operator:
-----
perl -e 'my ($user, $pass) = @ARGV; printf "%s:%s\n", $user, crypt($user, $pass)' $USER password
-----
Then provide your password via the pserver method, for example:
------
cvs -d:pserver:someuser:somepassword <at> server/path/repo.git co <HEAD_name>
------
No special setup is needed for SSH access, other than having GIT tools No special setup is needed for SSH access, other than having GIT tools
in the PATH. If you have clients that do not accept the CVS_SERVER in the PATH. If you have clients that do not accept the CVS_SERVER
environment variable, you can rename 'git-cvsserver' to `cvs`. environment variable, you can rename 'git-cvsserver' to `cvs`.

View File

@ -183,12 +183,58 @@ if ($state->{method} eq 'pserver') {
exit 1; exit 1;
} }
$line = <STDIN>; chomp $line; $line = <STDIN>; chomp $line;
unless ($line eq 'anonymous') { my $user = $line;
print "E Only anonymous user allowed via pserver\n"; $line = <STDIN>; chomp $line;
print "I HATE YOU\n"; my $password = $line;
exit 1;
if ($user eq 'anonymous') {
# "A" will be 1 byte, use length instead in case the
# encryption method ever changes (yeah, right!)
if (length($password) > 1 ) {
print "E Don't supply a password for the `anonymous' user\n";
print "I HATE YOU\n";
exit 1;
}
# Fall through to LOVE
} else {
# Trying to authenticate a user
if (not exists $cfg->{gitcvs}->{authdb}) {
print "E the repo config file needs a [gitcvs] section with an 'authdb' parameter set to the filename of the authentication database\n";
print "I HATE YOU\n";
exit 1;
}
my $authdb = $cfg->{gitcvs}->{authdb};
unless (-e $authdb) {
print "E The authentication database specified in [gitcvs.authdb] does not exist\n";
print "I HATE YOU\n";
exit 1;
}
my $auth_ok;
open my $passwd, "<", $authdb or die $!;
while (<$passwd>) {
if (m{^\Q$user\E:(.*)}) {
if (crypt($user, descramble($password)) eq $1) {
$auth_ok = 1;
}
};
}
close $passwd;
unless ($auth_ok) {
print "I HATE YOU\n";
exit 1;
}
# Fall through to LOVE
} }
$line = <STDIN>; chomp $line; # validate the password?
# For checking whether the user is anonymous on commit
$state->{user} = $user;
$line = <STDIN>; chomp $line; $line = <STDIN>; chomp $line;
unless ($line eq "END $request REQUEST") { unless ($line eq "END $request REQUEST") {
die "E Do not understand $line -- expecting END $request REQUEST\n"; die "E Do not understand $line -- expecting END $request REQUEST\n";
@ -1271,9 +1317,9 @@ sub req_ci
$log->info("req_ci : " . ( defined($data) ? $data : "[NULL]" )); $log->info("req_ci : " . ( defined($data) ? $data : "[NULL]" ));
if ( $state->{method} eq 'pserver') if ( $state->{method} eq 'pserver' and $state->{user} eq 'anonymous' )
{ {
print "error 1 pserver access cannot commit\n"; print "error 1 anonymous user cannot commit via pserver\n";
cleanupWorkTree(); cleanupWorkTree();
exit; exit;
} }
@ -2586,6 +2632,40 @@ sub cvs_author
$author; $author;
} }
sub descramble
{
# This table is from src/scramble.c in the CVS source
my @SHIFTS = (
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
114,120, 53, 79, 96,109, 72,108, 70, 64, 76, 67,116, 74, 68, 87,
111, 52, 75,119, 49, 34, 82, 81, 95, 65,112, 86,118,110,122,105,
41, 57, 83, 43, 46,102, 40, 89, 38,103, 45, 50, 42,123, 91, 35,
125, 55, 54, 66,124,126, 59, 47, 92, 71,115, 78, 88,107,106, 56,
36,121,117,104,101,100, 69, 73, 99, 63, 94, 93, 39, 37, 61, 48,
58,113, 32, 90, 44, 98, 60, 51, 33, 97, 62, 77, 84, 80, 85,223,
225,216,187,166,229,189,222,188,141,249,148,200,184,136,248,190,
199,170,181,204,138,232,218,183,255,234,220,247,213,203,226,193,
174,172,228,252,217,201,131,230,197,211,145,238,161,179,160,212,
207,221,254,173,202,146,224,151,140,196,205,130,135,133,143,246,
192,159,244,239,185,168,215,144,139,165,180,157,147,186,214,176,
227,231,219,169,175,156,206,198,129,164,150,210,154,177,134,127,
182,128,158,208,162,132,167,209,149,241,153,251,237,236,171,195,
243,233,253,240,194,250,191,155,142,137,245,235,163,242,178,152
);
my ($str) = @_;
# This should never happen, the same password format (A) bas been
# used by CVS since the beginning of time
die "invalid password format $1" unless substr($str, 0, 1) eq 'A';
my @str = unpack "C*", substr($str, 1);
my $ret = join '', map { chr $SHIFTS[$_] } @str;
return $ret;
}
package GITCVS::log; package GITCVS::log;
#### ####

View File

@ -48,7 +48,9 @@ test_expect_success 'setup' '
git pull secondroot master && git pull secondroot master &&
git clone -q --bare "$WORKDIR/.git" "$SERVERDIR" >/dev/null 2>&1 && git clone -q --bare "$WORKDIR/.git" "$SERVERDIR" >/dev/null 2>&1 &&
GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true && GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true &&
GIT_DIR="$SERVERDIR" git config gitcvs.logfile "$SERVERDIR/gitcvs.log" GIT_DIR="$SERVERDIR" git config gitcvs.logfile "$SERVERDIR/gitcvs.log" &&
GIT_DIR="$SERVERDIR" git config gitcvs.authdb "$SERVERDIR/auth.db" &&
echo cvsuser:cvGVEarMLnhlA > "$SERVERDIR/auth.db"
' '
# note that cvs doesn't accept absolute pathnames # note that cvs doesn't accept absolute pathnames
@ -94,6 +96,14 @@ git
END VERIFICATION REQUEST END VERIFICATION REQUEST
EOF EOF
cat >login-git-ok <<EOF
BEGIN VERIFICATION REQUEST
$SERVERDIR
cvsuser
Ah<Z:yZZ30 e
END VERIFICATION REQUEST
EOF
test_expect_success 'pserver authentication' \ test_expect_success 'pserver authentication' \
'cat request-anonymous | git-cvsserver pserver >log 2>&1 && 'cat request-anonymous | git-cvsserver pserver >log 2>&1 &&
sed -ne \$p log | grep "^I LOVE YOU\$"' sed -ne \$p log | grep "^I LOVE YOU\$"'
@ -107,6 +117,10 @@ test_expect_success 'pserver authentication failure (non-anonymous user)' \
fi && fi &&
sed -ne \$p log | grep "^I HATE YOU\$"' sed -ne \$p log | grep "^I HATE YOU\$"'
test_expect_success 'pserver authentication success (non-anonymous user with password)' \
'cat login-git-ok | git-cvsserver pserver >log 2>&1 &&
sed -ne \$p log | grep "^I LOVE YOU\$"'
test_expect_success 'pserver authentication (login)' \ test_expect_success 'pserver authentication (login)' \
'cat login-anonymous | git-cvsserver pserver >log 2>&1 && 'cat login-anonymous | git-cvsserver pserver >log 2>&1 &&
sed -ne \$p log | grep "^I LOVE YOU\$"' sed -ne \$p log | grep "^I LOVE YOU\$"'