[Koha-patches] [PATCH] Bug 6296: allow users to be authenticated by SSL client certs

Robin Sheat robin at catalyst.net.nz
Tue Jun 14 09:44:03 CEST 2011


This adds a new syspref: AllowPKIAuth. It can have one of three states:
* None
* Common Name
* emailAddress

If a) this is set to something that's not "None", and b) the webserver
is passing SSL client cert details on to Koha, then the relevant field
in the user's certificate will be matched up against the field in the
database and they will be automatically logged in. This is used as a
secure form of single sign-on in some organisations.

The "Common Name" field is matched up against the userid, while
"emailAddress" is matched against the primary email.

This is an example of what might go in the Apache configuration for the
virtual host:

    SSLVerifyClient require
    SSLVerifyDepth 2
    SSLCACertificateFile /etc/apache2/ssl/test/ca.crt
    SSLOptions +StdEnvVars

The last line ensures that the required details are passed to Koha.
---
 C4/Auth.pm                                         |  320 +++++++++++---------
 C4/Members.pm                                      |   29 ++
 acqui/finishreceive.pl                             |    4 +-
 catalogue/updateitem.pl                            |    4 +-
 installer/data/mysql/de-DE/mandatory/sysprefs.sql  |    3 +-
 installer/data/mysql/en/mandatory/sysprefs.sql     |    1 +
 .../1-Obligatoire/unimarc_standard_systemprefs.sql |    3 +-
 installer/data/mysql/it-IT/necessari/sysprefs.sql  |    1 +
 installer/data/mysql/pl-PL/mandatory/sysprefs.sql  |    3 +-
 ...m_preferences_full_optimal_for_install_only.sql |    3 +-
 ...m_preferences_full_optimal_for_install_only.sql |    1 +
 installer/data/mysql/updatedatabase.pl             |    9 +
 .../prog/en/modules/admin/preferences/admin.pref   |   11 +-
 members/setstatus.pl                               |    2 +-
 reserve/placerequest.pl                            |    2 +-
 serials/reorder_members.pl                         |    3 +-
 serials/subscription-detail.pl                     |    3 +-
 17 files changed, 245 insertions(+), 157 deletions(-)

diff --git a/C4/Auth.pm b/C4/Auth.pm
index b416449..a0212c9 100644
--- a/C4/Auth.pm
+++ b/C4/Auth.pm
@@ -147,6 +147,19 @@ sub get_template_and_user {
     my $borrowernumber;
     my $insecure = C4::Context->preference('insecure');
     if ($user or $insecure) {
+        # It's possible for $user to be the borrowernumber if they don't have a
+        # userid defined (and are logging in through some other method, such
+        # as SSL certs against an email address)
+        $borrowernumber = getborrowernumber($user) if defined($user);
+        if (!defined($borrowernumber) && defined($user)) {
+        	my $borrower = GetMember(borrowernumber => $user);
+        	if ($borrower) {
+            	$borrowernumber = $user;
+                # A bit of a hack, but I don't know there's a nicer way
+                # to do it.
+                $user = $borrower->{firstname} . ' ' . $borrower->{surname};
+            }
+        }
 
         # load the template variables for stylesheets and JavaScript
         $template->param( css_libs => $in->{'css_libs'} );
@@ -177,8 +190,6 @@ sub get_template_and_user {
             $template->param( bartotal  => $total->{'bartotal'}, ) if ($total->{'bartotal'} > scalar @{$barshelves});
         }
 
-        $borrowernumber = getborrowernumber($user) if defined($user);
-
         my ( $borr ) = GetMemberDetails( $borrowernumber );
         my @bordat;
         $bordat[0] = $borr;
@@ -722,154 +733,177 @@ sub checkauth {
     }
     unless ($userid || $sessionID) {
         #we initiate a session prior to checking for a username to allow for anonymous sessions...
-		my $session = get_session("") or die "Auth ERROR: Cannot get_session()";
+        my $session = get_session("") or die "Auth ERROR: Cannot get_session()";
         my $sessionID = $session->id;
-       	C4::Context->_new_userenv($sessionID);
+        C4::Context->_new_userenv($sessionID);
         $cookie = $query->cookie(CGISESSID => $sessionID);
-	    $userid    = $query->param('userid');
-    	    if ($cas || $userid) {
-        	my $password = $query->param('password');
-		my ($return, $cardnumber);
-		if ($cas && $query->param('ticket')) {
-		    my $retuserid;
-		    ( $return, $cardnumber, $retuserid ) = checkpw( $dbh, $userid, $password, $query );
-		    $userid = $retuserid;
-		    $info{'invalidCasLogin'} = 1 unless ($return);
-        	} else {
-		    my $retuserid;
-		    ( $return, $retuserid ) = checkpw( $dbh, $userid, $password, $query );
-		    $userid = $retuserid if ($retuserid ne '');
-		}
-		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);
-            	}
+        $userid    = $query->param('userid');
+        if ($cas || $userid ||
+        	(my $pki_field = C4::Context->preference('AllowPKIAuth')) ne 'None') {
+            my $password = $query->param('password');
+            my ($return, $cardnumber);
+            if ($cas && $query->param('ticket')) {
+                my $retuserid;
+                ( $return, $cardnumber, $retuserid ) = checkpw( $dbh, $userid, $password, $query );
+                $userid = $retuserid;
+                $info{'invalidCasLogin'} = 1 unless ($return);
+            } elsif (($pki_field eq 'Common Name' && $ENV{'SSL_CLIENT_S_DN_CN'}) ||
+                ($pki_field eq 'emailAddress' && $ENV{'SSL_CLIENT_S_DN_Email'})) {
+                my $value;
+                if ($pki_field eq 'Common Name') {
+                    $value = $ENV{'SSL_CLIENT_S_DN_CN'};
+                } elsif ($pki_field eq 'emailAddress') {
+                    $value = $ENV{'SSL_CLIENT_S_DN_Email'};
+                    # If we're looking up the email, there's a chance that the person
+                    # doesn't have a userid. So if there is none, we pass along the
+                    # borrower number, and the bits of code that need to know the user
+                    # ID will have to be smart enough to handle that.
+                    my @users_info = GetBorrowersWithEmail($value);
+                    if (@users_info) {
+                        # First the userid, then the borrowernum
+                        $value = $users_info[0][1] || $users_info[0][0];
+                    } else {
+                        undef $value;
+                    }
+                }
+                # 0 for no user, 1 for normal, 2 for demo user.
+                $return = $value ? 1 : 0;
+                $userid = $value;
+            } else {
+                my $retuserid;
+                ( $return, $retuserid ) = checkpw( $dbh, $userid, $password, $query );
+                $userid = $retuserid if ($retuserid ne '');
+            }
+            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);
+                }
 
-				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.
 
-					my $ip       = $ENV{'REMOTE_ADDR'};
-					# if they specify at login, use that
-					if ($query->param('branch')) {
-						$branchcode  = $query->param('branch');
-						$branchname = GetBranchName($branchcode);
-					}
-					my $branches = GetBranches();
-					if (C4::Context->boolean_preference('IndependantBranches') && C4::Context->boolean_preference('Autolocation')){
-						# we have to check they are coming from the right ip range
-						my $domain = $branches->{$branchcode}->{'branchip'};
-						if ($ip !~ /^$domain/){
-							$loggedin=0;
-							$info{'wrongip'} = 1;
-						}
-					}
-
-					my @branchesloop;
-					foreach my $br ( keys %$branches ) {
-						#     now we work with the treatment of ip
-						my $domain = $branches->{$br}->{'branchip'};
-						if ( $domain && $ip =~ /^$domain/ ) {
-							$branchcode = $branches->{$br}->{'branchcode'};
-
-							# new op dev : add the branchprinter and branchname in the cookie
-							$branchprinter = $branches->{$br}->{'branchprinter'};
-							$branchname    = $branches->{$br}->{'branchname'};
-						}
-					}
-					$session->param('number',$borrowernumber);
-					$session->param('id',$userid);
-					$session->param('cardnumber',$cardnumber);
-					$session->param('firstname',$firstname);
-					$session->param('surname',$surname);
-					$session->param('branch',$branchcode);
-					$session->param('branchname',$branchname);
-					$session->param('flags',$userflags);
-					$session->param('emailaddress',$emailaddress);
-					$session->param('ip',$session->remote_addr());
-					$session->param('lasttime',time());
-					$debug and printf STDERR "AUTH_4: (%s)\t%s %s - %s\n", map {$session->param($_)} qw(cardnumber firstname surname branch) ;
-				}
-				elsif ( $return == 2 ) {
-					#We suppose the user is the superlibrarian
-					$borrowernumber = 0;
-					$session->param('number',0);
-					$session->param('id',C4::Context->config('user'));
-					$session->param('cardnumber',C4::Context->config('user'));
-					$session->param('firstname',C4::Context->config('user'));
-					$session->param('surname',C4::Context->config('user'));
-					$session->param('branch','NO_LIBRARY_SET');
-					$session->param('branchname','NO_LIBRARY_SET');
-					$session->param('flags',1);
-					$session->param('emailaddress', C4::Context->preference('KohaAdminEmailAddress'));
-					$session->param('ip',$session->remote_addr());
-					$session->param('lasttime',time());
-				}
-				C4::Context::set_userenv(
-					$session->param('number'),       $session->param('id'),
-					$session->param('cardnumber'),   $session->param('firstname'),
-					$session->param('surname'),      $session->param('branch'),
-					$session->param('branchname'),   $session->param('flags'),
-					$session->param('emailaddress'), $session->param('branchprinter')
-				);
-
-				# Grab borrower's shelves and public shelves and add them to the session
-				# $row_count determines how many records are returned from the db query
-				# and the number of lists to be displayed of each type in the 'Lists' button drop down
-				my $row_count = 10; # FIXME:This probably should be a syspref
-				my ($total, $totshelves, $barshelves, $pubshelves);
-				($barshelves, $totshelves) = C4::VirtualShelves::GetRecentShelves(1, $row_count, $borrowernumber);
-				$total->{'bartotal'} = $totshelves;
-				($pubshelves, $totshelves) = C4::VirtualShelves::GetRecentShelves(2, $row_count, undef);
-				$total->{'pubtotal'} = $totshelves;
-				$session->param('barshelves', $barshelves);
-				$session->param('pubshelves', $pubshelves);
-				$session->param('totshelves', $total);
-
-				C4::Context::set_shelves_userenv('bar',$barshelves);
-				C4::Context::set_shelves_userenv('pub',$pubshelves);
-				C4::Context::set_shelves_userenv('tot',$total);
-			}
+                    my $ip       = $ENV{'REMOTE_ADDR'};
+                    # if they specify at login, use that
+                    if ($query->param('branch')) {
+                        $branchcode  = $query->param('branch');
+                        $branchname = GetBranchName($branchcode);
+                    }
+                    my $branches = GetBranches();
+                    if (C4::Context->boolean_preference('IndependantBranches') && C4::Context->boolean_preference('Autolocation')){
+                        # we have to check they are coming from the right ip range
+                        my $domain = $branches->{$branchcode}->{'branchip'};
+                        if ($ip !~ /^$domain/){
+                            $loggedin=0;
+                            $info{'wrongip'} = 1;
+                        }
+                    }
+
+                    my @branchesloop;
+                    foreach my $br ( keys %$branches ) {
+                        #     now we work with the treatment of ip
+                        my $domain = $branches->{$br}->{'branchip'};
+                        if ( $domain && $ip =~ /^$domain/ ) {
+                            $branchcode = $branches->{$br}->{'branchcode'};
+
+                            # new op dev : add the branchprinter and branchname in the cookie
+                            $branchprinter = $branches->{$br}->{'branchprinter'};
+                            $branchname    = $branches->{$br}->{'branchname'};
+                        }
+                    }
+                    $session->param('number',$borrowernumber);
+                    $session->param('id',$userid);
+                    $session->param('cardnumber',$cardnumber);
+                    $session->param('firstname',$firstname);
+                    $session->param('surname',$surname);
+                    $session->param('branch',$branchcode);
+                    $session->param('branchname',$branchname);
+                    $session->param('flags',$userflags);
+                    $session->param('emailaddress',$emailaddress);
+                    $session->param('ip',$session->remote_addr());
+                    $session->param('lasttime',time());
+                    $debug and printf STDERR "AUTH_4: (%s)\t%s %s - %s\n", map {$session->param($_)} qw(cardnumber firstname surname branch) ;
+                }
+                elsif ( $return == 2 ) {
+                    #We suppose the user is the superlibrarian
+                    $borrowernumber = 0;
+                    $session->param('number',0);
+                    $session->param('id',C4::Context->config('user'));
+                    $session->param('cardnumber',C4::Context->config('user'));
+                    $session->param('firstname',C4::Context->config('user'));
+                    $session->param('surname',C4::Context->config('user'));
+                    $session->param('branch','NO_LIBRARY_SET');
+                    $session->param('branchname','NO_LIBRARY_SET');
+                    $session->param('flags',1);
+                    $session->param('emailaddress', C4::Context->preference('KohaAdminEmailAddress'));
+                    $session->param('ip',$session->remote_addr());
+                    $session->param('lasttime',time());
+                }
+                C4::Context::set_userenv(
+                    $session->param('number'),       $session->param('id'),
+                    $session->param('cardnumber'),   $session->param('firstname'),
+                    $session->param('surname'),      $session->param('branch'),
+                    $session->param('branchname'),   $session->param('flags'),
+                    $session->param('emailaddress'), $session->param('branchprinter')
+                );
+
+                # Grab borrower's shelves and public shelves and add them to the session
+                # $row_count determines how many records are returned from the db query
+                # and the number of lists to be displayed of each type in the 'Lists' button drop down
+                my $row_count = 10; # FIXME:This probably should be a syspref
+                my ($total, $totshelves, $barshelves, $pubshelves);
+                ($barshelves, $totshelves) = C4::VirtualShelves::GetRecentShelves(1, $row_count, $borrowernumber);
+                $total->{'bartotal'} = $totshelves;
+                ($pubshelves, $totshelves) = C4::VirtualShelves::GetRecentShelves(2, $row_count, undef);
+                $total->{'pubtotal'} = $totshelves;
+                $session->param('barshelves', $barshelves);
+                $session->param('pubshelves', $pubshelves);
+                $session->param('totshelves', $total);
+
+                C4::Context::set_shelves_userenv('bar',$barshelves);
+                C4::Context::set_shelves_userenv('pub',$pubshelves);
+                C4::Context::set_shelves_userenv('tot',$total);
+            }
         	else {
             	if ($userid) {
                 	$info{'invalid_username_or_password'} = 1;
diff --git a/C4/Members.pm b/C4/Members.pm
index e03b40b..c9db1ae 100644
--- a/C4/Members.pm
+++ b/C4/Members.pm
@@ -91,6 +91,7 @@ BEGIN {
 		&DeleteMessage
 		&GetMessages
 		&GetMessagesCount
+		GetBorrowersWithEmail
 	);
 
 	#Modify data
@@ -2257,6 +2258,34 @@ sub DeleteMessage {
 
 }
 
+=head2 GetBorrowersWithEmail
+
+    ([$borrnum,$userid], ...) = GetBorrowersWithEmail('me at example.com');
+
+This gets a list of users and their basic details from their email address.
+As it's possible for multiple user to have the same email address, it provides
+you with all of them. If there is no userid for the user, there will be an
+C<undef> there. An empty list will be returned if there are no matches.
+
+=cut
+
+sub GetBorrowersWithEmail {
+    my $email = shift;
+
+    my $dbh = C4::Context->dbh;
+
+    my $query = "SELECT borrowernumber, userid FROM borrowers WHERE email=?";
+    my $sth=$dbh->prepare($query);
+    $sth->execute($email);
+    my @result = ();
+    while (my $ref = $sth->fetch) {
+        push @result, $ref;
+    }
+    die "Failure searching for borrowers by email address: $sth->errstr" if $sth->err;
+    return @result;
+}
+
+
 END { }    # module clean-up code here (global destructor)
 
 1;
diff --git a/acqui/finishreceive.pl b/acqui/finishreceive.pl
index 71b13d6..f8051ba 100755
--- a/acqui/finishreceive.pl
+++ b/acqui/finishreceive.pl
@@ -34,7 +34,9 @@ use List::MoreUtils qw/any/;
 
 my $input=new CGI;
 my $flagsrequired = {acquisition => 'order_receive'};
-my ($loggedinuser, $cookie, $sessionID) = checkauth($input, 0, $flagsrequired, 'intranet');
+
+checkauth($input, 0, $flagsrequired, 'intranet');
+
 my $user=$input->remote_user;
 my $biblionumber = $input->param('biblionumber');
 my $biblioitemnumber=$input->param('biblioitemnumber');
diff --git a/catalogue/updateitem.pl b/catalogue/updateitem.pl
index e8ce20d..50765b7 100755
--- a/catalogue/updateitem.pl
+++ b/catalogue/updateitem.pl
@@ -31,7 +31,7 @@ use C4::Reserves;
 
 my $cgi= new CGI;
 
-my ($loggedinuser, $cookie, $sessionID) = checkauth($cgi, 0, {circulate => 'circulate_remaining_permissions'}, 'intranet');
+checkauth($cgi, 0, {circulate => 'circulate_remaining_permissions'}, 'intranet');
 
 my $biblionumber=$cgi->param('biblionumber');
 my $itemnumber=$cgi->param('itemnumber');
@@ -57,7 +57,7 @@ for ($damaged,$itemlost,$wthdrawn) {
 # modify MARC item if input differs from items table.
 my $item_changes = {};
 if (defined $itemnotes) { # i.e., itemnotes parameter passed from form
-    my ($loggedinuser, $cookie, $sessionID) = checkauth($cgi, 0, {editcatalogue => 'edit_items'}, 'intranet');
+    checkauth($cgi, 0, {editcatalogue => 'edit_items'}, 'intranet');
     if ((not defined  $item_data_hashref->{'itemnotes'}) or $itemnotes ne $item_data_hashref->{'itemnotes'}) {
         $item_changes->{'itemnotes'} = $itemnotes;
     }
diff --git a/installer/data/mysql/de-DE/mandatory/sysprefs.sql b/installer/data/mysql/de-DE/mandatory/sysprefs.sql
index c7c885d..7c6d4bd 100755
--- a/installer/data/mysql/de-DE/mandatory/sysprefs.sql
+++ b/installer/data/mysql/de-DE/mandatory/sysprefs.sql
@@ -311,4 +311,5 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('AlternateHoldingsField','','The MARC field/subfield that contains alternate holdings information for bibs taht do not have items attached (e.g. 852abchi for libraries converting from MARC Magician).',NULL,'free');
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('AlternateHoldingsSeparator','','The string to use to separate subfields in alternate holdings displays.',NULL,'free');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacHiddenItems' ,'','This syspref allows to define custom rules for hiding specific items at opac. See docs/opac/O    pacHiddenItems.txt for more informations.','','Textarea');
-INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('numSearchRSSResults',50,'Specify the maximum number of results to display on a RSS page of results',NULL,'Integer');
\ No newline at end of file
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('numSearchRSSResults',50,'Specify the maximum number of results to display on a RSS page of results',NULL,'Integer');
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('AllowPKIAuth','None','Use the field from a client-side SSL certificate to look a user in the Koha database','None|Common Name|emailAddress','Choice');
diff --git a/installer/data/mysql/en/mandatory/sysprefs.sql b/installer/data/mysql/en/mandatory/sysprefs.sql
index f98b053..2fc0512 100755
--- a/installer/data/mysql/en/mandatory/sysprefs.sql
+++ b/installer/data/mysql/en/mandatory/sysprefs.sql
@@ -312,3 +312,4 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('AlternateHoldingsSeparator','','The string to use to separate subfields in alternate holdings displays.',NULL,'free');
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('OpacHiddenItems','','This syspref allows to define custom rules for hiding specific items at opac. See docs/opac/OpacHiddenItems.txt for more informations.','','Textarea');
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('numSearchRSSResults',50,'Specify the maximum number of results to display on a RSS page of results',NULL,'Integer');
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('AllowPKIAuth','None','Use the field from a client-side SSL certificate to look a user in the Koha database','None|Common Name|emailAddress','Choice');
diff --git a/installer/data/mysql/fr-FR/1-Obligatoire/unimarc_standard_systemprefs.sql b/installer/data/mysql/fr-FR/1-Obligatoire/unimarc_standard_systemprefs.sql
index 185c74b..0bf7f86 100755
--- a/installer/data/mysql/fr-FR/1-Obligatoire/unimarc_standard_systemprefs.sql
+++ b/installer/data/mysql/fr-FR/1-Obligatoire/unimarc_standard_systemprefs.sql
@@ -312,4 +312,5 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('AlternateHoldingsField','','The MARC field/subfield that contains alternate holdings information for bibs taht do not have items attached (e.g. 852abchi for libraries converting from MARC Magician).',NULL,'free');
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('AlternateHoldingsSeparator','','The string to use to separate subfields in alternate holdings displays.',NULL,'free');
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('OpacHiddenItems','','This syspref allows to define custom rules for hiding specific items at opac. See docs/opac/OpacHiddenItems.txt for more informations.','','Textarea');
-INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('numSearchRSSResults',50,'Specify the maximum number of results to display on a RSS page of results',NULL,'Integer');
\ No newline at end of file
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('numSearchRSSResults',50,'Specify the maximum number of results to display on a RSS page of results',NULL,'Integer');
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('AllowPKIAuth','None','Use the field from a client-side SSL certificate to look a user in the Koha database','None|Common Name|emailAddress','Choice');
diff --git a/installer/data/mysql/it-IT/necessari/sysprefs.sql b/installer/data/mysql/it-IT/necessari/sysprefs.sql
index fca0cfb..002a780 100755
--- a/installer/data/mysql/it-IT/necessari/sysprefs.sql
+++ b/installer/data/mysql/it-IT/necessari/sysprefs.sql
@@ -299,3 +299,4 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('AlternateHoldingsSeparator','','The string to use to separate subfields in alternate holdings displays.',NULL,'free');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacHiddenItems','','This syspref allows to define custom rules for hiding specific items at opac. See docs/opac/O    pacHiddenItems.txt for more informations.','','Textarea');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('numSearchRSSResults',50,'Specify the maximum number of results to display on a RSS page of results',NULL,'Integer');
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('AllowPKIAuth','None','Use the field from a client-side SSL certificate to look a user in the Koha database','None|Common Name|emailAddress','Choice');
diff --git a/installer/data/mysql/pl-PL/mandatory/sysprefs.sql b/installer/data/mysql/pl-PL/mandatory/sysprefs.sql
index c39e231..df13bcd 100755
--- a/installer/data/mysql/pl-PL/mandatory/sysprefs.sql
+++ b/installer/data/mysql/pl-PL/mandatory/sysprefs.sql
@@ -310,4 +310,5 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('AlternateHoldingsField','','The MARC field/subfield that contains alternate holdings information for bibs taht do not have items attached (e.g. 852abchi for libraries converting from MARC Magician).',NULL,'free');
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('AlternateHoldingsSeparator','','The string to use to separate subfields in alternate holdings displays.',NULL,'free');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacHiddenItems','','This syspref allows to define custom rules for hiding specific items at opac. See docs/opac/OpacHiddenItems.txt for more informations.','','Textarea');
-INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('numSearchRSSResults',50,'Specify the maximum number of results to display on a RSS page of results',NULL,'Integer');
\ No newline at end of file
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('numSearchRSSResults',50,'Specify the maximum number of results to display on a RSS page of results',NULL,'Integer');
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('AllowPKIAuth','None','Use the field from a client-side SSL certificate to look a user in the Koha database','None|Common Name|emailAddress','Choice');
diff --git a/installer/data/mysql/ru-RU/mandatory/system_preferences_full_optimal_for_install_only.sql b/installer/data/mysql/ru-RU/mandatory/system_preferences_full_optimal_for_install_only.sql
index a7c6a10..605dd47 100755
--- a/installer/data/mysql/ru-RU/mandatory/system_preferences_full_optimal_for_install_only.sql
+++ b/installer/data/mysql/ru-RU/mandatory/system_preferences_full_optimal_for_install_only.sql
@@ -365,4 +365,5 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('AlternateHoldingsField','','The MARC field/subfield that contains alternate holdings information for bibs taht do not have items attached (e.g. 852abchi for libraries converting from MARC Magician).',NULL,'free');
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('AlternateHoldingsSeparator','','The string to use to separate subfields in alternate holdings displays.',NULL,'free');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacHiddenItems','','This syspref allows to define custom rules for hiding specific items at opac. See docs/opac/OpacHiddenItems.txt for more informations.','','Textarea');
-INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('numSearchRSSResults',50,'Specify the maximum number of results to display on a RSS page of results',NULL,'Integer');
\ No newline at end of file
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('numSearchRSSResults',50,'Specify the maximum number of results to display on a RSS page of results',NULL,'Integer');
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('AllowPKIAuth','None','Use the field from a client-side SSL certificate to look a user in the Koha database','None|Common Name|emailAddress','Choice');
diff --git a/installer/data/mysql/uk-UA/mandatory/system_preferences_full_optimal_for_install_only.sql b/installer/data/mysql/uk-UA/mandatory/system_preferences_full_optimal_for_install_only.sql
index f370766..bfbd48c 100755
--- a/installer/data/mysql/uk-UA/mandatory/system_preferences_full_optimal_for_install_only.sql
+++ b/installer/data/mysql/uk-UA/mandatory/system_preferences_full_optimal_for_install_only.sql
@@ -391,3 +391,4 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('AlternateHoldingsSeparator','','The string to use to separate subfields in alternate holdings displays.',NULL,'free');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacHiddenItems','','This syspref allows to define custom rules for hiding specific items at opac. See docs/opac/O    pacHiddenItems.txt for more informations.','','Textarea');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('numSearchRSSResults',50,'Specify the maximum number of results to display on a RSS page of results',NULL,'Integer');
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('AllowPKIAuth','None','Use the field from a client-side SSL certificate to look a user in the Koha database','None|Common Name|emailAddress','Choice');
diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl
index 3c7d043..8e6fcde 100755
--- a/installer/data/mysql/updatedatabase.pl
+++ b/installer/data/mysql/updatedatabase.pl
@@ -4354,6 +4354,15 @@ if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
     SetVersion ($DBversion);
 }
 
+$DBversion = "3.04.01.001";
+if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
+    $dbh->do(qq{
+    INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('AllowPKIAuth',0,'This allows the user to authenticate via client side certificates',NULL,'YesNo');
+    });
+    print "Upgrade to $DBversion done (Bug 6296 New System preference AllowPKIAuth)\n";
+    SetVersion($DBversion);
+}
+
 =head1 FUNCTIONS
 
 =head2 DropAllForeignKeys($table)
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref
index a2ecc5c..85fd549 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref
@@ -94,4 +94,13 @@ Administration:
             - of CAS when logging out of Koha.
         -
             - The CAS Authentication Server can be found at
-            - pref: casServerUrl           
+            - pref: casServerUrl
+        -
+            - Use
+            - pref: AllowPkiAuth
+              default: None
+              choices:
+                  None: "no"
+                  Common Name: the Common Name
+                  emailAddress: the emailAddress
+            - field for SSL client certificate authentication
diff --git a/members/setstatus.pl b/members/setstatus.pl
index addeeb3..88825b6 100755
--- a/members/setstatus.pl
+++ b/members/setstatus.pl
@@ -36,7 +36,7 @@ my $input = new CGI;
 
 my $flagsrequired;
 $flagsrequired->{borrowers}=1;
-my ($loggedinuser, $cookie, $sessionID) = checkauth($input, 0, $flagsrequired);
+checkauth($input, 0, $flagsrequired);
 
 my $destination = $input->param("destination") || '';
 my $cardnumber = $input->param("cardnumber");
diff --git a/reserve/placerequest.pl b/reserve/placerequest.pl
index bc3fc74..d14c0a4 100755
--- a/reserve/placerequest.pl
+++ b/reserve/placerequest.pl
@@ -35,7 +35,7 @@ use C4::Auth qw/checkauth/;
 
 my $input = CGI->new();
 
-my ($user, $cookie, $sesion_id, $flags) = checkauth($input, 0, { reserveforothers => 'place_holds' }, 'intranet');
+checkauth($input, 0, { reserveforothers => 'place_holds' }, 'intranet');
 
 my @bibitems=$input->param('biblioitem');
 # FIXME I think reqbib does not exist anymore, it's used in line 82, to AddReserve of contraint type 'o'
diff --git a/serials/reorder_members.pl b/serials/reorder_members.pl
index 28175fb..8b64fc7 100755
--- a/serials/reorder_members.pl
+++ b/serials/reorder_members.pl
@@ -29,8 +29,7 @@ my $subscriptionid = $query->param('subscriptionid');
 my $routingid      = $query->param('routingid');
 my $rank           = $query->param('rank');
 
-my ( $user, $cookie, $sesion_id, $flags ) =
-  checkauth( $query, 0, { serials => 1 }, 'intranet' );
+checkauth( $query, 0, { serials => 1 }, 'intranet' );
 
 reorder_members( $subscriptionid, $routingid, $rank );
 
diff --git a/serials/subscription-detail.pl b/serials/subscription-detail.pl
index 7386820..ebb47ad 100755
--- a/serials/subscription-detail.pl
+++ b/serials/subscription-detail.pl
@@ -94,8 +94,7 @@ if ($op eq 'del') {
 }
 my $hasRouting = check_routing($subscriptionid);
 
-my ($user, $sessionID, $flags);
-($user, $cookie, $sessionID, $flags)
+(undef, $cookie, undef, undef)
     = checkauth($query, 0, {catalogue => 1}, "intranet");
 
 # COMMENT hdl : IMHO, we should think about passing more and more data hash to template->param rather than duplicating code a new coding Guideline ?
-- 
1.7.4.1



More information about the Koha-patches mailing list