diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2014-07-29 20:07:44 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2014-07-29 20:07:44 +0300 |
commit | b73431421025660d28198955c15356c086f5223f (patch) | |
tree | 8115c2a20986b61fac58dd0d3fc302c896262fee | |
parent | d745c522f462e01aa576c6f93b94cbad6c631f73 (diff) | |
download | gitaclhook-b73431421025660d28198955c15356c086f5223f.tar.gz gitaclhook-b73431421025660d28198955c15356c086f5223f.tar.bz2 |
Separate rules for the same user name coming from different IP addresses.
* Makefile.PL: Add Net::CIDR to the list of prerequisites.
* gitaclhook: Document user@CIDRLIST syntax and the hooks.acl.ip-env-var
variable.
* lib/GitACL.pm: Use Net::CIDR
(match_host): New sub.
(match_user): Check IP against cidr part (if defined).
(new): Get remote IP address from environment.
-rw-r--r-- | Makefile.PL | 3 | ||||
-rwxr-xr-x | gitaclhook | 36 | ||||
-rw-r--r-- | lib/GitACL.pm | 18 |
3 files changed, 47 insertions, 10 deletions
diff --git a/Makefile.PL b/Makefile.PL index db3859d..3f18606 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -32,3 +32,4 @@ WriteMakefile( 'PREREQ_PM' => { 'Getopt::Long' => 2.34, - 'File::Spec' => 3.39 } + 'File::Spec' => 3.39, + 'Net::CIDR' => 0.17 } ); @@ -88,3 +88,3 @@ An asterisk matches any project name. -=item I<USER> +=item I<USER>[B<@>I<CIDRLIST>] @@ -96,2 +96,11 @@ the literal match is assumed. +The I<CIDRLIST> part, if present, restricts the rule to users coming from +IP addresses that match one of the elements in the list. I<CIDRLIST> is a +comma-separated list of IP addresses, ranges or CIDRs. An IP range is +defined as two IP addresses separated by a minus sign. A CIDR is defined as +network address, followed by a slash and length of the netmask in decimal. +For example: + + gray@10.0.0.0/16,192.168.1.0-192.168.10.255 + =back @@ -187,3 +196,3 @@ The control verb. -The user name or group (B<%>I<GROUPNAME>) specification. +The user name specification (see description in the B<ACL FILE> section). @@ -223,3 +232,3 @@ If no matching entry is found, the update is allowed. -=item B<hooks.acl.type> STRING +=item B<hooks.acl.type> I<STRING> @@ -227,3 +236,3 @@ Type of the storage engine. Valid values are B<File> (default) and B<LDAP>. -=item B<hooks.acl.file> STRING +=item B<hooks.acl.file> I<STRING> @@ -231,3 +240,3 @@ For the B<File> storage engine, name of the ACL file. -=item B<hooks.acl.ldapconf> STRING +=item B<hooks.acl.ldapconf> I<STRING> @@ -236,3 +245,3 @@ instead of B</etc/ldap.conf>. -=item B<hooks.acl.log> STRING +=item B<hooks.acl.log> I<STRING> @@ -240,3 +249,3 @@ Send log info to this file. -=item B<hooks.acl.debug> NUMBER +=item B<hooks.acl.debug> I<NUMBER> @@ -245,3 +254,3 @@ be displayed. -=item B<hooks.acl.quiet> BOOL +=item B<hooks.acl.quiet> I<BOOL> @@ -254,3 +263,3 @@ rule matched the request. Unless defined, B<deny> is assumed. -=item B<hooks.acl.httpd-user> STRING +=item B<hooks.acl.httpd-user> I<STRING> @@ -261,2 +270,11 @@ from the environment variable B<REMOTE_USER>. +=item B<hooks.acl.ip-env-var> I<STRING> + +Name of the environment variable from where to retrieve remote IP address. +Default is B<REMOTE_ADDR>, if B<hooks.acl.httpd-user> is defined and current +user matches it, and B<SSH_CLIENT> otherwise. + +The part of the string up to the first space character (if any) is taken as +the IP address. + =back diff --git a/lib/GitACL.pm b/lib/GitACL.pm index cde9624..4214b3f 100644 --- a/lib/GitACL.pm +++ b/lib/GitACL.pm @@ -20,2 +20,3 @@ use strict; use File::Spec; +use Net::CIDR qw (cidrlookup); @@ -118,2 +119,8 @@ sub match_primary_group($$) { +sub match_host($$) { + my ($ip,$iplist) = @_; + return 0 unless defined($ip); + return cidrlookup($ip, split /,/, $iplist); +} + sub match_user($$) { @@ -122,2 +129,6 @@ sub match_user($$) { return 0 if ($expr eq 'none'); + if ($expr =~ /(.+)@(.+)/) { + return 0 unless match_host($self->{ip}, $2); + $expr = $1; + } if ($expr =~ /^%(.+)/) { @@ -222,2 +233,9 @@ sub new { $obj->{user_name} = $ENV{REMOTE_USER}; + $obj->{ip} = $ENV{REMOTE_ADDR}; + } else { + my $ipvar = git_value('config', 'hooks.acl.ip-env-var') or 'SSH_CLIENT'; + if (defined($ENV{$ipvar})) { + my @a = split /\S/, $ENV{$ipvar}, 2; + $obj->{ip} = $a[0]; + } } |