Revision 48c71a4b
Von Moritz Bunkus vor mehr als 5 Jahren hinzugefügt
SL/Auth.pm | ||
---|---|---|
5 | 5 |
use Digest::MD5 qw(md5_hex); |
6 | 6 |
use IO::File; |
7 | 7 |
use Time::HiRes qw(gettimeofday); |
8 |
use List::MoreUtils qw(uniq); |
|
8 |
use List::MoreUtils qw(any uniq);
|
|
9 | 9 |
use YAML; |
10 | 10 |
use Regexp::IPv6 qw($IPv6_re); |
11 | 11 |
|
... | ... | |
72 | 72 |
delete $self->{column_information}; |
73 | 73 |
} |
74 | 74 |
|
75 |
$self->{authenticator}->reset;
|
|
75 |
$_->reset for @{ $self->{authenticators} };
|
|
76 | 76 |
|
77 | 77 |
$self->client(undef); |
78 | 78 |
} |
... | ... | |
145 | 145 |
$self->{DB_config} = $::lx_office_conf{'authentication/database'}; |
146 | 146 |
} |
147 | 147 |
|
148 |
if ($self->{module} eq 'DB') { |
|
149 |
$self->{authenticator} = SL::Auth::DB->new($self); |
|
148 |
$self->{authenticators} = []; |
|
149 |
$self->{module} ||= 'DB'; |
|
150 |
$self->{module} =~ s{^ +| +$}{}g; |
|
150 | 151 |
|
151 |
} elsif ($self->{module} eq 'LDAP') { |
|
152 |
$self->{authenticator} = SL::Auth::LDAP->new($::lx_office_conf{'authentication/ldap'}); |
|
153 |
} |
|
152 |
foreach my $module (split m{ +}, $self->{module}) { |
|
153 |
my $config_name; |
|
154 |
($module, $config_name) = split m{:}, $module, 2; |
|
155 |
$config_name ||= $module eq 'DB' ? 'database' : lc($module); |
|
156 |
my $config = $::lx_office_conf{'authentication/' . $config_name}; |
|
154 | 157 |
|
155 |
if (!$self->{authenticator}) { |
|
156 |
my $locale = Locale->new('en'); |
|
157 |
$self->mini_error($locale->text('No or an unknown authenticantion module specified in "config/kivitendo.conf".')); |
|
158 |
if (!$config) { |
|
159 |
my $locale = Locale->new('en'); |
|
160 |
$self->mini_error($locale->text('Missing configuration section "authentication/#1" in "config/kivitendo.conf".', $config_name)); |
|
161 |
} |
|
162 |
|
|
163 |
if ($module eq 'DB') { |
|
164 |
push @{ $self->{authenticators} }, SL::Auth::DB->new($self); |
|
165 |
|
|
166 |
} elsif ($module eq 'LDAP') { |
|
167 |
push @{ $self->{authenticators} }, SL::Auth::LDAP->new($config); |
|
168 |
|
|
169 |
} else { |
|
170 |
my $locale = Locale->new('en'); |
|
171 |
$self->mini_error($locale->text('Unknown authenticantion module #1 specified in "config/kivitendo.conf".', $module)); |
|
172 |
} |
|
158 | 173 |
} |
159 | 174 |
|
160 | 175 |
my $cfg = $self->{DB_config}; |
... | ... | |
169 | 184 |
$self->mini_error($locale->text('config/kivitendo.conf: Missing parameters in "authentication/database". Required parameters are "host", "db" and "user".')); |
170 | 185 |
} |
171 | 186 |
|
172 |
$self->{authenticator}->verify_config();
|
|
187 |
$_->verify_config for @{ $self->{authenticators} };
|
|
173 | 188 |
|
174 | 189 |
$self->{session_timeout} *= 1; |
175 | 190 |
$self->{session_timeout} = 8 * 60 if (!$self->{session_timeout}); |
... | ... | |
229 | 244 |
return ERR_PASSWORD; |
230 | 245 |
} |
231 | 246 |
|
232 |
my $result = $login ? $self->{authenticator}->authenticate($login, $password) : ERR_USER; |
|
247 |
my $result = ERR_USER; |
|
248 |
if ($login) { |
|
249 |
foreach my $authenticator (@{ $self->{authenticators} }) { |
|
250 |
$result = $authenticator->authenticate($login, $password); |
|
251 |
last if $result == OK; |
|
252 |
} |
|
253 |
} |
|
254 |
|
|
233 | 255 |
$self->set_session_value(SESSION_KEY_USER_AUTH() => $result, login => $login, client_id => $self->client->{id}); |
234 | 256 |
return $result; |
235 | 257 |
} |
... | ... | |
414 | 436 |
sub can_change_password { |
415 | 437 |
my $self = shift; |
416 | 438 |
|
417 |
return $self->{authenticator}->can_change_password();
|
|
439 |
return any { $_->can_change_password } @{ $self->{authenticators} };
|
|
418 | 440 |
} |
419 | 441 |
|
420 | 442 |
sub change_password { |
421 | 443 |
my ($self, $login, $new_password) = @_; |
422 | 444 |
|
423 |
my $result = $self->{authenticator}->change_password($login, $new_password);
|
|
445 |
my $overall_result = OK;
|
|
424 | 446 |
|
425 |
return $result; |
|
447 |
foreach my $authenticator (@{ $self->{authenticators} }) { |
|
448 |
next unless $authenticator->can_change_password; |
|
449 |
|
|
450 |
my $result = $authenticator->change_password($login, $new_password); |
|
451 |
$overall_result = $result if $result != OK; |
|
452 |
} |
|
453 |
|
|
454 |
return $overall_result; |
|
426 | 455 |
} |
427 | 456 |
|
428 | 457 |
sub read_all_users { |
SL/Auth/LDAP.pm | ||
---|---|---|
32 | 32 |
|
33 | 33 |
return $self->{ldap} if $self->{ldap}; |
34 | 34 |
|
35 |
my $port = $cfg->{port} || 389;
|
|
36 |
$self->{ldap} = Net::LDAP->new($cfg->{host}, 'port' => $port);
|
|
35 |
my $port = $cfg->{port} || 389; |
|
36 |
my $ldap = Net::LDAP->new($cfg->{host}, port => $port, timeout => $cfg->{timeout} || 10);
|
|
37 | 37 |
|
38 |
if (!$self->{ldap}) { |
|
39 |
$main::form->error($main::locale->text('The LDAP server "#1:#2" is unreachable. Please check config/kivitendo.conf.', $cfg->{host}, $port)); |
|
38 |
if (!$ldap) { |
|
39 |
$::lxdebug->warn($main::locale->text('The LDAP server "#1:#2" is unreachable. Please check config/kivitendo.conf.', $cfg->{host}, $port)); |
|
40 |
return undef; |
|
40 | 41 |
} |
41 | 42 |
|
42 | 43 |
if ($cfg->{tls}) { |
43 |
my $mesg = $self->{ldap}->start_tls('verify' => 'none');
|
|
44 |
my $mesg = $ldap->start_tls(verify => $cfg->{verify} // 'require');
|
|
44 | 45 |
if ($mesg->is_error()) { |
45 |
$main::form->error($main::locale->text('The connection to the LDAP server cannot be encrypted (SSL/TLS startup failure). Please check config/kivitendo.conf.')); |
|
46 |
$::lxdebug->warn($main::locale->text('The connection to the LDAP server cannot be encrypted (SSL/TLS startup failure). Please check config/kivitendo.conf.')); |
|
47 |
return undef; |
|
46 | 48 |
} |
47 | 49 |
} |
48 | 50 |
|
49 | 51 |
if ($cfg->{bind_dn}) { |
50 |
my $mesg = $self->{ldap}->bind($cfg->{bind_dn}, 'password' => $cfg->{bind_password});
|
|
52 |
my $mesg = $ldap->bind($cfg->{bind_dn}, 'password' => $cfg->{bind_password});
|
|
51 | 53 |
if ($mesg->is_error()) { |
52 |
$main::form->error($main::locale->text('Binding to the LDAP server as "#1" failed. Please check config/kivitendo.conf.', $cfg->{bind_dn})); |
|
54 |
$::lxdebug->warn($main::locale->text('Binding to the LDAP server as "#1" failed. Please check config/kivitendo.conf.', $cfg->{bind_dn})); |
|
55 |
return undef; |
|
53 | 56 |
} |
54 | 57 |
} |
55 | 58 |
|
59 |
$self->{ldap} = $ldap; |
|
60 |
|
|
56 | 61 |
return $self->{ldap}; |
57 | 62 |
} |
58 | 63 |
|
config/kivitendo.conf.default | ||
---|---|---|
4 | 4 |
# interface. |
5 | 5 |
admin_password = admin123 |
6 | 6 |
|
7 |
# Which module to use for authentication. Valid values are 'DB' and |
|
8 |
# 'LDAP'. If 'LDAP' is used then users cannot change their password |
|
9 |
# via kivitendo. |
|
7 |
# Which modules to use for authentication. Valid values are 'DB' and |
|
8 |
# 'LDAP'. You can use multiple modules separated by spaces. |
|
9 |
# |
|
10 |
# Multiple LDAP modules with different configurations can be used by |
|
11 |
# postfixing 'LDAP' with the name of the configuration section to use: |
|
12 |
# 'LDAP:ldap_fallback' would use the data from |
|
13 |
# '[authentication/ldap_fallback]'. The name defaults to 'ldap' if it |
|
14 |
# isn't given. |
|
15 |
# |
|
16 |
# Note that the LDAP module doesn't support changing the password. |
|
10 | 17 |
module = DB |
11 | 18 |
|
12 | 19 |
# The cookie name can be changed if desired. |
... | ... | |
43 | 50 |
# specified. |
44 | 51 |
# |
45 | 52 |
# tls: Activate encryption via TLS |
53 |
# verify: If 'tls' is used, how to verify the server's certificate. |
|
54 |
# Can be one of 'require' or 'none'. |
|
46 | 55 |
# attribute: Name of the LDAP attribute containing the user's login name |
47 | 56 |
# base_dn: Base DN the LDAP searches start from |
48 | 57 |
# filter: An optional LDAP filter specification. The string '<%login%>' |
... | ... | |
51 | 60 |
# If searching the LDAP tree requires user credentials |
52 | 61 |
# (e.g. ActiveDirectory) then these two parameters specify |
53 | 62 |
# the user name and password to use. |
63 |
# timeout: Timeout when connecting to the server in seconds. |
|
64 |
# |
|
65 |
# You can specify a fallback LDAP server to use in case the main one |
|
66 |
# isn't reachable by duplicating this whole section as |
|
67 |
# "[authentication/ldap_fallback]". |
|
68 |
# |
|
54 | 69 |
host = localhost |
55 | 70 |
port = 389 |
56 | 71 |
tls = 0 |
... | ... | |
59 | 74 |
filter = |
60 | 75 |
bind_dn = |
61 | 76 |
bind_password = |
77 |
timeout = 10 |
|
78 |
verify = require |
|
62 | 79 |
|
63 | 80 |
[system] |
64 | 81 |
# Set language for login and admin forms. Currently "de" (German) |
locale/de/all | ||
---|---|---|
1907 | 1907 |
'Missing Method!' => 'Fehlender Voranmeldungszeitraum', |
1908 | 1908 |
'Missing Tax Authoritys Preferences' => 'Fehlende Angaben zum Finanzamt!', |
1909 | 1909 |
'Missing amount' => 'Fehlbetrag', |
1910 |
'Missing configuration section "authentication/#1" in "config/kivitendo.conf".' => 'Fehlender Konfigurationsabschnitt "authentication/#1" in "config/kivitendo.conf".', |
|
1910 | 1911 |
'Missing parameter #1 in call to sub #2.' => 'Fehlender Parameter \'#1\' in Funktionsaufruf \'#2\'.', |
1911 | 1912 |
'Missing parameter (at least one of #1) in call to sub #2.' => 'Fehlernder Parameter (mindestens einer aus \'#1\') in Funktionsaufruf \'#2\'.', |
1912 | 1913 |
'Missing parameter for WebDAV file copy' => 'Fehlender Parameter für WebDAV Datei kopieren', |
... | ... | |
2018 | 2019 |
'No groups have been created yet.' => 'Es wurden noch keine Gruppen angelegt.', |
2019 | 2020 |
'No internal phone extensions have been configured yet.' => 'Es wurden noch keine internen Durchwahlen konfiguriert.', |
2020 | 2021 |
'No invoices have been selected.' => 'Es wurden keine Rechnungen ausgewählt.', |
2021 |
'No or an unknown authenticantion module specified in "config/kivitendo.conf".' => 'Es wurde kein oder ein unbekanntes Authentifizierungsmodul in "config/kivitendo.conf" angegeben.', |
|
2022 | 2022 |
'No part was selected.' => 'Es wurde kein Artikel ausgewählt', |
2023 | 2023 |
'No payment term has been created yet.' => 'Es wurden noch keine Zahlungsbedingungen angelegt.', |
2024 | 2024 |
'No picture has been uploaded' => 'Es wurde kein Bild hochgeladen', |
... | ... | |
3711 | 3711 |
'Units that have already been used (e.g. for parts and services or in invoices or warehouse transactions) cannot be changed.' => 'Einheiten, die bereits in Benutzung sind (z.B. bei einer Warendefinition, einer Rechnung oder bei einer Lagerbuchung) können nachträglich nicht mehr verändert werden.', |
3712 | 3712 |
'Unknown Category' => 'Unbekannte Kategorie', |
3713 | 3713 |
'Unknown Link' => 'Unbekannte Verknüpfung', |
3714 |
'Unknown authenticantion module #1 specified in "config/kivitendo.conf".' => 'Unbekanntes Authentifizierungsmodul #1 angegeben in "config/kivitendo.conf".', |
|
3714 | 3715 |
'Unknown control fields: #1' => 'Unbekannte Kontrollfelder: #1', |
3715 | 3716 |
'Unknown dependency \'%s\'.' => 'Unbekannte Abhängigkeit \'%s\'.', |
3716 | 3717 |
'Unknown module: #1' => 'Unbekanntes Modul #1', |
Auch abrufbar als: Unified diff
Auth: Unterstützung für multiple Authentifizierungsbackends
Über den Parameter "module" kann man nun multiple Backends angeben,
die nacheinander versucht werden, bis ein Erfolg gemeldet wird oder
die Liste durchlaufen wurde.
Zusätzlich kann man LDAP-Module mehrfach angeben. Damit
unterschiedliche Konfigurationen für jede Modulinstanz benutzt werden
können, wurde die Syntax erweitert: für "LDAP:Config-Abschnitts-Name"
wird "[authentication/Config-Abschnitts-Name]" benutzt. Zwecks
Rückwärtskompatibilität sucht "LDAP" ohne Angabe eines Namens nach dem
bisher auch verwendeten Abschnitt "[authentication/ldap]".
Nützlich ist das Ganze z.B., um einen LDAP-Fallback-Server angeben zu
können, der benutzt wird, wenn der Hauptserver nicht erreichbar sein
sollte.