From 960a6547805d042eef6eabaf66f6565e4328a162 Mon Sep 17 00:00:00 2001 From: cajus Date: Thu, 27 Mar 2008 16:44:38 +0000 Subject: [PATCH] Updated password methods to support sub-hash-methods git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@10032 594d385d-05f5-0310-b6e9-bd551577e9d8 --- gosa-core/include/functions.inc | 31 +++--- .../class_password-methods-clear.inc | 2 +- .../class_password-methods-crypt.inc | 82 +++++++++++++++- .../class_password-methods-md5.inc | 1 + .../class_password-methods-sha.inc | 2 +- .../class_password-methods-smd5.inc | 2 +- .../class_password-methods-ssha.inc | 2 +- .../class_password-methods.inc | 95 ++++++++++++++----- .../plugins/personal/generic/class_user.inc | 8 +- gosa-core/setup/class_setupStep_Migrate.inc | 5 +- 10 files changed, 181 insertions(+), 49 deletions(-) diff --git a/gosa-core/include/functions.inc b/gosa-core/include/functions.inc index d84bf771b..5f8c1d0e1 100644 --- a/gosa-core/include/functions.inc +++ b/gosa-core/include/functions.inc @@ -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: ?> diff --git a/gosa-core/include/password-methods/class_password-methods-clear.inc b/gosa-core/include/password-methods/class_password-methods-clear.inc index 244c373ae..211e98b94 100644 --- a/gosa-core/include/password-methods/class_password-methods-clear.inc +++ b/gosa-core/include/password-methods/class_password-methods-clear.inc @@ -23,7 +23,7 @@ class passwordMethodClear extends passwordMethod { - function passwordMethodClear($config) + function passwordMethodClear($config) { } diff --git a/gosa-core/include/password-methods/class_password-methods-crypt.inc b/gosa-core/include/password-methods/class_password-methods-crypt.inc index 54ba4d1fb..b03b602c7 100644 --- a/gosa-core/include/password-methods/class_password-methods-crypt.inc +++ b/gosa-core/include/password-methods/class_password-methods-crypt.inc @@ -22,10 +22,11 @@ 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 ""; } } diff --git a/gosa-core/include/password-methods/class_password-methods-md5.inc b/gosa-core/include/password-methods/class_password-methods-md5.inc index fb6ba5622..41903a14a 100644 --- a/gosa-core/include/password-methods/class_password-methods-md5.inc +++ b/gosa-core/include/password-methods/class_password-methods-md5.inc @@ -47,6 +47,7 @@ class passwordMethodMd5 extends passwordMethod { return "md5"; } + } // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: diff --git a/gosa-core/include/password-methods/class_password-methods-sha.inc b/gosa-core/include/password-methods/class_password-methods-sha.inc index 7c5d80c12..8d73b2557 100644 --- a/gosa-core/include/password-methods/class_password-methods-sha.inc +++ b/gosa-core/include/password-methods/class_password-methods-sha.inc @@ -22,7 +22,7 @@ class passwordMethodsha extends passwordMethod { - function passwordMethodsha($config) + function passwordMethodsha($config) { } diff --git a/gosa-core/include/password-methods/class_password-methods-smd5.inc b/gosa-core/include/password-methods/class_password-methods-smd5.inc index e1129261d..135675d5f 100644 --- a/gosa-core/include/password-methods/class_password-methods-smd5.inc +++ b/gosa-core/include/password-methods/class_password-methods-smd5.inc @@ -22,7 +22,7 @@ class passwordMethodsmd5 extends passwordMethod { - function passwordMethodsmd5($config) + function passwordMethodsmd5($config) { } diff --git a/gosa-core/include/password-methods/class_password-methods-ssha.inc b/gosa-core/include/password-methods/class_password-methods-ssha.inc index e2d6e27d5..8c0b987b5 100644 --- a/gosa-core/include/password-methods/class_password-methods-ssha.inc +++ b/gosa-core/include/password-methods/class_password-methods-ssha.inc @@ -22,7 +22,7 @@ class passwordMethodssha extends passwordMethod { - function passwordMethodssha($config) + function passwordMethodssha($config) { } diff --git a/gosa-core/include/password-methods/class_password-methods.inc b/gosa-core/include/password-methods/class_password-methods.inc index 5f3e683ef..b2d0ac6fd 100644 --- a/gosa-core/include/password-methods/class_password-methods.inc +++ b/gosa-core/include/password-methods/class_password-methods.inc @@ -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: ?> diff --git a/gosa-core/plugins/personal/generic/class_user.inc b/gosa-core/plugins/personal/generic/class_user.inc index 5da067458..1ad2c9264 100644 --- a/gosa-core/plugins/personal/generic/class_user.inc +++ b/gosa-core/plugins/personal/generic/class_user.inc @@ -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"; diff --git a/gosa-core/setup/class_setupStep_Migrate.inc b/gosa-core/setup/class_setupStep_Migrate.inc index ed52e7cd5..7e45ca33e 100644 --- a/gosa-core/setup/class_setupStep_Migrate.inc +++ b/gosa-core/setup/class_setupStep_Migrate.inc @@ -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"); -- 2.30.2