X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=C4%2FAuth_with_ldap.pm;h=03e81e1c67709bc0b47a661e3b5d317e7300c396;hb=e1775fe1d5ffae3411d64c4d69fca75ad5641293;hp=b42506dfbe6d3b75b4f91e430988d054468da217;hpb=c9351807e9c4d46662257b85f106877e1198c542;p=koha.git diff --git a/C4/Auth_with_ldap.pm b/C4/Auth_with_ldap.pm index b42506dfbe..03e81e1c67 100644 --- a/C4/Auth_with_ldap.pm +++ b/C4/Auth_with_ldap.pm @@ -4,18 +4,18 @@ package C4::Auth_with_ldap; # # 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 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 3 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. +# 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., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . use strict; #use warnings; FIXME - Bug 2505 @@ -23,21 +23,21 @@ use Carp; use C4::Debug; use C4::Context; -use C4::Members qw(AddMember changepassword); +use C4::Members qw(AddMember); use C4::Members::Attributes; use C4::Members::AttributeTypes; use C4::Members::Messaging; use C4::Auth qw(checkpw_internal); +use Koha::Patrons; use Koha::AuthUtils qw(hash_password); use List::MoreUtils qw( any ); use Net::LDAP; use Net::LDAP::Filter; -use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug); +use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug); BEGIN { require Exporter; - $VERSION = 3.07.00.049; # set the version for version checking @ISA = qw(Exporter); @EXPORT = qw( checkpw_ldap ); } @@ -66,6 +66,15 @@ $debug and print STDERR "Got ", scalar(@mapkeys), " ldap mapkeys ( total ): ", @mapkeys = grep {defined $mapping{$_}->{is}} @mapkeys; $debug and print STDERR "Got ", scalar(@mapkeys), " ldap mapkeys (populated): ", join ' ', @mapkeys, "\n"; +my %categorycode_conversions; +my $default_categorycode; +if(defined $ldap->{categorycode_mapping}) { + $default_categorycode = $ldap->{categorycode_mapping}->{default}; + foreach my $cat (@{$ldap->{categorycode_mapping}->{categorycode}}) { + $categorycode_conversions{$cat->{value}} = $cat->{content}; + } +} + my %config = ( anonymous => ($ldapname and $ldappassword) ? 0 : 1, replicate => defined($ldap->{replicate}) ? $ldap->{replicate} : 1, # add from LDAP to Koha database for new user @@ -145,8 +154,19 @@ sub checkpw_ldap { # Perform a LDAP bind for the given username using the matched DN my $res = $db->bind( $principal_name, password => $password ); if ( $res->code ) { - warn "LDAP bind failed as kohauser $userid: " . description($res); - return -1; + if ( $ldap->{anonymous_bind} ) { + # With anonymous_bind approach we can be sure we have found the correct user + # and that any 'code' response indicates a 'bad' user (be that blocked, banned + # or password changed). We should not fall back to local accounts in this case. + warn "LDAP bind failed as kohauser $userid: " . description($res); + return -1; + } else { + # Without a anonymous_bind, we cannot be sure we are looking at a valid ldap user + # at all, and thus we should fall back to local logins to restore previous behaviour + # see bug 12831 + warn "LDAP bind failed as kohauser $userid: " . description($res); + return 0; + } } if ( !defined($userldapentry) && ( $config{update} or $config{replicate} ) ) @@ -196,25 +216,19 @@ sub checkpw_ldap { return 0; # B2, D2 } if (C4::Context->preference('ExtendedPatronAttributes') && $borrowernumber && ($config{update} ||$config{replicate})) { - my @extended_patron_attributes; foreach my $attribute_type ( C4::Members::AttributeTypes::GetAttributeTypes() ) { my $code = $attribute_type->{code}; - if ( exists($borrower{$code}) && $borrower{$code} !~ m/^\s*$/ ) { # skip empty values - push @extended_patron_attributes, { code => $code, value => $borrower{$code} }; + unless (exists($borrower{$code}) && $borrower{$code} !~ m/^\s*$/ ) { + next; } - } - #Check before add - my @unique_attr; - foreach my $attr ( @extended_patron_attributes ) { - if (C4::Members::Attributes::CheckUniqueness($attr->{code}, $attr->{value}, $borrowernumber)) { - push @unique_attr, $attr; + if (C4::Members::Attributes::CheckUniqueness($code, $borrower{$code}, $borrowernumber)) { + C4::Members::Attributes::UpdateBorrowerAttribute($borrowernumber, {code => $code, value => $borrower{$code}}); } else { - warn "ERROR_extended_unique_id_failed $attr->{code} $attr->{value}"; + warn "ERROR_extended_unique_id_failed $code $borrower{$code}"; } } - C4::Members::Attributes::SetBorrowerAttributes($borrowernumber, \@unique_attr); } -return(1, $cardnumber, $userid); + return(1, $cardnumber, $userid); } # Pass LDAP entry object and local cardnumber (userid). @@ -252,6 +266,14 @@ sub ldap_entry_2_hash { . substr($borrower{ 'surname' },0,1) . " "); + # categorycode conversions + if(defined $categorycode_conversions{$borrower{categorycode}}) { + $borrower{categorycode} = $categorycode_conversions{$borrower{categorycode}}; + } + elsif($default_categorycode) { + $borrower{categorycode} = $default_categorycode; + } + # check if categorycode exists, if not, fallback to default from koha-conf.xml my $dbh = C4::Context->dbh; my $sth = $dbh->prepare("SELECT categorycode FROM categories WHERE categorycode = ?"); @@ -282,13 +304,38 @@ sub exists_local { return 0; } +# This function performs a password update, given the userid, borrowerid, +# and digested password. It will verify that things are correct and return the +# borrowers cardnumber. The idea is that it is used to keep the local +# passwords in sync with the LDAP passwords. +# +# $cardnum = _do_changepassword($userid, $borrowerid, $digest) +# +# Note: if the LDAP config has the update_password tag set to a false value, +# then this will not update the password, it will simply return the cardnumber. sub _do_changepassword { my ($userid, $borrowerid, $password) = @_; + if ( exists( $ldap->{update_password} ) && !$ldap->{update_password} ) { + + # We don't store the password in the database + my $sth = C4::Context->dbh->prepare( + 'SELECT cardnumber FROM borrowers WHERE borrowernumber=?'); + $sth->execute($borrowerid); + die "Unable to access borrowernumber " + . "with userid=$userid, " + . "borrowernumber=$borrowerid" + if !$sth->rows; + my ($cardnum) = $sth->fetchrow; + $sth = C4::Context->dbh->prepare( + 'UPDATE borrowers SET password = null WHERE borrowernumber=?'); + $sth->execute($borrowerid); + return $cardnum; + } my $digest = hash_password($password); $debug and print STDERR "changing local password for borrowernumber=$borrowerid to '$digest'\n"; - changepassword($userid, $borrowerid, $digest); + Koha::Patrons->find($borrowerid)->update_password( $userid, $digest ); my ($ok, $cardnum) = checkpw_internal(C4::Context->dbh, $userid, $password); return $cardnum if $ok; @@ -444,7 +491,8 @@ Example XML stanza for LDAP configuration in KOHA_CONF. %s@my_domain.com - + 1 @@ -502,6 +550,14 @@ attribute that the server allows to be used for binding could be used. Currently, principal_name only operates when auth_by_bind is enabled. +=head2 update_password + +If this tag is left out or set to a true value, then the user's LDAP password +will be stored (hashed) in the local Koha database. If you don't want this +to happen, then set the value of this to '0'. Note that if passwords are not +stored locally, and the connection to the LDAP system fails, then the users +will not be able to log in at all. + =head2 Active Directory The auth_by_bind and principal_name settings are recommended for Active Directory.