git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Authentication support for pserver
@ 2007-12-14  4:08 Ævar Arnfjörð Bjarmason
  2007-12-14  5:32 ` Junio C Hamano
  0 siblings, 1 reply; 25+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2007-12-14  4:08 UTC (permalink / raw)
  To: git; +Cc: martyn, martin

[-- Attachment #1: Type: text/plain, Size: 1285 bytes --]

I've patched git-cvsserver so that it supports pserver authentication as
opposed to only anonymous access. The patch itself works but I haven't
updated the relevant documentation or test cases and won't be able to do
so until after the weekend so I'm submitting what I have for review on
the list.

The pserver user/password database is stored in the config file for each
repository because I didn't know where else to put it, for example:

avar@oe:/tmp/fleh$ cat /tmp/git-test.git/config 
[core]
	repositoryformatversion = 0
	filemode = true
	bare = true

[gitcvs]
    enabled = 1

[gitcvs.users]
    avar = foobar
    whee = whoo

The user can then login/checkout and do other operations with the
user/password set in the config file:

avar@oe:/tmp/fleh$ cvs -d:pserver:whee:whoo@localhost/tmp/git-test.git login
Logging in to :pserver:whee@localhost:2401/tmp/git-test.git
avar@oe:/tmp/fleh$ cvs -d:pserver:whee:oops@localhost/tmp/git-test.git login
Logging in to :pserver:whee@localhost:2401/tmp/git-test.git
The password supplied for user whee was incorrect
cvs login: authorization failed: server localhost rejected access to
    /tmp/git-test.git for user whee

$ cvs -d:pserver:whee:whoo@localhost/tmp/git-test.git co master
cvs checkout: Updating master
U master/.emacs
[...]


[-- Attachment #2: Patch that adds pserver authentication support to git-cvsserver --]
[-- Type: text/plain, Size: 4040 bytes --]

diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index ecded3b..851383b 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -150,12 +150,32 @@ if ($state->{method} eq 'pserver') {
        exit 1;
     }
     $line = <STDIN>; chomp $line;
-    unless ($line eq 'anonymous') {
-       print "E Only anonymous user allowed via pserver\n";
-       print "I HATE YOU\n";
-       exit 1;
+    my $user = $line;
+    $line = <STDIN>; chomp $line;
+    my $password = $line;
+
+    unless ($user eq 'anonymous') {
+        # Trying to authenticate a user
+        if (not exists $cfg->{gitcvs}->{users}) {
+            print "E the repo config file needs a [gitcvs.users] section with user/password key-value pairs\n";
+            print "I HATE YOU\n";
+            exit 1;
+        } elsif (exists $cfg->{gitcvs}->{users} and not exists $cfg->{gitcvs}->{users}->{$user}) {
+            print "E the repo config file has a [gitcvs.users] section but the user $user is not defined in it\n";
+            print "I HATE YOU\n";
+            exit 1;
+        } else {
+            my $descrambled_password = descramble($password);
+            my $cleartext_password = $cfg->{gitcvs}->{users}->{$user};
+            if ($descrambled_password ne $cleartext_password) {
+                print "E The password supplied for user $user was incorrect\n";
+                print "I HATE YOU\n";
+                exit 1;
+            }
+            # else fall through to LOVE
+        }
     }
-    $line = <STDIN>; chomp $line;    # validate the password?
+
     $line = <STDIN>; chomp $line;
     unless ($line eq "END $request REQUEST") {
        die "E Do not understand $line -- expecting END $request REQUEST\n";
@@ -273,7 +293,7 @@ sub req_Root
     }
     foreach my $line ( @gitvars )
     {
-        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver)\.)?([\w-]+)=(.*)$/ );
+        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver|users)\.)?([\w-]+)=(.*)$/ );
         unless ($2) {
             $cfg->{$1}{$3} = $4;
         } else {
@@ -1176,12 +1196,6 @@ sub req_ci
 
     $log->info("req_ci : " . ( defined($data) ? $data : "[NULL]" ));
 
-    if ( $state->{method} eq 'pserver')
-    {
-        print "error 1 pserver access cannot commit\n";
-        exit;
-    }
-
     if ( -e $state->{CVSROOT} . "/index" )
     {
         $log->warn("file 'index' already exists in the git repository");
@@ -2107,6 +2121,41 @@ sub kopts_from_path
     }
 }
 
+
+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 format has been used since
+    # CVS was spawned
+    $str =~ s/^(.)//;
+    die "invalid password format $1" unless $1 eq 'A';
+
+    $str =~ s/(.)/chr $SHIFTS[ord $1]/ge;
+
+    return $str;
+}
+
+
 package GITCVS::log;
 
 ####

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH] Authentication support for pserver
  2007-12-14  4:08 [PATCH] Authentication support for pserver Ævar Arnfjörð Bjarmason
@ 2007-12-14  5:32 ` Junio C Hamano
  2007-12-14  5:44   ` Shawn O. Pearce
  2007-12-14  6:55   ` Ævar Arnfjörð Bjarmason
  0 siblings, 2 replies; 25+ messages in thread
From: Junio C Hamano @ 2007-12-14  5:32 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: git, martyn, martin

avar@cpan.org (Ævar Arnfjörð Bjarmason) writes:

> +    unless ($user eq 'anonymous') {
> +        # Trying to authenticate a user
> +        if (not exists $cfg->{gitcvs}->{users}) {
> +            print "E the repo config file needs a [gitcvs.users] section with user/password key-value pairs\n";
> +            print "I HATE YOU\n";
> +            exit 1;
> +        } elsif (exists $cfg->{gitcvs}->{users} and not exists $cfg->{gitcvs}->{users}->{$user}) {
> +            print "E the repo config file has a [gitcvs.users] section but the user $user is not defined in it\n";
> +            print "I HATE YOU\n";
> +            exit 1;
> +        } else {
> +            my $descrambled_password = descramble($password);
> +            my $cleartext_password = $cfg->{gitcvs}->{users}->{$user};
> +            if ($descrambled_password ne $cleartext_password) {
> +                print "E The password supplied for user $user was incorrect\n";
> +                print "I HATE YOU\n";
> +                exit 1;
> +            }

I do not know what the real pserver does but by sending these E lines in
the latter two different forms back to the client you are leaking
sensitive information, which is probably not what you want (the first
one is Ok, though.  It would help the server administrator to notice
misconfiguration, and until it is corrected nobody would be able to log
in anyway).

Admittedly, the pserver password scrambling is not a real security, but
if we were paranoid, we would probably be even adding random delay in
"no user found" case and "password does not match" case, so that the
client cannot even tell from the response latency if a username exists
at the server.

> @@ -1176,12 +1196,6 @@ sub req_ci
>  
>      $log->info("req_ci : " . ( defined($data) ? $data : "[NULL]" ));
>  
> -    if ( $state->{method} eq 'pserver')
> -    {
> -        print "error 1 pserver access cannot commit\n";
> -        exit;
> -    }
> -

Is this correct?  You are still allowing anonymous pserver access, so
shouldn't you check if this was an anonymous access or authenticated one
and refuse access like before for anonymous people?

> +    my ($str) = @_;
> +
> +    # This should never happen, the same format has been used since
> +    # CVS was spawned
> +    $str =~ s/^(.)//;
> +    die "invalid password format $1" unless $1 eq 'A';

I do not quite understand what "spawn" means in this sentence.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] Authentication support for pserver
  2007-12-14  5:32 ` Junio C Hamano
@ 2007-12-14  5:44   ` Shawn O. Pearce
  2007-12-14  6:55   ` Ævar Arnfjörð Bjarmason
  1 sibling, 0 replies; 25+ messages in thread
From: Shawn O. Pearce @ 2007-12-14  5:44 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Ævar Arnfjörð Bjarmason, git, martyn, martin

Junio C Hamano <gitster@pobox.com> wrote:
> avar@cpan.org (Ævar Arnfjörð Bjarmason) writes:
> > +
> > +    # This should never happen, the same format has been used since
> > +    # CVS was spawned
> > +    $str =~ s/^(.)//;
> > +    die "invalid password format $1" unless $1 eq 'A';
> 
> I do not quite understand what "spawn" means in this sentence.

spawned: since it came from the depths of hell and cursed all
         developers, until the day Git was born.  :-)

-- 
Shawn.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] Authentication support for pserver
  2007-12-14  5:32 ` Junio C Hamano
  2007-12-14  5:44   ` Shawn O. Pearce
@ 2007-12-14  6:55   ` Ævar Arnfjörð Bjarmason
  2007-12-14  8:13     ` Junio C Hamano
  1 sibling, 1 reply; 25+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2007-12-14  6:55 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, martyn, martin

[-- Attachment #1: Type: text/plain, Size: 2833 bytes --]

Junio C Hamano <gitster@pobox.com> writes:

> avar@cpan.org (Ævar Arnfjörð Bjarmason) writes:
>
>> +    unless ($user eq 'anonymous') {
>> +        # Trying to authenticate a user
>> +        if (not exists $cfg->{gitcvs}->{users}) {
>> +            print "E the repo config file needs a [gitcvs.users] section with user/password key-value pairs\n";
>> +            print "I HATE YOU\n";
>> +            exit 1;
>> +        } elsif (exists $cfg->{gitcvs}->{users} and not exists $cfg->{gitcvs}->{users}->{$user}) {
>> +            print "E the repo config file has a [gitcvs.users] section but the user $user is not defined in it\n";
>> +            print "I HATE YOU\n";
>> +            exit 1;
>> +        } else {
>> +            my $descrambled_password = descramble($password);
>> +            my $cleartext_password = $cfg->{gitcvs}->{users}->{$user};
>> +            if ($descrambled_password ne $cleartext_password) {
>> +                print "E The password supplied for user $user was incorrect\n";
>> +                print "I HATE YOU\n";
>> +                exit 1;
>> +            }
>
> I do not know what the real pserver does but by sending these E lines in
> the latter two different forms back to the client you are leaking
> sensitive information, which is probably not what you want (the first
> one is Ok, though.  It would help the server administrator to notice
> misconfiguration, and until it is corrected nobody would be able to log
> in anyway).

I've commented out those two error messages, it now doesn't provide that
info.

> Admittedly, the pserver password scrambling is not a real security, but
> if we were paranoid, we would probably be even adding random delay in
> "no user found" case and "password does not match" case, so that the
> client cannot even tell from the response latency if a username exists
> at the server.
>
>> @@ -1176,12 +1196,6 @@ sub req_ci
>>  
>>      $log->info("req_ci : " . ( defined($data) ? $data : "[NULL]" ));
>>  
>> -    if ( $state->{method} eq 'pserver')
>> -    {
>> -        print "error 1 pserver access cannot commit\n";
>> -        exit;
>> -    }
>> -
>
> Is this correct?  You are still allowing anonymous pserver access, so
> shouldn't you check if this was an anonymous access or authenticated one
> and refuse access like before for anonymous people?

No it's not, oops. Fixed.

>> +    my ($str) = @_;
>> +
>> +    # This should never happen, the same format has been used since
>> +    # CVS was spawned
>> +    $str =~ s/^(.)//;
>> +    die "invalid password format $1" unless $1 eq 'A';
>
> I do not quite understand what "spawn" means in this sentence.

Shawn O. Pearce put it best but I've changed the comment to be more
readable to someone without a odd sense of humor:)


[-- Attachment #2: Fixed git-cvsserver patch --]
[-- Type: text/plain, Size: 5770 bytes --]

diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index 258a62f..5ca84fc 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -69,9 +69,6 @@ plugin. Most functionality works fine with both of these clients.
 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.
 
 git-cvsserver maps GIT branches to CVS modules. This is very different
@@ -81,7 +78,7 @@ one or more directories.
 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
 +
 --
@@ -98,6 +95,22 @@ looks like
    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.users]
+section to the repositories you want to access, for example:
+
+------
+   
+   [gitcvs.users]
+        someuser = somepassword
+        otheruser = otherpassword
+   
+------
+Then provide your password via the pserver method, for example:
+------
+   cvs -d:pserver:someuser:somepassword@server/path/repo.git co <HEAD_name>
+------
 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
 environment variable, you can rename git-cvsserver to cvs.
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index ecded3b..9541049 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -150,12 +150,35 @@ if ($state->{method} eq 'pserver') {
        exit 1;
     }
     $line = <STDIN>; chomp $line;
-    unless ($line eq 'anonymous') {
-       print "E Only anonymous user allowed via pserver\n";
-       print "I HATE YOU\n";
-       exit 1;
+    my $user = $line;
+    $line = <STDIN>; chomp $line;
+    my $password = $line;
+
+    unless ($user eq 'anonymous') {
+        # Trying to authenticate a user
+        if (not exists $cfg->{gitcvs}->{users}) {
+            print "E the repo config file needs a [gitcvs.users] section with user/password key-value pairs\n";
+            print "I HATE YOU\n";
+            exit 1;
+        } elsif (exists $cfg->{gitcvs}->{users} and not exists $cfg->{gitcvs}->{users}->{$user}) {
+            #print "E the repo config file has a [gitcvs.users] section but the user $user is not defined in it\n";
+            print "I HATE YOU\n";
+            exit 1;
+        } else {
+            my $descrambled_password = descramble($password);
+            my $cleartext_password = $cfg->{gitcvs}->{users}->{$user};
+            if ($descrambled_password ne $cleartext_password) {
+                #print "E The password supplied for user $user was incorrect\n";
+                print "I HATE YOU\n";
+                exit 1;
+            }
+            # else 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;
     unless ($line eq "END $request REQUEST") {
        die "E Do not understand $line -- expecting END $request REQUEST\n";
@@ -273,7 +296,7 @@ sub req_Root
     }
     foreach my $line ( @gitvars )
     {
-        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver)\.)?([\w-]+)=(.*)$/ );
+        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver|users)\.)?([\w-]+)=(.*)$/ );
         unless ($2) {
             $cfg->{$1}{$3} = $4;
         } else {
@@ -1176,9 +1199,9 @@ sub req_ci
 
     $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";
         exit;
     }
 
@@ -2107,6 +2130,41 @@ sub kopts_from_path
     }
 }
 
+
+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 beginnin of time
+    $str =~ s/^(.)//;
+    die "invalid password format $1" unless $1 eq 'A';
+
+    $str =~ s/(.)/chr $SHIFTS[ord $1]/ge;
+
+    return $str;
+}
+
+
 package GITCVS::log;
 
 ####

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH] Authentication support for pserver
  2007-12-14  6:55   ` Ævar Arnfjörð Bjarmason
@ 2007-12-14  8:13     ` Junio C Hamano
  2007-12-14 21:08       ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 25+ messages in thread
From: Junio C Hamano @ 2007-12-14  8:13 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: git, martyn, martin

avar@cpan.org (Ævar Arnfjörð Bjarmason) writes:

> diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
> index 258a62f..5ca84fc 100644
> --- a/Documentation/git-cvsserver.txt
> +++ b/Documentation/git-cvsserver.txt

Looks good.  I'll queue only so that I won't lose it and wait for Acks
from Mart[iy]ns.  Please sign off your patch.

Thanks.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] Authentication support for pserver
  2007-12-14  8:13     ` Junio C Hamano
@ 2007-12-14 21:08       ` Ævar Arnfjörð Bjarmason
  2007-12-18  9:41         ` Martin Langhoff
  0 siblings, 1 reply; 25+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2007-12-14 21:08 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, martyn, martin

[-- Attachment #1: Type: text/plain, Size: 181 bytes --]

Junio C Hamano <gitster@pobox.com> writes:

> Looks good.  I'll queue only so that I won't lose it and wait for Acks
> from Mart[iy]ns.  Please sign off your patch.

Will this do?


[-- Attachment #2: signed-off patch to git-cvsserver --]
[-- Type: text/plain, Size: 6200 bytes --]

Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
---
 Documentation/git-cvsserver.txt |   21 +++++++++--
 git-cvsserver.perl              |   74 ++++++++++++++++++++++++++++++++++----
 2 files changed, 83 insertions(+), 12 deletions(-)

diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index 258a62f..5ca84fc 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -69,9 +69,6 @@ plugin. Most functionality works fine with both of these clients.
 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.
 
 git-cvsserver maps GIT branches to CVS modules. This is very different
@@ -81,7 +78,7 @@ one or more directories.
 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
 +
 --
@@ -98,6 +95,22 @@ looks like
    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.users]
+section to the repositories you want to access, for example:
+
+------
+   
+   [gitcvs.users]
+        someuser = somepassword
+        otheruser = otherpassword
+   
+------
+Then provide your password via the pserver method, for example:
+------
+   cvs -d:pserver:someuser:somepassword@server/path/repo.git co <HEAD_name>
+------
 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
 environment variable, you can rename git-cvsserver to cvs.
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index ecded3b..6f08bed 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -150,12 +150,35 @@ if ($state->{method} eq 'pserver') {
        exit 1;
     }
     $line = <STDIN>; chomp $line;
-    unless ($line eq 'anonymous') {
-       print "E Only anonymous user allowed via pserver\n";
-       print "I HATE YOU\n";
-       exit 1;
+    my $user = $line;
+    $line = <STDIN>; chomp $line;
+    my $password = $line;
+
+    unless ($user eq 'anonymous') {
+        # Trying to authenticate a user
+        if (not exists $cfg->{gitcvs}->{users}) {
+            print "E the repo config file needs a [gitcvs.users] section with user/password key-value pairs\n";
+            print "I HATE YOU\n";
+            exit 1;
+        } elsif (exists $cfg->{gitcvs}->{users} and not exists $cfg->{gitcvs}->{users}->{$user}) {
+            #print "E the repo config file has a [gitcvs.users] section but the user $user is not defined in it\n";
+            print "I HATE YOU\n";
+            exit 1;
+        } else {
+            my $descrambled_password = descramble($password);
+            my $cleartext_password = $cfg->{gitcvs}->{users}->{$user};
+            if ($descrambled_password ne $cleartext_password) {
+                #print "E The password supplied for user $user was incorrect\n";
+                print "I HATE YOU\n";
+                exit 1;
+            }
+            # else 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;
     unless ($line eq "END $request REQUEST") {
        die "E Do not understand $line -- expecting END $request REQUEST\n";
@@ -273,7 +296,7 @@ sub req_Root
     }
     foreach my $line ( @gitvars )
     {
-        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver)\.)?([\w-]+)=(.*)$/ );
+        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver|users)\.)?([\w-]+)=(.*)$/ );
         unless ($2) {
             $cfg->{$1}{$3} = $4;
         } else {
@@ -1176,9 +1199,9 @@ sub req_ci
 
     $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";
         exit;
     }
 
@@ -2107,6 +2130,41 @@ sub kopts_from_path
     }
 }
 
+
+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
+    $str =~ s/^(.)//;
+    die "invalid password format $1" unless $1 eq 'A';
+
+    $str =~ s/(.)/chr $SHIFTS[ord $1]/ge;
+
+    return $str;
+}
+
+
 package GITCVS::log;
 
 ####
-- 
1.5.3.6.gea559


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH] Authentication support for pserver
  2007-12-14 21:08       ` Ævar Arnfjörð Bjarmason
@ 2007-12-18  9:41         ` Martin Langhoff
  2007-12-18 20:39           ` Martin Langhoff
                             ` (2 more replies)
  0 siblings, 3 replies; 25+ messages in thread
From: Martin Langhoff @ 2007-12-18  9:41 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: Junio C Hamano, git, martyn, martin

On Dec 15, 2007 10:08 AM, Ævar Arnfjörð Bjarmason <avar@cpan.org> wrote:
> > Looks good.  I'll queue only so that I won't lose it and wait for Acks
> > from Mart[iy]ns.  Please sign off your patch.

I have been mulling a bit about this change. Seems correct from a code
flow POV. But anon pserver support was added with a lot of
trepidation. Authenticated, write-enabled pserver support fills me
with dread ;-)

A few things that come to mind

 - git/config is very likely to be readable if the site is served via
other means, like dumb http protocol, or git+ssh. So even if the
password scrambling is mickey-mouse. it might make sense to force the
password data to live elsewhere.

 - umasks/file permissions will probably be handled by the underlying
git tools and core.sharedrepository, since we no longer update refs
"manually". So after a bit of thinking, this should not be an issue.

 - I still worry about running cvsserver with an acct that has write
privileges. With anon, all we need write access is the sqlite db, and
that's not even based on user input. And it can be relocated elsewhere
via git/config.

So, wondering about input validation and related matters re-read most
of cvsserver. The only suspicious bit I find is a caller to
transmitfile @ lines 1117, where the 2nd parameter doesn't come from
tempfile() - if a nasty filename sneaked in, we could (perhaps) be in
for a surprise. We do that for diff header prettyness - we could use
--label / -L instead. Will try and prep a patch for that tomorrow if
noone beats me to it (bedtime in nz!).

Hmmm. Does "worried ACK" count as an ACK? Can we add big fat warnings
along the lines of "run this in a locked down environment, pretty
please"?

cheers,



m

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] Authentication support for pserver
  2007-12-18  9:41         ` Martin Langhoff
@ 2007-12-18 20:39           ` Martin Langhoff
       [not found]           ` <46a038f90712181238p7529a02bmde21c89956a3f641@mail.gmail.com>
  2008-03-07  0:48           ` Ævar Arnfjörð Bjarmason
  2 siblings, 0 replies; 25+ messages in thread
From: Martin Langhoff @ 2007-12-18 20:39 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: Junio C Hamano, git, martyn, martin

On Dec 18, 2007 10:41 PM, Martin Langhoff <martin.langhoff@gmail.com> wrote:
>  - git/config is very likely to be readable if the site is served via
> other means, like dumb http protocol, or git+ssh. So even if the
> password scrambling is mickey-mouse. it might make sense to force the
> password data to live elsewhere.

On this aspect, I see no reason why we wouldn't have the passwords
crypt()ed or SHA1'd. Perl includes crypt() in the default
distribution, so it wouldn't add any dependency.

The protocol may be ROT13'ing the passwords, but we don't have to
double-ROT13 them in our storage format ;-)

cheers,


martin

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] Authentication support for pserver
       [not found]           ` <46a038f90712181238p7529a02bmde21c89956a3f641@mail.gmail.com>
@ 2007-12-18 21:10             ` Ævar Arnfjörð Bjarmason
  2007-12-18 21:37               ` Junio C Hamano
  0 siblings, 1 reply; 25+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2007-12-18 21:10 UTC (permalink / raw)
  To: Martin Langhoff; +Cc: Ævar Arnfjörð Bjarmason, git

On Dec 18, 2007 8:38 PM, Martin Langhoff <martin.langhoff@gmail.com> wrote:
> On Dec 18, 2007 10:41 PM, Martin Langhoff <martin.langhoff@gmail.com> wrote:
> >  - git/config is very likely to be readable if the site is served via
> > other means, like dumb http protocol, or git+ssh. So even if the
> > password scrambling is mickey-mouse. it might make sense to force the
> > password data to live elsewhere.
>
> On this aspect, I see no reason why we wouldn't have the passwords
> crypt()ed or SHA1'd. Perl includes crypt() in the default
> distribution, so it wouldn't add any dependency.

It also includes Digest::SHA in the default distribution as of today:)

I could add another option for allowing users to choose their password
storage, e.g.:

[gitcvs]
    password_storage = plaintext # or sha1, crypt, ...

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] Authentication support for pserver
  2007-12-18 21:10             ` Ævar Arnfjörð Bjarmason
@ 2007-12-18 21:37               ` Junio C Hamano
  0 siblings, 0 replies; 25+ messages in thread
From: Junio C Hamano @ 2007-12-18 21:37 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: Martin Langhoff, Ævar Arnfjörð Bjarmason, git

"Ævar Arnfjörð Bjarmason"  <avarab@gmail.com> writes:

>> On this aspect, I see no reason why we wouldn't have the passwords
>> crypt()ed or SHA1'd. Perl includes crypt() in the default
>> distribution, so it wouldn't add any dependency.
>
> It also includes Digest::SHA in the default distribution as of today:)
>
> I could add another option for allowing users to choose their password
> storage, e.g.:
>
> [gitcvs]
>     password_storage = plaintext # or sha1, crypt, ...

I personally feel that selectable password storage format is going
overboard.  Pick a reasonable one and use it everywhere.

Using some form of crypt is a good idea but then we would need a
separate mode of operation to gitcvs to generate user password.

	$ gitcvs adduser junio
        Password: ******
        Retype password: ******
	Added user 'junio' to .git/config
	$ exit

I personally do not care about deluser or change-password subcommands,
as you can always go directly to .git/config to remove the user and
recreate anew, but adding them might be nice finishing touches.

	$ gitcvs password junio
        New password: ******
        Retype password: ******
	Changed password for user 'junio' in .git/config        
	$ gitcvs deluser junio
        Are you sure you want to remove user 'junio' [y/N]? Y
	Removed user 'junio' from .git/config
	$ exit

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] Authentication support for pserver
  2007-12-18  9:41         ` Martin Langhoff
  2007-12-18 20:39           ` Martin Langhoff
       [not found]           ` <46a038f90712181238p7529a02bmde21c89956a3f641@mail.gmail.com>
@ 2008-03-07  0:48           ` Ævar Arnfjörð Bjarmason
  2008-03-07 16:13             ` Ævar Arnfjörð Bjarmason
  2 siblings, 1 reply; 25+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2008-03-07  0:48 UTC (permalink / raw)
  To: Martin Langhoff; +Cc: Junio C Hamano, git, martyn, martin, avar

[-- Attachment #1: Type: text/plain, Size: 2393 bytes --]

"Martin Langhoff" <martin.langhoff@gmail.com> writes:

> On Dec 15, 2007 10:08 AM, Ævar Arnfjörð Bjarmason <avar@cpan.org> wrote:
>> > Looks good.  I'll queue only so that I won't lose it and wait for Acks
>> > from Mart[iy]ns.  Please sign off your patch.
>
> I have been mulling a bit about this change. Seems correct from a code
> flow POV. But anon pserver support was added with a lot of
> trepidation. Authenticated, write-enabled pserver support fills me
> with dread ;-)
>
> A few things that come to mind
>
>  - git/config is very likely to be readable if the site is served via
> other means, like dumb http protocol, or git+ssh. So even if the
> password scrambling is mickey-mouse. it might make sense to force the
> password data to live elsewhere.
>
>  - umasks/file permissions will probably be handled by the underlying
> git tools and core.sharedrepository, since we no longer update refs
> "manually". So after a bit of thinking, this should not be an issue.
>
>  - I still worry about running cvsserver with an acct that has write
> privileges. With anon, all we need write access is the sqlite db, and
> that's not even based on user input. And it can be relocated elsewhere
> via git/config.
>
> So, wondering about input validation and related matters re-read most
> of cvsserver. The only suspicious bit I find is a caller to
> transmitfile @ lines 1117, where the 2nd parameter doesn't come from
> tempfile() - if a nasty filename sneaked in, we could (perhaps) be in
> for a surprise. We do that for diff header prettyness - we could use
> --label / -L instead. Will try and prep a patch for that tomorrow if
> noone beats me to it (bedtime in nz!).
>
> Hmmm. Does "worried ACK" count as an ACK? Can we add big fat warnings
> along the lines of "run this in a locked down environment, pretty
> please"?

Better late than never, here's a more complete and hopefully final patch
to add authentication support to CVS. Thanks to Sam Vilain for
contributing and kicking me into action.

Now you specify a user:password authentication database in the [gitcvs]
section. The passwords are crypt()-ed and can be produced by htpasswd,
example config file:
    
    [gitcvs]
        enabled = 1
        authdb = /tmp/authdb.htpasswd
    
The patch can be pulled from git://git.nix.is/avar/git

It's also produced below:


[-- Attachment #2: git-format-patch --signoff --stdout origin.. --]
[-- Type: text/x-diff, Size: 15989 bytes --]

>From 5900732b52c3a693bfb36c0bf56e3c5eb83ef65e Mon Sep 17 00:00:00 2001
From: =?utf-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= <avar@cpan.org>
Date: Fri, 14 Dec 2007 08:08:46 +0000
Subject: [PATCH] git-cvsserver: authentication support for pserver
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

Allow git-cvsserver to use authentication over pserver mode.  The
pserver user/password database is stored in the config file for each
repository.

Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
Worriedly-Acked-by: Martin Langhoff <martin.langhoff@gmail.com>
---
 Documentation/git-cvsserver.txt |   21 +++++++++--
 git-cvsserver.perl              |   74 ++++++++++++++++++++++++++++++++++----
 2 files changed, 83 insertions(+), 12 deletions(-)

diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index d3e9993..98183d4 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -69,9 +69,6 @@ plugin. Most functionality works fine with both of these clients.
 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.
 
 git-cvsserver maps GIT branches to CVS modules. This is very different
@@ -81,7 +78,7 @@ one or more directories.
 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
 +
 --
@@ -98,6 +95,22 @@ looks like
    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.users]
+section to the repositories you want to access, for example:
+
+------
+   
+   [gitcvs.users]
+        someuser = somepassword
+        otheruser = otherpassword
+   
+------
+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
 in the PATH. If you have clients that do not accept the CVS_SERVER
 environment variable, you can rename git-cvsserver to cvs.
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index afe3d0b..9bc2ff5 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -150,12 +150,35 @@ if ($state->{method} eq 'pserver') {
        exit 1;
     }
     $line = <STDIN>; chomp $line;
-    unless ($line eq 'anonymous') {
-       print "E Only anonymous user allowed via pserver\n";
-       print "I HATE YOU\n";
-       exit 1;
+    my $user = $line;
+    $line = <STDIN>; chomp $line;
+    my $password = $line;
+
+    unless ($user eq 'anonymous') {
+        # Trying to authenticate a user
+        if (not exists $cfg->{gitcvs}->{users}) {
+            print "E the repo config file needs a [gitcvs.users] section with user/password key-value pairs\n";
+            print "I HATE YOU\n";
+            exit 1;
+        } elsif (exists $cfg->{gitcvs}->{users} and not exists $cfg->{gitcvs}->{users}->{$user}) {
+            #print "E the repo config file has a [gitcvs.users] section but the user $user is not defined in it\n";
+            print "I HATE YOU\n";
+            exit 1;
+        } else {
+            my $descrambled_password = descramble($password);
+            my $cleartext_password = $cfg->{gitcvs}->{users}->{$user};
+            if ($descrambled_password ne $cleartext_password) {
+                #print "E The password supplied for user $user was incorrect\n";
+                print "I HATE YOU\n";
+                exit 1;
+            }
+            # else 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;
     unless ($line eq "END $request REQUEST") {
        die "E Do not understand $line -- expecting END $request REQUEST\n";
@@ -273,7 +296,7 @@ sub req_Root
     }
     foreach my $line ( @gitvars )
     {
-        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver)\.)?([\w-]+)=(.*)$/ );
+        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver|users)\.)?([\w-]+)=(.*)$/ );
         unless ($2) {
             $cfg->{$1}{$3} = $4;
         } else {
@@ -1176,9 +1199,9 @@ sub req_ci
 
     $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";
         exit;
     }
 
@@ -2107,6 +2130,41 @@ sub kopts_from_path
     }
 }
 
+
+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
+    $str =~ s/^(.)//;
+    die "invalid password format $1" unless $1 eq 'A';
+
+    $str =~ s/(.)/chr $SHIFTS[ord $1]/ge;
+
+    return $str;
+}
+
+
 package GITCVS::log;
 
 ####
-- 
1.5.3.rc3.120.g68d422


>From f59c255ed14c5b80d5328f94f6934461cfe454da Mon Sep 17 00:00:00 2001
From: Sam Vilain <sam.vilain@catalyst.net.nz>
Date: Fri, 7 Mar 2008 11:03:14 +1300
Subject: [PATCH] git-cvsserver: use a password file cvsserver pserver

If a git repository is shared via HTTP, the config file is typically
visible.  Use an external file instead.

Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
---
 Documentation/git-cvsserver.txt |   21 ++++++++++++++++-----
 git-cvsserver.perl              |   27 ++++++++++++++-------------
 2 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index 98183d4..c642f12 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -97,16 +97,27 @@ looks like
 ------
 
 Only anonymous access is provided by pserve by default. To commit you
-will have to create pserver accounts, simply add a [gitcvs.users]
-section to the repositories you want to access, for example:
+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.users]
-        someuser = somepassword
-        otheruser = otherpassword
+   [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.
+
 Then provide your password via the pserver method, for example:
 ------
    cvs -d:pserver:someuser:somepassword <at> server/path/repo.git co <HEAD_name>
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index 9bc2ff5..e54cbcd 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -156,24 +156,25 @@ if ($state->{method} eq 'pserver') {
 
     unless ($user eq 'anonymous') {
         # Trying to authenticate a user
-        if (not exists $cfg->{gitcvs}->{users}) {
-            print "E the repo config file needs a [gitcvs.users] section with user/password key-value pairs\n";
+        if (not exists $cfg->{gitcvs}->{authdb}) {
+            print "E the repo config file needs a [gitcvs.authdb] section with a filename\n";
             print "I HATE YOU\n";
             exit 1;
-        } elsif (exists $cfg->{gitcvs}->{users} and not exists $cfg->{gitcvs}->{users}->{$user}) {
-            #print "E the repo config file has a [gitcvs.users] section but the user $user is not defined in it\n";
+        }
+	my $auth_ok;
+	open PASSWD, "<$cfg->{gitcvs}->{authdb}" or die $!;
+	while(<PASSWD>) {
+	    if (m{^\Q$user\E:(.*)}) {
+		if (crypt($user, $1) eq $1) {
+		    $auth_ok = 1;
+		}
+	    };
+	}
+	unless ($auth_ok) {
             print "I HATE YOU\n";
             exit 1;
-        } else {
-            my $descrambled_password = descramble($password);
-            my $cleartext_password = $cfg->{gitcvs}->{users}->{$user};
-            if ($descrambled_password ne $cleartext_password) {
-                #print "E The password supplied for user $user was incorrect\n";
-                print "I HATE YOU\n";
-                exit 1;
-            }
-            # else fall through to LOVE
         }
+        # else fall through to LOVE
     }
 
     # For checking whether the user is anonymous on commit
-- 
1.5.3.rc3.120.g68d422


>From e8b69f313888900447f45ac3a8dceb38bd5c261e Mon Sep 17 00:00:00 2001
From: =?utf-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= <avar@cpan.org>
Date: Thu, 6 Mar 2008 23:43:13 +0000
Subject: [PATCH] Indent the last commit to fit with the rest of the code.

Use lexical filehandles instead of global globs

Close the filehandle after the password database has been read

Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
---
 git-cvsserver.perl |   23 +++++++++++++----------
 1 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index e54cbcd..f956ac9 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -161,16 +161,19 @@ if ($state->{method} eq 'pserver') {
             print "I HATE YOU\n";
             exit 1;
         }
-	my $auth_ok;
-	open PASSWD, "<$cfg->{gitcvs}->{authdb}" or die $!;
-	while(<PASSWD>) {
-	    if (m{^\Q$user\E:(.*)}) {
-		if (crypt($user, $1) eq $1) {
-		    $auth_ok = 1;
-		}
-	    };
-	}
-	unless ($auth_ok) {
+
+        my $auth_ok;
+        open my $passwd, "<", $cfg->{gitcvs}->{authdb} or die $!;
+        while (<$passwd>) {
+            if (m{^\Q$user\E:(.*)}) {
+                if (crypt($user, $1) eq $1) {
+                    $auth_ok = 1;
+                }
+            };
+        }
+        close $passwd;
+
+        unless ($auth_ok) {
             print "I HATE YOU\n";
             exit 1;
         }
-- 
1.5.3.rc3.120.g68d422


>From 90d3468556b46fc649a9408af42ff24ed2e50455 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= <avar@cpan.org>
Date: Fri, 7 Mar 2008 00:06:52 +0000
Subject: [PATCH] Produce an error if the user tries to supply a password for anonymous

Clarify the error message produced when there's no [gitcvs.authdb]

Produce an E error if the authdb doesn't exist instead of spewing $!
to the user

do crypt($user, descramble($pass)) eq $hash; crypt($user, $hash) eq
$hash would accept any password

Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
---
 git-cvsserver.perl |   28 +++++++++++++++++++++++-----
 1 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index f956ac9..aa0299e 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -154,19 +154,36 @@ if ($state->{method} eq 'pserver') {
     $line = <STDIN>; chomp $line;
     my $password = $line;
 
-    unless ($user eq 'anonymous') {
+    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";
+        }
+
+        # 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.authdb] section with a filename\n";
+            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, "<", $cfg->{gitcvs}->{authdb} or die $!;
+        open my $passwd, "<", $authdb or die $!;
         while (<$passwd>) {
             if (m{^\Q$user\E:(.*)}) {
-                if (crypt($user, $1) eq $1) {
+                if (crypt($user, descramble($password)) eq $1) {
                     $auth_ok = 1;
                 }
             };
@@ -177,7 +194,8 @@ if ($state->{method} eq 'pserver') {
             print "I HATE YOU\n";
             exit 1;
         }
-        # else fall through to LOVE
+
+        # Fall through to LOVE
     }
 
     # For checking whether the user is anonymous on commit
-- 
1.5.3.rc3.120.g68d422


>From a55dfa2667da1473199ee70ca6cfd53094001119 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= <avar@cpan.org>
Date: Fri, 7 Mar 2008 00:09:14 +0000
Subject: [PATCH] document a perl snippet to produce passwords for those that don't have htpasswd


Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
---
 Documentation/git-cvsserver.txt |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index c642f12..d410a11 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -118,6 +118,11 @@ 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>
-- 
1.5.3.rc3.120.g68d422


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH] Authentication support for pserver
  2008-03-07  0:48           ` Ævar Arnfjörð Bjarmason
@ 2008-03-07 16:13             ` Ævar Arnfjörð Bjarmason
  2008-06-19 17:38               ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 25+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2008-03-07 16:13 UTC (permalink / raw)
  To: Martin Langhoff; +Cc: Junio C Hamano, git, martyn, martin, avar

[-- Attachment #1: Type: text/plain, Size: 766 bytes --]

avar@cpan.org (Ævar Arnfjörð Bjarmason) writes:

> Better late than never, here's a more complete and hopefully final patch
> to add authentication support to CVS. Thanks to Sam Vilain for
> contributing and kicking me into action.
>
> Now you specify a user:password authentication database in the [gitcvs]
> section. The passwords are crypt()-ed and can be produced by htpasswd,
> example config file:
>     
>     [gitcvs]
>         enabled = 1
>         authdb = /tmp/authdb.htpasswd
>     
> The patch can be pulled from git://git.nix.is/avar/git
>
> It's also produced below:

The patch needed a small fix, I didn't exit(1) after an error
condition[1]. This can also be got at git://git.nix.is/avar/git and is
produced in full below:


[-- Attachment #2: The patch to git-cvsserver --]
[-- Type: text/x-diff, Size: 16861 bytes --]

>From 5900732b52c3a693bfb36c0bf56e3c5eb83ef65e Mon Sep 17 00:00:00 2001
From: =?utf-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= <avar@cpan.org>
Date: Fri, 14 Dec 2007 08:08:46 +0000
Subject: [PATCH] git-cvsserver: authentication support for pserver
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

Allow git-cvsserver to use authentication over pserver mode.  The
pserver user/password database is stored in the config file for each
repository.

Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
Worriedly-Acked-by: Martin Langhoff <martin.langhoff@gmail.com>
---
 Documentation/git-cvsserver.txt |   21 +++++++++--
 git-cvsserver.perl              |   74 ++++++++++++++++++++++++++++++++++----
 2 files changed, 83 insertions(+), 12 deletions(-)

diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index d3e9993..98183d4 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -69,9 +69,6 @@ plugin. Most functionality works fine with both of these clients.
 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.
 
 git-cvsserver maps GIT branches to CVS modules. This is very different
@@ -81,7 +78,7 @@ one or more directories.
 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
 +
 --
@@ -98,6 +95,22 @@ looks like
    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.users]
+section to the repositories you want to access, for example:
+
+------
+   
+   [gitcvs.users]
+        someuser = somepassword
+        otheruser = otherpassword
+   
+------
+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
 in the PATH. If you have clients that do not accept the CVS_SERVER
 environment variable, you can rename git-cvsserver to cvs.
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index afe3d0b..9bc2ff5 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -150,12 +150,35 @@ if ($state->{method} eq 'pserver') {
        exit 1;
     }
     $line = <STDIN>; chomp $line;
-    unless ($line eq 'anonymous') {
-       print "E Only anonymous user allowed via pserver\n";
-       print "I HATE YOU\n";
-       exit 1;
+    my $user = $line;
+    $line = <STDIN>; chomp $line;
+    my $password = $line;
+
+    unless ($user eq 'anonymous') {
+        # Trying to authenticate a user
+        if (not exists $cfg->{gitcvs}->{users}) {
+            print "E the repo config file needs a [gitcvs.users] section with user/password key-value pairs\n";
+            print "I HATE YOU\n";
+            exit 1;
+        } elsif (exists $cfg->{gitcvs}->{users} and not exists $cfg->{gitcvs}->{users}->{$user}) {
+            #print "E the repo config file has a [gitcvs.users] section but the user $user is not defined in it\n";
+            print "I HATE YOU\n";
+            exit 1;
+        } else {
+            my $descrambled_password = descramble($password);
+            my $cleartext_password = $cfg->{gitcvs}->{users}->{$user};
+            if ($descrambled_password ne $cleartext_password) {
+                #print "E The password supplied for user $user was incorrect\n";
+                print "I HATE YOU\n";
+                exit 1;
+            }
+            # else 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;
     unless ($line eq "END $request REQUEST") {
        die "E Do not understand $line -- expecting END $request REQUEST\n";
@@ -273,7 +296,7 @@ sub req_Root
     }
     foreach my $line ( @gitvars )
     {
-        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver)\.)?([\w-]+)=(.*)$/ );
+        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver|users)\.)?([\w-]+)=(.*)$/ );
         unless ($2) {
             $cfg->{$1}{$3} = $4;
         } else {
@@ -1176,9 +1199,9 @@ sub req_ci
 
     $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";
         exit;
     }
 
@@ -2107,6 +2130,41 @@ sub kopts_from_path
     }
 }
 
+
+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
+    $str =~ s/^(.)//;
+    die "invalid password format $1" unless $1 eq 'A';
+
+    $str =~ s/(.)/chr $SHIFTS[ord $1]/ge;
+
+    return $str;
+}
+
+
 package GITCVS::log;
 
 ####
-- 
1.5.3.rc3.120.g68d422


>From f59c255ed14c5b80d5328f94f6934461cfe454da Mon Sep 17 00:00:00 2001
From: Sam Vilain <sam.vilain@catalyst.net.nz>
Date: Fri, 7 Mar 2008 11:03:14 +1300
Subject: [PATCH] git-cvsserver: use a password file cvsserver pserver

If a git repository is shared via HTTP, the config file is typically
visible.  Use an external file instead.

Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
---
 Documentation/git-cvsserver.txt |   21 ++++++++++++++++-----
 git-cvsserver.perl              |   27 ++++++++++++++-------------
 2 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index 98183d4..c642f12 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -97,16 +97,27 @@ looks like
 ------
 
 Only anonymous access is provided by pserve by default. To commit you
-will have to create pserver accounts, simply add a [gitcvs.users]
-section to the repositories you want to access, for example:
+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.users]
-        someuser = somepassword
-        otheruser = otherpassword
+   [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.
+
 Then provide your password via the pserver method, for example:
 ------
    cvs -d:pserver:someuser:somepassword <at> server/path/repo.git co <HEAD_name>
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index 9bc2ff5..e54cbcd 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -156,24 +156,25 @@ if ($state->{method} eq 'pserver') {
 
     unless ($user eq 'anonymous') {
         # Trying to authenticate a user
-        if (not exists $cfg->{gitcvs}->{users}) {
-            print "E the repo config file needs a [gitcvs.users] section with user/password key-value pairs\n";
+        if (not exists $cfg->{gitcvs}->{authdb}) {
+            print "E the repo config file needs a [gitcvs.authdb] section with a filename\n";
             print "I HATE YOU\n";
             exit 1;
-        } elsif (exists $cfg->{gitcvs}->{users} and not exists $cfg->{gitcvs}->{users}->{$user}) {
-            #print "E the repo config file has a [gitcvs.users] section but the user $user is not defined in it\n";
+        }
+	my $auth_ok;
+	open PASSWD, "<$cfg->{gitcvs}->{authdb}" or die $!;
+	while(<PASSWD>) {
+	    if (m{^\Q$user\E:(.*)}) {
+		if (crypt($user, $1) eq $1) {
+		    $auth_ok = 1;
+		}
+	    };
+	}
+	unless ($auth_ok) {
             print "I HATE YOU\n";
             exit 1;
-        } else {
-            my $descrambled_password = descramble($password);
-            my $cleartext_password = $cfg->{gitcvs}->{users}->{$user};
-            if ($descrambled_password ne $cleartext_password) {
-                #print "E The password supplied for user $user was incorrect\n";
-                print "I HATE YOU\n";
-                exit 1;
-            }
-            # else fall through to LOVE
         }
+        # else fall through to LOVE
     }
 
     # For checking whether the user is anonymous on commit
-- 
1.5.3.rc3.120.g68d422


>From e8b69f313888900447f45ac3a8dceb38bd5c261e Mon Sep 17 00:00:00 2001
From: =?utf-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= <avar@cpan.org>
Date: Thu, 6 Mar 2008 23:43:13 +0000
Subject: [PATCH] Indent the last commit to fit with the rest of the code.

Use lexical filehandles instead of global globs

Close the filehandle after the password database has been read

Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
---
 git-cvsserver.perl |   23 +++++++++++++----------
 1 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index e54cbcd..f956ac9 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -161,16 +161,19 @@ if ($state->{method} eq 'pserver') {
             print "I HATE YOU\n";
             exit 1;
         }
-	my $auth_ok;
-	open PASSWD, "<$cfg->{gitcvs}->{authdb}" or die $!;
-	while(<PASSWD>) {
-	    if (m{^\Q$user\E:(.*)}) {
-		if (crypt($user, $1) eq $1) {
-		    $auth_ok = 1;
-		}
-	    };
-	}
-	unless ($auth_ok) {
+
+        my $auth_ok;
+        open my $passwd, "<", $cfg->{gitcvs}->{authdb} or die $!;
+        while (<$passwd>) {
+            if (m{^\Q$user\E:(.*)}) {
+                if (crypt($user, $1) eq $1) {
+                    $auth_ok = 1;
+                }
+            };
+        }
+        close $passwd;
+
+        unless ($auth_ok) {
             print "I HATE YOU\n";
             exit 1;
         }
-- 
1.5.3.rc3.120.g68d422


>From 90d3468556b46fc649a9408af42ff24ed2e50455 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= <avar@cpan.org>
Date: Fri, 7 Mar 2008 00:06:52 +0000
Subject: [PATCH] Produce an error if the user tries to supply a password for anonymous

Clarify the error message produced when there's no [gitcvs.authdb]

Produce an E error if the authdb doesn't exist instead of spewing $!
to the user

do crypt($user, descramble($pass)) eq $hash; crypt($user, $hash) eq
$hash would accept any password

Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
---
 git-cvsserver.perl |   28 +++++++++++++++++++++++-----
 1 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index f956ac9..aa0299e 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -154,19 +154,36 @@ if ($state->{method} eq 'pserver') {
     $line = <STDIN>; chomp $line;
     my $password = $line;
 
-    unless ($user eq 'anonymous') {
+    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";
+        }
+
+        # 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.authdb] section with a filename\n";
+            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, "<", $cfg->{gitcvs}->{authdb} or die $!;
+        open my $passwd, "<", $authdb or die $!;
         while (<$passwd>) {
             if (m{^\Q$user\E:(.*)}) {
-                if (crypt($user, $1) eq $1) {
+                if (crypt($user, descramble($password)) eq $1) {
                     $auth_ok = 1;
                 }
             };
@@ -177,7 +194,8 @@ if ($state->{method} eq 'pserver') {
             print "I HATE YOU\n";
             exit 1;
         }
-        # else fall through to LOVE
+
+        # Fall through to LOVE
     }
 
     # For checking whether the user is anonymous on commit
-- 
1.5.3.rc3.120.g68d422


>From a55dfa2667da1473199ee70ca6cfd53094001119 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= <avar@cpan.org>
Date: Fri, 7 Mar 2008 00:09:14 +0000
Subject: [PATCH] document a perl snippet to produce passwords for those that don't have htpasswd


Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
---
 Documentation/git-cvsserver.txt |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index c642f12..d410a11 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -118,6 +118,11 @@ 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>
-- 
1.5.3.rc3.120.g68d422


>From 60f893bd9fe329bd5cf8ec513d10ec00e85feb2c Mon Sep 17 00:00:00 2001
From: =?utf-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= <avar@cpan.org>
Date: Fri, 7 Mar 2008 16:06:31 +0000
Subject: [PATCH] exit after producing the error about anonymous having a password


Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
---
 git-cvsserver.perl |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index aa0299e..da48ebd 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -160,6 +160,7 @@ if ($state->{method} eq 'pserver') {
         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
-- 
1.5.3.rc3.120.g68d422


[-- Attachment #3: Type: text/plain, Size: 90 bytes --]


1. http://git.nix.is/?p=avar/git;a=commitdiff;h=60f893bd9fe329bd5cf8ec513d10ec00e85feb2c

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH] Authentication support for pserver
  2008-03-07 16:13             ` Ævar Arnfjörð Bjarmason
@ 2008-06-19 17:38               ` Ævar Arnfjörð Bjarmason
  2008-06-19 19:00                 ` Martin Langhoff
  2008-06-19 20:14                 ` Junio C Hamano
  0 siblings, 2 replies; 25+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2008-06-19 17:38 UTC (permalink / raw)
  To: Martin Langhoff; +Cc: Junio C Hamano, git, martyn, martin, avar

avar@cpan.org (Ævar Arnfjörð Bjarmason) writes:

> avar@cpan.org (Ævar Arnfjörð Bjarmason) writes:
>
>> Better late than never, here's a more complete and hopefully final patch
>> to add authentication support to CVS. Thanks to Sam Vilain for
>> contributing and kicking me into action.
>>
>> Now you specify a user:password authentication database in the [gitcvs]
>> section. The passwords are crypt()-ed and can be produced by htpasswd,
>> example config file:
>>     
>>     [gitcvs]
>>         enabled = 1
>>         authdb = /tmp/authdb.htpasswd
>>     
>> The patch can be pulled from git://git.nix.is/avar/git
>>
>> It's also produced below:
>
> The patch needed a small fix, I didn't exit(1) after an error
> condition[1]. This can also be got at git://git.nix.is/avar/git and is
> produced in full below:
>
>
> From 5900732b52c3a693bfb36c0bf56e3c5eb83ef65e Mon Sep 17 00:00:00 2001
> From: =?utf-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= <avar@cpan.org>
> Date: Fri, 14 Dec 2007 08:08:46 +0000
> Subject: [PATCH] git-cvsserver: authentication support for pserver
> MIME-Version: 1.0
> Content-Type: text/plain; charset=utf-8
> Content-Transfer-Encoding: 8bit
>
> Allow git-cvsserver to use authentication over pserver mode.  The
> pserver user/password database is stored in the config file for each
> repository.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
> Worriedly-Acked-by: Martin Langhoff <martin.langhoff@gmail.com>
> ---
>  Documentation/git-cvsserver.txt |   21 +++++++++--
>  git-cvsserver.perl              |   74 ++++++++++++++++++++++++++++++++++----
>  2 files changed, 83 insertions(+), 12 deletions(-)
>
> diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
> index d3e9993..98183d4 100644
> --- a/Documentation/git-cvsserver.txt
> +++ b/Documentation/git-cvsserver.txt
> @@ -69,9 +69,6 @@ plugin. Most functionality works fine with both of these clients.
>  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.
>  
>  git-cvsserver maps GIT branches to CVS modules. This is very different
> @@ -81,7 +78,7 @@ one or more directories.
>  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
>  +
>  --
> @@ -98,6 +95,22 @@ looks like
>     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.users]
> +section to the repositories you want to access, for example:
> +
> +------
> +   
> +   [gitcvs.users]
> +        someuser = somepassword
> +        otheruser = otherpassword
> +   
> +------
> +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
>  in the PATH. If you have clients that do not accept the CVS_SERVER
>  environment variable, you can rename git-cvsserver to cvs.
> diff --git a/git-cvsserver.perl b/git-cvsserver.perl
> index afe3d0b..9bc2ff5 100755
> --- a/git-cvsserver.perl
> +++ b/git-cvsserver.perl
> @@ -150,12 +150,35 @@ if ($state->{method} eq 'pserver') {
>         exit 1;
>      }
>      $line = <STDIN>; chomp $line;
> -    unless ($line eq 'anonymous') {
> -       print "E Only anonymous user allowed via pserver\n";
> -       print "I HATE YOU\n";
> -       exit 1;
> +    my $user = $line;
> +    $line = <STDIN>; chomp $line;
> +    my $password = $line;
> +
> +    unless ($user eq 'anonymous') {
> +        # Trying to authenticate a user
> +        if (not exists $cfg->{gitcvs}->{users}) {
> +            print "E the repo config file needs a [gitcvs.users] section with user/password key-value pairs\n";
> +            print "I HATE YOU\n";
> +            exit 1;
> +        } elsif (exists $cfg->{gitcvs}->{users} and not exists $cfg->{gitcvs}->{users}->{$user}) {
> +            #print "E the repo config file has a [gitcvs.users] section but the user $user is not defined in it\n";
> +            print "I HATE YOU\n";
> +            exit 1;
> +        } else {
> +            my $descrambled_password = descramble($password);
> +            my $cleartext_password = $cfg->{gitcvs}->{users}->{$user};
> +            if ($descrambled_password ne $cleartext_password) {
> +                #print "E The password supplied for user $user was incorrect\n";
> +                print "I HATE YOU\n";
> +                exit 1;
> +            }
> +            # else 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;
>      unless ($line eq "END $request REQUEST") {
>         die "E Do not understand $line -- expecting END $request REQUEST\n";
> @@ -273,7 +296,7 @@ sub req_Root
>      }
>      foreach my $line ( @gitvars )
>      {
> -        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver)\.)?([\w-]+)=(.*)$/ );
> +        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver|users)\.)?([\w-]+)=(.*)$/ );
>          unless ($2) {
>              $cfg->{$1}{$3} = $4;
>          } else {
> @@ -1176,9 +1199,9 @@ sub req_ci
>  
>      $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";
>          exit;
>      }
>  
> @@ -2107,6 +2130,41 @@ sub kopts_from_path
>      }
>  }
>  
> +
> +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
> +    $str =~ s/^(.)//;
> +    die "invalid password format $1" unless $1 eq 'A';
> +
> +    $str =~ s/(.)/chr $SHIFTS[ord $1]/ge;
> +
> +    return $str;
> +}
> +
> +
>  package GITCVS::log;
>  
>  ####
> -- 
> 1.5.3.rc3.120.g68d422
>
>
> From f59c255ed14c5b80d5328f94f6934461cfe454da Mon Sep 17 00:00:00 2001
> From: Sam Vilain <sam.vilain@catalyst.net.nz>
> Date: Fri, 7 Mar 2008 11:03:14 +1300
> Subject: [PATCH] git-cvsserver: use a password file cvsserver pserver
>
> If a git repository is shared via HTTP, the config file is typically
> visible.  Use an external file instead.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
> ---
>  Documentation/git-cvsserver.txt |   21 ++++++++++++++++-----
>  git-cvsserver.perl              |   27 ++++++++++++++-------------
>  2 files changed, 30 insertions(+), 18 deletions(-)
>
> diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
> index 98183d4..c642f12 100644
> --- a/Documentation/git-cvsserver.txt
> +++ b/Documentation/git-cvsserver.txt
> @@ -97,16 +97,27 @@ looks like
>  ------
>  
>  Only anonymous access is provided by pserve by default. To commit you
> -will have to create pserver accounts, simply add a [gitcvs.users]
> -section to the repositories you want to access, for example:
> +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.users]
> -        someuser = somepassword
> -        otheruser = otherpassword
> +   [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.
> +
>  Then provide your password via the pserver method, for example:
>  ------
>     cvs -d:pserver:someuser:somepassword <at> server/path/repo.git co <HEAD_name>
> diff --git a/git-cvsserver.perl b/git-cvsserver.perl
> index 9bc2ff5..e54cbcd 100755
> --- a/git-cvsserver.perl
> +++ b/git-cvsserver.perl
> @@ -156,24 +156,25 @@ if ($state->{method} eq 'pserver') {
>  
>      unless ($user eq 'anonymous') {
>          # Trying to authenticate a user
> -        if (not exists $cfg->{gitcvs}->{users}) {
> -            print "E the repo config file needs a [gitcvs.users] section with user/password key-value pairs\n";
> +        if (not exists $cfg->{gitcvs}->{authdb}) {
> +            print "E the repo config file needs a [gitcvs.authdb] section with a filename\n";
>              print "I HATE YOU\n";
>              exit 1;
> -        } elsif (exists $cfg->{gitcvs}->{users} and not exists $cfg->{gitcvs}->{users}->{$user}) {
> -            #print "E the repo config file has a [gitcvs.users] section but the user $user is not defined in it\n";
> +        }
> +	my $auth_ok;
> +	open PASSWD, "<$cfg->{gitcvs}->{authdb}" or die $!;
> +	while(<PASSWD>) {
> +	    if (m{^\Q$user\E:(.*)}) {
> +		if (crypt($user, $1) eq $1) {
> +		    $auth_ok = 1;
> +		}
> +	    };
> +	}
> +	unless ($auth_ok) {
>              print "I HATE YOU\n";
>              exit 1;
> -        } else {
> -            my $descrambled_password = descramble($password);
> -            my $cleartext_password = $cfg->{gitcvs}->{users}->{$user};
> -            if ($descrambled_password ne $cleartext_password) {
> -                #print "E The password supplied for user $user was incorrect\n";
> -                print "I HATE YOU\n";
> -                exit 1;
> -            }
> -            # else fall through to LOVE
>          }
> +        # else fall through to LOVE
>      }
>  
>      # For checking whether the user is anonymous on commit
> -- 
> 1.5.3.rc3.120.g68d422
>
>
> From e8b69f313888900447f45ac3a8dceb38bd5c261e Mon Sep 17 00:00:00 2001
> From: =?utf-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= <avar@cpan.org>
> Date: Thu, 6 Mar 2008 23:43:13 +0000
> Subject: [PATCH] Indent the last commit to fit with the rest of the code.
>
> Use lexical filehandles instead of global globs
>
> Close the filehandle after the password database has been read
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
> ---
>  git-cvsserver.perl |   23 +++++++++++++----------
>  1 files changed, 13 insertions(+), 10 deletions(-)
>
> diff --git a/git-cvsserver.perl b/git-cvsserver.perl
> index e54cbcd..f956ac9 100755
> --- a/git-cvsserver.perl
> +++ b/git-cvsserver.perl
> @@ -161,16 +161,19 @@ if ($state->{method} eq 'pserver') {
>              print "I HATE YOU\n";
>              exit 1;
>          }
> -	my $auth_ok;
> -	open PASSWD, "<$cfg->{gitcvs}->{authdb}" or die $!;
> -	while(<PASSWD>) {
> -	    if (m{^\Q$user\E:(.*)}) {
> -		if (crypt($user, $1) eq $1) {
> -		    $auth_ok = 1;
> -		}
> -	    };
> -	}
> -	unless ($auth_ok) {
> +
> +        my $auth_ok;
> +        open my $passwd, "<", $cfg->{gitcvs}->{authdb} or die $!;
> +        while (<$passwd>) {
> +            if (m{^\Q$user\E:(.*)}) {
> +                if (crypt($user, $1) eq $1) {
> +                    $auth_ok = 1;
> +                }
> +            };
> +        }
> +        close $passwd;
> +
> +        unless ($auth_ok) {
>              print "I HATE YOU\n";
>              exit 1;
>          }
> -- 
> 1.5.3.rc3.120.g68d422
>
>
> From 90d3468556b46fc649a9408af42ff24ed2e50455 Mon Sep 17 00:00:00 2001
> From: =?utf-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= <avar@cpan.org>
> Date: Fri, 7 Mar 2008 00:06:52 +0000
> Subject: [PATCH] Produce an error if the user tries to supply a password for anonymous
>
> Clarify the error message produced when there's no [gitcvs.authdb]
>
> Produce an E error if the authdb doesn't exist instead of spewing $!
> to the user
>
> do crypt($user, descramble($pass)) eq $hash; crypt($user, $hash) eq
> $hash would accept any password
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
> ---
>  git-cvsserver.perl |   28 +++++++++++++++++++++++-----
>  1 files changed, 23 insertions(+), 5 deletions(-)
>
> diff --git a/git-cvsserver.perl b/git-cvsserver.perl
> index f956ac9..aa0299e 100755
> --- a/git-cvsserver.perl
> +++ b/git-cvsserver.perl
> @@ -154,19 +154,36 @@ if ($state->{method} eq 'pserver') {
>      $line = <STDIN>; chomp $line;
>      my $password = $line;
>  
> -    unless ($user eq 'anonymous') {
> +    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";
> +        }
> +
> +        # 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.authdb] section with a filename\n";
> +            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, "<", $cfg->{gitcvs}->{authdb} or die $!;
> +        open my $passwd, "<", $authdb or die $!;
>          while (<$passwd>) {
>              if (m{^\Q$user\E:(.*)}) {
> -                if (crypt($user, $1) eq $1) {
> +                if (crypt($user, descramble($password)) eq $1) {
>                      $auth_ok = 1;
>                  }
>              };
> @@ -177,7 +194,8 @@ if ($state->{method} eq 'pserver') {
>              print "I HATE YOU\n";
>              exit 1;
>          }
> -        # else fall through to LOVE
> +
> +        # Fall through to LOVE
>      }
>  
>      # For checking whether the user is anonymous on commit
> -- 
> 1.5.3.rc3.120.g68d422
>
>
> From a55dfa2667da1473199ee70ca6cfd53094001119 Mon Sep 17 00:00:00 2001
> From: =?utf-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= <avar@cpan.org>
> Date: Fri, 7 Mar 2008 00:09:14 +0000
> Subject: [PATCH] document a perl snippet to produce passwords for those that don't have htpasswd
>
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
> ---
>  Documentation/git-cvsserver.txt |    5 +++++
>  1 files changed, 5 insertions(+), 0 deletions(-)
>
> diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
> index c642f12..d410a11 100644
> --- a/Documentation/git-cvsserver.txt
> +++ b/Documentation/git-cvsserver.txt
> @@ -118,6 +118,11 @@ 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>
> -- 
> 1.5.3.rc3.120.g68d422
>
>
> From 60f893bd9fe329bd5cf8ec513d10ec00e85feb2c Mon Sep 17 00:00:00 2001
> From: =?utf-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= <avar@cpan.org>
> Date: Fri, 7 Mar 2008 16:06:31 +0000
> Subject: [PATCH] exit after producing the error about anonymous having a password
>
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avar@cpan.org>
> ---
>  git-cvsserver.perl |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/git-cvsserver.perl b/git-cvsserver.perl
> index aa0299e..da48ebd 100755
> --- a/git-cvsserver.perl
> +++ b/git-cvsserver.perl
> @@ -160,6 +160,7 @@ if ($state->{method} eq 'pserver') {
>          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
> -- 
> 1.5.3.rc3.120.g68d422
>
>
>
> 1. http://git.nix.is/?p=avar/git;a=commitdiff;h=60f893bd9fe329bd5cf8ec513d10ec00e85feb2c

It has been over 3 months since I submitted this patch without anyone
acting on it. In absence of comment from the Mart[yi]ns could this
please applied anyway?

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] Authentication support for pserver
  2008-06-19 17:38               ` Ævar Arnfjörð Bjarmason
@ 2008-06-19 19:00                 ` Martin Langhoff
  2008-06-19 19:21                   ` Junio C Hamano
  2008-06-19 20:14                 ` Junio C Hamano
  1 sibling, 1 reply; 25+ messages in thread
From: Martin Langhoff @ 2008-06-19 19:00 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: Junio C Hamano, git, martyn, martin

On Thu, Jun 19, 2008 at 1:38 PM, Ævar Arnfjörð Bjarmason <avar@cpan.org> wrote:
>> 1. http://git.nix.is/?p=avar/git;a=commitdiff;h=60f893bd9fe329bd5cf8ec513d10ec00e85feb2c
>
> It has been over 3 months since I submitted this patch without anyone
> acting on it. In absence of comment from the Mart[yi]ns could this
> please applied anyway?

Sorry. My opinion on this is a mild ACK on the technical front, and a
bit of a frown ("do we really want to offer this?"). Specifically, my
concern goes beyond what you can do against a pserver service - git
hooks can be targeted with this. "Warning: as safe as telnet" ;-)

cheers,



m
-- 
 martin.langhoff@gmail.com
 martin@laptop.org -- School Server Architect
 - ask interesting questions
 - don't get distracted with shiny stuff - working code first
 - http://wiki.laptop.org/go/User:Martinlanghoff

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] Authentication support for pserver
  2008-06-19 19:00                 ` Martin Langhoff
@ 2008-06-19 19:21                   ` Junio C Hamano
  0 siblings, 0 replies; 25+ messages in thread
From: Junio C Hamano @ 2008-06-19 19:21 UTC (permalink / raw)
  To: Martin Langhoff
  Cc: Ævar Arnfjörð Bjarmason, Junio C Hamano, git,
	martyn, martin

"Martin Langhoff" <martin.langhoff@gmail.com> writes:

> On Thu, Jun 19, 2008 at 1:38 PM, Ævar Arnfjörð Bjarmason <avar@cpan.org> wrote:
>>> 1. http://git.nix.is/?p=avar/git;a=commitdiff;h=60f893bd9fe329bd5cf8ec513d10ec00e85feb2c
>>
>> It has been over 3 months since I submitted this patch without anyone
>> acting on it. In absence of comment from the Mart[yi]ns could this
>> please applied anyway?
>
> Sorry. My opinion on this is a mild ACK on the technical front, and a
> bit of a frown ("do we really want to offer this?"). Specifically, my
> concern goes beyond what you can do against a pserver service - git
> hooks can be targeted with this. "Warning: as safe as telnet" ;-)

"As safe as telnet" is Ok as long as it is strictly optional.  What I
would primarily be worried about is if this change is a no-op for existing
users, when they chose not to enable the new feature.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] Authentication support for pserver
  2008-06-19 17:38               ` Ævar Arnfjörð Bjarmason
  2008-06-19 19:00                 ` Martin Langhoff
@ 2008-06-19 20:14                 ` Junio C Hamano
  2010-05-15  2:45                   ` [PATCH 0/6] git-cvsserver: password " Ævar Arnfjörð Bjarmason
                                     ` (6 more replies)
  1 sibling, 7 replies; 25+ messages in thread
From: Junio C Hamano @ 2008-06-19 20:14 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: Martin Langhoff, Junio C Hamano, git, martyn, martin

avar@cpan.org (Ævar Arnfjörð Bjarmason) writes:

> ...
> It has been over 3 months since I submitted this patch without anyone
> acting on it. In absence of comment from the Mart[yi]ns could this
> please applied anyway?

Can you send a patch that can be applied (cf. Documentation/SubmittingPatches)?

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 0/6] git-cvsserver: password support for pserver
  2008-06-19 20:14                 ` Junio C Hamano
@ 2010-05-15  2:45                   ` Ævar Arnfjörð Bjarmason
  2010-05-15  2:45                   ` [PATCH 1/6] git-cvsserver: authentication " Ævar Arnfjörð Bjarmason
                                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 25+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-05-15  2:45 UTC (permalink / raw)
  To: git; +Cc: Sam Vilain, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

This series adds optional pserver authentication support to
git-cvsserver. It's useful in legacy environments that rely on pserver
authentication support, and for various reasons can't easily switch to
ssh-based authentication.

This series was originally submitted in 2007/2008[1] and approved by
Junio[2], it stalled because I didn't follow up[3] on sending it in an
applyable format until now.

Changes since the series was originally submitted:

  - There's now a test for pserver authentication support

  - Fixed the commit message of a few commits & squashed some commits.

  - It now complies with Documentation/SubmittingPatches. I.e. has
    signed-off-by lines.

  - Changed my E-Mail address in the commits.

1. http://lists-archives.org/git/640574-authentication-support-for-pserver.html 
2. http://lists-archives.org/git/640617-authentication-support-for-pserver.html 
3. http://article.gmane.org/gmane.comp.version-control.git/85521/

Sam Vilain (1):
  git-cvsserver: use a password file cvsserver pserver

Ævar Arnfjörð Bjarmason (5):
  git-cvsserver: authentication support for pserver
  git-cvsserver: indent & clean up authdb code
  git-cvsserver: Improved error handling for pserver
  git-cvsserver: document making a password without htpasswd
  git-cvsserver: test for pserver authentication support

 Documentation/git-cvsserver.txt |   37 +++++++++++++--
 git-cvsserver.perl              |   97 +++++++++++++++++++++++++++++++++++---
 t/t9400-git-cvsserver-server.sh |   16 ++++++-
 3 files changed, 137 insertions(+), 13 deletions(-)

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 1/6] git-cvsserver: authentication support for pserver
  2008-06-19 20:14                 ` Junio C Hamano
  2010-05-15  2:45                   ` [PATCH 0/6] git-cvsserver: password " Ævar Arnfjörð Bjarmason
@ 2010-05-15  2:45                   ` Ævar Arnfjörð Bjarmason
  2010-05-15 15:06                     ` [PATCH 1/6 v2] " Ævar Arnfjörð Bjarmason
  2010-05-15  2:46                   ` [PATCH 2/6] git-cvsserver: use a password file cvsserver pserver Ævar Arnfjörð Bjarmason
                                     ` (4 subsequent siblings)
  6 siblings, 1 reply; 25+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-05-15  2:45 UTC (permalink / raw)
  To: git; +Cc: Sam Vilain, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

Allow git-cvsserver to use authentication over pserver mode.  The
pserver user/password database is stored in the config file for each
repository.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Worriedly-Acked-by: Martin Langhoff <martin.langhoff@gmail.com>
---
 Documentation/git-cvsserver.txt |   21 +++++++++--
 git-cvsserver.perl              |   74 ++++++++++++++++++++++++++++++++++----
 2 files changed, 83 insertions(+), 12 deletions(-)

diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index dbb053e..f4e1339 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -72,9 +72,6 @@ plugin. Most functionality works fine with both of these clients.
 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.
 
 'git-cvsserver' maps GIT branches to CVS modules. This is very different
@@ -84,7 +81,7 @@ one or more directories.
 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
 +
 --
@@ -101,6 +98,22 @@ looks like
    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.users]
+section to the repositories you want to access, for example:
+
+------
+   
+   [gitcvs.users]
+        someuser = somepassword
+        otheruser = otherpassword
+   
+------
+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
 in the PATH. If you have clients that do not accept the CVS_SERVER
 environment variable, you can rename 'git-cvsserver' to `cvs`.
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index 13751db..d9a26cb 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -183,12 +183,35 @@ if ($state->{method} eq 'pserver') {
        exit 1;
     }
     $line = <STDIN>; chomp $line;
-    unless ($line eq 'anonymous') {
-       print "E Only anonymous user allowed via pserver\n";
-       print "I HATE YOU\n";
-       exit 1;
+    my $user = $line;
+    $line = <STDIN>; chomp $line;
+    my $password = $line;
+
+    unless ($user eq 'anonymous') {
+        # Trying to authenticate a user
+        if (not exists $cfg->{gitcvs}->{users}) {
+            print "E the repo config file needs a [gitcvs.users] section with user/password key-value pairs\n";
+            print "I HATE YOU\n";
+            exit 1;
+        } elsif (exists $cfg->{gitcvs}->{users} and not exists $cfg->{gitcvs}->{users}->{$user}) {
+            #print "E the repo config file has a [gitcvs.users] section but the user $user is not defined in it\n";
+            print "I HATE YOU\n";
+            exit 1;
+        } else {
+            my $descrambled_password = descramble($password);
+            my $cleartext_password = $cfg->{gitcvs}->{users}->{$user};
+            if ($descrambled_password ne $cleartext_password) {
+                #print "E The password supplied for user $user was incorrect\n";
+                print "I HATE YOU\n";
+                exit 1;
+            }
+            # else 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;
     unless ($line eq "END $request REQUEST") {
        die "E Do not understand $line -- expecting END $request REQUEST\n";
@@ -314,7 +337,7 @@ sub req_Root
     }
     foreach my $line ( @gitvars )
     {
-        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver)\.)?([\w-]+)=(.*)$/ );
+        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver|users)\.)?([\w-]+)=(.*)$/ );
         unless ($2) {
             $cfg->{$1}{$3} = $4;
         } else {
@@ -1271,9 +1294,9 @@ sub req_ci
 
     $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();
         exit;
     }
@@ -2586,6 +2609,41 @@ sub cvs_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
+    $str =~ s/^(.)//;
+    die "invalid password format $1" unless $1 eq 'A';
+
+    $str =~ s/(.)/chr $SHIFTS[ord $1]/ge;
+
+    return $str;
+}
+
+
 package GITCVS::log;
 
 ####
-- 
1.7.1.84.gd92f8

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 2/6] git-cvsserver: use a password file cvsserver pserver
  2008-06-19 20:14                 ` Junio C Hamano
  2010-05-15  2:45                   ` [PATCH 0/6] git-cvsserver: password " Ævar Arnfjörð Bjarmason
  2010-05-15  2:45                   ` [PATCH 1/6] git-cvsserver: authentication " Ævar Arnfjörð Bjarmason
@ 2010-05-15  2:46                   ` Ævar Arnfjörð Bjarmason
  2010-05-15 15:07                     ` [PATCH 2/6 v2] " Ævar Arnfjörð Bjarmason
  2010-05-15  2:46                   ` [PATCH 3/6] git-cvsserver: indent & clean up authdb code Ævar Arnfjörð Bjarmason
                                     ` (3 subsequent siblings)
  6 siblings, 1 reply; 25+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-05-15  2:46 UTC (permalink / raw)
  To: git; +Cc: Sam Vilain, Junio C Hamano

From: Sam Vilain <sam.vilain@catalyst.net.nz>

If a git repository is shared via HTTP, the config file is typically
visible.  Use an external file instead.
---
 Documentation/git-cvsserver.txt |   21 ++++++++++++++++-----
 git-cvsserver.perl              |   27 ++++++++++++++-------------
 2 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index f4e1339..bc2da8c 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -100,16 +100,27 @@ looks like
 ------
 
 Only anonymous access is provided by pserve by default. To commit you
-will have to create pserver accounts, simply add a [gitcvs.users]
-section to the repositories you want to access, for example:
+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.users]
-        someuser = somepassword
-        otheruser = otherpassword
+   [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.
+
 Then provide your password via the pserver method, for example:
 ------
    cvs -d:pserver:someuser:somepassword <at> server/path/repo.git co <HEAD_name>
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index d9a26cb..ca02fba 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -189,24 +189,25 @@ if ($state->{method} eq 'pserver') {
 
     unless ($user eq 'anonymous') {
         # Trying to authenticate a user
-        if (not exists $cfg->{gitcvs}->{users}) {
-            print "E the repo config file needs a [gitcvs.users] section with user/password key-value pairs\n";
+        if (not exists $cfg->{gitcvs}->{authdb}) {
+            print "E the repo config file needs a [gitcvs.authdb] section with a filename\n";
             print "I HATE YOU\n";
             exit 1;
-        } elsif (exists $cfg->{gitcvs}->{users} and not exists $cfg->{gitcvs}->{users}->{$user}) {
-            #print "E the repo config file has a [gitcvs.users] section but the user $user is not defined in it\n";
+        }
+	my $auth_ok;
+	open PASSWD, "<$cfg->{gitcvs}->{authdb}" or die $!;
+	while(<PASSWD>) {
+	    if (m{^\Q$user\E:(.*)}) {
+		if (crypt($user, $1) eq $1) {
+		    $auth_ok = 1;
+		}
+	    };
+	}
+	unless ($auth_ok) {
             print "I HATE YOU\n";
             exit 1;
-        } else {
-            my $descrambled_password = descramble($password);
-            my $cleartext_password = $cfg->{gitcvs}->{users}->{$user};
-            if ($descrambled_password ne $cleartext_password) {
-                #print "E The password supplied for user $user was incorrect\n";
-                print "I HATE YOU\n";
-                exit 1;
-            }
-            # else fall through to LOVE
         }
+        # else fall through to LOVE
     }
 
     # For checking whether the user is anonymous on commit
-- 
1.7.1.84.gd92f8

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 3/6] git-cvsserver: indent & clean up authdb code
  2008-06-19 20:14                 ` Junio C Hamano
                                     ` (2 preceding siblings ...)
  2010-05-15  2:46                   ` [PATCH 2/6] git-cvsserver: use a password file cvsserver pserver Ævar Arnfjörð Bjarmason
@ 2010-05-15  2:46                   ` Ævar Arnfjörð Bjarmason
  2010-05-15  2:46                   ` [PATCH 4/6] git-cvsserver: Improved error handling for pserver Ævar Arnfjörð Bjarmason
                                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 25+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-05-15  2:46 UTC (permalink / raw)
  To: git; +Cc: Sam Vilain, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

 - Indent the last commit to fit with the rest of the code.

 - Use lexical filehandles instead of global globs

 - Close the filehandle after the password database has been read.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-cvsserver.perl |   23 +++++++++++++----------
 1 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index ca02fba..9f63c56 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -194,16 +194,19 @@ if ($state->{method} eq 'pserver') {
             print "I HATE YOU\n";
             exit 1;
         }
-	my $auth_ok;
-	open PASSWD, "<$cfg->{gitcvs}->{authdb}" or die $!;
-	while(<PASSWD>) {
-	    if (m{^\Q$user\E:(.*)}) {
-		if (crypt($user, $1) eq $1) {
-		    $auth_ok = 1;
-		}
-	    };
-	}
-	unless ($auth_ok) {
+
+        my $auth_ok;
+        open my $passwd, "<", $cfg->{gitcvs}->{authdb} or die $!;
+        while (<$passwd>) {
+            if (m{^\Q$user\E:(.*)}) {
+                if (crypt($user, $1) eq $1) {
+                    $auth_ok = 1;
+                }
+            };
+        }
+        close $passwd;
+
+        unless ($auth_ok) {
             print "I HATE YOU\n";
             exit 1;
         }
-- 
1.7.1.84.gd92f8

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 4/6] git-cvsserver: Improved error handling for pserver
  2008-06-19 20:14                 ` Junio C Hamano
                                     ` (3 preceding siblings ...)
  2010-05-15  2:46                   ` [PATCH 3/6] git-cvsserver: indent & clean up authdb code Ævar Arnfjörð Bjarmason
@ 2010-05-15  2:46                   ` Ævar Arnfjörð Bjarmason
  2010-05-15  2:46                   ` [PATCH 5/6] git-cvsserver: document making a password without htpasswd Ævar Arnfjörð Bjarmason
  2010-05-15  2:46                   ` [PATCH 6/6] git-cvsserver: test for pserver authentication support Ævar Arnfjörð Bjarmason
  6 siblings, 0 replies; 25+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-05-15  2:46 UTC (permalink / raw)
  To: git; +Cc: Sam Vilain, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

  - Produce an error if the user tries to supply a password for anonymous

  - Clarify the error message produced when there's no [gitcvs.authdb]

  - Produce an E error if the authdb doesn't exist instead of spewing
    $! to the user

  - do crypt($user, descramble($pass)) eq $hash; crypt($user, $hash)
    eq $hash would accept any password

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 git-cvsserver.perl |   29 ++++++++++++++++++++++++-----
 1 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index 9f63c56..813df76 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -187,19 +187,37 @@ if ($state->{method} eq 'pserver') {
     $line = <STDIN>; chomp $line;
     my $password = $line;
 
-    unless ($user eq 'anonymous') {
+    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.authdb] section with a filename\n";
+            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, "<", $cfg->{gitcvs}->{authdb} or die $!;
+        open my $passwd, "<", $authdb or die $!;
         while (<$passwd>) {
             if (m{^\Q$user\E:(.*)}) {
-                if (crypt($user, $1) eq $1) {
+                if (crypt($user, descramble($password)) eq $1) {
                     $auth_ok = 1;
                 }
             };
@@ -210,7 +228,8 @@ if ($state->{method} eq 'pserver') {
             print "I HATE YOU\n";
             exit 1;
         }
-        # else fall through to LOVE
+
+        # Fall through to LOVE
     }
 
     # For checking whether the user is anonymous on commit
-- 
1.7.1.84.gd92f8

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 5/6] git-cvsserver: document making a password without htpasswd
  2008-06-19 20:14                 ` Junio C Hamano
                                     ` (4 preceding siblings ...)
  2010-05-15  2:46                   ` [PATCH 4/6] git-cvsserver: Improved error handling for pserver Ævar Arnfjörð Bjarmason
@ 2010-05-15  2:46                   ` Ævar Arnfjörð Bjarmason
  2010-05-15  2:46                   ` [PATCH 6/6] git-cvsserver: test for pserver authentication support Ævar Arnfjörð Bjarmason
  6 siblings, 0 replies; 25+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-05-15  2:46 UTC (permalink / raw)
  To: git; +Cc: Sam Vilain, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

This perl snippet is useful for quickly making a password without
htpasswd(1).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-cvsserver.txt |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index bc2da8c..5825787 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -121,6 +121,11 @@ 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>
-- 
1.7.1.84.gd92f8

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 6/6] git-cvsserver: test for pserver authentication support
  2008-06-19 20:14                 ` Junio C Hamano
                                     ` (5 preceding siblings ...)
  2010-05-15  2:46                   ` [PATCH 5/6] git-cvsserver: document making a password without htpasswd Ævar Arnfjörð Bjarmason
@ 2010-05-15  2:46                   ` Ævar Arnfjörð Bjarmason
  6 siblings, 0 replies; 25+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-05-15  2:46 UTC (permalink / raw)
  To: git; +Cc: Sam Vilain, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t9400-git-cvsserver-server.sh |   16 +++++++++++++++-
 1 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh
index daef2d6..437e9b8 100755
--- a/t/t9400-git-cvsserver-server.sh
+++ b/t/t9400-git-cvsserver-server.sh
@@ -48,7 +48,9 @@ test_expect_success 'setup' '
   git pull secondroot master &&
   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 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
@@ -94,6 +96,14 @@ git
 END VERIFICATION REQUEST
 EOF
 
+cat >login-git-ok <<EOF
+BEGIN VERIFICATION REQUEST
+$SERVERDIR
+cvsuser
+Ah<Z:yZZ30 e
+END VERIFICATION REQUEST
+EOF
+
 test_expect_success 'pserver authentication' \
   'cat request-anonymous | git-cvsserver pserver >log 2>&1 &&
    sed -ne \$p log | grep "^I LOVE YOU\$"'
@@ -107,6 +117,10 @@ test_expect_success 'pserver authentication failure (non-anonymous user)' \
    fi &&
    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)' \
   'cat login-anonymous | git-cvsserver pserver >log 2>&1 &&
    sed -ne \$p log | grep "^I LOVE YOU\$"'
-- 
1.7.1.84.gd92f8

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 1/6 v2] git-cvsserver: authentication support for pserver
  2010-05-15  2:45                   ` [PATCH 1/6] git-cvsserver: authentication " Ævar Arnfjörð Bjarmason
@ 2010-05-15 15:06                     ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 25+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-05-15 15:06 UTC (permalink / raw)
  To: git; +Cc: Sam Vilain, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

Allow git-cvsserver to use authentication over pserver mode.  The
pserver user/password database is stored in the config file for each
repository.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Worriedly-Acked-by: Martin Langhoff <martin.langhoff@gmail.com>
---
The descramble() method was potentially broken if anyone had fed it a
non-bytestring. Now it uses unpack() instead of regexes.

 Documentation/git-cvsserver.txt |   21 +++++++++--
 git-cvsserver.perl              |   73 ++++++++++++++++++++++++++++++++++----
 2 files changed, 82 insertions(+), 12 deletions(-)

diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index dbb053e..f4e1339 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -72,9 +72,6 @@ plugin. Most functionality works fine with both of these clients.
 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.
 
 'git-cvsserver' maps GIT branches to CVS modules. This is very different
@@ -84,7 +81,7 @@ one or more directories.
 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
 +
 --
@@ -101,6 +98,22 @@ looks like
    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.users]
+section to the repositories you want to access, for example:
+
+------
+   
+   [gitcvs.users]
+        someuser = somepassword
+        otheruser = otherpassword
+   
+------
+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
 in the PATH. If you have clients that do not accept the CVS_SERVER
 environment variable, you can rename 'git-cvsserver' to `cvs`.
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index 13751db..7097419 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -183,12 +183,35 @@ if ($state->{method} eq 'pserver') {
        exit 1;
     }
     $line = <STDIN>; chomp $line;
-    unless ($line eq 'anonymous') {
-       print "E Only anonymous user allowed via pserver\n";
-       print "I HATE YOU\n";
-       exit 1;
+    my $user = $line;
+    $line = <STDIN>; chomp $line;
+    my $password = $line;
+
+    unless ($user eq 'anonymous') {
+        # Trying to authenticate a user
+        if (not exists $cfg->{gitcvs}->{users}) {
+            print "E the repo config file needs a [gitcvs.users] section with user/password key-value pairs\n";
+            print "I HATE YOU\n";
+            exit 1;
+        } elsif (exists $cfg->{gitcvs}->{users} and not exists $cfg->{gitcvs}->{users}->{$user}) {
+            #print "E the repo config file has a [gitcvs.users] section but the user $user is not defined in it\n";
+            print "I HATE YOU\n";
+            exit 1;
+        } else {
+            my $descrambled_password = descramble($password);
+            my $cleartext_password = $cfg->{gitcvs}->{users}->{$user};
+            if ($descrambled_password ne $cleartext_password) {
+                #print "E The password supplied for user $user was incorrect\n";
+                print "I HATE YOU\n";
+                exit 1;
+            }
+            # else 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;
     unless ($line eq "END $request REQUEST") {
        die "E Do not understand $line -- expecting END $request REQUEST\n";
@@ -314,7 +337,7 @@ sub req_Root
     }
     foreach my $line ( @gitvars )
     {
-        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver)\.)?([\w-]+)=(.*)$/ );
+        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver|users)\.)?([\w-]+)=(.*)$/ );
         unless ($2) {
             $cfg->{$1}{$3} = $4;
         } else {
@@ -1271,9 +1294,9 @@ sub req_ci
 
     $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();
         exit;
     }
@@ -2586,6 +2609,40 @@ sub cvs_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;
 
 ####
-- 
1.7.1.84.gd92f8

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 2/6 v2] git-cvsserver: use a password file cvsserver pserver
  2010-05-15  2:46                   ` [PATCH 2/6] git-cvsserver: use a password file cvsserver pserver Ævar Arnfjörð Bjarmason
@ 2010-05-15 15:07                     ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 25+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-05-15 15:07 UTC (permalink / raw)
  To: git; +Cc: Sam Vilain, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

From: Sam Vilain <sam.vilain@catalyst.net.nz>

If a git repository is shared via HTTP, the config file is typically
visible.  Use an external file instead.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
This patch was missing a removal of the gitcvs.users config key
introduced in the last patch.

 Documentation/git-cvsserver.txt |   21 ++++++++++++++++-----
 git-cvsserver.perl              |   29 +++++++++++++++--------------
 2 files changed, 31 insertions(+), 19 deletions(-)

diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index f4e1339..bc2da8c 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -100,16 +100,27 @@ looks like
 ------
 
 Only anonymous access is provided by pserve by default. To commit you
-will have to create pserver accounts, simply add a [gitcvs.users]
-section to the repositories you want to access, for example:
+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.users]
-        someuser = somepassword
-        otheruser = otherpassword
+   [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.
+
 Then provide your password via the pserver method, for example:
 ------
    cvs -d:pserver:someuser:somepassword <at> server/path/repo.git co <HEAD_name>
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index 7097419..8b97fb8 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -189,24 +189,25 @@ if ($state->{method} eq 'pserver') {
 
     unless ($user eq 'anonymous') {
         # Trying to authenticate a user
-        if (not exists $cfg->{gitcvs}->{users}) {
-            print "E the repo config file needs a [gitcvs.users] section with user/password key-value pairs\n";
+        if (not exists $cfg->{gitcvs}->{authdb}) {
+            print "E the repo config file needs a [gitcvs.authdb] section with a filename\n";
             print "I HATE YOU\n";
             exit 1;
-        } elsif (exists $cfg->{gitcvs}->{users} and not exists $cfg->{gitcvs}->{users}->{$user}) {
-            #print "E the repo config file has a [gitcvs.users] section but the user $user is not defined in it\n";
+        }
+	my $auth_ok;
+	open PASSWD, "<$cfg->{gitcvs}->{authdb}" or die $!;
+	while(<PASSWD>) {
+	    if (m{^\Q$user\E:(.*)}) {
+		if (crypt($user, $1) eq $1) {
+		    $auth_ok = 1;
+		}
+	    };
+	}
+	unless ($auth_ok) {
             print "I HATE YOU\n";
             exit 1;
-        } else {
-            my $descrambled_password = descramble($password);
-            my $cleartext_password = $cfg->{gitcvs}->{users}->{$user};
-            if ($descrambled_password ne $cleartext_password) {
-                #print "E The password supplied for user $user was incorrect\n";
-                print "I HATE YOU\n";
-                exit 1;
-            }
-            # else fall through to LOVE
         }
+        # else fall through to LOVE
     }
 
     # For checking whether the user is anonymous on commit
@@ -337,7 +338,7 @@ sub req_Root
     }
     foreach my $line ( @gitvars )
     {
-        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver|users)\.)?([\w-]+)=(.*)$/ );
+        next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver)\.)?([\w-]+)=(.*)$/ );
         unless ($2) {
             $cfg->{$1}{$3} = $4;
         } else {
-- 
1.7.1.84.gd92f8

^ permalink raw reply related	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2010-05-15 15:08 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-14  4:08 [PATCH] Authentication support for pserver Ævar Arnfjörð Bjarmason
2007-12-14  5:32 ` Junio C Hamano
2007-12-14  5:44   ` Shawn O. Pearce
2007-12-14  6:55   ` Ævar Arnfjörð Bjarmason
2007-12-14  8:13     ` Junio C Hamano
2007-12-14 21:08       ` Ævar Arnfjörð Bjarmason
2007-12-18  9:41         ` Martin Langhoff
2007-12-18 20:39           ` Martin Langhoff
     [not found]           ` <46a038f90712181238p7529a02bmde21c89956a3f641@mail.gmail.com>
2007-12-18 21:10             ` Ævar Arnfjörð Bjarmason
2007-12-18 21:37               ` Junio C Hamano
2008-03-07  0:48           ` Ævar Arnfjörð Bjarmason
2008-03-07 16:13             ` Ævar Arnfjörð Bjarmason
2008-06-19 17:38               ` Ævar Arnfjörð Bjarmason
2008-06-19 19:00                 ` Martin Langhoff
2008-06-19 19:21                   ` Junio C Hamano
2008-06-19 20:14                 ` Junio C Hamano
2010-05-15  2:45                   ` [PATCH 0/6] git-cvsserver: password " Ævar Arnfjörð Bjarmason
2010-05-15  2:45                   ` [PATCH 1/6] git-cvsserver: authentication " Ævar Arnfjörð Bjarmason
2010-05-15 15:06                     ` [PATCH 1/6 v2] " Ævar Arnfjörð Bjarmason
2010-05-15  2:46                   ` [PATCH 2/6] git-cvsserver: use a password file cvsserver pserver Ævar Arnfjörð Bjarmason
2010-05-15 15:07                     ` [PATCH 2/6 v2] " Ævar Arnfjörð Bjarmason
2010-05-15  2:46                   ` [PATCH 3/6] git-cvsserver: indent & clean up authdb code Ævar Arnfjörð Bjarmason
2010-05-15  2:46                   ` [PATCH 4/6] git-cvsserver: Improved error handling for pserver Ævar Arnfjörð Bjarmason
2010-05-15  2:46                   ` [PATCH 5/6] git-cvsserver: document making a password without htpasswd Ævar Arnfjörð Bjarmason
2010-05-15  2:46                   ` [PATCH 6/6] git-cvsserver: test for pserver authentication support Ævar Arnfjörð Bjarmason

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).