2008-12-28 09:36:52 +01:00
|
|
|
##@file
|
|
|
|
# Auth-basic authentication with Lemonldap::NG rights management
|
|
|
|
|
|
|
|
##@class
|
|
|
|
# Auth-basic authentication with Lemonldap::NG rights management
|
2008-05-19 11:39:15 +02:00
|
|
|
package Lemonldap::NG::Handler::AuthBasic;
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
|
|
|
|
use Lemonldap::NG::Handler::SharedConf qw(:all);
|
|
|
|
use Digest::MD5 qw(md5_base64);
|
|
|
|
use MIME::Base64;
|
2009-02-10 12:10:12 +01:00
|
|
|
use SOAP::Lite; # link protected portalRequest
|
2008-05-19 11:39:15 +02:00
|
|
|
|
2008-12-04 14:53:05 +01:00
|
|
|
use base qw(Lemonldap::NG::Handler::SharedConf);
|
2009-02-10 12:10:12 +01:00
|
|
|
use utf8;
|
|
|
|
no utf8;
|
2008-05-19 11:39:15 +02:00
|
|
|
|
2012-10-16 16:11:52 +02:00
|
|
|
our $VERSION = '1.2.3';
|
2008-05-19 11:39:15 +02:00
|
|
|
|
|
|
|
# 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}';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-25 19:10:07 +01:00
|
|
|
## @rmethod int run(Apache2::RequestRec apacheRequest)
|
2008-12-28 09:36:52 +01:00
|
|
|
# overload run subroutine to implement Auth-Basic mechanism.
|
|
|
|
# @param $apacheRequest current request
|
|
|
|
# @return Apache constant
|
2008-05-19 11:39:15 +02:00
|
|
|
sub run ($$) {
|
|
|
|
my $class;
|
2010-01-31 09:25:05 +01:00
|
|
|
( $class, $apacheRequest ) = splice @_;
|
2008-05-19 11:39:15 +02:00
|
|
|
if ( time() - $lastReload > $reloadTime ) {
|
2009-02-10 12:10:12 +01:00
|
|
|
unless ( my $tmp = $class->testConf(1) == OK ) {
|
2008-05-19 11:39:15 +02:00
|
|
|
$class->lmLog( "$class: No configuration found", 'error' );
|
2009-02-10 12:10:12 +01:00
|
|
|
return $tmp;
|
2008-05-19 11:39:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return DECLINED unless ( $apacheRequest->is_initial_req );
|
2008-11-20 18:34:35 +01:00
|
|
|
my $uri = $apacheRequest->uri
|
|
|
|
. ( $apacheRequest->args ? "?" . $apacheRequest->args : "" );
|
2008-05-19 11:39:15 +02:00
|
|
|
|
|
|
|
# AUTHENTICATION
|
|
|
|
# I - recover the WWW-Authentication header
|
|
|
|
my ( $id, $user, $pass );
|
|
|
|
unless ( $user = lmHeaderIn( $apacheRequest, 'Authorization' ) ) {
|
2008-11-20 18:34:35 +01:00
|
|
|
lmSetErrHeaderOut( $apacheRequest,
|
2012-09-05 16:00:53 +02:00
|
|
|
'WWW-Authenticate' => 'Basic realm="LemonLDAP::NG"' );
|
2008-05-19 11:39:15 +02:00
|
|
|
return AUTH_REQUIRED;
|
|
|
|
}
|
|
|
|
$user =~ s/^Basic\s*//;
|
2008-11-20 18:34:35 +01:00
|
|
|
|
2008-05-19 11:39:15 +02:00
|
|
|
# DEBUG
|
|
|
|
$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).
|
2012-10-12 20:35:25 +02:00
|
|
|
unless ( $id eq $datas->{_cache_id} ) {
|
2008-05-19 11:39:15 +02:00
|
|
|
|
|
|
|
# 2.2 search in the local cache if exists
|
|
|
|
unless ( $refLocalStorage and $datas = $refLocalStorage->get($id) ) {
|
|
|
|
|
2009-02-10 12:10:12 +01:00
|
|
|
# 2.3 Authentication by Lemonldap::NG::Portal using SOAP request
|
|
|
|
my $soap =
|
2009-04-02 08:07:01 +02:00
|
|
|
SOAP::Lite->proxy( $class->portal() )
|
2009-02-10 12:10:12 +01:00
|
|
|
->uri('urn:Lemonldap::NG::Common::CGI::SOAPService');
|
|
|
|
$user = decode_base64($user);
|
2009-04-20 19:49:35 +02:00
|
|
|
( $user, $pass ) = ( $user =~ /^(.*?):(.*)$/ );
|
2012-09-10 11:23:46 +02:00
|
|
|
$class->lmLog( "AuthBasic authentication for user: $user",
|
|
|
|
'debug' );
|
2009-02-10 12:10:12 +01:00
|
|
|
my $r = $soap->getCookies( $user, $pass );
|
2010-06-21 15:35:36 +02:00
|
|
|
my $cv;
|
2009-02-10 12:10:12 +01:00
|
|
|
|
|
|
|
# Catch SOAP errors
|
|
|
|
if ( $r->fault ) {
|
2010-10-20 22:05:32 +02:00
|
|
|
return $class->abort( "SOAP request to the portal failed: "
|
|
|
|
. $r->fault->{faultstring} );
|
2009-02-10 12:10:12 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
my $res = $r->result();
|
|
|
|
|
|
|
|
# If authentication failed, display error
|
2012-09-05 16:00:53 +02:00
|
|
|
if ( $res->{errorCode} ) {
|
2009-02-10 12:10:12 +01:00
|
|
|
$class->lmLog(
|
2012-09-05 16:00:53 +02:00
|
|
|
"Authentication failed for $user: "
|
|
|
|
. $soap->error( $res->{errorCode}, 'en' )->result(),
|
2009-02-10 12:10:12 +01:00
|
|
|
'notice'
|
|
|
|
);
|
2012-09-05 16:00:53 +02:00
|
|
|
lmSetErrHeaderOut( $apacheRequest,
|
|
|
|
'WWW-Authenticate' => 'Basic realm="LemonLDAP::NG"' );
|
2009-02-10 12:10:12 +01:00
|
|
|
return AUTH_REQUIRED;
|
2008-11-20 18:34:35 +01:00
|
|
|
}
|
2010-06-21 15:35:36 +02:00
|
|
|
$cv = $res->{cookies}->{$cookieName};
|
2009-02-10 12:10:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
# Now, normal work to find session
|
|
|
|
my %h;
|
2010-06-21 15:35:36 +02:00
|
|
|
eval { tie %h, $globalStorage, $cv, $globalStorageOptions; };
|
2009-02-10 12:10:12 +01:00
|
|
|
if ($@) {
|
|
|
|
|
|
|
|
# The cookie isn't yet available
|
2010-06-21 15:35:36 +02:00
|
|
|
$class->lmLog( "The cookie $cv isn't yet available: $@",
|
2009-02-10 12:10:12 +01:00
|
|
|
'info' );
|
|
|
|
$class->updateStatus( $apacheRequest->connection->remote_ip,
|
|
|
|
$apacheRequest->uri, 'EXPIRED' );
|
|
|
|
return $class->goToPortal($uri);
|
|
|
|
}
|
|
|
|
$datas->{$_} = $h{$_} foreach ( keys %h );
|
2012-10-12 20:35:25 +02:00
|
|
|
$datas->{_cache_id} = $id;
|
2009-02-10 12:10:12 +01:00
|
|
|
|
2008-05-19 11:39:15 +02:00
|
|
|
# Store now the user in the local storage
|
|
|
|
if ($refLocalStorage) {
|
|
|
|
$refLocalStorage->set( $id, $datas, "20 minutes" );
|
|
|
|
}
|
2009-02-15 20:56:01 +01:00
|
|
|
untie %h;
|
2008-05-19 11:39:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# ACCOUNTING
|
|
|
|
# 1 - Inform Apache
|
2009-05-06 07:38:20 +02:00
|
|
|
$class->lmSetApacheUser( $apacheRequest, $datas->{$whatToTrace} );
|
2008-05-19 11:39:15 +02:00
|
|
|
|
|
|
|
# AUTHORIZATION
|
|
|
|
return $class->forbidden($uri) unless ( $class->grant($uri) );
|
2009-02-15 20:56:01 +01:00
|
|
|
$class->updateStatus( $datas->{$whatToTrace}, $apacheRequest->uri, 'OK' );
|
2012-09-10 11:23:46 +02:00
|
|
|
$class->logGranted( $uri, $datas );
|
2008-05-19 11:39:15 +02:00
|
|
|
|
|
|
|
# ACCOUNTING
|
|
|
|
# 2 - Inform remote application
|
|
|
|
$class->sendHeaders;
|
|
|
|
|
|
|
|
# SECURITY
|
|
|
|
# Hide Lemonldap::NG cookie
|
|
|
|
$class->hideCookie;
|
2009-02-03 18:49:10 +01:00
|
|
|
|
|
|
|
# Hide user password
|
2011-10-05 16:33:05 +02:00
|
|
|
$class->lmSetHeaderIn( $apacheRequest, Authorization => '' );
|
2008-05-19 11:39:15 +02:00
|
|
|
OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
1;
|
|
|
|
|
|
|
|
__END__
|
|
|
|
|
|
|
|
=head1 NAME
|
|
|
|
|
2010-01-03 09:09:59 +01:00
|
|
|
=encoding utf8
|
|
|
|
|
2008-05-19 11:39:15 +02:00
|
|
|
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)>,
|
2010-10-26 08:08:16 +02:00
|
|
|
L<http://lemonldap-ng.org/>
|
2008-05-19 11:39:15 +02:00
|
|
|
|
|
|
|
=head1 AUTHOR
|
|
|
|
|
|
|
|
Xavier Guimard, E<lt>x.guimard@free.frE<gt>
|
|
|
|
|
|
|
|
=head1 BUG REPORT
|
|
|
|
|
|
|
|
Use OW2 system to report bug or ask for features:
|
2010-10-26 08:08:16 +02:00
|
|
|
L<http://jira.ow2.org>
|
2008-05-19 11:39:15 +02:00
|
|
|
|
|
|
|
=head1 DOWNLOAD
|
|
|
|
|
|
|
|
Lemonldap::NG is available at
|
|
|
|
L<http://forge.objectweb.org/project/showfiles.php?group_id=274>
|
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE
|
|
|
|
|
2010-10-23 10:35:38 +02:00
|
|
|
Copyright (C) 2008, 2010 by Xavier Guimard E<lt>x.guimard@free.frE<gt>
|
2008-05-19 11:39:15 +02:00
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify
|
2010-10-24 09:25:44 +02:00
|
|
|
it under the same terms as Perl itself, either Perl version 5.10.0 or,
|
2008-05-19 11:39:15 +02:00
|
|
|
at your option, any later version of Perl 5 you may have available.
|
|
|
|
|
|
|
|
=cut
|