Code

Updated password methods to support sub-hash-methods
authorcajus <cajus@594d385d-05f5-0310-b6e9-bd551577e9d8>
Thu, 27 Mar 2008 16:44:38 +0000 (16:44 +0000)
committercajus <cajus@594d385d-05f5-0310-b6e9-bd551577e9d8>
Thu, 27 Mar 2008 16:44:38 +0000 (16:44 +0000)
git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@10032 594d385d-05f5-0310-b6e9-bd551577e9d8

gosa-core/include/functions.inc
gosa-core/include/password-methods/class_password-methods-clear.inc
gosa-core/include/password-methods/class_password-methods-crypt.inc
gosa-core/include/password-methods/class_password-methods-md5.inc
gosa-core/include/password-methods/class_password-methods-sha.inc
gosa-core/include/password-methods/class_password-methods-smd5.inc
gosa-core/include/password-methods/class_password-methods-ssha.inc
gosa-core/include/password-methods/class_password-methods.inc
gosa-core/plugins/personal/generic/class_user.inc
gosa-core/setup/class_setupStep_Migrate.inc

index d84bf771bc860be5e0f3b9562362eebcdf74a376..5f8c1d0e1eb6602c15c09509581805cfdcd1d9d0 100644 (file)
@@ -2420,8 +2420,8 @@ function change_password ($dn, $password, $mode=0, $hash= "")
   // Get all available encryption Methods
 
   // NON STATIC CALL :)
-  $tmp = new passwordMethod(session::get('config'));
-  $available = $tmp->get_available_methods();
+  $methods = new passwordMethod(session::get('config'));
+  $available = $methods->get_available_methods();
 
   // read current password entry for $dn, to detect the encryption Method
   $ldap       = $config->get_ldap_link();
@@ -2448,11 +2448,12 @@ function change_password ($dn, $password, $mode=0, $hash= "")
 
     /* Extract used hash */
     if ($hash == ""){
-      $hash= strtolower($matches[1]);
+      $test = passwordMethod::get_method($attrs['userPassword'][0]);
+    } else {
+      $test = new $available[$hash]($config);
+      $test->set_hash($hash);
     }
 
-    $test = new  $available[$hash]($config);
-
   } else {
     // User MD5 by default
     $hash= "md5";
@@ -2486,7 +2487,7 @@ function change_password ($dn, $password, $mode=0, $hash= "")
     $attrs= generate_smb_nt_hash($password);
   }
 
- /* Readd ! if user was deactivated */
+ /* Read ! if user was deactivated */
   if($deactivated){
     $newpass = preg_replace("/(^[^\}]+\})(.*$)/","\\1!\\2",$newpass);
   }
@@ -2570,12 +2571,6 @@ function generate_smb_nt_hash($password)
 }
 
 
-function crypt_single($string,$enc_type )
-{
-  return( passwordMethod::crypt_single_str($string,$enc_type));
-}
-
-
 function getEntryCSN($dn)
 {
   global $config;
@@ -2675,5 +2670,17 @@ function xmlentities($str)
   return (htmlentities($str,ENT_QUOTES));
 }
 
+
+function get_random_char () {
+     $randno = rand (0, 63);
+     if ($randno < 12) {
+         return (chr ($randno + 46)); // Digits, '/' and '.'
+     } else if ($randno < 38) {
+         return (chr ($randno + 53)); // Uppercase
+     } else {
+         return (chr ($randno + 59)); // Lowercase
+     }
+  }
+
 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
 ?>
index 244c373ae919c285dc4d3822510ae57c505782da..211e98b94b4724a29077f8f5b6e986afdb770310 100644 (file)
@@ -23,7 +23,7 @@
 class passwordMethodClear extends passwordMethod
 {
 
-       function passwordMethodClear($config)  
+       function passwordMethodClear($config)
        {
        }
 
index 54ba4d1fbd0baa0de73a42751dabf253ce7e7a2c..b03b602c7c0dd41fd3e91abcb062b18dac3f2361 100644 (file)
 
 class passwordMethodCrypt extends passwordMethod
 {
-  function passwordMethodCrypt($config)  
+  function passwordMethodCrypt($config)
   {
   }
 
+
   function is_available()
   {
     if(function_exists("crypt")){
@@ -38,13 +39,88 @@ class passwordMethodCrypt extends passwordMethod
 
   function generate_hash($pwd)
   {
-    return "{CRYPT}".crypt($pwd, substr(session_id(),0,2));
+    if ($this->hash == "crypt/standard-des"){
+      $salt = "";
+      for ($i = 0; $i < 2; $i++) {
+          $salt .= get_random_char();
+      }
+    }
+
+    if ($this->hash == "crypt/enhanced-des"){
+      $salt = "_";
+      for ($i = 0; $i < 8; $i++) {
+          $salt .= get_random_char();
+      }
+    }
+
+    if ($this->hash == "crypt/md5"){
+      $salt = "\$1\$";
+      for ($i = 0; $i < 8; $i++) {
+          $salt .= get_random_char();
+      }
+      $salt .= "\$";
+    }
+
+    if ($this->hash == "crypt/blowfish"){
+      $salt = "\$2a\$07\$";
+      for ($i = 0; $i < CRYPT_SALT_LENGTH; $i++) {
+          $salt .= get_random_char();
+      }
+      $salt .= "\$";
+    }
+
+    return "{CRYPT}".crypt($pwd, $salt);
   }
 
 
   function get_hash_name()
   {
-    return "crypt";
+    $hashes= array();
+    if (CRYPT_STD_DES == 1) {
+      $hashes[]= "crypt/standard-des";
+    }
+
+    if (CRYPT_EXT_DES == 1) {
+      $hashes[]= "crypt/enhanced-des";
+    }
+
+    if (CRYPT_MD5 == 1) {
+      $hashes[]= "crypt/md5";
+    }
+
+    if (CRYPT_BLOWFISH == 1) {
+      $hashes[]= "crypt/blowfish";
+    }
+
+    return $hashes;
+  }
+
+
+  function _extract_method($password_hash)
+  {
+    if (!preg_match('/^{crypt}/i', $password_hash)){
+      return "";
+    }
+
+    $password_hash= preg_replace('/^{[^}]+}!?/', '', $password_hash);
+
+    if (preg_match("/^[a-z-A-Z0-9.\/][a-z-A-Z0-9.\/]/", $password_hash)){
+      return "crypt/standard-des";
+    }
+
+    if (preg_match("/^_[a–zA-Z0–9.\/]/i", $password_hash)){
+      return "crypt/enhanced-des";
+    }
+    
+    if (preg_match('/^\$1\$/', $password_hash)){
+      return "crypt/md5";
+    }
+
+    if (preg_match('/^(\$2\$|\$2a\$)/', $password_hash)){
+      return "crypt/blowfish";
+    }
+
+    return "";
   }
 
 }
index fb6ba56226ee038d60e74e2a6896d2386786d8ca..41903a14aac4f6d78f8e991a800bbfb05fe2a0e0 100644 (file)
@@ -47,6 +47,7 @@ class passwordMethodMd5 extends passwordMethod
   {
     return "md5";
   }
+
 }
 
 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
index 7c5d80c120320da250e9fbf067b109f9f81a16e0..8d73b2557bb2c8d6836ed4c6ab803f54dca88861 100644 (file)
@@ -22,7 +22,7 @@
 
 class passwordMethodsha extends passwordMethod
 {
-  function passwordMethodsha($config)  
+  function passwordMethodsha($config)
   {
   }
 
index e1129261db625d019cb828fd3fe087e3c4943a2d..135675d5fb74e698c3775a4103690b6b7f63993c 100644 (file)
@@ -22,7 +22,7 @@
 
 class passwordMethodsmd5 extends passwordMethod
 {
-  function passwordMethodsmd5($config)  
+  function passwordMethodsmd5($config)
   {
   }
 
index e2d6e27d5e8dc8cbb7dd243f2c9c8714f4ddfde2..8c0b987b5109452f1381e4fc43f4f2c6eaf20381 100644 (file)
@@ -22,7 +22,7 @@
 
 class passwordMethodssha extends passwordMethod
 {
-  function passwordMethodssha($config)  
+  function passwordMethodssha($config)
   {
   }
 
index 5f3e683ef50dd042a15414dff15306519bfbb0e6..b2d0ac6fdf288bb59a8b3799ff564885345b9ba4 100644 (file)
@@ -24,6 +24,7 @@ class passwordMethod
 {
   var $config = false;
   var $attrs= array();
+  var $hash= "";
 
   // Konstructor
   function passwordMethod($config)
@@ -54,21 +55,6 @@ class passwordMethod
   }
 
 
-  // Crypts a single string, with given Method
-  function crypt_single_str($string,$method)
-  {
-    $available = passwordMethod::get_available_methods();
-    if(!is_array($available))
-    {
-      $available = passwordMethod::get_available_methods_if_not_loaded();
-    }
-
-    $test = new  $available[$method](false);
-    $newpass =  $test->generate_hash($string);
-    return( $newpass); 
-  }
-
-
   // this function returns all loaded classes for password encryption
   static function get_available_methods()
   {
@@ -78,18 +64,25 @@ class passwordMethod
     foreach($class_mapping as $class => $path) {
       if(preg_match('/passwordMethod/i', $class) && !preg_match("/^passwordMethod$/i", $class)){
         $name = preg_replace ("/passwordMethod/i", "", $class);
-        $test = new $class($config);
+        $test = new $class($config, "");
         if($test->is_available()) {
-          $plugname= $test->get_hash_name();
-          $ret['name'][$i]= $plugname;
-          $ret['class'][$i]=$class;
-          $ret[$i]['name']= $plugname;
-          $ret[$i]['class']= $class;
-          $ret[$plugname]=$class;                    
-          $i++;
+          $plugs= $test->get_hash_name();
+          if (!is_array($plugs)){
+            $plugs= array($plugs);
+          }
+
+          foreach ($plugs as $plugname){
+            $ret['name'][$i]= $plugname;
+            $ret['class'][$i]=$class;
+            $ret[$i]['name']= $plugname;
+            $ret[$i]['class']= $class;
+            $ret[$plugname]=$class;                    
+            $i++;
+          }
         }
       }
     }
+
     return($ret);
   }
   
@@ -128,6 +121,62 @@ class passwordMethod
   }
 
 
+  // Try to find out if it's our hash...
+  static function get_method($password_hash)
+  {
+    global $config;
+
+    $methods= passwordMethod::get_available_methods();
+
+    foreach ($methods['class'] as $class){
+
+        $test = new $class($config);
+        $method= $test->_extract_method($password_hash);
+        if ($method != ""){
+          $test->set_hash($method);
+          return $test;
+        }
+    }
+
+    msg_dialog::display(_("Error"), _("Cannot find a suitable password method for the current hash!"), ERROR_DIALOG);
+
+    return NULL;
+  }
+
+
+  function _extract_method($password_hash)
+  {
+    $hash= $this->get_hash_name();
+    if (preg_match("/^\{$hash\}/i", $password_hash)){
+      return $hash;
+    }
+
+    return "";
+  }
+
+
+  static function make_hash($password, $hash)
+  {
+    global $config;
+
+    $methods= passwordMethod::get_available_methods();
+    $tmp= new $methods[$hash]($config);
+    $tmp->set_hash($hash);
+    return $tmp->generate_hash($password);
+  }
+
+
+  function set_hash($hash)
+  {
+    $this->hash= $hash;
+  }
+
+
+  function get_hash()
+  {
+    return $this->hash;
+  }
+
 }
 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
 ?>
index 5da067458e0f538b7621361ca8283e7b91ed85e0..1ad2c92648c6e8661346c29412f977183a6a4b70 100644 (file)
@@ -99,7 +99,7 @@ class user extends plugin
   var $dialog;
 
   /* variables to trigger password changes */
-  var $pw_storage= "crypt";
+  var $pw_storage= "md5";
   var $last_pw_storage= "unset";
   var $had_userCertificate= FALSE;
 
@@ -184,8 +184,10 @@ class user extends plugin
       if (isset ($this->attrs['userPassword'][0])){
        /* Initialize local array */
        $matches= array();
-        if (preg_match ("/^{([^}]+)}(.+)/", $this->attrs['userPassword'][0], $matches)){
-          $this->pw_storage= strtolower($matches[1]);
+        if (preg_match ("/^{[^}]+}/", $this->attrs['userPassword'][0])){
+          $tmp= passwordMethod::get_method($this->attrs['userPassword'][0]);
+          $this->pw_storage= $tmp->get_hash(); 
+
         } else {
           if ($this->attrs['userPassword'][0] != ""){
             $this->pw_storage= "clear";
index ed52e7cd5ea192f9391c25634d5af4eb5158befa..7e45ca33e28fff923493f83bb731d1d925d16bbc 100644 (file)
@@ -1020,10 +1020,7 @@ class Step_Migrate extends setup_step
       $dn = "uid=".$uid.",".$people_ou.$cv['base'];
     }
 
-    $methods = @passwordMethod::get_available_methods();
-    $p_m = $methods[$cv['encryption']];
-    $p_c = new $p_m(array());
-    $hash = $p_c->generate_hash($pw2);
+    $hash = passwordMethod::make_hash($pw2, $cv['encryption']);
 
     $new_user=array();
     $new_user['objectClass']= array("top","person","gosaAccount","organizationalPerson","inetOrgPerson");