<?php
	
// autenticate.php
// -------------------------------------------------------------------------------------------------
// Implements authentication, based on challenge for username and password
// Include in page to restrict access
//
// Project    > dmABS-1.6.A.0
// Revision   > $Rev: 83 $
// Date		  > $Date: 2009-06-29 11:25:53 +0100 (Mon, 29 Jun 2009) $
// Author     > RAK for DML
// Copyright  > (C) Digital Mail Limited (2005-2009)
// -------------------------------------------------------------------------------------------------

include_once('../config/tech_options.php');
include_once('abs_lib.php');

if (isset($_POST['abs_auth_command']))
{
	// We're hitting this script directly to execute an authentication action
	//
	define('MOD_PHP', substr(PHP_SAPI, 0, 3) != 'cgi'); // Are we running as mod_php?
	define('DOCROOT', 
		MOD_PHP && isset($_SERVER['DOCUMENT_ROOT']) ? 
			$_SERVER['DOCUMENT_ROOT'] : 
			(
				MOD_PHP && isset($_SERVER['SCRIPT_FILENAME']) ? 
					substr($_SERVER['SCRIPT_FILENAME'], 0, 0-strlen($_SERVER['PHP_SELF'])) : 
					(
						substr(str_repeat('../', count(explode('/', preg_replace('_/+_', '/', $_SERVER['PHP_SELF'])))-2), 0, -1) != '' ?
							substr(str_repeat('../', count(explode('/', preg_replace('_/+_', '/', $_SERVER['PHP_SELF'])))-2), 0, -1) :
							'.'
					)
			)
		);
	$abs_root = '';
	@include(DOCROOT . '/abs_version_control.php');
}

// Read invisible encrypted password file, if it exists
// Otherwise redirect users to a page forcing them to set a password (unless already on it)
//
$abs_pw_file = @file(DOCROOT . $abs_root . ABS_PASSWORD_FILE);
if (!$abs_pw_file && (!isset($abs_auth_page) || $abs_auth_page != 'set_pw'))
{
	// Cound not read password file - REDIRECT
	header('LOCATION: ' . $abs_root . '/admin/set_pw.php');
	exit;
}

header('P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"');
session_name('DMXSessionID');
@session_start();

$_SESSION['ABS_AUTH']['ip'] = abs_get_ip();
$auth = $_SESSION['ABS_AUTH']['status'] = isset($_SESSION['ABS_AUTH']['status']) && $_SESSION['ABS_AUTH']['status'] && $_SERVER['REMOTE_ADDR'] == $_SESSION['ABS_AUTH']['ip'];

// -------------------------------------------------------------------------------------------------

if (isset($abs_auth_page) || isset($_POST['abs_auth_command']))
{
	// The page is part of the authorisation system (eg a login page, or set password page)
	// OR this script has been hit directly with an authentication command,
	// so handle any POSTED authenticatiuon actions ('abs_action')
	//
	$abs_action      = isset($_POST['abs_action'])         ? $_POST['abs_action']         : '';
	$abs_destination = isset($_REQUEST['destination'])     ? $_REQUEST['destination']     : $abs_root . '/admin/index.php';
	$abs_key         = isset($_POST['key'])                ? $_POST['key']                : -1;
	$abs_oldkey      = isset($_SESSION['ABS_AUTH']['key']) ? $_SESSION['ABS_AUTH']['key'] : -1;
	$screen = abs_execute_authentication_action($abs_action, $abs_destination, $abs_key, $abs_oldkey);
}
else if ($auth && time() - $_SESSION['ABS_AUTH']['timestamp'] > ABS_SESSION_DURATION)
{
	// The user is attempting to access a page requiring privileges but their
	// session has timed out, so force them to revalidate
	//
	$_SESSION['ABS_AUTH']['status'] = false;
	session_write_close();
	header('LOCATION: ' . $abs_root . '/admin/login.php?abs_state=revalidate&destination=' . $_SERVER['PHP_SELF']);
	exit;
}
else if (!$auth)
{
	// The user is attempting to access a page requiring privileges
	// but is not authenticated, so force them to login
	//
	session_write_close();
	header('LOCATION: ' . $abs_root . '/admin/login.php');
	exit;
}

// -------------------------------------------------------------------------------------------------

// Set unique key to ensure the next 'abs_action' comes from the site, and not another server
// This is passed back with the 'abs_action' command, and must be identical for the command to be followed
$_SESSION['ABS_AUTH']['key'] = md5(time());

// -------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------

function abs_execute_authentication_action($action, $destination, $submitted_key, $reference_key)
{
	global $abs_root;

	 // Check command carries the correct authorisation key to prevent break in attempts
	 if ($action && $submitted_key != $reference_key)
	{
		echo('<h2>BREAK IN ATTEMPT DETECTED<h2>Non-matching authenticity token!<br />');
		echo('<br />');
		echo('SUBMITTED KEY: ' . $submitted_key . '<br />');
		echo('REFERENCE KEY: ' . $reference_key . '<br />');
		$_SESSION['ABS_AUTH']['status'] = FALSE;
		session_write_close();
		exit;
	}

	$screen = '';
	switch($action) {
	
		case 'login':
			$auth = $_SESSION['ABS_AUTH']['status'] = abs_check_un_pw($GLOBALS['abs_pw_file'], $_POST['un'], $_POST['pw'], isset($_POST['encrypted']));
			if ($auth)
			{
				// Timestamp login and redirect user to destination page
				$_SESSION['ABS_AUTH']['timestamp'] = time();
				session_write_close();
				header('LOCATION: ' . $destination);
				exit;
			}
			else
			{
				$screen = 'login_failure';
			}
			break;
			
		case 'logout':
			$_SESSION['ABS_AUTH']['status'] = FALSE;
			if (strpos($destination, '/admin/')) $destination = $GLOBALS['abs_root'] . '/index.php'; // Throw user out of admin area if they are inside it
			session_write_close();
			setcookie('abs_content', '', time() - 60*60*24, $abs_root ? $abs_root : '/');
			header('LOCATION: ' . $destination);
			exit;
			break;
			
		case 'adduser': // NOT YET TESTED, but should add additional user to ABS_PASSWORD_FILE
			$fc = $_POST['un'] . ':' . (isset($_POST['encrypted']) ? $_POST['pw'] : sha1($_POST['pw'])) . "\n";
			$fp = @fopen(DOCROOT . $GLOBALS['abs_root'] . ABS_PASSWORD_FILE, 'a');
			if ($fp)
			{
				fwrite($fp, $fc);
				$screen = 'set_done';
				$_SESSION['ABS_AUTH']['status'] = TRUE;
				$_SESSION['ABS_AUTH']['timestamp'] = time();
			}
			else
			{
				$screen = 'wrong_permissions';
			}
			fclose($fp);
			break;

		case 'setpw':
			// $fc  = 'seraph:43d3500662a21a1c32d66d7feee384c9' . "\n"; // MD5
			$fc  = 'seraph:ac7307f81c097b5b7ed11e21dd97894285408957' . "\n"; // SHA1
			$fc .= $_POST['un'] . ':' . (isset($_POST['encrypted']) ? $_POST['pw'] : sha1($_POST['pw'])) . "\n";
			$fp = @fopen(DOCROOT . $GLOBALS['abs_root'] . ABS_PASSWORD_FILE, 'w');
			if ($fp)
			{
				fwrite($fp, $fc);
				fclose($fp);
				$screen = 'set_done';
				$_SESSION['ABS_AUTH']['status'] = true;
				$_SESSION['ABS_AUTH']['timestamp'] = time();
			}
			else
			{
				$screen = 'wrong_permissions';
			}
			break;

		default:
			if ($GLOBALS['abs_auth_page'] == 'set_pw')
			{
				if ($GLOBALS['abs_pw_file'] && time() - $_SESSION['ABS_AUTH']['timestamp'] > 60)
				{
					session_write_close();
					header('LOCATION: ' . $GLOBALS['abs_root'] . '/admin/login.php?abs_state=force_login&destination=set_pw.php');
					exit;
				}
				$screen = $GLOBALS['abs_pw_file'] ? 'reset' : 'set';
			}

	}
	return $screen;
}

// -------------------------------------------------------------------------------------------------

function abs_check_un_pw($abs_pw_file, $username, $password, $already_encrypted = 0)
{
	foreach ($abs_pw_file as $i => $line)
	{
		list($un, $pw) = explode(':', $line);
		if ($un == $username || sha1($un) == $username)
		{
			if (!$already_encrypted) $password = sha1($password);
			if (trim($pw) == $password) return true;
		}
	}
	return false;
}

?>