From 7126496210aff74692c8cee9ae5a029c81163a5a Mon Sep 17 00:00:00 2001 From: Henri-Damien LAURENT Date: Mon, 23 Nov 2009 16:21:37 +0100 Subject: [PATCH] First CAS version : when CAS is enabled, login through CAS is mandatory Conflicts solved C4/Auth.pm --- C4/Auth.pm | 142 ++++++++++++++++++++++++++++---------------- C4/Auth_with_cas.pm | 119 +++++++++++++++++++++++++++++++++++++ 2 files changed, 209 insertions(+), 52 deletions(-) create mode 100644 C4/Auth_with_cas.pm diff --git a/C4/Auth.pm b/C4/Auth.pm index 4c4fcd661a..e1d8003ec6 100755 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -33,20 +33,26 @@ use C4::VirtualShelves; use POSIX qw/strftime/; # use utf8; -use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug $ldap); +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug $ldap $cas); BEGIN { $VERSION = 3.02; # set version for version checking - $debug = $ENV{DEBUG} || 0 ; + $debug = $ENV{DEBUG} || 1 ; # Changed @ISA = qw(Exporter); @EXPORT = qw(&checkauth &get_template_and_user &haspermission &get_user_subpermissions); @EXPORT_OK = qw(&check_api_auth &get_session &check_cookie_auth &checkpw &get_all_subpermissions &get_user_subpermissions); %EXPORT_TAGS = (EditPermissions => [qw(get_all_subpermissions get_user_subpermissions)]); $ldap = C4::Context->config('useldapserver') || 0; + $cas = C4::Context->config('usecasserver') || 0; if ($ldap) { require C4::Auth_with_ldap; # no import import C4::Auth_with_ldap qw(checkpw_ldap); } + if ($cas) { + require C4::Auth_with_cas; # no import + import C4::Auth_with_cas qw(checkpw_cas login_cas logout_cas); + } + } =head1 NAME @@ -615,7 +621,6 @@ sub checkauth { $userid = $session->param('id'); $sessiontype = $session->param('sessiontype'); } - if ( ($query->param('koha_login_context')) && ($query->param('userid') ne $session->param('id')) ) { #if a user enters an id ne to the id in the current session, we need to log them in... #first we need to clear the anonymous session... @@ -634,6 +639,12 @@ sub checkauth { _session_log(sprintf "%20s from %16s logged out at %30s (manually).\n", $userid,$ip,(strftime "%c",localtime)); $sessionID = undef; $userid = undef; + + if ($cas) { + warn "Here we cas logout the user"; + # Add a syspref here + logout_cas($query); + } } elsif ( $lasttime < time() - $timeout ) { # timed logout @@ -674,53 +685,63 @@ sub checkauth { my $sessionID = $session->id; C4::Context->_new_userenv($sessionID); $cookie = $query->cookie(CGISESSID => $sessionID); - if ( $userid = $query->param('userid') ) { - my $password = $query->param('password'); - my ( $return, $cardnumber ) = checkpw( $dbh, $userid, $password ); - if ($return) { - _session_log(sprintf "%20s from %16s logged in at %30s.\n", $userid,$ENV{'REMOTE_ADDR'},(strftime "%c",localtime)); - if ( $flags = haspermission($userid, $flagsrequired) ) { - $loggedin = 1; - } - else { - $info{'nopermission'} = 1; - C4::Context->_unset_userenv($sessionID); - } + if ($cas && !$query->param('ticket')) { + login_cas($query); + } + if ($cas || ($userid = $query->param('userid')) ) { + my $password = $query->param('password'); + my ($return, $cardnumber); + if ($cas) { + my $retuserid; + ( $return, $cardnumber, $retuserid ) = checkpw( $dbh, $userid, $password, $query ); + $userid = $retuserid; + } else { + ( $return, $cardnumber ) = checkpw( $dbh, $userid, $password, $query ); + } + if ($return) { + _session_log(sprintf "%20s from %16s logged in at %30s.\n", $userid,$ENV{'REMOTE_ADDR'},localtime); + if ( $flags = haspermission( $dbh, $userid, $flagsrequired ) ) { + $loggedin = 1; + } + else { + $info{'nopermission'} = 1; + C4::Context->_unset_userenv($sessionID); + } - my ($borrowernumber, $firstname, $surname, $userflags, - $branchcode, $branchname, $branchprinter, $emailaddress); - - if ( $return == 1 ) { - my $select = " - SELECT borrowernumber, firstname, surname, flags, borrowers.branchcode, - branches.branchname as branchname, - branches.branchprinter as branchprinter, - email - FROM borrowers - LEFT JOIN branches on borrowers.branchcode=branches.branchcode - "; - my $sth = $dbh->prepare("$select where userid=?"); - $sth->execute($userid); - unless ($sth->rows) { - $debug and print STDERR "AUTH_1: no rows for userid='$userid'\n"; - $sth = $dbh->prepare("$select where cardnumber=?"); - $sth->execute($cardnumber); - unless ($sth->rows) { - $debug and print STDERR "AUTH_2a: no rows for cardnumber='$cardnumber'\n"; - $sth->execute($userid); - unless ($sth->rows) { - $debug and print STDERR "AUTH_2b: no rows for userid='$userid' AS cardnumber\n"; - } - } - } - if ($sth->rows) { - ($borrowernumber, $firstname, $surname, $userflags, - $branchcode, $branchname, $branchprinter, $emailaddress) = $sth->fetchrow; - $debug and print STDERR "AUTH_3 results: " . - "$cardnumber,$borrowernumber,$userid,$firstname,$surname,$userflags,$branchcode,$emailaddress\n"; - } else { - print STDERR "AUTH_3: no results for userid='$userid', cardnumber='$cardnumber'.\n"; - } + my ($borrowernumber, $firstname, $surname, $userflags, + $branchcode, $branchname, $branchprinter, $emailaddress); + + if ( $return == 1 ) { + my $select = " + SELECT borrowernumber, firstname, surname, flags, borrowers.branchcode, + branches.branchname as branchname, + branches.branchprinter as branchprinter, + email + FROM borrowers + LEFT JOIN branches on borrowers.branchcode=branches.branchcode + "; + my $sth = $dbh->prepare("$select where userid=?"); + $sth->execute($userid); + unless ($sth->rows) { + $debug and print STDERR "AUTH_1: no rows for userid='$userid'\n"; + $sth = $dbh->prepare("$select where cardnumber=?"); + $sth->execute($cardnumber); + unless ($sth->rows) { + $debug and print STDERR "AUTH_2a: no rows for cardnumber='$cardnumber'\n"; + $sth->execute($userid); + unless ($sth->rows) { + $debug and print STDERR "AUTH_2b: no rows for userid='$userid' AS cardnumber\n"; + } + } + } + if ($sth->rows) { + ($borrowernumber, $firstname, $surname, $userflags, + $branchcode, $branchname, $branchprinter, $emailaddress) = $sth->fetchrow; + $debug and print STDERR "AUTH_3 results: " . + "$cardnumber,$borrowernumber,$userid,$firstname,$surname,$userflags,$branchcode,$emailaddress\n"; + } else { + print STDERR "AUTH_3: no results for userid='$userid', cardnumber='$cardnumber'.\n"; + } # launch a sequence to check if we have a ip for the branch, i # if we have one we replace the branchcode of the userenv by the branch bound in the ip. @@ -1046,8 +1067,15 @@ sub check_api_auth { # caller did something wrong, fail the authenticateion return ("failed", undef, undef); } - my ( $return, $cardnumber ) = checkpw( $dbh, $userid, $password ); - if ($return and haspermission($userid, $flagsrequired)) { + my ($return, $cardnumber); + if ($cas) { + my $retuserid; + ( $return, $cardnumber, $retuserid ) = checkpw( $dbh, $userid, $password, $query ); + $userid = $retuserid; + } else { + ( $return, $cardnumber ) = checkpw( $dbh, $userid, $password, $query ); + } + if ($return and haspermission( $dbh, $userid, $flagsrequired)) { my $session = get_session(""); return ("failed", undef, undef) unless $session; @@ -1293,13 +1321,23 @@ sub get_session { sub checkpw { - my ( $dbh, $userid, $password ) = @_; + my ( $dbh, $userid, $password, $query ) = @_; if ($ldap) { $debug and print "## checkpw - checking LDAP\n"; my ($retval,$retcard) = checkpw_ldap(@_); # EXTERNAL AUTH ($retval) and return ($retval,$retcard); } + if ($cas) { + $debug and print STDERR "## checkpw - checking CAS\n"; + # In case of a CAS authentication, we use the ticket instead of the password + my $ticket = $query->param('ticket'); + warn ("ticket : $ticket"); + my ($retval,$retcard,$retuserid) = checkpw_cas($dbh, $ticket, $query); # EXTERNAL AUTH + warn "retval : $retval $retcard"; + ($retval) and return ($retval,$retcard,$retuserid); + } + # INTERNAL AUTH my $sth = $dbh->prepare( diff --git a/C4/Auth_with_cas.pm b/C4/Auth_with_cas.pm new file mode 100644 index 0000000000..694cbbbe3c --- /dev/null +++ b/C4/Auth_with_cas.pm @@ -0,0 +1,119 @@ +package C4::Auth_with_cas; + +# Copyright 2009 BibLibre SARL +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA + +use strict; + +use C4::Debug; +use C4::Context; +use C4::Utils qw( :all ); +use Authen::CAS::Client; +use CGI; + + +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug); + +BEGIN { + require Exporter; + $VERSION = 3.03; # set the version for version checking + @ISA = qw(Exporter); + @EXPORT = qw( checkpw_cas login_cas logout_cas ); +} + + +my $context = C4::Context->new() or die 'C4::Context->new failed'; +my $casserver = C4::Context->config("usecasserver") or die 'No "usecasserver" in KOHA_CONF: ' . $ENV{KOHA_CONF}; + +sub logout_cas { + my ($query) = @_; + my $cas = Authen::CAS::Client->new($casserver); + warn $cas->logout_url(); + print $query->redirect($cas->logout_url()); + +} + +sub login_cas { + my ($query) = @_; + my $cas = Authen::CAS::Client->new($casserver); + warn $cas->login_url(%ENV->{'SCRIPT_URI'}); + print $query->redirect($cas->login_url(%ENV->{'SCRIPT_URI'})); +} + +sub checkpw_cas { + warn "checkpw_cas"; + my ($dbh, $ticket, $query) = @_; + my $retnumber; + my $cas = Authen::CAS::Client->new($casserver); + + if ($ticket) { + warn "Got ticket : $ticket"; + my $val = $cas->service_validate(%ENV->{'SCRIPT_URI'}, $ticket); + if( $val->is_success() ) { + + my $userid = $val->user(); + warn "User authenticated as: $userid"; + + my $sth = $dbh->prepare("select cardnumber from borrowers where userid=?"); + $sth->execute($userid); + if ( $sth->rows ) { + $retnumber = $sth->fetchrow; + } + my $sth = $dbh->prepare("select userid from borrowers where cardnumber=?"); + $sth->execute($userid); + if ( $sth->rows ) { + $retnumber = $sth->fetchrow; + } + return (1, $retnumber, $userid); + } else { + warn "Invalid session ticket"; + return 0; + } + + } else { + warn ("Don't have any ticket, let's go get one from the CAS server!"); + my $url = $cas->login_url(%ENV->{'SCRIPT_URI'}); + print $query->redirect($url); + } + + warn "We should not reach this point"; + return 0; + #return(1, $retnumber); +} + +1; +__END__ + +=head1 NAME + +C4::Auth - Authenticates Koha users + +=head1 SYNOPSIS + + use C4::Auth_with_cas; + +=cut + +=head1 KOHA_CONF http://mycasserver/loginurl + +=head1 SEE ALSO + +CGI(3) + +Authen::CAS::Client + +=cut -- 2.20.1