package Apache::AuthzUnix;
our $VERSION = '0.02';
our $DEBUG = 0;
require File::stat;
use File::Basename qw(dirname);
use User::pwent;
use User::grent;
use constant MP2 =>
~~(exists $ENV{MOD_PERL_API_VERSION} && $ENV{MOD_PERL_API_VERSION} == 2);
BEGIN {
my @constants = qw( OK DECLINED );
if (MP2) {
require Apache2::Access;
require Apache2::RequestRec;
require Apache2::Const;
import Apache2::Const @constants;
}
else {
require Apache::Constants;
import Apache::Constants @constants;
}
}
sub authz {
my $r = shift;
my $user = $r->user or return DECLINED();
my $fn = $r->filename;
if (!-e $r->filename) { $fn = dirname($fn) }
# Why did we just do that? Because:
# If we're PUTting a file, we want to check if we can write to the directory.
# Otherwise, we're GETting a non-existent or autogenerated file (ie autoindex)
# If it's a directory index, then we use the permissions of the directory.
# If it's non-existent, permissions are an irrelevance!
my $stat = File::stat::stat($fn);
my $access =
_access($user, $stat->mode, $stat->uid, $stat->gid, $r->method);
warn "Access to file: "
. $r->filename
. " (resolved as $fn) : "
. ($access ? "allowed" : "denied")
if $DEBUG;
return $access ? OK() : DECLINED();
}
sub _access {
my ($username, $perms, $uid, $gid, $method) = @_;
my ($u, $g, $o) = ($perms & 0700, $perms & 0070, $perms & 0007);
my $user = getpwnam($username);
my %in_group = map { $_ => 1 } @{ getgrgid($gid)->members };
my $bit = $method =~ /(PUT|DELETE)/ ? 2 : 4;
return 1 if $o & $bit
|| ($uid == $user->uid and $u & ($bit << 6))
|| (($gid == $user->gid or $in_group{$username})
and $g & ($bit << 3));
return 0;
}
1;
__END__
# Below is stub documentation for your module. You'd better edit it!
=head1 NAME
Apache::AuthzUnix - Apache/Apache2 authorization handler for Unix permissions
=head1 SYNOPSIS
PerlModule Apache::AuthzUnix;
<Location ...>
AuthName auth
AuthType Basic
AuthBasicProvider ldap
PerlAuthzHandler Apache::AuthzUnix::authz
# Don't need a "requires" line
</Location>
=head1 DESCRIPTION
This module was written to provide authorization for DAV access to home
directories, but probably has other uses in the C<UserDir> space.
Assuming that Apache has authenticated a user, this module helps to
determine whether or not that user can read (or write) a file on the
filesystem. It applies standard Unix user and group tests on the file's
permissions to determine read access and, in the case of C<PUT> and
C<DELETE> methods, write access. If the file does not exist, then the
containing directory is tested, as one would expect.
This module is designed work on both mod_perl versions 1 and 2.
=head1 AUTHOR
Simon Cozens, E<lt>simon@simon-cozens.orgE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2007 by Simon Cozens
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.7 or,
at your option, any later version of Perl 5 you may have available.
=cut