PageRenderTime 61ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/php-pear-File-Passwd-1.1.7/File_Passwd-1.1.7/Passwd/Authbasic.php

#
PHP | 396 lines | 145 code | 21 blank | 230 comment | 17 complexity | 9bb60d8ddf459b382c0231440289dcb9 MD5 | raw file
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. /**
  4. * File::Passwd::Authbasic
  5. *
  6. * PHP versions 4 and 5
  7. *
  8. * LICENSE: This source file is subject to version 3.0 of the PHP license
  9. * that is available through the world-wide-web at the following URI:
  10. * http://www.php.net/license/3_0.txt. If you did not receive a copy of
  11. * the PHP License and are unable to obtain it through the web, please
  12. * send a note to license@php.net so we can mail you a copy immediately.
  13. *
  14. * @category FileFormats
  15. * @package File_Passwd
  16. * @author Michael Wallner <mike@php.net>
  17. * @copyright 2003-2005 Michael Wallner
  18. * @license http://www.php.net/license/3_0.txt PHP License 3.0
  19. * @version CVS: $Id: Authbasic.php,v 1.17 2005/03/30 18:33:33 mike Exp $
  20. * @link http://pear.php.net/package/File_Passwd
  21. */
  22. /**
  23. * Requires File::Passwd::Common
  24. */
  25. require_once 'File/Passwd/Common.php';
  26. /**
  27. * Manipulate AuthUserFiles as used for HTTP Basic Authentication.
  28. *
  29. * <kbd><u>
  30. * Usage Example:
  31. * </u></kbd>
  32. * <code>
  33. * $htp = &File_Passwd::factory('AuthBasic');
  34. * $htp->setMode('sha');
  35. * $htp->setFile('/www/mike/auth/.htpasswd');
  36. * $htp->load();
  37. * $htp->addUser('mike', 'secret');
  38. * $htp->save();
  39. * </code>
  40. *
  41. * <kbd><u>
  42. * Output of listUser()
  43. * </u></kbd>
  44. * <pre>
  45. * array
  46. * + user => crypted_passwd
  47. * + user => crypted_passwd
  48. * </pre>
  49. *
  50. * @author Michael Wallner <mike@php.net>
  51. * @package File_Passwd
  52. * @version $Revision: 1.17 $
  53. * @access public
  54. */
  55. class File_Passwd_Authbasic extends File_Passwd_Common
  56. {
  57. /**
  58. * Path to AuthUserFile
  59. *
  60. * @var string
  61. * @access private
  62. */
  63. var $_file = '.htpasswd';
  64. /**
  65. * Actual encryption mode
  66. *
  67. * @var string
  68. * @access private
  69. */
  70. var $_mode = 'sha';
  71. /**
  72. * Supported encryption modes
  73. *
  74. * @var array
  75. * @access private
  76. */
  77. var $_modes = array('md5' => 'm', 'des' => 'd', 'sha' => 's');
  78. /**
  79. * Constructor
  80. *
  81. * @access public
  82. * @param string $file path to AuthUserFile
  83. */
  84. function File_Passwd_Authbasic($file = '.htpasswd')
  85. {
  86. File_Passwd_Authbasic::__construct($file);
  87. }
  88. /**
  89. * Constructor (ZE2)
  90. *
  91. * Rewritten because DES encryption is not
  92. * supportet by the Win32 httpd.
  93. *
  94. * @access protected
  95. * @param string $file path to AuthUserFile
  96. */
  97. function __construct($file = '.htpasswd')
  98. {
  99. if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
  100. unset($this->_modes['des']);
  101. }
  102. $this->setFile($file);
  103. }
  104. /**
  105. * Fast authentication of a certain user
  106. *
  107. * Returns a PEAR_Error if:
  108. * o file doesn't exist
  109. * o file couldn't be opened in read mode
  110. * o file couldn't be locked exclusively
  111. * o file couldn't be unlocked (only if auth fails)
  112. * o file couldn't be closed (only if auth fails)
  113. *
  114. * @static call this method statically for a reasonable fast authentication
  115. *
  116. * @throws PEAR_Error
  117. * @access public
  118. * @return mixed true if authenticated, false if not or PEAR_Error
  119. * @param string $file path to passwd file
  120. * @param string $user user to authenticate
  121. * @param string $pass plaintext password
  122. * @param string $mode des, sha or md5
  123. */
  124. function staticAuth($file, $user, $pass, $mode)
  125. {
  126. $line = File_Passwd_Common::_auth($file, $user);
  127. if (!$line || PEAR::isError($line)) {
  128. return $line;
  129. }
  130. list(,$real) = explode(':', $line);
  131. $crypted = File_Passwd_Authbasic::_genPass($pass, $real, $mode);
  132. if (PEAR::isError($crypted)) {
  133. return $crypted;
  134. }
  135. return ($real === $crypted);
  136. }
  137. /**
  138. * Apply changes and rewrite AuthUserFile
  139. *
  140. * Returns a PEAR_Error if:
  141. * o directory in which the file should reside couldn't be created
  142. * o file couldn't be opened in write mode
  143. * o file couldn't be locked exclusively
  144. * o file couldn't be unlocked
  145. * o file couldn't be closed
  146. *
  147. * @throws PEAR_Error
  148. * @access public
  149. * @return mixed true on success or PEAR_Error
  150. */
  151. function save()
  152. {
  153. $content = '';
  154. foreach ($this->_users as $user => $pass) {
  155. $content .= $user . ':' . $pass . "\n";
  156. }
  157. return $this->_save($content);
  158. }
  159. /**
  160. * Add an user
  161. *
  162. * The username must start with an alphabetical character and must NOT
  163. * contain any other characters than alphanumerics, the underline and dash.
  164. *
  165. * Returns a PEAR_Error if:
  166. * o user already exists
  167. * o user contains illegal characters
  168. *
  169. * @throws PEAR_Error
  170. * @access public
  171. * @return mixed true on success or PEAR_Error
  172. * @param string $user
  173. * @param string $pass
  174. */
  175. function addUser($user, $pass)
  176. {
  177. if ($this->userExists($user)) {
  178. return PEAR::raiseError(
  179. sprintf(FILE_PASSWD_E_EXISTS_ALREADY_STR, 'User ', $user),
  180. FILE_PASSWD_E_EXISTS_ALREADY
  181. );
  182. }
  183. if (!preg_match($this->_pcre, $user)) {
  184. return PEAR::raiseError(
  185. sprintf(FILE_PASSWD_E_INVALID_CHARS_STR, 'User ', $user),
  186. FILE_PASSWD_E_INVALID_CHARS
  187. );
  188. }
  189. $this->_users[$user] = $this->_genPass($pass);
  190. return true;
  191. }
  192. /**
  193. * Change the password of a certain user
  194. *
  195. * Returns a PEAR_Error if user doesn't exist.
  196. *
  197. * @throws PEAR_Error
  198. * @access public
  199. * @return mixed true on success or a PEAR_Error
  200. * @param string $user the user whose password should be changed
  201. * @param string $pass the new plaintext password
  202. */
  203. function changePasswd($user, $pass)
  204. {
  205. if (!$this->userExists($user)) {
  206. return PEAR::raiseError(
  207. sprintf(FILE_PASSWD_E_EXISTS_NOT_STR, 'User ', $user),
  208. FILE_PASSWD_E_EXISTS_NOT
  209. );
  210. }
  211. $this->_users[$user] = $this->_genPass($pass);
  212. return true;
  213. }
  214. /**
  215. * Verify password
  216. *
  217. * Returns a PEAR_Error if:
  218. * o user doesn't exist
  219. * o an invalid encryption mode was supplied
  220. *
  221. * @throws PEAR_Error
  222. * @access public
  223. * @return mixed true if passwords equal, false if they don't, or PEAR_Error
  224. * @param string $user the user whose password should be verified
  225. * @param string $pass the plaintext password to verify
  226. */
  227. function verifyPasswd($user, $pass)
  228. {
  229. if (!$this->userExists($user)) {
  230. return PEAR::raiseError(
  231. sprintf(FILE_PASSWD_E_EXISTS_NOT_STR, 'User ', $user),
  232. FILE_PASSWD_E_EXISTS_NOT
  233. );
  234. }
  235. $real = $this->_users[$user];
  236. return ($real === $this->_genPass($pass, $real));
  237. }
  238. /**
  239. * Get actual encryption mode
  240. *
  241. * @access public
  242. * @return string
  243. */
  244. function getMode()
  245. {
  246. return $this->_mode;
  247. }
  248. /**
  249. * Get supported encryption modes
  250. *
  251. * <pre>
  252. * array
  253. * + md5
  254. * + sha
  255. * + des
  256. * </pre>
  257. *
  258. * ATTN: DES encryption not available on Win32!
  259. *
  260. * @access public
  261. * @return array
  262. */
  263. function listModes()
  264. {
  265. return array_keys($this->_modes);
  266. }
  267. /**
  268. * Set the encryption mode
  269. *
  270. * You can choose one of md5, sha or des.
  271. *
  272. * ATTN: DES encryption not available on Win32!
  273. *
  274. * Returns a PEAR_Error if a specific encryption mode is not supported.
  275. *
  276. * @throws PEAR_Error
  277. * @access public
  278. * @return mixed true on succes or PEAR_Error
  279. * @param string $mode
  280. */
  281. function setMode($mode)
  282. {
  283. $mode = strToLower($mode);
  284. if (!isset($this->_modes[$mode])) {
  285. return PEAR::raiseError(
  286. sprintf(FILE_PASSWD_E_INVALID_ENC_MODE_STR, $this->_mode),
  287. FILE_PASSWD_E_INVALID_ENC_MODE
  288. );
  289. }
  290. $this->_mode = $mode;
  291. return true;
  292. }
  293. /**
  294. * Generate password with htpasswd executable
  295. *
  296. * @access private
  297. * @return string the crypted password
  298. * @param string $pass the plaintext password
  299. * @param string $salt the salt to use
  300. * @param string $mode encyption mode, usually determined from
  301. * <var>$this->_mode</var>
  302. */
  303. function _genPass($pass, $salt = null, $mode = null)
  304. {
  305. $mode = is_null($mode) ? strToLower($this->_mode) : strToLower($mode);
  306. if ($mode == 'md5') {
  307. return File_Passwd::crypt_apr_md5($pass, $salt);
  308. } elseif ($mode == 'des') {
  309. return File_Passwd::crypt_des($pass, $salt);
  310. } elseif ($mode == 'sha') {
  311. return File_Passwd::crypt_sha($pass, $salt);
  312. }
  313. return PEAR::raiseError(
  314. sprintf(FILE_PASSWD_E_INVALID_ENC_MODE_STR, $mode),
  315. FILE_PASSWD_E_INVALID_ENC_MODE
  316. );
  317. }
  318. /**
  319. * Parse the AuthUserFile
  320. *
  321. * Returns a PEAR_Error if AuthUserFile has invalid format.
  322. *
  323. * @throws PEAR_Error
  324. * @access public
  325. * @return mixed true on success or PEAR_error
  326. */
  327. function parse()
  328. {
  329. $this->_users = array();
  330. foreach ($this->_contents as $line) {
  331. $user = explode(':', $line);
  332. if (count($user) != 2) {
  333. return PEAR::raiseError(
  334. FILE_PASSWD_E_INVALID_FORMAT_STR,
  335. FILE_PASSWD_E_INVALID_FORMAT
  336. );
  337. }
  338. $this->_users[$user[0]] = trim($user[1]);
  339. }
  340. $this->_contents = array();
  341. return true;
  342. }
  343. /**
  344. * Generate Password
  345. *
  346. * Returns PEAR_Error FILE_PASSD_E_INVALID_ENC_MODE if the supplied
  347. * encryption mode is not supported.
  348. *
  349. * @static
  350. * @access public
  351. * @return mixed The crypted password on success or PEAR_Error on failure.
  352. * @param string $pass The plaintext password.
  353. * @param string $mode The encryption mode to use (des|md5|sha).
  354. * @param string $salt The salt to use.
  355. */
  356. function generatePasswd($pass, $mode = FILE_PASSWD_DES, $salt = null)
  357. {
  358. if (!in_array(strToLower($mode), array('des', 'md5', 'sha'))) {
  359. return PEAR::raiseError(
  360. sprintf(FILE_PASSWD_E_INVALID_ENC_MODE_STR, $mode),
  361. FILE_PASSWD_E_INVALID_ENC_MODE
  362. );
  363. }
  364. return File_Passwd_Authbasic::_genPass($pass, $salt, $mode);
  365. }
  366. /**
  367. * @ignore
  368. * @deprecated
  369. */
  370. function generatePassword($pass, $mode = FILE_PASSWD_DES, $salt = null)
  371. {
  372. return File_Passwd_Authbasic::generatePasswd($pass, $mode, $salt);
  373. }
  374. }
  375. ?>