Apache-AuthzCache
view release on metacpan or search on metacpan
AuthzCache.pm view on Meta::CPAN
my $require_groups = undef;
# Get configuration
my $casesensitive = $r->dir_config('AuthzCache_CaseSensitive') || 'on';
my $cache_time_limit = $r->dir_config('AuthzCache_CacheTime') ||
$r->dir_config('AuthzCache_Timeout') || $Cache::Cache::EXPIRES_NEVER;
my $cache_dir = $r->dir_config('AuthzCache_Directory') || '/tmp';
my $cache_umask = $r->dir_config('AuthzCache_Umask') || '007';
my $auth_name = $r->auth_name;
my $requirement = $r->dir_config('AuthzRequire') || 'inAGroup';
$r->log->debug("manage_cache: cache_time_limit=$cache_time_limit, ",
"cache_dir=$cache_dir, cache_umask=$cache_umask, ",
"auth_name=$auth_name");
$requirement = REQUIRE_OPTS->{lc($requirement)} || 1;
# Get username
my $user_sent = $r->connection->user;
$r->log->debug("handler: username=$user_sent");
# Clear for paranoid security precautions
$r->subprocess_env(REMOTE_GROUP => undef);
undef($r->headers_in->{'REMOTE_GROUP'});
$r->notes('AuthzCache' => undef);
# Get required groups
for my $req (@$requires) {
my ($require, $rest) = split /\s+/, $req->{requirement}, 2;
if ($require eq "user") { return OK
if grep $user_sent eq $_, split /\s+/, $rest }
elsif ($require eq "valid-user") { return OK }
elsif ($require eq 'group') {
@$require_groups = Text::ParseWords::parse_line('\s+', 0, $rest);
}
}
# Do we want Windows-like case-insensitivity?
if ($casesensitive eq 'off') {
$user_sent = lc($user_sent);
}
# Create the cache if needed
my $cache = Cache::FileCache->new({ namespace => $auth_name,
default_expires_in => $cache_time_limit,
cache_root => $cache_dir,
directory_umask => $cache_umask });
my $user_groups = $cache->get($user_sent);
# Is the user in the cache
if ($user_groups) {
$r->log->debug("handler: using cached groups for $user_sent");
my $success_groups = '';
OUTTER: foreach my $req_group (@$require_groups) {
my $succeeded = 0;
INNER: foreach my $user_group (@$user_groups) {
$r->log->debug("handler: comparing $req_group to $user_group");
if ($casesensitive eq 'off' &&
lc($req_group) eq lc($user_group)) {
# Password matches so end stage
# The required patch was not introduced in 1.26. It is no longer
# promised to be included in any timeframe. Commenting out.
# if ($mod_perl::VERSION < 1.26) {
# Since set_handlers() doesn't work properly until
# 1.26 (according to Doug MacEachern) I have to work
# around it by cobbling together cheat sheets for the
# subsequent handlers in this phase. I get the
# willies about the security implications in a
# general environment where you might be using
# someone else's handlers upstream or downstream...
$r->log->debug("handler: user in cache and case-insensitive ",
"groups $req_group and $user_group match; ",
"appending to success list");
if ($requirement == 1) {
$r->subprocess_env(REMOTE_GROUP => $user_group);
$r->headers_in->{'REMOTE_GROUP'} = $user_group;
$r->notes('AuthzCache' => 'hit');
return OK;
} else {
$success_groups .= "\"$user_group\" ";
$succeeded = 1;
last INNER;
}
# } else {
# $r->log->debug("handler: user in cache and case-insensitive ",
# "groups $req_group and $user_group match; ",
# "returning OK and clearing PerlAuthzHandler");
# $r->set_handlers(PerlAuthzHandler => undef);
#}
} elsif ($req_group eq $user_group) {
# Password matches so end stage
# The required patch was not introduced in 1.26. It is no longer
# promised to be included in any timeframe. Commenting out.
# if ($mod_perl::VERSION < 1.26) {
# Since set_handlers() doesn't work properly until
# 1.26 (according to Doug MacEachern) I have to work
# around it by cobbling together cheat sheets for the
# subsequent handlers in this phase. I get the
# willies about the security implications in a
# general environment where you might be using
# someone else's handlers upstream or downstream...
$r->log->debug("handler: user in cache and case-sensitive ",
"groups $req_group and $user_group match; ",
"appending to success list");
if ($requirement == 1) {
$r->subprocess_env(REMOTE_GROUP => $user_group);
$r->headers_in->{'REMOTE_GROUP'} = $user_group;
$r->notes('AuthzCache' => 'hit');
return OK;
} else {
$success_groups .= "\"$user_group\" ";
$succeeded = 1;
last INNER;
}
# } else {
# $r->log->debug("handler: user in cache and case-insensitive ",
# "groups $req_group and $user_group match; ",
# "returning OK and clearing PerlAuthzHandler");
# $r->set_handlers(PerlAuthzHandler => undef);
#}
} # IF
} # INNER
if ($requirement == 3 && !$succeeded) {
$r->log->debug("handler: group $req_group not in cache for ",
"inAllGroups requirement; returning DECLINED");
return DECLINED;
}
$succeeded = 0;
} # OUTTER
if ($success_groups ne '') {
chop($success_groups);
$r->log->debug("handler: user in cache; returning OK and setting ",
"environment to $success_groups and notes");
$r->subprocess_env(REMOTE_GROUP => $success_groups);
$r->headers_in->{'REMOTE_GROUP'} = $success_groups;
$r->notes('AuthzCache' => 'hit');
return OK;
}
} # USER_GROUPS
# User not in cache
$r->log->debug("handler: user/group not in cache; returning DECLINED");
return DECLINED;
}
###############################################################################
###############################################################################
# manage_cache: insert new entries into the cache
###############################################################################
###############################################################################
sub manage_cache {
my $r = shift;
return OK unless $r->is_initial_req; # only the first internal request
my $requires = $r->requires;
return OK unless $requires;
# Get username
my $user_sent = $r->connection->user;
# Get required groups and proceed with caching only if groups were required
for my $req (@$requires) {
my ($require, $rest) = split /\s+/, $req->{requirement}, 2;
if ($require eq "user") { return OK
if grep $user_sent eq $_, split /\s+/, $rest }
elsif ($require eq "valid-user") { return OK }
}
my ($group_sent, $cache_result) = undef;
# The required patch was not introduced in 1.26. It is no longer
# promised to be included in any timeframe. Commenting out.
# if ($mod_perl::VERSION < 1.26) {
# I shouldn't need to use the below lines as this module
# should never be called if there was a cache hit. Since
# set_handlers() doesn't work properly until 1.26 (according
# to Doug MacEachern) I have to work around it by cobbling
# together cheat sheets for the previous handlers in this
# phase. I get the willies about the security implications in
# a general environment where you might be using someone
# else's handlers upstream or downstream...
$group_sent = $r->subprocess_env("REMOTE_GROUP") ||
$r->headers_in->{'REMOTE_GROUP'};
$cache_result = $r->notes('AuthzCache');
if ($group_sent && $cache_result eq 'hit') {
$r->log->debug("manage_cache: upstream cache hit for ",
"username=$user_sent, group=$group_sent");
return OK;
# }
}
# Get configuration
my $casesensitive = $r->dir_config('AuthzCache_CaseSensitive') || 'on';
my $cache_time_limit = $r->dir_config('AuthzCache_CacheTime') ||
$r->dir_config('AuthzCache_Timeout') || $Cache::Cache::EXPIRES_NEVER;
my $cache_dir = $r->dir_config('AuthzCache_Directory') || '/tmp';
my $cache_umask = $r->dir_config('AuthzCache_Umask') || '007';
my $auth_name = $r->auth_name;
$r->log->debug("manage_cache: cache_time_limit=$cache_time_limit, ",
"cache_dir=$cache_dir, cache_umask=$cache_umask, ",
"auth_name=$auth_name");
# Do we want Windows-like case-insensitivity?
if ($casesensitive eq 'off') {
$user_sent = lc($user_sent);
$group_sent = lc($group_sent);
}
# Add groups to the cache
my $groups = []; # perl-5.8 chokes on declaring an array dereference
@$groups = Text::ParseWords::parse_line('\s+', 0, $group_sent);
my $cache = Cache::FileCache->new({ namespace => $auth_name,
default_expires_in => $cache_time_limit,
cache_root => $cache_dir,
directory_umask => $cache_umask });
my $user_groups = $cache->get($user_sent);
if (ref($user_groups)) {
$cache->set($user_sent, [(@{$groups}, @{$user_groups})], $cache_time_limit);
} else {
$cache->set($user_sent, $groups, $cache_time_limit);
}
$r->log->debug("manage_cache: added $user_sent:$group_sent to the cache");
return OK;
}
if (Apache->module("Apache::Status")) {
Apache::Status->menu_item('AuthzCache' => 'AuthzCache Menu Item',
\&status_menu);
}
###############################################################################
( run in 1.955 second using v1.01-cache-2.11-cpan-df04353d9ac )