diff --git a/build/lemonldap-ng/Makefile b/build/lemonldap-ng/Makefile index c28c1e073..09def9550 100644 --- a/build/lemonldap-ng/Makefile +++ b/build/lemonldap-ng/Makefile @@ -319,6 +319,7 @@ install_portal_site: install_conf_dir @cp -pR --remove-destination ${SRCPORTALDIR}/example/error.pl ${RPORTALDIR} @cp -pR --remove-destination ${SRCPORTALDIR}/example/mail.pl ${RPORTALDIR} @cp -pR --remove-destination ${SRCPORTALDIR}/example/metadata.pl ${RPORTALDIR} + @cp -pR --remove-destination ${SRCPORTALDIR}/example/cdc.pl ${RPORTALDIR} @cp -pR --remove-destination ${SRCPORTALDIR}/example/skins/* $(RPORTALSKINSDIR) @if [ "$(PORTALDIR)/skins/" != "$(PORTALSKINSDIR)/" ]; then \ for skin in $$(ls lemonldap-ng-portal/example/skins/); do \ @@ -567,6 +568,7 @@ debian-diff: @$(DIFF) lemonldap-ng-portal/example/error.pl /var/lib/lemonldap-ng/portal/error.pl ||true @$(DIFF) lemonldap-ng-portal/example/mail.pl /var/lib/lemonldap-ng/portal/mail.pl ||true @$(DIFF) lemonldap-ng-portal/example/metadata.pl /var/lib/lemonldap-ng/portal/metadata.pl ||true + @$(DIFF) lemonldap-ng-portal/example/cdc.pl /var/lib/lemonldap-ng/portal/cdc.pl ||true @# Handler @$(DIFF) lemonldap-ng-handler/lib/Lemonldap/NG/Handler /usr/share/perl5/Lemonldap/NG/Handler ||true @# Common @@ -593,6 +595,7 @@ default-diff: @$(DIFF) lemonldap-ng-portal/example/error.pl $(LMPREFIX)/htdocs/portal/error.pl ||true @$(DIFF) lemonldap-ng-portal/example/mail.pl $(LMPREFIX)/htdocs/portal/mail.pl ||true @$(DIFF) lemonldap-ng-portal/example/metadata.pl $(LMPREFIX)/htdocs/portal/metadata.pl ||true + @$(DIFF) lemonldap-ng-portal/example/cdc.pl $(LMPREFIX)/htdocs/portal/cdc.pl ||true @# Handler @$(DIFF) lemonldap-ng-handler/lib/Lemonldap/NG/Handler /usr/local/share/perl/5.10.0/Lemonldap/NG/Handler ||true @$(DIFF) lemonldap-ng-handler/example/MyHandler.pm $(LMPREFIX)/handler/MyHandler.pm ||true diff --git a/modules/lemonldap-ng-portal/MANIFEST b/modules/lemonldap-ng-portal/MANIFEST index 2af9843d5..a221630f3 100644 --- a/modules/lemonldap-ng-portal/MANIFEST +++ b/modules/lemonldap-ng-portal/MANIFEST @@ -34,6 +34,7 @@ example/AuthLA/tpl/themes/federid/page-bg.png example/AuthLA/tpl/themes/federid/sso.css example/AuthLA/tpl/themes/federid/wui.css example/cas.pl +example/cdc.pl example/error.pl example/index.pl example/index_simple.pl @@ -184,6 +185,7 @@ lib/Lemonldap/NG/Portal/AuthSAML.pm lib/Lemonldap/NG/Portal/AuthSSL.pm lib/Lemonldap/NG/Portal/AuthTwitter.pm lib/Lemonldap/NG/Portal/CDA.pm +lib/Lemonldap/NG/Portal/CDC.pm lib/Lemonldap/NG/Portal/IssuerDBCAS.pm lib/Lemonldap/NG/Portal/IssuerDBNull.pm lib/Lemonldap/NG/Portal/IssuerDBOpenID.pm diff --git a/modules/lemonldap-ng-portal/example/cdc.pl b/modules/lemonldap-ng-portal/example/cdc.pl new file mode 100755 index 000000000..51b716ae7 --- /dev/null +++ b/modules/lemonldap-ng-portal/example/cdc.pl @@ -0,0 +1,31 @@ +#!/usr/bin/perl + +#============================================================================== +# Script to manage SAML Cross Domain Cookie +# +# Part of LemonLDAP::NG project +#============================================================================== + +use strict; +use Lemonldap::NG::Portal::CDC; + +# Create portal +my $portal = Lemonldap::NG::Portal::CDC->new(); + +# Process +my $result = $portal->process(); +my $values = $portal->{cdc_values}; + +# Very simple page displaying cookie content +print $portal->header('text/html; charset=utf-8'); +print $portal->start_html('Cross Domain Cookie'); +print $portal->h1("Cross Domain Cookie"); +if ( defined $values ) { + print $portal->p($_) foreach (@$values); +} +else { + print $portal->p("No cookie found"); +} +print $portal->end_html(); + +exit; diff --git a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/CDC.pm b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/CDC.pm new file mode 100644 index 000000000..f3a8ec830 --- /dev/null +++ b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/CDC.pm @@ -0,0 +1,201 @@ +## @file +# Module for SAML Common Domain Cookie Support + +## @class Lemonldap::NG::Portal::CDC +# Class for SAML Common Domain Cookie Support +package Lemonldap::NG::Portal::CDC; + +use strict; +use warnings; +use MIME::Base64; +use Lemonldap::NG::Portal::SharedConf; # inherits +use Lemonldap::NG::Portal::_SAML; # inherits + +our $VERSION = '0.1'; +our @ISA = qw(Lemonldap::NG::Portal::_SAML Lemonldap::NG::Portal::SharedConf); + +## @method int process() +# Main method to process CDC requests +# @return portal error code +sub process { + my $self = shift; + my $cdc_idp = ""; + my $cdc_cookie = ""; + + # Default values + my $cdc_name = $self->{samlCommonDomainCookieName} || '_saml_idp'; + my $cdc_domain = $self->{samlCommonDomainCookieDomain} || $ENV{'HTTP_HOST'}; + + $self->lmLog( "[CDC] Cookie name: $cdc_name", 'debug' ); + $self->lmLog( "[CDC] Domain name: $cdc_domain", 'debug' ); + + # Request parameter + my $action = $self->param('action') || ""; # What we do + my $idp = $self->param('idp'); # IDP ID in write mode + + # Control URL + my $control_url = $self->_sub('controlUrlOrigin'); + unless ( $control_url == PE_OK ) { + $self->lmLog( "[CDC] Bad URL", 'error' ); + return $control_url; + } + + # Get cookie + my %cookies = fetch CGI::Cookie; + $cdc_cookie = $cookies{$cdc_name} if %cookies; + $cdc_cookie &&= $cdc_cookie->value; + + if ($cdc_cookie) { + $self->lmLog( "[CDC] Cookie found with value $cdc_cookie", 'debug' ); + } + + # Write request + # Called in an iFrame + # Get or build common domain cookie + # Append IDP to common domain cookie + if ( $action eq 'write' ) { + + $self->lmLog( "[CDC] Write request detected", 'debug' ); + + # Check IDP value + unless ($idp) { + $self->lmLog( "[CDC] No IDP given", 'error' ); + return PE_SAML_ERROR; + } + + # Add IDP value + $self->lmLog( "[CDC] Will add IDP $idp to IDP list", 'debug' ); + + my $encoded_idp = encode_base64($idp); + + # Remove IDP value if already present + $cdc_cookie =~ s/$encoded_idp(\s+)?//g; + + # Add a space separator + $cdc_cookie .= ( $cdc_cookie ? " " : "" ); + $cdc_cookie .= $encoded_idp; + + $self->lmLog( "[CDC] Build cookie $cdc_name with value $cdc_cookie", + 'debug' ); + + # Build cookie + push @{ $self->{cookie} }, $self->cookie( + -name => $cdc_name, + -value => $cdc_cookie, + -domain => $cdc_domain, + -path => "/", # See SAML protocol + -secure => 1, # See SAML protocol + -httponly => $self->{httpOnly}, + -expires => $self->{cookieExpiration}, + ); + } + + # Read request + # Get last IDP from domain cookie + # Return on SP with idp as parameter + + elsif ( $action eq 'read' ) { + + $self->lmLog( "[CDC] Read request detected", 'debug' ); + + # Get last IDP from cookie + if ($cdc_cookie) { + $cdc_idp = decode_base64( ( split /\s+/, $cdc_cookie )[-1] ); + + $self->lmLog( "[CDC] Get value $cdc_idp", 'debug' ); + } + + } + + # Redirect if needed + if ( $self->{urldc} ) { + + # Add CDC IDP in return URL if needed + $self->{urldc} .= ( + $cdc_idp + ? ( + $self->{urldc} =~ /\?/ + ? '&idp=' . $cdc_idp + : '?idp=' . $cdc_idp + ) + : '' + ); + + # Redirect + $self->_sub('autoRedirect'); + + } + + if ($cdc_cookie) { + + # Parse cookie to display it if not redirected + my @cdc_values = + map( decode_base64($_), ( split( /\s+/, $cdc_cookie ) ) ); + $self->{cdc_values} = \@cdc_values; + } + + return PE_OK; +} + +1; + +__END__ + +=head1 NAME + +=encoding utf8 + +Lemonldap::NG::Portal::CDC - Manage SAML Common Domain Cookie + +=head1 SYNOPSIS + + use Lemonldap::NG::Portal::CDC; + + my $portal = new Lemonldap::NG::Portal::CDC(); + + $portal->process(); + + # Write here HTML to manage errors and confirmation messages + +=head1 DESCRIPTION + +Lemonldap::NG::Portal::CDC - Manage SAML Common Domain Cookie + +See L for a complete example of use of +Lemonldap::Portal::* libraries. + +=head1 METHODS + +=head3 process + +Main method. + +=head1 SEE ALSO + +L, L, L, +http://wiki.lemonldap.objectweb.org/xwiki/bin/view/NG/Presentation + +=head1 AUTHOR + +Clement Oudot, Eclement@oodo.netE + +=head1 BUG REPORT + +Use OW2 system to report bug or ask for features: +L + +=head1 DOWNLOAD + +Lemonldap::NG is available at +L + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2005-2009 by Xavier Guimard Ex.guimard@free.frE and +Clement Oudot, Eclement@oodo.netE + +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