From: Moritz Bunkus Date: Thu, 16 Jun 2011 08:27:25 +0000 (+0200) Subject: Merge branch 'no-cleartext-passwords-in-db' X-Git-Tag: release-2.7.0beta1~394 X-Git-Url: http://wagnertech.de/gitweb/gitweb.cgi/mfinanz.git/commitdiff_plain/1c385c602908735c3be266b1470b301050650fd3?hp=1d69ac97a6ccc808e72e951495e4dfa728ca832e Merge branch 'no-cleartext-passwords-in-db' --- diff --git a/SL/Auth.pm b/SL/Auth.pm index 784b185b4..5f3c65dd8 100644 --- a/SL/Auth.pm +++ b/SL/Auth.pm @@ -11,6 +11,7 @@ use YAML; use SL::Auth::Constants qw(:all); use SL::Auth::DB; use SL::Auth::LDAP; +use SL::Auth::Password; use SL::SessionFile; use SL::User; @@ -136,12 +137,10 @@ sub _read_auth_config { sub authenticate_root { $main::lxdebug->enter_sub(); - my $self = shift; - my $password = shift; - my $is_crypted = shift; + my ($self, $password) = @_; - $password = crypt $password, 'ro' if (!$password || !$is_crypted); - my $admin_password = crypt "$self->{admin_password}", 'ro'; + $password = SL::Auth::Password->hash_if_unhashed(login => 'root', password => $password); + my $admin_password = SL::Auth::Password->hash_if_unhashed(login => 'root', password => $self->{admin_password}); $main::lxdebug->leave_sub(); @@ -163,6 +162,24 @@ sub authenticate { return $result; } +sub store_credentials_in_session { + my ($self, %params) = @_; + + $params{password} = SL::Auth::Password->hash_if_unhashed(login => $params{login}, password => $params{password}) + unless $self->{authenticator}->requires_cleartext_password; + + $self->set_session_value(login => $params{login}, password => $params{password}); +} + +sub store_root_credentials_in_session { + my ($self, $rpw) = @_; + + $rpw = SL::Auth::Password->hash_if_unhashed(login => 'root', password => $rpw) + unless $self->{authenticator}->requires_cleartext_password; + + $self->set_session_value(rpw => $rpw); +} + sub dbconnect { $main::lxdebug->enter_sub(2); diff --git a/SL/Auth/DB.pm b/SL/Auth/DB.pm index dd6350623..66d23cd27 100644 --- a/SL/Auth/DB.pm +++ b/SL/Auth/DB.pm @@ -6,6 +6,7 @@ use Carp; use Scalar::Util qw(weaken); use SL::Auth::Constants qw(:all); +use SL::Auth::Password; use SL::DBUtils; sub new { @@ -45,9 +46,9 @@ sub authenticate { # Empty password hashes in the database mean just that -- empty # passwords. Hash it for easier comparison. - $stored_password = $self->hash_password(password => $stored_password) unless $stored_password; - ($algorithm, $stored_password) = $self->parse_password_entry($stored_password); - ($algorithm2, $password) = $self->parse_password_entry($self->hash_password(password => $password, algorithm => $algorithm, login => $login)); + $stored_password = SL::Auth::Password->hash(password => $stored_password) unless $stored_password; + ($algorithm, $stored_password) = SL::Auth::Password->parse($stored_password); + ($algorithm2, $password) = SL::Auth::Password->parse(SL::Auth::Password->hash_if_unhashed(password => $password, algorithm => $algorithm, login => $login)); $main::lxdebug->leave_sub(); @@ -58,6 +59,10 @@ sub can_change_password { return 1; } +sub requires_cleartext_password { + return 0; +} + sub change_password { $main::lxdebug->enter_sub(); @@ -73,7 +78,7 @@ sub change_password { return ERR_BACKEND; } - $password = $self->hash_password(password => $password) unless $is_crypted; + $password = SL::Auth::Password->hash(password => $password) unless $is_crypted; do_query($main::form, $dbh, qq|UPDATE auth."user" SET password = ? WHERE login = ?|, $password, $login); @@ -88,42 +93,4 @@ sub verify_config { return 1; } -sub hash_password { - my ($self, %params) = @_; - - if (!$params{algorithm}) { - $params{algorithm} = 'SHA1'; - $params{fallback_algorithm} = 'MD5'; - } - - if ($params{algorithm} eq 'SHA1') { - if (eval { require Digest::SHA1; 1 }) { - return '{SHA1}' . Digest::SHA1::sha1_hex($params{password}); - - } elsif ($params{fallback_algorithm}) { - return $self->hash_password(%params, algorithm => $params{fallback_algorithm}); - - } else { - die 'Digest::SHA1 not available'; - } - - } elsif ($params{algorithm} eq 'MD5') { - require Digest::MD5; - return '{MD5}' . Digest::MD5::md5_hex($params{password}); - - } elsif ($params{algorithm} eq 'CRYPT') { - return '{CRYPT}' . crypt($params{password}, substr($params{login}, 0, 2)); - - } else { - croak 'Unsupported hash algorithm ' . $params{algorithm}; - } -} - -sub parse_password_entry { - my ($self, $password) = @_; - - return ($1, $2) if $password =~ m/^\{ ([^\}]+) \} (.+)/x; - return ('CRYPT', $password); -} - 1; diff --git a/SL/Auth/LDAP.pm b/SL/Auth/LDAP.pm index 70e963d47..1c8c85161 100644 --- a/SL/Auth/LDAP.pm +++ b/SL/Auth/LDAP.pm @@ -180,6 +180,10 @@ sub can_change_password { return 0; } +sub requires_cleartext_password { + return 1; +} + sub change_password { return ERR_BACKEND; } diff --git a/SL/Auth/Password.pm b/SL/Auth/Password.pm new file mode 100644 index 000000000..5a17203c5 --- /dev/null +++ b/SL/Auth/Password.pm @@ -0,0 +1,53 @@ +package SL::Auth::Password; + +use strict; + +use Carp; + +sub hash { + my ($class, %params) = @_; + + if (!$params{algorithm}) { + $params{algorithm} = 'SHA1'; + $params{fallback_algorithm} = 'MD5'; + } + + if ($params{algorithm} eq 'SHA1') { + if (eval { require Digest::SHA1; 1 }) { + return '{SHA1}' . Digest::SHA1::sha1_hex($params{password}); + + } elsif ($params{fallback_algorithm}) { + return $class->hash_password(%params, algorithm => $params{fallback_algorithm}); + + } else { + die 'Digest::SHA1 not available'; + } + + } elsif ($params{algorithm} eq 'MD5') { + require Digest::MD5; + return '{MD5}' . Digest::MD5::md5_hex($params{password}); + + } elsif ($params{algorithm} eq 'CRYPT') { + return '{CRYPT}' . crypt($params{password}, substr($params{login}, 0, 2)); + + } else { + croak 'Unsupported hash algorithm ' . $params{algorithm}; + } +} + +sub hash_if_unhashed { + my ($class, %params) = @_; + + my ($algorithm, $password) = $class->parse($params{password}, 'NONE'); + + return $algorithm eq 'NONE' ? $class->hash(%params) : $params{password}; +} + +sub parse { + my ($class, $password, $default_algorithm) = @_; + + return ($1, $2) if $password =~ m/^\{ ([^\}]+) \} (.+)/x; + return ($default_algorithm || 'CRYPT', $password); +} + +1; diff --git a/SL/Dispatcher.pm b/SL/Dispatcher.pm index 76fcf6fb7..239cdcb96 100644 --- a/SL/Dispatcher.pm +++ b/SL/Dispatcher.pm @@ -202,7 +202,7 @@ sub handle_request { show_error('login/password_error', 'password') if SL::Auth::OK != $::auth->authenticate($::form->{login}, $::form->{password}); - $::auth->set_session_value('login', $::form->{login}, 'password', $::form->{password}); + $::auth->store_credentials_in_session(login => $::form->{login}, password => $::form->{password}); $::auth->create_or_refresh_session; $::auth->delete_session_value('FLASH'); delete $::form->{password}; diff --git a/bin/mozilla/admin.pl b/bin/mozilla/admin.pl index efd16fecf..4be5e330f 100755 --- a/bin/mozilla/admin.pl +++ b/bin/mozilla/admin.pl @@ -73,7 +73,7 @@ sub run { $locale = $::locale; $auth = $::auth; - $::auth->set_session_value('rpw', $::form->{rpw}) if $session_result == SL::Auth->SESSION_OK; + $::auth->store_root_credentials_in_session($form->{rpw}) if $session_result == SL::Auth->SESSION_OK; $form->{stylesheet} = "lx-office-erp.css"; $form->{favicon} = "favicon.ico"; @@ -81,11 +81,12 @@ sub run { if ($form->{action}) { if ($auth->authenticate_root($form->{rpw}) != $auth->OK()) { $form->{error_message} = $locale->text('Incorrect Password!'); + $auth->delete_session_value('rpw'); adminlogin(); } else { if ($auth->session_tables_present()) { - $::auth->set_session_value('rpw', $::form->{rpw}); - $::auth->create_or_refresh_session(); + $::auth->store_root_credentials_in_session($::form->{rpw}); + delete $::form->{rpw}; _apply_dbupgrade_scripts(); } diff --git a/bin/mozilla/login.pl b/bin/mozilla/login.pl index 03e6dd947..528c4eb4b 100644 --- a/bin/mozilla/login.pl +++ b/bin/mozilla/login.pl @@ -69,8 +69,9 @@ sub run { $form->{error_message} = $::locale->text('Incorrect username or password!'); login_screen(); } else { - $auth->set_session_value('login', $form->{login}, 'password', $form->{password}); + $auth->store_credentials_in_session(login => $form->{login}, password => $form->{password}); $auth->create_or_refresh_session(); + delete $form->{password}; $form->{titlebar} .= " - $::myconfig{name} - $::myconfig{dbname}"; call_sub($::locale->findsub($action));