Commit 5c28a9bf authored by Eric German's avatar Eric German

new module CAS

git-svn-id: svn://svn.forge.objectweb.org/svnroot/lemonldap/trunk@109 1dbb9719-a921-0410-b57f-c3a383c2c641
parent 98f9e81b
<?php /* ------ exemple de client CAS écrit en PHP --------*/
//print( "Content-type: text/html\n" );
//print( "\n" );
// localisation du serveur CAS
define('CAS_BASE','http://authen.demo.net');
// propre URL
//$service = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
$service = 'http://' . $_SERVER['SERVER_NAME'] . '/caspied.php';
/** Cette simple fonction réalise l?authentification CAS.
* @return le login de l?utilisateur authentifié, ou FALSE.
*/
function authenticate() {
global $service ;
// récupération du ticket (retour du serveur CAS)
if (!isset($_GET['ticket'])) {
// pas de ticket : on redirige le navigateur web vers le serveur CAS
header('Location: ' . CAS_BASE . '/cas/login/?service=' . $service);
exit() ;
}
// un ticket a été transmis, on essaie de le valider auprès du serveur CAS
$ticket = $_GET['ticket'];
// $service = $_GET['service'];
print( 'service: '.$service.'<br>' );
print( 'ticket: '.$ticket.'<br>' );
//$ticket .= '1';
$fpage = fopen (CAS_BASE . '/cas/serviceValidate?service='
. preg_replace('/&/','%26',$service) . '&ticket=' . $ticket, 'r');
if ($fpage) {
while (!feof ($fpage)) { $page .= fgets ($fpage, 1024); }
// analyse de la réponse du serveur CAS
if (preg_match('|<cas:authenticationSuccess>.*</cas:authenticationSuccess>|mis',$page)) {
if(preg_match('|<cas:user>(.*)</cas:user>|',$page,$match)){
return($match[1]);
}
}
}
// problème de validation
return FALSE;
}
//print( 'je passe ici' );
$login = authenticate();
if ($login == FALSE ) {
echo 'Requête non authentifiée (<a href="'.$service.'"><b>Recommencer</b></a>).';
exit() ;
}
// à ce point, l?utilisateur est authentifié
echo 'Utilisateur connecté : ' . $login . '(<a href="' . CAS_BASE . '/cas/logout"><b>déconnexion</b></a>)';
?>
<?php /* ------ exemple de client CAS écrit en PHP --------*/
//include_once('CAS.php');
//print( "Content-type: text/html\n" );
//print( "\n" );
// localisation du serveur CAS
define('CAS_BASE','http://authen.demo.net');
// propre URL
//$service = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
$service = 'http://' . $_SERVER['SERVER_NAME'] . '/castete.php';
/** Cette simple fonction réalise l?authentification CAS.
* @return le login de l?utilisateur authentifié, ou FALSE.
*/
function authenticate() {
global $service ;
// récupération du ticket (retour du serveur CAS)
if (!isset($_GET['ticket'])) {
// pas de ticket : on redirige le navigateur web vers le serveur CAS
header('Location: ' . CAS_BASE . '/cas/login?service=' . $service);
exit() ;
}
// un ticket a été transmis, on essaie de le valider auprès du serveur CAS
$ticket = $_GET['ticket'];
// $service = $_GET['service'];
print( 'service: '.$service.'<br>' );
print( 'ticket: '.$ticket.'<br>' );
//$ticket .= '1';
$fpage = fopen (CAS_BASE . '/cas/serviceValidate?service='
. preg_replace('/&/','%26',$service) . '&ticket=' . $ticket, 'r');
if ($fpage) {
while (!feof ($fpage)) { $page .= fgets ($fpage, 1024); }
// analyse de la réponse du serveur CAS
print( 'la: '.$page );
if (preg_match('|<cas:authenticationSuccess>.*</cas:authenticationSuccess>|mis',$page)) {
if(preg_match('|<cas:user>(.*)</cas:user>|',$page,$match)){
return($match[1]);
}
}
}
// problème de validation
return FALSE;
}
//print( 'je passe ici' );
$login = authenticate();
if ($login == FALSE ) {
echo 'Requête non authentifiée (<a href="'.$service.'"><b>Recommencer</b></a>).';
exit() ;
}
// à ce point, l?utilisateur est authentifié
echo 'Utilisateur connecté : ' . $login . '(<a href="' . CAS_BASE . '/cas/logout"><b>déconnexion</b></a>)';
?>
<lemonconfig>
<domain id="demo.net"
Cookie="lemondemo"
Sessionstore="memcached"
portal= "http://authen.demo.net/portail/accueil.pl"
LoginCASPage="/tmp/login.htmlcas"
LogoutCASPage="/tmp/logout.htmlcas"
LoginPage="/tmp/login.html"
ldap_server="192.168.247.30"
ldap_branch_people="ou=personnes,dc=demo,dc=net"
>
<handler
id="validate"
MultiHoming="pied,tete"
/>
<handler id="pied"
MotifIn="/192.168.204.108\/caspied"
applcode= "mail"
pluginpolicy="Lemonldap::Handlers::RowPolicy"
/>
<handler id="tete"
MotifIn="/192.168.204.108\/castete"
disableaccessControl="1"
/>
<handler
id="appli1"
applcode= "APT"
pluginpolicy="Lemonldap::Handlers::RowPolicy"
enableLWP="1"
basepub="http://myappli.demo.net"
basepriv="http://www.eyrolles.com"
>
</handler>
<DefinitionSession>
<ligne id = "mail"
type = "single"
cle ="mail"
valeur= "%mail%" >
</ligne>
<ligne id = "roleprofil"
type = "multi"
cle ="%roleprofil;0%"
valeur= "%roleprofil;1%" >
</ligne>
<ligne id = "dn"
type = "single"
cle ="dn"
valeur= "%dn%" >
</ligne>
<exp id ="dn"
type= "dnentry"
/>
<exp id ="mail"
type= "attrldap"
attribut= "mail"
/>
<exp id ="roleprofil"
type= "attrldap"
attribut= "mefiapplidgcp"
/>
</DefinitionSession>
</domain>
<session id="memcached"
SessionParams="( servers => ['localhost:11211'] )"
>
</session>
</lemonconfig>
ServerSignature Off
PerlModule APR::Table
namevirtualhost 192.168.204.100
perlsetvar internaldebug 1
<virtualhost 192.168.204.100>
servername authen.demo.net
loglevel debug
documentroot /usr/local/apache2/htdocs
alias /portal /usr/local/monapache/portal/
ErrorLog logs/error_log
PerlSetVar Configfile /usr/local/monapache/conf/application.xml
PerlSetVar Domain demo.net
<location /cas/login>
setHandler modperl
perlresponsehandler Lemonldap::Handlers::LoginCASFake
PerlOptions +GlobalRequest
</location>
<location /cas/serviceValidate>
setHandler modperl
perlresponsehandler Lemonldap::Handlers::ValidateCAS
PerlSetVar HandlerID validate
PerlOptions +GlobalRequest
</location>
<location /cas/logout>
setHandler modperl
perlresponsehandler Lemonldap::Handlers::LogoutCAS
PerlOptions +GlobalRequest
</location>
</virtualhost>
<virtualhost 192.168.204.100 >
servername myappli.demo.net
loglevel debug
documentroot /usr/local/apache2/htdocs
perltranshandler Lemonldap::Handlers::Generic4a2
PerlSetVar Domain demo.net
PerlSetVar Configfile /usr/local/monapache/conf/application.xml
PerlSetVar HandlerID appli1
</virtualhost>
<html>
<head>
<title>lemonldap websso</title>
<style type="text/css" media="all">
p { color: #060;
font-size: 1.0em;
font-family: Verdana, Arial, sans-serif;
font-weight: bold;
}
h1 { color: #000;
font-size: 1.5em;
font-family: Verdana, Arial, sans-serif;
font-weight: bold;
border-bottom: 3px solid #019733;
margin: 40px 0 20px 0px;
padding: 0 0.5em 0.5em 0.5em;
}
body { background-color: #77E0AB; }
label { background-color: #94DBB7;
color: #018023;
font-weight: bold;
padding: 4px;
font-family: Verdana, Arial, sans-serif;
font-size: 0.9em;
width: 500px;
}
input { display: block;
margin-top: 0.25em;
margin-bottom: 1.25em;
width: 150px;
border: solid black;
border-width: 1px 2px 2px 1px;
}
.butok { width: 75px;
margin-left: 75px;
color: #069836;
border: 2px solid #F1CC26;
font-weight: bold;
background-color: #E6E0A4;
padding: 2px;
}
.butok:hover { width: 75px;
margin-left: 75px;
color: #050;
border: 2px solid #E6E0A4;
font-weight: bold;
background-color: #F1CC26;
padding: 2px;
}
br { display: none;
}
.nodisp { display: none; }
</style>
</head>
<body>
<h1>Hello on lemonldap and CAS websso 'world</h1>
<form method="post" name="formIdent">
<p><p>Fill the 2 fields<p>
<label>Enter your user name (anything):</label><input type=text name="username" value="%user%">
<p>
<label>Enter password (anything):</label><input type=password name="password" value="%secret%">
<p>
<b>%message%</b>
<p> url demande : %urldc% <p>
<input type="hidden" name="url" value="%urldc%" class="nodisp">
<input type="hidden" name="service" value="%urldc%" class="nodisp">
<input type=hidden name="it" value="%it%" class="nodisp" >
<input type=submit name="envoi" class="butok">
</form>
</body>
</html>
<html>
<head>
<title>lemonldap websso</title>
<style type="text/css" media="all">
p { color: #060;
font-size: 1.0em;
font-family: Verdana, Arial, sans-serif;
font-weight: bold;
}
h1 { color: #000;
font-size: 1.5em;
font-family: Verdana, Arial, sans-serif;
font-weight: bold;
border-bottom: 3px solid #019733;
margin: 40px 0 20px 0px;
padding: 0 0.5em 0.5em 0.5em;
}
body { background-color: #77E0AB; }
label { background-color: #94DBB7;
color: #018023;
font-weight: bold;
padding: 4px;
font-family: Verdana, Arial, sans-serif;
font-size: 0.9em;
width: 500px;
}
input { display: block;
margin-top: 0.25em;
margin-bottom: 1.25em;
width: 150px;
border: solid black;
border-width: 1px 2px 2px 1px;
}
.butok { width: 75px;
margin-left: 75px;
color: #069836;
border: 2px solid #F1CC26;
font-weight: bold;
background-color: #E6E0A4;
padding: 2px;
}
.butok:hover { width: 75px;
margin-left: 75px;
color: #050;
border: 2px solid #E6E0A4;
font-weight: bold;
background-color: #F1CC26;
padding: 2px;
}
br { display: none;
}
.nodisp { display: none; }
</style>
</head>
<body>
<h1>logout from lemonldap and CAS websso 'world</h1>
<p><center><b>Your are deconnected , see you again !</b></center>
</body>
</html>
package Lemonldap::Handlers::CAS;
our ( @ISA, $VERSION, @EXPORTS );
$VERSION = '1.0';
1;
__END__
=pod
=head1 NAME
Lemonldap::Handlers::CAS - Perl extension for Lemonldap webSSO
=head1 SYNOPSIS
use Lemonldap::Handlers::Validate ### Validate service ticket
use Lemonldap::Handlers::LoginCASFake ### Fake login : user must be egal to password (like CAS server demo)
use Lemonldap::Handlers::LogoutCAS ### logout SSO
=head1 DESCRIPTION
Lemonldap is a Reverse-proxy webSSO and CAS (Central Authentification Service) is an another websso from Yales university .
CAS acts like Authentification service NOT for authorization service .
These modules give the capacity at a lemonldap to become CAS server.
So , an user will be authenticate on CAS server AND on lemonldap.
Then the service ticket is send to serviceValidate the lemonldap can retrieve all session for user and process to authorization like a lemonldap .
=head1 Compatibility with CAS protocol.
Lemonldap manages those parameters :
=over 4
=item service
=item renew
=item gateway
=back
=head1 INSTALLATION
You must have an lemonldap websso installed (see doc on lemonldap.objectweb.org)
Configures your Apache like this :
<virtualhost 192.168.204.100>
servername authen.demo.net
loglevel debug
documentroot /usr/local/apache2/htdocs
alias /portal /usr/local/monapache/portal/
ErrorLog logs/error_log
<location /cas/login>
setHandler modperl
perlresponsehandler Lemonldap::Handlers::LoginCASFake
PerlSetVar Domain demo.net
PerlSetVar Configfile /usr/local/monapache/conf/application.xml
PerlOptions +GlobalRequest
</location>
<location /cas/serviceValidate>
setHandler modperl
perlresponsehandler Lemonldap::Handlers::ValidateCAS
PerlSetVar Domain demo.net
PerlSetVar HandlerID validate
PerlSetVar Configfile /usr/local/monapache/conf/application.xml
PerlOptions +GlobalRequest
</location>
<location /cas/logout>
setHandler modperl
perlresponsehandler Lemonldap::Handlers::LogoutCAS
PerlSetVar Domain demo.net
PerlSetVar Configfile /usr/local/monapache/conf/application.xml
PerlOptions +GlobalRequest
</location>
</virtualhost>
YOU CAN MIXED lemonldap handler et CAS server
Your application.xml is like this
<domain id="demo.net"
Cookie="lemondemo"
Sessionstore="memcached"
portal= "http://authen.demo.net/portail/accueil.pl"
LoginCASPage="/tmp/login.htmlcas"
LogoutCASPage="/tmp/logout.htmlcas"
LoginPage="/tmp/login.html"
ldap_server="192.168.247.30"
ldap_branch_people="ou=personnes,dc=demo,dc=net"
>
<handler
id="validate"
MultiHoming="pied,tete"
/>
<handler id="pied"
MotifIn="/192.168.204.108\/caspied"
applcode= "mail"
pluginpolicy="Lemonldap::Handlers::RowPolicy"
/>
<handler id="tete"
MotifIn="/192.168.204.108\/castete"
disableaccessControl="1"
/>
#### here normal lemonldap application #####
<handler
id="appli1"
applcode= "APT"
pluginpolicy="Lemonldap::Handlers::RowPolicy"
enableLWP="1"
basepub="http://myappli.demo.net"
basepriv="http://www.eyrolles.com"
>
</handler>
etc..
Put your login.html and logout.cas in the good directory (here /tmp) and the right name (here /tmp/login.htmlcas )
See the caspied and castete php examples (basic and standard CAS application)
=head1 NOTES
=over 4
=item Lemonldapcas is just an emulation of CAS server , use the real CAS server if you have only CAS application .
=item Lemonldap provides CAS version 1 and version 2 protocol ,if your location of validation contents the word 'Validate' (eg serviceValidation) the hanlder will use CAS version 2 overwise (eg service) it's CAS version 1
=item Lemonlap DOESN'T provide 'proxycas' service (in process) .
=item Lemonldap shares its sessions with other lemonldap (unlike CAS server) .
=item YOU MUST use HTTPS (by mod_ssl) in your apache server
=back
=head2 EXPORT
None by default.
=head1 SEE ALSO
Mention other useful documentation such as the documentation of
related modules or operating system documentation (such as man pages
in UNIX), or any relevant external documentation such as RFCs or
standards.
=head1 AUTHOR
root, E<lt>germanlinux@yahoo.frE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2007 by germanlinux at yahoo.fr
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.5 or,
at your option, any later version of Perl 5 you may have available.
=cut
package Lemonldap::Handlers::CoreCAS;
use strict;
#A retirer en prod
use Data::Dumper;
our ( @ISA, $VERSION, @EXPORTS );
$VERSION = '3.1.0';
our $VERSION_LEMONLDAP = "3.1.0";
our $VERSION_INTERNAL = "3.1.0";
sub locationRules {
my %param = @_;
# first retrieve session
my $id = $param{'id'};
my $config = $param{'config'};
my $uri = $param{'uri'};
my $host = $param{'host'};
my $target = $param{'target'};
my $_session = $param{'session'};
#my $_session = Lemonldap::Handlers::Session->get ('id' => $id ,
# 'config' => $config)# ;
#if (keys(%{$_session}) == 0){
#return 0;
#}
my $_trust = Lemonldap::Handlers::Policy->get(
'session' => $_session,
'parameters' => \%param
);
my $result = $_trust->{profil};
my $response = $_trust->{response};
my $h = {
dn => $_session->{dn},
uid => $_session->{uid},
string => $_trust->{profil},
response => $_trust->{response},
clientIPAdress => $_session->{clientIPAdress},
SessExpTime => $_session->{SessExpTime}
};
return $h;
}
package Lemonldap::Handlers::Session;
use Data::Dumper;
sub get {
my $class = shift;
my %_param = @_;
$_param{config}->{'SESSIONSTOREPLUGIN'} = 'Lemonldap::Handlers::Memsession'
unless $_param{config}->{'SESSIONSTOREPLUGIN'};
my $api = $_param{config}->{'SESSIONSTOREPLUGIN'};
eval "use $api;";
my $html = $api->get(%_param);
# bless $session, $class;
return $html;
}
package Lemonldap::Handlers::Policy;
sub get {
my $class = shift;
my %_param = @_;
$_param{parameters}->{config}->{'PLUGINPOLICY'} =
'Lemonldap::Handlers::MatrixPolicy'
unless $_param{parameters}->{config}->{'PLUGINPOLICY'};
my $api = $_param{parameters}->{config}->{'PLUGINPOLICY'};
eval "use $api;";
my $trust = $api->get(%_param);
# bless $trust , $class;
return $trust;
}
1;
package Lemonldap::Handlers::LogoutCAS;
use strict;
use warnings;
use Lemonldap::Config::Parameters;
use Apache2::Const qw(DONE FORBIDDEN OK SERVER_ERROR REDIRECT);
use Apache2::ServerUtil ();
use Apache2::Log();
use Apache2::ServerRec();
use CGI ':cgi-lib';
use CGI::Cookie;
my $html;
sub handler {
my $r = shift;
my $log = $r->log;
my $MyApplicationXmlFile = $r->dir_config('ConfigFile');
my $MyDomain = lc( $r->dir_config('Domain') );
my $Parameters =
Lemonldap::Config::Parameters->new( file => $MyApplicationXmlFile, );
my $Conf_Domain = $Parameters->getDomain($MyDomain);
my $Cookie_Name = $Conf_Domain->{Cookie};
my $page_html = $Conf_Domain->{LogoutCASPage};
##########################################################################
my $pathlemon = "/";
my $pathCookie = "/cas";
my $dotdomain = "." . $MyDomain;
$log->info( "Set-Cookie: -name => $Cookie_Name -value => -domain => "
. ".$dotdomain -path => $pathCookie" );
my $CASCookie = CGI::cookie(
-name => "CASTGC",
-value => 0,
-domain => $dotdomain,
-path => $pathCookie,
);
my $LemonCookie = CGI::cookie(
-name => $Cookie_Name,
-value => 0,
-domain => $dotdomain,
-path => $pathlemon,
);
##############################################
if ( !$html ) {
my $file;
open( $file, "<$page_html" );
local $/;
$/ = '';
$html = <$file>;
close $file;
}
$r->content_type('text/html');
# my $linecookie= "CASTGC=0;domain=$dotdomain;path=/cas/ ; $cookiename=0;
# $r->headers_out->{'Set-Cookie'}= [$LemonCookie,$CASCookie] ;
$r->headers_out->add( 'Set-Cookie' => $CASCookie );
$r->headers_out->add( 'Set-Cookie' => $LemonCookie );
$r->print;
$r->print($html);
return OK;
}
1;
package Lemonldap::Handlers::MemsessionCAS;
use strict;
use Apache::Session::Memorycached;
our ( @ISA, $VERSION, @EXPORTS );
$VERSION = '3.1.0';
our $VERSION_LEMONLDAP = "3.1.0";
our $VERSION_INTERNAL = "3.1.0";
sub get {
my $class = shift;
my %_param = @_;
my $id = $_param{'id'};
return 0 unless $id;