From a98e3ac8bb4a32a5e2a95ae4dc2c5bd50500ff99 Mon Sep 17 00:00:00 2001 From: Xavier Guimard Date: Tue, 7 Apr 2009 20:38:24 +0000 Subject: [PATCH] SAML skeleton --- .../lib/Lemonldap/NG/Handler/CGI.pm | 1 + modules/lemonldap-ng-portal/MANIFEST | 7 ++ .../lib/Lemonldap/NG/Portal/AuthSAML.pm | 80 +++++++++++++++++++ .../lib/Lemonldap/NG/Portal/SAMLIssuer.pm | 74 +++++++++++++++++ .../lib/Lemonldap/NG/Portal/Simple.pm | 55 +++++++++---- .../lib/Lemonldap/NG/Portal/UserDBSAML.pm | 75 +++++++++++++++++ .../lib/Lemonldap/NG/Portal/_SAML.pm | 45 +++++++++++ .../t/60-Lemonldap-NG-Portal-SAMLIssuer.t | 15 ++++ .../t/63-Lemonldap-NG-Portal-AuthSAML.t | 15 ++++ .../t/64-Lemonldap-NG-Portal-UserDBSAML.t | 15 ++++ 10 files changed, 367 insertions(+), 15 deletions(-) create mode 100644 modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthSAML.pm create mode 100644 modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/SAMLIssuer.pm create mode 100644 modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDBSAML.pm create mode 100644 modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/_SAML.pm create mode 100644 modules/lemonldap-ng-portal/t/60-Lemonldap-NG-Portal-SAMLIssuer.t create mode 100644 modules/lemonldap-ng-portal/t/63-Lemonldap-NG-Portal-AuthSAML.t create mode 100644 modules/lemonldap-ng-portal/t/64-Lemonldap-NG-Portal-UserDBSAML.t diff --git a/modules/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/CGI.pm b/modules/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/CGI.pm index de3843a1c..c94447053 100644 --- a/modules/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/CGI.pm +++ b/modules/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/CGI.pm @@ -96,6 +96,7 @@ sub authenticate { } # Accounting : set user in apache logs $self->setApacheUser($datas->{$whatToTrace}); + $ENV{REMOTE_USER} = $datas->{$whatToTrace}; return 1; } diff --git a/modules/lemonldap-ng-portal/MANIFEST b/modules/lemonldap-ng-portal/MANIFEST index 883308b0b..c1488a69c 100644 --- a/modules/lemonldap-ng-portal/MANIFEST +++ b/modules/lemonldap-ng-portal/MANIFEST @@ -84,6 +84,7 @@ lib/Lemonldap/NG/Portal/_i18n.pm lib/Lemonldap/NG/Portal/_LDAP.pm lib/Lemonldap/NG/Portal/_Multi.pm lib/Lemonldap/NG/Portal/_Remote.pm +lib/Lemonldap/NG/Portal/_SAML.pm lib/Lemonldap/NG/Portal/_SOAP.pm lib/Lemonldap/NG/Portal/_WebForm.pm lib/Lemonldap/NG/Portal/AuthApache.pm @@ -92,6 +93,7 @@ lib/Lemonldap/NG/Portal/AuthLA.pm lib/Lemonldap/NG/Portal/AuthLDAP.pm lib/Lemonldap/NG/Portal/AuthMulti.pm lib/Lemonldap/NG/Portal/AuthRemote.pm +lib/Lemonldap/NG/Portal/AuthSAML.pm lib/Lemonldap/NG/Portal/AuthSSL.pm lib/Lemonldap/NG/Portal/CDA.pm lib/Lemonldap/NG/Portal/Error.pm @@ -99,11 +101,13 @@ lib/Lemonldap/NG/Portal/Menu.pm lib/Lemonldap/NG/Portal/Notification.pm lib/Lemonldap/NG/Portal/Notification/DBI.pm lib/Lemonldap/NG/Portal/Notification/File.pm +lib/Lemonldap/NG/Portal/SAMLIssuer.pm lib/Lemonldap/NG/Portal/SharedConf.pm lib/Lemonldap/NG/Portal/Simple.pm lib/Lemonldap/NG/Portal/UserDBLDAP.pm lib/Lemonldap/NG/Portal/UserDBMulti.pm lib/Lemonldap/NG/Portal/UserDBRemote.pm +lib/Lemonldap/NG/Portal/UserDBSAML.pm Makefile.PL MANIFEST This list of files META.yml @@ -121,4 +125,7 @@ t/24-Lemonldap-NG-Portal-AuthRemote.t t/25-Lemonldap-NG-Portal-Multi.t t/40-Lemonldap-NG-Portal-CDA.t t/50-Lemonldap-NG-Portal-Menu.t +t/60-Lemonldap-NG-Portal-SAMLIssuer.t +t/63-Lemonldap-NG-Portal-AuthSAML.t +t/64-Lemonldap-NG-Portal-UserDBSAML.t t/99-pod.t diff --git a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthSAML.pm b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthSAML.pm new file mode 100644 index 000000000..c584103f4 --- /dev/null +++ b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthSAML.pm @@ -0,0 +1,80 @@ +## @file +# SAML Consumer skeleton + +## @class +# SAML Consumer skeleton +package Lemonldap::NG::Portal::AuthSAML; + +use strict; +use Lemonldap::NG::Portal::Simple; + +## @apmethod int authInit() +# TODO +# Check SAML Consumer configuration. +# @return Lemonldap::NG::Portal error code +sub authInit { + my $self = shift; + $self->lmLog( 'This module is not yet usable', 'error' ); + PE_ERROR; +} + +## @apmethod int extractFormInfo() +# TODO +# @return Lemonldap::NG::Portal error code +sub extractFormInfo { + PE_OK; +} + +## @apmethod int setAuthSessionInfo() +# TODO +# @return Lemonldap::NG::Portal error code +sub setAuthSessionInfo { + PE_OK; +} + +## @apmethod int authenticate() +# Does nothing here +# @return PE_OK +sub authenticate { + PE_OK; +} + +## @apmethod void authLogout() +# TODO +sub authLogout { +} + +1; +__END__ + +=head1 NAME + +Lemonldap::NG::Portal::AuthSAML - TODO + +=head1 SYNOPSIS + + use Lemonldap::NG::Portal::AuthSAML; + #TODO + +=head1 DESCRIPTION + +TODO + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Xavier Guimard, Ex.guimard@free.frE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2009 by Xavier Guimard + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.10.0 or, +at your option, any later version of Perl 5 you may have available. + + +=cut diff --git a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/SAMLIssuer.pm b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/SAMLIssuer.pm new file mode 100644 index 000000000..b060f4c3a --- /dev/null +++ b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/SAMLIssuer.pm @@ -0,0 +1,74 @@ +## @file +# SAML Issuer skeleton + +## @class +# SAML Issuer skeleton +package Lemonldap::NG::Portal::SAMLIssuer; + +use strict; +use Lemonldap::NG::Portal::Simple; + +our $VERSION = '0.01'; + +## @method void SAMLIssuerInit() +# TODO +# Load and check SAML Issuer configuration +sub SAMLIssuerInit { + my $self = shift; + $self->abort('This feature is not released'); + return PE_OK; +} + +## @method int SAMLForUnAuthUser() +# TODO +# Check if there is an SAML authentication request. +# Called only for unauthenticated users, it store SAML request in +# $self->{url} +# @return Lemonldap::NG::Portal error code +sub SAMLForUnAuthUser { + PE_OK; +} + +## @method int SAMLForAuthUser() +# TODO +# Check if there is an SAML authentication request for an authenticated user +# and build assertions +# @return Lemonldap::NG::Portal error code +sub SAMLForAuthUser { + PE_OK; +} + +1; +__END__ + +=head1 NAME + +Lemonldap::NG::Portal::SAMLIssuer - TODO + +=head1 SYNOPSIS + + use Lemonldap::NG::Portal::SAMLIssuer; + #TODO + +=head1 DESCRIPTION + +TODO + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Xavier Guimard, Ex.guimard@free.frE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2009 by Xavier Guimard + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.10.0 or, +at your option, any later version of Perl 5 you may have available. + + +=cut diff --git a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Simple.pm b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Simple.pm index d1a0ca2c9..2872b3b55 100644 --- a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Simple.pm +++ b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Simple.pm @@ -15,7 +15,7 @@ use MIME::Base64; use Lemonldap::NG::Common::CGI; use CGI::Cookie; require POSIX; -use Lemonldap::NG::Portal::_i18n; #inherits +use Lemonldap::NG::Portal::_i18n; #inherits use Lemonldap::NG::Common::Safelib; #link protected safe Safe object use Safe; @@ -147,6 +147,11 @@ sub new { %$self = ( %h, %$self ); } } + if ( $self->{SAMLIssuer} ) { + require Lemonldap::NG::Portal::SAMLIssuer; + push @ISA, 'Lemonldap::NG::Portal::SAMLIssuer'; + $self->SAMLIssuerInit(); + } if ( $self->{notification} ) { require Lemonldap::NG::Portal::Notification; my $tmp; @@ -402,7 +407,7 @@ sub _subProcess { # If an handler is launched on the same server with "status=>1", inform the # status module with the result (portal error). sub updateStatus { - my ($self) = @_; + my $self = shift; print $Lemonldap::NG::Handler::Simple::statusPipe ( $self->{user} ? $self->{user} : $ENV{REMOTE_ADDR} ) . " => $ENV{SERVER_NAME}$ENV{SCRIPT_NAME} " @@ -413,7 +418,7 @@ sub updateStatus { ##@method protected string notification() #@return Notification stored by checkNotification() sub notification { - my ($self) = @_; + my $self = shift; return $self->{_notification}; } @@ -421,10 +426,8 @@ sub notification { # check url against XSS attacks # @return url parameter if good, nothing else. sub get_url { - my ($self) = @_; - return unless $self->param('url'); - return if ( $self->param('url') =~ m#[^A-Za-z0-9\+/=]# ); - return $self->param('url'); + my $self = shift; + return $self->{url}; } ##@method private Safe safe() @@ -510,10 +513,10 @@ sub process { my ($self) = @_; $self->{error} = PE_OK; $self->{error} = $self->_subProcess( - qw(controlUrlOrigin checkNotifBack controlExistingSession authInit - extractFormInfo userDBInit getUser setAuthSessionInfo setSessionInfo - setMacros setGroups authenticate store buildCookie checkNotification - autoRedirect) + qw(controlUrlOrigin checkNotifBack controlExistingSession + SAMLForUnAuthUser authInit extractFormInfo userDBInit getUser + setAuthSessionInfo setSessionInfo setMacros setGroups authenticate + store buildCookie checkNotification SAMLForAuthUser autoRedirect) ); $self->updateStatus; return ( ( $self->{error} > 0 ) ? 0 : 1 ); @@ -524,12 +527,14 @@ sub process { #@return Lemonldap::NG::Portal constant sub controlUrlOrigin { my $self = shift; + $self->{url} ||= ''; + my $url = $self->param('url'); if ( $self->param('url') ) { # REJECT NON BASE64 URL - return PE_BADURL if ( $self->param('url') =~ m#[^A-Za-z0-9\+/=]# ); + return PE_BADURL if ( $url =~ m#[^A-Za-z0-9\+/=]# ); - $self->{urldc} = decode_base64( $self->param('url') ); + $self->{urldc} = decode_base64($url); $self->{urldc} =~ s/[\r\n]//sg; # REJECT [\0<'"`] in URL or encoded '%' and non protected hosts @@ -543,6 +548,7 @@ m#^https?://(?:$self->{reVHosts}|(?:[^/]*)?$self->{domain})(?::\d+)?(?:/.*)?$# delete $self->{urldc}; return PE_BADURL; } + $self->{url} = $url; } PE_OK; } @@ -560,14 +566,23 @@ sub checkNotifBack { return PE_NOTIFICATION; } else { - $self->{error} = - $self->_subProcess(qw(checkNotification autoRedirect)); + $self->{error} = $self->_subProcess( + qw(checkNotification SAMLForAuthUser autoRedirect)); return $self->{error} || PE_DONE; } } PE_OK; } +##@apmethod int SAMLForUnAuthUser() +# Load Lemonldap::NG::Portal::SAMLIssuer::SAMLForUnAuthUser() if +# $self->{SAMLIssuer} is set. +#@return Lemonldap::NG::Portal constant +sub SAMLForUnAuthUser { + return $self->SUPER::SAMLForUnAuthUser(@_) if ( $self->{SAMLIssuer} ); + PE_OK; +} + ##@apmethod int controlExistingSession(string id) # 3) Control existing sessions. # To overload to control what to do with existing sessions. @@ -601,6 +616,7 @@ sub controlExistingSession { $self->_sub( 'userNotice', $self->{sessionInfo}->{ $self->{whatToTrace} } . " has been disconnected" ); + eval { $self->_sub('authLogout') }; $self->_subProcess(qw(autoRedirect)); return PE_FIRSTACCESS; } @@ -790,6 +806,15 @@ sub checkNotification { return PE_OK; } +##@apmethod int SAMLForAuthUser() +# Load Lemonldap::NG::Portal::SAMLIssuer::SAMLForAuthUser() if +# $self->{SAMLIssuer} is set. +#@return Lemonldap::NG::Portal constant +sub SAMLForAuthUser { + return $self->SUPER::SAMLForAuthUser(@_) if ( $self->{SAMLIssuer} ); + PE_OK; +} + ##@apmethod int autoRedirect() # 16) If the user was redirected to the portal, we will now redirect him # to the requested URL. diff --git a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDBSAML.pm b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDBSAML.pm new file mode 100644 index 000000000..7a3ec9952 --- /dev/null +++ b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDBSAML.pm @@ -0,0 +1,75 @@ +## @file +# UserDB SAML module + +## @class +# UserDB SAML module +package Lemonldap::NG::Portal::UserDBSAML; + +use strict; +use Lemonldap::NG::Portal::Simple; + +our $VERSION = '0.01'; + +## @apmethod int userDBInit() +# Check if authentication module is SAML +# @return Lemonldap::NG::Portal error code +sub userDBInit { + my $self = shift; + if ( $self->{authentication} =~ /^SAML/ + or $self->{stack}->[0]->[0]->{m} =~ /^SAML/ ) + { + return PE_OK; + } + else { + return PE_ERROR; + } +} + +## @apmethod int getUser() +# Does nothing +# @return Lemonldap::NG::Portal error code +sub getUser { + PE_OK; +} + +## @apmethod int setSessionInfo() +# Does nothing +# @return Lemonldap::NG::Portal error code +sub setSessionInfo { + PE_OK; +} + +1; +__END__ + +=head1 NAME + +Lemonldap::NG::Portal::UserDBSAML - TODO + +=head1 SYNOPSIS + + use Lemonldap::NG::Portal::UserDBSAML; + #TODO + +=head1 DESCRIPTION + +TODO + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Xavier Guimard, Ex.guimard@free.frE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2009 by Xavier Guimard + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.10.0 or, +at your option, any later version of Perl 5 you may have available. + + +=cut diff --git a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/_SAML.pm b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/_SAML.pm new file mode 100644 index 000000000..021031915 --- /dev/null +++ b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/_SAML.pm @@ -0,0 +1,45 @@ +## @file +# Common SAML functions + +## @class +# Common SAML functions +package Lemonldap::NG::Portal::_SAML; + +use strict; + +our $VERSION = '0.01'; + +1; +__END__ + +=head1 NAME + +Lemonldap::NG::Portal::_SAML - TODO + +=head1 SYNOPSIS + + use Lemonldap::NG::Portal::_SAML; + #TODO + +=head1 DESCRIPTION + +TODO + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Xavier Guimard, Ex.guimard@free.frE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2009 by Xavier Guimard + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.10.0 or, +at your option, any later version of Perl 5 you may have available. + + +=cut diff --git a/modules/lemonldap-ng-portal/t/60-Lemonldap-NG-Portal-SAMLIssuer.t b/modules/lemonldap-ng-portal/t/60-Lemonldap-NG-Portal-SAMLIssuer.t new file mode 100644 index 000000000..edb1ddd3b --- /dev/null +++ b/modules/lemonldap-ng-portal/t/60-Lemonldap-NG-Portal-SAMLIssuer.t @@ -0,0 +1,15 @@ +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl Lemonldap-NG-Portal-SAMLIssuer.t' + +######################### + +# change 'tests => 1' to 'tests => last_test_to_print'; + +use Test::More tests => 1; +BEGIN { use_ok('Lemonldap::NG::Portal::SAMLIssuer') }; + +######################### + +# Insert your test code below, the Test::More module is use()ed here so read +# its man page ( perldoc Test::More ) for help writing this test script. + diff --git a/modules/lemonldap-ng-portal/t/63-Lemonldap-NG-Portal-AuthSAML.t b/modules/lemonldap-ng-portal/t/63-Lemonldap-NG-Portal-AuthSAML.t new file mode 100644 index 000000000..029250cb3 --- /dev/null +++ b/modules/lemonldap-ng-portal/t/63-Lemonldap-NG-Portal-AuthSAML.t @@ -0,0 +1,15 @@ +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl Lemonldap-NG-Portal-AuthSAML.t' + +######################### + +# change 'tests => 1' to 'tests => last_test_to_print'; + +use Test::More tests => 1; +BEGIN { use_ok('Lemonldap::NG::Portal::AuthSAML') }; + +######################### + +# Insert your test code below, the Test::More module is use()ed here so read +# its man page ( perldoc Test::More ) for help writing this test script. + diff --git a/modules/lemonldap-ng-portal/t/64-Lemonldap-NG-Portal-UserDBSAML.t b/modules/lemonldap-ng-portal/t/64-Lemonldap-NG-Portal-UserDBSAML.t new file mode 100644 index 000000000..622189fec --- /dev/null +++ b/modules/lemonldap-ng-portal/t/64-Lemonldap-NG-Portal-UserDBSAML.t @@ -0,0 +1,15 @@ +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl Lemonldap-NG-Portal-UserDBSAML.t' + +######################### + +# change 'tests => 1' to 'tests => last_test_to_print'; + +use Test::More tests => 1; +BEGIN { use_ok('Lemonldap::NG::Portal::UserDBSAML') }; + +######################### + +# Insert your test code below, the Test::More module is use()ed here so read +# its man page ( perldoc Test::More ) for help writing this test script. +