aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xgit/gitaclhook169
1 files changed, 132 insertions, 37 deletions
diff --git a/git/gitaclhook b/git/gitaclhook
index f9b3d3a..dd31dd8 100755
--- a/git/gitaclhook
+++ b/git/gitaclhook
@@ -16,60 +16,116 @@
use strict;
use File::Spec;
+use Pod::Man;
+use Pod::Usage;
-=doc
-This hook is intended to be run as an "update" hook by git.
-It is called by git-receive-pack with arguments: refname old-sha1 new-sha1.
+=head1 NAME
-If the hooks.aclfile keyword is defined in the repository's config file,
+gitaclhook - control access to git repositories
+
+=head1 SYNOPSIS
+
+B<gitaclhook> I<refname> I<old-sha1> I<new-sha1>
+
+B<gitaclhook --help>
+
+=head1 DESCRIPTION
+
+This program is intended to be run as an "update" hook by git.
+It is called by B<git-receive-pack> with arguments:
+I<refname> I<old-sha1> I<new-sha1>.
+
+If the B<hooks.aclfile> keyword is defined in the repository's config file,
this hook will parse the file and allow or deny update depending on
-its settings. If hooks.aclfile is not defined, update is allowed
+its settings. If B<hooks.aclfile> is not defined, update is allowed
unconditionally.
+=head1 ACL FILE
+
The ACL file has the usual line-oriented syntax. Comments are introduced
by the # sign and extend to the end of the physical line. Comments and
empty lines are ignored.
Non-empty lines introduce ACL rules. The syntax is:
- VERB PROJECT USER [OP REF]
+=over 4
+
+I<VERB> I<PROJECT> I<USER> [I<OP> I<REF>]
+
+=back
where brackets denote optional parts. The parts of an ACL are:
-VERB Either 'allow' or 'deny', to allow or deny the operation,
- correspondingly.
+=over 4
+
+=item I<VERB>
+
+Either B<allow> or B<deny>, to allow or deny the operation, correspondingly.
+
+=item I<PROJECT>
-PROJECT The name of the project. It is obtained by removing the directory
+The name of the project. It is obtained by removing the directory
and suffix parts of the repository pathname. Thus, if the repository
- is located in /var/gitroot/foobar.git, then the corresponding name of
- the project is 'foobar'.
+is located in B</var/gitroot/foobar.git>, then the corresponding name of
+the project is B<foobar>.
-USER Name of the user. The word 'all' stands for any user, the word 'none'
+An asterisk matches any project name.
+
+=item I<USER>
+
+Name of the user. The word B<all> stands for any user, the word B<none>
matches no one at all. Otherwise, if this part begins with a percent
- sign (%), the rest of characters aretreated as the name of the UNIX
+sign (B<%>), the rest of characters are treated as the name of the UNIX
group to check and the rule matches any user in that group. Otherwise,
the literal match is assumed.
+=back
+
The optional parts are:
-OP Requested operation codes. It is a string consisting of one or more
+=over 4
+
+=item I<OP>
+
+Requested operation codes. It is a string consisting of one or more
of the following letters (case-insensitive):
- C: create new ref
- D: delete existing ref
- U: fast-forward existing ref (no commit loss)
- R: rewind or rebase existing ref (commit loss)
+=over 8
+
+=item B<C>
+
+Create new ref.
+
+=item B<D>
+
+Delete existing ref.
+
+=item B<U>
+
+Fast-forward existing ref (no commit loss).
+
+=item B<R>
-REF Affected ref, relative to the git refs/ directory. If it begins with
- a caret (^), it is treated as a Perl regular expression (with the ^
- being its part). If it ends with a /, it is treated as a prefix match,
- so, e.g., "heads/baz/" matches "refs/heads/baz" and anything below.
+Rewind or rebase existing ref (commit loss).
+
+=back
+
+=item I<REF>
+
+Affected ref, relative to the git B<refs/> directory. If it begins with
+a caret (B<^>), it is treated as a Perl regular expression (with the B<^>
+being its part). If it ends with a B</>, it is treated as a prefix match,
+so, e.g., B<heads/baz/> matches B<refs/heads/baz> and anything below.
Otherwise, it must match exactly the affected ref.
-The rule applies only if its PROJECT and USER parts match the project which is
-being updated and the user who requests the update, its OP contains the opcode
-of the requested operation and REF matches the affected ref. Missing REF
-and/or OP are treated as a match.
+=back
+
+=head1 RULE MATCHING
+
+The rule applies only if its I<PROJECT> and I<USER> parts match the project
+which is being updated and the user who requests the update, its I<OP>
+contains the opcode of the requested operation and I<REF> matches the affected
+ref. Missing I<REF> and/or I<OP> are treated as a match.
If no rule applies, the operation is allowed.
@@ -81,19 +137,49 @@ allow myprog %pm C ^heads/tags/v\\d+$
allow myprog admin CDUR
deny myprog all
-Then the users from the 'devel' group will be able to push updates to
-refs/heads/master, the users from the 'pm' group will be allowed to do
-anything with refs under refs/heads and to create tags with names beginning
-with 'v' and containing only digits afterwards, and the user 'admin' will
+Then the users from the B<devel> group will be able to push updates to
+B<refs/heads/master>, the users from the B<pm> group will be allowed to do
+anything with refs under B<refs/heads> and to create tags with names beginning
+with B<v> and containing only digits afterwards, and the user B<admin> will
be allowed to do anything he pleases. No other users will be allowed to
update that repository.
-Configuration settings:
+=head1 CONFIGURATION SETTINGS
+
+=over 4
+
+=item B<hooks.aclfile> STRING
+
+Name of the ACL file.
+
+=item B<hooks.acllog> STRING
+
+Send log info to this file.
+
+=item B<hooks.acldebug> BOOL
+
+Enable debugging.
-hooks.aclfile STRING Name of the ACL file
-hooks.acllog STRING Send log info to this file
-hooks.acldebug BOOL Enable debugging
-hooks.aclquiet BOOL Suppress diagnostics on stderr
+=item B<hooks.aclquiet> BOOL
+
+Suppress diagnostics on stderr.
+
+=item B<hooks.httpd-user> STRING
+
+Name of the user httpd runs as. Define it if the repository can be
+accessed via HTTP(S). If B<gitaclhook> is run as this user, it will
+get the name of the user on behalf of which the update is performed
+from the environment variable B<REMOTE_USER>.
+
+=back
+
+=head1 SEE ALSO
+
+B<git-receive-pack>(1).
+
+=head1 AUTHOR
+
+Sergey Poznyakoff, <gray@gno.org>
=cut
@@ -217,7 +303,7 @@ sub check_acl($$$) {
deny("malformed line", "$filename:$line")
unless $#x >= 2;
- next if ($x[1] ne $project);
+ next if ($x[1] ne "*" and $x[1] ne $project);
next unless match_user($x[2]);
next if ($#x >= 3 && index(uc $x[3], $op) == -1);
next if ($#x == 4 && !match_ref($x[4]));
@@ -233,7 +319,10 @@ sub check_acl($$$) {
####
# Sanity checks
-deny "don't run this script from the command line" unless ($git_dir);
+unless ($git_dir) {
+ pod2usage(-exitstatus => 0, -verbose => 2) if ($ref eq "--help");
+ deny "try \"$0 --help\" for fore info"
+}
$debug = git_value('config', '--bool', 'hooks.acldebug') unless ($debug);
$logfile = git_value('config', 'hooks.acllog');
@@ -242,6 +331,12 @@ if ($logfile && $logfile !~ /[>|]/) {
}
$quiet = git_value('config', 'hooks.aclquiet') unless ($debug);
+my $httpdusr = git_value('config', 'hooks.httpd-user');
+if (defined($httpdusr) and $user_name eq $httpdusr) {
+ deny "need authenticated user" unless defined($ENV{AUTH_TYPE});
+ $user_name = $ENV{REMOTE_USER};
+}
+
deny "need a ref name" unless $ref;
deny "bogus ref $ref" unless $ref =~ s,^refs/,,;
deny "bad old value $old" unless $old =~ /^[a-z0-9]{40}$/;

Return to:

Send suggestions and report system problems to the System administrator.