| Server IP : 208.122.213.31 / Your IP : 216.73.216.185 Web Server : Apache System : Linux msd6191.mjhst.com 4.18.0-553.137.1.el8_10.x86_64 #1 SMP Wed Jun 24 11:40:24 UTC 2026 x86_64 User : WHMCS_MIA_382 ( 1001) PHP Version : 7.4.33 Disable Function : NONE MySQL : ON | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/httpd/html/rin-city.com/public_html/epoch/ |
Upload File : |
<?php
/*
* 20230718MP
* PHP8.x
*
* Epoch Client Controller:
* ============================================================
* Notice: This script must be configured before it can be used.
*
* Configuration Instructions:
*
* Step 1) Set $configureTarget to either 'MySQL' or 'HTAccess' depending on your configuration needs.
*
* Step 2) Move to the proper if() statement and configure the variables for HTAccess or MySQL to match
* your environment.
*
* Step 3) Set the $challengeKey variable to the value provided to you by the epoch support team if not
* already set. This is used for authenticating requests for environment updates.
*
* Step 4) Environment should now be configured. Ask the Epoch Support team (support@epoch.com) to
* test your environment after configuration to ensure the site addition mechanisms are working
* properly.
*
*
* Note About File Permissions:
* ================================================================
* When using HTAccess as the storage mechanism, the htfile must be writable by the user
* who is running the webserver or the storage will not work. (www-data in most cases)
*
*
* Thank you for choosing Epoch for your processing needs.
* (c) Epoch LLC 2009
*
*/
// Set configure target here: MySQL/HTDigest/HTAccess (uncomment the one that matches your environment)
// $configureTarget = 'MySQL';
// $configureTarget = 'HTDigest';
$configureTarget = 'HTAccess';
// Set this to the key/digest provided to you by Epoch
$challengeKey = "27923c7960bf4ba93268321ef82e81e7";
// --- If the configure target is MySQL, set credentials here ------------------
if($configureTarget == 'MySQL')
{
$user = 'dbuser';
$pass = 'dbpass';
$host = 'dbhost';
$db = 'dbname';
// table must have two fields at a minimum (username, password)
$table = 'dbtable';
// customize the column names
$table_username = 'username';
$table_password = 'password';
}
// --- Configure HTAccess Parameters Here -------------------------------------
if($configureTarget == 'HTAccess')
{
// current htaccess configuration requires no custom additions at this time.
}
// --- Configure HTDigest Parameters Here ------------------------------------
if($configureTarget == 'HTDigest')
{
// current htaccess configuration requires no custom additions at this time.
// check your phpinfo() to see what db handlers you can support - common db
// handlers are 'dbm', 'gdbm', 'db2', 'db3', 'db4', etc.
$dbhandler = 'dbm';
}
// --- Backup file - Only for HTAccess or HTDigest ---------------------------
if($configureTarget != 'MySQL')
{
// Set $doBackup to false to turn off password file backups
$doBackup = true;
// uncomment the line below and assign the value an absolute path to a backup file
//$backupFile = '/absolute/path/to/backup/file'
}
// Configure the url to grab list of allowed ips
$ip_list_url="http://epoch.com/cachegen.php";
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
* DO NOT EDIT BELOW THIS LINE
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
// Sanitize POST variables based on a-z, A-Z, 0-9 policy
$sanity = new EP_Sanity;
// set sanitization routine to use
$sanity->sanitizeMethod = "whitelist_azAZ09Chars";
// sanitize all post variables
//$sanity->sanitizePOST();
// retrieve digest
$digest = $_POST['epoch_digest'];
// retrieve request data
$request = $_POST['command'];
$username = $_POST['username'];
$password = $_POST['password'];
$ht_file = $_POST['ht_file'];
// make sure the request type fits and is not empty
if(empty($request))
die("ERROR NOREQ");
if( $request != 'DELETE' && $request != 'ADD' && $request != 'CHECK')
die("ERROR INVALIDCOMMAND");
// If no digest is provided, default back on the IP list source verifier
// as a mechanism for authentication.
if(empty($digest))
{
// create new source request verifier
$srv = new EP_SourceRequestVerifier;
// set the IP list generation url
$srv->ipListURL = $ip_list_url;
// cache data
$srv->cache();
// Fail if we cannot verify source
if(!$srv->verify())
die("ERROR BADSRC");
} else {
// New Method
$keyarr=array();
foreach($_POST as $key => $val)
{
array_push($keyarr, $key);
}
sort($keyarr);
foreach($keyarr as $key)
{
if($key == "epoch_digest")
continue;
$challenge .= $key.trim($_POST[$key]);
}
// calculate digest and die if mismatch
if( calculateHMAC($challenge, $challengeKey) != $digest )
die("ERROR BADCHAL");
}
// Process MySQL Based Request if Configured for MySQL
if($configureTarget == 'MySQL')
{
// create either mysql or mysqli interface based on auto-discovery
foreach(get_loaded_extensions() as $key => $value) {
if ($value == 'mysqli') {
$cpm = new EP_ClientPassManagerMySQLi;
break;
}
}
// enable this to use the legacy interface to mysql (for php 4)
if( !$cpm )
$cpm = new EP_ClientPassManagerMySQL;
// database username and password
$cpm->user = $user;
$cpm->pass = $pass;
$cpm->host = $host;
$cpm->db = $db;
$cpm->table = $table;
// Set username and password columns
$cpm->username_column = $table_username;
$cpm->password_column = $table_password;
// set encryption routine (sha1/md5, default == sha1)
$cpm->encryption_function = 'sha1';
// attempt to connect to database
$cpm->connectDB();
switch($request)
{
case 'ADD':
$cpm->addUser($username, $password) ? print("ADDED $username") : print("ERROR");
break;
case 'DELETE':
$cpm->deleteUser($username) ? print("DELETED $username") : print("ERROR");
break;
case 'CHECK':
$cpm->userExists($username) ? print("FOUND") : print("NOT_FOUND");
break;
default:
print "Command not recognized.";
break;
}
exit;
}
// Process HTAccess Based Request if Configured for HTAccess
if($configureTarget == 'HTAccess' || $configureTarget == 'HTDigest')
{
if($configureTarget == 'HTAccess')
{
// create new instance of the pass manager
$cpm = new EP_ClientPassManagerHTAccess;
// set the passwd file
$cpm->htpasswd = $ht_file;
}
elseif($configureTarget=='HTDigest')
{
// create new instance of the pass manager
$cpm = new EP_ClientPassManagerHTDigest;
// set the passwd file
$cpm->htdigest = $ht_file;
// set the db handler
$cpm->dbhandler = $dbhandler;
}
// Set backup variables
$cpm->doBackup = $doBackup;
if(!empty($backupFile))
{
$cpm->backupFile = $backupFile;
}
else
{
$cpm->backupFile = $ht_file . $cpm->backupSuffix;
}
// process request
switch($request)
{
case 'ADD':
$cpm->processRequest($username, $password, 'ADD') ? print("ADDED $username") : print("ERROR $username " . $cpm->lastError);;
break;
case 'DELETE':
$cpm->processRequest($username, 0, 'DELETE') ? print("DELETED $username") : print("ERROR $username " . $cpm->lastError);
break;
case 'CHECK':
$cpm->processRequest($username, 0, 'CHECK') ? print("FOUND") : print("NOT_FOUND");
break;
default:
print("Command not recognized.");
break;
}
exit;
}
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
* EPOCH CLIENT CLASSES
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
class EP_Sanity
{
// Sanitization Method: Available types are
// -> "whitelist_azAZ09"
// -> "whitelist_azAZ"
// -> "whitelist_azAZ09Chars"
// -> "blacklist"
// default whitelist: a-z, A-Z, 0-9
var $sanitizeMethod = 'whitelist_azAZ09';
// -------------- Default Blacklist Sets -------------------------
// Sanitize these characters (case insensitive)
var $badChars = array
(
";" ,
"<" ,
">" ,
"\"",
"'" ,
"(" ,
")" ,
"{" ,
"}" ,
"[" ,
"]" ,
"%" ,
"!" ,
"=" ,
"\\",
"/"
);
// Sanitize these strings (case insensitive)
var $badStrings = array
(
"java" ,
"script" ,
"union" ,
"select" ,
"drop" ,
"insert" ,
"delete" ,
"?php" ,
"onClick" ,
"onMouseOver",
"onLoad"
);
// -------------- Whitelist Processors -------------------------
// Whitelist a String by Constraints: a-z, A-Z, 0-9
function whitelistAZaz09($str)
{
return preg_replace( "/[^a-zA-Z0-9_]/", "", $str );
}
// Whitelist a String by AZaz09Chars
function whitelistAZaz09Chars($str)
{
// __ Begin script modification on Jan 28, 2014. __
// This modification extends the regular expression filter to
// allow for additional characters. The filter regular expression
// has been taking directly from the join form input processor.
// Filter definition for review.
$filter_regexp_modified = "/[^A-Za-z0-9@_\.\-!]/";
// Apply filter and return filtered string.
return preg_replace($filter_regexp_modified, "", $str);
}
// Whitelist a String by Constraints: a-z, A-Z
function whitelistAZaz($str)
{
return preg_replace( "/[^a-zA-Z_]/", "", $str );
}
// -------------- General Purpose Array Sanitizers -------------
// Sanitize any given array
function sanitizeArray($array)
{
// walk and sanitize array
foreach($array as $idx => $val){
// sanize string based on string sanitization policy
$array[$idx] = $this->sanitizeString($array[$idx]);
}
// return sanitized array
return $array;
}
// Sanitize any given array (keyed array version)
function sanitizeKeyedArray($keyedArray)
{
// walk and sanitize keyed array
if(empty($keyedArray))
return $keyedArray;
// walk array and sanitize each string
foreach($keyedArray as $gkey => $val){
// sanize string based on string sanitization policy
$keyedArray[$gkey] = $this->sanitizeString($keyedArray[$gkey]);
}
// return the sanitized array
return $keyedArray;
}
// string sanitizer
function sanitizeString($str)
{
// sanitize by type
switch($this->sanitizeMethod)
{
// a-z A-Z 0-9
case 'whitelist_azAZ09':
$str = $this->whitelistAZaz09($str);
break;
// a-z A-Z
case 'whitelist_azAZ':
$str = $this->whitelistAZaz($str);
break;
case 'whitelist_azAZ09Chars':
$str = $this->whitelistAZaz09Chars($str);
break;
// blacklist against blacklist arrays
case 'blacklist':
// replace all bad strings with empty string
foreach($this->badStrings as $key => $search)
$str = preg_replace("/$search/i", "", $str);
//$str = str_ireplace($search, "", $str);
// replace all bad characters with empty string
foreach($this->badChars as $key => $search)
$str = preg_replace("/$search/i", "", $str);
// $str = str_ireplace($search, "", $str);
break;
// default case
default:
break;
}
// return the sanitized string
return $str;
}
// -------------- Custom Sanitizers --------------------------------
// sanitizes all $_GET
function sanitizeGET()
{
$_GET = $this->sanitizeKeyedArray($_GET);
}
// sanitizes all $_POST
function sanitizePOST()
{
$_POST = $this->sanitizeKeyedArray($_POST);
}
// sanitizes all $_COOKIE
function sanitizeCOOKIE()
{
$_COOKIE = $this->sanitizeKeyedArray($_COOKIE);
}
// sanitize all $_REQUEST ($_REQUEST contains GET/POST/COOKIE copy)
function sanitizeREQUEST()
{
$_REQUEST = $this->sanitizeKeyedArray($_REQUEST);
}
// sanitize all $_SERVER
function sanitizeSERVER()
{
$_SERVER = $this->sanitizeKeyedArray($_SERVER);
}
// sanitize all $_FILE (can be problematic, use with caution)
function sanitizeFILE()
{
$_FILES = $this->sanitizeKeyedArray($_FILES);
}
// sanitize all $_SESSION (can be problematic, use with caution)
function sanitizeSESSION()
{
$_SESSION = $this->sanitizeKeyedArray($_SESSION);
}
// ----------------- Batch Processor Functions (EZ Use) ---------------
// Sanitize GET/POST/COOKIE all in one.
function sanitize_ALL_REQUEST_VARS()
{
// sanitize all request oriented values
$this->sanitizeGET();
$this->sanitizePOST();
$this->sanitizeCOOKIE();
$this->sanitizeREQUEST();
}
// Sanitize everything everywhere (may cause problems)
function sanitizeEVERYTHING()
{
$this->sanitizeGET();
$this->sanitizePOST();
$this->sanitizeCOOKIE();
$this->sanitizeREQUEST();
$this->sanitizeSERVER();
$this->sanitizeFILE();
$this->sanitizeSESSION();
}
}
// Mysqli variant of the pass manager class
class EP_ClientPassManagerMySQLi
{
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
* Last Errors
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/*! Public variable which allows the retrieval of the last error which
has occured in the class.
*/
var $lastError;
//! Prints out the last error.
function displayLastError()
{
print $this->lastError;
}
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
* MySQL User Managment
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
// MySQLi Connection (Class) Used For Database Operations
var $conn = 0;
// DB Credentials
var $user = '';
var $pass = '';
var $host = '';
// Database Information (defaults below)
var $db = 'ep_client_data';
var $table = 'users';
// Collumns used for inserts
var $username_column = 'username';
var $password_column = 'password';
// Function Used for Encryption/Decryption
var $use_encryption = true;
var $encryption_function = 'sha1';
// HMAC Challenge Server
var $ep_hmac_challenger = "http://localhost/challenger.php";
// Establishes a connection to the database
function connectDB()
{
// initialize a new mysqli connection object
$this->conn = mysqli_init();
// connect to server
if(!$this->conn->real_connect($this->host, $this->user, $this->pass, $this->db))
{
$this->lastError = "Error in ".__FUNCTION__.": Unable to connect to database with supplied credential/configuration.";
return false;
}
// return indicating success
return true;
}
// Encrypts a value based on the set encryption function (sha1 is default)
function encrypt($str)
{
return call_user_func($this->encryption_function, $str);
}
// Verify a users existance by username. Function will fail if multiple usernames are encountered.
function userExists( $username )
{
// set up prepared statement
$stmt = $this->conn->prepare("SELECT * FROM $this->table WHERE $this->username_column = ?");
// bind the parameters
$stmt->bind_param("s", $username);
// execute prepared statement
if(!$stmt->execute())
{
$this->lastError = "Error in ".__FUNCTION__.": SQL Query failed to execute.";
return false;
}
$stmt->store_result();
// check to make sure a username doesn't have duplicate usernames
if($stmt->num_rows() == 0)
{
$this->lastError = "Error in ".__FUNCTION__.": Username provided has more then one (".$stmt->num_rows().") records associated with it where there should only be one record.";
return false;
}
// return indicating success
return true;
}
/* */
function addUser( $username, $password )
{
// encrypt password if set (default == enabled w/ sha1)
if($this->use_encryption)
$password = $this->encrypt($password);
if($this->userExists( $username ))
die("ERROR USEREXISTS");
// create sql
$sql = "REPLACE INTO $this->table ( $this->username_column , $this->password_column) VALUES (?, ?)";
// set up prepared statement
$stmt = $this->conn->prepare($sql);
// bind the parameters
$stmt->bind_param("ss", $username, $password);
// execute prepared statement
if(!$stmt->execute()){
$this->lastError = "Error in ".__FUNCTION__.": Supplied user/pass fields cannot be added.";
return false;
}
return true;
}
// remove user from database
function deleteUser( $username )
{
// Delete user from database (LIMIT 1 ADDED)
$sql = "DELETE FROM $this->table WHERE $this->username_column = ? LIMIT 1";
// set up prepared statement
$stmt = $this->conn->prepare($sql);
// bind the parameters
$stmt->bind_param("s", $username);
// execute prepared statement
if(!$stmt->execute()){
$this->lastError = "Error in ".__FUNCTION__.": User cannot be deleted.";
return false;
}
return true;
}
}
// Mysql variant of the pass manager class (PHP4 Legacy Support)
//
// SECURITY NOTICE: Do not use this class without sanitizing inputs first. Because legacy mysql
// does not support prepared statements, this class uses ad-hoc sql. Be safe, sanitize.
class EP_ClientPassManagerMySQL
{
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
* Last Errors
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/*! Public variable which allows the retrieval of the last error which
has occured in the class.
*/
var $lastError;
//! Prints out the last error.
function displayLastError()
{
print $this->lastError;
}
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
* MySQL User Managment
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
// MySQL Connection
var $conn = 0;
// DB Credentials
var $user = '';
var $pass = '';
var $host = '';
// Database Information (defaults below)
var $db = 'ep_client_data';
var $table = 'users';
// Collumns used for inserts
var $username_column = 'username';
var $password_column = 'password';
// Function Used for Encryption/Decryption
var $use_encryption = true;
var $encryption_function = 'sha1';
// HMAC Challenge Server
var $ep_hmac_challenger = "http://localhost/challenger.php";
// Establishes a connection to the database
function connectDB()
{
// connect through mysql interface
$this->conn = mysql_connect($this->host, $this->user, $this->pass);
// check connection status
if(!$this->conn)
{
$this->lastError = "Error in ".__FUNCTION__.": Unable to connect to database with supplied credential/configuration.";
return false;
}
// select database
mysql_select_db($this->db, $this->conn);
// return indicating success
return true;
}
// Encrypts a value based on the set encryption function (sha1 is default)
function encrypt($str)
{
return call_user_func($this->encryption_function, $str);
}
// Verify a users existance by username. Function will fail if multiple usernames are encountered.
function userExists( $username )
{
// ensure no quote has somehow made it past our sanitization routines
if(strstr($username, "'"))
{
$this->lastError = "Error in ".__FUNCTION__.": Non-allowed quote being passed in with username, possible sql injection attempt.";
return false;
}
// create query
$query = "SELECT * FROM $this->table WHERE $this->username_column = '$username' LIMIT 0,1";
// run query against database
$result = mysql_query($query, $this->conn);
if(!$result)
return false;
if(mysql_num_rows($result) > 0)
return true;
// return indicating failure
return false;
}
/* */
function addUser( $username, $password )
{
// make sure that somehow a quote didn't make it into the query parameters
if(strstr($username, "'") || strstr($password, "'"))
{
$this->lastError = "Error in ".__FUNCTION__.": Non-allowed quote being passed in with username, possible sql injection attempt.";
return false;
}
// encrypt password if set (default == enabled w/ sha1)
if($this->use_encryption)
$password = $this->encrypt($password);
// check if user exists
if($this->userExists( $username ))
die("ERROR USEREXISTS");
// add user to table
$query = "REPLACE INTO $this->table ( $this->username_column , $this->password_column) VALUES ('$username', '$password')";
// run query against database
$result = mysql_query($query, $this->conn);
if(mysql_affected_rows($this->conn) == 1)
return true;
return false;
}
// remove user from database
function deleteUser( $username )
{
// ensure no quote has somehow made it past our sanitization routines
if(strstr($username, "'"))
{
$this->lastError = "Error in ".__FUNCTION__.": Non-allowed quote being passed in with username, possible sql injection attempt.";
return false;
}
// Delete user from database
$query = "DELETE FROM $this->table WHERE $this->username_column = '$username' LIMIT 1";
// run query against database
$result = mysql_query($query, $this->conn);
if(mysql_affected_rows($this->conn) == 1)
return true;
return false;
}
}
// HTAccess variant of the htaccess manager
class EP_ClientPassManagerHTAccess
{
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
* Last Errors
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/*! Public variable which allows the retrieval of the last error which
has occured in the class.
*/
var $lastError;
//! Prints out the last error.
function displayLastError()
{
print $this->lastError;
}
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
* HTAccess User Managment
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
// new credentials to add
var $username = '';
var $password = '';
var $command = '';
// file to modify
var $htpasswd = '.htpasswd';
// optional htaccess prefix
var $htpasswdPrefix = "./";
// create backups?
var $doBackup = true;
// backup suffix
var $backupSuffix = '.bak';
// backup file
var $backupFile = "";
// indicates a proper configuration has been set
var $configured = 0;
// user array (created from htaccess file specified)
var $userArray = 0;
// Main Request Switch (Commands are: CHECK, ADD, DELETE)
function processRequest($username, $password, $command)
{
// verify that arguments are not empty
if( empty($username) || empty($command) )
{
$this->lastError = "Error in ".__FUNCTION__.": Request processor contains invalid empty parameters.";
return false;
}
// verify that the htfile exists
if(!file_exists($this->htpasswd))
{
$this->lastError = "Error in ".__FUNCTION__.": HTAccess file does not exist.";
return false;
}
// create a user array, if it hasn't been created already
if(empty($this->userArray))
$this->createUserArray();
// return false if the array failed to be created
//if(empty($this->userArray))
// return false;
// switch off the command provided
switch($command){
case 'CHECK':
return $this->check($username);
break;
case 'ADD':
return $this->add($username, $password);
break;
case 'DELETE':
return $this->delete($username);
break;
default:
break;
}
}
// Request Processors
function check($username)
{
// check to see if the user is in the array
if(!empty($this->userArray[$username]))
return true;
// return indicating failure
return false;
}
function add($username, $password)
{
if(empty($password) || empty($username) )
{
$this->lastError = "Error in ".__FUNCTION__.": Attempted to add a user with empty username or password field as parameters.";
return false;
}
// make sure the user doesn't already exist
if( $this->check($username) )
{
$this->lastError = "Error in ".__FUNCTION__.": User cannot be added, because user already exists.";
return false;
}
// push the user on the user list
$pattern = '/(^\$.+\$).+/';
$stored_hash = '$1$N1EHVYY9$qz.BE7oyWWkD85o5uCvO8/';
preg_match($pattern, $stored_hash, $matches); if (empty($matches[1])) {
return false;// Unknown salt pattern.
} $this ->userArray[$username] = crypt($password, $matches[1]);
// write the updated file
if(!$this->writeUpdatedFile($this->doBackup))
return false;
// return indicating success
return true;
}
// removes a user from the file, default $write flag enables rewriting the htaccess
function delete($username, $write = true)
{
// verify that the user to delete, exists
if( !$this->check($username) )
{
$this->lastError = "Error in ".__FUNCTION__.": User cannot be deleted, because user does not exist.";
return false;
}
// remove element from the array
unset($this->userArray[$username]);
// write the updated file (auto-backup of the file)
if(!$this->writeUpdatedFile($this->doBackup))
return false;
// return indicating success
return true;
}
// Utility functions
function createUserArray()
{
$this->userArray = array();
// walk line by line through htfile
foreach( file($this->htpasswd) as $line )
{
// remove whitespace / newlines
$line = trim($line);
// explode the htpasswd file based on delimiter
list($username, $password) = explode( ':', $line, 2 );
// set value in class array
$this->userArray[$username] = $password;
}
// return indicating success
return true;
}
// write the new htaccess
function writeUpdatedFile($createBackup = true, $dieOnBadBackup = true)
{
// create backup (default)
if($dieOnBadBackup)
if($createBackup == true){
if(!$this->createBackup())
die("Error: Backup unwritable");
}
// open file with write permissions (non-append)
$f = fopen($this->htpasswd, "w");
if(!$f)
{
$this->lastError = "Error in ".__FUNCTION__.": Unable to open htpasswd file specified, for writing.";
return false;
}
// lock file
if(!flock( $f, LOCK_EX ))
{
$this->lastError = "Error in ".__FUNCTION__.": Unable to lock file.";
return false;
}
// write all users in the user array to the htpasswd
foreach( $this->userArray as $username => $password )
{
if(!fwrite( $f, "$username:$password\n"))
{
$this->lastError = "Error in ".__FUNCTION__.": Unable to write credentials in main write loop.";
return false;
}
}
// unlock file
if(!flock( $f, LOCK_UN ))
{
$this->lastError = "Error in ".__FUNCTION__.": Unable to unlock file after write.";
return false;
}
// close the file
fclose($f);
// return indicating success
return true;
}
// Create backup of htpasswd file
function createBackup()
{
if(!copy($this->htpasswd, $this->backupFile))
{
$this->lastError = "Error in ".__FUNCTION__.": Unable to create backup.";
return false;
}
// return indicating success
return true;
}
}
// HTDigest variant of the htaccess manager
class EP_ClientPassManagerHTDigest
{
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
* Last Errors
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/*! Public variable which allows the retrieval of the last error which
has occured in the class.
*/
var $lastError;
//! Prints out the last error.
function displayLastError()
{
print $this->lastError;
}
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
* HTAccess User Managment
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
// new credentials to add
var $username = '';
var $password = '';
var $command = '';
// file to modify
var $htdigest = '.htdigest';
// optional htaccess prefix
var $htdigestPrefix = "./";
// create backups?
var $doBackup = true;
// backup suffix
var $backupSuffix = '.bak';
// backup file
var $backupFile = "";
// indicates a proper configuration has been set
var $configured = 0;
// user array (created from htaccess file specified)
var $userArray = 0;
// db handler type
var $dbhandler = 'dbm';
// Main Request Switch (Commands are: CHECK, ADD, DELETE)
function processRequest($username, $password, $command)
{
// verify that arguments are not empty
if( empty($username) || empty($command) )
{
$this->lastError = "Error in ".__FUNCTION__.": Request processor contains invalid empty parameters.";
return false;
}
// verify that the htfile exists
if(!file_exists($this->htdigest))
{
$this->lastError = "Error in ".__FUNCTION__.": HTDigest file does not exist.";
return false;
}
// return false if the array failed to be created
//if(empty($this->userArray))
// return false;
// switch off the command provided
switch($command){
case 'CHECK':
return $this->check($username);
break;
case 'ADD':
return $this->add($username, $password);
break;
case 'DELETE':
return $this->delete($username);
break;
default:
break;
}
}
// Request Processors
function check($username)
{
$db = dba_open($this->htdigest,"rdt",$this->dbhandler);
$exists = dba_exists($username,$db);
dba_close($db);
return $exists;
}
function add($username, $password)
{
if(empty($password) || empty($username) )
{
$this->lastError = "Error in ".__FUNCTION__.": Attempted to add a user with empty username or password field as parameters.";
return false;
}
// make sure the user doesn't already exist
if( $this->check($username) )
{
$this->lastError = "Error in ".__FUNCTION__.": User cannot be added, because user already exists.";
return false;
}
// push the user on the user list
$this->username = $username;
$this->password = crypt($password);
// write the updated file
if(!$this->writeUpdatedFile($this->doBackup))
return false;
// return indicating success
return true;
}
// removes a user from the file, default $write flag enables rewriting the htaccess
function delete($username, $write = true)
{
// verify that the user to delete, exists
if( !$this->check($username) )
{
$this->lastError = "Error in ".__FUNCTION__.": User cannot be deleted, because user does not exist.";
return false;
}
$db = dba_open($ht_file, "wdt","dbm");
if(!$db)
{
$this->lastError = "ERROR in ".__FUNCTION__.": unable to open file for writing." ;
return false;
}
if(!dba_delete($username,$db))
{
$this->lastError = "ERROR: unable to delete record.";
return false;
}
// close htdigest file
dba_close($db);
// return indicating success
return true;
}
// Utility functions
function writeUpdatedFile($createBackup = true, $dieOnBadBackup = true)
{
// create backup (default)
if($dieOnBadBackup)
if($createBackup == true){
if(!$this->createBackup())
die("Error: Backup unwritable");
}
// open file with write permissions (non-append)
$db = dba_open($this->htdigest, "wd","dbm");
if(!$db)
{
$this->lastError = "Error in ".__FUNCTION__.": Unable to open htdigest file specified, for writing.";
return false;
}
if(dba_exists($this->username,$db))
if(!dba_replace($this->username,$this->password,$db))
{
$this->lastError = "ERROR: unable to write to file." ;
return false;
}
elseif (!dba_insert( $this->username,$this->password,$db))
{
$this->lastError = "ERROR: unable to write to file.";
return false;
}
// close the file
dba_close($db);
// return indicating success
return true;
}
// Create backup of htdigest file
function createBackup()
{
if(!copy($this->htdigest, $this->backupFile))
{
$this->lastError = "Error in ".__FUNCTION__.": Unable to create backup.";
return false;
}
// return indicating success
return true;
}
}
// Verification mechanisms
class EP_SourceRequestVerifier
{
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
* Last Errors
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
/*! Public variable which allows the retrieval of the last error which
has occured in the class.
*/
var $lastError;
//! Prints out the last error.
function displayLastError()
{
print $this->lastError;
}
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
* Verification Data and Routines
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
// IP/Host Lists (generated automatically)
var $ipList = 0;
var $hostList = 0;
// Boolean switch indicating if we've failed over (set in constructor)
var $failedOver = 0;
// URL containing the current list of allowed IP addresses
var $ipListURL = 'http://www.epoch.com/cachegen.php';
// Failover IP list to use in the case that the primary list is down
var $failoverIPList = array(
'127.0.0.1',
'208.236.105.',
'63.81.1.',
'63.84.23.',
'65.17.248.50',
'65.17.248.171',
'65.17.248.172',
'65.17.248.173',
'65.17.248.174'
);
// key used to deobfuscate data recieved from cachegen.php
var $rijKey = "366bb13c8d50be6c272b4ef228fcca79";
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
* Routines
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
// IP Address from which this class is being accessed
var $accessorIP = 0;
// cache generator routine
function cache()
{
// set remote accessor IP address as IP having invoked the class
$this->accessorIP = $_SERVER['REMOTE_ADDR'];
// Check cache (suggested by Chris L. )
if(file_exists("./ipcache.php")){
// recieve variables from the previous cache
require("./ipcache.php");
// overwrite the existing cache if the cache has expired
if(time() > $ttl)
$this->cacheIPList();
// set local ip allow list
$this->ipList = $ipList;
} else {
// if the file does not exist, create it
$this->cacheIPList();
// check to make sure that the file has been created successfully
if(file_exists("ipcache.php"))
{
// recieve variables from the previous cache
require("./ipcache.php");
// set local ip allow list
$this->ipList = $ipList;
}
}
// if IP list cannot be retrieved, set IP list as failover list
if(!$this->ipList) {
// indicate that we've failed over
$this->failedOver = true;
// set failover list
$this->ipList = $this->failoverIPList;
}
}
// verify the incomming host matches a correct IP
function verify()
{
// walk the ip list and attempt to match against the accessor
foreach($this->ipList as $goodIP){
// only attempt binary match if strings are of equal or lesser lengths
if(strlen($goodIP) > strlen($this->accessorIP))
continue;
// used strncmp here to match against even partial ip entries (primarily for epoch owned /24's)
if(strncmp($this->accessorIP, $goodIP, strlen($goodIP)) == 0)
return true;
}
// set warning
$this->lastError = "Warning in ".__FUNCTION__.": Cannot verify IP address, source IP is invalid.";
// did not match, accessor is invalid return false
return false;
}
// This function caches the Epoch IP list and sets a static timestamp in the cache file.
// Default cache file is ipcache.php
function cacheIPList()
{
// attempt to retrieve the list of IP addresses from the server (PHP 4 SAFE)
$f = fopen($this->ipListURL, "r");
$this->ipList = fread($f, 256000); /* stops on EOF */
// $this->ipList = file_get_contents($this->ipListURL); /* PHP 5 Only */
// decrypt raw data
$this->ipList = $this->decodeDecrypt($this->ipList);
// remove any spaces, newlines, or null characters
$this->ipList = trim($this->ipList);
// validate a returned ip list
if(!$this->ipList)
{
$this->lastError = "Error in ".__FUNCTION__.": Unable to retrieve IP list from server for caching";
return false;
}
// create ip list from retrieved data
$this->ipList = explode('|', $this->ipList);
// retrieve ttl and hmac key
$ttl = trim($this->ipList[0]);
// set timestamp
$ttl += time();
// remove elements from array
unset($this->ipList[0]);
// Generate php file content for storage
$fBuff = "<?PHP \n\t/* Do not edit below, this file has been autogenerated for Epoch usage. (c) Epoch */";
$fBuff .= "\n\t\$ttl = $ttl;\n\t\$ipList = array(";
// store each ip in the script
foreach($this->ipList as $cacheVal)
{
if(empty($cacheVal))
continue;
$fBuff .= "\n\t\t '$cacheVal',";
}
// remove trailing comma
$fBuff[strlen($fBuff)-1] = ' ';
// terminate the cache content array and script
$fBuff .= "\n\t);\n ?>\n\n";
// open cache file for writing
$f = fopen("./ipcache.php", "w");
if(!fwrite($f, $fBuff))
{
$this->lastError = "Error in ".__FUNCTION__.": Unable to write out ip cache to file.";
return false;
}
// cache file has been written successfully
return true;
}
// Decode/Decrypt routine for cache data
function decodeDecrypt($crypted)
{
// add base64 indicator to end of string
$crypted .= "==";
// decrypt data
$decrypted = mcrypt_decrypt(
MCRYPT_RIJNDAEL_256,
$this->rijKey,
base64_decode($crypted),
MCRYPT_MODE_ECB,
mcrypt_create_iv(
mcrypt_get_iv_size(
MCRYPT_RIJNDAEL_256,
MCRYPT_MODE_ECB
),
MCRYPT_RAND
)
);
// return the decrypted data
return trim($decrypted);
}
}
// Custom HMAC Calculation (for php4 deployments)
function calculateHMAC($data, $key, $raw_output = false)
{
// set algorithm to md5
$algo = strtolower('md5');
// set up ipad and opad
$pack = 'H'.strlen($algo('test'));
$size = 64;
$opad = str_repeat(chr(0x5C), $size);
$ipad = str_repeat(chr(0x36), $size);
if (strlen($key) > $size)
{
$key = str_pad(pack($pack, $algo($key)), $size, chr(0x00));
}
else
{
$key = str_pad($key, $size, chr(0x00));
}
for ($i = 0; $i < strlen($key) - 1; $i++)
{
$opad[$i] = $opad[$i] ^ $key[$i];
$ipad[$i] = $ipad[$i] ^ $key[$i];
}
$output = $algo($opad.pack($pack, $algo($ipad.$data)));
return ($raw_output) ? pack($pack, $output) : $output;
}
?>