diff --git a/include/password-methods/class_password-methods-clear.inc b/include/password-methods/class_password-methods-clear.inc index d84ff16b9467e07e2fd038599e96f741c431c3b0..70d13d1c10538157028035f704526be66cbb2071 100644 --- a/include/password-methods/class_password-methods-clear.inc +++ b/include/password-methods/class_password-methods-clear.inc @@ -57,7 +57,7 @@ class passwordMethodClear extends passwordMethod * * \param string $pwd Password */ - function generate_hash($pwd) + function generate_hash($pwd, $locked = FALSE) { return $pwd; } diff --git a/include/password-methods/class_password-methods-crypt.inc b/include/password-methods/class_password-methods-crypt.inc index 0e44832dd4d4cb2f3483a4801580fe5ee142b168..5e76216e557aff3d48637a493f8d522c3fa55e3c 100644 --- a/include/password-methods/class_password-methods-crypt.inc +++ b/include/password-methods/class_password-methods-crypt.inc @@ -54,7 +54,7 @@ class passwordMethodCrypt extends passwordMethod * * \param string $pwd Password */ - function generate_hash($pwd) + function generate_hash($pwd, $locked = FALSE) { if ($this->hash == "crypt/standard-des") { $salt = ""; @@ -102,7 +102,7 @@ class passwordMethodCrypt extends passwordMethod $salt .= "\$"; } - return "{CRYPT}".crypt($pwd, $salt); + return '{CRYPT}'.($locked ? '!' : '').crypt($pwd, $salt); } function checkPassword($pwd, $hash) @@ -151,7 +151,7 @@ class passwordMethodCrypt extends passwordMethod * * \param string $password_hash */ - static function _extract_method($classname, $password_hash) + static function _extract_method($password_hash) { if (!preg_match('/^{crypt}/i', $password_hash)) { return ""; diff --git a/include/password-methods/class_password-methods-empty.inc b/include/password-methods/class_password-methods-empty.inc index 14f43e4e07ead6743c9dbdd448c4f144affb5135..8fc8a7b4b619eb6f7286c452e43faaa01e612e85 100644 --- a/include/password-methods/class_password-methods-empty.inc +++ b/include/password-methods/class_password-methods-empty.inc @@ -30,10 +30,12 @@ */ class passwordMethodEmpty extends passwordMethod { - protected $lockable = FALSE; + protected $lockable = TRUE; public $hash = 'empty'; + const LOCKVALUE = '{CRYPT}!'; + /*! * \brief passwordMethodClear Constructor */ @@ -56,9 +58,9 @@ class passwordMethodEmpty extends passwordMethod * * \param string $pwd Password */ - function generate_hash($pwd) + function generate_hash($pwd, $locked = FALSE) { - return ''; + return ($locked ? static::LOCKVALUE : ''); } /*! @@ -78,5 +80,14 @@ class passwordMethodEmpty extends passwordMethod { return FALSE; } + + static function _extract_method($password_hash) + { + if (empty($password_hash) || ($password_hash == static::LOCKVALUE)) { + return static::get_hash_name(); + } + + return ''; + } } ?> diff --git a/include/password-methods/class_password-methods-md5.inc b/include/password-methods/class_password-methods-md5.inc index 127a5178c2ccfbab8428470209670429b1f12273..835a8adcd7adc9b6ebe0a60c0335fddbbc318fbe 100644 --- a/include/password-methods/class_password-methods-md5.inc +++ b/include/password-methods/class_password-methods-md5.inc @@ -54,9 +54,9 @@ class passwordMethodMd5 extends passwordMethod * * \param string $pwd Password */ - function generate_hash($pwd) + function generate_hash($pwd, $locked = FALSE) { - return '{MD5}'.base64_encode( pack('H*', md5($pwd))); + return '{MD5}'.($locked ? '!' : '').base64_encode( pack('H*', md5($pwd))); } /*! diff --git a/include/password-methods/class_password-methods-sasl.inc b/include/password-methods/class_password-methods-sasl.inc index a170602d1f685894fc8b8015db93a3b2ffdc1490..064e7154b29880f56d7c3f4d1997a236dba71fd6 100644 --- a/include/password-methods/class_password-methods-sasl.inc +++ b/include/password-methods/class_password-methods-sasl.inc @@ -85,16 +85,16 @@ class passwordMethodsasl extends passwordMethod * * \param string $pwd Password */ - function generate_hash($pwd) + function generate_hash($pwd, $locked = FALSE) { if (empty($this->exop)) { if (empty($this->realm)) { msg_dialog::display(_('Error'), _('You need to fill saslRealm or saslExop in the configuration screen in order to use SASL'), ERROR_DIALOG); } - return '{SASL}'.$this->uid.'@'.$this->realm; + return '{SASL}'.($locked ? '!' : '').$this->uid.'@'.$this->realm; } else { // may not be the uid, see saslExop option - return '{SASL}'.$this->uid; + return '{SASL}'.($locked ? '!' : '').$this->uid; } } diff --git a/include/password-methods/class_password-methods-sha.inc b/include/password-methods/class_password-methods-sha.inc index 95f3dd3d6e5567a6380312d3fd19e37d4b46ffba..8e05c7b745e8bda8556ffd10a57f050175206e2a 100644 --- a/include/password-methods/class_password-methods-sha.inc +++ b/include/password-methods/class_password-methods-sha.inc @@ -53,12 +53,12 @@ class passwordMethodsha extends passwordMethod * * \param string $password Password */ - function generate_hash($password) + function generate_hash($password, $locked = FALSE) { if (function_exists('sha1')) { - $hash = '{SHA}' . base64_encode(pack('H*', sha1($password))); + $hash = '{SHA}'.($locked ? '!' : '').base64_encode(pack('H*', sha1($password))); } elseif (function_exists('mhash')) { - $hash = '{SHA}' . base64_encode(mHash(MHASH_SHA1, $password)); + $hash = '{SHA}'.($locked ? '!' : '').base64_encode(mHash(MHASH_SHA1, $password)); } else { msg_dialog::display(_('Configuration error'), msgPool::missingext('mhash'), ERROR_DIALOG); return FALSE; diff --git a/include/password-methods/class_password-methods-smd5.inc b/include/password-methods/class_password-methods-smd5.inc index 8f4246255a71c2b4a125f99ed6d27598f25dc86c..655bb75a2f76c88c29ef147ee0f99ede98f394c0 100644 --- a/include/password-methods/class_password-methods-smd5.inc +++ b/include/password-methods/class_password-methods-smd5.inc @@ -53,11 +53,11 @@ class passwordMethodsmd5 extends passwordMethod * * \param string $pwd Password */ - function generate_hash($pwd) + function generate_hash($pwd, $locked = FALSE) { $salt0 = substr(pack('h*', md5(random_int(0, PHP_INT_MAX))), 0, 8); $salt = substr(pack('H*', md5($salt0 . $pwd)), 0, 4); - return '{SMD5}'.base64_encode(pack('H*', md5($pwd . $salt)) . $salt); + return '{SMD5}'.($locked ? '!' : '').base64_encode(pack('H*', md5($pwd . $salt)) . $salt); } function checkPassword($pwd, $hash) diff --git a/include/password-methods/class_password-methods-ssha.inc b/include/password-methods/class_password-methods-ssha.inc index 92081f1be45ee5a05efd904a7c554642708b01d1..c0d287b55e6eefd6361792349ad01158bb5eb8ef 100644 --- a/include/password-methods/class_password-methods-ssha.inc +++ b/include/password-methods/class_password-methods-ssha.inc @@ -53,15 +53,15 @@ class passwordMethodssha extends passwordMethod * * \param string $pwd Password */ - function generate_hash($pwd) + function generate_hash($pwd, $locked = FALSE) { if (function_exists('sha1')) { $salt = substr(pack('h*', md5(random_int(0, PHP_INT_MAX))), 0, 8); $salt = substr(pack('H*', sha1($salt.$pwd)), 0, 4); - $pwd = '{SSHA}'.base64_encode(pack('H*', sha1($pwd.$salt)).$salt); + $pwd = '{SSHA}'.($locked ? '!' : '').base64_encode(pack('H*', sha1($pwd.$salt)).$salt); } elseif (function_exists('mhash')) { $salt = mhash_keygen_s2k(MHASH_SHA1, $pwd, substr(pack('h*', md5(random_int(0, PHP_INT_MAX))), 0, 8), 4); - $pwd = '{SSHA}'.base64_encode(mhash(MHASH_SHA1, $pwd.$salt).$salt); + $pwd = '{SSHA}'.($locked ? '!' : '').base64_encode(mhash(MHASH_SHA1, $pwd.$salt).$salt); } else { msg_dialog::display(_('Configuration error'), msgPool::missingext('mhash'), ERROR_DIALOG); return FALSE; diff --git a/include/password-methods/class_password-methods.inc b/include/password-methods/class_password-methods.inc index 0582f523f180fd711d0f0fa8454a30abf4228a2e..5ad44c626c19c34d368cbc3b4244f419079371c9 100644 --- a/include/password-methods/class_password-methods.inc +++ b/include/password-methods/class_password-methods.inc @@ -77,7 +77,7 @@ class passwordMethod * * \param string $dn The DN */ - function is_locked($dn = "") + function is_locked($dn = '', $pwd = '') { global $config; if (!$this->lockable) { @@ -85,7 +85,6 @@ class passwordMethod } /* Get current password hash */ - $pwd = ""; if (!empty($dn)) { $ldap = $config->get_ldap_link(); $ldap->cd($config->current['BASE']); @@ -147,56 +146,60 @@ class passwordMethod } } - /* We can only lock/unlock non-empty passwords */ - if (!empty($pwd)) { - /* Check if this entry is already locked. */ - if (!preg_match("/^[^\}]*+\}!/", $pwd)) { - if ($mode == 'UNLOCK') { - return TRUE; - } - } elseif ($mode == 'LOCK') { + /* Check if this entry is already locked. */ + if (!preg_match("/^[^\}]*+\}!/", $pwd)) { + if ($mode == 'UNLOCK') { return TRUE; } + } elseif ($mode == 'LOCK') { + return TRUE; + } - // (Un)lock the samba account - $modify = lock_samba_account($mode, $attrs); + // (Un)lock the samba account + $modify = lock_samba_account($mode, $attrs); - // (Un)lock SSH keys - lock_ssh_account($mode, $attrs, $modify); + // (Un)lock SSH keys + lock_ssh_account($mode, $attrs, $modify); - // Call pre hooks - $userClass = new user($dn); - $errors = $userClass->callHook('PRE'.$mode, array(), $ret); - if (!empty($errors)) { - msg_dialog::displayChecks($errors); - return FALSE; - } + // Call pre hooks + $userClass = new user($dn); + $errors = $userClass->callHook('PRE'.$mode, array(), $ret); + if (!empty($errors)) { + msg_dialog::displayChecks($errors); + return FALSE; + } - // (Un)lock the account by modifying the password hash. - if ($mode == 'LOCK') { - /* Lock entry */ + // (Un)lock the account by modifying the password hash. + if ($mode == 'LOCK') { + /* Lock entry */ + if (empty($pwd)) { + $pwd = passwordMethodEmpty::LOCKVALUE; + } else { $pwd = preg_replace("/(^[^\}]+\})(.*$)/", "\\1!\\2", $pwd); + } + } else { + /* Unlock entry */ + if ($pwd == passwordMethodEmpty::LOCKVALUE) { + $pwd = ''; } else { - /* Unlock entry */ $pwd = preg_replace("/(^[^\}]+\})!(.*$)/", "\\1\\2", $pwd); } - $modify['userPassword'] = $pwd; - $ldap->cd($dn); - $ldap->modify($modify); - - // Call the password post-lock hook, if defined. - if ($ldap->success()) { - $userClass = new user($dn); - $errors = $userClass->callHook('POST'.$mode, array(), $ret); - if (!empty($errors)) { - msg_dialog::displayChecks($errors); - } - } else { - msg_dialog::display(_('LDAP error'), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_MOD), LDAP_ERROR); + } + $modify['userPassword'] = $pwd; + $ldap->cd($dn); + $ldap->modify($modify); + + // Call the password post-lock hook, if defined. + if ($ldap->success()) { + $userClass = new user($dn); + $errors = $userClass->callHook('POST'.$mode, array(), $ret); + if (!empty($errors)) { + msg_dialog::displayChecks($errors); } - return $ldap->success(); + } else { + msg_dialog::display(_('LDAP error'), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_MOD), LDAP_ERROR); } - return FALSE; + return $ldap->success(); } @@ -299,14 +302,15 @@ class passwordMethod { $methods = passwordMethod::get_available_methods(); - if (empty($password_hash) && passwordMethodEmpty::is_available()) { + if (isset($methods['class']['passwordMethodEmpty']) && (passwordMethodEmpty::_extract_method($password_hash) != '')) { + /* Test empty method first as it gets priority */ $method = new passwordMethodEmpty($dn); return $method; } foreach ($methods['class'] as $class) { - $method = $class::_extract_method($class, $password_hash); - if ($method != "") { + $method = $class::_extract_method($password_hash); + if ($method != '') { $test = new $class($dn); $test->set_hash($method); return $test; @@ -324,9 +328,9 @@ class passwordMethod * * \param string $password_hash */ - static function _extract_method($classname, $password_hash) + static function _extract_method($password_hash) { - $hash = $classname::get_hash_name(); + $hash = static::get_hash_name(); if (preg_match("/^\{$hash\}/i", $password_hash)) { return $hash; } diff --git a/include/simpleplugin/attributes/class_BooleanAttribute.inc b/include/simpleplugin/attributes/class_BooleanAttribute.inc index 0ba929c9790f8b279768a93888631c02590e31d5..c1b1bba5a0d8a899e78f7579ab2052f155c8538a 100644 --- a/include/simpleplugin/attributes/class_BooleanAttribute.inc +++ b/include/simpleplugin/attributes/class_BooleanAttribute.inc @@ -25,6 +25,7 @@ class BooleanAttribute extends Attribute { public $trueValue; public $falseValue; + protected $templatable = TRUE; /*! \brief The constructor of BooleanAttribute * @@ -44,6 +45,11 @@ class BooleanAttribute extends Attribute $this->falseValue = $falseValue; } + function setTemplatable($bool) + { + $this->templatable = $bool; + } + function inputValue ($value) { return ($value == $this->trueValue); @@ -92,7 +98,7 @@ class BooleanAttribute extends Attribute function renderTemplateInput () { - if (!$this->submitForm && empty($this->managedAttributes)) { + if (!$this->submitForm && empty($this->managedAttributes) && $this->templatable) { /* Allow to set to %askme% if we are not (de)activating other fields */ $id = $this->getHtmlId(); diff --git a/plugins/admin/users/class_userManagement.inc b/plugins/admin/users/class_userManagement.inc index 2ad4f6b44cfadb00e9881da93643ff1ad79b155b..02ad2d1eebac3133bade6538ae17362703f4e96e 100644 --- a/plugins/admin/users/class_userManagement.inc +++ b/plugins/admin/users/class_userManagement.inc @@ -37,6 +37,9 @@ class LockAction extends Action { if (isset($entry['userPassword']) && preg_match('/^\{[^\}]/', $entry['userPassword'])) { return (preg_match('/^[^\}]*+\}!/', $entry['userPassword']) === 1); + } elseif ((strtolower($entry->type) == 'user') && !isset($entry['userPassword'])) { + /* Empty lockable password */ + return FALSE; } return NULL; } @@ -170,9 +173,6 @@ class userManagement extends management foreach ($allowed as $dn) { // We can't lock empty passwords. $entry = $this->listing->getEntry($dn); - if (!isset($entry['userPassword'])) { - continue; - } // Detect the password method and try to lock/unlock. $pwd = $entry['userPassword']; diff --git a/plugins/personal/generic/class_UserPasswordAttribute.inc b/plugins/personal/generic/class_UserPasswordAttribute.inc new file mode 100644 index 0000000000000000000000000000000000000000..220db59333cb28f39854fd9a6481871bb869312c --- /dev/null +++ b/plugins/personal/generic/class_UserPasswordAttribute.inc @@ -0,0 +1,252 @@ +<?php +/* + This code is part of FusionDirectory (http://www.fusiondirectory.org/) + Copyright (C) 2013-2018 FusionDirectory + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +/* Handle a password and its hash method */ +class UserPasswordAttribute extends CompositeAttribute +{ + protected $needPassword; + protected $previousMethod; + + function __construct ($label, $description, $ldapName, $required = FALSE, $defaultValue = "", $acl = "") + { + $temp = passwordMethod::get_available_methods(); + + /* Create password methods array */ + $pwd_methods = array(); + $this->needPassword = array(); + foreach ($temp['name'] as $id => $name) { + $this->needPassword[$name] = $temp[$id]['object']->need_password(); + $pwd_methods[$name] = $name; + if (!empty($temp[$id]['desc'])) { + $pwd_methods[$name] .= " (".$temp[$id]['desc'].")"; + } + } + + parent::__construct ( + $description, $ldapName, + array( + new SelectAttribute( + _('Password method'), _('Password hash method to use'), + $ldapName.'_pwstorage', TRUE, + array_keys($pwd_methods), '', array_values($pwd_methods) + ), + new PasswordAttribute( + _('Password'), _('Password (Leave empty if you do not wish to change it)'), + $ldapName.'_password', $required + ), + new PasswordAttribute( + _('Password again'), _('Same password as above, to avoid errors'), + $ldapName.'_password2', $required + ), + new HiddenAttribute( + $ldapName.'_hash' + ), + new BooleanAttribute( + /* Label/Description will only be visible for templates */ + _('Locked'), _('Whether accounts created with this template will be locked'), + $ldapName.'_locked', FALSE, + FALSE + ) + ), + '', '', $acl, $label + ); + $this->attributes[0]->setSubmitForm(TRUE); + $this->attributes[4]->setTemplatable(FALSE); + } + + public function setParent(&$plugin) + { + global $config; + parent::setParent($plugin); + if (is_object($this->plugin)) { + $hash = $config->get_cfg_value('passwordDefaultHash', 'ssha'); + $this->attributes[0]->setDefaultValue($hash); + if ($config->get_cfg_value('forcePasswordDefaultHash', 'FALSE') == 'TRUE') { + $this->attributes[0]->setValue($hash); + $this->attributes[0]->setDisabled(TRUE); + } + if (!$this->plugin->is_template) { + $this->attributes[4]->setVisible(FALSE); + } + $this->checkIfMethodNeedsPassword(); + } + } + + /* We need to handle method select disabling manually */ + function renderAttribute(array &$attributes, $readOnly) + { + global $config; + if ($this->visible) { + if ($this->linearRendering) { + parent::renderAttribute($attributes, $readOnly); + } else { + foreach ($this->attributes as $key => &$attribute) { + if (is_object($this->plugin) && $this->plugin->is_template && ($key == 2)) { + /* Do not display confirmation field in template mode */ + continue; + } + if (($key == 0) && ($config->get_cfg_value('forcePasswordDefaultHash', 'FALSE') == 'TRUE')) { + $attribute->setDisabled(TRUE); + } else { + $attribute->setDisabled($this->disabled); + } + $attribute->renderAttribute($attributes, $readOnly); + } + unset($attribute); + } + } + } + + /*! \brief Loads this attribute value from the attrs array + */ + protected function loadAttrValue (array $attrs) + { + if (isset($attrs[$this->getLdapName()])) { + $this->setValue($this->inputValue($attrs[$this->getLdapName()][0])); + } elseif ($this->plugin->initially_was_account) { + $this->setValue($this->inputValue('')); + } else { + $this->attributes[0]->resetToDefault(); + $this->checkIfMethodNeedsPassword(); + } + } + + function setValue ($value) + { + if (!is_array($value)) { + $value = $this->inputValue($value); + } + reset($value); + $key = key($value); + if ($this->attributes[0]->isDisabled() || ($value[$key] == '')) { + $value[$key] = $this->attributes[0]->getValue(); + } + parent::setValue($value); + $this->checkIfMethodNeedsPassword(); + } + + function applyPostValue () + { + parent::applyPostValue(); + $this->checkIfMethodNeedsPassword(); + } + + function checkIfMethodNeedsPassword() + { + $method = $this->attributes[0]->getValue(); + if ($method != $this->previousMethod) { + if (isset($this->needPassword[$method]) && $this->needPassword[$method]) { + $hashEmpty = ($this->attributes[3]->getValue() == ''); + $this->attributes[1]->setVisible(TRUE); + $this->attributes[1]->setRequired($hashEmpty); + $this->attributes[2]->setVisible(TRUE); + $this->attributes[2]->setRequired($hashEmpty); + } else { + $this->attributes[1]->setRequired(FALSE); + $this->attributes[1]->setVisible(FALSE); + $this->attributes[1]->setValue(''); + $this->attributes[2]->setRequired(FALSE); + $this->attributes[2]->setVisible(FALSE); + $this->attributes[2]->setValue(''); + } + } + $this->previousMethod = $method; + } + + function readValues($value) + { + return $this->readUserPasswordValues($value, $this->plugin->is_template); + } + + function readUserPasswordValues($value, $istemplate) + { + global $config; + $pw_storage = $config->get_cfg_value('passwordDefaultHash', 'ssha'); + $locked = FALSE; + $password = ''; + if ($istemplate && !empty($value)) { + if ($value == '%askme%') { + return array('%askme%', '', '', $value, $locked); + } + list($value, $password) = explode('|', $value, 2); + } + if (preg_match ('/^{[^}]+}/', $value)) { + $tmp = passwordMethod::get_method($value); + if (is_object($tmp)) { + $pw_storage = $tmp->get_hash(); + $locked = $tmp->is_locked('', $value); + } + } elseif ($value != '') { + $pw_storage = 'clear'; + } elseif ($this->plugin->initially_was_account) { + $pw_storage = 'empty'; + } + return array($pw_storage, $password, $password, $value, $locked); + } + + function writeValues(array $values) + { + if ($this->plugin->is_template && ($values[0] == '%askme%')) { + return '%askme%'; + } + if (!$this->plugin->is_template && ($this->needPassword[$values[0]] || ($values[0] == 'empty')) && ($values[1] == '')) { + return $values[3]; + } + $temp = passwordMethod::get_available_methods(); + if (!isset($temp[$values[0]])) { + trigger_error('Unknown password method '.$values[0]); + return $values[3]; + } + $test = new $temp[$values[0]]($this->plugin->dn, $this->plugin); + $test->set_hash($values[0]); + if ($this->plugin->is_template) { + return $test->generate_hash($values[1], $values[4]).'|'.$values[1]; + } else { + return $test->generate_hash($values[1]); + } + } + + function check() + { + $method = $this->attributes[0]->getValue(); + $error = parent::check(); + if (!empty($error)) { + return $error; + } + if (($this->attributes[1]->getValue() != '') || ($this->attributes[2]->getValue() != '')) { + return user::reportPasswordProblems($this->plugin->dn, $this->attributes[1]->getValue(), $this->attributes[2]->getValue()); + } + } + + function getMethod() + { + return $this->attributes[0]->getValue(); + } + + function getClear() + { + return $this->attributes[1]->getValue(); + } + + function isLocked() + { + return $this->attributes[4]->getValue(); + } +} diff --git a/plugins/personal/generic/class_user.inc b/plugins/personal/generic/class_user.inc index 52f0812f304819ba6bade0d738178012a7512cd9..c32c1c0991c6610ec535c77a239d58b636db74be 100644 --- a/plugins/personal/generic/class_user.inc +++ b/plugins/personal/generic/class_user.inc @@ -1,7 +1,7 @@ <?php /* This code is part of FusionDirectory (http://www.fusiondirectory.org/) - Copyright (C) 2013-2016 FusionDirectory + Copyright (C) 2013-2018 FusionDirectory This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,231 +18,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* Handle a password and its hash method */ -class UserPasswordAttribute extends CompositeAttribute -{ - protected $needPassword; - protected $previousMethod; - - function __construct ($label, $description, $ldapName, $required = FALSE, $defaultValue = "", $acl = "") - { - $temp = passwordMethod::get_available_methods(); - - /* Create password methods array */ - $pwd_methods = array(); - $this->needPassword = array(); - foreach ($temp['name'] as $id => $name) { - $this->needPassword[$name] = $temp[$id]['object']->need_password(); - $pwd_methods[$name] = $name; - if (!empty($temp[$id]['desc'])) { - $pwd_methods[$name] .= " (".$temp[$id]['desc'].")"; - } - } - - parent::__construct ( - $description, $ldapName, - array( - new SelectAttribute( - _('Password method'), _('Password hash method to use'), - $ldapName.'_pwstorage', TRUE, - array_keys($pwd_methods), '', array_values($pwd_methods) - ), - new PasswordAttribute( - _('Password'), _('Password (Leave empty if you do not wish to change it)'), - $ldapName.'_password', $required - ), - new PasswordAttribute( - _('Password again'), _('Same password as above, to avoid errors'), - $ldapName.'_password2', $required - ), - new HiddenAttribute( - $ldapName.'_hash' - ), - new HiddenAttribute( - $ldapName.'_locked', FALSE, - FALSE - ) - ), - '', '', $acl, $label - ); - $this->attributes[0]->setSubmitForm(TRUE); - } - - public function setParent(&$plugin) - { - global $config; - parent::setParent($plugin); - if (is_object($this->plugin)) { - $hash = $config->get_cfg_value('passwordDefaultHash', 'ssha'); - $this->attributes[0]->setDefaultValue($hash); - if ($config->get_cfg_value('forcePasswordDefaultHash', 'FALSE') == 'TRUE') { - $this->attributes[0]->setValue($hash); - $this->attributes[0]->setDisabled(TRUE); - } - $this->checkIfMethodNeedsPassword(); - } - } - - /* We need to handle method select disabling manually */ - function renderAttribute(array &$attributes, $readOnly) - { - global $config; - if ($this->visible) { - if ($this->linearRendering) { - parent::renderAttribute($attributes, $readOnly); - } else { - foreach ($this->attributes as $key => &$attribute) { - if (is_object($this->plugin) && $this->plugin->is_template && ($key == 2)) { - /* Do not display confirmation field in template mode */ - continue; - } - if (($key == 0) && ($config->get_cfg_value('forcePasswordDefaultHash', 'FALSE') == 'TRUE')) { - $attribute->setDisabled(TRUE); - } else { - $attribute->setDisabled($this->disabled); - } - $attribute->renderAttribute($attributes, $readOnly); - } - unset($attribute); - } - } - } - - /*! \brief Loads this attribute value from the attrs array - */ - protected function loadAttrValue (array $attrs) - { - if (isset($attrs[$this->getLdapName()])) { - $this->setValue($this->inputValue($attrs[$this->getLdapName()][0])); - } elseif ($this->plugin->initially_was_account) { - $this->setValue($this->inputValue('')); - } else { - $this->attributes[0]->resetToDefault(); - $this->checkIfMethodNeedsPassword(); - } - } - - function setValue ($value) - { - if (!is_array($value)) { - $value = $this->inputValue($value); - } - reset($value); - $key = key($value); - if ($this->attributes[0]->isDisabled() || ($value[$key] == '')) { - $value[$key] = $this->attributes[0]->getValue(); - } - parent::setValue($value); - $this->checkIfMethodNeedsPassword(); - } - - function applyPostValue () - { - parent::applyPostValue(); - $this->checkIfMethodNeedsPassword(); - } - - function checkIfMethodNeedsPassword() - { - $method = $this->attributes[0]->getValue(); - if ($method != $this->previousMethod) { - if (isset($this->needPassword[$method]) && $this->needPassword[$method]) { - $hashEmpty = ($this->attributes[3]->getValue() == ''); - $this->attributes[1]->setVisible(TRUE); - $this->attributes[1]->setRequired($hashEmpty); - $this->attributes[2]->setVisible(TRUE); - $this->attributes[2]->setRequired($hashEmpty); - } else { - $this->attributes[1]->setRequired(FALSE); - $this->attributes[1]->setVisible(FALSE); - $this->attributes[1]->setValue(''); - $this->attributes[2]->setRequired(FALSE); - $this->attributes[2]->setVisible(FALSE); - $this->attributes[2]->setValue(''); - } - } - $this->previousMethod = $method; - } - - function readValues($value) - { - global $config; - $pw_storage = $config->get_cfg_value('passwordDefaultHash', 'ssha'); - $locked = FALSE; - $password = ''; - if ($this->plugin->is_template && !empty($value)) { - if ($value == '%askme%') { - return array('%askme%', '', '', $value, $locked); - } - list($value, $password) = explode('|', $value, 2); - } - if (preg_match ('/^{[^}]+}/', $value)) { - $tmp = passwordMethod::get_method($value); - if (is_object($tmp)) { - $pw_storage = $tmp->get_hash(); - $locked = $tmp->is_locked($this->plugin->dn); - if ($this->plugin->is_template) { - $value = $tmp->generate_hash($password); - } - } - } elseif ($value != '') { - $pw_storage = 'clear'; - } elseif ($this->plugin->initially_was_account) { - $pw_storage = 'empty'; - } - return array($pw_storage, $password, $password, $value, $locked); - } - - function writeValues(array $values) - { - if ($this->plugin->is_template && ($values[0] == '%askme%')) { - return '%askme%'; - } - if (!$this->plugin->is_template && $this->needPassword[$values[0]] && ($values[1] == '')) { - return $values[3]; - } - $temp = passwordMethod::get_available_methods(); - if (!isset($temp[$values[0]])) { - trigger_error('Unknown password method '.$values[0]); - return $values[3]; - } - $test = new $temp[$values[0]]($this->plugin->dn, $this->plugin); - $test->set_hash($values[0]); - if ($this->plugin->is_template) { - return $test->generate_hash($values[1]).'|'.$values[1]; - } else { - return $test->generate_hash($values[1]); - } - } - - function check() - { - $method = $this->attributes[0]->getValue(); - $error = parent::check(); - if (!empty($error)) { - return $error; - } - if (($this->attributes[1]->getValue() != '') || ($this->attributes[2]->getValue() != '')) { - return user::reportPasswordProblems($this->plugin->dn, $this->attributes[1]->getValue(), $this->attributes[2]->getValue()); - } - } - - function getMethod() - { - return $this->attributes[0]->getValue(); - } - - function getClear() - { - return $this->attributes[1]->getValue(); - } - - function isLocked() - { - return $this->attributes[4]->getValue(); - } -} - class PostalAddressAttribute extends TextAreaAttribute { function inputValue ($ldapValue) @@ -609,22 +384,9 @@ class user extends simplePlugin if ($this->uid != '') { $skip[] = 'uid'; } - parent::adapt_from_template($attrs, $skip); + parent::adapt_from_template($attrs, array_merge($skip, array('userPassword'))); if (isset($this->attrs['userPassword']) && !in_array('userPassword', $skip)) { - list($hash,$password) = explode('|', $this->attrs['userPassword'][0], 2); - if (preg_match ('/^{[^}]+}/', $hash)) { - $tmp = passwordMethod::get_method($hash); - if (is_object($tmp)) { - $hash = $tmp->generate_hash($password); - } - } - $this->userPassword = array( - '', - $password, - $password, - $hash, - $this->attributesAccess['userPassword']->isLocked() - ); + $this->userPassword = $this->attributesAccess['userPassword']->readUserPasswordValues($this->attrs['userPassword'][0], TRUE); } }