$Htpasswd = new Htpasswd("/home/users/cdi/.htpasswd");
$Htpasswd->addUser("cdi","secret");
$Htpasswd->changePass("cdi","new-password","secret");
$Htpasswd->verifyUser("cdi","new-password");
$Htpasswd->getPass("cdi");
$Htpasswd->deleteUser("cdi");
$Htpasswd->renameUser("OldName","NewName","Password");
The password file is a flat-file with login name and their associated crypt.3 passwords, in the format login:password.
new("/full/path/to/htpasswd/file" );
Creates a new Htpasswd object. The path and file may be omitted. If the
path and file are omitted, the initialize() method must be called.
"path-to-file" should be the path and name of the file containing the login/password
information.
initialize("/full/path/to/htpasswd/file" );
The first method that should be called. (if file was omitted from the new() method) Loads the file specified
into memory. Some methods may be called or some variables set prior to
initialize() to modify how it reads the file. See also
sane(), and do_not_blame_cdi().
"path-to-file" should be the path and name of the file containing the login/password
information.
verifyUser("user id", "unencrypted password" );
Given a user id and password, returns true if the password matches the encrypted version stored in the htpasswd file. Returns false otherwise.
isUser("user");
Given a user id, will return true if that ID exists in the password file, will return false otherwise. It should be noted that user ids are case sensitive, so user is NOT the same user ID as User or USER.
getUserNum("user");
Given a user id, will return the user (line) number of that user. All entrys in the password file are assigned the User Id of the USERS() array index. All of this is just glorified line numbers from the password file, where line number 1 is user number 0. The total number of users in the password file can be obtained from the USERCOUNT variable. Returns null if the user is not found.
version();
Returns the version information for this class.
do_not_blame_cdi();
Used to turn off sanity checking on the file pointed to by
new() or initialize(). This is not reccommended.
See also sane().
getPass("user");
Given a userID, will return the user's encrypted password from the password file. Returns null if the user is not found.
changePass("user", "newPass", "oldPass");
changePass() will change the password of an existing user. If "oldPass"
is omitted or is empty/null, a password change is forced. If the
"oldPass" is submitted, changePass() first verifies that the password
they entered was correct before it will change their password. "newPass"
should be the plain text version of the user's password, as this method
will automatically encrypt it. Returns true upon success, returns false if
their
"oldPass" doesn't match or if the user wasn't found in the password file.
renameUser("OldName", "NewName", "password");
renameUser() changes a user ID in the password file. If the "password" is empty/null, the name change is forced. If the password is sent, the
"OldName" is first authenticated prior to allowing the name change. If
"OldName" doesn't exist or if "NewName" does exist, the change fails. Returns true on success, false on failure.
addUser("user", "password");
addUser() will add a user and password to the password file.
The password given to this method must not be encrypted as the
addUser() method will first encrypt the password, then save
it. You do not need to concern yourself with generating a salt for the
password encryption, as this method automatically calls
genSalt(). Returns true on success, false on failure, and the
script exits with a fatal ERROR condition if it fails to save the new password file. Will also return false
if the user id submitted already exists in the password file.
genSalt();
Called directly, genSalt() will return a random two digit
salt. The salt will have the range A-Za-z./, which are the only legal characters that can be used by crypt.3. This method is considered internal, as all password encryption routines
will generate their own random salts automatically.
genPass();
If you want to generate a random password, which is always a better idea
than letting users pick wimpy passwords, use the genPass()
method. This method returns a randomly generated 5 to 8 character plain
text password, which can then be sent to addUser() or
changePass() as the users password. The password generated is
in the range [A-Za-z0-9!@#$%^&*()-=_+].
assignPass("user");
assignPass(UserID) adds the user to the password file using an
automatically generated password. This method returns the plain text
version of a genPass() password. This method is designed to
quickly add users to the password file while maintaining the highest degree
of security by forcing random passwords on the user. It should be noted
that when this method returns the password, the user has already been added to the password
file. This method returns null upon failure. A file write error will cause the
program to immediately exit.
genUser();
To really clamp down on your system security, you can also assign random
user IDs. genUser() returns a random 5 to 8 character user ID,
suitable for use with assignPass(). IDs generated will be in
the range A-Za-z0-9.
deleteUser("user");
Fairly straight forward, deleteUser() removes a given user
from the password file. Returns true on success, false on failure.
getUserNum("user");
All users in the password array have a user number assigned to them,
corresponding to their line number from the password file.
getUserNum() returns the users ID, or -1 on failure. Remember,
this is a zero based array where line number one from the password file
will be userNum zero. See also USERCOUNT.
cryptPass("password","salt");
Returns the encrypted form of password using the submitted salt. If the salt is omitted or is null, cryptPass() will
automatically generate a random salt before encrypting the password. This
method is considered internal, as the higher level methods that encrypt
user passwords will automatically call this method.
htWriteFile();
This is an internal method and is called anytime the password file needs to
be written. If however, you have made your own changes to the USERS
array, calling this method will save those changes to the file. Returns
true on success, false upon failure. If for any reason
htWriteFile() cannot save the file, it will immediately echo
an error message to the client and exit the program. If
htWriteFile() is successfull, it automatically re-calls the
initialize() method and refreshes the file contents in memory.
Word to the wise: Since the class loads the file contents into memory, if
multiple processes update the file, strange things may happen. I've tried
to make it so that the class makes no assumptions about the file's
contents, and the way it writes the file should be safe from multiple hits
to it simultaneously. I can't guarantee that though. The PHP maintainers
really need to implement some kind of file locking routines. If you're concerned
that this may become a problem, you'll need to implement some kind of
locking procedure within your own program. Some pseudo-code on how you
might do this;
+--+- [check for a lock] | | | | | +------ No lock -> initialize() | | | | | | | +- lock file | | +-- Locked --+ | | | | +- Do Stuff | +------<--------+ | | +- Unlock | | + ------------------<-----------------------------+
initialize() method is invoked. Some may be set before the
initialize() method to effect the results. (DEBUG and the
method do_not_blame_cdi() )
new() or
initialize() method.
initialize() or
new() exists. If starting a new password file, will remain
false until the first user is added to the file, then will be true from
then on out. (Or until all users are deleted from the file)
do_not_blame_cdi() before calling the
initialize() method. If you want to turn off sanity checking,
you must call the initialize() method after calling the
do_not_blame_cdi() method.
htWriteFile() if you want changes made to
the actual file contents.
initialize()
method. The array is in the form of:
$Htpasswd->USERS[index number][ "user" ] = Username
$Htpasswd->USERS[index number][ "pass" ] = Password
So, to grab the username for UserID # 5:
$User5 = $Htpasswd->USERS[ 5 ][ "user" ];
echo " oops, $Htpasswd-E<gt>ERROR \n " ;
.
Only one type of error is not trapped in this fashion: Fatal file access errors, specifically fatal file write errors. If at any time this class cannot write a file it needs to write, it will immediately exit the entire program, rather than compromise security by assuming the file was successfully written. The class will echo the contents of ERROR to the client prior to exiting.
cp class.Htpasswd.php3 $INCLUDE_PATH/class.Htpasswd.php3
chmod 444 $INCLUDE_PATH/class.Htpasswd.php3
Change $INCLUDE_PATH to whatever your include_path directive is set to. If you don't have include_path set, then edit your php3.ini file and set one. That's it. Simple yes?
The comments in the source code itself should also help, but I'm not guaranteeing that.
http://www.thewebmasters.net/php/Htpasswd.phtml
or
renameUser() method per request from Rainer Scholz
jrs@startrek.franken.de .
General code clean-up.
Coming soon: class.Htgroup.php3
If running PHP as a CGI: Be sure to set DEBUG to false, or modify the error() function to log to someplace
other than error_log().
FATAL errors during file operations will cause an immediate exit of the program. Fatal errors are echo'd to STDOUT.
htpasswd.1, httpd.8, and crypt.3
Address bug reports and comments to:
The author makes no warranties, promises, or gaurantees of this software. As with all software, use at your own risk. This software is distributed "AS-IS".