Add slave auth (#595)

environments/ppa-mbqj77/deployments/1
Xavier Guimard 9 years ago
parent fd5a1230a6
commit 4ee99bd0f9
  1. 4
      lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/Base.pm
  2. 4
      lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/Null.pm
  3. 49
      lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/Slave.pm
  4. 152
      lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthSlave.pm
  5. 42
      lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/Slave.pm
  6. 7
      lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Process.pm
  7. 46
      lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/Slave.pm
  8. 36
      lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDBSlave.pm
  9. 41
      lemonldap-ng-portal/lib/Lemonldap/NG/Portal/_Slave.pm
  10. 2
      lemonldap-ng-portal/t/01-AuthDemo.t
  11. 35
      lemonldap-ng-portal/t/06-AuthSlave.t
  12. 5
      lemonldap-ng-portal/t/test-lib.pm

@ -34,6 +34,10 @@ authentication modules.
our $VERSION = '0.1';
extends 'Lemonldap::NG::Portal::Auth::Base';
sub init {
...
}
sub extractFormInfo {
my ( $self, $req ) = @_;

@ -30,10 +30,6 @@ sub authLogout {
PE_OK;
}
sub getDisplayType {
return 'logo';
}
sub getDisplayType {
return '';
}

@ -0,0 +1,49 @@
package Lemonldap::NG::Portal::Auth::Slave;
use strict;
use Mouse;
# Add constants used by this module
use Lemonldap::NG::Portal::Main::Constants
qw(PE_OK PE_FORBIDDENIP PE_USERNOTFOUND);
use Lemonldap::NG::Portal::Lib::Slave;
our $VERSION = '2.0.0';
extends 'Lemonldap::NG::Portal::Auth::Base';
sub init { 1 }
sub extractFormInfo {
my ( $self, $req ) = @_;
return PE_FORBIDDENIP
unless ( $self->checkIP($req) and $self->checkHeader($req) );
my $user_header = $self->conf->{slaveUserHeader};
$user_header = 'HTTP_' . uc($user_header);
$user_header =~ s/\-/_/g;
unless ( $req->{user} = $req->{$user_header} ) {
$self->lmLog( "No header " . $self->conf->{slaveUserHeader} . " found",
'error' );
return PE_USERNOTFOUND;
}
PE_OK;
}
sub authenticate {
my ( $self, $req ) = @_;
PE_OK;
}
sub authForce {
my ( $self, $req ) = @_;
PE_OK;
}
sub authLogout {
my ( $self, $req ) = @_;
PE_OK;
}
1;

@ -1,152 +0,0 @@
##@file
# Slave authentication backend file
##@class
# Slave authentication backend class
package Lemonldap::NG::Portal::AuthSlave;
use strict;
use Lemonldap::NG::Portal::_Slave;
use Lemonldap::NG::Portal::Simple;
use Lemonldap::NG::Portal::AuthNull;
our $VERSION = '2.0.0';
our @ISA = qw(Lemonldap::NG::Portal::AuthNull);
## @apmethod int extractFormInfo()
# Read username in a specific header.
# @return Lemonldap::NG::Portal constant
sub extractFormInfo {
my $self = shift;
return PE_FORBIDDENIP
unless ( $self->checkIP and $self->checkHeader );
my $user_header = $self->{slaveUserHeader};
$user_header = 'HTTP_' . uc($user_header);
$user_header =~ s/\-/_/g;
unless ( $self->{user} = $ENV{$user_header} ) {
$self->lmLog( "No header " . $self->{slaveUserHeader} . " found",
'error' );
return PE_USERNOTFOUND;
}
PE_OK;
}
## @apmethod int setAuthSessionInfo()
# Set _user value to 'anonymous' and authenticationLevel to 0
# @return Lemonldap::NG::Portal constant
sub setAuthSessionInfo {
my $self = shift;
# Store user submitted login for basic rules
$self->{sessionInfo}->{'_user'} = $self->{'user'};
$self->{sessionInfo}->{authenticationLevel} = $self->{slaveAuthnLevel};
PE_OK;
}
## @method string getDisplayType
# @return display type
sub getDisplayType {
return "logo";
}
1;
__END__
=head1 NAME
=encoding utf8
Lemonldap::NG::Portal::AuthSlave - Perl extension for building Lemonldap::NG
compatible portals with Apache authentication.
=head1 SYNOPSIS
use Lemonldap::NG::Portal::SharedConf;
my $portal = new Lemonldap::NG::Portal::Simple(
configStorage => {...}, # See Lemonldap::NG::Portal
authentication => 'Slave',
);
if($portal->process()) {
# Write here the menu with CGI methods. This page is displayed ONLY IF
# the user was not redirected here.
print $portal->header('text/html; charset=utf-8'); # DON'T FORGET THIS (see CGI(3))
print "...";
# or redirect the user to the menu
print $portal->redirect( -uri => 'https://portal/menu');
}
else {
print $portal->header('text/html; charset=utf-8'); # DON'T FORGET THIS (see CGI(3))
print "<html><body><h1>Unable to work</h1>";
print "This server isn't well configured. Contact your administrator.";
print "</body></html>";
}
=head1 DESCRIPTION
This library just overload few methods of Lemonldap::NG::Portal::Simple to
create sessions for anonymous users.
See L<Lemonldap::NG::Portal::Simple> for usage and other methods.
=head1 SEE ALSO
L<Lemonldap::NG::Portal>, L<Lemonldap::NG::Portal::Simple>,
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) 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) 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

@ -0,0 +1,42 @@
##@file
# Slave common functions
##@class
# Slave common functions
package Lemonldap::NG::Portal::Lib::Slave;
use Exporter;
use base qw(Exporter);
use strict;
our @EXPORT = qw(checkIP checkHeader);
our $VERSION = '2.0.0';
## @method Lemonldap::NG::Portal::_Slave checkIP()
# @return true if remote IP is accredited in LL::NG conf
sub checkIP {
my ( $self, $req ) = @_;
my $remoteIP = $req->remote_ip;
return 1
if (!$self->conf->{slaveMasterIP}
|| $self->conf->{slaveMasterIP} =~ /\b$remoteIP\b/ );
$self->userError('Client IP not accredited for Slave module');
return 0;
}
## @method Lemonldap::NG::Portal::_Slave checkHeader()
# @return true if header content matches LL::NG conf
sub checkHeader {
my ( $self, $req ) = @_;
return 1
unless ( $self->conf->{slaveHeaderName}
and $self->conf->{slaveHeaderContent} );
my $headerContent = $req->{ $self->conf->{slaveHeaderName} };
return 1 if ( $self->conf->{slaveHeaderContent} =~ /\b$headerContent\b/ );
$self->userError('Matching header not found for Slave module ');
return 0;
}
1;

@ -216,7 +216,12 @@ sub checkXSSAttack {
sub extractFormInfo {
my ( $self, $req ) = @_;
return $self->_authentication->extractFormInfo($req);
my $ret = $self->_authentication->extractFormInfo($req);
if($ret == PE_OK and not $req->user) {
$self->lmLog('Authentication module succeed but has not set $req->user','error');
return PE_ERROR;
}
return $ret;
}
sub getUser {

@ -0,0 +1,46 @@
## @file
# Slave userDB mechanism
## @class
# Slave userDB mechanism class
package Lemonldap::NG::Portal::UserDB::Slave;
use strict;
use Mouse;
use Lemonldap::NG::Portal::Lib::Slave;
use Lemonldap::NG::Portal::Main::Constants qw(PE_FORBIDDENIP PE_OK);
our $VERSION = '2.0.0';
extends 'Lemonldap::NG::Portal::Main::Module';
sub init { 1 }
sub getUser {
PE_OK;
}
# Search exportedVars values in HTTP headers.
sub setSessionInfo {
my ( $self, $req ) = @_;
return PE_FORBIDDENIP
unless ( $self->checkIP($req) );
my %vars = (
%{ $self->conf->{exportedVars} },
%{ $self->conf->{slaveExportedVars} }
);
while ( my ( $k, $v ) = each %vars ) {
$v = 'HTTP_' . uc($v);
$v =~ s/\-/_/g;
$req->{sessionInfo}->{$k} = $req->{$v};
}
return PE_OK;
}
sub setGroups {
PE_OK;
}
1;

@ -1,36 +0,0 @@
## @file
# Slave userDB mechanism
## @class
# Slave userDB mechanism class
package Lemonldap::NG::Portal::UserDBSlave;
use strict;
use Lemonldap::NG::Portal::_Slave;
use Lemonldap::NG::Portal::Simple;
use Lemonldap::NG::Portal::UserDBNull;
our $VERSION = '2.0.0';
our @ISA = qw(Lemonldap::NG::Portal::UserDBNull);
## @apmethod int setSessionInfo()
# Search exportedVars values in HTTP headers.
# @return Lemonldap::NG::Portal constant
sub setSessionInfo {
my $self = shift;
return PE_FORBIDDENIP
unless ( $self->checkIP );
my %vars = ( %{ $self->{exportedVars} }, %{ $self->{slaveExportedVars} } );
while ( my ( $k, $v ) = each %vars ) {
$v = 'HTTP_' . uc($v);
$v =~ s/\-/_/g;
$self->{sessionInfo}->{$k} = $ENV{$v};
}
return PE_OK;
}
1;

@ -1,41 +0,0 @@
##@file
# Slave common functions
##@class
# Slave common functions
package Lemonldap::NG::Portal::_Slave;
use Exporter;
use base qw(Exporter);
use strict;
our @EXPORT = qw(checkIP checkHeader);
our $VERSION = '2.0.0';
## @method Lemonldap::NG::Portal::_Slave checkIP()
# @return true if remote IP is accredited in LL::NG conf
sub checkIP {
my $self = shift;
my $remoteIP = $self->remote_addr;
return 1
if (!$self->{slaveMasterIP}
|| $self->{slaveMasterIP} =~ /\b$remoteIP\b/ );
$self->_sub( 'userError', "Client IP not accredited for Slave module" );
return 0;
}
## @method Lemonldap::NG::Portal::_Slave checkHeader()
# @return true if header content matches LL::NG conf
sub checkHeader {
my $self = shift;
return 1
unless ( $self->{slaveHeaderName} and $self->{slaveHeaderContent} );
my $headerContent = $self->http( $self->{slaveHeaderName} );
return 1 if ( $self->{slaveHeaderContent} =~ /\b$headerContent\b/ );
$self->_sub( 'userError', "Matching header not found for Slave module" );
return 0;
}
1;

@ -72,7 +72,7 @@ ok(
'Auth request with bad url'
);
ok( $res->[0] == 200, 'HTTP code is 200' ) or explain( $res, 200 );
my %hdrs = @{ $res->[1] };
%hdrs = @{ $res->[1] };
ok( $hdrs{'Lm-Remote-User'} eq 'dwho', 'User is set' )
or explain( \%hdrs, 'Lm-Remote-User => "dwho"' );
ok( $hdrs{'Content-Type'} eq 'text/html', 'Reponse is HTML' )

@ -0,0 +1,35 @@
use Test::More;
use strict;
require 't/test-lib.pm';
my $res;
init(
{
logLevel => 'error',
useSafeJail => 1,
authentication => 'Slave',
userDB => 'Slave',
slaveUserHeader => 'My-Test',
slaveExportedVars => {
name => 'Name',
}
}
);
ok(
$res = &client->_get(
'/', custom => { HTTP_MY_TEST => 'dwho', HTTP_NAME => 'Dr Who' }
),
'Auth query'
);
ok( $res->[0] == 200, 'Response is 200' ) or explain( $res->[0], 200 );
my $cookies = getCookies($res);
my $id;
ok( $id = $cookies->{lemonldap}, 'Get cookie' )
or explain( $res, 'Set-Cookie: something' );
clean_sessions();
count(3);
done_testing( count() );

@ -4,9 +4,7 @@ use strict;
use Data::Dumper;
use 5.10.0;
BEGIN {
use_ok('Lemonldap::NG::Portal::Main');
}
use_ok('Lemonldap::NG::Portal::Main');
our $client;
our $count = 1;
@ -137,6 +135,7 @@ sub _get {
'SERVER_NAME' => 'auth.example.com',
'SERVER_PORT' => '8002',
'SERVER_PROTOCOL' => 'HTTP/1.1',
( $args{custom} ? %{ $args{custom} } : () ),
}
);
}

Loading…
Cancel
Save