Projekt

Allgemein

Profil

Herunterladen (3,93 KB) Statistiken
| Zweig: | Markierung: | Revision:
8c7e4493 Moritz Bunkus
package SL::Auth::LDAP;

use English '-no_match_vars';

5d23fb60 Sven Schöling
use SL::Auth::Constants qw(:all);
8c7e4493 Moritz Bunkus
c510d88b Sven Schöling
use strict;

8c7e4493 Moritz Bunkus
sub new {
if (!defined eval "require Net::LDAP;") {
die 'The module "Net::LDAP" is not installed.';
}

211f4e60 Moritz Bunkus
my $type = shift;
my $self = {};
$self->{config} = shift;
8c7e4493 Moritz Bunkus
bless $self, $type;

return $self;
}

72887d24 Sven Schöling
sub reset {
my ($self) = @_;
$self->{ldap} = undef;
$self->{dn_cache} = { };
}

8c7e4493 Moritz Bunkus
sub _connect {
my $self = shift;
211f4e60 Moritz Bunkus
my $cfg = $self->{config};
8c7e4493 Moritz Bunkus
64c14bc5 Moritz Bunkus
return $self->{ldap} if $self->{ldap};
8c7e4493 Moritz Bunkus
48c71a4b Moritz Bunkus
my $port = $cfg->{port} || 389;
my $ldap = Net::LDAP->new($cfg->{host}, port => $port, timeout => $cfg->{timeout} || 10);
8c7e4493 Moritz Bunkus
48c71a4b Moritz Bunkus
if (!$ldap) {
$::lxdebug->warn($main::locale->text('The LDAP server "#1:#2" is unreachable. Please check config/kivitendo.conf.', $cfg->{host}, $port));
return undef;
8c7e4493 Moritz Bunkus
}

if ($cfg->{tls}) {
48c71a4b Moritz Bunkus
my $mesg = $ldap->start_tls(verify => $cfg->{verify} // 'require');
8c7e4493 Moritz Bunkus
if ($mesg->is_error()) {
48c71a4b Moritz Bunkus
$::lxdebug->warn($main::locale->text('The connection to the LDAP server cannot be encrypted (SSL/TLS startup failure). Please check config/kivitendo.conf.'));
return undef;
8c7e4493 Moritz Bunkus
}
}

if ($cfg->{bind_dn}) {
48c71a4b Moritz Bunkus
my $mesg = $ldap->bind($cfg->{bind_dn}, 'password' => $cfg->{bind_password});
8c7e4493 Moritz Bunkus
if ($mesg->is_error()) {
48c71a4b Moritz Bunkus
$::lxdebug->warn($main::locale->text('Binding to the LDAP server as "#1" failed. Please check config/kivitendo.conf.', $cfg->{bind_dn}));
return undef;
8c7e4493 Moritz Bunkus
}
}

48c71a4b Moritz Bunkus
$self->{ldap} = $ldap;

8c7e4493 Moritz Bunkus
return $self->{ldap};
}

sub _get_filter {
my $self = shift;
my $login = shift;

my ($cfg, $filter);

211f4e60 Moritz Bunkus
$cfg = $self->{config};
8c7e4493 Moritz Bunkus
$filter = "$cfg->{filter}";
$filter =~ s|^\s+||;
$filter =~ s|\s+$||;

$login =~ s|\\|\\\\|g;
$login =~ s|\(|\\\(|g;
$login =~ s|\)|\\\)|g;
$login =~ s|\*|\\\*|g;
$login =~ s|\x00|\\00|g;

if ($filter =~ m|<\%login\%>|) {
substr($filter, $LAST_MATCH_START[0], $LAST_MATCH_END[0] - $LAST_MATCH_START[0]) = $login;

} elsif ($filter) {
if ((substr($filter, 0, 1) ne '(') || (substr($filter, -1, 1) ne ')')) {
$filter = "($filter)";
}

$filter = "(&${filter}($cfg->{attribute}=${login}))";

} else {
$filter = "$cfg->{attribute}=${login}";

}

return $filter;
}

sub _get_user_dn {
my $self = shift;
my $ldap = shift;
my $login = shift;

$self->{dn_cache} ||= { };

64c14bc5 Moritz Bunkus
return $self->{dn_cache}->{$login} if $self->{dn_cache}->{$login};
8c7e4493 Moritz Bunkus
211f4e60 Moritz Bunkus
my $cfg = $self->{config};
8c7e4493 Moritz Bunkus
my $filter = $self->_get_filter($login);

my $mesg = $ldap->search('base' => $cfg->{base_dn}, 'scope' => 'sub', 'filter' => $filter);

64c14bc5 Moritz Bunkus
return undef if $mesg->is_error || !$mesg->count();
8c7e4493 Moritz Bunkus
my $entry = $mesg->entry(0);
$self->{dn_cache}->{$login} = $entry->dn();

return $self->{dn_cache}->{$login};
}

sub authenticate {
my $self = shift;
my $login = shift;
my $password = shift;
my $is_crypted = shift;

64c14bc5 Moritz Bunkus
return ERR_BACKEND if $is_crypted;
8c7e4493 Moritz Bunkus
my $ldap = $self->_connect();

64c14bc5 Moritz Bunkus
return ERR_BACKEND if !$ldap;
8c7e4493 Moritz Bunkus
my $dn = $self->_get_user_dn($ldap, $login);

c510d88b Sven Schöling
$main::lxdebug->message(LXDebug->DEBUG2(), "LDAP authenticate: dn $dn");
8c7e4493 Moritz Bunkus
64c14bc5 Moritz Bunkus
return ERR_BACKEND if !$dn;
8c7e4493 Moritz Bunkus
my $mesg = $ldap->bind($dn, 'password' => $password);

c510d88b Sven Schöling
$main::lxdebug->message(LXDebug->DEBUG2(), "LDAP authenticate: bind mesg " . $mesg->error());
8c7e4493 Moritz Bunkus
5d23fb60 Sven Schöling
return $mesg->is_error() ? ERR_PASSWORD : OK;
8c7e4493 Moritz Bunkus
}

sub can_change_password {
return 0;
}

d0c2cfbe Moritz Bunkus
sub requires_cleartext_password {
return 1;
}

8c7e4493 Moritz Bunkus
sub change_password {
5d23fb60 Sven Schöling
return ERR_BACKEND;
8c7e4493 Moritz Bunkus
}

sub verify_config {
c510d88b Sven Schöling
my $form = $main::form;
my $locale = $main::locale;

8c7e4493 Moritz Bunkus
my $self = shift;
211f4e60 Moritz Bunkus
my $cfg = $self->{config};
8c7e4493 Moritz Bunkus
if (!$cfg) {
4bacfb02 Moritz Bunkus
$form->error($locale->text('config/kivitendo.conf: Key "authentication/ldap" is missing.'));
8c7e4493 Moritz Bunkus
}

if (!$cfg->{host} || !$cfg->{attribute} || !$cfg->{base_dn}) {
4bacfb02 Moritz Bunkus
$form->error($locale->text('config/kivitendo.conf: Missing parameters in "authentication/ldap". Required parameters are "host", "attribute" and "base_dn".'));
8c7e4493 Moritz Bunkus
}
}

1;