| <?php␊ |
| /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */␊ |
| ␊ |
| /**␊ |
| * File::Passwd::Authbasic␊ |
| * ␊ |
| * PHP versions 4 and 5␊ |
| *␊ |
| * LICENSE: This source file is subject to version 3.0 of the PHP license␊ |
| * that is available through the world-wide-web at the following URI:␊ |
| * http://www.php.net/license/3_0.txt. If you did not receive a copy of␊ |
| * the PHP License and are unable to obtain it through the web, please␊ |
| * send a note to license@php.net so we can mail you a copy immediately.␊ |
| *␊ |
| * @category FileFormats␊ |
| * @package File_Passwd␊ |
| * @author Michael Wallner <mike@php.net>␊ |
| * @copyright 2003-2005 Michael Wallner␊ |
| * @license http://www.php.net/license/3_0.txt PHP License 3.0␊ |
| * @version CVS: $Id: Authbasic.php,v 1.17 2005/03/30 18:33:33 mike Exp $␊ |
| * @link http://pear.php.net/package/File_Passwd␊ |
| */␊ |
| ␊ |
| /**␊ |
| * Requires File::Passwd::Common␊ |
| */␊ |
| require_once 'File/Passwd/Common.php';␊ |
| ␊ |
| /**␊ |
| * Manipulate AuthUserFiles as used for HTTP Basic Authentication.␊ |
| *␊ |
| * <kbd><u>␊ |
| * Usage Example:␊ |
| * </u></kbd>␊ |
| * <code>␊ |
| * $htp = &File_Passwd::factory('AuthBasic');␊ |
| * $htp->setMode('sha');␊ |
| * $htp->setFile('/www/mike/auth/.htpasswd');␊ |
| * $htp->load();␊ |
| * $htp->addUser('mike', 'secret');␊ |
| * $htp->save();␊ |
| * </code>␊ |
| * ␊ |
| * <kbd><u>␊ |
| * Output of listUser()␊ |
| * </u></kbd>␊ |
| * <pre>␊ |
| * array␊ |
| * + user => crypted_passwd␊ |
| * + user => crypted_passwd␊ |
| * </pre>␊ |
| * ␊ |
| * @author Michael Wallner <mike@php.net>␊ |
| * @package File_Passwd␊ |
| * @version $Revision: 1.17 $␊ |
| * @access public␊ |
| */␊ |
| class File_Passwd_Authbasic extends File_Passwd_Common␊ |
| {␊ |
| /** ␊ |
| * Path to AuthUserFile␊ |
| *␊ |
| * @var string␊ |
| * @access private␊ |
| */␊ |
| var $_file = '.htpasswd';␊ |
| ␊ |
| /** ␊ |
| * Actual encryption mode␊ |
| *␊ |
| * @var string␊ |
| * @access private␊ |
| */␊ |
| var $_mode = 'sha';␊ |
| ␊ |
| /** ␊ |
| * Supported encryption modes␊ |
| *␊ |
| * @var array␊ |
| * @access private␊ |
| */␊ |
| var $_modes = array('plain' => 'p', 'md5' => 'm', 'des' => 'd', 'sha' => 's');␊ |
| ␊ |
| /** ␊ |
| * Constructor␊ |
| * ␊ |
| * @access public␊ |
| * @param string $file path to AuthUserFile␊ |
| */␊ |
| function File_Passwd_Authbasic($file = '.htpasswd')␊ |
| {␊ |
| File_Passwd_Authbasic::__construct($file);␊ |
| }␊ |
| ␊ |
| /**␊ |
| * Constructor (ZE2)␊ |
| * ␊ |
| * Rewritten because DES encryption is not ␊ |
| * supportet by the Win32 httpd.␊ |
| * ␊ |
| * @access protected␊ |
| * @param string $file path to AuthUserFile␊ |
| */␊ |
| function __construct($file = '.htpasswd')␊ |
| {␊ |
| if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {␊ |
| unset($this->_modes['des']);␊ |
| }␊ |
| $this->setFile($file);␊ |
| }␊ |
| ␊ |
| /**␊ |
| * Fast authentication of a certain user␊ |
| * ␊ |
| * Returns a PEAR_Error if:␊ |
| * o file doesn't exist␊ |
| * o file couldn't be opened in read mode␊ |
| * o file couldn't be locked exclusively␊ |
| * o file couldn't be unlocked (only if auth fails)␊ |
| * o file couldn't be closed (only if auth fails)␊ |
| *␊ |
| * @static call this method statically for a reasonable fast authentication␊ |
| * ␊ |
| * @throws PEAR_Error␊ |
| * @access public␊ |
| * @return mixed true if authenticated, false if not or PEAR_Error␊ |
| * @param string $file path to passwd file␊ |
| * @param string $user user to authenticate␊ |
| * @param string $pass plaintext password␊ |
| * @param string $mode des, sha or md5␊ |
| */␊ |
| function staticAuth($file, $user, $pass, $mode)␊ |
| {␊ |
| $line = File_Passwd_Common::_auth($file, $user);␊ |
| if (!$line || PEAR::isError($line)) {␊ |
| return $line;␊ |
| }␊ |
| list(,$real) = explode(':', $line);␊ |
| $crypted = File_Passwd_Authbasic::_genPass($pass, $real, $mode);␊ |
| if (PEAR::isError($crypted)) {␊ |
| return $crypted;␊ |
| }␊ |
| return ($real === $crypted);␊ |
| }␊ |
| ␊ |
| /** ␊ |
| * Apply changes and rewrite AuthUserFile␊ |
| *␊ |
| * Returns a PEAR_Error if:␊ |
| * o directory in which the file should reside couldn't be created␊ |
| * o file couldn't be opened in write mode␊ |
| * o file couldn't be locked exclusively␊ |
| * o file couldn't be unlocked␊ |
| * o file couldn't be closed␊ |
| * ␊ |
| * @throws PEAR_Error␊ |
| * @access public␊ |
| * @return mixed true on success or PEAR_Error␊ |
| */␊ |
| function save()␊ |
| {␊ |
| $content = '';␊ |
| foreach ($this->_users as $user => $pass) {␊ |
| $content .= $user . ':' . $pass . "\n";␊ |
| }␊ |
| return $this->_save($content);␊ |
| }␊ |
| ␊ |
| /** ␊ |
| * Add an user␊ |
| *␊ |
| * The username must start with an alphabetical character and must NOT␊ |
| * contain any other characters than alphanumerics, the underline and dash.␊ |
| * ␊ |
| * Returns a PEAR_Error if:␊ |
| * o user already exists␊ |
| * o user contains illegal characters␊ |
| * ␊ |
| * @throws PEAR_Error␊ |
| * @access public␊ |
| * @return mixed true on success or PEAR_Error␊ |
| * @param string $user␊ |
| * @param string $pass␊ |
| */␊ |
| function addUser($user, $pass)␊ |
| {␊ |
| if ($this->userExists($user)) {␊ |
| return PEAR::raiseError(␊ |
| sprintf(FILE_PASSWD_E_EXISTS_ALREADY_STR, 'User ', $user),␊ |
| FILE_PASSWD_E_EXISTS_ALREADY␊ |
| );␊ |
| }␊ |
| if (!preg_match($this->_pcre, $user)) {␊ |
| return PEAR::raiseError(␊ |
| sprintf(FILE_PASSWD_E_INVALID_CHARS_STR, 'User ', $user),␊ |
| FILE_PASSWD_E_INVALID_CHARS␊ |
| );␊ |
| }␊ |
| $this->_users[$user] = $this->_genPass($pass);␊ |
| return true;␊ |
| }␊ |
| ␊ |
| /** ␊ |
| * Change the password of a certain user␊ |
| *␊ |
| * Returns a PEAR_Error if user doesn't exist.␊ |
| * ␊ |
| * @throws PEAR_Error␊ |
| * @access public␊ |
| * @return mixed true on success or a PEAR_Error␊ |
| * @param string $user the user whose password should be changed␊ |
| * @param string $pass the new plaintext password␊ |
| */␊ |
| function changePasswd($user, $pass)␊ |
| {␊ |
| if (!$this->userExists($user)) {␊ |
| return PEAR::raiseError(␊ |
| sprintf(FILE_PASSWD_E_EXISTS_NOT_STR, 'User ', $user),␊ |
| FILE_PASSWD_E_EXISTS_NOT␊ |
| );␊ |
| }␊ |
| $this->_users[$user] = $this->_genPass($pass);␊ |
| return true;␊ |
| }␊ |
| ␊ |
| /** ␊ |
| * Verify password␊ |
| *␊ |
| * Returns a PEAR_Error if:␊ |
| * o user doesn't exist␊ |
| * o an invalid encryption mode was supplied␊ |
| * ␊ |
| * @throws PEAR_Error␊ |
| * @access public␊ |
| * @return mixed true if passwords equal, false if they don't, or PEAR_Error␊ |
| * @param string $user the user whose password should be verified␊ |
| * @param string $pass the plaintext password to verify␊ |
| */␊ |
| function verifyPasswd($user, $pass)␊ |
| {␊ |
| if (!$this->userExists($user)) {␊ |
| return PEAR::raiseError(␊ |
| sprintf(FILE_PASSWD_E_EXISTS_NOT_STR, 'User ', $user),␊ |
| FILE_PASSWD_E_EXISTS_NOT␊ |
| );␊ |
| }␊ |
| $real = $this->_users[$user];␊ |
| return ($real === $this->_genPass($pass, $real));␊ |
| }␊ |
| ␊ |
| /** ␊ |
| * Get actual encryption mode␊ |
| *␊ |
| * @access public␊ |
| * @return string␊ |
| */␊ |
| function getMode()␊ |
| {␊ |
| return $this->_mode;␊ |
| }␊ |
| ␊ |
| /** ␊ |
| * Get supported encryption modes␊ |
| *␊ |
| * <pre>␊ |
| * array␊ |
| * + md5␊ |
| * + sha␊ |
| * + des␊ |
| * </pre>␊ |
| * ␊ |
| * ATTN: DES encryption not available on Win32!␊ |
| * ␊ |
| * @access public␊ |
| * @return array␊ |
| */␊ |
| function listModes()␊ |
| {␊ |
| return array_keys($this->_modes);␊ |
| }␊ |
| ␊ |
| /** ␊ |
| * Set the encryption mode␊ |
| *␊ |
| * You can choose one of md5, sha or des.␊ |
| * ␊ |
| * ATTN: DES encryption not available on Win32!␊ |
| * ␊ |
| * Returns a PEAR_Error if a specific encryption mode is not supported.␊ |
| * ␊ |
| * @throws PEAR_Error␊ |
| * @access public␊ |
| * @return mixed true on succes or PEAR_Error␊ |
| * @param string $mode␊ |
| */␊ |
| function setMode($mode)␊ |
| {␊ |
| $mode = strToLower($mode);␊ |
| if (!isset($this->_modes[$mode])) {␊ |
| return PEAR::raiseError(␊ |
| sprintf(FILE_PASSWD_E_INVALID_ENC_MODE_STR, $this->_mode),␊ |
| FILE_PASSWD_E_INVALID_ENC_MODE␊ |
| );␊ |
| }␊ |
| $this->_mode = $mode;␊ |
| return true;␊ |
| }␊ |
| ␊ |
| /**␊ |
| * Generate password with htpasswd executable␊ |
| * ␊ |
| * @access private␊ |
| * @return string the crypted password␊ |
| * @param string $pass the plaintext password␊ |
| * @param string $salt the salt to use␊ |
| * @param string $mode encyption mode, usually determined from␊ |
| * <var>$this->_mode</var>␊ |
| */␊ |
| function _genPass($pass, $salt = null, $mode = null)␊ |
| {␊ |
| $mode = is_null($mode) ? strToLower($this->_mode) : strToLower($mode);␊ |
| ␊ |
| if ($mode == 'md5') {␊ |
| return File_Passwd::crypt_apr_md5($pass, $salt);␊ |
| } elseif ($mode == 'des') {␊ |
| return File_Passwd::crypt_des($pass, $salt);␊ |
| } elseif ($mode == 'sha') {␊ |
| return File_Passwd::crypt_sha($pass, $salt);␊ |
| } else if ($mode == 'plain') {␊ |
| return $pass;␊ |
| ␉}␊ |
| ␊ |
| return PEAR::raiseError(␊ |
| sprintf(FILE_PASSWD_E_INVALID_ENC_MODE_STR, $mode),␊ |
| FILE_PASSWD_E_INVALID_ENC_MODE ␊ |
| );␊ |
| }␊ |
| ␊ |
| /** ␊ |
| * Parse the AuthUserFile␊ |
| * ␊ |
| * Returns a PEAR_Error if AuthUserFile has invalid format.␊ |
| *␊ |
| * @throws PEAR_Error␊ |
| * @access public␊ |
| * @return mixed true on success or PEAR_error␊ |
| */␊ |
| function parse()␊ |
| {␊ |
| $this->_users = array();␊ |
| foreach ($this->_contents as $line) {␊ |
| $user = explode(':', $line);␊ |
| if (count($user) != 2) {␊ |
| return PEAR::raiseError(␊ |
| FILE_PASSWD_E_INVALID_FORMAT_STR,␊ |
| FILE_PASSWD_E_INVALID_FORMAT␊ |
| );␊ |
| }␊ |
| $this->_users[$user[0]] = trim($user[1]);␊ |
| }␊ |
| $this->_contents = array();␊ |
| return true;␊ |
| }␊ |
| ␊ |
| /**␊ |
| * Generate Password␊ |
| * ␊ |
| * Returns PEAR_Error FILE_PASSD_E_INVALID_ENC_MODE if the supplied␊ |
| * encryption mode is not supported.␊ |
| *␊ |
| * @static␊ |
| * @access public␊ |
| * @return mixed The crypted password on success or PEAR_Error on failure.␊ |
| * @param string $pass The plaintext password.␊ |
| * @param string $mode The encryption mode to use (des|md5|sha).␊ |
| * @param string $salt The salt to use.␊ |
| */␊ |
| function generatePasswd($pass, $mode = FILE_PASSWD_DES, $salt = null)␊ |
| {␊ |
| if (!in_array(strToLower($mode), array('des', 'md5', 'sha'))) {␊ |
| return PEAR::raiseError(␊ |
| sprintf(FILE_PASSWD_E_INVALID_ENC_MODE_STR, $this->_mode),␊ |
| FILE_PASSWD_E_INVALID_ENC_MODE ␊ |
| );␊ |
| }␊ |
| return File_Passwd_Authbasic::_genPass($pass, $salt, $mode);␊ |
| }␊ |
| ␊ |
| /**␊ |
| * @ignore␊ |
| * @deprecated␊ |
| */␊ |
| function generatePassword($pass, $mode = FILE_PASSWD_DES, $salt = null)␊ |
| {␊ |
| return File_Passwd_Authbasic::generatePasswd($pass, $mode, $salt);␊ |
| }␊ |
| }␊ |