2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
#===============================================================================
|
2007-02-11 16:14:33 +01:00
|
|
|
# Liberty Alliance Authentication for LemonLDAP.
|
2008-04-07 18:40:09 +02:00
|
|
|
#-------------------------------------------------------------------------------
|
2007-02-11 16:14:33 +01:00
|
|
|
#
|
|
|
|
# This file is part of the LemonLDAP project and released under GPL.
|
2008-04-07 18:40:09 +02:00
|
|
|
#
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
# CHANGELOGS
|
|
|
|
#-------------------------------------------------------------------------------
|
2009-02-09 17:06:41 +01:00
|
|
|
# 2009-02-09 - Version 0.3.1
|
|
|
|
# Author(s) : Thomas CHEMINEAU
|
|
|
|
# - Fixe a bug in libertySignOn function, to retrieve correct $providerID
|
2008-04-07 18:40:09 +02:00
|
|
|
# 2008-03-25 - Version 0.3
|
|
|
|
# Author(s) : Thomas CHEMINEAU
|
|
|
|
# - Fixe some bugs into logout process from IDP or SP ;
|
|
|
|
# - Add some checks into general algorithm ;
|
|
|
|
#
|
2007-10-15 07:29:29 +02:00
|
|
|
#===============================================================================
|
2007-02-11 16:14:33 +01:00
|
|
|
|
|
|
|
package Lemonldap::NG::Portal::AuthLA;
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
|
|
|
|
use Lemonldap::NG::Portal::SharedConf qw(:all);
|
|
|
|
use lasso;
|
2007-10-15 07:29:29 +02:00
|
|
|
use CGI::Cookie;
|
2008-04-07 18:40:09 +02:00
|
|
|
use CGI::Session;
|
2007-10-15 07:29:29 +02:00
|
|
|
use HTTP::Request;
|
|
|
|
use HTTP::Response;
|
|
|
|
use LWP::UserAgent;
|
|
|
|
use MIME::Base64;
|
|
|
|
use XML::Simple;
|
|
|
|
use UNIVERSAL qw( isa can VERSION );
|
2007-02-11 16:14:33 +01:00
|
|
|
|
|
|
|
*EXPORT_OK = *Lemonldap::NG::Portal::SharedConf::EXPORT_OK;
|
|
|
|
*EXPORT_TAGS = *Lemonldap::NG::Portal::SharedConf::EXPORT_TAGS;
|
|
|
|
*EXPORT = *Lemonldap::NG::Portal::SharedConf::EXPORT;
|
|
|
|
|
2009-06-08 18:29:13 +02:00
|
|
|
our $VERSION = '0.33';
|
2008-12-04 14:53:05 +01:00
|
|
|
use base qw(Lemonldap::NG::Portal::SharedConf);
|
2007-02-11 16:14:33 +01:00
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
#===============================================================================
|
|
|
|
# Global Constants
|
|
|
|
#===============================================================================
|
2007-02-11 16:14:33 +01:00
|
|
|
|
2008-05-30 08:07:37 +02:00
|
|
|
use constant {
|
2008-10-07 22:15:48 +02:00
|
|
|
PE_LA_FAILED => 11,
|
|
|
|
PE_LA_ARTFAILED => 12,
|
|
|
|
PE_LA_DEFEDFAILED => 13,
|
|
|
|
PE_LA_QUERYEMPTY => 14,
|
|
|
|
PE_LA_SOAPFAILED => 15,
|
|
|
|
PE_LA_SLOFAILED => 16,
|
|
|
|
PE_LA_SSOFAILED => 17,
|
|
|
|
PE_LA_SSOINITFAILED => 18,
|
|
|
|
PE_LA_SESSIONERROR => 19,
|
|
|
|
PE_LA_SEPFAILED => 20,
|
|
|
|
|
|
|
|
PC_LA_URLAC => '/liberty/assertionConsumer.pl',
|
|
|
|
PC_LA_URLFT => '/liberty/federationTermination.pl',
|
|
|
|
PC_LA_URLFTR => '/liberty/federationTerminationReturn.pl',
|
|
|
|
PC_LA_URLSL => '/liberty/singleLogout.pl',
|
|
|
|
PC_LA_URLSLR => '/liberty/singleLogoutReturn.pl',
|
|
|
|
PC_LA_URLSC => '/liberty/soapCall.pl',
|
|
|
|
PC_LA_URLSE => '/liberty/soapEndpoint.pl',
|
2008-05-30 08:07:37 +02:00
|
|
|
};
|
2007-03-14 16:39:29 +01:00
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
#===============================================================================
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# TODO
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# - category / function : comments
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# - association / store : Replace files by hastable or DBI implementation
|
|
|
|
# - security / process : Check if URL figures in locationRules
|
|
|
|
# - security / libertyFederationTermination : Implementation
|
|
|
|
# - wsf / setSessionInfo : Code for getting informations via wsf protocol
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
#===============================================================================
|
2007-03-14 16:39:29 +01:00
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
################################################################################
|
|
|
|
################################################################################
|
|
|
|
## ##
|
|
|
|
## Lemonldap::NG::Portal functions ##
|
|
|
|
## ##
|
|
|
|
################################################################################
|
|
|
|
################################################################################
|
2007-03-14 16:39:29 +01:00
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
#===============================================================================
|
|
|
|
# new
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Instanciate this class. This constructor takes special parameters with
|
|
|
|
# classical Lemonldap::NG::SharedConf parameters.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
2008-06-01 08:25:09 +02:00
|
|
|
sub new {
|
|
|
|
my $class = shift;
|
|
|
|
my $self = $class->SUPER::new(@_);
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->{isLibertyProcess} = 1;
|
|
|
|
$self->{laDebug} = 0 unless ( $self->{laDebug} );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
die('No Liberty Alliance Service Provider data defined')
|
2007-10-22 21:42:19 +02:00
|
|
|
unless ( $self->{laSp} );
|
2007-10-15 07:29:29 +02:00
|
|
|
die('No Liberty Alliance Identity Provider file defined')
|
2007-10-22 21:42:19 +02:00
|
|
|
unless ( $self->{laIdpsFile} );
|
2007-10-15 07:29:29 +02:00
|
|
|
die('No laStorage configuration defined')
|
2007-10-22 21:42:19 +02:00
|
|
|
unless ( $self->{laStorage} );
|
2007-10-15 07:29:29 +02:00
|
|
|
die('No laLdapLoginAttribute configuration defined')
|
2007-10-22 21:42:19 +02:00
|
|
|
unless ( $self->{laLdapLoginAttribute} );
|
2007-10-15 07:29:29 +02:00
|
|
|
die('No localStorage configuration defined')
|
2007-10-22 21:42:19 +02:00
|
|
|
unless ( $self->{localStorage} and $self->{localStorageOptions} );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-06-01 08:25:09 +02:00
|
|
|
bless( $self, $class );
|
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
# Create LassoServer
|
2007-03-14 19:11:15 +01:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->{laServer} = lasso::Server->new(
|
|
|
|
$self->{laSp}->{metadata},
|
|
|
|
$self->{laSp}->{privkey},
|
|
|
|
undef, #$self->{laSp}->{secretkey} ,
|
|
|
|
undef, #$self->{laSp}->{certificate} ,
|
2007-10-15 07:29:29 +02:00
|
|
|
);
|
2007-03-14 19:11:15 +01:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->_loadXmlIdpFile();
|
2008-06-01 08:25:09 +02:00
|
|
|
return $self;
|
2007-02-11 16:14:33 +01:00
|
|
|
}
|
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
#===============================================================================
|
|
|
|
# authenticate
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# User is authenticated automatically, no ldap authentication.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub authenticate {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
|
|
|
return $self->SUPER::authenticate()
|
|
|
|
unless ( $self->{isLibertyProcess} );
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_BADCREDENTIALS
|
2007-10-22 21:42:19 +02:00
|
|
|
unless ( defined $self->{user} );
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# extractFormInfo
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# This function is just override to do nothing.
|
2007-10-22 21:42:19 +02:00
|
|
|
# $self->{user} is already fixed in libertySetSessionInfo function.
|
2007-10-15 07:29:29 +02:00
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub extractFormInfo {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
|
|
|
return $self->SUPER::extractFormInfo()
|
|
|
|
unless ( $self->{isLibertyProcess} );
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# formateFilter
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# By default, the user is searched in the LDAP server with its UID. Here,
|
2007-10-22 21:42:19 +02:00
|
|
|
# $self->{user} contains nameIdentifier of the user, which is already stored
|
2007-10-15 07:29:29 +02:00
|
|
|
# in LDAP directory.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
2007-02-11 16:14:33 +01:00
|
|
|
sub formateFilter {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
|
|
|
return $self->SUPER::formateFilter()
|
|
|
|
unless ( $self->{isLibertyProcess} );
|
|
|
|
$self->{filter} =
|
|
|
|
"(&(uid=" . $self->{user} . ")(objectClass=inetOrgPerson))";
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# process
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Do portal Lemonldap::NG processing. Actions based on Lemonldap::NG structure
|
|
|
|
# and philosophy.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub process {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
|
|
|
$self->{error} = PE_OK;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
# Trace param()
|
2007-10-22 21:42:19 +02:00
|
|
|
# my @params = $self->param() ;
|
2007-10-15 07:29:29 +02:00
|
|
|
# foreach( @params ) {
|
2008-04-07 18:40:09 +02:00
|
|
|
# $self->_debug("parameter : $_ = " . $self->param($_)) ;
|
2007-10-15 07:29:29 +02:00
|
|
|
# }
|
|
|
|
# while(my($k,$v) = each(%ENV)) {
|
2008-05-09 22:50:27 +02:00
|
|
|
# $self->_debug("env : $k = $v") ;
|
2007-10-15 07:29:29 +02:00
|
|
|
# }
|
|
|
|
|
|
|
|
#--------
|
|
|
|
# Nothing to do if user access to portal directly. We have to verify if
|
|
|
|
# user was redirected from a protected host.
|
|
|
|
#--------
|
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
my $url = $self->url();
|
2007-10-15 07:29:29 +02:00
|
|
|
my $urlr = $url . substr( $ENV{'SCRIPT_NAME'}, 1 );
|
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
if ( not $self->param('url')
|
|
|
|
and ( $url eq $self->{portal} or $urlr eq $self->{portal} ) )
|
2007-10-15 07:29:29 +02:00
|
|
|
{
|
2008-10-07 22:15:48 +02:00
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
# TODO Security tricks :
|
|
|
|
# - Check if URL figures in locationRules
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->{error} = PE_DONE;
|
2008-05-11 21:21:39 +02:00
|
|
|
$self->updateStatus;
|
2007-10-22 21:42:19 +02:00
|
|
|
return $self->{error};
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#--------
|
|
|
|
# Authentication process
|
|
|
|
#--------
|
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
my $urldir = $self->url( -absolute => 1 );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
# assertionCustomer
|
2007-10-22 21:42:19 +02:00
|
|
|
if ( $urldir eq $self->PC_LA_URLAC ) {
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->{error} = $self->_subProcess(
|
2007-10-15 07:29:29 +02:00
|
|
|
qw( libertyAssertionConsumer libertySetSessionInfo ));
|
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->_debug( "Login user = '" . $self->{user} . "'" );
|
2007-02-11 16:14:33 +01:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
# federationTermination
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
2007-10-22 21:42:19 +02:00
|
|
|
elsif ( $urldir eq $self->PC_LA_URLFT ) {
|
2007-02-11 16:14:33 +01:00
|
|
|
|
2009-12-11 22:17:06 +01:00
|
|
|
$self->{error} =
|
|
|
|
$self->_subProcess(qw( libertyFederationTermination autoRedirect ));
|
2007-02-11 16:14:33 +01:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
# federationTerminationReturn
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
2007-10-22 21:42:19 +02:00
|
|
|
elsif ( $urldir eq $self->PC_LA_URLFTR ) {
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->{error} = $self->_subProcess(
|
2009-12-11 22:17:06 +01:00
|
|
|
qw( libertyFederationTerminationReturn autoRedirect ) );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
# singleLogout : called when IDP request Logout.
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
2007-10-22 21:42:19 +02:00
|
|
|
elsif ( $urldir eq $self->PC_LA_URLSL ) {
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->{error} = $self->_subProcess(
|
2007-10-15 07:29:29 +02:00
|
|
|
qw( libertyRetrieveExistingSession libertySingleLogout
|
|
|
|
libertyDeletingExistingSession )
|
|
|
|
);
|
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
# OK : $self->{urldc} is fixed at the end of this process.
|
2008-04-07 18:40:09 +02:00
|
|
|
$self->_debug( "Logout user = '" . $self->{user} . "'" );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
# singleLogoutReturn
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
2007-10-22 21:42:19 +02:00
|
|
|
elsif ( $urldir eq $self->PC_LA_URLSLR ) {
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2009-12-11 22:17:06 +01:00
|
|
|
$self->{error} = $self->_subProcess(qw( libertySingleLogoutReturn ));
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
# soapCall
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
2007-10-22 21:42:19 +02:00
|
|
|
elsif ( $urldir eq $self->PC_LA_URLSC ) {
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2009-02-15 18:58:38 +01:00
|
|
|
$self->{error} = $self->_subProcess(qw( libertySoapCall ));
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
# soapEndpoint
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
2007-10-22 21:42:19 +02:00
|
|
|
elsif ( $urldir eq $self->PC_LA_URLSE ) {
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2009-02-15 18:58:38 +01:00
|
|
|
$self->{error} = $self->_subProcess(qw( libertySoapEndpoint ));
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
# Direct access or simple access -> main
|
|
|
|
# WARNING : we permit authentication on service.
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
2008-10-07 22:15:48 +02:00
|
|
|
elsif ( not $self->param('user')
|
|
|
|
and not $self->param('password')
|
|
|
|
and not $self->param('logout') )
|
|
|
|
{
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->{error} = $self->_subProcess(
|
2009-02-15 18:58:38 +01:00
|
|
|
qw( libertyRetrieveExistingSession libertyExtractFormInfo
|
|
|
|
libertySignOn autoRedirect )
|
2007-10-15 07:29:29 +02:00
|
|
|
);
|
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
# Not in liberty authentication process.
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
else {
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->{isLibertyProcess} = 0;
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
|
2008-05-11 21:21:39 +02:00
|
|
|
if ( $self->{error} ) {
|
|
|
|
$self->updateStatus;
|
2008-10-07 22:15:48 +02:00
|
|
|
return 0;
|
2008-05-11 21:21:39 +02:00
|
|
|
}
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
# Liberty Process OK -> do Lemonldap::NG process.
|
2008-05-11 21:21:39 +02:00
|
|
|
# TODO Warning, PE_OK==0 and process returns 0 if an error occurs!
|
|
|
|
# my $err = $self->SUPER::process(@_);
|
|
|
|
#return $err unless( $err != PE_OK );
|
2009-02-15 18:58:38 +01:00
|
|
|
# TODO: Why ? autoRedirect is executed with SUPER::process
|
|
|
|
#$err = $self->_subProcess(qw( autoRedirect ))
|
2008-05-11 21:21:39 +02:00
|
|
|
# if ( $self->{urldc} );
|
|
|
|
#return $err;
|
|
|
|
# So I think we have just to write this
|
|
|
|
return $self->SUPER::process(@_);
|
2007-02-11 16:14:33 +01:00
|
|
|
}
|
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
#===============================================================================
|
|
|
|
# setSessionInfo
|
|
|
|
#===============================================================================
|
|
|
|
#
|
2008-05-24 15:18:54 +02:00
|
|
|
# After a valid auth assertion consumption, this function is called to init
|
|
|
|
# session info. If ID-WSF is enabled, get attributes from WebServices, else
|
|
|
|
# use the standard setSessionInfo (attributes read from LDAP).
|
2007-10-15 07:29:29 +02:00
|
|
|
#
|
2008-05-24 15:18:54 +02:00
|
|
|
# TODO: implement ID-WSF support
|
2007-10-15 07:29:29 +02:00
|
|
|
#
|
|
|
|
#===============================================================================
|
2007-03-14 16:39:29 +01:00
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
sub setSessionInfo {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-03-14 16:39:29 +01:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
# If ID-WSF enabled, use WebService
|
|
|
|
# TODO
|
2007-03-14 16:39:29 +01:00
|
|
|
|
2008-05-24 15:18:54 +02:00
|
|
|
# Else use SUPER::setSessionInfo
|
2007-10-22 21:42:19 +02:00
|
|
|
return $self->SUPER::setSessionInfo;
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
2007-03-14 16:39:29 +01:00
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
#===============================================================================
|
|
|
|
# store
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# This function store existing association between userNameIdentifier from IDP
|
|
|
|
# and Apache session ID of Lemonldap::NG.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
2007-03-14 16:39:29 +01:00
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
sub store {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-03-14 16:39:29 +01:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
my $err = $self->SUPER::store();
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
return $err
|
|
|
|
if ( $err != PE_OK or not $self->{isLibertyProcess} );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
return PE_LA_SESSIONERROR
|
2008-10-07 22:15:48 +02:00
|
|
|
unless defined $self->{userNameIdentifier};
|
2008-04-07 18:40:09 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
return $self->_assertionSessionStore( $self->{userNameIdentifier} );
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
################################################################################
|
|
|
|
################################################################################
|
|
|
|
## ##
|
|
|
|
## Some Data Access functions ##
|
|
|
|
## ##
|
|
|
|
################################################################################
|
|
|
|
################################################################################
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# getIdpURLs
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Returns all IDP URLs
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub getIdpIDs {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-10-15 07:29:29 +02:00
|
|
|
my @tab = ();
|
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
if ( $self->{laIdps} ) {
|
|
|
|
push @tab, $_ foreach ( keys %{ $self->{laIdps} } );
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return @tab;
|
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
################################################################################
|
|
|
|
################################################################################
|
|
|
|
## ##
|
|
|
|
## Liberty Alliance functions ##
|
|
|
|
## ##
|
|
|
|
################################################################################
|
|
|
|
################################################################################
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# libertyArtefactResolution
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# This function do Liberty artefact resolution. Verification is already made
|
|
|
|
# if this function is called, normaly it is authorized.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub libertyArtefactResolution {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
my $lassoLogin = undef;
|
|
|
|
my $lassoHttpMethod =
|
|
|
|
( defined( $ENV{'REQUEST_METHOD'} ) and $ENV{'REQUEST_METHOD'} eq 'GET' )
|
|
|
|
? $lasso::HTTP_METHOD_REDIRECT
|
|
|
|
: $lasso::HTTP_METHOD_POST;
|
|
|
|
|
|
|
|
# Retrieve or create lassoLogin.
|
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
if ( $self->{laLogin} and defined( $self->{laLogin} ) ) {
|
|
|
|
$lassoLogin = $self->{laLogin};
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
else {
|
2007-10-22 21:42:19 +02:00
|
|
|
$lassoLogin = lasso::Login->new( $self->{laServer} );
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
# POST
|
|
|
|
|
|
|
|
if ( $lassoHttpMethod == $lasso::HTTP_METHOD_POST
|
2007-10-22 21:42:19 +02:00
|
|
|
and $self->param('LARES') )
|
2007-10-15 07:29:29 +02:00
|
|
|
{
|
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
my $formLares = $self->param('LARES');
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
if ( my $error = $lassoLogin->processAuthnResponseMsg($formLares) ) {
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->_debug("lassoLogin->initRequest(...) : error = $error");
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_LA_ARTFAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( my $error = $lassoLogin->acceptSso() ) {
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->_debug("lassoLogin->acceptSso(...) : error = $error");
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_LA_SSOFAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
# GET : artefact is in QUERY_STRING param
|
|
|
|
|
|
|
|
}
|
|
|
|
elsif ( $lassoHttpMethod == $lasso::HTTP_METHOD_REDIRECT
|
|
|
|
and defined $ENV{'QUERY_STRING'} )
|
|
|
|
{
|
|
|
|
|
|
|
|
# NOTES :
|
|
|
|
# Documentation indicates that $formLareq is QUERY_STRING HTTP
|
|
|
|
# header. We should have
|
2007-10-22 21:42:19 +02:00
|
|
|
# $formLareq = $self->param('QUERY_STRING').
|
2007-10-15 07:29:29 +02:00
|
|
|
# But initRequest method on lassoLogin returns -502 error code
|
|
|
|
# (LASSO_PARAM_ERROR_INVALID_VALUE) when QUERY_STRING is like
|
|
|
|
# 'SAMLart=...&RelayState=...'. So, $formLareq is rebuild so
|
|
|
|
# that it only contains 'SAMLart=...'.
|
|
|
|
|
|
|
|
my $formLareq = $ENV{'QUERY_STRING'};
|
2007-10-22 21:42:19 +02:00
|
|
|
if ( $self->param('SAMLart') ) {
|
|
|
|
$formLareq = 'SAMLart=' . $self->param('SAMLart');
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
if ( my $error =
|
|
|
|
$lassoLogin->initRequest( $formLareq, $lassoHttpMethod ) )
|
|
|
|
{
|
|
|
|
$self->_debug(
|
|
|
|
"libertyArtefactResolution : lassoLogin->initRequest(...) : error = $error"
|
|
|
|
);
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_LA_ARTFAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( my $error = $lassoLogin->buildRequestMsg() ) {
|
2008-10-07 22:15:48 +02:00
|
|
|
$self->_debug(
|
|
|
|
"libertyArtefactResolution : lassoLogin->buildRequestMsg(...) : error = $error"
|
|
|
|
);
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_LA_ARTFAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Check if SSO is OK
|
|
|
|
# Successed = $soapResponseMsg contains code 200.
|
|
|
|
|
|
|
|
my $soapResponseMsg =
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->_soapRequest( $lassoLogin->{msgUrl}, $lassoLogin->{msgBody} );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
if ( my $error = $lassoLogin->processResponseMsg($soapResponseMsg) ) {
|
2008-10-07 22:15:48 +02:00
|
|
|
$self->_debug(
|
|
|
|
"libertyArtefactResolution : lassoLogin->processResponseMsg(...) : error = $error"
|
|
|
|
);
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_LA_SOAPFAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( my $error = $lassoLogin->acceptSso() ) {
|
2008-10-07 22:15:48 +02:00
|
|
|
$self->_debug(
|
|
|
|
"libertyArtefactResolution : lassoLogin->acceptSso(...) : error = $error"
|
|
|
|
);
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_LA_SSOFAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return PE_LA_SSOFAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Backup $lassoLogin object
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->{laLogin} = $lassoLogin;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
# Save RelayState.
|
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
if ( $self->param('RelayState') ) {
|
|
|
|
$self->{urldc} = $self->param('RelayState');
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return PE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# libertyAssertionConsumption
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Realize assertion.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub libertyAssertionConsumer {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->{laLogin} = lasso::Login->new( $self->{laServer} );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
return PE_LA_SSOFAILED
|
2007-10-22 21:42:19 +02:00
|
|
|
unless ( $self->{laLogin}
|
|
|
|
and defined( $self->{laLogin} )
|
|
|
|
and defined( $self->param('SAMLart') ) );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
return $self->libertyArtefactResolution(@_);
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# libertyDeletingExistingSession
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Delete existing Apache session file and Apache session ID <-> nameIdentifier
|
|
|
|
# association file.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub libertyDeletingExistingSession {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
# Deleting local cache session shared by all Lemonldap::NG::Handler.
|
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
if ( $self->{datas} ) {
|
2007-10-15 07:29:29 +02:00
|
|
|
my $refLocalStorage = undef;
|
2007-10-22 21:42:19 +02:00
|
|
|
my $localStorage = $self->{localStorage};
|
2007-10-15 07:29:29 +02:00
|
|
|
my $localStorageOptions = {};
|
|
|
|
$localStorageOptions->{namespace} ||= "lemonldap";
|
|
|
|
$localStorageOptions->{default_expires_in} ||= 600;
|
|
|
|
|
|
|
|
eval "use $localStorage;";
|
|
|
|
die("Unable to load $localStorage: $@") if ($@);
|
|
|
|
|
|
|
|
eval '$refLocalStorage = new '
|
|
|
|
. $localStorage
|
|
|
|
. '($localStorageOptions);';
|
|
|
|
if ( defined $refLocalStorage ) {
|
2007-10-22 21:42:19 +02:00
|
|
|
$refLocalStorage->remove( ${ $self->{datas} }{_session_id} );
|
2007-10-15 07:29:29 +02:00
|
|
|
$refLocalStorage->purge();
|
|
|
|
}
|
|
|
|
else {
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->_debug("Deleting apache session failed");
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Deleting association file, which is created when asserting consumer,
|
|
|
|
# in store function.
|
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
if ( $self->{sessionInfo}->{'laNameIdentifier'} ) {
|
2008-04-07 18:40:09 +02:00
|
|
|
return $self->_assertionSessionDelete(
|
2008-10-07 22:15:48 +02:00
|
|
|
$self->{sessionInfo}->{'laNameIdentifier'} );
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return PE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# libertyExtractFormInfo
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Verify that user has choose a IDP for authentication.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub libertyExtractFormInfo {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
# If only one IDP -> redirect automatically on this IDP
|
|
|
|
my $idp;
|
2007-10-22 21:42:19 +02:00
|
|
|
my @idps = keys %{ $self->{laIdps} };
|
|
|
|
if ( $#idps >= 0 && $self->param('idpChoice') ) {
|
|
|
|
$idp = $self->param('idpChoice');
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
return PE_FIRSTACCESS
|
|
|
|
unless $idp;
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->{idp}->{id} = $idp;
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# libertyFederationTermination
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Terminate federation.
|
|
|
|
#
|
2008-05-24 15:18:54 +02:00
|
|
|
# TODO
|
2007-10-15 07:29:29 +02:00
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub libertyFederationTermination {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
# $self->_debug("Processing federation termination...");
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
my $query = $ENV{'QUERY_STRING'};
|
|
|
|
return PE_LA_QUERYEMPTY
|
|
|
|
unless $query;
|
|
|
|
|
|
|
|
if ( lasso::isLibertyQuery($query) ) {
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->{lassoDefederation} =
|
|
|
|
lasso::Defederation->new( $self->{laServer} );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
return PE_LA_DEFEDFAILED
|
2007-10-22 21:42:19 +02:00
|
|
|
unless ( $self->{lassoDefederation}
|
|
|
|
and defined( $self->{lassoDefederation} )
|
|
|
|
and $self->{lassoDefederation}->processNotificationMsg($query) );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
# $self->_debug("lassoDefederation->processNotificationMsg... OK");
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
# TODO :
|
2007-10-22 21:42:19 +02:00
|
|
|
# $self->fedTerm();
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
return PE_OK;
|
|
|
|
}
|
|
|
|
return PE_DONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# libertyFederationTerminationReturn
|
|
|
|
#===============================================================================
|
|
|
|
#
|
2008-10-07 22:15:48 +02:00
|
|
|
# TODO
|
2007-10-15 07:29:29 +02:00
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub libertyFederationTerminationReturn {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = @_;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
# $self->_debug("The Return of the federation termination...");
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->{urldc} = $self->{portal};
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_OK;
|
2007-02-11 16:14:33 +01:00
|
|
|
}
|
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
#===============================================================================
|
|
|
|
# libertyRetrieveExistingSession
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Try to restore session whithin userNameIdentifier.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub libertyRetrieveExistingSession {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
# To retrieve current Liberty session, there is one way :
|
|
|
|
# - We have a query string that contains the userNameIdentifier.
|
2007-10-15 07:29:29 +02:00
|
|
|
# Then, we could retrieve apache session from cache files.
|
|
|
|
|
|
|
|
return PE_LA_SESSIONERROR
|
2007-10-22 21:42:19 +02:00
|
|
|
unless ( defined $self->{laStorageOptions}->{Directory} );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
return PE_OK
|
2008-10-07 22:15:48 +02:00
|
|
|
unless ( defined $self->param('NameIdentifier') );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
# Retrieve the Apache session ID.
|
|
|
|
# It should not return any errors when trying to retrieve assertions.
|
2007-03-14 16:39:29 +01:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
my $err =
|
|
|
|
$self->_assertionSessionRetrieve( $self->param('NameIdentifier') );
|
2007-03-14 16:39:29 +01:00
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
# return PE_LA_SESSIONERROR
|
|
|
|
# unless $err == 0 ;
|
2007-03-14 16:39:29 +01:00
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
# We can not rebuild factice cookie for Lemonldap::NG retrieving itself the
|
|
|
|
# session. So, we retrieve here directly the session. This is the
|
|
|
|
# Lemonldap::NG::Simple code of controlExistingSession function.
|
2007-02-11 16:14:33 +01:00
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
my %h;
|
|
|
|
eval {
|
|
|
|
tie %h,
|
2008-10-07 22:15:48 +02:00
|
|
|
$self->{globalStorage}, $self->{id}, $self->{globalStorageOptions};
|
2008-04-07 18:40:09 +02:00
|
|
|
};
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
if ( $@ or not tied(%h) ) {
|
2008-10-07 22:15:48 +02:00
|
|
|
print STDERR "Session "
|
|
|
|
. $self->{id}
|
|
|
|
. " isn't yet available ($ENV{REMOTE_ADDR})\n";
|
|
|
|
return PE_OK;
|
2008-04-07 18:40:09 +02:00
|
|
|
}
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
%{ $self->{datas} } = %h;
|
2008-04-07 18:40:09 +02:00
|
|
|
untie(%h);
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
my $r;
|
2008-04-07 18:40:09 +02:00
|
|
|
if ( $self->{existingSession} ) {
|
2008-10-07 22:15:48 +02:00
|
|
|
$r =
|
|
|
|
&{ $self->{existingSession} }( $self, $self->{id}, $self->{datas} );
|
2008-04-07 18:40:09 +02:00
|
|
|
}
|
|
|
|
else {
|
2008-10-07 22:15:48 +02:00
|
|
|
$r = $self->existingSession( $self->{id}, $self->{datas} );
|
2008-04-07 18:40:09 +02:00
|
|
|
}
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
if ( $r == PE_OK ) {
|
|
|
|
print STDERR "No existing liberty session found\n";
|
|
|
|
return PE_OK;
|
2008-04-07 18:40:09 +02:00
|
|
|
}
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
while ( my ( $k, $v ) = each( %{ $self->{datas} } ) ) {
|
|
|
|
$self->{sessionInfo}->{$k} = $v;
|
2008-04-07 18:40:09 +02:00
|
|
|
}
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
if ( defined $self->{sessionInfo}->{ $self->{laLdapLoginAttribute} } ) {
|
|
|
|
$self->{user} = $self->{sessionInfo}->{ $self->{laLdapLoginAttribute} };
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return PE_OK;
|
2007-03-14 19:11:15 +01:00
|
|
|
}
|
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
#===============================================================================
|
|
|
|
# libertySetSessionInfo
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# This function store in session cache information retrieve from IDP. If
|
|
|
|
# ID-WSF option is specified, it also store ID-WSF-attributes.
|
|
|
|
# In all cases, it fixes username of user who is authenticated on IDP.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub libertySetSessionInfo {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
return PE_LA_FAILED
|
2007-10-22 21:42:19 +02:00
|
|
|
unless ( defined $self->{laLogin} );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
my $lassoLogin = $self->{laLogin};
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
# Store identity in LDAP Directory, if identity not exists. Good
|
|
|
|
# opportunity to ask user some more informations.
|
|
|
|
|
|
|
|
return PE_LA_FAILED
|
|
|
|
unless (
|
|
|
|
defined $lassoLogin->{session}
|
2008-10-07 22:15:48 +02:00
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
# and defined $lassoLogin->{identity}
|
|
|
|
and $lassoLogin->{nameIdentifier}->{content}
|
|
|
|
);
|
|
|
|
|
|
|
|
# Here, we store liberty identity and session in Apache session.
|
|
|
|
# We just store informations in cache, then those are saved by
|
|
|
|
# store function. Saved nameIdentifier too.
|
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
# $self->{sessionInfo}->{laIdentityDump} = $lassoLogin->{identity}->dump() ;
|
|
|
|
$self->{sessionInfo}->{laSessionDump} = $lassoLogin->{session}->dump();
|
|
|
|
$self->{sessionInfo}->{laNameIdentifier} =
|
2007-10-15 07:29:29 +02:00
|
|
|
$lassoLogin->{nameIdentifier}->{content};
|
|
|
|
|
|
|
|
# Get username from assertion and restore it in param('user'). Be
|
|
|
|
# carefull, IDP does not return username but an id for user assertion.
|
|
|
|
# The Lemonldap::NG search consists to perform a search with a filter
|
|
|
|
# using nameIdentifier, instead of username.
|
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
$self->{userNameIdentifier} = $lassoLogin->{nameIdentifier}->{content};
|
|
|
|
$self->{password} = 'none';
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
# Try to retrieve uid in SAML response form assertion statement.
|
|
|
|
# For the moment, uid have to be unique in LDAP directory.
|
2008-04-07 18:40:09 +02:00
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
my @uidValues =
|
2008-10-07 22:15:48 +02:00
|
|
|
$self->_getAttributeValuesOfSamlAssertion( $lassoLogin->{response},
|
|
|
|
$self->{laLdapLoginAttribute} );
|
2008-04-07 18:40:09 +02:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->{user} = $uidValues[0]
|
2007-10-15 07:29:29 +02:00
|
|
|
if (@uidValues);
|
|
|
|
|
|
|
|
return PE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# libertySignOn
|
|
|
|
#===============================================================================
|
|
|
|
#
|
2007-10-22 21:42:19 +02:00
|
|
|
# Init SSO request. If successfull, $self->{urldc} contains Liberty IDP Url
|
2007-10-15 07:29:29 +02:00
|
|
|
# for redirection.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub libertySignOn {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
my $lassoLogin = lasso::Login->new( $self->{laServer} );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
return PE_LA_FAILED
|
|
|
|
unless ( $lassoLogin and defined($lassoLogin) );
|
|
|
|
|
|
|
|
# TODO :
|
|
|
|
# Catching error when retrieving $providerID.
|
2007-03-14 19:11:15 +01:00
|
|
|
|
2009-02-09 17:06:41 +01:00
|
|
|
my $providerID = $self->{laIdps}->{ $self->{idp}->{id} }->{url};
|
2007-03-14 19:11:15 +01:00
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
if (
|
|
|
|
my $error = $lassoLogin->initAuthnRequest(
|
|
|
|
$providerID, $lasso::HTTP_METHOD_REDIRECT
|
|
|
|
)
|
|
|
|
)
|
|
|
|
{
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->_debug("lassoLogin->initAuthnRequest(...) : error = $error");
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_LA_SSOINITFAILED;
|
|
|
|
}
|
2007-03-14 19:11:15 +01:00
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
# We do one time federation, IDP doe not have to store nameIdentifier.
|
|
|
|
|
|
|
|
$lassoLogin->{request}->{consent} = $lasso::LIB_CONSENT_OBTAINED;
|
|
|
|
$lassoLogin->{request}->{nameIdPolicy} =
|
|
|
|
$lasso::LIB_NAMEID_POLICY_TYPE_ONE_TIME;
|
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
#$lassoLogin->{request}->{nameIdPolicy} = $lasso::LIB_NAMEID_POLICY_TYPE_FEDERATED ;
|
2007-10-15 07:29:29 +02:00
|
|
|
$lassoLogin->{request}->{isPassive} = 0;
|
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
if ( $self->param('url') ) {
|
|
|
|
my $url = decode_base64( $self->param('url') );
|
2007-10-15 07:29:29 +02:00
|
|
|
chomp $url;
|
|
|
|
$lassoLogin->{request}->{relayState} = $url;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( my $error = $lassoLogin->buildAuthnRequestMsg() ) {
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->_debug("lassoLogin->buildAuthnRequestMsg(..) : error = $error");
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_LA_SSOINITFAILED;
|
|
|
|
}
|
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->{urldc} = $lassoLogin->{msgUrl};
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_OK;
|
2007-03-14 19:11:15 +01:00
|
|
|
}
|
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
#===============================================================================
|
|
|
|
# libertySingleLogout
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Two cases :
|
2008-05-09 22:50:27 +02:00
|
|
|
# * Portal or applications requiere singleLogout -> SP request ;
|
|
|
|
# * IDP requiere singleLogout -> IDP request with $ENV{'QUERY_STRING'}
|
|
|
|
# specified.
|
2007-10-15 07:29:29 +02:00
|
|
|
#
|
2008-04-07 18:40:09 +02:00
|
|
|
# This function one optional parameter that specifies if the portal is called
|
|
|
|
# through a SOAP call.
|
|
|
|
#
|
2007-10-15 07:29:29 +02:00
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub libertySingleLogout {
|
2008-10-07 22:15:48 +02:00
|
|
|
my $self = shift;
|
|
|
|
my $soap = shift;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
my $lassoLogout = lasso::Logout->new( $self->{laServer} );
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_LA_FAILED
|
|
|
|
unless ( $lassoLogout
|
|
|
|
and defined($lassoLogout)
|
|
|
|
and defined $ENV{'QUERY_STRING'} );
|
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
if ( lasso::isLibertyQuery( $ENV{'QUERY_STRING'} ) ) {
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
# We retrieve query string and verify it.
|
|
|
|
# If it is OK, we set lemonldap::ng logout parameter, so we can perform
|
|
|
|
# it in Lemonldap::NG normal process. Then, we remove our stored liberty
|
|
|
|
# association file.
|
2007-03-14 19:11:15 +01:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->param( 'logout' => '1' );
|
2007-03-14 19:11:15 +01:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
if ( my $error =
|
|
|
|
$lassoLogout->processRequestMsg( $ENV{'QUERY_STRING'} ) )
|
|
|
|
{
|
|
|
|
$self->_debug(
|
|
|
|
"lassoLogout->processRequestMsg(...) : error = $error");
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_LA_SLOFAILED;
|
|
|
|
}
|
2007-03-14 19:11:15 +01:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
# my $lassoIdentity = lasso::Identity::newFromDump($self->{sessionInfo}->{laIdentityDump}) ;
|
|
|
|
# $lassoLogout->{identity} = $lassoIdentity ;
|
2007-10-15 07:29:29 +02:00
|
|
|
my $lassoSession =
|
2007-10-22 21:42:19 +02:00
|
|
|
lasso::Session::newFromDump( $self->{sessionInfo}->{laSessionDump} );
|
2007-10-15 07:29:29 +02:00
|
|
|
$lassoLogout->{session} = $lassoSession;
|
|
|
|
|
|
|
|
# Logout by soap call could failed with those two errors.
|
|
|
|
if ( my $error = $lassoLogout->validateRequest() ) {
|
|
|
|
if ( $error != $lasso::PROFILE_ERROR_SESSION_NOT_FOUND
|
|
|
|
and $error != $lasso::PROFILE_ERROR_IDENTITY_NOT_FOUND )
|
|
|
|
{
|
2008-10-07 22:15:48 +02:00
|
|
|
$self->_debug(
|
|
|
|
"lassoLogout->validateRequest(...) : error = $error");
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_LA_SLOFAILED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( my $error = $lassoLogout->buildResponseMsg() ) {
|
2008-10-07 22:15:48 +02:00
|
|
|
$self->_debug(
|
|
|
|
"lassoLogout->buildResponseMsg(...) : error = $error");
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_LA_SLOFAILED;
|
|
|
|
}
|
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
# Confirm logout by soap request, only if portal is not already called
|
|
|
|
# itself by a SOAP request.
|
|
|
|
if ( defined $lassoLogout->{msgBody} && !$soap ) {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $soapResponseMsg = $self->_soapRequest( $lassoLogout->{msgUrl},
|
2008-10-07 22:15:48 +02:00
|
|
|
$lassoLogout->{msgBody} );
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Fixes redirection.
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->{urldc} = $lassoLogout->{msgUrl};
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
# If $self->{urldc} empty, then we try to use HTTP referer if it exists
|
|
|
|
$self->{urldc} = $ENV{'HTTP_REFERER'}
|
|
|
|
if ( not $self->{urldc} and $ENV{'HTTP_REFERER'} );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
return PE_OK;
|
2007-03-14 19:11:15 +01:00
|
|
|
}
|
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
#===============================================================================
|
|
|
|
# libertySingleLogoutReturn
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# SP provides singleLogout, it calls IDP which has done Liberty logout. Then IDP
|
|
|
|
# requests http://portal/liberty/singleLogoutReturn.
|
|
|
|
# Here, as there is no more liberty session on IDP, we suppress liberty session
|
|
|
|
# on Lemon.
|
|
|
|
#
|
2008-05-24 15:18:54 +02:00
|
|
|
# TODO: Modify redirect to call handler logout configured in location directive
|
|
|
|
# (dedicated portal or handler, nor more relaystate need)
|
2007-10-15 07:29:29 +02:00
|
|
|
#
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub libertySingleLogoutReturn {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
# Original code from Unwind :
|
|
|
|
#
|
|
|
|
# 8<--------
|
|
|
|
# logout = lasso.Logout(misc.get_lasso_server())
|
|
|
|
# try:
|
|
|
|
# logout.processResponseMsg(get_request().get_query())
|
|
|
|
# except lasso.Error, error:
|
|
|
|
# if error[0] == lasso.PROFILE_ERROR_INVALID_QUERY:
|
|
|
|
# raise AccessError()
|
|
|
|
# if error[0] == lasso.DS_ERROR_INVALID_SIGNATURE:
|
|
|
|
# return error_page(_('Failed to check single logout request signature.'))
|
|
|
|
# if hasattr(lasso, 'LOGOUT_ERROR_REQUEST_DENIED') and \
|
|
|
|
# error[0] == lasso.LOGOUT_ERROR_REQUEST_DENIED:
|
|
|
|
# # ignore silently
|
|
|
|
# return redirect(get_request().environ['SCRIPT_NAME'] + '/')
|
|
|
|
# elif error[0] == lasso.ERROR_UNDEFINED:
|
|
|
|
# # XXX: unknown status; ignoring for now.
|
|
|
|
# return redirect(get_request().environ['SCRIPT_NAME'] + '/')
|
|
|
|
# raise
|
|
|
|
# return redirect(get_request().environ['SCRIPT_NAME'] + '/')
|
|
|
|
# 8<--------
|
|
|
|
#
|
|
|
|
# Normaly, if we are here, assertion and session should have been removed
|
|
|
|
# in a previous request.
|
|
|
|
|
|
|
|
$self->{lassoLogout} = lasso::Logout->new( $self->{laServer} );
|
2008-04-07 18:40:09 +02:00
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_LA_SLOFAILED
|
2008-10-07 22:15:48 +02:00
|
|
|
unless $self->{lassoLogout} and defined( $self->{lassoLogout} );
|
2008-04-07 18:40:09 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
if ( my $error =
|
|
|
|
$self->{lassoLogout}->processResponseMsg( $ENV{'QUERY_STRING'} ) )
|
2008-04-07 18:40:09 +02:00
|
|
|
{
|
2008-10-07 22:15:48 +02:00
|
|
|
$self->_debug("Process response message error = $error");
|
|
|
|
return PE_LA_SLOFAILED;
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
2008-04-07 18:40:09 +02:00
|
|
|
|
|
|
|
# Test if Lemonldap::NG cookie is available. If it is the case, the
|
|
|
|
# corresponding session should be previously deleted.
|
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
return PE_OK;
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# libertySoapCall
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# IDP request defederation by SOAP calls.
|
|
|
|
#
|
2008-05-24 15:18:54 +02:00
|
|
|
# TODO
|
2007-10-15 07:29:29 +02:00
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub libertySoapCall {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
$self->_debug("Soap call processing...");
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
my $contentType = $ENV{'CONTENT_TYPE'};
|
|
|
|
my $soapMsg = $ENV{'QUERY_STRING'};
|
|
|
|
|
|
|
|
return PE_LA_SOAPFAILED
|
|
|
|
unless ( $contentType and $soapMsg and $contentType eq 'text/xml' );
|
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
#$self->_debug("contentType: $contentType");
|
|
|
|
#$self->_debug("soapMsg: $soapMsg");
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
my $requestType = lasso::getRequestTypeFromSoapMsg($soapMsg);
|
|
|
|
|
|
|
|
# Logout request
|
2007-10-22 21:42:19 +02:00
|
|
|
return $self->libertySingleLogout
|
2007-10-15 07:29:29 +02:00
|
|
|
if ( $requestType eq $lasso::REQUEST_TYPE_LOGOUT );
|
|
|
|
|
|
|
|
# Defederation request
|
2007-10-22 21:42:19 +02:00
|
|
|
return $self->libertyFederationTermination
|
2007-10-15 07:29:29 +02:00
|
|
|
if ( $requestType eq $lasso::REQUEST_TYPE_DEFEDERATION );
|
|
|
|
|
|
|
|
return PE_DONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# libertySoapEndpoint
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Requests arrive in SOAP. We MUST traited them.
|
|
|
|
# Work as process function : call other functions.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub libertySoapEndpoint {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
# $self->_debug("SoapEndpoint processing...");
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
my $soapRequest = $self->param('POSTDATA');
|
2007-10-15 07:29:29 +02:00
|
|
|
return PE_LA_SEPFAILED
|
|
|
|
unless $soapRequest;
|
|
|
|
|
|
|
|
my $soapRequestType = lasso::getRequestTypeFromSoapMsg($soapRequest);
|
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
# $self->_debug("RequestType = $soapRequestType");
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
# Logout SOAP request
|
|
|
|
if ( $soapRequestType == $lasso::REQUEST_TYPE_LOGOUT ) {
|
|
|
|
$ENV{'QUERY_STRING'} = $soapRequest;
|
2008-10-07 22:15:48 +02:00
|
|
|
return $self->libertySingleLogout(1);
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
# Defederation SOAP request
|
|
|
|
}
|
|
|
|
elsif ( $soapRequestType == $lasso::REQUEST_TYPE_DEFEDERATION ) {
|
|
|
|
|
|
|
|
# TODO
|
|
|
|
# Lemonldap do defederation ?
|
|
|
|
}
|
|
|
|
|
|
|
|
return PE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
################################################################################
|
|
|
|
################################################################################
|
|
|
|
## ##
|
|
|
|
## Private functions ##
|
|
|
|
## ##
|
|
|
|
################################################################################
|
|
|
|
################################################################################
|
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
#===============================================================================
|
|
|
|
# _assertionSessionDelete
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Delete liberty assertion session.
|
|
|
|
# This function takes one parameter : the assertion identifier.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub _assertionSessionDelete {
|
2008-10-07 22:15:48 +02:00
|
|
|
my $self = shift;
|
|
|
|
my $assertionId = shift;
|
2008-04-07 18:40:09 +02:00
|
|
|
|
|
|
|
return PE_LA_SESSIONERROR
|
2008-10-07 22:15:48 +02:00
|
|
|
unless ( defined $self->{laStorage}
|
|
|
|
and defined $self->{laStorageOptions} );
|
2008-04-07 18:40:09 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
my $session =
|
|
|
|
new CGI::Session( "driver:" . $self->{laStorage} . ";id:STATIC",
|
|
|
|
$assertionId, $self->{laStorageOptions} );
|
2008-04-07 18:40:09 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
if ( defined $session ) {
|
|
|
|
$session->delete();
|
|
|
|
$session->flush();
|
2008-04-07 18:40:09 +02:00
|
|
|
}
|
2008-10-07 22:15:48 +02:00
|
|
|
else {
|
|
|
|
$self->_debug("Unable to delete assertion file\n");
|
|
|
|
return PE_LA_SESSIONERROR;
|
2008-04-07 18:40:09 +02:00
|
|
|
}
|
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
return PE_OK;
|
2008-04-07 18:40:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# _assertionSessionRetrieve
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Get the Apache Session Identifier from the liberty assertion session. The
|
|
|
|
# result will be stored into the $self->{id} parameter, when PE_OK returned.
|
|
|
|
# This function takes one parameter : the assertion identifier.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub _assertionSessionRetrieve {
|
2008-10-07 22:15:48 +02:00
|
|
|
my $self = shift;
|
|
|
|
my $assertionId = shift;
|
2008-04-07 18:40:09 +02:00
|
|
|
|
|
|
|
return PE_LA_SESSIONERROR
|
2008-10-07 22:15:48 +02:00
|
|
|
unless ( defined $self->{laStorage}
|
|
|
|
and defined $self->{laStorageOptions} );
|
2008-04-07 18:40:09 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
my $session =
|
|
|
|
new CGI::Session( "driver:" . $self->{laStorage} . ";id:STATIC",
|
|
|
|
$assertionId, $self->{laStorageOptions} );
|
2008-04-07 18:40:09 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
if ( defined $session and defined $session->param('id') ) {
|
|
|
|
$self->{id} = $session->param('id');
|
2008-04-07 18:40:09 +02:00
|
|
|
}
|
2008-10-07 22:15:48 +02:00
|
|
|
else {
|
|
|
|
$self->_debug("Unable to retrieve assertion file\n");
|
|
|
|
return PE_LA_SESSIONERROR;
|
2008-04-07 18:40:09 +02:00
|
|
|
}
|
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
return PE_OK;
|
2008-04-07 18:40:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# _assertionSessionStore
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Store liberty assertion session.
|
|
|
|
# This function takes one parameter : the assertion identifier.
|
|
|
|
#
|
|
|
|
# We have to store association between Apache Session Identifier and Liberty
|
|
|
|
# Session Identifier. There is several solutions. A simple way will be to create
|
|
|
|
# a file named by userNameIdentifier from IDP, which contains session ID from
|
|
|
|
# Apache. The advanced one, which is used, is to manage simple CGI::Session to
|
|
|
|
# store the association.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub _assertionSessionStore {
|
2008-10-07 22:15:48 +02:00
|
|
|
my $self = shift;
|
|
|
|
my $assertionId = shift;
|
2008-04-07 18:40:09 +02:00
|
|
|
|
|
|
|
return PE_LA_SESSIONERROR
|
2008-10-07 22:15:48 +02:00
|
|
|
unless ( defined $self->{laStorage}
|
|
|
|
and defined $self->{laStorageOptions} );
|
2008-04-07 18:40:09 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
my $session =
|
|
|
|
new CGI::Session( "driver:" . $self->{laStorage} . ";id:STATIC",
|
|
|
|
$assertionId, $self->{laStorageOptions} );
|
2008-04-07 18:40:09 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
if ( defined $session and defined $self->{id} ) {
|
|
|
|
$session->param( 'id', $self->{id} );
|
|
|
|
$session->flush();
|
2008-04-07 18:40:09 +02:00
|
|
|
}
|
2008-10-07 22:15:48 +02:00
|
|
|
else {
|
|
|
|
$self->_debug("Unable to store assertion file\n");
|
|
|
|
return PE_LA_SESSIONERROR;
|
2008-04-07 18:40:09 +02:00
|
|
|
}
|
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
return PE_OK;
|
2008-04-07 18:40:09 +02:00
|
|
|
}
|
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
#===============================================================================
|
|
|
|
# _getAttributeValuesOfSamlAssertion
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Retrieve attribute value from a SAMLP response specified in first parameter.
|
|
|
|
# Return a table of values corresponding to the attribute name specified in
|
|
|
|
# second parameter.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub _getAttributeValuesOfSamlAssertion {
|
2008-10-07 22:15:48 +02:00
|
|
|
my $self = shift;
|
|
|
|
my $samlp = shift;
|
|
|
|
my $attributeName = shift;
|
|
|
|
my @tab = ();
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
# This function is in version alpha. The structure of the SAML assertion
|
|
|
|
# depends of the source application. So, we decide to catch possible
|
|
|
|
# exception due to parsing errors. So, if an error occurs, we just return
|
|
|
|
# an empty table. BUT, the error has been logged.
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
eval {
|
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
# Search the specific attribute.
|
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
my $attribute = undef;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
for (
|
2008-04-07 18:40:09 +02:00
|
|
|
my $i = 0 ;
|
2007-10-15 07:29:29 +02:00
|
|
|
not defined $attribute
|
2008-04-07 18:40:09 +02:00
|
|
|
and $i < lasso::NodeList::length( $samlp->{assertion} ) ;
|
|
|
|
$i++
|
2007-10-15 07:29:29 +02:00
|
|
|
)
|
|
|
|
{
|
2008-04-07 18:40:09 +02:00
|
|
|
my $assertion = lasso::NodeList::getItem( $samlp->{assertion}, $i );
|
|
|
|
my $attributeStatement = $assertion->{attributeStatement};
|
|
|
|
|
|
|
|
for (
|
|
|
|
my $j = 0 ;
|
|
|
|
not defined $attribute
|
|
|
|
and $j <
|
|
|
|
lasso::NodeList::length( $attributeStatement->{attribute} ) ;
|
|
|
|
$j++
|
|
|
|
)
|
|
|
|
{
|
|
|
|
my $attr =
|
2008-10-07 22:15:48 +02:00
|
|
|
lasso::NodeList::getItem( $attributeStatement->{attribute},
|
|
|
|
$j );
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
if ( $attr->{attributeName} eq $attributeName ) {
|
|
|
|
$attribute = $attr;
|
|
|
|
}
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-07 18:40:09 +02:00
|
|
|
# Then get values for this attribute.
|
|
|
|
# Values are only lasso::MiscTextNode type.
|
2007-10-15 07:29:29 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
if ( defined $attribute ) {
|
2008-04-07 18:40:09 +02:00
|
|
|
for (
|
|
|
|
my $k = 0 ;
|
|
|
|
$k < lasso::NodeList::length( $attribute->{attributeValue} ) ;
|
|
|
|
$k++
|
|
|
|
)
|
|
|
|
{
|
|
|
|
my $attributeValue =
|
|
|
|
lasso::NodeList::getItem( $attribute->{attributeValue}, $k );
|
|
|
|
my $valueList = $attributeValue->{any};
|
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
for (
|
|
|
|
my $l = 0 ;
|
|
|
|
$l < lasso::NodeList::length($valueList) ;
|
|
|
|
$l++
|
|
|
|
)
|
2008-04-07 18:40:09 +02:00
|
|
|
{
|
|
|
|
my $value = lasso::NodeList::getItem( $valueList, $l );
|
|
|
|
push @tab, $value->{content}
|
|
|
|
if ( isa( $value, "lasso::MiscTextNode" ) );
|
|
|
|
}
|
|
|
|
}
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
2008-04-07 18:40:09 +02:00
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
}; # end eval
|
2008-04-07 18:40:09 +02:00
|
|
|
|
|
|
|
if ($@) {
|
2008-10-07 22:15:48 +02:00
|
|
|
$self->_debug(
|
|
|
|
"SAML parsing errors : could not retrieve values for $attributeName attribute"
|
|
|
|
);
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
|
2008-10-07 22:15:48 +02:00
|
|
|
return @tab;
|
2007-10-15 07:29:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# _loadXMLIdpFile
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Load Identity Providers file.
|
|
|
|
# File is a XML file which contains providers definition.
|
|
|
|
# Only one service provider for multiple identity provider.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub _loadXmlIdpFile {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-10-15 07:29:29 +02:00
|
|
|
my $file = shift;
|
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
my $xml = XML::Simple::XMLin( $self->{laIdpsFile}, ForceArray => ['idp'] );
|
|
|
|
$self->{laIdps} = $xml->{idp};
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
# Adding all IDPs in laIdpsFile in laServer.
|
|
|
|
# Have to be done one time -> no choice : in constructor.
|
|
|
|
|
2007-10-22 21:42:19 +02:00
|
|
|
foreach ( keys %{ $self->{laIdps} } ) {
|
|
|
|
my $hash = $self->{laIdps}->{$_};
|
|
|
|
$self->{laServer}->addProvider(
|
2007-10-15 07:29:29 +02:00
|
|
|
$lasso::PROVIDER_ROLE_IDP, $hash->{'metadata'},
|
|
|
|
$hash->{'pubkey'}, $hash->{'certificate'},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# _soapRequest
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Do soap request with only two parameters :
|
|
|
|
# - URI string ;
|
|
|
|
# - Body string ;
|
|
|
|
# Thus function return body's response message.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub _soapRequest {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-10-15 07:29:29 +02:00
|
|
|
my ( $uri, $body ) = @_;
|
|
|
|
|
|
|
|
my $soapHeaders = new HTTP::Headers( Content_Type => "text/xml" );
|
|
|
|
my $soapRequest = new HTTP::Request( "POST", $uri, $soapHeaders, $body );
|
|
|
|
my $soapAgent = LWP::UserAgent->new( agent => 'Mozilla/5.0 [en]' );
|
|
|
|
my $soapResponse = $soapAgent->request($soapRequest);
|
|
|
|
|
|
|
|
return $soapResponse->content();
|
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
# _debug
|
|
|
|
#===============================================================================
|
|
|
|
#
|
|
|
|
# Private tracing function.
|
|
|
|
#
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
sub _debug {
|
2007-10-22 21:42:19 +02:00
|
|
|
my $self = shift;
|
2007-10-15 07:29:29 +02:00
|
|
|
my $str = shift;
|
|
|
|
my (
|
|
|
|
$package, $filename, $line, $subroutine, $hasargs,
|
|
|
|
$wantarray, $evaltext, $is_require, $hints, $bitmask
|
|
|
|
) = caller(1);
|
|
|
|
print STDERR $subroutine . " : " . $str . "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
#===============================================================================
|
|
|
|
#===============================================================================
|
|
|
|
|
|
|
|
################################################################################
|
|
|
|
################################################################################
|
|
|
|
## ##
|
2007-10-25 08:06:17 +02:00
|
|
|
## Documentation ##
|
2007-10-15 07:29:29 +02:00
|
|
|
## ##
|
|
|
|
################################################################################
|
|
|
|
################################################################################
|
2007-03-14 19:11:15 +01:00
|
|
|
|
2007-02-11 16:14:33 +01:00
|
|
|
1;
|
|
|
|
__END__
|
|
|
|
|
|
|
|
=head1 NAME
|
|
|
|
|
2010-01-03 09:09:59 +01:00
|
|
|
=encoding utf8
|
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
Lemonldap::NG::Portal::AuthLA - Provide Liberty Alliance Authentication for
|
|
|
|
FederID project.
|
|
|
|
|
2007-02-11 16:14:33 +01:00
|
|
|
=head1 SYNOPSIS
|
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
use Lemonldap::NG::Portal::AuthLA;
|
|
|
|
my $portal = Lemonldap::NG::Portal::AuthLA->new({
|
|
|
|
configStorage => {
|
|
|
|
type => 'DBI',
|
|
|
|
dbiChain => "dbi:mysql:...",
|
|
|
|
dbiUser => "lemonldap",
|
|
|
|
dbiPassword => "password",
|
|
|
|
dbiTable => "lmConfig",
|
|
|
|
} ,
|
|
|
|
|
|
|
|
# Liberty Parameters
|
|
|
|
laSp => {
|
|
|
|
certificate => '/path/to/public/key.pem' ,
|
|
|
|
metadata => '/path/to/metadata.xml' ,
|
|
|
|
privkey => '/path/to/private/key.pem' ,
|
|
|
|
secretkey => '/path/to/private/key.pem' ,
|
|
|
|
} ,
|
|
|
|
laIdpsFile => '/path/to/idps/file.xml' ,
|
|
|
|
laStorage => 'Apache::Session::File',
|
|
|
|
laStorageOptions => {
|
|
|
|
Directory => '/path/to/session/directory' ,
|
|
|
|
LockDirectory => '/path/to/lockedsession/directory' ,
|
|
|
|
} ,
|
|
|
|
laDebug => 1 ,
|
|
|
|
laLdapLoginAttribute => 'uid' ,
|
|
|
|
|
|
|
|
# Parameters that permit to access lemonldap::NG::Handler local cache
|
|
|
|
localStorage => 'Cache::FileCache' ,
|
|
|
|
localStorageOptions => {} ,
|
|
|
|
});
|
|
|
|
|
|
|
|
if( $portal->process() ) {
|
|
|
|
# Print protected URLs
|
|
|
|
print $portal->header ;
|
|
|
|
print "<a href=\"http://$_\"> $_</a><br/>"
|
2007-10-27 08:02:02 +02:00
|
|
|
foreach ($portal->getProtectedSites) ;
|
2007-10-15 07:29:29 +02:00
|
|
|
|
|
|
|
} else {
|
|
|
|
print $portal->header ;
|
|
|
|
print '...' ;
|
|
|
|
|
|
|
|
# Print simple template
|
|
|
|
print 'Simple Authentication<br/>' ;
|
|
|
|
print '<input type="hidden" name="url" value="' . $portal->param('url') . '"/>' ;
|
|
|
|
print 'Login :' ;
|
|
|
|
if ($portal->param('user')) {
|
|
|
|
print '<input type="hidden" name="user" value="' . $portal->param('user') . '"/>' ;
|
|
|
|
} else {
|
|
|
|
print '<input type="hidden" name="user"/>' ;
|
|
|
|
}
|
|
|
|
print 'Password : <input name="password" type="password" autocomplete="off">' ;
|
|
|
|
|
|
|
|
# Retrieve IDP list.
|
|
|
|
my @idps = () ;
|
|
|
|
foreach ($portal->getIdpIDs) {
|
|
|
|
my %row_data ;
|
|
|
|
$row_data{IDPNAME} = $_ ;
|
|
|
|
push (@idps, \%row_data) ;
|
|
|
|
}
|
|
|
|
@idps = sort {$a cmp $b} @idps ;
|
|
|
|
|
|
|
|
# Print SSO template
|
|
|
|
print 'SSO Authentication<br/>' ;
|
|
|
|
print '<select name="idpChoice"><option value="null">Select IDP</option>' ;
|
|
|
|
foreach (@idps) {
|
|
|
|
print '<option value="' . $_ . '">' . $_ . '</option>' ;
|
|
|
|
}
|
|
|
|
|
|
|
|
print '<input type="submit" value="ok" />' ;
|
|
|
|
print '</form>' ;
|
|
|
|
}
|
|
|
|
|
2007-02-11 16:14:33 +01:00
|
|
|
=head1 DESCRIPTION
|
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
Lemonldap::NG::Portal::AuthLA is the base module for building Lemonldap::NG
|
|
|
|
compatible portals using a authentication mechanism based on Liberty Alliance.
|
|
|
|
You have to use by inheritance.
|
|
|
|
|
2007-02-11 16:14:33 +01:00
|
|
|
=head1 SEE ALSO
|
|
|
|
|
|
|
|
L<Lemonldap::NG::Portal::SharedConf>, L<Lemonldap::NG::Portal>,
|
2007-04-02 21:13:05 +02:00
|
|
|
L<Lemonldap::NG::Handler>, L<Lemonldap::NG::Manager>,
|
|
|
|
http://wiki.lemonldap.objectweb.org/xwiki/bin/view/NG/Presentation
|
2007-02-11 16:14:33 +01:00
|
|
|
|
|
|
|
=head1 AUTHOR
|
|
|
|
|
2007-03-14 16:39:29 +01:00
|
|
|
Clement Oudot, E<lt>coudot@linagora.comE<gt>
|
2008-04-07 18:40:09 +02:00
|
|
|
Mikael Ates, E<lt>mikael.ates@univ-st-etienne.frE<gt>
|
|
|
|
Thomas Chemineau, E<lt>thomas.chemineau@gmail.comE<gt>
|
2007-02-11 16:14:33 +01:00
|
|
|
|
2007-04-14 15:12:11 +02:00
|
|
|
=head1 BUG REPORT
|
|
|
|
|
|
|
|
Use OW2 system to report bug or ask for features:
|
|
|
|
L<http://forge.objectweb.org/tracker/?group_id=274>
|
|
|
|
|
|
|
|
=head1 DOWNLOAD
|
|
|
|
|
|
|
|
Lemonldap::NG is available at
|
|
|
|
L<http://forge.objectweb.org/project/showfiles.php?group_id=274>
|
|
|
|
|
2007-02-11 16:14:33 +01:00
|
|
|
=head1 COPYRIGHT AND LICENSE
|
|
|
|
|
2007-10-15 07:29:29 +02:00
|
|
|
Copyright (C) 2007 by FederID Consortium, E<lt>mail@FederIDE<gt>
|
2007-02-11 16:14:33 +01:00
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify
|
|
|
|
it under the same terms as Perl itself, either Perl version 5.8.4 or,
|
|
|
|
at your option, any later version of Perl 5 you may have available.
|
|
|
|
|
|
|
|
=cut
|
2007-10-15 07:29:29 +02:00
|
|
|
|