{"thread":{"id":"16154","subject":"[RFC PATCH] gitweb: Support filtering projects by .htaccess files.","startedAt":"2008-11-03T16:43:29Z","lastAt":"2008-11-06T19:43:26Z","messageCount":14,"participants":["Alexander Gavrilov","Francis Galiegue","Jakub Narebski"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"94778","messageId":"200811031943.30033.angavrilov@gmail.com","threadId":"16154","inReplyTo":null,"subject":"[RFC PATCH] gitweb: Support filtering projects by .htaccess files.","fromName":"Alexander Gavrilov","fromEmail":"angavrilov@gmail.com","sentAt":"2008-11-03T16:43:29Z","receivedAt":"2008-11-03T16:43:29Z","isPatch":true,"sender":{"key":"angavrilov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42666?v=4"},"body":"Some environments may require selective limiting of read access to\nrepositories. While even dumb http transport supports it through .htaccess\nfiles, gitweb currently does not implement discretionary access control.\n\nThis patch adds a configuration-contolled check that matches simple\n'Reguire user'/'Reguire group' lines in the .htaccess files with the\nauthenticated user name. Using group authentication requires specifying\na path to the Apache group file in the configuration.\n\nUsing htaccess has an additional bonus that the same authentication\ndata can be used both for gitweb and the dumb http transport.\n\nSigned-off-by: Alexander Gavrilov <angavrilov@gmail.com>\n---\n\n\tI also created a gitosis fork that can generate the necessary files:\n\n\t\thttp://repo.or.cz/w/gitosis/httpauth.git\n\n\t-- Alexander\n\n gitweb/INSTALL     |   14 ++++++++++\n gitweb/gitweb.perl |   68 +++++++++++++++++++++++++++++++++++++++++++++++++--\n 2 files changed, 79 insertions(+), 3 deletions(-)\n\ndiff --git a/gitweb/INSTALL b/gitweb/INSTALL\nindex 26967e2..0841db6 100644\n--- a/gitweb/INSTALL\n+++ b/gitweb/INSTALL\n@@ -166,6 +166,20 @@ Gitweb repositories\n   shows repositories only if this file exists in its object database\n   (if directory has the magic file named $export_ok).\n \n+- Finally, it is possible to use primitive .htaccess authentication by\n+  enabling the $check_htaccess variable in the config file. Gitweb\n+  recognizes the following htaccess commands:\n+\n+    Require user name1 name2 ...     # grant access to the listed users\n+    Require group group1 group2 ...  # grant access to the listed groups\n+    Deny from all                    # deny unless overridden by a Require\n+\n+  Access is granted if the currently authenticated user matches one\n+  of the Require lines, or if the file does not contain any of the listed\n+  commands, or if .htaccess does not exist. If the file exists but cannot\n+  be opened, access is denied. To use group authentication you have to\n+  point $auth_group_file to the group list in Apache format.\n+\n Generating projects list using gitweb\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n \ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 63c793e..4b962c3 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -98,6 +98,12 @@ our $export_ok = \"++GITWEB_EXPORT_OK++\";\n # only allow viewing of repositories also shown on the overview page\n our $strict_export = \"++GITWEB_STRICT_EXPORT++\";\n \n+# check basic authentication rules in .htaccess\n+our $check_htaccess  = 0;\n+\n+# name of the file that lists groups for htaccess check\n+our $auth_group_file = \"\";\n+\n # list of git base URLs used for URL to where fetch project from,\n # i.e. full URL is \"$git_base_url/$project\"\n our @git_base_url_list = grep { $_ ne '' } (\"++GITWEB_BASE_URL++\");\n@@ -397,10 +403,64 @@ sub check_head_link {\n \t\t(-l $headfile && readlink($headfile) =~ /^refs\\/heads\\//));\n }\n \n+# set of htaccess groups for the current user\n+our %cur_auth_groups = ();\n+\n+sub find_current_groups($$) {\n+\tmy ($gfile, $user) = @_;\n+\treturn () unless $gfile && $user;\n+\n+\tmy @groups;\n+\topen my $gf, $gfile or return ();\n+\n+\twhile(<$gf>) {\n+\t\tnext unless /^\\s*(\\S+)\\s*:\\s*(\\S.*\\S)\\s*$/;\n+\t\tmy ($grp, $usrs) = ($1, $2);\n+\t\tpush @groups, $grp if grep { $_ eq $user } split (' ', $usrs);\n+\t}\n+\n+\tclose $gf;\n+\treturn @groups;\n+}\n+\n+sub check_htaccess_files($) {\n+\tmy ($dir) = @_;\n+\tmy $user = $cgi->remote_user() || ' ';\n+\n+\twhile (length $dir >= length $projectroot) {\n+\t\tmy $file = \"$dir/.htaccess\";\n+\t\tnext unless -e $file;\n+\t\topen my $htf, $file or return 0;\n+\n+\t\tmy $ok = 0;\n+\t\tmy $need_ok = 0;\n+\t\twhile (<$htf>) {\n+\t\t\tif (/^\\s*Require\\s+user\\s+(\\S.*\\S)\\s*$/i) {\n+\t\t\t\t$ok++ if grep { $_ eq $user; } split (' ', $1);\n+\t\t\t\t$need_ok++;\n+\t\t\t} elsif (/^\\s*Require\\s+group\\s+(\\S.*\\S)\\s*$/i) {\n+\t\t\t\t$ok++ if grep { $cur_auth_groups{$_}; } split(' ', $1);\n+\t\t\t\t$need_ok++;\n+\t\t\t} elsif (/^\\s*Deny\\s+from\\s+all\\s*$/ix) {\n+\t\t\t\t$need_ok++;\n+\t\t\t}\n+\t\t}\n+\t\tclose $htf;\n+\n+\t\treturn $ok if $need_ok;\n+\t\tlast;\n+\t} continue {\n+\t\t$dir =~ s/\\/[^\\/]*$// or last;\n+\t}\n+\n+\treturn 1;\n+}\n+\n sub check_export_ok {\n \tmy ($dir) = @_;\n \treturn (check_head_link($dir) &&\n-\t\t(!$export_ok || -e \"$dir/$export_ok\"));\n+\t\t(!$export_ok || -e \"$dir/$export_ok\") &&\n+\t\t(!$check_htaccess || check_htaccess_files($dir)));\n }\n \n # process alternate names for backward compatibility\n@@ -626,6 +686,9 @@ if (defined $action) {\n \t}\n }\n \n+# compute authenticated groups\n+$cur_auth_groups{$_}++ for find_current_groups($auth_group_file, $cgi->remote_user());\n+\n # parameters which are pathnames\n our $project = $input_params{'project'};\n if (defined $project) {\n@@ -853,8 +916,7 @@ sub validate_project {\n \tmy $input = shift || return undef;\n \tif (!validate_pathname($input) ||\n \t\t!(-d \"$projectroot/$input\") ||\n-\t\t!check_head_link(\"$projectroot/$input\") ||\n-\t\t($export_ok && !(-e \"$projectroot/$input/$export_ok\")) ||\n+\t\t!check_export_ok(\"$projectroot/$input\") ||\n \t\t($strict_export && !project_in_list($input))) {\n \t\treturn undef;\n \t} else {\n-- \n1.6.0.3.15.gb8d36\n"},{"id":"94780","messageId":"200811031754.00545.fg@one2team.net","threadId":"16154","inReplyTo":"200811031943.30033.angavrilov@gmail.com","subject":"Re: [RFC PATCH] gitweb: Support filtering projects by .htaccess files.","fromName":"Francis Galiegue","fromEmail":"fg@one2team.net","sentAt":"2008-11-03T16:54:00Z","receivedAt":"2008-11-03T16:54:00Z","isPatch":true,"sender":{"key":"fg@one2team.net","avatar":null},"body":"Le Monday 03 November 2008 17:43:29, vous avez écrit :\n> Some environments may require selective limiting of read access to\n> repositories. While even dumb http transport supports it through .htaccess\n> files, gitweb currently does not implement discretionary access control.\n> \n> This patch adds a configuration-contolled check that matches simple\n> 'Reguire user'/'Reguire group' lines in the .htaccess files with the\n> authenticated user name. Using group authentication requires specifying\n> a path to the Apache group file in the configuration.\n> \n> Using htaccess has an additional bonus that the same authentication\n> data can be used both for gitweb and the dumb http transport.\n> \n> Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>\n\nIt just seems to me that this is emulating functionality that multiple Web servers already provide...\n\nWhat's more, knowledge about these Web servers are _much_ more widespread than knowledge about gitweb.\n\nWhy reinvent the wheel?\n\nJust a thought,\n-- \nfge\n"},{"id":"94781","messageId":"bb6f213e0811030926n32c1befcj5d9add6378f7dce4@mail.gmail.com","threadId":"16154","inReplyTo":"200811031754.00545.fg@one2team.net","subject":"Re: [RFC PATCH] gitweb: Support filtering projects by .htaccess files.","fromName":"Alexander Gavrilov","fromEmail":"angavrilov@gmail.com","sentAt":"2008-11-03T17:26:44Z","receivedAt":"2008-11-03T17:26:44Z","isPatch":true,"sender":{"key":"angavrilov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42666?v=4"},"body":"On Mon, Nov 3, 2008 at 7:54 PM, Francis Galiegue <fg@one2team.net> wrote:\n> It just seems to me that this is emulating functionality that multiple Web servers already provide...\n>\n> What's more, knowledge about these Web servers are _much_ more widespread than knowledge about gitweb.\n>\n> Why reinvent the wheel?\n\nIf you are speaking of web servers as in 'GitHub', then it is\nirrelevant, because its server software is nonfree.\n\nIf you are speaking of web servers as in 'Apache', then how would it\nknow which files are going to be accessed when it executes\ncgi-bin/gitweb.cgi?p=very/private/project.git to check permissions?\n\nAlexander\n"},{"id":"94782","messageId":"200811031845.46451.fg@one2team.net","threadId":"16154","inReplyTo":"bb6f213e0811030926n32c1befcj5d9add6378f7dce4@mail.gmail.com","subject":"Re: [RFC PATCH] gitweb: Support filtering projects by .htaccess files.","fromName":"Francis Galiegue","fromEmail":"fg@one2team.net","sentAt":"2008-11-03T17:45:46Z","receivedAt":"2008-11-03T17:45:46Z","isPatch":true,"sender":{"key":"fg@one2team.net","avatar":null},"body":"Le Monday 03 November 2008 18:26:44 Alexander Gavrilov, vous avez écrit :\n> On Mon, Nov 3, 2008 at 7:54 PM, Francis Galiegue <fg@one2team.net> wrote:\n> > It just seems to me that this is emulating functionality that multiple Web servers already provide...\n> >\n> > What's more, knowledge about these Web servers are _much_ more widespread than knowledge about gitweb.\n> >\n> > Why reinvent the wheel?\n> \n> If you are speaking of web servers as in 'GitHub', then it is\n> irrelevant, because its server software is nonfree.\n> \n\nI didn't even account for these.\n\n> If you are speaking of web servers as in 'Apache', then how would it\n> know which files are going to be accessed when it executes\n> cgi-bin/gitweb.cgi?p=very/private/project.git to check permissions?\n> \n\nWell, as far as Apache is concerned, it can do:\n\n* basic .htpasswd authentication,\n* LDAP,\n* PAM,\n* SSL certificate check (via mod_ssl),\n* probably others.\n\nPlenty of possibilities.\n\nWell, that's just mho. But if ever I complete my current work on\ngit-cvsimport (or using git2(svn|git)), I'll go for option 2: my LDAP\ndatabase has all the info, and Apache knows about Cache-Control, not\ngitweb...\n\nNOTE: I'm just saying here that your patch is of no use as far as _I_\nam concerned. I'm basically saying that git cannot account for all\nauthentication schemes out there. Neither can Apache, but it supports a\nbuckload of them already.\n\n-- \nfge\n"},{"id":"94792","messageId":"m38ws0fzca.fsf@localhost.localdomain","threadId":"16154","inReplyTo":"200811031845.46451.fg@one2team.net","subject":"Re: [RFC PATCH] gitweb: Support filtering projects by .htaccess files.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-11-03T18:18:56Z","receivedAt":"2008-11-03T18:18:56Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Francis Galiegue <fg@one2team.net> writes:\n> Le Monday 03 November 2008 18:26:44 Alexander Gavrilov, vous avez écrit :\n>> On Mon, Nov 3, 2008 at 7:54 PM, Francis Galiegue <fg@one2team.net> wrote:\n>>>\n>>> It just seems to me that this is emulating functionality that\n>>> multiple Web servers already provide...\n>>>\n>>> What's more, knowledge about these Web servers are _much_ more\n>>> widespread than knowledge about gitweb.\n>>>\n>>> Why reinvent the wheel?\n[...]\n\n>> If you are speaking of web servers as in 'Apache', then how would it\n>> know which files are going to be accessed when it executes\n>> cgi-bin/gitweb.cgi?p=very/private/project.git to check permissions?\n>> \n> \n> Well, as far as Apache is concerned, it can do:\n> \n> * basic .htpasswd authentication,\n> * LDAP,\n> * PAM,\n> * SSL certificate check (via mod_ssl),\n> * probably others.\n> \n> Plenty of possibilities.\n[...]\n\nWell, the question is if Apache (and other web servers used with\ngitweb) can do authentication based on path_info or on query-string.\nBecause it is encoded in gitweb (via $projectroot) where to find git\nrepositories...\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"94794","messageId":"200811031944.03116.fg@one2team.net","threadId":"16154","inReplyTo":"m38ws0fzca.fsf@localhost.localdomain","subject":"Re: [RFC PATCH] gitweb: Support filtering projects by .htaccess files.","fromName":"Francis Galiegue","fromEmail":"fg@one2team.net","sentAt":"2008-11-03T18:44:02Z","receivedAt":"2008-11-03T18:44:02Z","isPatch":true,"sender":{"key":"fg@one2team.net","avatar":null},"body":"Le Monday 03 November 2008 19:18:56 Jakub Narebski, vous avez écrit :\n\n> > \n> > Well, as far as Apache is concerned, it can do:\n> > \n> > * basic .htpasswd authentication,\n> > * LDAP,\n> > * PAM,\n> > * SSL certificate check (via mod_ssl),\n> > * probably others.\n> > \n> > Plenty of possibilities.\n> [...]\n> \n> Well, the question is if Apache (and other web servers used with\n> gitweb) can do authentication based on path_info or on query-string.\n> Because it is encoded in gitweb (via $projectroot) where to find git\n> repositories...\n> \n\nCan you expand on path_info and query-string? Keep in mind that Apache\nhas mod_rewrite, which can rewrite URLs in any way before it gets\nactually sent to the underlying program (whether it be a CGI or\nanything else), even badly (or mischievously).\n\n-- \nfge\n"},{"id":"298930","messageId":"200811032017.47652.jnareb@gmail.com","threadId":"16154","inReplyTo":"200811031944.03116.fg@one2team.net","subject":"Re: [RFC PATCH] gitweb: Support filtering projects by .htaccess files.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-11-03T19:17:47Z","receivedAt":"2008-11-03T19:17:47Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Dnia poniedziałek 3. listopada 2008 19:44, Francis Galiegue napisał:\n> Le Monday 03 November 2008 19:18:56 Jakub Narebski, vous avez écrit :\n\n> > > Well, as far as Apache is concerned, it can do:\n> > > \n> > > * basic .htpasswd authentication,\n> > > * LDAP,\n> > > * PAM,\n> > > * SSL certificate check (via mod_ssl),\n> > > * probably others.\n> > > \n> > > Plenty of possibilities.\n> > [...]\n> > \n> > Well, the question is if Apache (and other web servers used with\n> > gitweb) can do authentication based on path_info or on query-string.\n> > Because it is encoded in gitweb (via $projectroot) where to find git\n> > repositories...\n> > \n> \n> Can you expand on path_info and query-string? Keep in mind that Apache\n> has mod_rewrite, which can rewrite URLs in any way before it gets\n> actually sent to the underlying program (whether it be a CGI or\n> anything else), even badly (or mischievously).\n\nWhat I mean here that the following example gitweb URLs\n\n  http://example.com/gitweb.cgi?p=some/project.git;a=commit;h=HEAD\n  http://example.com/gitweb.cgi/some/project.git/commit/HEAD\n\nwith the following gitweb configuration\n\n  $projectroot = /var/scm\n\nboth refer to git repository (directory) at\n\n  /var/scm/some/project.git\n\nApache (or other web server) would have to somehow decide based on URL\nthat it refers to some project, and based on project and authentication\ndecide whether to grant access to it.\n\n\nWhat is more, and what cannot be done by web server alone, is that we\nwould want to not show projects which you don't have access to in the\n'projects_list' page, i.e. at\n\n  http://example.com/gitweb.cgi\n\n-- \nJakub Narebski\nPoland\n"},{"id":"293739","messageId":"200811032259.03394.fg@one2team.net","threadId":"16154","inReplyTo":"200811032017.47652.jnareb@gmail.com","subject":"Re: [RFC PATCH] gitweb: Support filtering projects by .htaccess files.","fromName":"Francis Galiegue","fromEmail":"fg@one2team.net","sentAt":"2008-11-03T21:59:03Z","receivedAt":"2008-11-03T21:59:03Z","isPatch":true,"sender":{"key":"fg@one2team.net","avatar":null},"body":"Le Monday 03 November 2008 20:17:47 Jakub Narebski, vous avez écrit :\n> Dnia poniedziałek 3. listopada 2008 19:44, Francis Galiegue napisał:\n> > Le Monday 03 November 2008 19:18:56 Jakub Narebski, vous avez écrit :\n> \n> > > > Well, as far as Apache is concerned, it can do:\n> > > > \n> > > > * basic .htpasswd authentication,\n> > > > * LDAP,\n> > > > * PAM,\n> > > > * SSL certificate check (via mod_ssl),\n> > > > * probably others.\n> > > > \n> > > > Plenty of possibilities.\n> > > [...]\n> > > \n> > > Well, the question is if Apache (and other web servers used with\n> > > gitweb) can do authentication based on path_info or on query-string.\n> > > Because it is encoded in gitweb (via $projectroot) where to find git\n> > > repositories...\n> > > \n> > \n> > Can you expand on path_info and query-string? Keep in mind that Apache\n> > has mod_rewrite, which can rewrite URLs in any way before it gets\n> > actually sent to the underlying program (whether it be a CGI or\n> > anything else), even badly (or mischievously).\n> \n> What I mean here that the following example gitweb URLs\n> \n>   http://example.com/gitweb.cgi?p=some/project.git;a=commit;h=HEAD\n>   http://example.com/gitweb.cgi/some/project.git/commit/HEAD\n> \n> with the following gitweb configuration\n> \n>   $projectroot = /var/scm\n> \n> both refer to git repository (directory) at\n> \n>   /var/scm/some/project.git\n> \n> Apache (or other web server) would have to somehow decide based on URL\n> that it refers to some project, and based on project and authentication\n> decide whether to grant access to it.\n> \n> \n> What is more, and what cannot be done by web server alone, is that we\n> would want to not show projects which you don't have access to in the\n> 'projects_list' page, i.e. at\n> \n>   http://example.com/gitweb.cgi\n> \n\nI see the point. Note that the second URL can be converted into the first one with mod_rewrite, and probably the first to the second as well.\n\nAs to what repository is accessible to whom, does gitweb really have an internal mechanism for this? Wouldn't it be \"better\" is privately accessible projects were available on another website to start with?\n\n\n-- \n"},{"id":"94823","messageId":"200811032357.38893.jnareb@gmail.com","threadId":"16154","inReplyTo":"200811031943.30033.angavrilov@gmail.com","subject":"Re: [RFC PATCH] gitweb: Support filtering projects by .htaccess files.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-11-03T22:57:38Z","receivedAt":"2008-11-03T22:57:38Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Nice idea, but for now certainly an RFC\n\nOn Mon, 3 Nov 2008, Alexander Gavrilov wrote:\n\n> Some environments may require selective limiting of read access to\n> repositories. While even dumb http transport supports it through .htaccess\n> files, gitweb currently does not implement discretionary access control.\n> \n> This patch adds a configuration-contolled check that matches simple\n> 'Reguire user'/'Reguire group' lines in the .htaccess files with the\n\nTypo: Reguire -> Require\n\n> authenticated user name. Using group authentication requires specifying\n> a path to the Apache group file in the configuration.\n> \n> Using .htaccess has an additional bonus that the same authentication\n> data can be used both for gitweb and the dumb http transport.\n\nI'm not sure if it wouldn't be a better solution to try to ask web\nserver to do authentication, for example in MOD_PERL case via $r\nobject (if I remember correctly)...\n\n> \n> Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>\n> ---\n> \n> \tI also created a gitosis fork that can generate the necessary files:\n> \n> \t\thttp://repo.or.cz/w/gitosis/httpauth.git\n> \n> \t-- Alexander\n> \n>  gitweb/INSTALL     |   14 ++++++++++\n>  gitweb/gitweb.perl |   68 +++++++++++++++++++++++++++++++++++++++++++++++++--\n>  2 files changed, 79 insertions(+), 3 deletions(-)\n> \n> diff --git a/gitweb/INSTALL b/gitweb/INSTALL\n> index 26967e2..0841db6 100644\n> --- a/gitweb/INSTALL\n> +++ b/gitweb/INSTALL\n> @@ -166,6 +166,20 @@ Gitweb repositories\n>    shows repositories only if this file exists in its object database\n>    (if directory has the magic file named $export_ok).\n>  \n> +- Finally, it is possible to use primitive .htaccess authentication by\n> +  enabling the $check_htaccess variable in the config file. Gitweb\n> +  recognizes the following htaccess commands:\n> +\n> +    Require user name1 name2 ...     # grant access to the listed users\n> +    Require group group1 group2 ...  # grant access to the listed groups\n> +    Deny from all                    # deny unless overridden by a Require\n> +\n> +  Access is granted if the currently authenticated user matches one\n> +  of the Require lines, or if the file does not contain any of the listed\n> +  commands, or if .htaccess does not exist. If the file exists but cannot\n> +  be opened, access is denied. To use group authentication you have to\n> +  point $auth_group_file to the group list in Apache format.\n> +\n>  Generating projects list using gitweb\n>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n>  \n> diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\n> index 63c793e..4b962c3 100755\n> --- a/gitweb/gitweb.perl\n> +++ b/gitweb/gitweb.perl\n> @@ -98,6 +98,12 @@ our $export_ok = \"++GITWEB_EXPORT_OK++\";\n>  # only allow viewing of repositories also shown on the overview page\n>  our $strict_export = \"++GITWEB_STRICT_EXPORT++\";\n>  \n> +# check basic authentication rules in .htaccess\n> +our $check_htaccess  = 0;\n> +\n> +# name of the file that lists groups for htaccess check\n> +our $auth_group_file = \"\";\n> +\n>  # list of git base URLs used for URL to where fetch project from,\n>  # i.e. full URL is \"$git_base_url/$project\"\n>  our @git_base_url_list = grep { $_ ne '' } (\"++GITWEB_BASE_URL++\");\n> @@ -397,10 +403,64 @@ sub check_head_link {\n>  \t\t(-l $headfile && readlink($headfile) =~ /^refs\\/heads\\//));\n>  }\n>  \n> +# set of htaccess groups for the current user\n> +our %cur_auth_groups = ();\n\nWhy it is hash, and not list? What are the keys, and what are values?\n\n> +\n> +sub find_current_groups($$) {\n\nStyle: I think we prefer not using function prototypes.\n\n> +\tmy ($gfile, $user) = @_;\n> +\treturn () unless $gfile && $user;\n\nStyle: you can use simple \"return\" which means '()' in list context,\nand 'undef' in scalar context.\n\nSo it could have been written as:\n\n+\t($gfile && $user) or return;\n\n\nBut I'd rather someone better in Perl decided...\n\n> +\n> +\tmy @groups;\n> +\topen my $gf, $gfile or return ();\n> +\n> +\twhile(<$gf>) {\n> +\t\tnext unless /^\\s*(\\S+)\\s*:\\s*(\\S.*\\S)\\s*$/;\n> +\t\tmy ($grp, $usrs) = ($1, $2);\n> +\t\tpush @groups, $grp if grep { $_ eq $user } split (' ', $usrs);\n\nWouldn't it be better to use regexp match instead of this split+grep\npipeline?\n\n> +\t}\n> +\n> +\tclose $gf;\n> +\treturn @groups;\n> +}\n> +\n> +sub check_htaccess_files($) {\n\nStyle: I think we prefer not using function prototypes.\n\nThis function lack description: where it tries to find '.htaccess'\nfiles, what does it return, etc.\n\n> +\tmy ($dir) = @_;\n> +\tmy $user = $cgi->remote_user() || ' ';\n\nWhy \"|| ' '\" here?\n\n> +\n> +\twhile (length $dir >= length $projectroot) {\n> +\t\tmy $file = \"$dir/.htaccess\";\n> +\t\tnext unless -e $file;\n> +\t\topen my $htf, $file or return 0;\n> +\n> +\t\tmy $ok = 0;\n> +\t\tmy $need_ok = 0;\n> +\t\twhile (<$htf>) {\n> +\t\t\tif (/^\\s*Require\\s+user\\s+(\\S.*\\S)\\s*$/i) {\n> +\t\t\t\t$ok++ if grep { $_ eq $user; } split (' ', $1);\n> +\t\t\t\t$need_ok++;\n> +\t\t\t} elsif (/^\\s*Require\\s+group\\s+(\\S.*\\S)\\s*$/i) {\n> +\t\t\t\t$ok++ if grep { $cur_auth_groups{$_}; } split(' ', $1);\n> +\t\t\t\t$need_ok++;\n> +\t\t\t} elsif (/^\\s*Deny\\s+from\\s+all\\s*$/ix) {\n> +\t\t\t\t$need_ok++;\n> +\t\t\t}\n> +\t\t}\n> +\t\tclose $htf;\n> +\n> +\t\treturn $ok if $need_ok;\n> +\t\tlast;\n> +\t} continue {\n> +\t\t$dir =~ s/\\/[^\\/]*$// or last;\n> +\t}\n\nFirst, this loop is IMHO very hacky and unclean, using 'continue' block\n(which is not very visible on first glance) to advance through loop.\n\nSecond, while this loop might be good for _single_ repository, it is\ncleanly suboptimal in the case of 'projects_list' action... unless you\nwant to list projects which are not accessible (I think it is the case\nfor accessing static pages / static files).\n\nThird, again there is split+grep (well, this is at least consistent).\n\n> +\n> +\treturn 1;\n> +}\n> +\n>  sub check_export_ok {\n>  \tmy ($dir) = @_;\n>  \treturn (check_head_link($dir) &&\n> -\t\t(!$export_ok || -e \"$dir/$export_ok\"));\n> +\t\t(!$export_ok || -e \"$dir/$export_ok\") &&\n> +\t\t(!$check_htaccess || check_htaccess_files($dir)));\n>  }\n\nO.K. Nice and clean.\n\n>  \n>  # process alternate names for backward compatibility\n> @@ -626,6 +686,9 @@ if (defined $action) {\n>  \t}\n>  }\n>  \n> +# compute authenticated groups\n> +$cur_auth_groups{$_}++ for find_current_groups($auth_group_file, $cgi->remote_user());\n> +\n\nThis is a bit hacky. And I am not sure if its place should be here...\n\n>  # parameters which are pathnames\n>  our $project = $input_params{'project'};\n>  if (defined $project) {\n> @@ -853,8 +916,7 @@ sub validate_project {\n>  \tmy $input = shift || return undef;\n>  \tif (!validate_pathname($input) ||\n>  \t\t!(-d \"$projectroot/$input\") ||\n> -\t\t!check_head_link(\"$projectroot/$input\") ||\n> -\t\t($export_ok && !(-e \"$projectroot/$input/$export_ok\")) ||\n> +\t\t!check_export_ok(\"$projectroot/$input\") ||\n>  \t\t($strict_export && !project_in_list($input))) {\n>  \t\treturn undef;\n>  \t} else {\n\nAnd this is independent change, and should be in separate patch...\n...or should be dropped (I'd have to examine this code better).\n\n> -- \n> 1.6.0.3.15.gb8d36\n> \n\n-- \nJakub Narebski\nPoland\n"},{"id":"94830","messageId":"200811040124.36708.jnareb@gmail.com","threadId":"16154","inReplyTo":"200811032259.03394.fg@one2team.net","subject":"Re: [RFC PATCH] gitweb: Support filtering projects by .htaccess files.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-11-04T00:24:36Z","receivedAt":"2008-11-04T00:24:36Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Mon, 3 Nov 2008, Francis Galiegue wrote:\n> Le Monday 03 November 2008 20:17:47 Jakub Narebski, vous avez écrit :\n> > Dnia poniedziałek 3. listopada 2008 19:44, Francis Galiegue napisał:\n> > > Le Monday 03 November 2008 19:18:56 Jakub Narebski, vous avez écrit :\n \n\n> > > > Well, the question is if Apache (and other web servers used with\n> > > > gitweb) can do authentication based on path_info or on query-string.\n> > > > Because it is encoded in gitweb (via $projectroot) where to find git\n> > > > repositories...\n> > > > \n> > > \n> > > Can you expand on path_info and query-string? Keep in mind that Apache\n> > > has mod_rewrite, which can rewrite URLs in any way before it gets\n> > > actually sent to the underlying program (whether it be a CGI or\n> > > anything else), even badly (or mischievously).\n> > \n> > What I mean here that the following example gitweb URLs\n> > \n> >   http://example.com/gitweb.cgi?p=some/project.git;a=commit;h=HEAD\n> >   http://example.com/gitweb.cgi/some/project.git/commit/HEAD\n> > \n> > with the following gitweb configuration\n> > \n> >   $projectroot = /var/scm\n> > \n> > both refer to git repository (directory) at\n> > \n> >   /var/scm/some/project.git\n> > \n> > Apache (or other web server) would have to somehow decide based on URL\n> > that it refers to some project, and based on project and authentication\n> > decide whether to grant access to it.\n> > \n> > \n> > What is more, and what cannot be done by web server alone, is that we\n> > would want to not show projects which you don't have access to in the\n> > 'projects_list' page, i.e. at\n> > \n> >   http://example.com/gitweb.cgi\n> > \n\nOn the other hand we can decide to display projects for which user\ndoesn't have access (via HTTP authentication) for, just like\ndirectories in *Index* directive can be shown even if they cannot be\naccessed.\n \n> I see the point. Note that the second URL can be converted into the first\n> one with mod_rewrite, and probably the first to the second as well. \n> \n> As to what repository is accessible to whom, does gitweb really have\n> an internal mechanism for this? Wouldn't it be \"better\" is privately\n> accessible projects were available on another website to start with?  \n\nThe problem is that Apache has to decide whether to deny or grant access\nbased on URL, not on path in filesystem. Perhaps that is possible...\n\nAs to having in gitweb mechanism for this... even now gitweb supports\nbare-bones access control in terms of $export_ok. BTW you can have\n not displayed but still accessible.project\n-- \nJakub Narebski\nPoland\n"},{"id":"94866","messageId":"200811040842.26710.fg@one2team.net","threadId":"16154","inReplyTo":"200811040124.36708.jnareb@gmail.com","subject":"Re: [RFC PATCH] gitweb: Support filtering projects by .htaccess files.","fromName":"Francis Galiegue","fromEmail":"fg@one2team.net","sentAt":"2008-11-04T07:42:26Z","receivedAt":"2008-11-04T07:42:26Z","isPatch":true,"sender":{"key":"fg@one2team.net","avatar":null},"body":"Le mardi 04 novembre 2008, Jakub Narebski a écrit :\n[...]\n> > \n> > As to what repository is accessible to whom, does gitweb really have\n> > an internal mechanism for this? Wouldn't it be \"better\" is privately\n> > accessible projects were available on another website to start with?  \n> \n> The problem is that Apache has to decide whether to deny or grant access\n> based on URL, not on path in filesystem. Perhaps that is possible...\n> \n\nIt is, with <Location> or <LocationMatch>. You can use mod_access directives \nwithin these (or mod_auth* ones).\n\n\n-- \nFrancis Galiegue, fg@one2team.com\n[ATTENTION - CHANGEMENT D'ADRESSE !]\n40 av Raymond Poincaré, 75016 PARIS\n+33178945570, +33683877875\n"},{"id":"95008","messageId":"200811060136.23806.angavrilov@gmail.com","threadId":"16154","inReplyTo":"200811032357.38893.jnareb@gmail.com","subject":"Re: [RFC PATCH] gitweb: Support filtering projects by .htaccess files.","fromName":"Alexander Gavrilov","fromEmail":"angavrilov@gmail.com","sentAt":"2008-11-05T22:36:23Z","receivedAt":"2008-11-05T22:36:23Z","isPatch":true,"sender":{"key":"angavrilov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42666?v=4"},"body":"> > authenticated user name. Using group authentication requires specifying\n> > a path to the Apache group file in the configuration.\n> > \n> > Using .htaccess has an additional bonus that the same authentication\n> > data can be used both for gitweb and the dumb http transport.\n> \n> I'm not sure if it wouldn't be a better solution to try to ask web\n> server to do authentication, for example in MOD_PERL case via $r\n> object (if I remember correctly)...\n\nYou are right. I never used mod_perl before, so I didn't know that it's possible.\n\nHow about the following patch, that simply adds a hook, and provides\nan example using mod_perl in the documentation?\n\n--- >8 ---\nSubject: [PATCH] gitweb: Add a per-repository authorization hook.\n\nAdd a configuration variable that can be used to specify an\narbitrary subroutine that will be called in the same situations\nwhere $export_ok is checked, and its return value used\nto decide whether the repository is to be shown.\n\nThis allows the user to implement custom authentication\nschemes, for example by issuing a subrequest through mod_perl\nand checking if Apache will authorize it.\n\nSigned-off-by: Alexander Gavrilov <angavrilov@gmail.com>\n---\n gitweb/INSTALL     |   21 +++++++++++++++++++++\n gitweb/gitweb.perl |    8 +++++++-\n 2 files changed, 28 insertions(+), 1 deletions(-)\n\ndiff --git a/gitweb/INSTALL b/gitweb/INSTALL\nindex 26967e2..fa5917a 100644\n--- a/gitweb/INSTALL\n+++ b/gitweb/INSTALL\n@@ -166,6 +166,27 @@ Gitweb repositories\n   shows repositories only if this file exists in its object database\n   (if directory has the magic file named $export_ok).\n \n+- Finally, it is possible to specify an arbitrary perl subroutine that\n+  will be called for each project to determine if it can be exported.\n+  The subroutine receives an absolute path to the project as its only\n+  parameter.\n+\n+  For example, if you use mod_perl to run the script, and have dumb\n+  http protocol authentication configured for your repositories, you\n+  can use the following hook to allow access only if the user is\n+  authorized to read the files:\n+\n+    $export_auth_hook = sub {\n+        use Apache2::SubRequest ();\n+        use Apache2::Const -compile => qw(HTTP_OK);\n+        my $path = \"$_[0]/HEAD\";\n+        my $r    = Apache2::RequestUtil->request;\n+        my $sub  = $r->lookup_file($path);\n+        return $sub->filename eq $path \n+            && $sub->status == Apache2::Const::HTTP_OK;\n+    };\n+\n+\n Generating projects list using gitweb\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n \ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 172ea6b..9329880 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -95,6 +95,11 @@ our $default_projects_order = \"project\";\n # (only effective if this variable evaluates to true)\n our $export_ok = \"++GITWEB_EXPORT_OK++\";\n \n+# show repository only if this subroutine returns true\n+# when given the path to the project, for example:\n+#    sub { return -e \"$_[0]/git-daemon-export-ok\"; }\n+our $export_auth_hook = undef;\n+\n # only allow viewing of repositories also shown on the overview page\n our $strict_export = \"++GITWEB_STRICT_EXPORT++\";\n \n@@ -400,7 +405,8 @@ sub check_head_link {\n sub check_export_ok {\n \tmy ($dir) = @_;\n \treturn (check_head_link($dir) &&\n-\t\t(!$export_ok || -e \"$dir/$export_ok\"));\n+\t\t(!$export_ok || -e \"$dir/$export_ok\") &&\n+\t\t(!$export_auth_hook || $export_auth_hook->($dir)));\n }\n \n # process alternate names for backward compatibility\n-- \ntg: (0d4f9de..) t/authenticate/hook (depends on: t/authenticate/unify-exportok)\n"},{"id":"95015","messageId":"200811060026.59340.jnareb@gmail.com","threadId":"16154","inReplyTo":"200811060136.23806.angavrilov@gmail.com","subject":"Re: [RFC PATCH] gitweb: Support filtering projects by .htaccess files.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-11-05T23:26:58Z","receivedAt":"2008-11-05T23:26:58Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Alexander Gavrilov wrote:\n \n> How about the following patch, that simply adds a hook, and provides\n> an example using mod_perl in the documentation?\n\nVery nice, simple yet powerfull solution.\n \n> --- >8 ---\n> Subject: [PATCH] gitweb: Add a per-repository authorization hook.\n> \n> Add a configuration variable that can be used to specify an\n> arbitrary subroutine that will be called in the same situations\n> where $export_ok is checked, and its return value used\n> to decide whether the repository is to be shown.\n> \n> This allows the user to implement custom authentication\n> schemes, for example by issuing a subrequest through mod_perl\n> and checking if Apache will authorize it.\n> \n> Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>\n\nIf somebody could check out example given for this feature, I'd add\nAcked-by: Jakub Narebski <jnareb@gmail.com>\n\n> ---\n>  gitweb/INSTALL     |   21 +++++++++++++++++++++\n>  gitweb/gitweb.perl |    8 +++++++-\n>  2 files changed, 28 insertions(+), 1 deletions(-)\n> \n> diff --git a/gitweb/INSTALL b/gitweb/INSTALL\n> index 26967e2..fa5917a 100644\n> --- a/gitweb/INSTALL\n> +++ b/gitweb/INSTALL\n> @@ -166,6 +166,27 @@ Gitweb repositories\n>    shows repositories only if this file exists in its object database\n>    (if directory has the magic file named $export_ok).\n>  \n> +- Finally, it is possible to specify an arbitrary perl subroutine that\n> +  will be called for each project to determine if it can be exported.\n> +  The subroutine receives an absolute path to the project as its only\n> +  parameter.\n> +\n> +  For example, if you use mod_perl to run the script, and have dumb\n> +  http protocol authentication configured for your repositories, you\n> +  can use the following hook to allow access only if the user is\n> +  authorized to read the files:\n> +\n> +    $export_auth_hook = sub {\n> +        use Apache2::SubRequest ();\n> +        use Apache2::Const -compile => qw(HTTP_OK);\n> +        my $path = \"$_[0]/HEAD\";\n> +        my $r    = Apache2::RequestUtil->request;\n> +        my $sub  = $r->lookup_file($path);\n> +        return $sub->filename eq $path \n> +            && $sub->status == Apache2::Const::HTTP_OK;\n> +    };\n\nCan anybody check this? Or was it checked by author?\n\n> +\n> +\n>  Generating projects list using gitweb\n>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n>  \n> diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\n> index 172ea6b..9329880 100755\n> --- a/gitweb/gitweb.perl\n> +++ b/gitweb/gitweb.perl\n> @@ -95,6 +95,11 @@ our $default_projects_order = \"project\";\n>  # (only effective if this variable evaluates to true)\n>  our $export_ok = \"++GITWEB_EXPORT_OK++\";\n>  \n> +# show repository only if this subroutine returns true\n> +# when given the path to the project, for example:\n> +#    sub { return -e \"$_[0]/git-daemon-export-ok\"; }\n> +our $export_auth_hook = undef;\n> +\n\nSimple, yet powerfull. Nice short example.\n\n>  # only allow viewing of repositories also shown on the overview page\n>  our $strict_export = \"++GITWEB_STRICT_EXPORT++\";\n>  \n> @@ -400,7 +405,8 @@ sub check_head_link {\n>  sub check_export_ok {\n>  \tmy ($dir) = @_;\n>  \treturn (check_head_link($dir) &&\n> -\t\t(!$export_ok || -e \"$dir/$export_ok\"));\n> +\t\t(!$export_ok || -e \"$dir/$export_ok\") &&\n> +\t\t(!$export_auth_hook || $export_auth_hook->($dir)));\n\nNice.\n\n>  }\n>  \n>  # process alternate names for backward compatibility\n> -- \n> tg: (0d4f9de..) t/authenticate/hook (depends on: t/authenticate/unify-exportok)\n> \n\nP.S. Why doesn't TopGit add git and TopGit version to signature?\n\n-- \nJakub Narebski\nPoland\n"},{"id":"95076","messageId":"200811062243.27348.angavrilov@gmail.com","threadId":"16154","inReplyTo":"200811060026.59340.jnareb@gmail.com","subject":"Re: [RFC PATCH] gitweb: Support filtering projects by .htaccess files.","fromName":"Alexander Gavrilov","fromEmail":"angavrilov@gmail.com","sentAt":"2008-11-06T19:43:26Z","receivedAt":"2008-11-06T19:43:26Z","isPatch":true,"sender":{"key":"angavrilov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42666?v=4"},"body":"On Thursday 06 November 2008 02:26:58 Jakub Narebski wrote:\n> Alexander Gavrilov wrote:\n> > +  For example, if you use mod_perl to run the script, and have dumb\n> > +  http protocol authentication configured for your repositories, you\n> > +  can use the following hook to allow access only if the user is\n> > +  authorized to read the files:\n> > +\n> > +    $export_auth_hook = sub {\n> > +        use Apache2::SubRequest ();\n> > +        use Apache2::Const -compile => qw(HTTP_OK);\n> > +        my $path = \"$_[0]/HEAD\";\n> > +        my $r    = Apache2::RequestUtil->request;\n> > +        my $sub  = $r->lookup_file($path);\n> > +        return $sub->filename eq $path \n> > +            && $sub->status == Apache2::Const::HTTP_OK;\n> > +    };\n> \n> Can anybody check this? Or was it checked by author?\n\nWell, it seems to do what is intended on my home server,\nalthough it has a known limitation, so here is an updated\nversion that warns about it.\n\nBy the way, do you know how to deal with Apache or ModPerl's\nurge to append standard error messages to the script output, other\nthan adding a bunch of lines like the following to the config?\n\n  ErrorMessage 400 \" \"\n\nI couldn't find any solutions so far.\n\n\n--- >8 ---\nSubject: [PATCH] gitweb: Add a per-repository authorization hook.\n\nAdd a configuration variable that can be used to specify an\narbitrary subroutine that will be called in the same situations\nwhere $export_ok is checked, and its return value will be used\nto decide whether the repository is to be shown.\n\nThis allows the user to implement custom authentication\nschemes, for example by issuing a subrequest through mod_perl\nand checking if Apache will authorize it.\n\nSigned-off-by: Alexander Gavrilov <angavrilov@gmail.com>\n---\n gitweb/INSTALL     |   23 +++++++++++++++++++++++\n gitweb/gitweb.perl |    8 +++++++-\n 2 files changed, 30 insertions(+), 1 deletions(-)\n\ndiff --git a/gitweb/INSTALL b/gitweb/INSTALL\nindex 26967e2..72a1322 100644\n--- a/gitweb/INSTALL\n+++ b/gitweb/INSTALL\n@@ -166,6 +166,29 @@ Gitweb repositories\n   shows repositories only if this file exists in its object database\n   (if directory has the magic file named $export_ok).\n \n+- Finally, it is possible to specify an arbitrary perl subroutine that\n+  will be called for each project to determine if it can be exported.\n+  The subroutine receives an absolute path to the project as its only\n+  parameter.\n+\n+  For example, if you use mod_perl to run the script, and have dumb\n+  http protocol authentication configured for your repositories, you\n+  can use the following hook to allow access only if the user is\n+  authorized to read the files:\n+\n+    $export_auth_hook = sub {\n+        use Apache2::SubRequest ();\n+        use Apache2::Const -compile => qw(HTTP_OK);\n+        my $path = \"$_[0]/HEAD\";\n+        my $r    = Apache2::RequestUtil->request;\n+        my $sub  = $r->lookup_file($path);\n+        return $sub->filename eq $path \n+            && $sub->status == Apache2::Const::HTTP_OK;\n+    };\n+\n+  Note that since this sample works exclusively in the filesystem\n+  namespace, <Location> sections of the configuration have no effect.\n+\n Generating projects list using gitweb\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n \ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 172ea6b..9329880 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -95,6 +95,11 @@ our $default_projects_order = \"project\";\n # (only effective if this variable evaluates to true)\n our $export_ok = \"++GITWEB_EXPORT_OK++\";\n \n+# show repository only if this subroutine returns true\n+# when given the path to the project, for example:\n+#    sub { return -e \"$_[0]/git-daemon-export-ok\"; }\n+our $export_auth_hook = undef;\n+\n # only allow viewing of repositories also shown on the overview page\n our $strict_export = \"++GITWEB_STRICT_EXPORT++\";\n \n@@ -400,7 +405,8 @@ sub check_head_link {\n sub check_export_ok {\n \tmy ($dir) = @_;\n \treturn (check_head_link($dir) &&\n-\t\t(!$export_ok || -e \"$dir/$export_ok\"));\n+\t\t(!$export_ok || -e \"$dir/$export_ok\") &&\n+\t\t(!$export_auth_hook || $export_auth_hook->($dir)));\n }\n \n # process alternate names for backward compatibility\n-- \ntg: (0d4f9de..) t/authenticate/hook (depends on: t/authenticate/unify-exportok)\n"}]}