X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=C4%2FAuth_with_ldap.pm;h=3b40015343f2ba59ab557eb679fe98988cb16330;hb=568f32606c2c9c247b2b477193a2d6814f738fa6;hp=f3c1f7f39dd006298cc25f69e746f5eec8361748;hpb=e93cc449410f6c8d90b616f3d8e002e9ade4dadd;p=koha.git diff --git a/C4/Auth_with_ldap.pm b/C4/Auth_with_ldap.pm index f3c1f7f39d..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,32 +104,54 @@ sub checkpw_ldap { my ($dbh, $userid, $password) = @_; my @hosts = split(',', $prefhost); my $db = Net::LDAP->new(\@hosts); + unless ( $db ) { + warn "LDAP connexion failed"; + return 0; + } + #$debug and $db->debug(5); my $userldapentry; - if ( $ldap->{auth_by_bind} ) { - my $principal_name = $ldap->{principal_name}; - if ($principal_name and $principal_name =~ /\%/) { - $principal_name = sprintf($principal_name,$userid); - } else { - $principal_name = $userid; + + 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; } - my $res = $db->bind( $principal_name, password => $password ); + else { + $principal_name = $ldap->{principal_name}; + if ( $principal_name and $principal_name =~ /\%/ ) { + $principal_name = sprintf( $principal_name, $userid ); + } + else { + $principal_name = $userid; + } + } + + # Perform a LDAP bind for the given username using the matched DN + my $res = $db->bind( $principal_name, password => $password ); if ( $res->code ) { - $debug and warn "LDAP bind failed as kohauser $principal_name: ". description($res); + warn "LDAP bind failed as kohauser $userid: " . description($res); return 0; } - - # FIXME dpavlin -- we really need $userldapentry leater on even if using auth_by_bind! - - # BUG #5094 - # 2010-08-04 JeremyC - # a $userldapentry is only needed if either updating or replicating are enabled - if($config{update} or $config{replicate}) { - my $search = search_method($db, $userid) or return 0; # warnings are in the sub - $userldapentry = $search->shift_entry; - } - - } else { + 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); @@ -168,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); } @@ -205,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; @@ -262,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; @@ -419,8 +435,12 @@ Example XML stanza for LDAP configuration in KOHA_CONF. 1 0 + 0 %s@my_domain.com - + +