- deleting specific handlers defined in two places.

- deleting old MyHandler*, because they are not used anymore. (Specific handlers are called directly)
- renaming SpecificHandlers into Specific

- documentation updated accordingly in: 1.4/upgrades, 1.4/applications/zimbra, 1.4/applications/sympa, 1.4/securetoken
(references #630)
This commit is contained in:
David COUTADEUR 2014-05-21 16:30:14 +00:00
parent 233026eb6f
commit ca6227f469
16 changed files with 0 additions and 1429 deletions

View File

@ -1,42 +0,0 @@
package My::Package;
use Lemonldap::NG::Handler::DefaultHandler;
@ISA = qw(Lemonldap::NG::Handler::DefaultHandler);
__PACKAGE__->init(
{
# WARNING:
# all args inserted here must be the same for all handlers launched on
# the same Apache server even if they inherits from different classes
# (SympaAutoLogin,...)
# ACCESS TO CONFIGURATION
# By default, Lemonldap::NG uses the default lemonldap-ng.ini file to
# know where to find is configuration
# (generaly /etc/lemonldap-ng/lemonldap-ng.ini)
# You can specify by yourself this file :
#configStorage => { confFile => '/path/to/my/file' },
# You can also specify directly the configuration
# (see Lemonldap::NG::Handler::DefaultHandler(3))
#configStorage => {
# type => 'File',
# dirName => '/usr/local/lemonldap-ng/data/conf/'
#},
# OTHERS
# You can also overload any parameter issued from manager
# configuration. Example:
#globalStorage => 'Lemonldap::NG::Common::Apache::Session::SOAP',
#globalStorageOptions => {
# proxy => 'http://auth.example.com/index.pl/sessions',
# proxyOptions => {
# timeout => 5,
# },
# # If soapserver is protected by HTTP Basic:
# User => 'http-user',
# Password => 'pass',
#},
}
);
1;

View File

@ -1,16 +0,0 @@
# Handler for Auth Basic
package My::AuthBasic;
# Load Auth Basic Handler
use Lemonldap::NG::Handler::SpecificHandlers::AuthBasic;
@ISA = qw(Lemonldap::NG::Handler::SpecificHandlers::AuthBasic);
__PACKAGE__->init(
{
# See Lemonldap::NG::Handler
}
);
1;

View File

@ -1,16 +0,0 @@
# Handler for Secure Token
package My::SecureToken;
# Load Secure Token Handler
use Lemonldap::NG::Handler::SpecificHandlers::SecureToken;
@ISA = qw(Lemonldap::NG::Handler::SpecificHandlers::SecureToken);
__PACKAGE__->init(
{
# See Lemonldap::NG::Handler
}
);
1;

View File

@ -1,16 +0,0 @@
# Handler for Sympa autologin
package My::Sympa;
# Load Sympa Handler
use Lemonldap::NG::Handler::SpecificHandlers::SympaAutoLogin;
@ISA = qw(Lemonldap::NG::Handler::SpecificHandlers::SympaAutoLogin);
__PACKAGE__->init(
{
# See Lemonldap::NG::Handler
}
);
1;

View File

@ -1,16 +0,0 @@
# Handler for Zimbra preauthentication
package My::Zimbra;
# Load Zimbra Handler
use Lemonldap::NG::Handler::SpecificHandlers::ZimbraPreAuth;
@ISA = qw(Lemonldap::NG::Handler::SpecificHandlers::ZimbraPreAuth);
__PACKAGE__->init(
{
# See Lemonldap::NG::Handler
}
);
1;

View File

@ -1,14 +0,0 @@
# Handler to manage update cookie
package My::Package::UpdateCookie;
use Lemonldap::NG::Handler::SpecificHandlers::UpdateCookie;
@ISA = qw(Lemonldap::NG::Handler::SpecificHandlers::UpdateCookie);
__PACKAGE__->init(
{
# See Lemonldap::NG::Handler
}
);
1;

View File

@ -1,292 +0,0 @@
##@file
# Auth-basic authentication with Lemonldap::NG rights management
##@class
# Auth-basic authentication with Lemonldap::NG rights management
# This specific handler is intended to be called by a handler caller
# old working, kept for compatibility with previous 1.4.0 versions
package Lemonldap::NG::Handler::AuthBasic;
use strict;
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 Lemonldap::NG::Common::Session;
use base qw(Lemonldap::NG::Handler::DefaultHandler);
use utf8;
no utf8;
our $VERSION = '1.4.0';
# We need just this constant, that's why Portal is 'required' but not 'used'
*PE_OK = *Lemonldap::NG::Portal::SharedConf::PE_OK;
# Apache constants
BEGIN {
if ( MP() == 2 ) {
*AUTH_REQUIRED = \&Apache2::Const::AUTH_REQUIRED;
require Apache2::Access;
}
elsif ( MP() == 0 ) {
eval 'sub AUTH_REQUIRED {1}';
}
}
## @rmethod int run(Apache2::RequestRec apacheRequest)
# overload run subroutine to implement Auth-Basic mechanism.
# @param $apacheRequest current request
# @return Apache constant
sub run ($$) {
my $class;
( $class, $apacheRequest ) = splice @_;
if ( time() - $lastReload > $reloadTime ) {
unless ( my $tmp = $class->testConf(1) == OK ) {
Lemonldap::NG::Handler::Main::Logger->lmLog(
"$class: No configuration found", 'error' );
return $tmp;
}
}
return DECLINED unless ( $apacheRequest->is_initial_req );
my $uri = $apacheRequest->uri
. ( $apacheRequest->args ? "?" . $apacheRequest->args : "" );
# AUTHENTICATION
# I - recover the WWW-Authentication header
my ( $id, $user, $pass );
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;
}
$user =~ s/^Basic\s*//;
# ID for local cache
$id = md5_base64($user);
# II - recover the user datas
# 2.1 search if the user was the same as previous (very efficient in
# persistent connection).
unless ( $id eq $datas->{_cache_id} ) {
# 2.2 search in the local cache if exists
my $session_id;
unless ($tsv->{refLocalStorage}
and $session_id = $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 =
Lemonldap::NG::Handler::Main::Headers->lmHeaderIn( $apacheRequest,
'X-Forwarded-For' );
$xheader .= ", " if ($xheader);
$xheader .= $class->ip();
my $soapHeaders =
HTTP::Headers->new( "X-Forwarded-For" => $xheader );
my $soap =
SOAP::Lite->proxy( $class->portal(),
default_headers => $soapHeaders )
->uri('urn:Lemonldap::NG::Common::CGI::SOAPService');
$user = decode_base64($user);
( $user, $pass ) = ( $user =~ /^(.*?):(.*)$/ );
Lemonldap::NG::Handler::Main::Logger->lmLog(
"AuthBasic authentication for user: $user", 'debug' );
my $r = $soap->getCookies( $user, $pass );
# Catch SOAP errors
if ( $r->fault ) {
return $class->abort( "SOAP request to the portal failed: "
. $r->fault->{faultstring} );
}
else {
my $res = $r->result();
# If authentication failed, display error
if ( $res->{errorCode} ) {
Lemonldap::NG::Handler::Main::Logger->lmLog(
"Authentication failed for $user: "
. $soap->error( $res->{errorCode}, 'en' )->result(),
'notice'
);
Lemonldap::NG::Handler::Main::Headers->lmSetErrHeaderOut(
$apacheRequest,
'WWW-Authenticate' => 'Basic realm="LemonLDAP::NG"' );
return AUTH_REQUIRED;
}
$session_id = $res->{cookies}->{ $tsv->{cookieName} };
}
}
# Get the session
my $apacheSession = Lemonldap::NG::Common::Session->new(
{
storageModule => $tsv->{globalStorage},
storageModuleOptions => $tsv->{globalStorageOptions},
cacheModule => $tsv->{localSessionStorage},
cacheModuleOptions => $tsv->{localSessionStorageOptions},
id => $session_id,
kind => "SSO",
}
);
unless ( $apacheSession->data ) {
Lemonldap::NG::Handler::Main::Logger->lmLog(
"The cookie $session_id isn't yet available", 'info' );
$class->updateStatus( $class->ip(), $apacheRequest->uri,
'EXPIRED' );
return $class->goToPortal($uri);
}
$datas->{$_} = $apacheSession->data->{$_}
foreach ( keys %{ $apacheSession->data } );
$datas->{_cache_id} = $id;
# Store now the user in the local storage
if ( $tsv->{refLocalStorage} ) {
$tsv->{refLocalStorage}
->set( $id, $datas->{_session_id}, "20 minutes" );
}
}
# ACCOUNTING
# 1 - Inform Apache
$class->lmSetApacheUser( $apacheRequest, $datas->{ $tsv->{whatToTrace} } );
# AUTHORIZATION
return $class->forbidden($uri) unless ( $class->grant($uri) );
$class->updateStatus( $datas->{ $tsv->{whatToTrace} },
$apacheRequest->uri, 'OK' );
$class->logGranted( $uri, $datas );
# SECURITY
# Hide Lemonldap::NG cookie
$class->hideCookie;
# Hide user password
Lemonldap::NG::Handler::Main::Headers->lmUnsetHeaderIn( $apacheRequest,
"Authorization" );
# ACCOUNTING
# 2 - Inform remote application
Lemonldap::NG::Handler::Main::Headers->sendHeaders( $apacheRequest,
$tsv->{forgeHeaders} );
OK;
}
1;
__END__
=head1 NAME
=encoding utf8
Lemonldap::NG::Handler::AuthBasic - Perl extension to be able to authenticate
users by basic web system but to use Lemonldap::NG to control authorizations.
=head1 SYNOPSIS
Create your own package:
package My::Package;
use Lemonldap::NG::Handler::AuthBasic;
# IMPORTANT ORDER
our @ISA = qw (Lemonldap::NG::Handler::AuthBasic);
__PACKAGE__->init ( {
# Local storage used for sessions and configuration
localStorage => "Cache::DBFile",
localStorageOptions => {...},
# How to get my configuration
configStorage => {
type => "DBI",
dbiChain => "DBI:mysql:database=lemondb;host=$hostname",
dbiUser => "lemonldap",
dbiPassword => "password",
}
# Uncomment this to activate status module
# status => 1,
} );
Call your package in <apache-directory>/conf/httpd.conf
PerlRequire MyFile
PerlHeaderParserHandler My::Package
=head1 DESCRIPTION
This library provides a way to use Lemonldap::NG to manage authorizations
without using Lemonldap::NG for authentications. This can be used in conjunction
with a normal Lemonldap::NG installation but to manage non-browser clients.
=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) 2008, 2009, 2010 by Xavier Guimard, E<lt>x.guimard@free.frE<gt>
=item Copyright (C) 2012, 2013 by François-Xavier Deltombe, E<lt>fxdeltombe@gmail.com.E<gt>
=item Copyright (C) 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

View File

@ -1,383 +0,0 @@
##@file
# Secure Token
##@class
# Secure Token
#
# Create a secure token used to resolve user identity by a protected application
# This specific handler is intended to be called by a handler caller
# old working, kept for compatibility with previous 1.4.0 versions
package Lemonldap::NG::Handler::SecureToken;
use strict;
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';
# Shared variables
our (
$secureTokenMemcachedServers, $secureTokenExpiration,
$secureTokenAttribute, $secureTokenUrls,
$secureTokenHeader, $datas,
$secureTokenMemcachedConnection, $secureTokenAllowOnError,
);
BEGIN {
eval {
require threads::shared;
threads::share($secureTokenMemcachedConnection);
};
}
## @imethod protected void globalInit(hashRef args)
# Overload globalInit to launch this class defaultValuesInit
# @param $args reference to the configuration hash
sub globalInit {
my $class = shift;
__PACKAGE__->defaultValuesInit(@_);
$class->SUPER::globalInit(@_);
}
## @imethod protected void defaultValuesInit(hashRef args)
# Overload defaultValuesInit
# @param $args reference to the configuration hash
sub defaultValuesInit {
my ( $class, $args ) = splice @_;
# Catch Secure Token parameters
$secureTokenMemcachedServers =
$args->{'secureTokenMemcachedServers'}
|| $secureTokenMemcachedServers
|| ['127.0.0.1:11211'];
$secureTokenExpiration =
$args->{'secureTokenExpiration'}
|| $secureTokenExpiration
|| '60';
$secureTokenAttribute =
$args->{'secureTokenAttribute'}
|| $secureTokenAttribute
|| 'uid';
$secureTokenUrls = $args->{'secureTokenUrls'} || $secureTokenUrls || ['.*'];
$secureTokenHeader =
$args->{'secureTokenHeader'}
|| $secureTokenHeader
|| 'Auth-Token';
$args->{'secureTokenAllowOnError'} = 1
unless defined $args->{'secureTokenAllowOnError'};
$secureTokenAllowOnError =
defined $secureTokenAllowOnError
? $secureTokenAllowOnError
: $args->{'secureTokenAllowOnError'};
# Force some parameters to be array references
foreach (qw/secureTokenMemcachedServers secureTokenUrls/) {
no strict 'refs';
unless ( ref ${$_} eq "ARRAY" ) {
Lemonldap::NG::Handler::Main::Logger->lmLog(
"Transform $_ value into an array reference", 'debug' );
my @array = split( /\s+/, ${$_} );
${$_} = \@array;
}
}
# Display found values in debug mode
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'};
delete $args->{'secureTokenExpiration'};
delete $args->{'secureTokenAttribute'};
delete $args->{'secureTokenUrls'};
delete $args->{'secureTokenHeader'};
delete $args->{'secureTokenAllowOnError'};
# Call main subroutine
return $class->SUPER::defaultValuesInit($args);
}
## @rmethod Apache2::Const run(Apache2::RequestRec r)
# Overload main run method
# @param r Current request
# @return Apache2::Const value (OK, FORBIDDEN, REDIRECT or SERVER_ERROR)
sub run {
my $class = shift;
my $r = $_[0];
my $ret = $class->SUPER::run(@_);
# Continue only if user is authorized
return $ret unless ( $ret == OK );
# Get current URI
my $args = $r->args;
my $uri = $r->uri . ( $args ? "?$args" : "" );
# Return if we are not on a secure token URL
my $checkurl = 0;
foreach (@$secureTokenUrls) {
if ( $uri =~ m#$_# ) {
$checkurl = 1;
Lemonldap::NG::Handler::Main::Logger->lmLog(
"URL $uri detected as an Secure Token URL (rule $_)", 'debug' );
last;
}
}
return OK unless ($checkurl);
# Test Memcached connection
unless ( $class->_isAlive() ) {
$secureTokenMemcachedConnection = $class->_createMemcachedConnection();
}
# Exit if no connection
return $class->_returnError() unless $class->_isAlive();
# Value to store
my $value = $datas->{$secureTokenAttribute};
# Set token
my $key = $class->_setToken($value);
return $class->_returnError() unless $key;
# Header location
Lemonldap::NG::Handler::Main::Headers->lmSetHeaderIn( $r,
$secureTokenHeader => $key );
# Remove token
eval 'use Apache2::Filter' unless ( $INC{"Apache2/Filter.pm"} );
$r->add_output_filter(
sub {
my $f = shift;
while ( $f->read( my $buffer, 1024 ) ) {
$f->print($buffer);
}
if ( $f->seen_eos ) {
$class->_deleteToken($key);
}
return OK;
}
);
# Return OK
return OK;
}
## @method private Cache::Memcached _createMemcachedConnection
# Create Memcached connexion
# @return Cache::Memcached object
sub _createMemcachedConnection {
my ($class) = splice @_;
# Open memcached connexion
my $memd = new Cache::Memcached {
'servers' => $secureTokenMemcachedServers,
'debug' => 0,
};
Lemonldap::NG::Handler::Main::Logger->lmLog( "Memcached connection created",
'debug' );
return $memd;
}
## @method private string _setToken(string value)
# Set token value
# @param value Value
# @return Token key
sub _setToken {
my ( $class, $value ) = splice @_;
my $key = Apache::Session::Generate::MD5::generate();
my $res =
$secureTokenMemcachedConnection->set( $key, $value,
$secureTokenExpiration );
unless ($res) {
Lemonldap::NG::Handler::Main::Logger->lmLog(
"Unable to store secure token $key", 'error' );
return;
}
Lemonldap::NG::Handler::Main::Logger->lmLog( "Set $value in token $key",
'info' );
return $key;
}
## @method private boolean _deleteToken(string key)
# Delete token
# @param key Key
# @return result
sub _deleteToken {
my ( $class, $key ) = splice @_;
my $res = $secureTokenMemcachedConnection->delete($key);
unless ($res) {
Lemonldap::NG::Handler::Main::Logger->lmLog(
"Unable to delete secure token $key", 'error' );
}
else {
Lemonldap::NG::Handler::Main::Logger->lmLog( "Token $key deleted",
'info' );
}
return $res;
}
## @method private boolean _isAlive()
# Run a STATS command to see if Memcached connection is alive
# @param connection Cache::Memcached object
# @return result
sub _isAlive {
my ($class) = splice @_;
return 0 unless defined $secureTokenMemcachedConnection;
my $stats = $secureTokenMemcachedConnection->stats();
if ( $stats and defined $stats->{'total'} ) {
my $total_c = $stats->{'total'}->{'connection_structures'};
my $total_i = $stats->{'total'}->{'total_items'};
Lemonldap::NG::Handler::Main::Logger->lmLog(
"Memcached connection is alive ($total_c connections / $total_i items)",
'debug'
);
return 1;
}
Lemonldap::NG::Handler::Main::Logger->lmLog(
"Memcached connection is not alive", 'error' );
return 0;
}
## @method private int _returnError()
# Give hand back to Apache
# @return Apache2::Const value
sub _returnError {
my ($class) = splice @_;
if ($secureTokenAllowOnError) {
Lemonldap::NG::Handler::Main::Logger->lmLog(
"Allow request without secure token", 'debug' );
return OK;
}
# Redirect or Forbidden?
if ( $tsv->{useRedirectOnError} ) {
Lemonldap::NG::Handler::Main::Logger->lmLog( "Use redirect for error",
'debug' );
return $class->goToPortal( '/', 'lmError=500' );
}
else {
Lemonldap::NG::Handler::Main::Logger->lmLog( "Return error", 'debug' );
return SERVER_ERROR;
}
}
1;
__END__
=head1 NAME
=encoding utf8
Lemonldap::NG::Handler::SecureToken - Perl extension to generate a secure token
=head1 SYNOPSIS
package My::SecureToken;
use Lemonldap::NG::Handler::SecureToken;
@ISA = qw(Lemonldap::NG::Handler::SecureToken);
__PACKAGE__->init ( {
# See Lemonldap::NG::Handler for more
} );
1;
=head1 DESCRIPTION
Edit your vhost configuration like this:
<VirtualHost *>
ServerName secure.example.com
# Load Secure Token Handler
PerlRequire __HANDLERDIR__/MyHandlerSecureToken.pm
PerlHeaderParserHandler My::SecureToken
</VirtualHost>
=head2 EXPORT
See L<Lemonldap::NG::Handler>
=head1 SEE ALSO
L<Lemonldap::NG::Handler>
=head1 AUTHOR
=over
=item Clement Oudot, E<lt>clem.oudot@gmail.comE<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) 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/>.

View File

@ -1,205 +0,0 @@
##@file
# Sympa autologin
##@class
# Sympa autologin
#
# Build Sympa cookie and send it to Sympa
# This specific handler is intended to be called by a handler caller
# old working, kept for compatibility with previous 1.4.0 versions
package Lemonldap::NG::Handler::SympaAutoLogin;
use strict;
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';
# Shared variables
our ( $sympaSecret, $sympaMailKey );
## @imethod protected void globalInit(hashRef args)
# Overload globalInit to launch this class defaultValuesInit
# @param $args reference to the configuration hash
sub globalInit {
my $class = shift;
__PACKAGE__->defaultValuesInit(@_);
$class->SUPER::globalInit(@_);
}
## @imethod protected void defaultValuesInit(hashRef args)
# Overload defaultValuesInit
# @param $args reference to the configuration hash
sub defaultValuesInit {
my ( $class, $args ) = splice @_;
# Sympa secret should be in configuration
$sympaSecret = $args->{'sympaSecret'} || $sympaSecret;
# If not, try to read it from /etc/lemonldap-ng/sympa.secret
if ( !$sympaSecret and -r '/etc/lemonldap-ng/sympa.secret' ) {
open S, '/etc/lemonldap-ng/sympa.secret'
or die("Unable to open /etc/lemonldap-ng/sympa.secret");
$sympaSecret = join( '', <S> );
close S;
$sympaSecret =~ s/[\r\n]//g;
}
# Sympa mail key
$sympaMailKey = $args->{'sympaMailKey'} || $sympaMailKey || "mail";
# Display found values in debug mode
Lemonldap::NG::Handler::Main::Logger->lmLog( "sympaSecret: $sympaSecret",
'debug' );
Lemonldap::NG::Handler::Main::Logger->lmLog( "sympaMailKey: $sympaMailKey",
'debug' );
# Delete Sympa parameters
delete $args->{'sympaSecret'};
delete $args->{'sympaMailKey'};
# Call main subroutine
return $class->SUPER::defaultValuesInit($args);
}
## @rmethod Apache2::Const run(Apache2::RequestRec r)
# Overload main run method
# @param r Current request
# @return Apache2::Const value (OK, FORBIDDEN, REDIRECT or SERVER_ERROR)
sub run {
my $class = shift;
my $r = $_[0];
my $ret = $class->SUPER::run(@_);
# Continue only if user is authorized
return $ret unless ( $ret == OK );
# Fail if no sympaSecret
return $class->abort("No Sympa secret configured")
unless ($sympaSecret);
# Mail value
my $mail = $datas->{$sympaMailKey};
# Building Sympa cookie
my $tmp = new Digest::MD5;
$tmp->reset;
$tmp->add( $mail . $sympaSecret );
my $str = "sympauser=$mail:" . substr( unpack( "H*", $tmp->digest ), -8 );
# Get cookie header, removing Sympa cookie if exists (avoid security
# problems) and set the new value
$tmp = Lemonldap::NG::Handler::Main::Headers->lmHeaderIn( $r, 'Cookie' );
$tmp =~ s/\bsympauser=[^,;]*[,;]?//;
$tmp .= $tmp ? ";$str" : $str;
Lemonldap::NG::Handler::Main::Headers->lmSetHeaderIn( $r,
'Cookie' => $tmp );
# Return SUPER::run() result
return $ret;
}
1;
__END__
=head1 NAME
=encoding utf8
Lemonldap::NG::Handler::SympaAutoLogin - Perl extension to generate Sympa cookie
for users authenticated by LemonLDAP::NG
=head1 SYNOPSIS
package My::Sympa;
use Lemonldap::NG::Handler::SympaAutoLogin;
@ISA = qw(Lemonldap::NG::Handler::SympaAutoLogin);
__PACKAGE__->init ( {
# Sympa parameters
sympaSecret => 'XXXX',
sympaMailKey => 'mail',
# See Lemonldap::NG::Handler for more
} );
1;
=head1 DESCRIPTION
Lemonldap::NG::Handler::SympaAutoLogin is a special Lemonldap::NG handler that
generates Sympa cookie for authenticated users. Use it instead of classic
Lemonldap::NG::Handler to protect your Sympa web server. You have to set the
configuration key containing user email (parameter sympaMailKey) and to
store Sympa secret (cookie parameter on Sympa configuration file) in the
corresponding configuration parameter (sympaSecret)
Edit you Sympa vhost configuration like this:
<VirtualHost *>
ServerName sympa.example.com
# Load Sympa Handler
PerlRequire __HANDLERDIR__/MyHandlerSympa.pm
PerlHeaderParserHandler My::Sympa
</VirtualHost>
=head2 EXPORT
See L<Lemonldap::NG::Handler>
=head1 SEE ALSO
L<Lemonldap::NG::Handler>
=head1 AUTHOR
=over
=item Clement Oudot, E<lt>clem.oudot@gmail.comE<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) 2009, 2010 by Xavier Guimard, E<lt>x.guimard@free.frE<gt>
=item Copyright (C) 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

View File

@ -1,181 +0,0 @@
## @file
# Lemonldap::NG special handler
## @class
# Lemonldap::NG special handler
# This specific handler is intended to be called by a handler caller
# old working, kept for compatibility with previous 1.4.0 versions
package Lemonldap::NG::Handler::UpdateCookie;
use strict;
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;
use Lemonldap::NG::Common::Session;
our $VERSION = '1.4.0';
## @rmethod int run(Apache2::RequestRec apacheRequest)
# Main method used to control access.
# Calls :
# - fetchId()
# - fetchUTime()
# - SUPER::run()
# @param $apacheRequest Current request
# @return Apache2::Const value (OK, FORBIDDEN, REDIRECT or SERVER_ERROR)
sub run {
my $class = shift;
$apacheRequest = $_[0];
# I - Recover the main cookie.
# If not present, then call parent.
my $id;
if ( $id = $class->SUPER::fetchId ) {
# II - Found update cookie.
# If found, remove session from local cache when utime is recent.
my $utime;
if ( $utime = $class->fetchUTime ) {
my $clear = 0;
my $apacheSession = Lemonldap::NG::Common::Session->new(
{
storageModule => $tsv->{globalStorage},
storageModuleOptions => $tsv->{globalStorageOptions},
cacheModule => $tsv->{localSessionStorage},
cacheModuleOptions => $tsv->{localSessionStorageOptions},
id => $id,
kind => "SSO",
}
);
# Check process data
if ( $id eq $datas->{_session_id} and $datas->{_utime} lt $utime ) {
$datas->{_session_id} = 0;
$clear = 1;
}
# Get session
else {
unless ( $apacheSession->data ) {
Lemonldap::NG::Handler::Main::Logger->lmLog(
"Session $id can't be retrieved", 'info' );
}
else {
$clear = 1 if ( $apacheSession->data->{_utime} lt $utime );
}
}
# Clear cache if needed
if ($clear) {
Lemonldap::NG::Handler::Main::Logger->lmLog(
"$class: remove $id from local cache", 'debug' );
$apacheSession->cacheUpdate();
}
}
}
# III - Call parent process.
$class->SUPER::run(@_);
}
## @rmethod protected $ fetchUTime()
# Get user cookies and search for Lemonldap::NG update cookie.
# @return Value of the cookie if found, 0 else
sub fetchUTime {
my $t = Lemonldap::NG::Handler::Main::Headers->lmHeaderIn( $apacheRequest,
'Cookie' );
my $c = $tsv->{cookieName} . 'update';
return ( $t =~ /$c=([^,; ]+)/o ) ? $1 : 0;
}
1;
__END__
=head1 NAME
=encoding utf8
Lemonldap::NG::Handler::UpdateCookie - Perl extension to manage update
cookie sent by client, to reload session in local cache.
=head1 SYNOPSIS
package My::Package;
use Lemonldap::NG::Handler::UpdateCookie;
@ISA = qw(Lemonldap::NG::Handler::DefaultHandler);
__PACKAGE__->init ( {
# See Lemonldap::NG::Handler for more
# Local storage used for sessions and configuration
} );
=head1 DESCRIPTION
Lemonldap::NG::Handler::UpdateCookie is a special Lemonldap::NG:: handler that
allow a session to be removed from local cache of the current handler, if a
update cookie is sent by the user.
The update cookie should be name "lemonldapupdate" and only contains a simple
timestamp.
=head2 EXPORT
See L<Lemonldap::NG::Handler>
=head1 SEE ALSO
L<Lemonldap::NG::Handler>
=head1 AUTHOR
=over
=item Clement Oudot, E<lt>clem.oudot@gmail.comE<gt>
=item Xavier Guimard, E<lt>x.guimard@free.frE<gt>
=item Thomas Chemineau, E<lt>thomas.chemineau@gmail.comE<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) 2010 by Xavier Guimard, E<lt>x.guimard@free.frE<gt>
=item Copyright (C) 2010, 2012 by Clement Oudot, E<lt>clem.oudot@gmail.comE<gt>
=item Copyright (C) 2010 by Thomas Chemineau, E<lt>thomas.chemineau@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

View File

@ -1,248 +0,0 @@
##@file
# Zimbra preauthentication
##@class
# Zimbra preauthentication
#
# It will build Zimbra preauth URL
# This specific handler is intended to be called by a handler caller
# old working, kept for compatibility with previous 1.4.0 versions
package Lemonldap::NG::Handler::ZimbraPreAuth;
use strict;
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';
# Shared variables
our ( $zimbraPreAuthKey, $zimbraAccountKey, $zimbraBy, $zimbraUrl,
$zimbraSsoUrl, $timeout );
## @imethod protected void globalInit(hashRef args)
# Overload globalInit to launch this class defaultValuesInit
# @param $args reference to the configuration hash
sub globalInit {
my $class = shift;
__PACKAGE__->defaultValuesInit(@_);
$class->SUPER::globalInit(@_);
}
## @imethod protected void defaultValuesInit(hashRef args)
# Overload defaultValuesInit
# @param $args reference to the configuration hash
sub defaultValuesInit {
my ( $class, $args ) = splice @_;
# Catch Zimbra parameters
$zimbraPreAuthKey = $args->{'zimbraPreAuthKey'} || $zimbraPreAuthKey;
$zimbraAccountKey =
$args->{'zimbraAccountKey'}
|| $zimbraAccountKey
|| 'uid';
$zimbraBy = $args->{'zimbraBy'} || $zimbraBy || 'id';
$zimbraUrl = $args->{'zimbraUrl'} || $zimbraUrl || '/service/preauth';
$zimbraSsoUrl = $args->{'zimbraSsoUrl'} || $zimbraSsoUrl || '^/zimbrasso$';
$timeout = $args->{'timeout'} || $timeout || '0';
# Display found values in debug mode
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'};
delete $args->{'zimbraAccountKey'};
delete $args->{'zimbraBy'};
delete $args->{'zimbraUrl'};
delete $args->{'zimbraSsoUrl'};
delete $args->{'timeout'};
# Call main subroutine
return $class->SUPER::defaultValuesInit($args);
}
## @rmethod Apache2::Const run(Apache2::RequestRec r)
# Overload main run method
# @param r Current request
# @return Apache2::Const value (OK, FORBIDDEN, REDIRECT or SERVER_ERROR)
sub run {
my $class = shift;
my $r = $_[0];
my $ret = $class->SUPER::run(@_);
# Continue only if user is authorized
return $ret unless ( $ret == OK );
# Get current URI
my $args = $r->args;
my $uri = $r->uri . ( $args ? "?$args" : "" );
# Return if we are not on a Zimbra SSO URI
return OK unless ( $uri =~ $zimbraSsoUrl );
# Check mandatory parameters
return $class->abort("No Zimbra preauth key configured")
unless ($zimbraPreAuthKey);
# Build URL
my $zimbra_url = $class->_buildZimbraPreAuthUrl(
$zimbraPreAuthKey, $zimbraUrl,
$datas->{$zimbraAccountKey}, $zimbraBy
);
# Header location
Lemonldap::NG::Handler::Main::Headers->lmSetHeaderOut( $r,
'Location' => $zimbra_url );
# Return REDIRECT
return REDIRECT;
}
## @method private string _buildZimbraPreAuthUrl(string key, string url, string account, string by)
# Build Zimbra PreAuth URL
# @param key PreAuthKey
# @param url URL
# @param account User account
# @param by Account type
# @return Zimbra PreAuth URL
sub _buildZimbraPreAuthUrl {
my ( $class, $key, $url, $account, $by ) = splice @_;
# Expiration time is calculated with _utime and timeout
my $expires = $timeout ? ( $datas->{_utime} + $timeout ) * 1000 : $timeout;
# Timestamp
my $timestamp = time() * 1000;
# Compute preauth value
my $computed_value =
hmac_sha1_hex( "$account|$by|$expires|$timestamp", $key );
Lemonldap::NG::Handler::Main::Logger->lmLog(
"Compute value $account|$by|$expires|$timestamp into $computed_value",
'debug' );
# Build PreAuth URL
my $zimbra_url =
"$url?account=$account&by=$by&timestamp=$timestamp&expires=$expires&preauth=$computed_value";
Lemonldap::NG::Handler::Main::Logger->lmLog(
"Build Zimbra URL: $zimbra_url", 'debug' );
return $zimbra_url;
}
1;
__END__
=head1 NAME
=encoding utf8
Lemonldap::NG::Handler::ZimbraPreAuth - Perl extension to generate Zimbra preauth URL
for users authenticated by Lemonldap::NG
=head1 SYNOPSIS
package My::Zimbra;
use Lemonldap::NG::Handler::ZimbraPreAuth;
@ISA = qw(Lemonldap::NG::Handler::ZimbraPreAuth);
__PACKAGE__->init ( {
# Zimbra parameters
zimbraPreAuthKey => 'XXXX',
zimbraAccountKey => 'uid',
zimbraBy => 'id',
zimbraUrl => '/service/preauth',
zimbraSsoUrl => '^/zimbrasso$',
# Common parameters
timeout => '72000',
# See Lemonldap::NG::Handler for more
} );
1;
=head1 DESCRIPTION
Edit you Zimbra vhost configuration like this:
<VirtualHost *>
ServerName zimbra.example.com
# Load Zimbra Handler
PerlRequire __HANDLERDIR__/MyHandlerZimbra.pm
PerlHeaderParserHandler My::Zimbra
</VirtualHost>
=head2 EXPORT
See L<Lemonldap::NG::Handler>
=head1 SEE ALSO
L<http://wiki.zimbra.com/wiki/Preauth>
L<Lemonldap::NG::Handler>
=head1 AUTHOR
=over
=item Clement Oudot, E<lt>clem.oudot@gmail.comE<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) 2010 by Xavier Guimard, E<lt>x.guimard@free.frE<gt>
=item Copyright (C) 2010, 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