X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=C4%2FAuth_with_ldap.pm;h=3b40015343f2ba59ab557eb679fe98988cb16330;hb=6e21422d00f02c88384ce361dab86ccc44e92e49;hp=0d002187c1278656b0464f7fa76619e65df61476;hpb=bb4ab3ee765e5664f2d1645efd4b5e5e973a9d56;p=koha_fer
diff --git a/C4/Auth_with_ldap.pm b/C4/Auth_with_ldap.pm
index 0d002187c1..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;
@@ -47,7 +48,7 @@ BEGIN {
# ~ then gets the LDAP entry
# ~ and calls the memberadd if necessary
-sub ldapserver_error ($) {
+sub ldapserver_error {
return sprintf('No ldapserver "%s" defined in KOHA_CONF: ' . $ENV{KOHA_CONF}, shift);
}
@@ -70,8 +71,8 @@ my %config = (
update => defined($ldap->{update} ) ? $ldap->{update} : 1, # update from LDAP to Koha database for existing user
);
-sub description ($) {
- my $result = shift or return undef;
+sub description {
+ my $result = shift or return;
return "LDAP error #" . $result->code
. ": " . $result->error_name . "\n"
. "# " . $result->error_text . "\n";
@@ -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,27 +191,25 @@ sub checkpw_ldap {
} else {
return 0; # B2, D2
}
- if (C4::Context->preference('ExtendedPatronAttributes') && $borrowernumber && ($config{update} ||$config{replicate})) {
- my @types = C4::Members::AttributeTypes::GetAttributeTypes();
- my @attributes = grep{my $key=$_; any{$_ eq $key}@types;} keys %borrower;
- my $extended_patron_attributes;
- @{$extended_patron_attributes} =
- map { { code => $_, value => $borrower{$_} } } @attributes;
- 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);
- }
+ 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} };
+ }
+ }
+ #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);
}
@@ -197,19 +218,17 @@ return(1, $cardnumber, $userid);
# Edit KOHA_CONF so $memberhash{'xxx'} fits your ldap structure.
# Ensure that mandatory fields are correctly filled!
#
-sub ldap_entry_2_hash ($$) {
+sub ldap_entry_2_hash {
my $userldapentry = shift;
my %borrower = ( cardnumber => shift );
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 undef;
+ my $x = $userldapentry->{attrs} or return;
foreach (keys %$x) {
$memberhash{$_} = join ' ', @{$x->{$_}};
$debug and print STDERR sprintf("building \$memberhash{%s} = ", $_, join(' ', @{$x->{$_}})), "\n";
@@ -242,7 +261,7 @@ sub ldap_entry_2_hash ($$) {
return %borrower;
}
-sub exists_local($) {
+sub exists_local {
my $arg = shift;
my $dbh = C4::Context->dbh;
my $select = "SELECT borrowernumber,cardnumber,userid,password FROM borrowers ";
@@ -260,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 undef;
- }
- 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 undef;
- my $digest = md5_base64(shift) or return undef;
- my $borrowerid = shift or return undef;
- my $borrower = shift or return undef;
- 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)
- );
+sub update_local {
+ 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;
@@ -417,8 +435,12 @@ Example XML stanza for LDAP configuration in KOHA_CONF.
1
0
+ 0
%s@my_domain.com
-
+
+