X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=C4%2FAuth_with_ldap.pm;h=3b40015343f2ba59ab557eb679fe98988cb16330;hb=568f32606c2c9c247b2b477193a2d6814f738fa6;hp=1f2f617d6a1b8271a9abd093df8e55229823f3a1;hpb=961b9ef8c560353dc2bbc4b8a902e8de4904ca06;p=koha.git diff --git a/C4/Auth_with_ldap.pm b/C4/Auth_with_ldap.pm index 1f2f617d6a..3b40015343 100644 --- a/C4/Auth_with_ldap.pm +++ b/C4/Auth_with_ldap.pm @@ -19,14 +19,15 @@ package C4::Auth_with_ldap; use strict; #use warnings; FIXME - Bug 2505 -use Digest::MD5 qw(md5_base64); +use Carp; use C4::Debug; use C4::Context; use C4::Members qw(AddMember changepassword); use C4::Members::Attributes; use C4::Members::AttributeTypes; -use C4::Utils qw( :all ); +use C4::Auth qw(checkpw_internal); +use Koha::AuthUtils qw(hash_password); use List::MoreUtils qw( any ); use Net::LDAP; use Net::LDAP::Filter; @@ -103,29 +104,54 @@ sub checkpw_ldap { my ($dbh, $userid, $password) = @_; my @hosts = split(',', $prefhost); my $db = Net::LDAP->new(\@hosts); - #$debug and $db->debug(5); - my $userldapentry; - - if ( $ldap->{auth_by_bind} ) { - # Perform an anonymous bind - my $res = $db->bind; - if ( $res->code ) { - $debug and warn "Anonymous LDAP bind failed: ". description($res); - return 0; + unless ( $db ) { + warn "LDAP connexion failed"; + return 0; } - # Perform a LDAP search for the given username - my $search = search_method($db, $userid) or return 0; # warnings are in the sub - $userldapentry = $search->shift_entry; + #$debug and $db->debug(5); + my $userldapentry; - # Perform a LDAP bind for the given username using the matched DN - $res = $db->bind( $userldapentry->dn, password => $password ); - if ( $res->code ) { - $debug and warn "LDAP bind failed as kohauser $userid: ". description($res); - return 0; - } + if ( $ldap->{auth_by_bind} ) { + my $principal_name; + if ( $ldap->{anonymous_bind} ) { + + # Perform an anonymous bind + my $res = $db->bind; + if ( $res->code ) { + warn "Anonymous LDAP bind failed: " . description($res); + return 0; + } + + # Perform a LDAP search for the given username + my $search = search_method( $db, $userid ) + or return 0; # warnings are in the sub + $userldapentry = $search->shift_entry; + $principal_name = $userldapentry->dn; + } + else { + $principal_name = $ldap->{principal_name}; + if ( $principal_name and $principal_name =~ /\%/ ) { + $principal_name = sprintf( $principal_name, $userid ); + } + else { + $principal_name = $userid; + } + } - } else { + # 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 0; + } + if ( !defined($userldapentry) + && ( $config{update} or $config{replicate} ) ) + { + my $search = search_method( $db, $userid ) or return 0; + $userldapentry = $search->shift_entry; + } + } else { my $res = ($config{anonymous}) ? $db->bind : $db->bind($ldapname, password=>$ldappassword); if ($res->code) { # connection refused warn "LDAP bind failed as ldapuser " . ($ldapname || '[ANONYMOUS]') . ": " . description($res); @@ -165,29 +191,25 @@ sub checkpw_ldap { } else { return 0; # B2, D2 } - if (C4::Context->preference('ExtendedPatronAttributes') && $borrowernumber && ($config{update} ||$config{replicate})) { - my $extended_patron_attributes; + 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} }; - } + 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} }; + } } - my @errors; - #Check before add - for (my $i; $i< scalar(@$extended_patron_attributes)-1;$i++) { - my $attr=$extended_patron_attributes->[$i]; - unless (C4::Members::Attributes::CheckUniqueness($attr->{code}, $attr->{value}, $borrowernumber)) { - unshift @errors, $i; - warn "ERROR_extended_unique_id_failed $attr->{code} $attr->{value}"; - } - } - #Removing erroneous attributes - foreach my $index (@errors){ - @$extended_patron_attributes=splice(@$extended_patron_attributes,$index,1); - } - C4::Members::Attributes::SetBorrowerAttributes($borrowernumber, $extended_patron_attributes); - } + #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; + } else { + warn "ERROR_extended_unique_id_failed $attr->{code} $attr->{value}"; + } + } + C4::Members::Attributes::SetBorrowerAttributes($borrowernumber, \@unique_attr); + } return(1, $cardnumber, $userid); } @@ -202,10 +224,8 @@ sub ldap_entry_2_hash { my %memberhash; $userldapentry->exists('uid'); # This is bad, but required! By side-effect, this initializes the attrs hash. if ($debug) { - print STDERR "\nkeys(\%\$userldapentry) = " . join(', ', keys %$userldapentry), "\n", $userldapentry->dump(); foreach (keys %$userldapentry) { print STDERR "\n\nLDAP key: $_\t", sprintf('(%s)', ref $userldapentry->{$_}), "\n"; - hashdump("LDAP key: ",$userldapentry->{$_}); } } my $x = $userldapentry->{attrs} or return; @@ -259,44 +279,43 @@ sub exists_local { } sub _do_changepassword { - my ($userid, $borrowerid, $digest) = @_; + my ($userid, $borrowerid, $password) = @_; + + my $digest = hash_password($password); + $debug and print STDERR "changing local password for borrowernumber=$borrowerid to '$digest'\n"; changepassword($userid, $borrowerid, $digest); - # Confirm changes - my $sth = C4::Context->dbh->prepare("SELECT password,cardnumber FROM borrowers WHERE borrowernumber=? "); - $sth->execute($borrowerid); - if ($sth->rows) { - my ($md5password, $cardnum) = $sth->fetchrow; - ($digest eq $md5password) and return $cardnum; - warn "Password mismatch after update to cardnumber=$cardnum (borrowernumber=$borrowerid)"; - return; - } - die "Unexpected error after password update to userid/borrowernumber: $userid / $borrowerid."; + my ($ok, $cardnum) = checkpw_internal(C4::Context->dbh, $userid, $password); + return $cardnum if $ok; + + warn "Password mismatch after update to borrowernumber=$borrowerid"; + return; } sub update_local { - my $userid = shift or return; - my $digest = md5_base64(shift) or return; - my $borrowerid = shift or return; - my $borrower = shift or return; - my @keys = keys %$borrower; - my $dbh = C4::Context->dbh; - my $query = "UPDATE borrowers\nSET " . - join(',', map {"$_=?"} @keys) . - "\nWHERE borrowernumber=? "; - my $sth = $dbh->prepare($query); - if ($debug) { - print STDERR $query, "\n", - join "\n", map {"$_ = '" . $borrower->{$_} . "'"} @keys; - print STDERR "\nuserid = $userid\n"; - } - $sth->execute( - ((map {$borrower->{$_}} @keys), $borrowerid) - ); + my $userid = shift or croak "No userid"; + my $password = shift or croak "No password"; + my $borrowerid = shift or croak "No borrowerid"; + my $borrower = shift or croak "No borrower record"; + + my @keys = keys %$borrower; + my $dbh = C4::Context->dbh; + my $query = "UPDATE borrowers\nSET " . + join(',', map {"$_=?"} @keys) . + "\nWHERE borrowernumber=? "; + my $sth = $dbh->prepare($query); + if ($debug) { + print STDERR $query, "\n", + join "\n", map {"$_ = '" . $borrower->{$_} . "'"} @keys; + print STDERR "\nuserid = $userid\n"; + } + $sth->execute( + ((map {$borrower->{$_}} @keys), $borrowerid) + ); - # MODIFY PASSWORD/LOGIN - _do_changepassword($userid, $borrowerid, $digest); + # MODIFY PASSWORD/LOGIN + _do_changepassword($userid, $borrowerid, $password); } 1; @@ -416,6 +435,12 @@ Example XML stanza for LDAP configuration in KOHA_CONF. 1 0 + 0 + %s@my_domain.com + +