2014-03-13 16:07:36 +01:00
|
|
|
## @file
|
|
|
|
# Base file for Lemonldap::NG handlers
|
|
|
|
|
|
|
|
## @class
|
|
|
|
# Base class for Lemonldap::NG handlers.
|
|
|
|
# All methods in handler are class methods: in ModPerl environment, handlers
|
|
|
|
# are always launched without object created.
|
|
|
|
#
|
|
|
|
# The main method is run() who is called by Apache for each requests (using
|
|
|
|
# handler() wrapper).
|
|
|
|
#
|
|
|
|
# The main initialization subroutine is init() who launch localInit() and
|
|
|
|
# globalInit().
|
|
|
|
package Lemonldap::NG::Handler::Main;
|
|
|
|
|
|
|
|
#use strict;
|
|
|
|
|
|
|
|
use MIME::Base64;
|
|
|
|
use Exporter 'import';
|
|
|
|
|
|
|
|
#use AutoLoader 'AUTOLOAD';
|
|
|
|
use Lemonldap::NG::Common::Crypto;
|
2014-04-11 18:12:21 +02:00
|
|
|
use Lemonldap::NG::Common::Session;
|
2014-03-13 16:07:36 +01:00
|
|
|
require POSIX;
|
|
|
|
use CGI::Util 'expires';
|
|
|
|
use constant UNPROTECT => 1;
|
|
|
|
use constant SKIP => 2;
|
|
|
|
use constant MAINTENANCE_CODE => 503;
|
|
|
|
|
|
|
|
#inherits Cache::Cache
|
|
|
|
#inherits Apache::Session
|
|
|
|
#link Lemonldap::NG::Common::Apache::Session::SOAP protected globalStorage
|
|
|
|
|
2014-04-11 18:12:21 +02:00
|
|
|
our $VERSION = '1.4.0';
|
2014-03-13 16:07:36 +01:00
|
|
|
|
|
|
|
our %EXPORT_TAGS;
|
|
|
|
|
|
|
|
our @EXPORT_OK;
|
|
|
|
|
|
|
|
our @EXPORT;
|
|
|
|
|
2014-05-22 14:21:28 +02:00
|
|
|
# my @threadSharedVar = qw(
|
|
|
|
# cda childInitDone cipher
|
|
|
|
# cookieExpiration cookieName customFunctions
|
|
|
|
# defaultCondition defaultProtection forgeHeaders
|
|
|
|
# globalStorage globalStorageOptions headerList
|
|
|
|
# httpOnly https key
|
|
|
|
# localStorage localStorageOptions locationCondition
|
|
|
|
# locationConditionText locationCount locationProtection
|
|
|
|
# locationRegexp maintenance port
|
|
|
|
# refLocalStorage safe securedCookie
|
|
|
|
# statusOut statusPipe timeoutActivity
|
|
|
|
# transform useRedirectOnError useRedirectOnForbidden
|
|
|
|
# useSafeJail whatToTrace
|
2014-03-13 16:07:36 +01:00
|
|
|
# );
|
|
|
|
#
|
2014-05-22 14:21:28 +02:00
|
|
|
# non thread shared vars
|
2014-03-13 16:07:36 +01:00
|
|
|
# $datas
|
2014-05-22 14:21:28 +02:00
|
|
|
# $datasUpdate
|
2014-03-13 16:07:36 +01:00
|
|
|
|
|
|
|
# Shared variables
|
2014-05-23 12:23:51 +02:00
|
|
|
our ( $datas, $datasUpdate, $tsv );
|
2014-03-13 16:07:36 +01:00
|
|
|
|
|
|
|
##########################################
|
|
|
|
# COMPATIBILITY WITH APACHE AND APACHE 2 #
|
|
|
|
##########################################
|
|
|
|
|
|
|
|
BEGIN {
|
|
|
|
|
|
|
|
# globalStorage and locationRules are set for Manager compatibility only
|
|
|
|
%EXPORT_TAGS = (
|
|
|
|
globalStorage => [qw( )],
|
|
|
|
locationRules => [qw( )],
|
2014-05-23 12:23:51 +02:00
|
|
|
jailSharedVars => [qw( $datas )],
|
2014-03-13 16:07:36 +01:00
|
|
|
tsv => [qw( $tsv )],
|
|
|
|
import => [qw( import @EXPORT_OK @EXPORT %EXPORT_TAGS )],
|
|
|
|
headers => [
|
|
|
|
qw(
|
|
|
|
lmHeaderIn lmSetHeaderIn lmHeaderOut
|
|
|
|
lmSetHeaderOut lmSetErrHeaderOut
|
|
|
|
)
|
|
|
|
],
|
|
|
|
apache => [
|
|
|
|
qw( MP OK REDIRECT FORBIDDEN DONE DECLINED SERVER_ERROR
|
|
|
|
)
|
|
|
|
],
|
|
|
|
post => [qw(postFilter)],
|
|
|
|
);
|
|
|
|
push( @EXPORT_OK, @{ $EXPORT_TAGS{$_} } ) foreach ( keys %EXPORT_TAGS );
|
|
|
|
$EXPORT_TAGS{all} = \@EXPORT_OK;
|
|
|
|
if ( exists $ENV{MOD_PERL} ) {
|
|
|
|
if ( $ENV{MOD_PERL_API_VERSION} and $ENV{MOD_PERL_API_VERSION} >= 2 ) {
|
|
|
|
eval 'use constant MP => 2;';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
eval 'use constant MP => 1;';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
eval 'use constant MP => 0;';
|
|
|
|
}
|
|
|
|
if ( MP() == 2 ) {
|
|
|
|
require Apache2::Log;
|
|
|
|
require Apache2::RequestUtil;
|
|
|
|
Apache2::RequestUtil->import();
|
|
|
|
require Apache2::RequestRec;
|
|
|
|
Apache2::RequestRec->import();
|
|
|
|
require Apache2::ServerUtil;
|
|
|
|
Apache2::ServerUtil->import();
|
|
|
|
require Apache2::Connection;
|
|
|
|
Apache2::Connection->import();
|
|
|
|
require Apache2::RequestIO;
|
|
|
|
Apache2::RequestIO->import();
|
|
|
|
require APR::Table;
|
|
|
|
APR::Table->import();
|
|
|
|
require Apache2::URI;
|
|
|
|
Apache2::URI->import();
|
|
|
|
require Apache2::Const;
|
|
|
|
Apache2::Const->import( '-compile', qw(:common :log) );
|
|
|
|
eval '
|
|
|
|
use constant FORBIDDEN => Apache2::Const::FORBIDDEN;
|
|
|
|
use constant REDIRECT => Apache2::Const::REDIRECT;
|
|
|
|
use constant OK => Apache2::Const::OK;
|
|
|
|
use constant DECLINED => Apache2::Const::DECLINED;
|
|
|
|
use constant DONE => Apache2::Const::DONE;
|
|
|
|
use constant SERVER_ERROR => Apache2::Const::SERVER_ERROR;
|
|
|
|
';
|
|
|
|
eval {
|
|
|
|
require threads::shared;
|
|
|
|
threads::shared::share($tsv);
|
|
|
|
};
|
|
|
|
print "eval error: $@" if ($@);
|
|
|
|
}
|
|
|
|
elsif ( MP() == 1 ) {
|
|
|
|
require Apache;
|
|
|
|
require Apache::Log;
|
|
|
|
require Apache::Constants;
|
|
|
|
Apache::Constants->import(':common');
|
|
|
|
Apache::Constants->import(':response');
|
|
|
|
}
|
|
|
|
else { # For Test or CGI
|
|
|
|
eval '
|
|
|
|
use constant FORBIDDEN => 1;
|
|
|
|
use constant REDIRECT => 1;
|
|
|
|
use constant OK => 1;
|
|
|
|
use constant DECLINED => 1;
|
|
|
|
use constant DONE => 1;
|
|
|
|
use constant SERVER_ERROR => 1;
|
|
|
|
';
|
|
|
|
}
|
|
|
|
*handler = ( MP() == 2 ) ? \&handler_mp2 : \&handler_mp1;
|
|
|
|
*logout = ( MP() == 2 ) ? \&logout_mp2 : \&logout_mp1;
|
|
|
|
}
|
|
|
|
|
|
|
|
use Lemonldap::NG::Handler::Initialization::LocalInit;
|
|
|
|
use Lemonldap::NG::Handler::Initialization::GlobalInit;
|
|
|
|
use Lemonldap::NG::Handler::Main::Jail;
|
|
|
|
use Lemonldap::NG::Handler::Main::Headers;
|
|
|
|
use Lemonldap::NG::Handler::Main::PostForm;
|
|
|
|
use Lemonldap::NG::Handler::Main::Logger;
|
|
|
|
|
|
|
|
## @rmethod protected int handler_mp2()
|
|
|
|
# Launch run() when used under mod_perl version 2
|
|
|
|
# @return Apache constant
|
|
|
|
sub handler_mp2 : method {
|
|
|
|
shift->run(@_);
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected int logout_mp2()
|
|
|
|
# Launch unlog() when used under mod_perl version 2
|
|
|
|
# @return Apache constant
|
|
|
|
sub logout_mp2 : method {
|
|
|
|
shift->unlog(@_);
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected void lmSetApacheUser(Apache2::RequestRec r,string s)
|
|
|
|
# Inform Apache for the data to use as user for logs
|
|
|
|
# @param $r current request
|
|
|
|
# @param $s string to use
|
|
|
|
sub lmSetApacheUser {
|
|
|
|
my ( $class, $r, $s ) = splice @_;
|
|
|
|
return unless ($s);
|
|
|
|
if ( MP() == 2 ) {
|
|
|
|
$r->user($s);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$r->connection->user($s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected void updateStatus(string user,string url,string action)
|
|
|
|
# Inform the status process of the result of the request if it is available.
|
|
|
|
sub updateStatus {
|
2014-05-23 12:23:51 +02:00
|
|
|
my ( $class, $apacheRequest, $user, $url, $action ) = splice @_;
|
2014-03-13 16:07:36 +01:00
|
|
|
eval {
|
|
|
|
print { $tsv->{statusPipe} } "$user => "
|
|
|
|
. $apacheRequest->hostname
|
|
|
|
. "$url $action\n"
|
|
|
|
if ( $tsv->{statusPipe} );
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected int forbidden(string uri)
|
|
|
|
# Used to reject non authorized requests.
|
|
|
|
# Inform the status processus and call logForbidden().
|
2014-05-23 12:23:51 +02:00
|
|
|
# @param $apacheRequest current request
|
|
|
|
# @param $uri URI
|
2014-03-13 16:07:36 +01:00
|
|
|
# @return Apache2::Const::REDIRECT or Apache2::Const::FORBIDDEN
|
|
|
|
sub forbidden {
|
2014-05-23 12:23:51 +02:00
|
|
|
my ( $class, $apacheRequest, $uri ) = splice @_;
|
2014-03-13 16:07:36 +01:00
|
|
|
if ( $datas->{_logout} ) {
|
2014-05-23 12:23:51 +02:00
|
|
|
$class->updateStatus( $apacheRequest,
|
|
|
|
$datas->{ $tsv->{whatToTrace} }, $uri, 'LOGOUT' );
|
2014-03-13 16:07:36 +01:00
|
|
|
my $u = $datas->{_logout};
|
|
|
|
$class->localUnlog;
|
2014-05-23 12:23:51 +02:00
|
|
|
return $class->goToPortal( $apacheRequest, $u, 'logout=1' );
|
2014-03-13 16:07:36 +01:00
|
|
|
}
|
2014-05-23 12:23:51 +02:00
|
|
|
$class->updateStatus( $apacheRequest,
|
|
|
|
$datas->{ $tsv->{whatToTrace} }, $uri, 'REJECT' );
|
2014-03-13 16:07:36 +01:00
|
|
|
$apacheRequest->push_handlers(
|
|
|
|
PerlLogHandler => sub {
|
|
|
|
$_[0]->status(FORBIDDEN);
|
|
|
|
$class->logForbidden( $uri, $datas );
|
|
|
|
DECLINED;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
# Redirect or Forbidden?
|
|
|
|
if ( $tsv->{useRedirectOnForbidden} ) {
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
|
|
|
"Use redirect for forbidden access", 'debug' );
|
2014-05-23 12:23:51 +02:00
|
|
|
return $class->goToPortal( $apacheRequest, $uri, 'lmError=403' );
|
2014-03-13 16:07:36 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( "Return forbidden access",
|
|
|
|
'debug' );
|
|
|
|
return FORBIDDEN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected void logForbidden(string uri,hashref datas)
|
|
|
|
# Insert a log in Apache errors log system to inform that the user was rejected.
|
|
|
|
# This method has to be overloaded to use different logs systems
|
|
|
|
# @param $uri uri asked
|
|
|
|
# @param $datas hash re to user's datas
|
|
|
|
sub logForbidden {
|
|
|
|
my ( $class, $uri, $datas ) = splice @_;
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
|
|
|
'User "'
|
|
|
|
. $datas->{ $tsv->{whatToTrace} }
|
|
|
|
. '" was reject when he tried to access to '
|
|
|
|
. $uri,
|
|
|
|
'notice'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected void logGranted(string uri)
|
|
|
|
# Insert a log in Apache errors log system to inform that the user was
|
|
|
|
# authorizated. This method has to be overloaded to use different logs systems
|
|
|
|
# @param $uri uri asked
|
|
|
|
sub logGranted {
|
|
|
|
my ( $class, $uri, $datas ) = splice @_;
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
|
|
|
'User "'
|
|
|
|
. $datas->{ $tsv->{whatToTrace} }
|
|
|
|
. '" was granted to access to '
|
|
|
|
. $uri,
|
|
|
|
'debug'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected void hideCookie()
|
|
|
|
# Hide Lemonldap::NG cookie to the protected application.
|
2014-05-23 12:23:51 +02:00
|
|
|
# @param $apacheRequest current request
|
2014-03-13 16:07:36 +01:00
|
|
|
sub hideCookie {
|
2014-05-23 12:23:51 +02:00
|
|
|
my ($class, $apacheRequest) = @_;
|
2014-03-13 16:07:36 +01:00
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( "removing cookie", 'debug' );
|
|
|
|
my $tmp = Lemonldap::NG::Handler::Main::Headers->lmHeaderIn( $apacheRequest,
|
|
|
|
'Cookie' );
|
|
|
|
$tmp =~ s/$tsv->{cookieName}(http)?=[^,;]*[,;\s]*//og;
|
|
|
|
if ($tmp) {
|
|
|
|
Lemonldap::NG::Handler::Main::Headers->lmSetHeaderIn( $apacheRequest,
|
|
|
|
'Cookie' => $tmp );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Lemonldap::NG::Handler::Main::Headers->lmUnsetHeaderIn( $apacheRequest,
|
|
|
|
'Cookie' );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected string encodeUrl(string url)
|
|
|
|
# Encode URl in the format used by Lemonldap::NG::Portal for redirections.
|
|
|
|
# @return Base64 encoded string
|
|
|
|
sub encodeUrl {
|
2014-05-23 12:23:51 +02:00
|
|
|
my ( $class, $apacheRequest, $url ) = splice @_;
|
|
|
|
$url = $class->_buildUrl($apacheRequest, $url) if ( $url !~ m#^https?://# );
|
2014-03-13 16:07:36 +01:00
|
|
|
return encode_base64( $url, '' );
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected int goToPortal(string url, string arg)
|
|
|
|
# Redirect non-authenticated users to the portal by setting "Location:" header.
|
2014-05-23 12:23:51 +02:00
|
|
|
# @param $apacheRequest current request
|
2014-03-13 16:07:36 +01:00
|
|
|
# @param $url Url requested
|
|
|
|
# @param $arg optionnal GET parameters
|
|
|
|
# @return Apache2::Const::REDIRECT
|
|
|
|
sub goToPortal {
|
2014-05-23 12:23:51 +02:00
|
|
|
my ( $class, $apacheRequest, $url, $arg ) = splice @_;
|
2014-03-13 16:07:36 +01:00
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
2014-05-23 12:23:51 +02:00
|
|
|
"Redirect " . $class->ip($apacheRequest) . " to portal (url was $url)", 'debug' );
|
|
|
|
my $urlc_init = $class->encodeUrl($apacheRequest, $url);
|
2014-03-13 16:07:36 +01:00
|
|
|
Lemonldap::NG::Handler::Main::Headers->lmSetHeaderOut( $apacheRequest,
|
|
|
|
'Location' => $class->portal()
|
|
|
|
. "?url=$urlc_init"
|
|
|
|
. ( $arg ? "&$arg" : "" ) );
|
|
|
|
return REDIRECT;
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected $ fetchId()
|
|
|
|
# Get user cookies and search for Lemonldap::NG cookie.
|
2014-05-23 12:23:51 +02:00
|
|
|
# @param $apacheRequest current request
|
2014-03-13 16:07:36 +01:00
|
|
|
# @return Value of the cookie if found, 0 else
|
|
|
|
sub fetchId {
|
2014-05-23 12:23:51 +02:00
|
|
|
my ( $class, $apacheRequest) = @_;
|
2014-03-13 16:07:36 +01:00
|
|
|
my $t = Lemonldap::NG::Handler::Main::Headers->lmHeaderIn( $apacheRequest,
|
|
|
|
'Cookie' );
|
|
|
|
my $vhost = $apacheRequest->hostname;
|
|
|
|
my $lookForHttpCookie = $tsv->{securedCookie} =~ /^(2|3)$/
|
|
|
|
&& !(
|
|
|
|
defined( $tsv->{https}->{$vhost} )
|
2014-04-22 16:47:30 +02:00
|
|
|
? $tsv->{https}->{$vhost}
|
2014-03-13 16:07:36 +01:00
|
|
|
: $tsv->{https}->{_}
|
|
|
|
);
|
|
|
|
my $value =
|
|
|
|
$lookForHttpCookie
|
|
|
|
? ( $t =~ /$tsv->{cookieName}http=([^,; ]+)/o ? $1 : 0 )
|
|
|
|
: ( $t =~ /$tsv->{cookieName}=([^,; ]+)/o ? $1 : 0 );
|
|
|
|
|
2014-05-22 14:21:28 +02:00
|
|
|
$value = $tsv->{cipher}->decryptHex( $value, "http" )
|
2014-03-13 16:07:36 +01:00
|
|
|
if ( $value && $lookForHttpCookie && $tsv->{securedCookie} == 3 );
|
|
|
|
return $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected boolean retrieveSession(id)
|
|
|
|
# Tries to retrieve the session whose index is id
|
|
|
|
# @return true if the session was found, false else
|
|
|
|
sub retrieveSession {
|
|
|
|
my ( $class, $id ) = @_;
|
|
|
|
|
2014-04-11 18:12:21 +02:00
|
|
|
# 1. Search if the user was the same as previous (very efficient in
|
|
|
|
# persistent connection).
|
2014-03-13 16:07:36 +01:00
|
|
|
return 1
|
|
|
|
if ( defined $datas->{_session_id}
|
|
|
|
and $id eq $datas->{_session_id}
|
2014-05-22 14:21:28 +02:00
|
|
|
and ( time() - $datasUpdate < 60 ) );
|
2014-03-13 16:07:36 +01:00
|
|
|
|
2014-04-11 18:12:21 +02:00
|
|
|
# 2. Get the session from cache or backend
|
|
|
|
my $apacheSession = Lemonldap::NG::Common::Session->new(
|
|
|
|
{
|
|
|
|
storageModule => $tsv->{globalStorage},
|
|
|
|
storageModuleOptions => $tsv->{globalStorageOptions},
|
|
|
|
cacheModule => $tsv->{localSessionStorage},
|
|
|
|
cacheModuleOptions => $tsv->{localSessionStorageOptions},
|
|
|
|
id => $id,
|
|
|
|
kind => "SSO",
|
|
|
|
}
|
|
|
|
);
|
2014-03-13 16:07:36 +01:00
|
|
|
|
2014-04-11 18:12:21 +02:00
|
|
|
unless ( $apacheSession->data ) {
|
2014-03-13 16:07:36 +01:00
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
2014-04-11 18:12:21 +02:00
|
|
|
"Session $id can't be retrieved", 'info' );
|
2014-03-13 16:07:36 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-04-11 18:12:21 +02:00
|
|
|
# 3. Check local macros
|
|
|
|
my $local_macros;
|
|
|
|
if ( $tsv->{refLocalStorage}
|
|
|
|
and $local_macros = $tsv->{refLocalStorage}->get($id) )
|
|
|
|
{
|
|
|
|
foreach ( keys %$local_macros ) {
|
|
|
|
$datas->{$_} = $local_macros->{$_} unless defined $datas->{$_};
|
|
|
|
}
|
|
|
|
}
|
2014-03-13 16:07:36 +01:00
|
|
|
|
2014-04-11 18:12:21 +02:00
|
|
|
# Update the session to notify activity, if necessary
|
|
|
|
$apacheSession->update( { '_lastSeen' => time() } )
|
|
|
|
if ( $tsv->{timeoutActivity} );
|
2014-03-13 16:07:36 +01:00
|
|
|
|
|
|
|
# Store data in current shared variables
|
2014-04-11 18:12:21 +02:00
|
|
|
$datas->{$_} = $apacheSession->data->{$_}
|
|
|
|
foreach ( keys %{ $apacheSession->data } );
|
2014-03-13 16:07:36 +01:00
|
|
|
|
2014-05-22 14:21:28 +02:00
|
|
|
$datasUpdate = time();
|
2014-03-13 16:07:36 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-05-23 12:23:51 +02:00
|
|
|
## @rmethod protected string ip(string url)
|
|
|
|
# @param $apacheRequest current request
|
|
|
|
# @return client IP address
|
2014-03-13 16:07:36 +01:00
|
|
|
sub ip {
|
2014-05-23 12:23:51 +02:00
|
|
|
my ( $class, $apacheRequest) = @_;
|
2014-03-13 16:07:36 +01:00
|
|
|
my $ip = 'unknownIP';
|
|
|
|
eval {
|
|
|
|
$ip =
|
|
|
|
( MP() == 2 )
|
|
|
|
? $apacheRequest->connection->remote_ip
|
|
|
|
: $apacheRequest->remote_ip;
|
|
|
|
};
|
|
|
|
return $ip;
|
|
|
|
}
|
|
|
|
|
|
|
|
# MAIN SUBROUTINE called by Apache (using PerlHeaderParserHandler option)
|
|
|
|
|
|
|
|
## @rmethod int run(Apache2::RequestRec apacheRequest)
|
|
|
|
# Main method used to control access.
|
|
|
|
# Calls :
|
|
|
|
# - fetchId()
|
|
|
|
# - retrieveSession()
|
|
|
|
# - lmSetApacheUser()
|
|
|
|
# - grant()
|
|
|
|
# - forbidden() if user is rejected
|
|
|
|
# - sendHeaders() if user is granted
|
|
|
|
# - hideCookie()
|
|
|
|
# - updateStatus()
|
|
|
|
# @param $apacheRequest Current request
|
|
|
|
# @return Apache2::Const value (OK, FORBIDDEN, REDIRECT or SERVER_ERROR)
|
|
|
|
sub run ($$) {
|
2014-05-23 12:23:51 +02:00
|
|
|
my ( $class, $apacheRequest ) = splice @_;
|
2014-03-13 16:07:36 +01:00
|
|
|
return DECLINED unless ( $apacheRequest->is_initial_req );
|
|
|
|
my $args = $apacheRequest->args;
|
|
|
|
|
|
|
|
# Direct return if maintenance mode is active
|
2014-05-23 12:23:51 +02:00
|
|
|
if ( $class->checkMaintenanceMode($apacheRequest) ) {
|
2014-03-13 16:07:36 +01:00
|
|
|
|
|
|
|
if ( $tsv->{useRedirectOnError} ) {
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
|
|
|
"Got to portal with maintenance error code", 'debug' );
|
2014-05-23 12:23:51 +02:00
|
|
|
return $class->goToPortal( $apacheRequest, '/',
|
|
|
|
'lmError=' . MAINTENANCE_CODE );
|
2014-03-13 16:07:36 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
|
|
|
"Return maintenance error code", 'debug' );
|
|
|
|
return MAINTENANCE_CODE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Cross domain authentication
|
2014-05-22 14:21:28 +02:00
|
|
|
if ( $tsv->{cda}
|
2014-03-13 16:07:36 +01:00
|
|
|
and $args =~ s/[\?&]?($tsv->{cookieName}(http)?=\w+)$//oi )
|
|
|
|
{
|
|
|
|
my $str = $1;
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( 'CDA request', 'debug' );
|
|
|
|
$apacheRequest->args($args);
|
2014-05-23 12:23:51 +02:00
|
|
|
my $redirectUrl = $class->_buildUrl( $apacheRequest, $apacheRequest->uri );
|
2014-03-13 16:07:36 +01:00
|
|
|
my $redirectHttps = ( $redirectUrl =~ m/^https/ );
|
|
|
|
Lemonldap::NG::Handler::Main::Headers->lmSetErrHeaderOut(
|
|
|
|
$apacheRequest,
|
|
|
|
'Location' => $redirectUrl . ( $args ? "?" . $args : "" ) );
|
|
|
|
Lemonldap::NG::Handler::Main::Headers->lmSetErrHeaderOut(
|
|
|
|
$apacheRequest,
|
|
|
|
'Set-Cookie' => "$str; path=/"
|
|
|
|
. ( $redirectHttps ? "; secure" : "" )
|
2014-05-22 14:21:28 +02:00
|
|
|
. ( $tsv->{httpOnly} ? "; HttpOnly" : "" )
|
2014-03-13 16:07:36 +01:00
|
|
|
. (
|
2014-05-22 14:21:28 +02:00
|
|
|
$tsv->{cookieExpiration}
|
|
|
|
? "; expires=" . expires( $tsv->{cookieExpiration}, 'cookie' )
|
2014-03-13 16:07:36 +01:00
|
|
|
: ""
|
|
|
|
)
|
|
|
|
);
|
|
|
|
return REDIRECT;
|
|
|
|
}
|
|
|
|
my $uri = $apacheRequest->unparsed_uri();
|
|
|
|
my $uri_orig = $uri;
|
|
|
|
Apache2::URI::unescape_url($uri);
|
|
|
|
|
2014-05-23 12:23:51 +02:00
|
|
|
my $protection = $class->isUnprotected($apacheRequest, $uri);
|
2014-03-13 16:07:36 +01:00
|
|
|
|
|
|
|
if ( $protection == SKIP ) {
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( "Access control skipped",
|
|
|
|
"debug" );
|
2014-05-23 12:23:51 +02:00
|
|
|
$class->updateStatus( $apacheRequest, $class->ip($apacheRequest),
|
|
|
|
$apacheRequest->uri, 'SKIP' );
|
|
|
|
$class->hideCookie($apacheRequest);
|
2014-03-13 16:07:36 +01:00
|
|
|
Lemonldap::NG::Handler::Main::Headers->cleanHeaders( $apacheRequest,
|
|
|
|
$tsv->{forgeHeaders}, $tsv->{headerList} );
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
my $id;
|
|
|
|
|
|
|
|
# Try to recover cookie and user session
|
2014-05-23 12:23:51 +02:00
|
|
|
if ( $id = $class->fetchId($apacheRequest) and $class->retrieveSession($id) ) {
|
2014-03-13 16:07:36 +01:00
|
|
|
|
|
|
|
# AUTHENTICATION done
|
|
|
|
|
2014-04-11 18:12:21 +02:00
|
|
|
# Local macros
|
2014-03-13 16:07:36 +01:00
|
|
|
my $kc = keys %$datas; # in order to detect new local macro
|
|
|
|
|
|
|
|
# ACCOUNTING (1. Inform Apache)
|
|
|
|
$class->lmSetApacheUser( $apacheRequest,
|
|
|
|
$datas->{ $tsv->{whatToTrace} } );
|
|
|
|
|
|
|
|
# AUTHORIZATION
|
2014-05-23 12:23:51 +02:00
|
|
|
return $class->forbidden($apacheRequest, $uri)
|
|
|
|
unless ( $class->grant($apacheRequest, $uri) );
|
|
|
|
$class->updateStatus( $apacheRequest, $datas->{ $tsv->{whatToTrace} },
|
2014-03-13 16:07:36 +01:00
|
|
|
$apacheRequest->uri, 'OK' );
|
|
|
|
|
|
|
|
# ACCOUNTING (2. Inform remote application)
|
|
|
|
Lemonldap::NG::Handler::Main::Headers->sendHeaders( $apacheRequest,
|
|
|
|
$tsv->{forgeHeaders} );
|
|
|
|
|
|
|
|
# Store local macros
|
|
|
|
if ( keys %$datas > $kc and $tsv->{refLocalStorage} ) {
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( "Update local cache",
|
|
|
|
"debug" );
|
|
|
|
$tsv->{refLocalStorage}->set( $id, $datas, "10 minutes" );
|
|
|
|
}
|
|
|
|
|
|
|
|
# Hide Lemonldap::NG cookie
|
2014-05-23 12:23:51 +02:00
|
|
|
$class->hideCookie($apacheRequest);
|
2014-03-13 16:07:36 +01:00
|
|
|
|
|
|
|
# Log
|
|
|
|
$apacheRequest->push_handlers( PerlLogHandler =>
|
|
|
|
sub { $class->logGranted( $uri, $datas ); DECLINED }, );
|
|
|
|
|
|
|
|
# Catch POST rules
|
2014-05-23 12:23:51 +02:00
|
|
|
Lemonldap::NG::Handler::Main::PostForm->transformUri($apacheRequest, $uri);
|
2014-03-13 16:07:36 +01:00
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ( $protection == UNPROTECT ) {
|
|
|
|
|
|
|
|
# Ignore unprotected URIs
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
|
|
|
"No valid session but unprotected access", "debug" );
|
2014-05-23 12:23:51 +02:00
|
|
|
$class->updateStatus( $apacheRequest, $class->ip($apacheRequest),
|
|
|
|
$apacheRequest->uri, 'UNPROTECT' );
|
|
|
|
$class->hideCookie($apacheRequest);
|
2014-03-13 16:07:36 +01:00
|
|
|
Lemonldap::NG::Handler::Main::Headers->cleanHeaders( $apacheRequest,
|
|
|
|
$tsv->{forgeHeaders}, $tsv->{headerList} );
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
# Redirect user to the portal
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( "$class: No cookie found",
|
|
|
|
'info' )
|
|
|
|
unless ($id);
|
|
|
|
|
|
|
|
# if the cookie was fetched, a log is sent by retrieveSession()
|
2014-05-23 12:23:51 +02:00
|
|
|
$class->updateStatus( $apacheRequest, $class->ip($apacheRequest),
|
|
|
|
$apacheRequest->uri,
|
2014-03-13 16:07:36 +01:00
|
|
|
$id ? 'EXPIRED' : 'REDIRECT' );
|
2014-05-23 12:23:51 +02:00
|
|
|
return $class->goToPortal( $apacheRequest, $uri_orig );
|
2014-03-13 16:07:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected boolean checkMaintenanceMode
|
|
|
|
# Check if we are in maintenance mode
|
2014-05-23 12:23:51 +02:00
|
|
|
# @param $apacheRequest current request
|
2014-03-13 16:07:36 +01:00
|
|
|
# @return true if maintenance mode
|
|
|
|
sub checkMaintenanceMode {
|
2014-05-23 12:23:51 +02:00
|
|
|
my ( $class, $apacheRequest) = @_;
|
2014-03-13 16:07:36 +01:00
|
|
|
my $vhost = $apacheRequest->hostname;
|
|
|
|
my $_maintenance =
|
|
|
|
( defined $tsv->{maintenance}->{$vhost} )
|
|
|
|
? $tsv->{maintenance}->{$vhost}
|
|
|
|
: $tsv->{maintenance}->{_};
|
|
|
|
|
|
|
|
if ($_maintenance) {
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
|
|
|
"Maintenance mode activated", 'debug' );
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod int abort(string mess)
|
|
|
|
# Logs message and exit or redirect to the portal if "useRedirectOnError" is
|
|
|
|
# set to true.
|
2014-05-23 12:23:51 +02:00
|
|
|
# @param $apacheRequest current request
|
2014-03-13 16:07:36 +01:00
|
|
|
# @param $mess Message to log
|
|
|
|
# @return Apache2::Const::REDIRECT or Apache2::Const::SERVER_ERROR
|
|
|
|
sub abort {
|
2014-05-23 12:23:51 +02:00
|
|
|
my ( $class, $apacheRequest, $mess ) = splice @_;
|
2014-03-13 16:07:36 +01:00
|
|
|
|
|
|
|
# If abort is called without a valid request, fall to die
|
|
|
|
eval {
|
|
|
|
my $args = $apacheRequest->args;
|
|
|
|
my $uri = $apacheRequest->unparsed_uri();
|
|
|
|
|
|
|
|
# Set error 500 in logs even if "useRedirectOnError" is set
|
|
|
|
$apacheRequest->push_handlers(
|
|
|
|
PerlLogHandler => sub { $_[0]->status(SERVER_ERROR); DECLINED; } );
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( $mess, 'error' );
|
|
|
|
|
|
|
|
# Redirect or die
|
|
|
|
if ( $tsv->{useRedirectOnError} ) {
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
|
|
|
"Use redirect for error", 'debug' );
|
2014-05-23 12:23:51 +02:00
|
|
|
return $class->goToPortal( $apacheRequest, $uri, 'lmError=500' );
|
2014-03-13 16:07:36 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
return SERVER_ERROR;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
die $mess if ($@);
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected int handler_mp1()
|
|
|
|
# Launch run() when used under mod_perl version 1
|
|
|
|
# @return Apache constant
|
|
|
|
sub handler_mp1 ($$) { shift->run(@_); }
|
|
|
|
|
|
|
|
## @rmethod protected int logout_mp1()
|
|
|
|
# Launch unlog() when used under mod_perl version 1
|
|
|
|
# @return Apache constant
|
|
|
|
sub logout_mp1 ($$) { shift->unlog(@_); }
|
|
|
|
|
|
|
|
## @imethod void localInit(hashRef args)
|
|
|
|
# instanciate a LocalInit object with variables:
|
|
|
|
# localStorage, localStorageOptions, refLocalStorage, childInitDone
|
|
|
|
# launch localInit method:
|
|
|
|
# - calls purgeCache() to purge the local cache,
|
|
|
|
# - launch the status processus,
|
|
|
|
# - launch childInit (to init / clean local storage)
|
|
|
|
# @param $args reference to the initialization hash
|
|
|
|
sub localInit($$) {
|
|
|
|
my ( $class, $args ) = splice @_;
|
|
|
|
|
|
|
|
my $localinit = Lemonldap::NG::Handler::Initialization::LocalInit->new(
|
|
|
|
localStorage => $tsv->{localStorage},
|
|
|
|
refLocalStorage => $tsv->{refLocalStorage},
|
|
|
|
localStorageOptions => $tsv->{localStorageOptions},
|
|
|
|
childInitDone => $tsv->{childInitDone},
|
|
|
|
);
|
|
|
|
(
|
|
|
|
@$tsv{
|
2014-05-22 14:21:28 +02:00
|
|
|
qw( localStorage refLocalStorage localStorageOptions statusPipe statusOut childInitDone )
|
|
|
|
}
|
2014-03-13 16:07:36 +01:00
|
|
|
) = $localinit->localInit($args);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
## @imethod void globalInit(hashRef args)
|
|
|
|
# instanciate a GlobalInit object with variables:
|
|
|
|
# customFunctions, useSafeJail, and safe
|
|
|
|
# Global initialization process launches :
|
|
|
|
# - defaultValuesInit()
|
|
|
|
# - portalInit()
|
|
|
|
# - locationRulesInit()
|
|
|
|
# - globalStorageInit()
|
2014-04-02 10:22:30 +02:00
|
|
|
# - localSessionStorageInit()
|
2014-03-13 16:07:36 +01:00
|
|
|
# - headerListInit()
|
|
|
|
# - forgeHeadersInit()
|
|
|
|
# - postUrlInit()
|
|
|
|
# @param $args reference to the configuration hash
|
|
|
|
sub globalInit {
|
|
|
|
my $class = shift;
|
|
|
|
|
|
|
|
my $globalinit = Lemonldap::NG::Handler::Initialization::GlobalInit->new(
|
|
|
|
customFunctions => $tsv->{customFunctions},
|
|
|
|
useSafeJail => $tsv->{useSafeJail},
|
2014-05-22 14:21:28 +02:00
|
|
|
safe => $tsv->{safe},
|
2014-03-13 16:07:36 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
(
|
|
|
|
@$tsv{
|
2014-05-22 14:21:28 +02:00
|
|
|
qw( cookieName securedCookie whatToTrace
|
2014-03-13 16:07:36 +01:00
|
|
|
https port customFunctions
|
|
|
|
timeoutActivity useRedirectOnError useRedirectOnForbidden
|
2014-05-22 14:21:28 +02:00
|
|
|
useSafeJail key maintenance
|
|
|
|
cda httpOnly cookieExpiration
|
|
|
|
cipher )
|
2014-03-13 16:07:36 +01:00
|
|
|
}
|
|
|
|
)
|
|
|
|
= $globalinit->defaultValuesInit(
|
|
|
|
@$tsv{
|
2014-05-22 14:21:28 +02:00
|
|
|
qw( cookieName securedCookie whatToTrace
|
2014-03-13 16:07:36 +01:00
|
|
|
https port customFunctions
|
|
|
|
timeoutActivity useRedirectOnError useRedirectOnForbidden
|
2014-05-22 14:21:28 +02:00
|
|
|
useSafeJail key maintenance
|
|
|
|
cda httpOnly cookieExpiration
|
2014-03-13 16:07:36 +01:00
|
|
|
cipher )
|
|
|
|
},
|
|
|
|
@_
|
|
|
|
);
|
|
|
|
|
2014-05-22 14:21:28 +02:00
|
|
|
( *portal, $tsv->{safe} ) = $globalinit->portalInit( $class, @_ );
|
2014-03-13 16:07:36 +01:00
|
|
|
|
|
|
|
(
|
|
|
|
@$tsv{
|
|
|
|
qw( locationCount defaultCondition
|
|
|
|
defaultProtection locationCondition
|
|
|
|
locationProtection locationRegexp
|
2014-05-22 14:21:28 +02:00
|
|
|
locationConditionText safe )
|
|
|
|
}
|
2014-03-13 16:07:36 +01:00
|
|
|
)
|
|
|
|
= $globalinit->locationRulesInit(
|
|
|
|
$class,
|
|
|
|
@$tsv{
|
|
|
|
qw( locationCount defaultCondition
|
|
|
|
defaultProtection locationCondition
|
|
|
|
locationProtection locationRegexp
|
|
|
|
locationConditionText )
|
|
|
|
},
|
|
|
|
@_
|
|
|
|
);
|
|
|
|
|
|
|
|
@$tsv{qw( globalStorage globalStorageOptions )} =
|
|
|
|
$globalinit->globalStorageInit(
|
|
|
|
@$tsv{qw( globalStorage globalStorageOptions )}, @_ );
|
|
|
|
|
2014-04-02 10:22:30 +02:00
|
|
|
@$tsv{qw( localSessionStorage localSessionStorageOptions )} =
|
|
|
|
$globalinit->localSessionStorageInit(
|
|
|
|
@$tsv{qw( localSessionStorage localSessionStorageOptions )}, @_ );
|
|
|
|
|
2014-03-13 16:07:36 +01:00
|
|
|
$tsv->{headerList} = $globalinit->headerListInit( $tsv->{headerList}, @_ );
|
|
|
|
|
|
|
|
$tsv->{forgeHeaders} =
|
|
|
|
$globalinit->forgeHeadersInit( $tsv->{forgeHeaders}, @_ );
|
|
|
|
|
2014-05-22 14:21:28 +02:00
|
|
|
$tsv->{transform} = $globalinit->postUrlInit( $tsv->{transform}, @_ );
|
2014-03-13 16:07:36 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod boolean grant()
|
|
|
|
# Grant or refuse client using compiled regexp and functions
|
2014-05-23 12:23:51 +02:00
|
|
|
# @param $apacheRequest current request
|
|
|
|
# @param $uri URI
|
2014-03-13 16:07:36 +01:00
|
|
|
# @return True if the user is granted to access to the current URL
|
|
|
|
sub grant {
|
2014-05-23 12:23:51 +02:00
|
|
|
my ( $class, $apacheRequest, $uri ) = splice @_;
|
2014-03-13 16:07:36 +01:00
|
|
|
my $vhost = $apacheRequest->hostname;
|
|
|
|
for ( my $i = 0 ; $i < $tsv->{locationCount}->{$vhost} ; $i++ ) {
|
|
|
|
if ( $uri =~ $tsv->{locationRegexp}->{$vhost}->[$i] ) {
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
|
|
|
'Regexp "'
|
|
|
|
. $tsv->{locationConditionText}->{$vhost}->[$i]
|
|
|
|
. '" match',
|
|
|
|
'debug'
|
|
|
|
);
|
2014-05-22 17:08:18 +02:00
|
|
|
return &{ $tsv->{locationCondition}->{$vhost}->[$i] }($apacheRequest);
|
2014-03-13 16:07:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
unless ( $tsv->{defaultCondition}->{$vhost} ) {
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
|
|
|
"User rejected because VirtualHost \"$vhost\" has no configuration",
|
|
|
|
'warn'
|
|
|
|
);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( "$vhost: Apply default rule",
|
|
|
|
'debug' );
|
2014-05-22 17:08:18 +02:00
|
|
|
return &{ $tsv->{defaultCondition}->{$vhost} }($apacheRequest);
|
2014-03-13 16:07:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
## @cmethod private string _buildUrl(string s)
|
|
|
|
# Transform /<s> into http(s?)://<host>:<port>/s
|
2014-05-23 12:23:51 +02:00
|
|
|
# @param $apacheRequest current request
|
2014-03-13 16:07:36 +01:00
|
|
|
# @param $s path
|
|
|
|
# @return URL
|
|
|
|
sub _buildUrl {
|
2014-05-23 12:23:51 +02:00
|
|
|
my ( $class, $apacheRequest, $s ) = splice @_;
|
2014-03-13 16:07:36 +01:00
|
|
|
my $vhost = $apacheRequest->hostname;
|
|
|
|
my $portString =
|
|
|
|
$tsv->{port}->{$vhost}
|
|
|
|
|| $tsv->{port}->{_}
|
|
|
|
|| $apacheRequest->get_server_port();
|
|
|
|
my $_https = (
|
|
|
|
defined( $tsv->{https}->{$vhost} )
|
|
|
|
? $tsv->{https}->{$vhost}
|
|
|
|
: $tsv->{https}->{_}
|
|
|
|
);
|
|
|
|
$portString =
|
|
|
|
( $_https && $portString == 443 ) ? ''
|
|
|
|
: ( !$_https && $portString == 80 ) ? ''
|
|
|
|
: ':' . $portString;
|
|
|
|
my $url = "http"
|
|
|
|
. ( $_https ? "s" : "" ) . "://"
|
|
|
|
. $apacheRequest->get_server_name()
|
|
|
|
. $portString
|
|
|
|
. $s;
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( "Build URL $url", 'debug' );
|
|
|
|
return $url;
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod int unprotect()
|
|
|
|
# Used to unprotect an area.
|
|
|
|
# To use it, set "PerlHeaderParserHandler My::Package->unprotect" Apache
|
|
|
|
# configuration file.
|
|
|
|
# It replace run() by doing nothing.
|
|
|
|
# @return Apache2::Const::OK
|
|
|
|
sub unprotect {
|
|
|
|
OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected void localUnlog()
|
|
|
|
# Delete current user from local cache entry.
|
|
|
|
sub localUnlog {
|
|
|
|
my $class = shift;
|
2014-05-23 12:23:51 +02:00
|
|
|
if ( my $id = $class->fetchId($apacheRequest) ) {
|
2014-03-13 16:07:36 +01:00
|
|
|
|
|
|
|
# Delete Apache thread datas
|
|
|
|
if ( $id eq $datas->{_session_id} ) {
|
|
|
|
$datas = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
# Delete Apache local cache
|
|
|
|
if ( $tsv->{refLocalStorage} and $tsv->{refLocalStorage}->get($id) ) {
|
|
|
|
$tsv->{refLocalStorage}->remove($id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected int unlog(Apache::RequestRec apacheRequest)
|
|
|
|
# Call localUnlog() then goToPortal() to unlog the current user.
|
2014-05-23 12:23:51 +02:00
|
|
|
# @param $apacheRequest current request
|
2014-03-13 16:07:36 +01:00
|
|
|
# @return Apache2::Const value returned by goToPortal()
|
|
|
|
sub unlog ($$) {
|
2014-05-23 12:23:51 +02:00
|
|
|
my ( $class, $apacheRequest ) = @_;
|
2014-03-13 16:07:36 +01:00
|
|
|
$class->localUnlog;
|
2014-05-23 12:23:51 +02:00
|
|
|
$class->updateStatus( $apacheRequest, $class->ip($apacheRequest),
|
|
|
|
$apacheRequest->uri, 'LOGOUT' );
|
|
|
|
return $class->goToPortal( $apacheRequest, '/', 'logout=1' );
|
2014-03-13 16:07:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod int status(Apache2::RequestRec $r)
|
|
|
|
# Get the result from the status process and launch a PerlResponseHandler to
|
|
|
|
# display it.
|
|
|
|
# @param $r Current request
|
|
|
|
# @return Apache2::Const::OK
|
|
|
|
sub status($$) {
|
|
|
|
my ( $class, $r ) = splice @_;
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( "$class: request for status",
|
|
|
|
'debug' );
|
2014-05-23 12:23:51 +02:00
|
|
|
return $class->abort($r, "$class: status page can not be displayed")
|
2014-03-13 16:07:36 +01:00
|
|
|
unless ( $tsv->{statusPipe} and $tsv->{statusOut} );
|
|
|
|
$r->handler("perl-script");
|
|
|
|
print { $tsv->{statusPipe} } "STATUS"
|
|
|
|
. ( $r->args ? " " . $r->args : '' ) . "\n";
|
|
|
|
my $buf;
|
|
|
|
my $statusOut = $tsv->{statusOut};
|
|
|
|
while ($statusOut) {
|
|
|
|
last if (/^END$/);
|
|
|
|
$buf .= $_;
|
|
|
|
}
|
|
|
|
if ( MP() == 2 ) {
|
|
|
|
$r->push_handlers(
|
|
|
|
'PerlResponseHandler' => sub {
|
|
|
|
my $r = shift;
|
|
|
|
$r->content_type('text/html; charset=UTF-8');
|
|
|
|
$r->print($buf);
|
|
|
|
OK;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$r->push_handlers(
|
|
|
|
'PerlHandler' => sub {
|
|
|
|
my $r = shift;
|
|
|
|
$r->content_type('text/html; charset=UTF-8');
|
|
|
|
$r->send_http_header;
|
|
|
|
$r->print($buf);
|
|
|
|
OK;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected int redirectFilter(string url, Apache2::Filter f)
|
|
|
|
# Launch the current HTTP request then redirects the user to $url.
|
|
|
|
# Used by logout_app and logout_app_sso targets
|
|
|
|
# @param $url URL to redirect the user
|
|
|
|
# @param $f Current Apache2::Filter object
|
|
|
|
# @return Apache2::Const::OK
|
|
|
|
sub redirectFilter {
|
|
|
|
my $class = shift;
|
|
|
|
my $url = shift;
|
|
|
|
my $f = shift;
|
|
|
|
unless ( $f->ctx ) {
|
|
|
|
|
|
|
|
# Here, we can use Apache2 functions instead of lmSetHeaderOut because
|
|
|
|
# this function is used only with Apache2.
|
|
|
|
$f->r->status(REDIRECT);
|
|
|
|
$f->r->status_line("303 See Other");
|
|
|
|
$f->r->headers_out->unset('Location');
|
|
|
|
$f->r->err_headers_out->set( 'Location' => $url );
|
|
|
|
$f->ctx(1);
|
|
|
|
}
|
|
|
|
while ( $f->read( my $buffer, 1024 ) ) {
|
|
|
|
}
|
|
|
|
$class->updateStatus(
|
2014-05-23 12:23:51 +02:00
|
|
|
$apacheRequest,
|
2014-03-13 16:07:36 +01:00
|
|
|
(
|
|
|
|
$datas->{ $tsv->{whatToTrace} }
|
|
|
|
? $datas->{ $tsv->{whatToTrace} }
|
|
|
|
: $f->r->connection->remote_ip
|
|
|
|
),
|
|
|
|
'filter',
|
|
|
|
'REDIRECT'
|
|
|
|
);
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
## @rmethod protected int isUnprotected()
|
2014-05-23 12:23:51 +02:00
|
|
|
# @param $apacheRequest current request
|
|
|
|
# @param $uri URI
|
2014-03-13 16:07:36 +01:00
|
|
|
# @return 0 if URI is protected,
|
|
|
|
# UNPROTECT if it is unprotected by "unprotect",
|
|
|
|
# SKIP if is is unprotected by "skip"
|
|
|
|
sub isUnprotected {
|
2014-05-23 12:23:51 +02:00
|
|
|
my ( $class, $apacheRequest, $uri ) = splice @_;
|
2014-03-13 16:07:36 +01:00
|
|
|
my $vhost = $apacheRequest->hostname;
|
|
|
|
for ( my $i = 0 ; $i < $tsv->{locationCount}->{$vhost} ; $i++ ) {
|
|
|
|
if ( $uri =~ $tsv->{locationRegexp}->{$vhost}->[$i] ) {
|
|
|
|
return $tsv->{locationProtection}->{$vhost}->[$i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $tsv->{defaultProtection}->{$vhost};
|
|
|
|
}
|
|
|
|
|
|
|
|
1;
|