<?php
////////////////////////////////////////////////////////////////////////
// Breeze Website Builder
// Copyright Silver Dolphin Solutions, LLC, Edward Lemmers, P.E.
// For licensing, see license.txt.
// Revised: 4/26/2010	ELL
// Added dictionary attack protection.
// Revised: 10/15/2011	ELL
// Added ability to lockout file manager for restricted users.
// Revised: 2/8/2012	ELL
// Added table prefix handling.
// Revised: 11/16/2012	ELL
// Added handling of passwords sent SHA-256 hashed and added handling of salt.
// Revised: 3/25/2013	ELL
// Security enhancements for PDO.
// Revised: 11/20/2016	ELL
// Modified reset password to store temp password in temp users table, then update users table upon logging in with temp password to new temp password.
// Revised: 11/23/2018	ELL
// Modified to go to last selected module if session timed out and logging back in.
//
	$userid = $_REQUEST['userid'];
	$password = $_REQUEST['password'];
	$password_reset = $_POST['password_reset'];
	$module = $_POST['module'];
	$btn = $_POST['btn'];
	$active_site = $_POST['active_site'];
	$site_select = $_POST['site_select'];
	
	$mask = "captcha/*.captcha";
	array_map("unlink", glob($mask));

	$connect_dir = "connect";
	if (isset($site_select) && ($site_select != 1))
		$connect_dir .= $site_select;
	elseif (isset($active_site) && ($active_site != 1))
		$connect_dir .= $active_site;
		
	include ("../$connect_dir/db_connect.php");
	include ("../$connect_dir/config.php");
	
	if (defined("BWB_LANG"))
		include ("lang/" . BWB_LANG . ".php");
	else
		include ("lang/en.php");
		
//////////////////////////////////////////////////
function CheckPassword($enc_text, $key, $password)
{
	/////////////////////////////////////////////
	//Decrypt password for comparison:
	$enc_text = stripslashes($enc_text);
	$key = strtolower(stripslashes($key));
	//Convert key to codes and pad as necessary.
	for( $i = 0; $i < (strlen($enc_text))/2; $i++)
	{
		if ($i < strlen($key))
		{
			$c = $key[$i];
			$k[$i] = ord($c);
		}
		else
			$k[$i] = 65 + $i;
	}
	
	//Convert encrypted string to array of HEX uni-character codes.
	$j = 0;
	$q = 0;
	for( $i = 0; $i < strlen($enc_text); $i++)
	{
		if ($j == 0) {
			$c = $enc_text[$i];
			$j++;
		}
		else {
			$c = $c.$enc_text[$i];
			$e[$q] = hexdec($c);
			$q++;
			$j = 0;
		}
		
	}
	
	//Decrypt encrypted string with key to get original data.
	$decrypt_text = "";
	for( $i = 0; $i < (strlen($enc_text))/2; $i++)
   	{
   		$a[$i] = $e[$i] ^ $k[$i];
		$decrypt_text = $decrypt_text. chr($a[$i]);
   	}
	////////////////////////////////////////////////////

	$decrypt_text = str_replace(BWB_SALT, '', $decrypt_text);
	$password_lookup = hash('sha256', $decrypt_text);

	if ($password_lookup == $password)
		return true;
	else
		return false;
}

function Login($userid, $access_level, $show_password_reset = false, $module = "", $btn = "")
{
	global $site_select;
	global $enable_file_manager;
	global $bwb_dbh;

	$sess_save_path = session_save_path();
	if (!isset($sess_save_path) || ($sess_save_path == ""))	{
		if (defined('SESSION_SAVE_PATH'))
			session_save_path(SESSION_SAVE_PATH);
		else
			session_save_path('/tmp');
	}
	session_start();
	$_SESSION['userid'] = $userid;
	unset($_SESSION['captcha']);
	$session = md5(session_id());
	$ip = $_SERVER['REMOTE_ADDR'];
	$query = "UPDATE `" . BWB_TABLE_PREFIX . "users` SET `Session`='$session', `IP`='$ip' WHERE `UserID` = :userid";
	$stmt = $bwb_dbh->prepare($query);
	$stmt->execute(array(':userid' => $userid));
	CleanAttemptLog();
	LogAttempt($userid, 1);
	
	if ($access_level == "restricted")	{
		$query = "SELECT `option_value` FROM `" . BWB_TABLE_PREFIX . "options_selected` WHERE `option_name`='EnableFileManager'";
		$result = $bwb_dbh->query($query);
		$row = $result->fetch(PDO::FETCH_ASSOC);
		$enable_file_manager = $row["option_value"];
	}
	
	if (($access_level != "restricted") || ($enable_file_manager == 1))
		$_SESSION['enable_file_manager'] = "100";
	else
		$_SESSION['enable_file_manager'] = "0";
		
	$_SESSION['module'] = $module;
	$_SESSION['btn'] = $btn;
	if (isset($site_select) && ($active_site != $site_select))
		$_SESSION['site_under_edit'] = $site_select;
		
	$url = "main.php";
	if ($show_password_reset)
		$url .= "?show_password_reset=1";
	header("Location: " . $url);
	exit;
}

function CheckAttempts($userid)
{
	global $bwb_dbh;
	
	$ip = $_SERVER['REMOTE_ADDR'];
	$current_ts = date('Y-m-d H:i:s', time());
	$query = "SELECT * FROM " . BWB_TABLE_PREFIX . "login_attempts WHERE (`IP` = '$ip') AND (TIMESTAMPDIFF(MINUTE, `AttemptTimeStamp`, '$current_ts') < 60)";
	$result = $bwb_dbh->query($query);
	$row = $bwb_dbh->query($query)->fetch();
	return($result->rowCount());
}

function LogAttempt($userid, $success = 0)
{
	global $bwb_dbh;
	
	$ip = $_SERVER['REMOTE_ADDR'];
	$query = "INSERT INTO " . BWB_TABLE_PREFIX . "login_attempts (`UserID`, `IP`, `Success`) VALUES (:userid, '$ip', $success)";
	$stmt = $bwb_dbh->prepare($query);
	$stmt->execute(array(':userid' => $userid));
}

function CleanAttemptLog()
{
	global $bwb_dbh;
	
	$current_ts = date('Y-m-d H:i:s', time());
	$query = "DELETE FROM " . BWB_TABLE_PREFIX . "login_attempts WHERE (TIMESTAMPDIFF(DAY, `AttemptTimeStamp`, '$current_ts') > 7)";
	$cnt = $bwb_dbh->exec($query);
	
}
	
 /****************************************************************
 * check_referer() breaks up the enviromental variable		*
 * HTTP_REFERER by "/" and then checks to see if the second	*
 * member of the array (from the explode) matches any of the	*
 * domains listed in the $referers array (declaired at top)	*
 ****************************************************************/

function check_referer($referers)
{
	global $errors;
	if (count($referers)) {
		if (getenv('HTTP_REFERER')) {
			$temp = explode('/', getenv('HTTP_REFERER'));
			$found = false;
			foreach ($referers as $stored_referer)	{
				if (preg_match('/^' . $stored_referer . '$/i', $temp[2]))
					$found = true;
			}
			if (!$found) {
				$errors[] = '1|You are coming from an unauthorized domain.';
				error_log('[PHPFormMail] Illegal Referer. (' . getenv('HTTP_REFERER') . ')', 0);
			}
			return $found;
		} else {
			$errors[] = '0|Sorry, but I cannot figure out who sent you here.  Your browser is not sending an HTTP_REFERER.  This could be caused by a firewall or browser that removes the HTTP_REFERER from each HTTP request you submit.';
			error_log('[PHPFormMail] HTTP_REFERER not defined. Browser: ' . getenv('HTTP_USER_AGENT') . '; Client IP: ' . getenv('REMOTE_ADDR') . '; Request Method: ' . getenv('REQUEST_METHOD') . ';', 0);
			return false;
		}
	} else {
		$errors[] = '1|There are no referers defined.  All submissions will be denied.';
		error_log('[PHPFormMail] You have no referers defined.  All submissions will be denied.', 0);
		return false;
	}
}
//////////////////////////////////////////////////	

	// Check referers to make sure SPAM bot is not trying to brake in.
	$server_name = $_SERVER['SERVER_NAME'];
	if (stripos($server_name, "www.") === false)
		$server_name_www = "www." . $server_name;
	else	{
		$server_name_www = $server_name;
		$server_name = str_ireplace("www.", "", $server_name);
	}
	$referers = array($server_name_www, $server_name);
	if (!check_referer($referers))	{
		echo <<<END
		<br>
		<div align="center">
		<h2>You do not appear to be valid. Make sure you have JavaScript turned on, cookies turned on, referers turned on and IP tracking blocks turned off. If this is in error, go back and try again.</h2>
		<h2><a href="javascript:history.go(-1);">Click here</a> to return to the login page, or use your 'Back' button.</h2>
		</div>
		<br>
END;
	
		exit;
	}
	
	// If dictionary attack detected, just dump 'em. 
	$attempt_limit = CheckAttempts($userid);
	if ($attempt_limit > 10)	{
		LogAttempt($userid);
		echo LOGIN_EXCEEDED_MAX_ATTEMPTS;
		exit;
	}

	$query = "SELECT * FROM " . BWB_TABLE_PREFIX . "users WHERE `UserID` = :userid";
	$stmt = $bwb_dbh->prepare($query);
	$stmt->execute(array(':userid' => $userid));
	$num_results = $stmt->rowCount();
	$row = $stmt->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT);
	
	if ($num_results < 1)	{
		LogAttempt($userid);
		header("Location: index.php?err=no_user_found");
		exit;
	}
		
	$access_level = $row["AccessLevel"];
	
	
	if (CheckPassword($row["password"], $row["UserID"], $password) === true)
	{
		Login($userid, $access_level, false, $module, $btn);
	}
	else
	{
		if (isset($password_reset) && ($password_reset == 1))
		{
			$query = "SHOW TABLES LIKE '" . BWB_TABLE_PREFIX . "tmp_users'";
			$result = $bwb_dbh->query($query);
			if ($result->rowCount() > 0)
			{
				// If temp users table exist, look for record with temp password.
				$query = "SELECT * FROM " . BWB_TABLE_PREFIX . "tmp_users WHERE (`UserID` = :userid) AND (`created` BETWEEN TIMESTAMPADD(MINUTE, -240, NOW()) AND NOW())";
				$stmt = $bwb_dbh->prepare($query);
				$stmt->execute(array(':userid' => $userid));
				$num_results = $stmt->rowCount();
				$row = $stmt->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT);
				
				if ($num_results > 0)
				{	
					if (CheckPassword($row["password"], $row["UserID"], $password) === true)	{
						// Encrypt password for password update.
						$encrypt_password = $row["password"];
						// Successful login, delete temp password record.
						$query = "DELETE FROM " . BWB_TABLE_PREFIX . "tmp_users WHERE `UserID` = :userid";
						$stmt = $bwb_dbh->prepare($query);
						$stmt->execute(array(':userid' => $userid));
						// If no records left in temp user table, drop the table.
						$query = "SELECT * FROM " . BWB_TABLE_PREFIX . "tmp_users";
						$result = $bwb_dbh->query($query);
						if ($result->rowCount() < 1)
						{
							$query = "DROP TABLE IF EXISTS " . BWB_TABLE_PREFIX . "tmp_users";
							$cnt = $bwb_dbh->exec($query);
						}
						// Update password with temp password.
						$query = "UPDATE " . BWB_TABLE_PREFIX . "users SET `password` = :encrypt_password WHERE `UserID` = :userid";
						$stmt = $bwb_dbh->prepare($query);
						$stmt->execute(array(':encrypt_password' => $encrypt_password, ':userid' => $userid));
						// Login
						Login($userid, $access_level, true);
					}
				}
			}
		}
		
		LogAttempt($userid);
		header("Location: index.php?err=wrong_password&userid=$userid");
	}
?>
