First CAS version : when CAS is enabled, login through CAS is mandatory
authorHenri-Damien LAURENT <henridamien.laurent@biblibre.com>
Mon, 23 Nov 2009 15:21:37 +0000 (16:21 +0100)
committerHenri-Damien LAURENT <henridamien.laurent@biblibre.com>
Mon, 23 Nov 2009 15:21:37 +0000 (16:21 +0100)
Conflicts solved C4/Auth.pm

C4/Auth.pm
C4/Auth_with_cas.pm [new file with mode: 0644]

index 4c4fcd6..e1d8003 100755 (executable)
@@ -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 (file)
index 0000000..694cbbb
--- /dev/null
@@ -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 <usecasserver>http://mycasserver/loginurl</usecasserver>
+
+=head1 SEE ALSO
+
+CGI(3)
+
+Authen::CAS::Client
+
+=cut