Skip to content

Commit a5080d8

Browse files
committed
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
2 parents 2d4fef9 + 1dd3f29 commit a5080d8

File tree

3 files changed

+135
-12
lines changed

3 files changed

+135
-12
lines changed

Documentation/git-cvsserver.txt

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,6 @@ plugin. Most functionality works fine with both of these clients.
7272
LIMITATIONS
7373
-----------
7474

75-
Currently cvsserver works over SSH connections for read/write clients, and
76-
over pserver for anonymous CVS access.
77-
7875
CVS clients cannot tag, branch or perform GIT merges.
7976

8077
'git-cvsserver' maps GIT branches to CVS modules. This is very different
@@ -84,7 +81,7 @@ one or more directories.
8481
INSTALLATION
8582
------------
8683

87-
1. If you are going to offer anonymous CVS access via pserver, add a line in
84+
1. If you are going to offer CVS access via pserver, add a line in
8885
/etc/inetd.conf like
8986
+
9087
--
@@ -101,6 +98,38 @@ looks like
10198
cvspserver stream tcp nowait nobody /usr/bin/git-cvsserver git-cvsserver pserver
10299

103100
------
101+
102+
Only anonymous access is provided by pserve by default. To commit you
103+
will have to create pserver accounts, simply add a gitcvs.authdb
104+
setting in the config file of the repositories you want the cvsserver
105+
to allow writes to, for example:
106+
107+
------
108+
109+
[gitcvs]
110+
authdb = /etc/cvsserver/passwd
111+
112+
------
113+
The format of these files is username followed by the crypted password,
114+
for example:
115+
116+
------
117+
myuser:$1Oyx5r9mdGZ2
118+
myuser:$1$BA)@$vbnMJMDym7tA32AamXrm./
119+
------
120+
You can use the 'htpasswd' facility that comes with Apache to make these
121+
files, but Apache's MD5 crypt method differs from the one used by most C
122+
library's crypt() function, so don't use the -m option.
123+
124+
Alternatively you can produce the password with perl's crypt() operator:
125+
-----
126+
perl -e 'my ($user, $pass) = @ARGV; printf "%s:%s\n", $user, crypt($user, $pass)' $USER password
127+
-----
128+
129+
Then provide your password via the pserver method, for example:
130+
------
131+
cvs -d:pserver:someuser:somepassword <at> server/path/repo.git co <HEAD_name>
132+
------
104133
No special setup is needed for SSH access, other than having GIT tools
105134
in the PATH. If you have clients that do not accept the CVS_SERVER
106135
environment variable, you can rename 'git-cvsserver' to `cvs`.

git-cvsserver.perl

Lines changed: 87 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,58 @@
183183
exit 1;
184184
}
185185
$line = <STDIN>; chomp $line;
186-
unless ($line eq 'anonymous') {
187-
print "E Only anonymous user allowed via pserver\n";
188-
print "I HATE YOU\n";
189-
exit 1;
186+
my $user = $line;
187+
$line = <STDIN>; chomp $line;
188+
my $password = $line;
189+
190+
if ($user eq 'anonymous') {
191+
# "A" will be 1 byte, use length instead in case the
192+
# encryption method ever changes (yeah, right!)
193+
if (length($password) > 1 ) {
194+
print "E Don't supply a password for the `anonymous' user\n";
195+
print "I HATE YOU\n";
196+
exit 1;
197+
}
198+
199+
# Fall through to LOVE
200+
} else {
201+
# Trying to authenticate a user
202+
if (not exists $cfg->{gitcvs}->{authdb}) {
203+
print "E the repo config file needs a [gitcvs] section with an 'authdb' parameter set to the filename of the authentication database\n";
204+
print "I HATE YOU\n";
205+
exit 1;
206+
}
207+
208+
my $authdb = $cfg->{gitcvs}->{authdb};
209+
210+
unless (-e $authdb) {
211+
print "E The authentication database specified in [gitcvs.authdb] does not exist\n";
212+
print "I HATE YOU\n";
213+
exit 1;
214+
}
215+
216+
my $auth_ok;
217+
open my $passwd, "<", $authdb or die $!;
218+
while (<$passwd>) {
219+
if (m{^\Q$user\E:(.*)}) {
220+
if (crypt($user, descramble($password)) eq $1) {
221+
$auth_ok = 1;
222+
}
223+
};
224+
}
225+
close $passwd;
226+
227+
unless ($auth_ok) {
228+
print "I HATE YOU\n";
229+
exit 1;
230+
}
231+
232+
# Fall through to LOVE
190233
}
191-
$line = <STDIN>; chomp $line; # validate the password?
234+
235+
# For checking whether the user is anonymous on commit
236+
$state->{user} = $user;
237+
192238
$line = <STDIN>; chomp $line;
193239
unless ($line eq "END $request REQUEST") {
194240
die "E Do not understand $line -- expecting END $request REQUEST\n";
@@ -1271,9 +1317,9 @@ sub req_ci
12711317

12721318
$log->info("req_ci : " . ( defined($data) ? $data : "[NULL]" ));
12731319

1274-
if ( $state->{method} eq 'pserver')
1320+
if ( $state->{method} eq 'pserver' and $state->{user} eq 'anonymous' )
12751321
{
1276-
print "error 1 pserver access cannot commit\n";
1322+
print "error 1 anonymous user cannot commit via pserver\n";
12771323
cleanupWorkTree();
12781324
exit;
12791325
}
@@ -2586,6 +2632,40 @@ sub cvs_author
25862632
$author;
25872633
}
25882634

2635+
2636+
sub descramble
2637+
{
2638+
# This table is from src/scramble.c in the CVS source
2639+
my @SHIFTS = (
2640+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2641+
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2642+
114,120, 53, 79, 96,109, 72,108, 70, 64, 76, 67,116, 74, 68, 87,
2643+
111, 52, 75,119, 49, 34, 82, 81, 95, 65,112, 86,118,110,122,105,
2644+
41, 57, 83, 43, 46,102, 40, 89, 38,103, 45, 50, 42,123, 91, 35,
2645+
125, 55, 54, 66,124,126, 59, 47, 92, 71,115, 78, 88,107,106, 56,
2646+
36,121,117,104,101,100, 69, 73, 99, 63, 94, 93, 39, 37, 61, 48,
2647+
58,113, 32, 90, 44, 98, 60, 51, 33, 97, 62, 77, 84, 80, 85,223,
2648+
225,216,187,166,229,189,222,188,141,249,148,200,184,136,248,190,
2649+
199,170,181,204,138,232,218,183,255,234,220,247,213,203,226,193,
2650+
174,172,228,252,217,201,131,230,197,211,145,238,161,179,160,212,
2651+
207,221,254,173,202,146,224,151,140,196,205,130,135,133,143,246,
2652+
192,159,244,239,185,168,215,144,139,165,180,157,147,186,214,176,
2653+
227,231,219,169,175,156,206,198,129,164,150,210,154,177,134,127,
2654+
182,128,158,208,162,132,167,209,149,241,153,251,237,236,171,195,
2655+
243,233,253,240,194,250,191,155,142,137,245,235,163,242,178,152
2656+
);
2657+
my ($str) = @_;
2658+
2659+
# This should never happen, the same password format (A) bas been
2660+
# used by CVS since the beginning of time
2661+
die "invalid password format $1" unless substr($str, 0, 1) eq 'A';
2662+
2663+
my @str = unpack "C*", substr($str, 1);
2664+
my $ret = join '', map { chr $SHIFTS[$_] } @str;
2665+
return $ret;
2666+
}
2667+
2668+
25892669
package GITCVS::log;
25902670

25912671
####

t/t9400-git-cvsserver-server.sh

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ test_expect_success 'setup' '
4848
git pull secondroot master &&
4949
git clone -q --bare "$WORKDIR/.git" "$SERVERDIR" >/dev/null 2>&1 &&
5050
GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true &&
51-
GIT_DIR="$SERVERDIR" git config gitcvs.logfile "$SERVERDIR/gitcvs.log"
51+
GIT_DIR="$SERVERDIR" git config gitcvs.logfile "$SERVERDIR/gitcvs.log" &&
52+
GIT_DIR="$SERVERDIR" git config gitcvs.authdb "$SERVERDIR/auth.db" &&
53+
echo cvsuser:cvGVEarMLnhlA > "$SERVERDIR/auth.db"
5254
'
5355

5456
# note that cvs doesn't accept absolute pathnames
@@ -94,6 +96,14 @@ git
9496
END VERIFICATION REQUEST
9597
EOF
9698

99+
cat >login-git-ok <<EOF
100+
BEGIN VERIFICATION REQUEST
101+
$SERVERDIR
102+
cvsuser
103+
Ah<Z:yZZ30 e
104+
END VERIFICATION REQUEST
105+
EOF
106+
97107
test_expect_success 'pserver authentication' \
98108
'cat request-anonymous | git-cvsserver pserver >log 2>&1 &&
99109
sed -ne \$p log | grep "^I LOVE YOU\$"'
@@ -107,6 +117,10 @@ test_expect_success 'pserver authentication failure (non-anonymous user)' \
107117
fi &&
108118
sed -ne \$p log | grep "^I HATE YOU\$"'
109119

120+
test_expect_success 'pserver authentication success (non-anonymous user with password)' \
121+
'cat login-git-ok | git-cvsserver pserver >log 2>&1 &&
122+
sed -ne \$p log | grep "^I LOVE YOU\$"'
123+
110124
test_expect_success 'pserver authentication (login)' \
111125
'cat login-anonymous | git-cvsserver pserver >log 2>&1 &&
112126
sed -ne \$p log | grep "^I LOVE YOU\$"'

0 commit comments

Comments
 (0)