htpasswd.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <?php
  2. include_once ("model/meta_model.php");
  3. include_once ("hash_tool.php");
  4. /**
  5. * htpasswd tools for Apache Basic Auth.
  6. *
  7. * Uses crypt only!
  8. */
  9. class htpasswd {
  10. var $fp;
  11. var $metafp;
  12. var $filename;
  13. var $metafilename;
  14. var $use_metadata;
  15. /* All ht-files. These files are stored within the secured folder. */
  16. const HTPASSWD_NAME = ".htpasswd";
  17. const HTACCESS_NAME = ".htaccess";
  18. const HTMETA_NAME = ".htmeta";
  19. function htpasswd($configpath, $use_metadata = false) {
  20. $path = realpath ( $configpath );
  21. $htaccessfile = $path . "/" . self::HTACCESS_NAME;
  22. $htpasswdfile = $path . "/" . self::HTPASSWD_NAME;
  23. @$this->use_metadata = $use_metadata;
  24. if (! file_exists ( $htaccessfile )) {
  25. $bdfp = fopen ( $htaccessfile, 'w' );
  26. $htaccess_content = "AuthType Basic\nAuthName \"Password Protected Area\"\nAuthUserFile \"" . $htpasswdfile . "\"\nRequire valid-user" . "\n<Files .ht*>\nOrder deny,allow\nDeny from all\n</Files>";
  27. fwrite ( $bdfp, $htaccess_content );
  28. }
  29. @$this->fp = @$this::open_or_create ( $htpasswdfile );
  30. if ($use_metadata) {
  31. $htmetafile = $path . "/" . self::HTMETA_NAME;
  32. @$this->metafp = @$this::open_or_create ( $htmetafile );
  33. $this->metafilename = $htmetafile;
  34. }
  35. $this->filename = $htpasswdfile;
  36. }
  37. function user_exists($username) {
  38. return self::exists ( @$this->fp, $username );
  39. }
  40. function meta_exists($username) {
  41. return self::exists ( @$this->metafp, $username );
  42. }
  43. function meta_find_user_for_mail($email) {
  44. while ( ! feof ( $this->metafp ) && $meta = explode ( ":", $line = rtrim ( fgets ( $this->metafp ) ) ) ) {
  45. if (count ( $meta ) > 1) {
  46. $username = trim ( $meta [0] );
  47. $lemail = $meta [1];
  48. if ($lemail == $email) {
  49. return $username;
  50. }
  51. }
  52. }
  53. return null;
  54. }
  55. function get_metadata() {
  56. rewind ( $this->metafp );
  57. $meta_model_map = array ();
  58. $metaarr = array ();
  59. while ( ! feof ( $this->metafp ) && $line = rtrim ( fgets ( $this->metafp ) ) ) {
  60. $metaarr = explode ( ":", $line );
  61. $model = new meta_model ();
  62. $model->user = $metaarr [0];
  63. if (count ( $metaarr ) > 1) {
  64. $model->email = $metaarr [1];
  65. }
  66. if (count ( $metaarr ) > 2) {
  67. $model->name = $metaarr [2];
  68. }
  69. if (count ( $metaarr ) > 3) {
  70. $model->mailkey = $metaarr [3];
  71. }
  72. $meta_model_map [$model->user] = $model;
  73. }
  74. return $meta_model_map;
  75. }
  76. function get_users() {
  77. rewind ( $this->fp );
  78. $users = array ();
  79. $i = 0;
  80. while ( ! feof ( $this->fp ) && trim ( $lusername = array_shift ( explode ( ":", $line = rtrim ( fgets ( $this->fp ) ) ) ) ) ) {
  81. $users [$i] = $lusername;
  82. $i ++;
  83. }
  84. return $users;
  85. }
  86. function user_add($username, $password) {
  87. if ($this->user_exists ( $username ))
  88. return false;
  89. fseek ( $this->fp, 0, SEEK_END );
  90. fwrite ( $this->fp, $username . ':' . self::htcrypt ( $password ) . "\n" );
  91. return true;
  92. }
  93. function meta_add(meta_model $meta_model) {
  94. if (self::exists ( @$this->metafp, $meta_model->user )) {
  95. return false;
  96. }
  97. fseek ( $this->metafp, 0, SEEK_END );
  98. fwrite ( $this->metafp, $meta_model->user . ':' . $meta_model->email . ':' . $meta_model->name . ':' . $meta_model->mailkey . "\n" );
  99. return true;
  100. }
  101. /**
  102. * Login check
  103. * first 2 characters of hash is the salt.
  104. *
  105. * @param user $username
  106. * @param pass $password
  107. * @return boolean true if password is correct!
  108. */
  109. function user_check($username, $password) {
  110. rewind ( $this->fp );
  111. while ( ! feof ( $this->fp ) && $userpass = explode ( ":", $line = rtrim ( fgets ( $this->fp ) ) ) ) {
  112. $lusername = trim ( $userpass [0] );
  113. $hash = trim ($userpass [1] );
  114. if ($lusername == $username) {
  115. $validator = self::create_hash_tool($hash);
  116. return $validator->check_password_hash($password, $hash);
  117. }
  118. }
  119. return false;
  120. }
  121. function user_delete($username) {
  122. return self::delete ( @$this->fp, $username, @$this->filename );
  123. }
  124. function meta_delete($username) {
  125. return self::delete ( @$this->metafp, $username, @$this->metafilename );
  126. }
  127. function user_update($username, $password) {
  128. rewind ( $this->fp );
  129. while ( ! feof ( $this->fp ) && trim ( $lusername = array_shift ( explode ( ":", $line = rtrim ( fgets ( $this->fp ) ) ) ) ) ) {
  130. if ($lusername == $username) {
  131. fseek ( $this->fp, (- 15 - strlen ( $username )), SEEK_CUR );
  132. fwrite ( $this->fp, $username . ':' . self::htcrypt ( $password ) . "\n" );
  133. return true;
  134. }
  135. }
  136. return false;
  137. }
  138. function meta_update(meta_model $meta_model) {
  139. $this->meta_delete ( $meta_model->user );
  140. $this->meta_add ( $meta_model );
  141. return false;
  142. }
  143. static function write_meta_line($fp, meta_model $meta_model) {
  144. fwrite ( $fp, $meta_model->user . ':' . $meta_model->email . ':' . $meta_model->name . "\n" );
  145. }
  146. static function exists($fp, $username) {
  147. rewind ( $fp );
  148. while ( ! feof ( $fp ) && trim ( $lusername = array_shift ( explode ( ":", $line = rtrim ( fgets ( $fp ) ) ) ) ) ) {
  149. if ($lusername == $username)
  150. return true;
  151. }
  152. return false;
  153. }
  154. static function open_or_create($filename) {
  155. if (! file_exists ( $filename )) {
  156. return fopen ( $filename, 'w+' );
  157. } else {
  158. return fopen ( $filename, 'r+' );
  159. }
  160. }
  161. static function delete($fp, $username, $filename) {
  162. $data = '';
  163. rewind ( $fp );
  164. while ( ! feof ( $fp ) && trim ( $lusername = array_shift ( explode ( ":", $line = rtrim ( fgets ( $fp ) ) ) ) ) ) {
  165. if (! trim ( $line ))
  166. break;
  167. if ($lusername != $username)
  168. $data .= $line . "\n";
  169. }
  170. $fp = fopen ( $filename, 'w' );
  171. fwrite ( $fp, rtrim ( $data ) . (trim ( $data ) ? "\n" : '') );
  172. fclose ( $fp );
  173. $fp = fopen ( $filename, 'r+' );
  174. return true;
  175. }
  176. static function htcrypt($password) {
  177. return crypt ( $password, substr ( str_replace ( '+', '.', base64_encode ( pack ( 'N4', mt_rand (), mt_rand (), mt_rand (), mt_rand () ) ) ), 0, 22 ) );
  178. }
  179. static function create_hash_tool($hash) {
  180. if (strpos($hash, '$apr1') === 0) {
  181. return new md5_hash_tool();
  182. } else {
  183. return new crypt_hash_tool();
  184. }
  185. }
  186. }
  187. ?>