edit .htpasswd file through php

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
benyboi
Forum Commoner
Posts: 80
Joined: Sat Feb 24, 2007 5:37 am

edit .htpasswd file through php

Post 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!
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Why not just have PHP do the password protection?
User avatar
s.dot
Tranquility In Moderation
Posts: 5001
Joined: Sun Feb 06, 2005 7:18 pm
Location: Indiana

Re: edit .htpasswd file through php

Post 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+)
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.
leewad
Forum Commoner
Posts: 91
Joined: Tue May 11, 2004 8:32 am

Post 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);

?>
User avatar
mikeq
Forum Regular
Posts: 512
Joined: Fri May 03, 2002 3:33 am
Location: Edinburgh, Scotland

Post 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 {

}
?>
User avatar
stereofrog
Forum Contributor
Posts: 386
Joined: Mon Dec 04, 2006 6:10 am

Post by stereofrog »

You can also try

Code: Select all

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