- Merging branch lemonldap-ng-experimental/Handler-Mouse with with trunk
code impacted: * lemonldap-ng-handler/*: handler code, * lemonldap-ng-handler/example/*.pm: handler aliases to libraries, * _example/etc/*.conf: virtual host templates (references #630, #LEMONLDAP-386)
This commit is contained in:
parent
a232f149fa
commit
f993e2e6dd
|
@ -6,7 +6,7 @@
|
|||
#NameVirtualHost __VHOSTLISTEN__
|
||||
|
||||
# Load LemonLDAP::NG Handler
|
||||
PerlRequire __HANDLER__
|
||||
PerlRequire Lemonldap/NG/Handler/DefaultHandler.pm
|
||||
|
||||
# Common error page and security parameters
|
||||
ErrorDocument 403 http://auth.__DNSDOMAIN__/?lmError=403
|
||||
|
@ -23,7 +23,7 @@ ErrorDocument 503 http://auth.__DNSDOMAIN__/?lmError=503
|
|||
Order deny,allow
|
||||
Deny from all
|
||||
Allow from 127.0.0.0/8
|
||||
PerlHeaderParserHandler My::Package->refresh
|
||||
PerlHeaderParserHandler Lemonldap::NG::Handler::DefaultHandler->refresh
|
||||
</Location>
|
||||
|
||||
# Uncomment this to activate status module
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
# Load LemonLDAP::NG Handler
|
||||
PerlOptions +GlobalRequest
|
||||
PerlRequire __HANDLER__
|
||||
PerlRequire Lemonldap/NG/Handler/DefaultHandler.pm
|
||||
|
||||
# Common error page and security parameters
|
||||
ErrorDocument 403 http://auth.__DNSDOMAIN__/?lmError=403
|
||||
|
@ -22,7 +22,7 @@ ErrorDocument 503 http://auth.__DNSDOMAIN__/?lmError=503
|
|||
# configuration change
|
||||
<Location /reload>
|
||||
Require all granted
|
||||
PerlHeaderParserHandler My::Package->refresh
|
||||
PerlHeaderParserHandler Lemonldap::NG::Handler::DefaultHandler->refresh
|
||||
</Location>
|
||||
|
||||
# Uncomment this to activate status module
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
# Load LemonLDAP::NG Handler
|
||||
PerlOptions +GlobalRequest
|
||||
PerlRequire __HANDLER__
|
||||
PerlRequire Lemonldap/NG/Handler/DefaultHandler.pm
|
||||
|
||||
# Common error page and security parameters
|
||||
ErrorDocument 403 http://auth.__DNSDOMAIN__/?lmError=403
|
||||
|
@ -24,7 +24,7 @@ ErrorDocument 503 http://auth.__DNSDOMAIN__/?lmError=503
|
|||
Order deny,allow
|
||||
Deny from all
|
||||
Allow from 127.0.0.0/8
|
||||
PerlHeaderParserHandler My::Package->refresh
|
||||
PerlHeaderParserHandler Lemonldap::NG::Handler::DefaultHandler->refresh
|
||||
</Location>
|
||||
|
||||
# Uncomment this to activate status module
|
||||
|
|
|
@ -92,8 +92,8 @@
|
|||
|
||||
# Uncomment this to increase performance of Portal:
|
||||
<Perl>
|
||||
#require Lemonldap::NG::Portal::SharedConf;
|
||||
#Lemonldap::NG::Portal::SharedConf->compile(
|
||||
#require Lemonldap::NG::Portal::DefaultHandler;
|
||||
#Lemonldap::NG::Portal::DefaultHandler->compile(
|
||||
# qw(delete header cache read_from_client cookie redirect unescapeHTML));
|
||||
# Uncomment this line if you use Lemonldap::NG menu
|
||||
#require Lemonldap::NG::Portal::Menu;
|
||||
|
|
|
@ -97,8 +97,8 @@
|
|||
|
||||
# Uncomment this to increase performance of Portal:
|
||||
<Perl>
|
||||
#require Lemonldap::NG::Portal::SharedConf;
|
||||
#Lemonldap::NG::Portal::SharedConf->compile(
|
||||
#require Lemonldap::NG::Portal::DefaultHandler;
|
||||
#Lemonldap::NG::Portal::DefaultHandler->compile(
|
||||
# qw(delete header cache read_from_client cookie redirect unescapeHTML));
|
||||
# Uncomment this line if you use Lemonldap::NG menu
|
||||
#require Lemonldap::NG::Portal::Menu;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
ServerAlias test2.__DNSDOMAIN__
|
||||
|
||||
# SSO protection
|
||||
PerlHeaderParserHandler My::Package
|
||||
PerlHeaderParserHandler Lemonldap::NG::Handler::DefaultHandler
|
||||
|
||||
# DocumentRoot
|
||||
DocumentRoot __TESTDIR__
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
ServerAlias test2.__DNSDOMAIN__
|
||||
|
||||
# SSO protection
|
||||
PerlHeaderParserHandler My::Package
|
||||
PerlHeaderParserHandler Lemonldap::NG::Handler::DefaultHandler
|
||||
|
||||
# DocumentRoot
|
||||
DocumentRoot __TESTDIR__
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package My::Package;
|
||||
use Lemonldap::NG::Handler::SharedConf;
|
||||
@ISA = qw(Lemonldap::NG::Handler::SharedConf);
|
||||
use Lemonldap::NG::Handler::DefaultHandler;
|
||||
@ISA = qw(Lemonldap::NG::Handler::DefaultHandler);
|
||||
|
||||
__PACKAGE__->init(
|
||||
{
|
||||
|
@ -18,7 +18,7 @@ __PACKAGE__->init(
|
|||
# You can specify by yourself this file :
|
||||
#configStorage => { confFile => '/path/to/my/file' },
|
||||
# You can also specify directly the configuration
|
||||
# (see Lemonldap::NG::Handler::SharedConf(3))
|
||||
# (see Lemonldap::NG::Handler::DefaultHandler(3))
|
||||
#configStorage => {
|
||||
# type => 'File',
|
||||
# dirName => '/usr/local/lemonldap-ng/data/conf/'
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
package My::AuthBasic;
|
||||
|
||||
# Load Auth Basic Handler
|
||||
use Lemonldap::NG::Handler::AuthBasic;
|
||||
@ISA = qw(Lemonldap::NG::Handler::AuthBasic);
|
||||
use Lemonldap::NG::Handler::SpecificHandlers::AuthBasic;
|
||||
@ISA = qw(Lemonldap::NG::Handler::SpecificHandlers::AuthBasic);
|
||||
|
||||
__PACKAGE__->init(
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package My::Package;
|
||||
use Lemonldap::NG::Handler::SharedConf;
|
||||
@ISA = qw(Lemonldap::NG::Handler::SharedConf);
|
||||
use Lemonldap::NG::Handler::DefaultHandler;
|
||||
@ISA = qw(Lemonldap::NG::Handler::DefaultHandler);
|
||||
|
||||
use Log::Log4perl;
|
||||
|
||||
|
@ -27,7 +27,7 @@ __PACKAGE__->init(
|
|||
#configStorage => { confFile => '/path/to/my/file' },
|
||||
|
||||
# You can also specify directly the configuration
|
||||
# (see Lemonldap::NG::Handler::SharedConf(3))
|
||||
# (see Lemonldap::NG::Handler::DefaultHandler(3))
|
||||
#configStorage => {
|
||||
# type => 'File',
|
||||
# dirName => '/usr/local/lemonldap-ng/data/conf/'
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
package My::SecureToken;
|
||||
|
||||
# Load Secure Token Handler
|
||||
use Lemonldap::NG::Handler::SecureToken;
|
||||
@ISA = qw(Lemonldap::NG::Handler::SecureToken);
|
||||
use Lemonldap::NG::Handler::SpecificHandlers::SecureToken;
|
||||
@ISA = qw(Lemonldap::NG::Handler::SpecificHandlers::SecureToken);
|
||||
|
||||
__PACKAGE__->init(
|
||||
{
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
package My::Sympa;
|
||||
|
||||
# Load Sympa Handler
|
||||
use Lemonldap::NG::Handler::SympaAutoLogin;
|
||||
@ISA = qw(Lemonldap::NG::Handler::SympaAutoLogin);
|
||||
use Lemonldap::NG::Handler::SpecificHandlers::SympaAutoLogin;
|
||||
@ISA = qw(Lemonldap::NG::Handler::SpecificHandlers::SympaAutoLogin);
|
||||
|
||||
__PACKAGE__->init(
|
||||
{
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
package My::Zimbra;
|
||||
|
||||
# Load Zimbra Handler
|
||||
use Lemonldap::NG::Handler::ZimbraPreAuth;
|
||||
@ISA = qw(Lemonldap::NG::Handler::ZimbraPreAuth);
|
||||
use Lemonldap::NG::Handler::SpecificHandlers::ZimbraPreAuth;
|
||||
@ISA = qw(Lemonldap::NG::Handler::SpecificHandlers::ZimbraPreAuth);
|
||||
|
||||
__PACKAGE__->init(
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Handler to manage update cookie
|
||||
package My::Package::UpdateCookie;
|
||||
|
||||
use Lemonldap::NG::Handler::UpdateCookie;
|
||||
@ISA = qw(Lemonldap::NG::Handler::UpdateCookie);
|
||||
use Lemonldap::NG::Handler::SpecificHandlers::UpdateCookie;
|
||||
@ISA = qw(Lemonldap::NG::Handler::SpecificHandlers::UpdateCookie);
|
||||
|
||||
__PACKAGE__->init(
|
||||
{
|
||||
|
|
|
@ -7,13 +7,15 @@ package Lemonldap::NG::Handler::AuthBasic;
|
|||
|
||||
use strict;
|
||||
|
||||
use Lemonldap::NG::Handler::SharedConf qw(:all);
|
||||
use Lemonldap::NG::Handler::DefaultHandler qw(:all);
|
||||
use Digest::MD5 qw(md5_base64);
|
||||
use MIME::Base64;
|
||||
use HTTP::Headers;
|
||||
use SOAP::Lite; # link protected portalRequest
|
||||
use Lemonldap::NG::Handler::Main::Headers;
|
||||
use Lemonldap::NG::Handler::Main::Logger;
|
||||
|
||||
use base qw(Lemonldap::NG::Handler::SharedConf);
|
||||
use base qw(Lemonldap::NG::Handler::DefaultHandler);
|
||||
use utf8;
|
||||
no utf8;
|
||||
|
||||
|
@ -42,7 +44,8 @@ sub run ($$) {
|
|||
( $class, $apacheRequest ) = splice @_;
|
||||
if ( time() - $lastReload > $reloadTime ) {
|
||||
unless ( my $tmp = $class->testConf(1) == OK ) {
|
||||
$class->lmLog( "$class: No configuration found", 'error' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"$class: No configuration found", 'error' );
|
||||
return $tmp;
|
||||
}
|
||||
}
|
||||
|
@ -53,8 +56,14 @@ sub run ($$) {
|
|||
# AUTHENTICATION
|
||||
# I - recover the WWW-Authentication header
|
||||
my ( $id, $user, $pass );
|
||||
unless ( $user = lmHeaderIn( $apacheRequest, 'Authorization' ) ) {
|
||||
lmSetErrHeaderOut( $apacheRequest,
|
||||
unless (
|
||||
$user = Lemonldap::NG::Handler::Main::Headers->lmHeaderIn(
|
||||
$apacheRequest, 'Authorization'
|
||||
)
|
||||
)
|
||||
{
|
||||
Lemonldap::NG::Handler::Main::Headers->lmSetErrHeaderOut(
|
||||
$apacheRequest,
|
||||
'WWW-Authenticate' => 'Basic realm="LemonLDAP::NG"' );
|
||||
return AUTH_REQUIRED;
|
||||
}
|
||||
|
@ -69,12 +78,16 @@ sub run ($$) {
|
|||
unless ( $id eq $datas->{_cache_id} ) {
|
||||
|
||||
# 2.2 search in the local cache if exists
|
||||
unless ( $refLocalStorage and $datas = $refLocalStorage->get($id) ) {
|
||||
unless ($tsv->{refLocalStorage}
|
||||
and $datas = $tsv->{refLocalStorage}->get($id) )
|
||||
{
|
||||
|
||||
# 2.3 Authentication by Lemonldap::NG::Portal using SOAP request
|
||||
|
||||
# Add client IP as X-Forwarded-For IP in SOAP request
|
||||
my $xheader = lmHeaderIn( $apacheRequest, 'X-Forwarded-For' );
|
||||
my $xheader =
|
||||
Lemonldap::NG::Handler::Main::Headers->lmHeaderIn( $apacheRequest,
|
||||
'X-Forwarded-For' );
|
||||
$xheader .= ", " if ($xheader);
|
||||
$xheader .= $class->ip();
|
||||
my $soapHeaders =
|
||||
|
@ -86,8 +99,8 @@ sub run ($$) {
|
|||
->uri('urn:Lemonldap::NG::Common::CGI::SOAPService');
|
||||
$user = decode_base64($user);
|
||||
( $user, $pass ) = ( $user =~ /^(.*?):(.*)$/ );
|
||||
$class->lmLog( "AuthBasic authentication for user: $user",
|
||||
'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"AuthBasic authentication for user: $user", 'debug' );
|
||||
my $r = $soap->getCookies( $user, $pass );
|
||||
my $cv;
|
||||
|
||||
|
@ -101,26 +114,30 @@ sub run ($$) {
|
|||
|
||||
# If authentication failed, display error
|
||||
if ( $res->{errorCode} ) {
|
||||
$class->lmLog(
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"Authentication failed for $user: "
|
||||
. $soap->error( $res->{errorCode}, 'en' )->result(),
|
||||
'notice'
|
||||
);
|
||||
lmSetErrHeaderOut( $apacheRequest,
|
||||
Lemonldap::NG::Handler::Main::Headers->lmSetErrHeaderOut(
|
||||
$apacheRequest,
|
||||
'WWW-Authenticate' => 'Basic realm="LemonLDAP::NG"' );
|
||||
return AUTH_REQUIRED;
|
||||
}
|
||||
$cv = $res->{cookies}->{$cookieName};
|
||||
$cv = $res->{cookies}->{ $tsv->{cookieName} };
|
||||
}
|
||||
|
||||
# Now, normal work to find session
|
||||
my %h;
|
||||
eval { tie %h, $globalStorage, $cv, $globalStorageOptions; };
|
||||
eval {
|
||||
tie %h, $tsv->{globalStorage}, $cv,
|
||||
$tsv->{globalStorageOptions};
|
||||
};
|
||||
if ($@) {
|
||||
|
||||
# The cookie isn't yet available
|
||||
$class->lmLog( "The cookie $cv isn't yet available: $@",
|
||||
'info' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"The cookie $cv isn't yet available: $@", 'info' );
|
||||
$class->updateStatus( $class->ip(), $apacheRequest->uri,
|
||||
'EXPIRED' );
|
||||
return $class->goToPortal($uri);
|
||||
|
@ -129,8 +146,8 @@ sub run ($$) {
|
|||
$datas->{_cache_id} = $id;
|
||||
|
||||
# Store now the user in the local storage
|
||||
if ($refLocalStorage) {
|
||||
$refLocalStorage->set( $id, $datas, "20 minutes" );
|
||||
if ( $tsv->{refLocalStorage} ) {
|
||||
$tsv->{refLocalStorage}->set( $id, $datas, "20 minutes" );
|
||||
}
|
||||
untie %h;
|
||||
}
|
||||
|
@ -138,11 +155,12 @@ sub run ($$) {
|
|||
|
||||
# ACCOUNTING
|
||||
# 1 - Inform Apache
|
||||
$class->lmSetApacheUser( $apacheRequest, $datas->{$whatToTrace} );
|
||||
$class->lmSetApacheUser( $apacheRequest, $datas->{ $tsv->{whatToTrace} } );
|
||||
|
||||
# AUTHORIZATION
|
||||
return $class->forbidden($uri) unless ( $class->grant($uri) );
|
||||
$class->updateStatus( $datas->{$whatToTrace}, $apacheRequest->uri, 'OK' );
|
||||
$class->updateStatus( $datas->{ $tsv->{whatToTrace} },
|
||||
$apacheRequest->uri, 'OK' );
|
||||
$class->logGranted( $uri, $datas );
|
||||
|
||||
# SECURITY
|
||||
|
@ -150,11 +168,12 @@ sub run ($$) {
|
|||
$class->hideCookie;
|
||||
|
||||
# Hide user password
|
||||
$class->lmUnsetHeaderIn( $apacheRequest, "Authorization" );
|
||||
Lemonldap::NG::Handler::Main::Headers->lmUnsetHeaderIn( $apacheRequest,
|
||||
"Authorization" );
|
||||
|
||||
# ACCOUNTING
|
||||
# 2 - Inform remote application
|
||||
$class->sendHeaders;
|
||||
Lemonldap::NG::Handler::Main::Headers->sendHeaders;
|
||||
OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,11 +7,11 @@ package Lemonldap::NG::Handler::CDA;
|
|||
|
||||
use strict;
|
||||
|
||||
use Lemonldap::NG::Handler::SharedConf qw(:all);
|
||||
use Lemonldap::NG::Handler::DefaultHandler qw(:all);
|
||||
|
||||
our $VERSION = '1.2.2';
|
||||
|
||||
use base qw(Lemonldap::NG::Handler::SharedConf);
|
||||
use base qw(Lemonldap::NG::Handler::DefaultHandler);
|
||||
|
||||
## @rmethod int run(Apache2::RequestRec apacheRequest)
|
||||
# overload run subroutine to implement cross-domain mechanism.
|
||||
|
@ -20,7 +20,7 @@ use base qw(Lemonldap::NG::Handler::SharedConf);
|
|||
sub run ($$) {
|
||||
my $class;
|
||||
( $class, $apacheRequest ) = splice @_;
|
||||
$cda = 1;
|
||||
$ntsv->{cda} = 1;
|
||||
return $class->SUPER::run($apacheRequest);
|
||||
}
|
||||
|
||||
|
@ -80,18 +80,18 @@ configuration reload, so you don't need to restart Apache at each change :
|
|||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This library inherit from L<Lemonldap::NG::Handler::SharedConf> and add the
|
||||
This library inherit from L<Lemonldap::NG::Handler::DefaultHandler> and add the
|
||||
capability to control users that are authenticated with a
|
||||
L<Lemonldap::NG::Portal::CDA> CGI in another domain.
|
||||
|
||||
=head2 EXPORT
|
||||
|
||||
Same as L<Lemonldap::NG::Handler::SharedConf>.
|
||||
Same as L<Lemonldap::NG::Handler::DefaultHandler>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Lemonldap::NG::Manager>, L<Lemonldap::NG::Handler>,
|
||||
L<Lemonldap::NG::Handler::SharedConf>,
|
||||
L<Lemonldap::NG::Handler::DefaultHandler>,
|
||||
L<http://lemonldap-ng.org/>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
|
|
@ -13,7 +13,7 @@ use MIME::Base64;
|
|||
|
||||
use base qw(Lemonldap::NG::Common::CGI);
|
||||
|
||||
use Lemonldap::NG::Handler::SharedConf qw(:all);
|
||||
use Lemonldap::NG::Handler::DefaultHandler qw(:all);
|
||||
|
||||
#link Lemonldap::NG::Handler::_CGI protected _handler
|
||||
|
||||
|
@ -27,9 +27,10 @@ sub new {
|
|||
my $class = shift;
|
||||
my $self = $class->SUPER::new() or $class->abort("Unable to build CGI");
|
||||
$Lemonldap::NG::Handler::_CGI::_cgi = $self;
|
||||
unless ($Lemonldap::NG::Handler::_CGI::cookieName) {
|
||||
unless ( $Lemonldap::NG::Handler::_CGI::tsv->{cookieName} ) {
|
||||
Lemonldap::NG::Handler::_CGI->init(@_);
|
||||
Lemonldap::NG::Handler::_CGI->initLocalStorage(@_);
|
||||
|
||||
#Lemonldap::NG::Handler::_CGI->initLocalStorage(@_); # already called by _CGI->init()
|
||||
}
|
||||
unless ( eval { Lemonldap::NG::Handler::_CGI->testConf() } == OK ) {
|
||||
if ( $_[0]->{noAbort} ) {
|
||||
|
@ -65,8 +66,9 @@ sub new {
|
|||
$rule =~ s/\$(\w+)/\$datas->{$1}/g;
|
||||
$rule = 0 if ( $rule eq 'deny' );
|
||||
my $r;
|
||||
|
||||
unless ( $rule eq 'accept'
|
||||
or Lemonldap::NG::Handler::_CGI->safe->reval($rule) )
|
||||
or Lemonldap::NG::Handler::_CGI->safe_reval($rule) )
|
||||
{
|
||||
$self->abort( 'Forbidden',
|
||||
"You don't have rights to access this page" );
|
||||
|
@ -95,26 +97,33 @@ sub authenticate {
|
|||
if ( $self->{_noConf} );
|
||||
my %cookies = fetch CGI::Cookie;
|
||||
my $id;
|
||||
unless ( $cookies{$cookieName} and $id = $cookies{$cookieName}->value ) {
|
||||
unless ($cookies{ $tsv->{cookieName} }
|
||||
and $id = $cookies{ $tsv->{cookieName} }->value )
|
||||
{
|
||||
return $self->goToPortal();
|
||||
}
|
||||
unless ( $datas and $id eq $datas->{_session_id} ) {
|
||||
unless ( $refLocalStorage and $datas = $refLocalStorage->get($id) ) {
|
||||
unless ($tsv->{refLocalStorage}
|
||||
and $datas = $tsv->{refLocalStorage}->get($id) )
|
||||
{
|
||||
my %h;
|
||||
eval { tie %h, $globalStorage, $id, $globalStorageOptions; };
|
||||
eval {
|
||||
tie %h, $tsv->{globalStorage}, $id,
|
||||
$tsv->{globalStorageOptions};
|
||||
};
|
||||
if ($@) {
|
||||
return $self->goToPortal();
|
||||
}
|
||||
$datas->{$_} = $h{$_} foreach ( keys %h );
|
||||
if ($refLocalStorage) {
|
||||
$refLocalStorage->set( $id, $datas, "10 minutes" );
|
||||
if ( $tsv->{refLocalStorage} ) {
|
||||
$tsv->{refLocalStorage}->set( $id, $datas, "10 minutes" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Accounting : set user in apache logs
|
||||
$self->setApacheUser( $datas->{$whatToTrace} );
|
||||
$ENV{REMOTE_USER} = $datas->{$whatToTrace};
|
||||
$self->setApacheUser( $datas->{ $tsv->{whatToTrace} } );
|
||||
$ENV{REMOTE_USER} = $datas->{ $tsv->{whatToTrace} };
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -176,11 +185,14 @@ sub goToPortal {
|
|||
sub _uri {
|
||||
my $vhost = $ENV{SERVER_NAME};
|
||||
my $portString =
|
||||
$port->{$vhost}
|
||||
|| $port->{_}
|
||||
$tsv->{port}->{$vhost}
|
||||
|| $tsv->{port}->{_}
|
||||
|| $ENV{SERVER_PORT};
|
||||
my $_https =
|
||||
( defined( $https->{$vhost} ) ? $https->{$vhost} : $https->{_} );
|
||||
my $_https = (
|
||||
defined( $tsv->{https}->{$vhost} )
|
||||
? $tsv->{https}->{$vhost}
|
||||
: $tsv->{https}->{_}
|
||||
);
|
||||
$portString =
|
||||
( $_https && $portString == 443 ) ? ''
|
||||
: ( !$_https && $portString == 80 ) ? ''
|
||||
|
@ -198,12 +210,29 @@ sub _uri {
|
|||
package Lemonldap::NG::Handler::_CGI;
|
||||
|
||||
use strict;
|
||||
use Lemonldap::NG::Handler::SharedConf qw(:locationRules :localStorage :traces);
|
||||
|
||||
use base qw(Lemonldap::NG::Handler::SharedConf);
|
||||
#use Lemonldap::NG::Handler::DefaultHandler qw(:locationRules :localStorage :traces);
|
||||
use Lemonldap::NG::Handler::DefaultHandler qw(:tsv :ntsv :jailSharedVars);
|
||||
use Lemonldap::NG::Handler::Main::Jail;
|
||||
|
||||
use base qw(Lemonldap::NG::Handler::DefaultHandler);
|
||||
|
||||
our $_cgi;
|
||||
|
||||
sub safe_reval {
|
||||
my $class = shift;
|
||||
my $rule = shift;
|
||||
|
||||
my $jail = Lemonldap::NG::Handler::Main::Jail->new(
|
||||
'safe' => $ntsv->{safe},
|
||||
'useSafeJail' => $tsv->{useSafeJail},
|
||||
'customFunctions' => $tsv->{customFunctions}
|
||||
);
|
||||
$ntsv->{safe} = $jail->build_safe();
|
||||
|
||||
return $ntsv->{safe}->reval($rule);
|
||||
}
|
||||
|
||||
## @method boolean childInit()
|
||||
# Since this is not a real Apache handler, childs have not to be initialized.
|
||||
# @return true
|
||||
|
@ -229,7 +258,7 @@ sub lmLog {
|
|||
# @return boolean : true if $vhost is available
|
||||
sub vhostAvailable {
|
||||
my ( $self, $vhost ) = splice @_;
|
||||
return defined( $defaultCondition->{$vhost} );
|
||||
return defined( $tsv->{defaultCondition}->{$vhost} );
|
||||
}
|
||||
|
||||
## @method boolean grant(string uri, string vhost)
|
||||
|
@ -246,19 +275,19 @@ sub grant {
|
|||
args => '',
|
||||
}
|
||||
);
|
||||
for ( my $i = 0 ; $i < $locationCount->{$vhost} ; $i++ ) {
|
||||
if ( $uri =~ $locationRegexp->{$vhost}->[$i] ) {
|
||||
return &{ $locationCondition->{$vhost}->[$i] }($datas);
|
||||
for ( my $i = 0 ; $i < $tsv->{locationCount}->{$vhost} ; $i++ ) {
|
||||
if ( $uri =~ $tsv->{locationRegexp}->{$vhost}->[$i] ) {
|
||||
return &{ $tsv->{locationCondition}->{$vhost}->[$i] }($datas);
|
||||
}
|
||||
}
|
||||
unless ( $defaultCondition->{$vhost} ) {
|
||||
unless ( $tsv->{defaultCondition}->{$vhost} ) {
|
||||
$self->lmLog(
|
||||
"User rejected because VirtualHost \"$vhost\" has no configuration",
|
||||
'warn'
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
return &{ $defaultCondition->{$vhost} }($datas);
|
||||
return &{ $tsv->{defaultCondition}->{$vhost} }($datas);
|
||||
}
|
||||
|
||||
package Lemonldap::NG::Apache::Request;
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
package Lemonldap::NG::Handler::Menu;
|
||||
|
||||
use strict;
|
||||
use Lemonldap::NG::Handler::SharedConf qw(:all);
|
||||
use base qw(Lemonldap::NG::Handler::SharedConf);
|
||||
use Lemonldap::NG::Handler::DefaultHandler qw(:all);
|
||||
use base qw(Lemonldap::NG::Handler::DefaultHandler);
|
||||
use Apache2::Filter ();
|
||||
use constant BUFF_LEN => 1024;
|
||||
|
||||
|
|
|
@ -7,8 +7,10 @@ package Lemonldap::NG::Handler::Proxy;
|
|||
|
||||
use strict;
|
||||
|
||||
use Lemonldap::NG::Handler::Simple qw(:apache :headers :traces);
|
||||
use Lemonldap::NG::Handler::Main qw(:apache :headers :tsv);
|
||||
use LWP::UserAgent;
|
||||
use Lemonldap::NG::Handler::Main::Headers;
|
||||
use Lemonldap::NG::Handler::Main::Logger;
|
||||
|
||||
our $VERSION = '1.2.0';
|
||||
|
||||
|
@ -35,7 +37,7 @@ sub handler_mp2 : method {
|
|||
shift->run(@_);
|
||||
}
|
||||
|
||||
*lmLog = *Lemonldap::NG::Handler::Simple::lmLog;
|
||||
*lmLog = *Lemonldap::NG::Handler::Main::lmLog;
|
||||
|
||||
########
|
||||
# MAIN #
|
||||
|
@ -75,7 +77,7 @@ sub run($$) {
|
|||
sub {
|
||||
return 1 if ( $_[1] =~ /^$/ );
|
||||
$request->header(@_) unless ( $_[0] =~ /^(Host|Referer)$/i );
|
||||
$class->lmLog(
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"$class: header pushed to the server: " . $_[0] . ": " . $_[1],
|
||||
'debug'
|
||||
);
|
||||
|
@ -148,9 +150,9 @@ sub headers {
|
|||
and $cookieDomain_new
|
||||
and $_[0] =~ /Set-Cookie/i );
|
||||
|
||||
lmSetErrHeaderOut( $r, @_ );
|
||||
Lemonldap::NG::Handler::Main::Headers->lmSetErrHeaderOut( $r, @_ );
|
||||
|
||||
$class->lmLog(
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"$class: header pushed to the client: " . $_[0] . ": " . $_[1],
|
||||
'debug'
|
||||
);
|
||||
|
|
|
@ -8,10 +8,12 @@
|
|||
package Lemonldap::NG::Handler::SecureToken;
|
||||
|
||||
use strict;
|
||||
use Lemonldap::NG::Handler::SharedConf qw(:all);
|
||||
use base qw(Lemonldap::NG::Handler::SharedConf);
|
||||
use Lemonldap::NG::Handler::DefaultHandler qw(:all);
|
||||
use base qw(Lemonldap::NG::Handler::DefaultHandler);
|
||||
use Cache::Memcached;
|
||||
use Apache::Session::Generate::MD5;
|
||||
use Lemonldap::NG::Handler::Main::Headers;
|
||||
use Lemonldap::NG::Handler::Main::Logger;
|
||||
|
||||
our $VERSION = '1.1.2';
|
||||
|
||||
|
@ -65,22 +67,26 @@ sub defaultValuesInit {
|
|||
foreach (qw/secureTokenMemcachedServers secureTokenUrls/) {
|
||||
no strict 'refs';
|
||||
unless ( ref ${$_} eq "ARRAY" ) {
|
||||
$class->lmLog( "Transform $_ value into an array reference",
|
||||
'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"Transform $_ value into an array reference", 'debug' );
|
||||
my @array = split( /\s+/, ${$_} );
|
||||
${$_} = \@array;
|
||||
}
|
||||
}
|
||||
|
||||
# Display found values in debug mode
|
||||
$class->lmLog( "secureTokenMemcachedServers: @$secureTokenMemcachedServers",
|
||||
'debug' );
|
||||
$class->lmLog( "secureTokenExpiration: $secureTokenExpiration", 'debug' );
|
||||
$class->lmLog( "secureTokenAttribute: $secureTokenAttribute", 'debug' );
|
||||
$class->lmLog( "secureTokenUrls: @$secureTokenUrls", 'debug' );
|
||||
$class->lmLog( "secureTokenHeader: $secureTokenHeader", 'debug' );
|
||||
$class->lmLog( "secureTokenAllowOnError: $secureTokenAllowOnError",
|
||||
'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"secureTokenMemcachedServers: @$secureTokenMemcachedServers", 'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"secureTokenExpiration: $secureTokenExpiration", 'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"secureTokenAttribute: $secureTokenAttribute", 'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"secureTokenUrls: @$secureTokenUrls", 'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"secureTokenHeader: $secureTokenHeader", 'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"secureTokenAllowOnError: $secureTokenAllowOnError", 'debug' );
|
||||
|
||||
# Delete Secure Token parameters
|
||||
delete $args->{'secureTokenMemcachedServers'};
|
||||
|
@ -115,8 +121,8 @@ sub run {
|
|||
foreach (@$secureTokenUrls) {
|
||||
if ( $uri =~ m#$_# ) {
|
||||
$checkurl = 1;
|
||||
$class->lmLog( "URL $uri detected as an Secure Token URL (rule $_)",
|
||||
'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"URL $uri detected as an Secure Token URL (rule $_)", 'debug' );
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
@ -138,7 +144,8 @@ sub run {
|
|||
return $class->_returnError() unless $key;
|
||||
|
||||
# Header location
|
||||
$class->lmSetHeaderIn( $r, $secureTokenHeader => $key );
|
||||
Lemonldap::NG::Handler::Main::Headers->lmSetHeaderIn( $r,
|
||||
$secureTokenHeader => $key );
|
||||
|
||||
# Remove token
|
||||
eval 'use Apache2::Filter' unless ( $INC{"Apache2/Filter.pm"} );
|
||||
|
@ -172,7 +179,8 @@ sub _createMemcachedConnection {
|
|||
'debug' => 0,
|
||||
};
|
||||
|
||||
$class->lmLog( "Memcached connection created", 'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog( "Memcached connection created",
|
||||
'debug' );
|
||||
|
||||
return $memd;
|
||||
}
|
||||
|
@ -191,11 +199,13 @@ sub _setToken {
|
|||
$secureTokenExpiration );
|
||||
|
||||
unless ($res) {
|
||||
$class->lmLog( "Unable to store secure token $key", 'error' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"Unable to store secure token $key", 'error' );
|
||||
return;
|
||||
}
|
||||
|
||||
$class->lmLog( "Set $value in token $key", 'info' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog( "Set $value in token $key",
|
||||
'info' );
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
@ -210,10 +220,12 @@ sub _deleteToken {
|
|||
my $res = $secureTokenMemcachedConnection->delete($key);
|
||||
|
||||
unless ($res) {
|
||||
$class->lmLog( "Unable to delete secure token $key", 'error' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"Unable to delete secure token $key", 'error' );
|
||||
}
|
||||
else {
|
||||
$class->lmLog( "Token $key deleted", 'info' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog( "Token $key deleted",
|
||||
'info' );
|
||||
}
|
||||
|
||||
return $res;
|
||||
|
@ -234,7 +246,7 @@ sub _isAlive {
|
|||
my $total_c = $stats->{'total'}->{'connection_structures'};
|
||||
my $total_i = $stats->{'total'}->{'total_items'};
|
||||
|
||||
$class->lmLog(
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"Memcached connection is alive ($total_c connections / $total_i items)",
|
||||
'debug'
|
||||
);
|
||||
|
@ -242,7 +254,8 @@ sub _isAlive {
|
|||
return 1;
|
||||
}
|
||||
|
||||
$class->lmLog( "Memcached connection is not alive", 'error' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"Memcached connection is not alive", 'error' );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -254,18 +267,20 @@ sub _returnError {
|
|||
my ($class) = splice @_;
|
||||
|
||||
if ($secureTokenAllowOnError) {
|
||||
$class->lmLog( "Allow request without secure token", 'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"Allow request without secure token", 'debug' );
|
||||
return OK;
|
||||
}
|
||||
|
||||
# Redirect or Forbidden?
|
||||
if ($useRedirectOnError) {
|
||||
$class->lmLog( "Use redirect for error", 'debug' );
|
||||
if ( $tsv->{useRedirectOnError} ) {
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog( "Use redirect for error",
|
||||
'debug' );
|
||||
return $class->goToPortal( '/', 'lmError=500' );
|
||||
}
|
||||
|
||||
else {
|
||||
$class->lmLog( "Return error", 'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog( "Return error", 'debug' );
|
||||
return SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,354 +0,0 @@
|
|||
## @file
|
||||
# Main handler.
|
||||
|
||||
## @class
|
||||
# Main handler.
|
||||
# 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 initialization process is splitted in two parts :
|
||||
# - init() is launched as Apache startup
|
||||
# - globalInit() is launched at each first request received by an Apache child
|
||||
# and each time a new configuration is detected
|
||||
package Lemonldap::NG::Handler::SharedConf;
|
||||
|
||||
use strict;
|
||||
|
||||
use Lemonldap::NG::Handler::Simple qw(:all);
|
||||
use Lemonldap::NG::Handler::Vhost;
|
||||
use Lemonldap::NG::Common::Conf; #link protected lmConf
|
||||
use Lemonldap::NG::Common::Conf::Constants; #inherits
|
||||
use Cache::Cache qw($EXPIRES_NEVER);
|
||||
|
||||
use base qw(Lemonldap::NG::Handler::Vhost Lemonldap::NG::Handler::Simple);
|
||||
|
||||
#parameter reloadTime Time in second between 2 configuration check (600)
|
||||
|
||||
our $VERSION = '1.1.1';
|
||||
our $cfgNum = 0;
|
||||
our $lastReload = 0;
|
||||
our $reloadTime;
|
||||
our $lmConf;
|
||||
our $localConfig;
|
||||
|
||||
BEGIN {
|
||||
if ( MP() == 2 ) {
|
||||
eval {
|
||||
require threads::shared;
|
||||
Apache2::RequestUtil->import();
|
||||
threads::shared::share($cfgNum);
|
||||
threads::shared::share($lastReload);
|
||||
threads::shared::share($reloadTime);
|
||||
threads::shared::share($lmConf);
|
||||
threads::shared::share($localConfig);
|
||||
};
|
||||
}
|
||||
*EXPORT_TAGS = *Lemonldap::NG::Handler::Simple::EXPORT_TAGS;
|
||||
*EXPORT_OK = *Lemonldap::NG::Handler::Simple::EXPORT_OK;
|
||||
push(
|
||||
@{ $EXPORT_TAGS{$_} },
|
||||
qw($cfgNum $lastReload $reloadTime $lmConf $localConfig)
|
||||
) foreach (qw(variables localStorage));
|
||||
push @EXPORT_OK, qw($cfgNum $lastReload $reloadTime $lmConf $localConfig);
|
||||
}
|
||||
|
||||
# INIT PROCESS
|
||||
|
||||
## @imethod void init(hashRef args)
|
||||
# Constructor.
|
||||
# init is overloaded to call only localInit. globalInit is called later.
|
||||
# @param $args hash containing parameters
|
||||
sub init($$) {
|
||||
my ( $class, $args ) = splice @_;
|
||||
|
||||
# TODO reloadTime in defaultValuesInit ?
|
||||
$reloadTime = $args->{reloadTime} || 600;
|
||||
$class->localInit($args);
|
||||
}
|
||||
|
||||
## @imethod protected void defaultValuesInit(hashRef args)
|
||||
# Set default values for non-customized variables
|
||||
# @param $args hash containing parameters
|
||||
# @return boolean
|
||||
sub defaultValuesInit {
|
||||
my ( $class, $args ) = splice @_;
|
||||
|
||||
# Local configuration overrides global configuration
|
||||
my %h = ( %$args, %$localConfig );
|
||||
return $class->SUPER::defaultValuesInit( \%h );
|
||||
}
|
||||
|
||||
## @imethod void localInit(hashRef args)
|
||||
# Load parameters and build the Lemonldap::NG::Common::Conf object.
|
||||
# @return boolean
|
||||
sub localInit {
|
||||
my ( $class, $args ) = splice @_;
|
||||
die(
|
||||
"$class : unable to build configuration : $Lemonldap::NG::Common::Conf::msg"
|
||||
)
|
||||
unless ( $lmConf =
|
||||
Lemonldap::NG::Common::Conf->new( $args->{configStorage} ) );
|
||||
|
||||
# Get local configuration parameters
|
||||
my $localconf = $lmConf->getLocalConf(HANDLERSECTION);
|
||||
if ($localconf) {
|
||||
$args->{$_} ||= $localconf->{$_} foreach ( keys %$localconf );
|
||||
}
|
||||
|
||||
# Store in localConfig global variable
|
||||
$localConfig = $args;
|
||||
|
||||
# localStorage can be declared in configStorage or at the root or both
|
||||
foreach (qw(localStorage localStorageOptions)) {
|
||||
$args->{$_} ||= $args->{configStorage}->{$_} || $lmConf->{$_};
|
||||
$args->{configStorage}->{$_} ||= $args->{$_};
|
||||
}
|
||||
|
||||
$class->defaultValuesInit($args);
|
||||
$class->SUPER::localInit($args);
|
||||
}
|
||||
|
||||
# MAIN
|
||||
|
||||
## @rmethod int run(Apache2::RequestRec r)
|
||||
# Check configuration and launch Lemonldap::NG::Handler::Simple::run().
|
||||
# Each $reloadTime, the Apache child verify if its configuration is the same
|
||||
# as the configuration stored in the local storage.
|
||||
# @param $r Apache2::RequestRec object
|
||||
# @return Apache constant
|
||||
sub run($$) {
|
||||
my ( $class, $r ) = splice @_;
|
||||
if ( time() - $lastReload > $reloadTime ) {
|
||||
die("$class: No configuration found")
|
||||
unless ( $class->testConf(1) == OK );
|
||||
}
|
||||
return $class->SUPER::run($r);
|
||||
}
|
||||
|
||||
# CONFIGURATION UPDATE
|
||||
|
||||
## @rmethod protected int testConf(boolean local)
|
||||
# Test if configuration has changed and launch setConf() if needed.
|
||||
# If the optional boolean $local is true, remote configuration is not tested:
|
||||
# only local cached configuration is tested if available. $local is given to
|
||||
# Lemonldap::NG::Common::getConf()
|
||||
# @param $local boolean
|
||||
# @return Apache constant
|
||||
sub testConf {
|
||||
my ( $class, $local ) = splice @_;
|
||||
my $conf = $lmConf->getConf( { local => $local } );
|
||||
unless ( ref($conf) ) {
|
||||
$class->lmLog(
|
||||
"$class: Unable to load configuration: $Lemonldap::NG::Common::Conf::msg",
|
||||
'error'
|
||||
);
|
||||
return $cfgNum ? OK : SERVER_ERROR;
|
||||
}
|
||||
if ( !$cfgNum or $cfgNum != $conf->{cfgNum} ) {
|
||||
$class->lmLog(
|
||||
"$class: get configuration $conf->{cfgNum} ($Lemonldap::NG::Common::Conf::msg)",
|
||||
'debug'
|
||||
);
|
||||
$lastReload = time();
|
||||
return $class->setConf($conf);
|
||||
}
|
||||
$class->lmLog( "$class: configuration is up to date", 'debug' );
|
||||
OK;
|
||||
}
|
||||
|
||||
## @rmethod protected int setConf(hashRef conf)
|
||||
# Launch globalInit().
|
||||
# Local parameters have best precedence on configuration parameters.
|
||||
# @return Apache constant
|
||||
sub setConf {
|
||||
my ( $class, $conf ) = splice @_;
|
||||
|
||||
# Local configuration overrides global configuration
|
||||
$cfgNum = $conf->{cfgNum};
|
||||
$conf->{$_} = $localConfig->{$_} foreach ( keys %$localConfig );
|
||||
$class->globalInit($conf);
|
||||
OK;
|
||||
}
|
||||
|
||||
# RELOAD SYSTEM
|
||||
|
||||
*reload = *refresh;
|
||||
|
||||
## @rmethod int refresh(Apache::RequestRec r)
|
||||
# Launch testConf() with $local=0, so remote configuration is tested.
|
||||
# Then build a simple HTTP response that just returns "200 OK" or
|
||||
# "500 Server Error".
|
||||
# @param $r current request
|
||||
# @return Apache constant (OK or SERVER_ERROR)
|
||||
sub refresh($$) {
|
||||
my ( $class, $r ) = splice @_;
|
||||
$class->lmLog( "$class: request for configuration reload", 'notice' );
|
||||
$r->handler("perl-script");
|
||||
if ( $class->testConf(0) == OK ) {
|
||||
if ( MP() == 2 ) {
|
||||
$r->push_handlers( 'PerlResponseHandler' =>
|
||||
sub { my $r = shift; $r->content_type('text/plain'); OK } );
|
||||
}
|
||||
elsif ( MP() == 1 ) {
|
||||
$r->push_handlers(
|
||||
'PerlHandler' => sub { my $r = shift; $r->send_http_header; OK }
|
||||
);
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( MP() == 2 ) {
|
||||
$r->push_handlers( 'PerlResponseHandler' => sub { SERVER_ERROR } );
|
||||
}
|
||||
elsif ( MP() == 1 ) {
|
||||
$r->push_handlers( 'PerlHandler' => sub { SERVER_ERROR } );
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
=encoding utf8
|
||||
|
||||
Lemonldap::NG::Handler::SharedConf - Perl extension to use dynamic
|
||||
configuration provide by Lemonldap::NG::Manager.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
package My::Package;
|
||||
use Lemonldap::NG::Handler::SharedConf;
|
||||
@ISA = qw(Lemonldap::NG::Handler::SharedConf);
|
||||
__PACKAGE__->init ( {
|
||||
localStorage => "Cache::FileCache",
|
||||
localStorageOptions => {
|
||||
'namespace' => 'lemonldap-ng',
|
||||
'default_expires_in' => 600,
|
||||
},
|
||||
configStorage => {
|
||||
type => "DBI"
|
||||
dbiChain => "DBI:mysql:database=$database;host=$hostname;port=$port",
|
||||
dbiUser => "lemonldap",
|
||||
dbiPassword => "password",
|
||||
},
|
||||
} );
|
||||
|
||||
Call your package in /apache-dir/conf/httpd.conf :
|
||||
|
||||
PerlRequire MyFile
|
||||
# TOTAL PROTECTION
|
||||
PerlHeaderParserHandler My::Package
|
||||
# OR SELECTED AREA
|
||||
<Location /protected-area>
|
||||
PerlHeaderParserHandler My::Package
|
||||
</Location>
|
||||
|
||||
The configuration is loaded only at Apache start. Create an URI to force
|
||||
configuration reload, so you don't need to restart Apache at each change :
|
||||
|
||||
# /apache-dir/conf/httpd.conf
|
||||
<Location /location/that/I/ve/choosed>
|
||||
Order deny,allow
|
||||
Deny from all
|
||||
Allow from my.manager.com
|
||||
PerlHeaderParserHandler My::Package->refresh
|
||||
</Location>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This library inherit from L<Lemonldap::NG::Handler::Simple> to build a
|
||||
complete SSO Handler System: a central database contains the policy of your
|
||||
domain. People that want to access to a protected applications are redirected
|
||||
to the portal that run L<Lemonldap::NG::Portal::SharedConf>. After reading
|
||||
configuration from the database and authenticating the user, it stores a key
|
||||
word for each application the user is granted to access to.
|
||||
Then the user is redirected to the application he wanted to access and the
|
||||
Apache handler build with L<Lemonldap::NG::Handler::SharedConf::DBI> has just
|
||||
to verify that the keyword corresponding to the protected area is stored in
|
||||
the database.
|
||||
|
||||
=head2 OVERLOADED SUBROUTINES
|
||||
|
||||
=head3 init
|
||||
|
||||
Like L<Lemonldap::NG::Handler::Simple>::init() but read only localStorage
|
||||
related options. You may change default time between two configuration checks
|
||||
with the C<reloadTime> parameter (default 600s).
|
||||
|
||||
=head1 OPERATION
|
||||
|
||||
Each new Apache child checks if there's a configuration stored in the local
|
||||
store. If not, it calls getConf to get one and store it in the local store by
|
||||
calling setconf.
|
||||
|
||||
Every 600 seconds, each Apache child checks if the local stored configuration
|
||||
has changed and reload it if it has.
|
||||
|
||||
When refresh subroutine is called (by http for example: see synopsis), getConf
|
||||
is called to get the new configuration and setconf is called to store it in the
|
||||
local store.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Lemonldap::NG::Handler>, L<Lemonldap::NG::Manager>, L<Lemonldap::NG::Portal>,
|
||||
L<http://lemonldap-ng.org/>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
=over
|
||||
|
||||
=item Clement Oudot, E<lt>clem.oudot@gmail.comE<gt>
|
||||
|
||||
=item François-Xavier Deltombe, E<lt>fxdeltombe@gmail.com.E<gt>
|
||||
|
||||
=item Xavier Guimard, E<lt>x.guimard@free.frE<gt>
|
||||
|
||||
=back
|
||||
|
||||
=head1 BUG REPORT
|
||||
|
||||
Use OW2 system to report bug or ask for features:
|
||||
L<http://jira.ow2.org>
|
||||
|
||||
=head1 DOWNLOAD
|
||||
|
||||
Lemonldap::NG is available at
|
||||
L<http://forge.objectweb.org/project/showfiles.php?group_id=274>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
=over
|
||||
|
||||
=item Copyright (C) 2006, 2007, 2008, 2009, 2010, 2013 by Xavier Guimard, E<lt>x.guimard@free.frE<gt>
|
||||
|
||||
=item Copyright (C) 2012 by François-Xavier Deltombe, E<lt>fxdeltombe@gmail.com.E<gt>
|
||||
|
||||
=item Copyright (C) 2006, 2008, 2009, 2010, 2011, 2012 by Clement Oudot, E<lt>clem.oudot@gmail.comE<gt>
|
||||
|
||||
=back
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see L<http://www.gnu.org/licenses/>.
|
||||
|
||||
=cut
|
File diff suppressed because it is too large
Load Diff
|
@ -429,8 +429,8 @@ Lemonldap::NG::Handler::Status - Perl extension to add a mod_status like system
|
|||
Create your own package (example using a central configuration database):
|
||||
|
||||
package My::Package;
|
||||
use Lemonldap::NG::Handler::SharedConf;
|
||||
@ISA = qw(Lemonldap::NG::Handler::SharedConf);
|
||||
use Lemonldap::NG::Handler::DefaultHandler;
|
||||
@ISA = qw(Lemonldap::NG::Handler::DefaultHandler);
|
||||
|
||||
__PACKAGE__->init ( {
|
||||
# Activate status feature
|
||||
|
|
|
@ -8,9 +8,11 @@
|
|||
package Lemonldap::NG::Handler::SympaAutoLogin;
|
||||
|
||||
use strict;
|
||||
use Lemonldap::NG::Handler::SharedConf qw(:all);
|
||||
use base qw(Lemonldap::NG::Handler::SharedConf);
|
||||
use Lemonldap::NG::Handler::DefaultHandler qw(:all);
|
||||
use base qw(Lemonldap::NG::Handler::DefaultHandler);
|
||||
use Digest::MD5;
|
||||
use Lemonldap::NG::Handler::Main::Headers;
|
||||
use Lemonldap::NG::Handler::Main::Logger;
|
||||
|
||||
our $VERSION = '1.1.2';
|
||||
|
||||
|
@ -39,8 +41,10 @@ sub defaultValuesInit {
|
|||
$sympaMailKey = $args->{'sympaMailKey'} || $sympaMailKey || "mail";
|
||||
|
||||
# Display found values in debug mode
|
||||
$class->lmLog( "sympaSecret: $sympaSecret", 'debug' );
|
||||
$class->lmLog( "sympaMailKey: $sympaMailKey", 'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog( "sympaSecret: $sympaSecret",
|
||||
'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog( "sympaMailKey: $sympaMailKey",
|
||||
'debug' );
|
||||
|
||||
# Delete Sympa parameters
|
||||
delete $args->{'sympaSecret'};
|
||||
|
@ -77,10 +81,11 @@ sub run {
|
|||
|
||||
# Get cookie header, removing Sympa cookie if exists (avoid security
|
||||
# problems) and set the new value
|
||||
$tmp = lmHeaderIn( $r, 'Cookie' );
|
||||
$tmp = Lemonldap::NG::Handler::Main::Headers->lmHeaderIn( $r, 'Cookie' );
|
||||
$tmp =~ s/\bsympauser=[^,;]*[,;]?//;
|
||||
$tmp .= $tmp ? ";$str" : $str;
|
||||
$class->lmSetHeaderIn( $r, 'Cookie' => $tmp );
|
||||
Lemonldap::NG::Handler::Main::Headers->lmSetHeaderIn( $r,
|
||||
'Cookie' => $tmp );
|
||||
|
||||
# Return SUPER::run() result
|
||||
return $ret;
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
package Lemonldap::NG::Handler::UpdateCookie;
|
||||
|
||||
use strict;
|
||||
use Lemonldap::NG::Handler::SharedConf qw(:all);
|
||||
use base qw(Lemonldap::NG::Handler::SharedConf);
|
||||
use Lemonldap::NG::Handler::DefaultHandler qw(:all);
|
||||
use base qw(Lemonldap::NG::Handler::DefaultHandler);
|
||||
use Lemonldap::NG::Handler::Main::Headers;
|
||||
use Lemonldap::NG::Handler::Main::Logger;
|
||||
|
||||
our $VERSION = '1.0.0';
|
||||
|
||||
|
@ -37,16 +39,17 @@ sub run {
|
|||
$datas->{_session_id} = 0;
|
||||
$clear = 1;
|
||||
}
|
||||
elsif ( $refLocalStorage
|
||||
and my $ldatas = $refLocalStorage->get($id) )
|
||||
elsif ( $tsv->{refLocalStorage}
|
||||
and my $ldatas = $tsv->{refLocalStorage}->get($id) )
|
||||
{
|
||||
if ( $ldatas->{_utime} lt $utime ) {
|
||||
$clear = 1;
|
||||
}
|
||||
}
|
||||
if ($clear) {
|
||||
$class->lmLog( "$class: remove $id from local cache", 'debug' );
|
||||
$refLocalStorage->remove($id);
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"$class: remove $id from local cache", 'debug' );
|
||||
$tsv->{refLocalStorage}->remove($id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,8 +63,9 @@ sub run {
|
|||
# Get user cookies and search for Lemonldap::NG update cookie.
|
||||
# @return Value of the cookie if found, 0 else
|
||||
sub fetchUTime {
|
||||
my $t = lmHeaderIn( $apacheRequest, 'Cookie' );
|
||||
my $c = $cookieName . 'update';
|
||||
my $t = Lemonldap::NG::Handler::Main::Headers->lmHeaderIn( $apacheRequest,
|
||||
'Cookie' );
|
||||
my $c = $tsv->{cookieName} . 'update';
|
||||
return ( $t =~ /$c=([^,; ]+)/o ) ? $1 : 0;
|
||||
}
|
||||
|
||||
|
@ -79,7 +83,7 @@ cookie sent by client, to reload session in local cache.
|
|||
|
||||
package My::Package;
|
||||
use Lemonldap::NG::Handler::UpdateCookie;
|
||||
@ISA = qw(Lemonldap::NG::Handler::SharedConf);
|
||||
@ISA = qw(Lemonldap::NG::Handler::DefaultHandler);
|
||||
|
||||
__PACKAGE__->init ( {
|
||||
# See Lemonldap::NG::Handler for more
|
||||
|
|
|
@ -1,503 +0,0 @@
|
|||
## @file
|
||||
# Virtual host support mechanism
|
||||
|
||||
## @class
|
||||
# This class adds virtual host support for Lemonldap::NG handlers.
|
||||
package Lemonldap::NG::Handler::Vhost;
|
||||
|
||||
use strict;
|
||||
use AutoLoader 'AUTOLOAD';
|
||||
|
||||
use Lemonldap::NG::Handler::Simple qw(:locationRules :headers :post :apache)
|
||||
; #inherits
|
||||
use MIME::Base64;
|
||||
use constant SAFEWRAP => ( Safe->can("wrap_code_ref") ? 1 : 0 );
|
||||
|
||||
our $VERSION = '1.3.0';
|
||||
|
||||
## @imethod protected void defaultValuesInit(hashRef args)
|
||||
# Set default values for non-customized variables
|
||||
# @param $args reference to the configuration hash
|
||||
sub defaultValuesInit {
|
||||
my ( $class, $args ) = splice @_;
|
||||
foreach my $t (qw(https port maintenance)) {
|
||||
|
||||
# Skip Handler initialization (values not defined)
|
||||
next unless defined $args->{$t};
|
||||
|
||||
# Record default value in key '_'
|
||||
$args->{$t} = { _ => $args->{$t} } unless ( ref( $args->{$t} ) );
|
||||
|
||||
# Override with vhost options
|
||||
if ( defined $args->{vhostOptions} ) {
|
||||
my $n = 'vhost' . ucfirst($t);
|
||||
foreach my $k ( keys %{ $args->{vhostOptions} } ) {
|
||||
foreach my $alias (
|
||||
@{ $class->getAliases( $k, $args->{vhostOptions} ) } )
|
||||
{
|
||||
my $v = $args->{vhostOptions}->{$k}->{$n};
|
||||
$class->lmLog( "Options $t for vhost $alias: $v", 'debug' );
|
||||
$args->{$t}->{$alias} = $v
|
||||
if ( $v >= 0 ); # Keep default value if $v is negative
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$class->Lemonldap::NG::Handler::Simple::defaultValuesInit($args);
|
||||
}
|
||||
|
||||
## @imethod void locationRulesInit(hashRef args)
|
||||
# Compile rules.
|
||||
# Rules are stored in $args->{locationRules}->{<virtualhost>} that contains
|
||||
# regexp=>test expressions where :
|
||||
# - regexp is used to test URIs
|
||||
# - test contains an expression used to grant the user
|
||||
#
|
||||
# This function creates 2 hashRef containing :
|
||||
# - one list of the compiled regular expressions for each virtual host
|
||||
# - one list of the compiled functions (compiled with conditionSub()) for each
|
||||
# virtual host
|
||||
# @param $args reference to the configuration hash
|
||||
sub locationRulesInit {
|
||||
my ( $class, $args ) = splice @_;
|
||||
foreach my $vhost ( keys %{ $args->{locationRules} } ) {
|
||||
foreach
|
||||
my $alias ( @{ $class->getAliases( $vhost, $args->{vhostOptions} ) } )
|
||||
{
|
||||
$locationCount->{$alias} = 0;
|
||||
foreach ( sort keys %{ $args->{locationRules}->{$vhost} } ) {
|
||||
if ( $_ eq 'default' ) {
|
||||
(
|
||||
$defaultCondition->{$alias},
|
||||
$defaultProtection->{$alias}
|
||||
)
|
||||
= $class->conditionSub(
|
||||
$args->{locationRules}->{$vhost}->{$_} );
|
||||
}
|
||||
else {
|
||||
(
|
||||
$locationCondition->{$alias}
|
||||
->[ $locationCount->{$alias} ],
|
||||
$locationProtection->{$alias}
|
||||
->[ $locationCount->{$alias} ]
|
||||
)
|
||||
= $class->conditionSub(
|
||||
$args->{locationRules}->{$vhost}->{$_} );
|
||||
$locationRegexp->{$alias}->[ $locationCount->{$alias} ] =
|
||||
qr/$_/;
|
||||
$locationConditionText->{$alias}
|
||||
->[ $locationCount->{$alias} ] =
|
||||
/^\(\?#(.*?)\)/ ? $1 : /^(.*?)##(.+)$/ ? $2 : $_;
|
||||
$locationCount->{$alias}++;
|
||||
}
|
||||
}
|
||||
|
||||
# Default police
|
||||
( $defaultCondition->{$alias}, $defaultProtection->{$alias} ) =
|
||||
$class->conditionSub('accept')
|
||||
unless ( $defaultCondition->{$alias} );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
## @imethod void forgeHeadersInit(hashRef args)
|
||||
# Create the &$forgeHeaders->{<virtualhost>} subroutines used to insert
|
||||
# headers into the HTTP request.
|
||||
# @param $args reference to the configuration hash
|
||||
sub forgeHeadersInit {
|
||||
my ( $class, $args ) = splice @_;
|
||||
|
||||
# Creation of the subroutine who will generate headers
|
||||
foreach my $vhost ( keys %{ $args->{exportedHeaders} } ) {
|
||||
foreach
|
||||
my $alias ( @{ $class->getAliases( $vhost, $args->{vhostOptions} ) } )
|
||||
{
|
||||
my %tmp = %{ $args->{exportedHeaders}->{$vhost} };
|
||||
foreach ( keys %tmp ) {
|
||||
$tmp{$_} =~ s/\$(\w+)/\$datas->{$1}/g;
|
||||
$tmp{$_} = $class->regRemoteIp( $tmp{$_} );
|
||||
}
|
||||
|
||||
my $sub;
|
||||
foreach ( keys %tmp ) {
|
||||
$sub .= "'$_' => join('',split(/[\\r\\n]+/,$tmp{$_})),";
|
||||
}
|
||||
|
||||
$forgeHeaders->{$alias} = (
|
||||
SAFEWRAP
|
||||
? $class->safe->wrap_code_ref(
|
||||
$class->safe->reval("sub {$sub}")
|
||||
)
|
||||
: $class->safe->reval("sub {return($sub)}")
|
||||
);
|
||||
$class->lmLog( "$class: Unable to forge headers: $@: sub {$sub}",
|
||||
'error' )
|
||||
if ($@);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
1;
|
||||
}
|
||||
|
||||
## @imethod void headerListInit(hashRef args)
|
||||
# Lists the exported HTTP headers into $headerList
|
||||
# @param $args reference to the configuration hash
|
||||
sub headerListInit {
|
||||
my ( $class, $args ) = splice @_;
|
||||
|
||||
foreach my $vhost ( keys %{ $args->{exportedHeaders} } ) {
|
||||
foreach
|
||||
my $alias ( @{ $class->getAliases( $vhost, $args->{vhostOptions} ) } )
|
||||
{
|
||||
my @tmp = keys %{ $args->{exportedHeaders}->{$vhost} };
|
||||
$headerList->{$alias} = \@tmp;
|
||||
}
|
||||
}
|
||||
1;
|
||||
}
|
||||
|
||||
## @rmethod void sendHeaders()
|
||||
# Launch function compiled by forgeHeadersInit() for the current virtual host
|
||||
sub sendHeaders {
|
||||
my $class = shift;
|
||||
my $vhost = $apacheRequest->hostname;
|
||||
if ( defined( $forgeHeaders->{$vhost} ) ) {
|
||||
$class->lmSetHeaderIn( $apacheRequest, &{ $forgeHeaders->{$vhost} } );
|
||||
}
|
||||
}
|
||||
|
||||
## @rmethod void cleanHeaders()
|
||||
# Unset HTTP headers for the current virtual host, when sendHeaders is skipped
|
||||
sub cleanHeaders {
|
||||
my $class = shift;
|
||||
my $vhost = $apacheRequest->hostname;
|
||||
if ( defined( $forgeHeaders->{$vhost} ) ) {
|
||||
$class->lmUnsetHeaderIn( $apacheRequest, @{ $headerList->{$vhost} } );
|
||||
}
|
||||
}
|
||||
|
||||
## @rmethod protected int isUnprotected()
|
||||
# @return 0 if URI is protected,
|
||||
# UNPROTECT if it is unprotected by "unprotect",
|
||||
# SKIP if is is unprotected by "skip"
|
||||
sub isUnprotected {
|
||||
my ( $class, $uri ) = splice @_;
|
||||
my $vhost = $apacheRequest->hostname;
|
||||
for ( my $i = 0 ; $i < $locationCount->{$vhost} ; $i++ ) {
|
||||
if ( $uri =~ $locationRegexp->{$vhost}->[$i] ) {
|
||||
return $locationProtection->{$vhost}->[$i];
|
||||
}
|
||||
}
|
||||
return $defaultProtection->{$vhost};
|
||||
}
|
||||
|
||||
## @rmethod boolean grant()
|
||||
# Grant or refuse client using compiled regexp and functions
|
||||
# @return True if the user is granted to access to the current URL
|
||||
sub grant {
|
||||
my ( $class, $uri ) = splice @_;
|
||||
my $vhost = $apacheRequest->hostname;
|
||||
for ( my $i = 0 ; $i < $locationCount->{$vhost} ; $i++ ) {
|
||||
if ( $uri =~ $locationRegexp->{$vhost}->[$i] ) {
|
||||
$class->lmLog(
|
||||
'Regexp "' . $locationConditionText->{$vhost}->[$i] . '" match',
|
||||
'debug'
|
||||
);
|
||||
return &{ $locationCondition->{$vhost}->[$i] }($datas);
|
||||
}
|
||||
}
|
||||
unless ( $defaultCondition->{$vhost} ) {
|
||||
$class->lmLog(
|
||||
"User rejected because VirtualHost \"$vhost\" has no configuration",
|
||||
'warn'
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
$class->lmLog( "$vhost: Apply default rule", 'debug' );
|
||||
return &{ $defaultCondition->{$vhost} }($datas);
|
||||
}
|
||||
|
||||
## @rmethod protected $ fetchId()
|
||||
# Get user cookies and search for Lemonldap::NG cookie.
|
||||
# @return Value of the cookie if found, 0 else
|
||||
sub fetchId {
|
||||
my $t = lmHeaderIn( $apacheRequest, 'Cookie' );
|
||||
my $vhost = $apacheRequest->hostname;
|
||||
my $lookForHttpCookie = $securedCookie =~ /^(2|3)$/
|
||||
&& !(
|
||||
defined( $https->{$vhost} )
|
||||
? $https->{$vhost}
|
||||
: $https->{_}
|
||||
);
|
||||
my $value =
|
||||
$lookForHttpCookie
|
||||
? ( $t =~ /${cookieName}http=([^,; ]+)/o ? $1 : 0 )
|
||||
: ( $t =~ /$cookieName=([^,; ]+)/o ? $1 : 0 );
|
||||
|
||||
$value = $cipher->decryptHex( $value, "http" )
|
||||
if ( $value && $lookForHttpCookie && $securedCookie == 3 );
|
||||
return $value;
|
||||
}
|
||||
|
||||
## @cmethod private string _buildUrl(string s)
|
||||
# Transform /<s> into http(s?)://<host>:<port>/s
|
||||
# @param $s path
|
||||
# @return URL
|
||||
sub _buildUrl {
|
||||
my ( $class, $s ) = splice @_;
|
||||
my $vhost = $apacheRequest->hostname;
|
||||
my $portString =
|
||||
$port->{$vhost}
|
||||
|| $port->{_}
|
||||
|| $apacheRequest->get_server_port();
|
||||
my $_https = (
|
||||
defined( $https->{$vhost} )
|
||||
? $https->{$vhost}
|
||||
: $https->{_}
|
||||
);
|
||||
$portString =
|
||||
( $_https && $portString == 443 ) ? ''
|
||||
: ( !$_https && $portString == 80 ) ? ''
|
||||
: ':' . $portString;
|
||||
my $url = "http"
|
||||
. ( $_https ? "s" : "" ) . "://"
|
||||
. $apacheRequest->get_server_name()
|
||||
. $portString
|
||||
. $s;
|
||||
$class->lmLog( "Build URL $url", 'debug' );
|
||||
return $url;
|
||||
}
|
||||
|
||||
## @imethod protected void postUrlInit()
|
||||
# Prepare methods to post form attributes
|
||||
sub postUrlInit {
|
||||
my ( $class, $args ) = splice @_;
|
||||
|
||||
# Do nothing if no POST configured
|
||||
return unless ( $args->{post} );
|
||||
|
||||
# Load required modules
|
||||
eval 'use Apache2::Filter;use URI';
|
||||
|
||||
# Prepare transform sub
|
||||
$transform = {};
|
||||
|
||||
# Browse all vhost
|
||||
foreach my $vhost ( keys %{ $args->{post} } ) {
|
||||
|
||||
foreach
|
||||
my $alias ( @{ $class->getAliases( $vhost, $args->{vhostOptions} ) } )
|
||||
{
|
||||
|
||||
# Browse all POST URI
|
||||
while ( my ( $url, $d ) = each( %{ $args->{post}->{$vhost} } ) ) {
|
||||
|
||||
# Where to POST
|
||||
$d->{postUrl} ||= $url;
|
||||
|
||||
# Register POST form for POST URL
|
||||
$transform->{$alias}->{$url} =
|
||||
sub { $class->buildPostForm( $d->{postUrl} ) }
|
||||
if ( $url ne $d->{postUrl} );
|
||||
|
||||
# Get datas to POST
|
||||
my $expr = $d->{expr};
|
||||
my %postdata;
|
||||
|
||||
# Manage old and new configuration format
|
||||
# OLD: expr => 'param1 => value1, param2 => value2',
|
||||
# NEW : expr => { param1 => value1, param2 => value2 },
|
||||
if ( ref $expr eq 'HASH' ) {
|
||||
%postdata = %$expr;
|
||||
}
|
||||
else {
|
||||
%postdata = split /(?:\s*=>\s*|\s*,\s*)/, $expr;
|
||||
}
|
||||
|
||||
# Build string for URI::query_form
|
||||
my $tmp;
|
||||
foreach ( keys %postdata ) {
|
||||
$postdata{$_} =~ s/\$(\w+)/\$datas->{$1}/g;
|
||||
$postdata{$_} = "'$postdata{$_}'"
|
||||
if ( $postdata{$_} =~ /^\w+$/ );
|
||||
$tmp .= "'$_'=>$postdata{$_},";
|
||||
}
|
||||
|
||||
$class->lmLog( "Compiling POST request for $url (vhost $alias)",
|
||||
'debug' );
|
||||
$transform->{$alias}->{ $d->{postUrl} } = sub {
|
||||
return $class->buildPostForm( $d->{postUrl} )
|
||||
if ( $apacheRequest->method ne 'POST' );
|
||||
$apacheRequest->add_input_filter(
|
||||
sub {
|
||||
$class->postFilter( $tmp, @_ );
|
||||
}
|
||||
);
|
||||
OK;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
## @rmethod protected transformUri(string uri)
|
||||
# Transform URI to replay POST forms
|
||||
# @param uri URI to catch
|
||||
# @return Apache2::Const
|
||||
sub transformUri {
|
||||
my ( $class, $uri ) = splice @_;
|
||||
my $vhost = $apacheRequest->hostname;
|
||||
|
||||
if ( defined( $transform->{$vhost}->{$uri} ) ) {
|
||||
return &{ $transform->{$vhost}->{$uri} };
|
||||
}
|
||||
|
||||
OK;
|
||||
}
|
||||
|
||||
## @rmethod protected boolean checkMaintenanceMode
|
||||
# Check if we are in maintenance mode
|
||||
# @return true if maintenance mode
|
||||
sub checkMaintenanceMode {
|
||||
my ($class) = splice @_;
|
||||
my $vhost = $apacheRequest->hostname;
|
||||
my $_maintenance =
|
||||
( defined $maintenance->{$vhost} )
|
||||
? $maintenance->{$vhost}
|
||||
: $maintenance->{_};
|
||||
|
||||
if ($_maintenance) {
|
||||
$class->lmLog( "Maintenance mode activated", 'debug' );
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
## @method arrayref getAliases(scalar vhost, hashref options)
|
||||
# Check aliases of a vhost
|
||||
# @param vhost vhost name
|
||||
# @param options vhostOptions configuration item
|
||||
# @return arrayref of vhost and aliases
|
||||
sub getAliases {
|
||||
my ( $class, $vhost, $options ) = splice @_;
|
||||
my $aliases = [$vhost];
|
||||
|
||||
if ( $options->{$vhost}->{vhostAliases} ) {
|
||||
foreach ( split /\s+/, $options->{$vhost}->{vhostAliases} ) {
|
||||
push @$aliases, $_;
|
||||
$class->lmLog( "$_ is an alias for $vhost", 'debug' );
|
||||
}
|
||||
}
|
||||
|
||||
return $aliases;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
=encoding utf8
|
||||
|
||||
Lemonldap::NG::Handler::Vhost - Perl extension for building a Lemonldap::NG
|
||||
compatible handler able to manage Apache virtual hosts.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Create your own package:
|
||||
|
||||
package My::Package;
|
||||
use Lemonldap::NG::Handler::Vhost;
|
||||
|
||||
# IMPORTANT ORDER
|
||||
our @ISA = qw (Lemonldap::NG::Handler::Vhost Lemonldap::NG::Handler::Simple);
|
||||
|
||||
__PACKAGE__->init ( { locationRules => {
|
||||
'vhost1.dc.com' => {
|
||||
'default' => '$ou =~ /brh/'
|
||||
},
|
||||
'vhost2.dc.com' => {
|
||||
'^/pj/.*$' => '$qualif="opj"',
|
||||
'^/rh/.*$' => '$ou=~/brh/',
|
||||
'^/rh_or_opj.*$' => '$qualif="opj" or $ou=~/brh/',
|
||||
default => 'accept',
|
||||
},
|
||||
# Put here others Lemonldap::NG::Handler::Simple options
|
||||
}
|
||||
);
|
||||
|
||||
Call your package in <apache-directory>/conf/httpd.conf
|
||||
|
||||
PerlRequire MyFile
|
||||
PerlHeaderParserHandler My::Package
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This library provides a way to protect Apache virtual hosts with Lemonldap::NG.
|
||||
|
||||
=head2 INITIALISATION PARAMETERS
|
||||
|
||||
Lemonldap::NG::Handler::Vhost splits the locationRules parameter into a hash
|
||||
reference which contains anonymous hash references as used by
|
||||
L<Lemonldap::NG::Handler::Simple>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Lemonldap::NG::Handler(3)>,
|
||||
L<http://lemonldap-ng.org/>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
=over
|
||||
|
||||
=item Clement Oudot, E<lt>clem.oudot@gmail.comE<gt>
|
||||
|
||||
=item François-Xavier Deltombe, E<lt>fxdeltombe@gmail.com.E<gt>
|
||||
|
||||
=item Xavier Guimard, E<lt>x.guimard@free.frE<gt>
|
||||
|
||||
=back
|
||||
|
||||
=head1 BUG REPORT
|
||||
|
||||
Use OW2 system to report bug or ask for features:
|
||||
L<http://jira.ow2.org>
|
||||
|
||||
=head1 DOWNLOAD
|
||||
|
||||
Lemonldap::NG is available at
|
||||
L<http://forge.objectweb.org/project/showfiles.php?group_id=274>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
=over
|
||||
|
||||
=item Copyright (C) 2006, 2007, 2008, 2009, 2010 by Xavier Guimard, E<lt>x.guimard@free.frE<gt>
|
||||
|
||||
=item Copyright (C) 2012 by François-Xavier Deltombe, E<lt>fxdeltombe@gmail.com.E<gt>
|
||||
|
||||
=item Copyright (C) 2006, 2010, 2011, 2012, 2013 by Clement Oudot, E<lt>clem.oudot@gmail.comE<gt>
|
||||
|
||||
=back
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see L<http://www.gnu.org/licenses/>.
|
||||
|
||||
=cut
|
|
@ -8,9 +8,11 @@
|
|||
package Lemonldap::NG::Handler::ZimbraPreAuth;
|
||||
|
||||
use strict;
|
||||
use Lemonldap::NG::Handler::SharedConf qw(:all);
|
||||
use base qw(Lemonldap::NG::Handler::SharedConf);
|
||||
use Lemonldap::NG::Handler::DefaultHandler qw(:all);
|
||||
use base qw(Lemonldap::NG::Handler::DefaultHandler);
|
||||
use Digest::HMAC_SHA1 qw(hmac_sha1 hmac_sha1_hex);
|
||||
use Lemonldap::NG::Handler::Main::Headers;
|
||||
use Lemonldap::NG::Handler::Main::Logger;
|
||||
|
||||
our $VERSION = '1.0.0';
|
||||
|
||||
|
@ -36,12 +38,17 @@ sub defaultValuesInit {
|
|||
$timeout = $args->{'timeout'} || $timeout || '0';
|
||||
|
||||
# Display found values in debug mode
|
||||
$class->lmLog( "zimbraPreAuthKey: $zimbraPreAuthKey", 'debug' );
|
||||
$class->lmLog( "zimbraAccountKey: $zimbraAccountKey", 'debug' );
|
||||
$class->lmLog( "zimbraBy: $zimbraBy", 'debug' );
|
||||
$class->lmLog( "zimbraUrl: $zimbraUrl", 'debug' );
|
||||
$class->lmLog( "zimbraSsoUrl: $zimbraSsoUrl", 'debug' );
|
||||
$class->lmLog( "timeout: $timeout", 'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"zimbraPreAuthKey: $zimbraPreAuthKey", 'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"zimbraAccountKey: $zimbraAccountKey", 'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog( "zimbraBy: $zimbraBy",
|
||||
'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog( "zimbraUrl: $zimbraUrl",
|
||||
'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog( "zimbraSsoUrl: $zimbraSsoUrl",
|
||||
'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog( "timeout: $timeout", 'debug' );
|
||||
|
||||
# Delete Zimbra parameters
|
||||
delete $args->{'zimbraPreAuthKey'};
|
||||
|
@ -85,7 +92,8 @@ sub run {
|
|||
);
|
||||
|
||||
# Header location
|
||||
lmSetHeaderOut( $r, 'Location' => $zimbra_url );
|
||||
Lemonldap::NG::Handler::Main::Headers->lmSetHeaderOut( $r,
|
||||
'Location' => $zimbra_url );
|
||||
|
||||
# Return REDIRECT
|
||||
return REDIRECT;
|
||||
|
@ -111,7 +119,7 @@ sub _buildZimbraPreAuthUrl {
|
|||
my $computed_value =
|
||||
hmac_sha1_hex( "$account|$by|$expires|$timestamp", $key );
|
||||
|
||||
$class->lmLog(
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"Compute value $account|$by|$expires|$timestamp into $computed_value",
|
||||
'debug' );
|
||||
|
||||
|
@ -119,7 +127,8 @@ sub _buildZimbraPreAuthUrl {
|
|||
my $zimbra_url =
|
||||
"$url?account=$account&by=$by×tamp=$timestamp&expires=$expires&preauth=$computed_value";
|
||||
|
||||
$class->lmLog( "Build Zimbra URL: $zimbra_url", 'debug' );
|
||||
Lemonldap::NG::Handler::Main::Logger->lmLog(
|
||||
"Build Zimbra URL: $zimbra_url", 'debug' );
|
||||
|
||||
return $zimbra_url;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
package Lemonldap::NG::Manager::Sessions;
|
||||
|
||||
use strict;
|
||||
use Lemonldap::NG::Handler::CGI qw(:globalStorage :locationRules);
|
||||
use Lemonldap::NG::Handler::CGI qw(:tsv);
|
||||
use Lemonldap::NG::Common::Apache::Session; #inherits
|
||||
use Lemonldap::NG::Common::Conf; #link protected conf Configuration
|
||||
use Lemonldap::NG::Common::Conf::Constants; #inherits
|
||||
|
@ -21,8 +21,8 @@ use utf8;
|
|||
|
||||
#inherits Apache::Session
|
||||
|
||||
our $whatToTrace;
|
||||
*whatToTrace = \$Lemonldap::NG::Handler::_CGI::whatToTrace;
|
||||
#our $whatToTrace;
|
||||
#*whatToTrace = \$Lemonldap::NG::Handler::_CGI::whatToTrace;
|
||||
|
||||
our $VERSION = '1.3.0';
|
||||
|
||||
|
@ -67,12 +67,12 @@ sub new {
|
|||
$self->{managerSkin} ||= 'default';
|
||||
|
||||
# Now try to load Apache::Session module
|
||||
unless ( $globalStorage->can('populate') ) {
|
||||
eval "require $globalStorage";
|
||||
$class->abort( "Unable to load $globalStorage", $@ ) if ($@);
|
||||
unless ( $tsv->{globalStorage}->can('populate') ) {
|
||||
eval "require $tsv->{globalStorage}";
|
||||
$class->abort( "Unable to load $tsv->{globalStorage}", $@ ) if ($@);
|
||||
}
|
||||
%{ $self->{globalStorageOptions} } = %$globalStorageOptions;
|
||||
$self->{globalStorageOptions}->{backend} = $globalStorage;
|
||||
%{ $self->{globalStorageOptions} } = %{$tsv->{globalStorageOptions}};
|
||||
$self->{globalStorageOptions}->{backend} = $tsv->{globalStorage};
|
||||
|
||||
# IP field
|
||||
$self->{ipField} = "ipAddr";
|
||||
|
@ -139,10 +139,10 @@ sub list {
|
|||
# Parse all sessions to store first letter
|
||||
$res = Lemonldap::NG::Common::Apache::Session->get_key_from_all_sessions(
|
||||
$self->{globalStorageOptions},
|
||||
[ '_httpSessionType', $whatToTrace ] );
|
||||
[ '_httpSessionType', $tsv->{whatToTrace} ] );
|
||||
while ( my ( $id, $entry ) = each %$res ) {
|
||||
next if ( $entry->{_httpSessionType} );
|
||||
next unless $entry->{$whatToTrace} =~ /^(\w)/;
|
||||
next unless $entry->{$tsv->{whatToTrace}} =~ /^(\w)/;
|
||||
$byUid->{$1}++;
|
||||
$count++;
|
||||
}
|
||||
|
@ -189,10 +189,10 @@ sub doubleIp {
|
|||
# Parse all sessions
|
||||
$res = Lemonldap::NG::Common::Apache::Session->get_key_from_all_sessions(
|
||||
$self->{globalStorageOptions},
|
||||
[ '_httpSessionType', $whatToTrace, $self->{ipField}, 'startTime' ] );
|
||||
[ '_httpSessionType', $tsv->{whatToTrace}, $self->{ipField}, 'startTime' ] );
|
||||
while ( my ( $id, $entry ) = each %$res ) {
|
||||
next if ( $entry->{_httpSessionType} );
|
||||
push @{ $byUid->{ $entry->{$whatToTrace} }
|
||||
push @{ $byUid->{ $entry->{$tsv->{whatToTrace}} }
|
||||
->{ $entry->{ $self->{ipField} } } },
|
||||
{ id => $id, startTime => $entry->{startTime} };
|
||||
}
|
||||
|
@ -250,12 +250,12 @@ sub fullip {
|
|||
# Parse sessions and store only if IP match regexp
|
||||
$res = Lemonldap::NG::Common::Apache::Session->searchOnExpr(
|
||||
$self->{globalStorageOptions},
|
||||
$self->{ipField}, $req, $whatToTrace, 'startTime', $self->{ipField},
|
||||
$self->{ipField}, $req, $tsv->{whatToTrace}, 'startTime', $self->{ipField},
|
||||
'_httpSessionType' );
|
||||
while ( my ( $id, $entry ) = each %$res ) {
|
||||
next if ( $entry->{_httpSessionType} );
|
||||
push @{ $byUid->{ $entry->{ $self->{ipField} } }
|
||||
->{ $entry->{$whatToTrace} } },
|
||||
->{ $entry->{$tsv->{whatToTrace}} } },
|
||||
{ id => $id, startTime => $entry->{startTime} };
|
||||
}
|
||||
$res = '';
|
||||
|
@ -293,10 +293,10 @@ sub fulluid {
|
|||
# Parse sessions to find user that match regexp
|
||||
$res = Lemonldap::NG::Common::Apache::Session->searchOnExpr(
|
||||
$self->{globalStorageOptions},
|
||||
$whatToTrace, $req, $whatToTrace, 'startTime', '_httpSessionType' );
|
||||
$tsv->{whatToTrace}, $req, $tsv->{whatToTrace}, 'startTime', '_httpSessionType' );
|
||||
while ( my ( $id, $entry ) = each %$res ) {
|
||||
next if ( $entry->{_httpSessionType} );
|
||||
push @{ $byUid->{ $entry->{$whatToTrace} } },
|
||||
push @{ $byUid->{ $entry->{$tsv->{whatToTrace}} } },
|
||||
{ id => $id, startTime => $entry->{startTime} };
|
||||
}
|
||||
$res = '';
|
||||
|
@ -341,7 +341,7 @@ sub delete {
|
|||
my ( %h, $res );
|
||||
|
||||
# Try to read session
|
||||
eval { tie %h, $globalStorage, $id, $globalStorageOptions; };
|
||||
eval { tie %h, $tsv->{globalStorage}, $id, $tsv->{globalStorageOptions}; };
|
||||
if ($@) {
|
||||
if ( $@ =~ /does not exist in the data store/i ) {
|
||||
$self->lmLog( "Apache::Session error: $@", 'error' );
|
||||
|
@ -360,8 +360,8 @@ sub delete {
|
|||
if ( $h{_httpSession} ) {
|
||||
my %h2;
|
||||
eval {
|
||||
tie %h2, $globalStorage, $h{_httpSession},
|
||||
$globalStorageOptions;
|
||||
tie %h2, $tsv->{globalStorage}, $h{_httpSession},
|
||||
$tsv->{globalStorageOptions};
|
||||
tied(%h2)->delete();
|
||||
};
|
||||
if ($@) {
|
||||
|
@ -395,7 +395,7 @@ sub session {
|
|||
my ( %h, $res );
|
||||
|
||||
# Try to read session
|
||||
eval { tie %h, $globalStorage, $id, $globalStorageOptions; };
|
||||
eval { tie %h, $tsv->{globalStorage}, $id, $tsv->{globalStorageOptions}; };
|
||||
if ($@) {
|
||||
$self->lmLog( "Apache::Session error: $@", 'error' );
|
||||
$res .= '<h1 class="ui-widget-header ui-corner-all">'
|
||||
|
@ -655,12 +655,12 @@ sub uidByIp {
|
|||
my ( $byUser, $res );
|
||||
$res = Lemonldap::NG::Common::Apache::Session->searchOn(
|
||||
$self->{globalStorageOptions},
|
||||
$self->{ipField}, $ip, '_httpSessionType', $whatToTrace,
|
||||
$self->{ipField}, $ip, '_httpSessionType', $tsv->{whatToTrace},
|
||||
$self->{ipField}, 'startTime' );
|
||||
while ( my ( $id, $entry ) = each(%$res) ) {
|
||||
next if ( $entry->{_httpSessionType} );
|
||||
if ( $entry->{ $self->{ipField} } eq $ip ) {
|
||||
push @{ $byUser->{ $entry->{$whatToTrace} } },
|
||||
push @{ $byUser->{ $entry->{$tsv->{whatToTrace}} } },
|
||||
{ id => $id, startTime => $entry->{startTime} };
|
||||
}
|
||||
}
|
||||
|
@ -688,11 +688,11 @@ sub uid {
|
|||
my ( $byIp, $res );
|
||||
$res = Lemonldap::NG::Common::Apache::Session->searchOn(
|
||||
$self->{globalStorageOptions},
|
||||
$whatToTrace, $uid, '_httpSessionType', $whatToTrace, $self->{ipField},
|
||||
$tsv->{whatToTrace}, $uid, '_httpSessionType', $tsv->{whatToTrace}, $self->{ipField},
|
||||
'startTime' );
|
||||
while ( my ( $id, $entry ) = each(%$res) ) {
|
||||
next if ( $entry->{_httpSessionType} );
|
||||
if ( $entry->{$whatToTrace} eq $uid ) {
|
||||
if ( $entry->{$tsv->{whatToTrace}} eq $uid ) {
|
||||
push @{ $byIp->{ $entry->{ $self->{ipField} } } },
|
||||
{ id => $id, startTime => $entry->{startTime} };
|
||||
}
|
||||
|
@ -724,10 +724,10 @@ sub letter {
|
|||
|
||||
$res = Lemonldap::NG::Common::Apache::Session->searchOnExpr(
|
||||
$self->{globalStorageOptions},
|
||||
$whatToTrace, "${letter}*", '_httpSessionType', $whatToTrace );
|
||||
$tsv->{whatToTrace}, "${letter}*", '_httpSessionType', $tsv->{whatToTrace} );
|
||||
while ( my ( $id, $entry ) = each %$res ) {
|
||||
next if ( $entry->{_httpSessionType} );
|
||||
$byUid->{ $entry->{$whatToTrace} }++;
|
||||
$byUid->{ $entry->{$tsv->{whatToTrace}} }++;
|
||||
}
|
||||
$res = '';
|
||||
foreach my $uid ( sort keys %$byUid ) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user