Merge branch 'no-cleartext-passwords-in-db'
authorMoritz Bunkus <m.bunkus@linet-services.de>
Thu, 16 Jun 2011 08:27:25 +0000 (10:27 +0200)
committerMoritz Bunkus <m.bunkus@linet-services.de>
Thu, 16 Jun 2011 08:27:25 +0000 (10:27 +0200)
SL/Auth.pm
SL/Auth/DB.pm
SL/Auth/LDAP.pm
SL/Auth/Password.pm [new file with mode: 0644]
SL/Dispatcher.pm
bin/mozilla/admin.pl
bin/mozilla/login.pl

index 784b185..5f3c65d 100644 (file)
@@ -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);
 
index dd63506..66d23cd 100644 (file)
@@ -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;
index 70e963d..1c8c851 100644 (file)
@@ -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 (file)
index 0000000..5a17203
--- /dev/null
@@ -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;
index 76fcf6f..239cdcb 100644 (file)
@@ -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};
index efd16fe..4be5e33 100755 (executable)
@@ -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();
       }
 
index 03e6dd9..528c4eb 100644 (file)
@@ -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));