{"thread":{"id":"24302","subject":"[PATCH 1/5] git-cvsserver: implement script based pserver auth","startedAt":"2010-07-06T17:34:43Z","lastAt":"2010-07-07T05:28:34Z","messageCount":2,"participants":["Áshin László","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"144926","messageId":"AANLkTilguZZVVstmJvEDudhRP5Ko6m-ajtn9d7nIl3UR@mail.gmail.com","threadId":"24302","inReplyTo":"449772932078145114@unknownmsgid","subject":"[PATCH 1/5] git-cvsserver: implement script based pserver auth","fromName":"Áshin László","fromEmail":"ashinlaszlo@gmail.com","sentAt":"2010-07-06T17:34:43Z","receivedAt":"2010-07-06T17:34:43Z","isPatch":true,"sender":{"key":"ashinlaszlo@gmail.com","avatar":null},"body":"---\n Documentation/git-cvsserver.txt |   42 +++++++++++++++++++++++++++---\n git-cvsserver.perl              |   34 ++++++++++++++++++++++++\n t/t9400-git-cvsserver-server.sh |   55 +++++++++++++++++++++++++++++++++++++++\n 3 files changed, 127 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt\nindex 7004dd2..59c8e5d 100644\n--- a/Documentation/git-cvsserver.txt\n+++ b/Documentation/git-cvsserver.txt\n@@ -100,10 +100,44 @@ looks like\n ------\n\n Only anonymous access is provided by pserve by default. To commit you\n-will have to create pserver accounts, simply add a gitcvs.authdb\n-setting in the config file of the repositories you want the cvsserver\n-to allow writes to, for example:\n+will have to specify an authentication option in the config file.\n+Currently there are two options are available for authentication through\n+pserver in git-cvsserver: one through an authenticator script and an other\n+through a textual authentication database.\n+\n+  a. To use the authentication script based method, simply add a\n+     gitcvs.authscript setting in the config file of the repositories you want\n+     the cvsserver to allow writes to, for example:\n++\n+--\n+------\n+\n+   [gitcvs]\n+    authscript = /usr/local/bin/cvsserver-auth.sh\n+\n+------\n+The file specified here must be executable by the user the git-cvsserver runs\n+under. The script will receive two lines on standard input, the first is the\n+username and the second is the password. It should return 0 if the user was\n+successfully authenticated, and a non-zero value if not.\n+Here is an example for an authentication script which checks the users against\n+active directory:\n+------\n+#!/bin/sh\n+# /usr/local/bin/cvsserver-auth.sh\n\n+read username\n+read password\n+\n+wbinfo -a \"${username}%${password}\"\n+------\n+--\n+\n+  b. To use the authentication database based method, simply add a\n+     gitcvs.authdb setting in the config file of the repositories you want the\n+     cvsserver to allow writes to, for example:\n++\n+--\n ------\n\n   [gitcvs]\n@@ -125,7 +159,7 @@ Alternatively you can produce the password with\nperl's crypt() operator:\n -----\n   perl -e 'my ($user, $pass) = @ARGV; printf \"%s:%s\\n\", $user,\ncrypt($user, $pass)' $USER password\n -----\n-\n+--\n Then provide your password via the pserver method, for example:\n ------\n   cvs -d:pserver:someuser:somepassword <at> server/path/repo.git co <HEAD_name>\ndiff --git a/git-cvsserver.perl b/git-cvsserver.perl\nindex e9f3037..c89d999 100755\n--- a/git-cvsserver.perl\n+++ b/git-cvsserver.perl\n@@ -197,6 +197,40 @@ if ($state->{method} eq 'pserver') {\n        }\n\n        # Fall through to LOVE\n+    } elsif (exists $cfg->{gitcvs}->{authscript} and\n+             exists $cfg->{gitcvs}->{authdb}) {\n+        print \"E Ambiguous configuration of authentication methods. \" .\n+            \"Only one authentication method can be enabled at once\\n\";\n+        print \"I HATE YOU\\n\";\n+        exit 1;\n+    } elsif (exists $cfg->{gitcvs}->{authscript}) {\n+        my $authscript = $cfg->{gitcvs}->{authscript};\n+\n+        unless (-x $authscript) {\n+            print \"E The authentication script specified in \" .\n+                \"[gitcvs.authscript] cannot be executed\\n\";\n+            print \"I HATE YOU\\n\";\n+            exit 1;\n+        }\n+\n+        open my $script_fd, '|-', \"'$authscript'\"\n+            or die \"Couldn't open authentication script '$authscript': $!\";\n+\n+        if (length($password) > 0) {\n+            $password = descramble($password);\n+        }\n+\n+        print $script_fd \"$user\\n\";\n+        print $script_fd \"$password\\n\";\n+        close $script_fd;\n+\n+        unless ($? == 0) {\n+            print \"E External script authentication failed.\\n\";\n+            print \"I HATE YOU\\n\";\n+            exit 1;\n+        }\n+\n+        # Fall through to LOVE\n    } else {\n        # Trying to authenticate a user\n        if (not exists $cfg->{gitcvs}->{authdb}) {\ndiff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh\nindex 8639506..ab5cb26 100755\n--- a/t/t9400-git-cvsserver-server.sh\n+++ b/t/t9400-git-cvsserver-server.sh\n@@ -64,6 +64,16 @@ test_expect_success 'basic checkout' \\\n # PSERVER AUTHENTICATION\n #------------------------\n\n+cat >\"$SERVERDIR/authscript.sh\" <<EOF\n+#!/bin/sh\n+read username\n+read password\n+\n+test \"\\$username\" = cvsuser -a \"\\$password\" = cvspassword\n+EOF\n+\n+chmod a+x \"$SERVERDIR/authscript.sh\"\n+\n cat >request-anonymous  <<EOF\n BEGIN AUTH REQUEST\n $SERVERDIR\n@@ -134,6 +144,51 @@ test_expect_success 'pserver authentication\nfailure (login/non-anonymous user)'\n   fi &&\n   sed -ne \\$p log | grep \"^I HATE YOU\\$\"'\n\n+GIT_DIR=\"$SERVERDIR\" git config gitcvs.authscript\n\"$SERVERDIR/authscript.sh\" || exit 1\n+\n+test_expect_success 'pserver authentication failure (both\nauthentication methods)' \\\n+  'if cat request-git | git-cvsserver pserver >log 2>&1\n+   then\n+       false\n+   else\n+       true\n+   fi &&\n+   sed -ne \\$p log | grep \"^I HATE YOU\\$\"'\n+\n+GIT_DIR=\"$SERVERDIR\" git config --unset gitcvs.authdb || exit 1\n+\n+test_expect_success 'pserver authentication (authscript)' \\\n+  'cat request-anonymous | git-cvsserver pserver >log 2>&1 &&\n+   sed -ne \\$p log | grep \"^I LOVE YOU\\$\"'\n+\n+test_expect_success 'pserver authentication failure (authscript,\nnon-anonymous user)' \\\n+  'if cat request-git | git-cvsserver pserver >log 2>&1\n+   then\n+       false\n+   else\n+       true\n+   fi &&\n+   sed -ne \\$p log | grep \"^I HATE YOU\\$\"'\n+\n+test_expect_success 'pserver authentication success (authscript,\nnon-anonymous user with password)' \\\n+  'cat login-git-ok | git-cvsserver pserver >log 2>&1 &&\n+   sed -ne \\$p log | grep \"^I LOVE YOU\\$\"'\n+\n+test_expect_success 'pserver authentication (authscript, login)' \\\n+  'cat login-anonymous | git-cvsserver pserver >log 2>&1 &&\n+   sed -ne \\$p log | grep \"^I LOVE YOU\\$\"'\n+\n+test_expect_success 'pserver authentication failure (authscript,\nlogin/non-anonymous user)' \\\n+  'if cat login-git | git-cvsserver pserver >log 2>&1\n+   then\n+       false\n+   else\n+       true\n+   fi &&\n+   sed -ne \\$p log | grep \"^I HATE YOU\\$\"'\n+\n+GIT_DIR=\"$SERVERDIR\" git config --unset gitcvs.authscript || exit 1\n+GIT_DIR=\"$SERVERDIR\" git config gitcvs.authdb \"$SERVERDIR/auth.db\" || exit 1\n\n # misuse pserver authentication for testing of req_Root\n\n--\n1.7.0.4\n"},{"id":"145001","messageId":"7v39vv273x.fsf@alter.siamese.dyndns.org","threadId":"24302","inReplyTo":"AANLkTilguZZVVstmJvEDudhRP5Ko6m-ajtn9d7nIl3UR@mail.gmail.com","subject":"Re: [PATCH 1/5] git-cvsserver: implement script based pserver auth","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-07-07T05:28:34Z","receivedAt":"2010-07-07T05:28:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Áshin László <ashinlaszlo@gmail.com> writes:\n\n> ---\n\nSign-off?\n\n>  Documentation/git-cvsserver.txt |   42 +++++++++++++++++++++++++++---\n>  git-cvsserver.perl              |   34 ++++++++++++++++++++++++\n>  t/t9400-git-cvsserver-server.sh |   55 +++++++++++++++++++++++++++++++++++++++\n>  3 files changed, 127 insertions(+), 4 deletions(-)\n>\n> diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt\n> index 7004dd2..59c8e5d 100644\n> --- a/Documentation/git-cvsserver.txt\n> +++ b/Documentation/git-cvsserver.txt\n> @@ -100,10 +100,44 @@ looks like\n>  ------\n>\n>  Only anonymous access is provided by pserve by default. To commit you\n\nIt is ok to squash 5/5 here, as that is so trivial.\n\n> -will have to create pserver accounts, simply add a gitcvs.authdb\n> -setting in the config file of the repositories you want the cvsserver\n> -to allow writes to, for example:\n> +will have to specify an authentication option in the config file.\n> +Currently there are two options are available for authentication through\n\ns/options are/options/;\n\n> +pserver in git-cvsserver: one through an authenticator script and an other\n> +through a textual authentication database.\n> +\n> +  a. To use the authentication script based method, simply add a\n> +     gitcvs.authscript setting in the config file of the repositories you want\n> +     the cvsserver to allow writes to, for example:\n\nWhy \"simply\"?  Adding that word does not make the procedure nor the\nexplanation any simpler than it is.  Just drop it.\n\nMore importantly, you should explicitly say what _value_ the variable\nshould be set to, and what it means.  E.g.\n\n\t...method, set the gitcvs.authscript variable to the path of your\n        custom authentication script in the repository.\n\nYou already said that the user needs to specify an auth option to allow\nwrite access, so there is no need to repeat \"you want ... to allow writes\nto\" here.\n\n> +The file specified here must be executable by the user the git-cvsserver runs\n> +under. The script will receive two lines on standard input, the first is the\n\ns/under/as/; s/standard input/the &/;\n\n> +username and the second is the password. It should return 0 if the user was\n> +successfully authenticated, and a non-zero value if not.\n> +Here is an example for an authentication script which checks the users against\n> +active directory:\n> +------\n> +#!/bin/sh\n> +# /usr/local/bin/cvsserver-auth.sh\n>\n> +read username\n> +read password\n> +\n> +wbinfo -a \"${username}%${password}\"\n\nExposing username/password pair on a command line looks like a not-so-good\nexample.  Also it is a bit disturbing to see that wbinfo(1) says:\n\n       -a username%password\n              Attempt to authenticate a user via winbindd.  This  checks\n              both\n              authenticaion methods and reports its results.\n\n              Note\n\n              Do  not  be tempted to use this functionality for\n              authentication\n              in third-party applications. Instead use ntlm_auth(1).\n\n> +  b. To use the authentication database based method, simply add a\n> +     gitcvs.authdb setting in the config file of the repositories you want the\n> +     cvsserver to allow writes to, for example:\n\nLikewise.\n\n> diff --git a/git-cvsserver.perl b/git-cvsserver.perl\n> index e9f3037..c89d999 100755\n> --- a/git-cvsserver.perl\n> +++ b/git-cvsserver.perl\n> @@ -197,6 +197,40 @@ if ($state->{method} eq 'pserver') {\n>         }\n>\n>         # Fall through to LOVE\n> +    } elsif (exists $cfg->{gitcvs}->{authscript} and\n> +             exists $cfg->{gitcvs}->{authdb}) {\n> +        print \"E Ambiguous configuration of authentication methods. \" .\n> +            \"Only one authentication method can be enabled at once\\n\";\n> +        print \"I HATE YOU\\n\";\n> +        exit 1;\n\nHmph.  It is not unconceivable that you would want to use an authscript\nthat gives company or group wide user database, augmented with an authdb\nthat is for the particular repository...  Of course if we do that we would\nneed a way to specify which one wins when both knows about the user.\n\n> +    } elsif (exists $cfg->{gitcvs}->{authscript}) {\n> +        my $authscript = $cfg->{gitcvs}->{authscript};\n> +\n> +        unless (-x $authscript) {\n> +            print \"E The authentication script specified in \" .\n> +                \"[gitcvs.authscript] cannot be executed\\n\";\n> +            print \"I HATE YOU\\n\";\n> +            exit 1;\n> +        }\n> +\n> +        open my $script_fd, '|-', \"'$authscript'\"\n> +            or die \"Couldn't open authentication script '$authscript': $!\";\n> +\n> +        if (length($password) > 0) {\n> +            $password = descramble($password);\n> +        }\n> +\n> +        print $script_fd \"$user\\n\";\n> +        print $script_fd \"$password\\n\";\n> +        close $script_fd;\n\nDon't you need to check the return value of \"close\" here, even if you will\nalso check the value of $? next?\n\n> +        unless ($? == 0) {\n> +            print \"E External script authentication failed.\\n\";\n> +            print \"I HATE YOU\\n\";\n\nI don't think this \"E\" is necessary nor desirable.  Does the existing\npassword database authenticator codepath say \"authentication failed\" like\nthis, when it gets a wrong password?\n\n> @@ -134,6 +144,51 @@ test_expect_success 'pserver authentication\n> failure (login/non-anonymous user)'\n\nCorrupt patch.\n"}]}