Page 1 of 1

edit .htpasswd file through php

Posted: Tue Mar 27, 2007 3:38 pm
by benyboi
is it poissible to have a php page where a user can enter a new password and it will update the .htpasswd file?

if so, how?

thanks!

Posted: Tue Mar 27, 2007 5:42 pm
by feyd
Why not just have PHP do the password protection?

Re: edit .htpasswd file through php

Posted: Wed Mar 28, 2007 1:23 am
by s.dot
benyboi wrote:is it poissible to have a php page where a user can enter a new password and it will update the .htpasswd file?

if so, how?

thanks!
Yes.

Using a nifty combination of reading the text file with file() or file_get_contents(), searching for what you're looking for with explode(), replacing the old password with str_replace, and writing the new .htpasswd file with fopen(), fwrite(), and fclose() (or file_put_contents() for php5+)

Posted: Wed Mar 28, 2007 1:41 am
by leewad
You can use the following:

Code: Select all

<?PHP

    //    username and password values
  
    $pwd= $_POST['password'];
    $usr= $_POST['username'];

    //    directory of .htpasswd

   $url = $DOCUMENT_ROOT . dirname($PHP_SELF) . "/.htpasswd";

   //    make .htaccess and .htpasswd

   $htaccess_txt  = "AuthType Basic" . "\n";
   $htaccess_txt .= "AuthName \" Login Area\"" . "\n";
   $htaccess_txt .= "AuthUserFile $url" . "\n";
   $htaccess_txt .= "require valid-user" . "\n";

    $htpasswd_txt .= "$usr:".crypt($pwd,CRYPT_STD_DES)."\n";

   // save files

   $htaccess= fopen(".htaccess", "w");
   $htpasswd= fopen(".htpasswd", "w");

   fputs($htaccess, $htaccess_txt);
   fputs($htpasswd, $htpasswd_txt);
   fclose($htaccess);
   fclose($htpasswd);

?>

Posted: Wed Mar 28, 2007 2:07 am
by mikeq
I did this very thing a few weeks ago.

I found this class on the web

Code: Select all

<?php 
/*************************************\ 
| htpasswd class                      | 
| By Jorge Schrauwen 2007             | 
| http://www.blackdot.be              | 
\*************************************/ 

/* 
Usage: 
require('htpasswd.php'); 

$pwmanager = new htpasswd('.htpasswd'); 
$pwmanager->create('test', 'pass'); 
$pwmanager->save(); 

Functions: 
create('MyUser', 'Pass')      : create MyUser with password Pass. (true/false) 
remove('MyUser')              : remove MyUser. (true/false) 
validate('MyUser', 'Pass')    : will validate the user. (true/false) 
display()                     : return and array with the usernames. 
save()                        : save the password file. (true/false) 
save('/server/www/.htpasswd') : save the password file to /server/www/.htpasswd. (true/false) 

Error Handling: 
when a function returns false you can get more information via 
echo $pwmanager->error; 
*/ 

class htpasswd{ 
   public $users; 
   public $error; 
   private $_path;    

   function htpasswd($file=false){ 
      if(!$file){ 
         die('Please specify a file!'); 
      }else{    
         //configure 
         $this->_path = $file; 
         $this->users = ''; 
         //load database 
         if(file_exists($file)){ 
            $data = array(); 
            $fcontents = file($file); 
            while(list($line_num, $line) = each($fcontents)){ 
               $user = explode(':',$line); 
               //$user = $arraydata[0]; 
               $data[$user[0]] = chop($user[1]); 
            } 
            $this->users = $data; 
         } 
      } 
   } 
          
   function create($user, $passwd, $update=false){ 
      $this->error = ''; 
      if(isset($this->users[$user]) && !$update){ 
         $this->error = 'User <strong>'.$user.'</strong> exists! To update the user set the update parameter to true.'; 
         return false; 
      } 
      $this->users[$user] = $this->non_salted_sha1($passwd); 
      return true; 
   } 
    
   function remove($user){ 
      $this->error = ''; 
      if(isset($this->users[$user])){ 
         unset($this->users[$user]); 
         return true; 
      }else{ 
         $this->error = 'User <strong>'.$user.'</strong> does not exist!'; 
         return false; 
      } 
   } 
    
   function users(){ 
      $this->error = ''; 
      $rval = Array(); 
      if(is_array($this->users)){ 
         foreach(array_keys($this->users) as $uid){ 
            $rval[count($rval)] = $uid; 
         } 
      } 
      return $rval; 
   } 
       
   function validate($user, $pass){ 
      $this->error = ''; 
      if(!isset($this->users[$user])) return False; 
      $crypted = $this->users[$user]; 
       
      if(substr($crypted, 0, 6) == "{SSHA}"){ 
         $ohash = base64_decode(substr($crypted, 6)); 
         return substr($ohash, 0, 20) == pack("H*", sha1($pass . substr($ohash, 20))); 
      }elseif(substr($crypted, 0, 5) == "{SHA}"){ 
         return ($this->non_salted_sha1($pass) == $crypted); 
      }else{ 
         return ($pass == $crypted); 
      } 
   } 

   function save($file=false){ 
      $fcontents = ""; 
      if($file == false) $file = $this->_path; 
      foreach(array_keys($this->users) as $user){ 
         $fcontents .= $user.":".$this->users[$user]."\n"; 
      } 
      if(file_put_contents($file, $fcontents)){ 
         $this->error = ''; 
         return true; 
      }else{ 
         $this->error = 'Couln\'t save the file!'; 
         return false; 
      } 
   }    

   //encryption functions 
   function rand_salt_crypt($pass){ 
      $salt = ""; 
      mt_srand((double)microtime()*1000000); 
      for ($i=0; $i<CRYPT_SALT_LENGTH; $i++) 
         $salt .= substr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./", mt_rand() & 63, 1); 
      return "$apr1$".crypt($pass, $salt); 
   } 
    
   function rand_salt_sha1($pass){ 
      mt_srand((double)microtime()*1000000); 
      $salt = pack("CCCC", mt_rand(), mt_rand(), mt_rand(), mt_rand()); 
      return "{SSHA}".base64_encode(pack("H*", sha1($pass . $salt)) . $salt); 
   } 
    
   function non_salted_sha1($pass){ 
      return "{SHA}".base64_encode(pack("H*", sha1($pass))); 
   } 
} 

//php4 work around 
if(!function_exists('file_put_contents')){ 
   function file_put_contents($filename, $content, $flags = null, $resource_context = null){ 
      if(is_array($content)){ 
         $content = implode('', $content); 
      } 
      if(!is_scalar($content)){ 
         user_error('file_put_contents() The 2nd parameter should be either a string or an array', E_USER_WARNING); 
         return false; 
      } 
      $length = strlen($content); 
      $mode = ($flags &FILE_APPEND) ? 'a' : 'w'; 
      $use_inc_path = ($flags &FILE_USE_INCLUDE_PATH) ? true : false; 
      if(($fh = @fopen($filename, $mode, $use_inc_path)) === false){ 
         user_error('file_put_contents() failed to open stream: Permission denied', E_USER_WARNING); 
         return false; 
      } 
      $bytes = 0; 
      if(($bytes = @fwrite($fh, $content)) === false){ 
         $errormsg = sprintf('file_put_contents() Failed to write %d bytes to %s', 
         $length, 
         $filename); 
         user_error($errormsg, E_USER_WARNING); 
         return false; 
      } 
      @fclose($fh); 
      if($bytes != $length){ 
         $errormsg = sprintf('file_put_contents() Only %d of %d bytes written, possibly out of free disk space.', 
         $bytes, 
         $length); 
         user_error($errormsg, E_USER_WARNING); 
         return false; 
      } 
      return $bytes; 
   } 
} 
?>
I then created a page for the user (changepass.php)

Code: Select all

<?php
/*
 * Created on 7 Mar 2007
 *
 * To change the template for this generated file go to
 * Window - Preferences - PHPeclipse - PHP - Code Templates
 */
 require('htpaswd.class.php');
 require('customexception.class.php');
 $CurrentUser = $_SERVER['PHP_AUTH_USER'];
 $CurrentPassword = $_SERVER['PHP_AUTH_PW'];
 $CurrentEncodedPassword = base64_encode($CurrentPassword);
 $Success = "";
?>
<html>
<head>
<title>Change Password</title>
<script language="JavaScript" type="text/javascript">
  function changePass(){
  	document.getElementById('change').value=1;
  }
</script>
  
</head>
<body style="font-family: arial; font-size: 9pt">
<?php
	if (isset($_POST['change'])&&$_POST['change']==1){
		try{
			$NewPassword = $_POST['newpass'];
			$ConfirmPassword = $_POST['confirmpass'];
			$EncodedOldPassword = base64_encode($_POST['oldpass']);
			if (($EncodedOldPassword<>$CurrentEncodedPassword)||($_POST['oldpass']='')){
				throw new InvalidPasswordException('The old password is not correct');
			}
			if (($NewPassword<>$ConfirmPassword)||($NewPassword=='')){
				throw new InvalidPasswordException('The new and confirm passwords must be the same.  The new password cannot be blank');
			}
			$htpw = new htpasswd('/path/to/your/safe/.htpasswd'); 
			$htpw->remove($CurrentUser); 
			$htpw->create($CurrentUser, $NewPassword); 
			$htpw->save();
			$Success = "Password changed"; 
		}
		catch(InvalidPasswordException $e){
			print "<span style=\"color: #FF0000\">Error: ".$e->getMessage()."</span>";
		}
		catch(Exception $e){
			print "<span style=\"color: #FF0000\">Error: ".$e->getMessage()."</span>";
		}
	}

?>
<form id="password_form" action="changepass.php" method="POST" onsubmit="changePass();">
<input type="hidden" id="atpvalue" name="atpvalue" value="<?=$CurrentEncodedPassword?>" />
<input type="hidden" id="change" name="change" value="0" />
<?=$Success?>
<p>User: 
<?php	
	if ($CurrentUser==''){
		print "Could not find your user ID";
	}
	else{
		print $CurrentUser;
	}
?></p>
Old Password: <input type="password" id="oldpass" name="oldpass" /><br />
New Password: <input type="password" id="newpass" name="newpass" /><br />
Confirm Password: <input type="password" id="confirmpass" name="confirmpass" /><br />
<input type="submit" name="submit" value="Change Password" />
</form>
</body>
</html>
If you are not using PHP5 you will need to take out the try{}catch{} blocks

This is the customexception.class.php file

Code: Select all

<?php

     class InvalidPasswordException extends Exception {

}
?>

Posted: Wed Mar 28, 2007 3:01 am
by stereofrog
You can also try

Code: Select all

`htpasswd -bc $path_to_pass_file $username $password`;