class_password-methods.inc 10.30 KiB
<?php
/*
  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
  Copyright (C) 2003-2010  Cajus Pollmeier
  Copyright (C) 2011-2016  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.
 * \file class_pasword-methods.inc
 * Source code for class password-methods
/*!
 * \brief This class contains all the basic function for password methods
class passwordMethod
  var $attrs    = array();
  var $display  = FALSE;
  var $hash     = "";
  var $lockable = TRUE;
  /*!
   * \brief Password method contructor
   * \param string $dn The DN
  function __construct($dn = "")
  /*!
   * \brief Get the Hash name
  static function get_hash_name()
    trigger_error("get_hash_name can't be called on main class");
  /*!
   * \brief If we need password
   * \return boolean TRUE
  function need_password()
    return TRUE;
  /*!
   * \brief Is locked
   * \param string $dn The DN
  function is_locked($dn = "")
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
{ global $config; if (!$this->lockable) { return FALSE; } /* Get current password hash */ $pwd = ""; if (!empty($dn)) { $ldap = $config->get_ldap_link(); $ldap->cd($config->current['BASE']); $ldap->cat($dn); $attrs = $ldap->fetch(); if (isset($attrs['userPassword'][0])) { $pwd = $attrs['userPassword'][0]; } } elseif (isset($this->attrs['userPassword'][0])) { $pwd = $this->attrs['userPassword'][0]; } return preg_match("/^[^\}]*+\}!/", $pwd); } /*! \brief Locks an account by adding a '!' as prefix to the password hashes. * This makes login impossible, due to the fact that the hash becomes invalid. * userPassword: {SHA}!q02NKl9IChNwZEAJxzRdmB6E * sambaLMPassword: !EBD223B61F8C259AD3B435B51404EE * sambaNTPassword: !98BB35737013AAF181D0FE9FDA09E * * \param string $dn */ function lock_account($dn = "") { return $this->generic_modify_account($dn, 'LOCK'); } /*! * \brief Unlocks an account which was locked by 'lock_account()'. * For details about the locking mechanism see 'lock_account()'. */ function unlock_account($dn = "") { return $this->generic_modify_account($dn, 'UNLOCK'); } /*! * \brief Unlocks an account which was locked by 'lock_account()'. * For details about the locking mechanism see 'lock_account()'. */ private function generic_modify_account($dn, $mode) { global $config; if (!$this->lockable) { return FALSE; } if ($mode != 'LOCK' && $mode != 'UNLOCK') { die('Invalid mode "'.$mode.'"'); } /* Get current password hash */ $attrs = $this->attrs; $pwd = ""; $ldap = $config->get_ldap_link(); $ldap->cd($config->current['BASE']); if (!empty($dn)) { $ldap->cat($dn); $attrs = $ldap->fetch(); } if (isset($attrs['userPassword'][0])) { $pwd = $attrs['userPassword'][0]; $dn = $attrs['dn'];
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
} /* 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') { return TRUE; } // (Un)lock the samba account $modify = lock_samba_account($mode, $attrs); // (Un)lock SSH keys lock_ssh_account($mode, $attrs, $modify); // (Un)lock the account by modifying the password hash. $pwdClass = new user($dn); $pwdClass->callHook('PRE'.$mode, array(), $ret); if ($mode == 'LOCK') { /* Lock entry */ $pwd = preg_replace("/(^[^\}]+\})(.*$)/", "\\1!\\2", $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()) { $pwdClass->callHook('POST'.$mode, array(), $ret); } else { msg_dialog::display(_('LDAP error'), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_MOD), LDAP_ERROR); } return $ldap->success(); } return FALSE; } /*! * \brief This function returns all loaded classes for password encryption */ static function get_available_methods() { global $class_mapping, $config; $ret = FALSE; $i = 0; /* Only */ if (!session::is_set("passwordMethod::get_available_methods")) { foreach (array_keys($class_mapping) as $class) { if (preg_match('/passwordMethod/i', $class) && !preg_match("/^passwordMethod$/i", $class)) { $test = new $class(""); if ($test->is_available()) { $plugs = $test->get_hash_name(); if (!is_array($plugs)) { $plugs = array($plugs); } foreach ($plugs as $plugname) { $cfg = $test->is_configurable();
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
$ret['name'][$i] = $plugname; $ret['class'][$i] = $class; $ret['is_configurable'][$i] = $cfg; $ret['object'][$i] = $test; $ret['desc'][$i] = $test->get_description(); $ret[$i]['name'] = $plugname; $ret[$i]['class'] = $class; $ret[$i]['object'] = $test; $ret[$i]['is_configurable'] = $cfg; $ret[$i]['desc'] = $test->get_description(); $ret[$plugname] = $class; $i++; } } } } session::set("passwordMethod::get_available_methods", $ret); } return session::get("passwordMethod::get_available_methods"); } /*! * \brief Get desciption */ function get_description() { return ""; } /*! * \brief Method to let password backends remove additional information besides * the userPassword attribute */ function remove_from_parent() { } /*! * \brief Method to check if a password matches a hash */ function checkPassword($pwd, $hash) { return ($hash == $this->generate_hash($pwd)); } /*! * \brief Return true if this password method provides a configuration dialog */ function is_configurable() { return FALSE; } /*! * \brief Provide a subdialog to configure a password method */ function configure() { return ""; } /*! * \brief Save information to LDAP * * \param string $dn The DN */ function save($dn)
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
{ } /*! * \brief Try to find out if it's our hash... * * \param string $password_hash * * \param string $dn The DN */ static function get_method($password_hash, $dn = "") { global $config; $methods = passwordMethod::get_available_methods(); foreach ($methods['class'] as $class) { $method = $class::_extract_method($class, $password_hash); if ($method != "") { $test = new $class($dn); $test->set_hash($method); return $test; } } $method = new passwordMethodClear($dn); $method->set_hash('clear'); return $method; } /*! * \brief Extract a method * * \param string $password_hash */ static function _extract_method($classname, $password_hash) { $hash = $classname::get_hash_name(); if (preg_match("/^\{$hash\}/i", $password_hash)) { return $hash; } return ""; } /*! * \brief Make a hash * * \param string $password The password * * \param string $hash */ static function make_hash($password, $hash) { $methods = passwordMethod::get_available_methods(); $tmp = new $methods[$hash](); $tmp->set_hash($hash); return $tmp->generate_hash($password); } /*! * \brief Set a hash * * \param string $hash */ function set_hash($hash) { $this->hash = $hash; }
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
/*! * \brief Get a hash */ function get_hash() { return $this->hash; } /*! * \brief Test for problematic unicode caracters in password * This can be activated with the keyword strictPasswordRules in the * fusiondirectory.conf * * \param string $password The password */ static function is_harmless($password) { global $config; if ($config->get_cfg_value("strictPasswordRules") == "TRUE") { // Do we have UTF8 characters in the password? return ($password == utf8_decode($password)); } return TRUE; } /*! * \brief Get the password proposal */ static function getPasswordProposal() { global $config; if ($config->get_cfg_value('passwordProposalHook', '') != '') { $command = $config->get_cfg_value('passwordProposalHook', ''); if (check_command($command)) { @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Execute"); exec($command, $arr, $returnCode); if ($returnCode != 0) { $str = implode("\n", $arr); @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Execution failed code: ".$returnCode); $message = msgPool::cmdexecfailed($cmd, $command, get_class($plugin)); msg_dialog::display(_("Error"), $message, ERROR_DIALOG); } elseif (is_array($arr)) { $str = implode("\n", $arr); @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Result: ".$str); if (count($arr) && !empty($arr[0])) { return $arr[0]; } } } else { $message = msgPool::cmdinvalid($cmd, $command, get_class($plugin)); msg_dialog::display(_("Error"), $message, ERROR_DIALOG); } } return ''; } } ?>