Manage CAS service validate URL (#101)

This commit is contained in:
Clément Oudot 2010-08-26 12:24:38 +00:00
parent cf282a3c25
commit b721763e23
2 changed files with 211 additions and 11 deletions

View File

@ -175,6 +175,112 @@ sub issuerForUnAuthUser {
return PE_ERROR;
}
# 4. SERVICE VALIDATE [CAS 2.0]
if ( $url =~ /\Q$cas_serviceValidate_url\E/io ) {
$self->lmLog( "URL $url detected as an CAS SERVICE VALIDATE URL",
'debug' );
# GET parameters
my $service = $self->param('service');
my $ticket = $self->param('ticket');
my $pgtUrl = $self->param('pgtUrl');
my $renew = $self->param('renew');
# Required parameters: service and ticket
unless ( $service and $ticket ) {
$self->lmLog( "Service and Ticket parameters required", 'error' );
$self->returnCasServiceValidateError( 'INVALID_REQUEST',
'Missing mandatory parameters (service, ticket)' );
}
$self->lmLog(
"Get service validate request with ticket $ticket for service $service",
'debug'
);
# Get CAS session corresponding to ticket
unless ( $ticket =~ s/^ST-// ) {
$self->lmLog( "Provided ticket is not a service ticket (ST)",
'error' );
$self->returnCasServiceValidateError( 'INVALID_TICKET',
'Provided ticket is not a service ticket' );
}
my $casServiceSession = $self->getCasSession($ticket);
unless ($casServiceSession) {
$self->lmLog( "Service ticket session $ticket not found", 'error' );
$self->returnCasServiceValidateError( 'INVALID_TICKET',
'Ticket not found' );
}
$self->lmLog( "Service ticket session $ticket found", 'debug' );
# Check service
unless ( $service eq $casServiceSession->{service} ) {
$self->lmLog(
"Submitted service $service does not match initial service "
. $casServiceSession->{service},
'error'
);
# CAS protocol: invalidate ticket if service is invalid
$self->deleteCasSession($casServiceSession);
$self->returnCasServiceValidateError( 'INVALID_SERVICE',
'Submitted service does not match initial service' );
}
$self->lmLog( "Submitted service $service match initial servce",
'debug' );
# Check renew
if ( $renew eq 'true' ) {
# We should check the ST was delivered with primary credentials
# TODO
$self->lmLog( "Renew parameter not managed", 'warn' );
}
# Proxy granting ticket
if ($pgtUrl) {
# Request pgtUrl
# TODO
$self->lmLog( "PgtUrl parameter not managed", 'warn' );
}
# Open local session
my $localSession =
$self->getApacheSession( $casServiceSession->{_cas_id}, 1 );
unless ($localSession) {
$self->lmLog(
"Local session " . $casServiceSession->{_cas_id} . " notfound",
'error'
);
untie %$casServiceSession;
$self->returnCasServiceValidateError( 'INTERNAL_ERROR',
'No session associated to ticket' );
}
# Get username
my $username = $localSession->{ $self->{whatToTrace} };
$self->lmLog( "Get username $username", 'debug' );
# Close sessions
untie %$casServiceSession;
untie %$localSession;
# Return success message
$self->returnCasServiceValidateSuccess($username);
# We should not be there
return PE_ERROR;
}
return PE_OK;
}
@ -306,6 +412,21 @@ sub issuerForAuthUser {
return PE_OK;
}
# 4. SERVICE VALIDATE [CAS 2.0]
if ( $url =~ /\Q$cas_serviceValidate_url\E/io ) {
$self->lmLog( "URL $url detected as an CAS SERVICE VALIDATE URL",
'debug' );
# This URL must not be called by authenticated users
$self->lmLog(
"CAS SERVICE VALIDATE URL called by authenticated user, ignore it",
'info'
);
return PE_OK;
}
return PE_OK;
}

View File

@ -41,6 +41,8 @@ sub getCasSession {
sub returnCasValidateError {
my ($self) = splice @_;
$self->lmLog( "Return CAS validate error", 'debug' );
print $self->header();
print "no\n\n";
@ -54,12 +56,58 @@ sub returnCasValidateError {
sub returnCasValidateSuccess {
my ( $self, $username ) = splice @_;
$self->lmLog( "Return CAS validate success with username $username",
'debug' );
print $self->header();
print "yes\n$username\n";
$self->quit();
}
## @method void returnCasServiceValidateError(string code, string text)
# Return an error for CAS SERVICE VALIDATE request
# @param code CAS error code
# @param text Error text
# @return nothing
sub returnCasServiceValidateError {
my ( $self, $code, $text ) = splice @_;
$code ||= 'INTERNAL_ERROR';
$text ||= 'No description provided';
$self->lmLog( "Return CAS service validate error $code ($text)", 'debug' );
print $self->header( -type => 'application/xml' );
print "<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>\n";
print "\t<cas:authenticationFailure code=\"$code\">\n";
print "\t\t$text\n";
print "\t</cas:authenticationFailure>\n";
print "</cas:serviceResponse>\n";
$self->quit();
}
## @method void returnCasServiceValidateSuccess(string username)
# Return success for CAS SERVICE VALIDATE request
# @param username User name
# @return nothing
sub returnCasServiceValidateSuccess {
my ( $self, $username ) = splice @_;
$self->lmLog( "Return CAS service validate success with username $username",
'debug' );
print $self->header( -type => 'application/xml' );
print "<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>\n";
print "\t<cas:authenticationSuccess>\n";
print "\t\t<cas:user>$username</cas:user>\n";
print "\t</cas:authenticationSuccess>\n";
print "</cas:serviceResponse>\n";
$self->quit();
}
## @method boolean deleteCasSecondarySessions(string session_id)
# Find and delete CAS sessions bounded to a primary session
# @param session_id Primary session ID
@ -83,17 +131,7 @@ sub deleteCasSecondarySessions {
my $casSessionInfo = $self->getCasSession($cas_session);
# Delete session
eval { tied(%$casSessionInfo)->delete() };
if ($@) {
$self->lmLog( "Unable to delete CAS session $cas_session: $@",
'error' );
$result = 0;
}
else {
$self->lmLog( "CAS session $cas_session deleted", 'debug' );
}
$result = $self->deleteCasSession($casSessionInfo);
}
}
else {
@ -105,6 +143,35 @@ sub deleteCasSecondarySessions {
}
## @method boolean deleteCasSession(hashref session)
# Delete an opened CAS session
# @param session Tied session object
# @return result
sub deleteCasSession {
my ( $self, $session ) = splice @_;
# Check session object
unless ( ref($session) eq 'HASH' ) {
$self->lmLog( "Provided session is not a HASH reference", 'error' );
return 0;
}
# Get session_id
my $session_id = $session->{_session_id};
# Delete session
eval { tied(%$session)->delete() };
if ($@) {
$self->lmLog( "Unable to delete CAS session $session_id: $@", 'error' );
return 0;
}
$self->lmLog( "CAS session $session_id deleted", 'debug' );
return 1;
}
1;
__END__
@ -142,6 +209,18 @@ Return success for CAS VALIDATE request
Find and delete CAS sessions bounded to a primary session
=head2 returnCasServiceValidateError
Return an error for CAS SERVICE VALIDATE request
=head2 returnCasServiceValidateSuccess
Return success for CAS SERVICE VALIDATE request
=head2 deleteCasSession
Delete an opened CAS session
=head1 SEE ALSO
L<Lemonldap::NG::Portal::IssuerDBCAS>