|
|
|
|
|
|
| |
| <?php
/* Copyright (C) 2004 Jarno Elonen <elonen@iki.fi>
* Copyright (C) 2005 Sarah King <http://sarahk.pcpropertymanager.com>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * The name of the author may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* History:
* Jarno Elonen created the original script and basic functions
* Sarah King converted the functions to a class and built in management routines
*
* References:
* CRYPT_SALT_LENGTH is a PHP constant
* http://elonen.iki.fi/code/misc-notes/htpasswd-php/htpasswd.inc
* http://www.php.net/manual/en/function.crypt.php
* http://www.php.net/manual/en/function.assert.php
* http://www.php.net/manual/en/function.ignore-user-abort.php
* .htpasswd file functions
*/
define("HTPASSWDPATH", "/home/mysite/");
define("HTPASSWDFILE", ".htpasswd");
class UTIL_crypt
{
/**
* @return void
* @desc The main function which displays users and allows changes.
* Be aware that the passwords are one way encryptions and can't be retrieved
*/
function manage_users()
{
global $_SERVER;
$admin = UTIL_crypt::is_admin();
$users = UTIL_crypt::load_htpasswd();
$output = "<html>
<body>
<h1>Manage Users</h1><ul>\n";
if ($admin) $output .= "<li>You are an Admin user</li>";
if (!UTIL_crypt::is_apache()) $output .= "<li>Your server is not Apache, this script may not work</li>";
$output .= "</ul>
<table cellpadding='10' cellspacing='0' border='1'>
<tr><th>User</th><th>Password</th><th> </th><th> </th><th> </th></tr>";
foreach($users as $user => $passwd)
{
$enc = urlencode($user);
$output .= "<tr><td>{$user}</td><td>**encrypted**</td>";
if ($_SERVER['PHP_AUTH_USER'] == $user || $admin)
$output .= "<td><a href='auth.php?op=chgpwd&user={$enc}'>Change Password</a></td>";
else $output .= "<td> </td>";
if ($_SERVER['PHP_AUTH_USER'] != $user && $admin)
$output .= "<td><a href='auth.php?op=delete&user={$enc}'
onclick=\"return confirm('Are you SURE you want to delete this user?')\">Delete</a></td>";
else $output .= "<td> </td>";
if (UTIL_crypt::is_email($user)) $output .= "<td>*</td>";
else $output .= "<td> </td>";
$output .= "</tr>";
}
if ($admin)
{
$output .= "<tr><form action='auth.php' method='GET'>
<input type='hidden' name='op' value='adduser'>
<td><input type='text' name='user' value='' size='20' maxlength='50'></td>
<td><input type='password' name='passwd' value='' size='20' maxlength='50'></td>
<td><input type='submit' value='Add'></td><td colspan='2'> </td>
</form>
</tr>";
}
$output .= "</table>
</body>
</html>";
echo $output;
}
/**
* @return void
* @desc Adds a user to the password file
*/
function add_user()
{
$user = UTIL_crypt::getGetVar('user');
$passwd = UTIL_crypt::getGetVar('passwd');
if (!empty($user) && !empty($passwd))
{
$users = UTIL_crypt::load_htpasswd();
$safepwd = UTIL_crypt::rand_salt_crypt($passwd);
$users[$user] = $safepwd;
UTIL_crypt::notify_user($user, $passwd);
UTIL_crypt::save_htpasswd($users);
}
header('Location: auth.php?op=manage');
exit;
}//add_user
/**
* @return void
* @desc Saves a new password. Admins don't have to enter the old password
*/
function save_password()
{
$user = UTIL_crypt::getGetVar('user');
$passwd = UTIL_crypt::getGetVar('passwd');
//defaults are different to force non empty result
$passwd1 = UTIL_crypt::getGetVar('passwd1', 'x');
$passwd2 = UTIL_crypt::getGetVar('passwd2', 'y');
if ($passwd1 != $passwd2) UTIL_crypt::feedback('The new passwords did not match');
$admin = UTIL_crypt::is_admin();
if ($admin == 0) $validpwd = UTIL_crypt::is_valid_password($user, $passwd);
else $validpwd = true;
if ($validpwd)
{
$users = UTIL_crypt::load_htpasswd();
$safepwd = UTIL_crypt::rand_salt_crypt($passwd1);
$users[$user] = $safepwd;
UTIL_crypt::notify_user($user, $passwd);
UTIL_crypt::save_htpasswd($users);
header('Location: auth.php?op=manage');
exit;
}
else UTIL_crypt::feedback('You dont have the rights to change this password unless you enter the old password correctly');
}//save_password
/**
* @return boolean
* @param string $user
* @param string $passwd
* @desc Tests to see if the password is current
*/
function is_valid_password($user, $passwd)
{
$users = UTIL_crypt::load_htpasswd();
$outcome = UTIL_crypt::test_htpasswd($users, $user, $passwd);
return $outcome;
}
/**
* @return void
* @param string $feedback
* @desc shows errors if necessary and exits
*/
function feedback($feedback)
{
echo "<html><body><div style='border: 2px solid red; padding: 10px;'><p>{$feedback}</p>
<p><A href='javascript:history.back(1)'>Go Back</A></p>
</div>
</body></html>";
exit;
}
/**
* @return boolean
* @param string $var
* @desc ereg check to see if the username is an email
*/
function is_email($var)
{
//ref: http://www.php.net/eregi
return eregi("^[A-Z0-9._%-]+@[A-Z0-9._%-]+\.[A-Z]{2,4}$", $var);
}
/**
* @return void
* @param string $user
* @param string $passwd
* @desc If the username is an email address the user will get an email
*/
function notify_user($user, $passwd)
{
if (UTIL_crypt::is_email($user))
{
$body = "Your logins to the Admin Section have been changed.
Username: {$user}
Password: {$passwd}
Please keep this document safe.";
mail($user, 'Admin Login Info', $body, "From: \"Webmaster\"<info@here.com>\n");
}
}//notify_user
/**
* @return void
* @desc deletes a user from .htpassword and saves the file
*/
function delete_user()
{
if (UTIL_crypt::is_admin())
{
$user = UTIL_crypt::getGetVar('user');
$users = UTIL_crypt::load_htpasswd();
if (!empty($user))
{
unset( $users[$user]);
UTIL_crypt::save_htpasswd($users);
}
}
header('Location: auth.php?op=manage');
exit;
}
/**
* @return void
* @desc Form for the user to fill in new and old passwords
*/
function change_pwd_request()
{
$user = UTIL_crypt::getGetVar('user');
$output = "<html>
<body>
<h1>Change Password</h1>
<form action='auth.php' method='GET'>
<input type='hidden' name='op' value='savepwd'>
<input type='hidden' name='user' value='{$user}'>
<table cellpadding='10' cellspacing='0' border='1'>
<tr><td>User: </td><td>{$user}</td></tr>
<tr><td>Current Password</td><td><input type='password' name='passwd' value='' size='20' maxlength='50'></td></tr>
<tr><td>New Password</td><td><input type='password' name='passwd1' value='' size='20' maxlength='50'></td></tr>
<tr><td>Repeat</td><td><input type='password' name='passwd2' value='' size='20' maxlength='50'></td></tr>
<tr><td> </td><td><input type='submit' value='Save'></td></tr>
</table>
</form>
</body>
</html>";
echo $output;
}//change_pwd_request
/**
* @return int
* @desc Returns a 1/0 flag for admin or not
*/
function is_admin()
{
global $_SERVER;
$admins = array('sarahk');
if (defined('UTIL_CRYPT_ADMIN')) $outcome = UTIL_CRYPT_ADMIN;
else
{
if (in_array($_SERVER['PHP_AUTH_USER'], $admins)) $outcome = 1;
else $outcome = 0;
define('UTIL_CRYPT_ADMIN', $outcome);
}
return $outcome;
}//is_admin
/**
* @return array
* @desc Loads htpasswd file into an array of form. Array( username => crypted_pass, ... )
*/
function load_htpasswd()
{
if ( !file_exists(HTPASSWDPATH.HTPASSWDFILE))
return Array();
$res = Array();
foreach(file(HTPASSWDPATH.HTPASSWDFILE) as $l)
{
$array = explode(':',$l);
$user = $array[0];
$pass = chop($array[1]);
$res[$user] = $pass;
}
return $res;
}//load_htpasswd
/**
* @return void
* @param array $pass_array
* @desc Writes the array to the .htpasswd file
*/
function save_htpasswd( $pass_array )
{
ignore_user_abort(true);
// get the file content
$txt = '';
foreach($pass_array as $u => $p) $txt .= "$u:$p\n";
//just incase we need it
$feedback = 'You will need to save the following to the .htpasswd file manually:<br><textarea rows=8 cols=100>'.$txt.'</textarea>';
// Server detection
$is_apache = UTIL_crypt::is_apache();
if (!$is_apache) UTIL_crypt::feedback($feedback);
if ( ! ((!file_exists(HTPASSWDPATH.HTPASSWDFILE) && is_writable(HTPASSWDPATH)) || is_writable(HTPASSWDPATH.HTPASSWDFILE)) )
UTIL_crypt::feedback('ERROR! .htpasswd! does not exist or is not chmod 777<br><br>'.$feedback);
$fp = fopen(HTPASSWDPATH.HTPASSWDFILE, 'w+');
if (flock($fp, LOCK_EX))
{
fputs($fp, $txt);
flock($fp, LOCK_UN); // release the lock
}
else
{
fclose($fp);
UTIL_crypt::feedback('ERROR! Could not save (lock) .htpasswd!<br><br>'.$feedback);
}
fclose($fp);
ignore_user_abort(false);
}// save_htpasswd
/**
* @return boolean
* @desc Is the server apache, allows the user to be warned if the script won't work
*/
function is_apache()
{
return strstr($_SERVER['SERVER_SOFTWARE'], 'Apache') ? 1 : 0;
}//is_apache
/**
* @return string
* @param string $pass
* @desc Generates a htpasswd compatible crypted password string.
*/
function rand_salt_crypt( $pass )
{
// Randomize a CRYPT_SALT_LENGTH-letter crypt() salt:
$cset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./';
$salt = '';
for ($i=0; $i<CRYPT_SALT_LENGTH; $i++)
{
$salt .= substr($cset, rand() & 63, 1);
}
return crypt($pass, $salt);
}// rand_salt_crypt
/**
* @return boolean
* @param array $pass_array
* @param string $user
* @param string $pass
* @desc Returns true if the user exists and the password matches, false otherwise
*/
function test_htpasswd( $pass_array, $user, $pass )
{
if ( !isset($pass_array[$user])) return False;
$crypted = $pass_array[$user];
return crypt( $pass, substr($crypted,0,CRYPT_SALT_LENGTH) ) == $crypted;
}// test_htpasswd
/**
* @return void
* @desc Internal test: Use care when using this - it saves the passwords - use only for first testing
*/
function internal_unit_test()
{
echo "<p>Running from " . getcwd() . "</p>";
$pwds = Array( "Test" => UTIL_crypt::rand_salt_crypt("testSecret!"),
"fish" => UTIL_crypt::rand_salt_crypt("sest Ticret"),
"Generated" => "/uieo1ANOvsdA",
"Generated2" => "Q3cbHUBgm7aYk");
$tests = array(
"Test" => "testSecret!",
"Test1" => "wrong pass",
"fish" => "sest Ticret",
"fish1" => "wrong pass",
"Generated" => "withHtppasswdCmd",
"Generated1" => "",
"Generated2" => "",
"Generated3" => "this is wrong too"
);
foreach($tests as $user => $passwd)
{
$isgood = UTIL_crypt::test_htpasswd($pwds, $user, $pass);
if ($isgood) echo "<b>{$user} => {$passwd}</b> is good<br>\n";
else echo "<i>{$user} => {$passwd}</i> failed<br>\n";
}
UTIL_crypt::save_htpasswd($pwds);
}
/**
* @return string
* @param string $name
* @param string $default
* @desc generic routine to get a value from the $_GET variable
*/
function getGetVar($name, $default='')
{
global $_GET;
if (isset($_GET[$name])) $output = $_GET[$name];
else $output = $default;
return $output;
}//getGetVar
}//class UTIL_crypt
$op = UTIL_crypt::getGetVar('op', 'manage');
switch($op)
{
case 'test':
UTIL_crypt::internal_unit_test();
break;
case 'adduser':
UTIL_crypt::add_user();
break;
case 'savepwd':
UTIL_crypt::save_password();
break;
case 'delete':
UTIL_crypt::delete_user();
break;
case 'chgpwd':
UTIL_crypt::change_pwd_request();
break;
case 'manage':
default:
UTIL_crypt::manage_users();
break;
}
?> | | |
|
| PHP4 MYSQL Authentication Script with cookie. Short & Sweet
Categories : Authentication, Apache, Cookies, PHP, MySQL | | | Simple and fast user authentication Categories : PHP, PHP Classes, Authentication | | | PHP Based Apache + Mysql Error Log Parser Categories : PHP, PHP Classes, Apache, MySQL, Log Files | | | Access_user Class - an easy to use system for protecting pages and register users. Categories : PHP, Classes and Objects, Object Oriented, PHP Classes, Authentication | | | Use of bitmasks to represent permissions Categories : PHP, Authentication, Bitwise Operators, Security, PHP Classes | | | Scan Apache access log files and report possible worms attack Categories : PHP, PHP Classes, Security, Apache, Log Files | | | Using $PHP_AUTH_USER and $PHP_AUTH_PW to authenticate. Categories : Authentication, PHP | | | file class , uploade file , download file already uploaded on another website Categories : PHP, PHP Classes, Filesystem, Web Services | | | Authorize.net AIM Interface Class v1.0.0 Categories : PHP, PHP Classes, Ecommerce, Payment Gateways | | | Function to remember password Categories : PHP, Authentication, Personalization and Membership | | | crop and resize image class using gd library function Categories : PHP, PHP Classes, GD image library, Graphics | | | Basic Authentication with sessions Categories : PHP, Beginner Guides, Authentication, Form Processing, Sessions | | | News management class Categories : PHP, PHP Classes, Beginner Guides | | | A Timing Class Categories : PHP, PHP Classes, Date Time | | | The class to check load time of your script
VERY usefull for relatively slow applications, but not only.. Categories : PHP, PHP Classes, Debugging | |
|
|
|