...
 
Commits (2)
<?php
/*
This code is part of FusionDirectory (http://www.fusiondirectory.org/)
Copyright (C) 2003-2010 Cajus Pollmeier
Copyright (C) 2011-2019 FusionDirectory
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* Basic setup, remove eventually registered sessions */
require_once("../include/php_setup.inc");
require_once("functions.inc");
require_once("variables.inc");
/* Set headers */
header('Content-type: text/html; charset=UTF-8');
header('X-XSS-Protection: 1; mode=block');
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: deny');
/* Set the text domain as 'fusiondirectory' */
$domain = 'fusiondirectory';
bindtextdomain($domain, LOCALE_DIR);
textdomain($domain);
/* Remember everything we did after the last click */
session::start();
session::set('DEBUGLEVEL', 0);
reset_errors();
/* Force SSL for second factor */
if ($ssl != '') {
header("Location: $ssl");
exit;
}
CSRFProtection::check();
/* Logged in? Redirect to FD */
if (session::is_set('connected')) {
header('Location: main.php');
exit;
}
/* Missing data? Redirect to login */
if (!session::is_set('ui') || !session::is_set('config')) {
header('Location: index.php');
exit;
}
$ui = session::get('ui');
$config = session::get('config');
timezone::setDefaultTimezoneFromConfig();
/* Check for invalid sessions */
if (session::get('_LAST_PAGE_REQUEST') != '') {
/* check FusionDirectory.conf for defined session lifetime */
$max_life = $config->get_cfg_value('sessionLifetime', 60 * 60 * 2);
if ($max_life > 0) {
/* get time difference between last page reload */
$request_time = (time() - session::get('_LAST_PAGE_REQUEST'));
/* If page wasn't reloaded for more than max_life seconds
* kill session
*/
if ($request_time > $max_life) {
session::destroy('main.php called with expired session');
header('Location: index.php?signout=1&message=expired');
exit;
}
}
}
session::set('_LAST_PAGE_REQUEST', time());
foreach (LoginPost::$secondFactorMethods as $secondFactorMethod) {
if (!class_available($secondFactorMethod)) {
continue;
}
$secondFactorMethod::earlyProcess();
}
session::set('DEBUGLEVEL', $config->get_cfg_value('DEBUGLEVEL'));
/* Set template compile directory */
$smarty->compile_dir = $config->get_cfg_value('templateCompileDirectory', SPOOL_DIR);
Language::init();
LoginPost::displaySecondFactorPage();
<body>
{$php_errors}
{* FusionDirectory login - smarty template *}
<div id="window-container">
<div id="window-div">
<form action="index.php" method="post" id="loginform" name="loginform">
{$msg_dialogs}
<div id="window-titlebar">
<img id="fd-logo" src="geticon.php?context=applications&amp;icon=fusiondirectory&amp;size=48" alt="FusionDirectory logo"/>
<p>
{t}Two factor authentication{/t}
</p>
</div>
<div id="window-content">
{foreach from=$methodOutputs key=method item=methodOutput}
<div class="secondfactormethod" id="{$method|escape}">
{$methodOutput}
</div>
{/foreach}
</div>
<div id="window-footer" class="plugbottom">
<div>
<!-- Display error message on demand -->
{$message}
</div>
<div>
</div>
</div>
</form>
</div>
</div>
{include file={filePath file="copynotice.tpl"}}
<script type="text/javascript">
<!--
next_msg_dialog();
-->
</script>
</body>
</html>
......@@ -145,15 +145,23 @@ class LoginMethod
return TRUE;
}
/*! \brief Final step of successful login: redirect to main.php */
static function redirect ()
/*! \brief Connect user */
static function connect ()
{
global $config, $ui;
$ui = session::get('ui');
/* Not account expired or password forced change go to main page */
logging::log('security', 'login', static::$username, [], 'Logged in successfully');
logging::log('security', 'login', $ui->uid, [], 'Logged in successfully');
session::set('connected', 1);
session::set('DEBUGLEVEL', $config->get_cfg_value('DEBUGLEVEL'));
}
/*! \brief Final step of successful login: redirect to main.php */
static function redirect ()
{
static::connect();
header('Location: main.php');
exit;
}
......
......@@ -23,12 +23,28 @@
*/
class LoginPost extends LoginMethod
{
/*! \brief List of second factor methods, may be dynamic later */
static $secondFactorMethods = ['SecondFactorWebAuthn'];
/*! \brief Displayed name */
static function getLabel ()
{
return _('HTML form');
}
static function init ()
{
parent::init();
/* Init second factor methods if needed */
foreach (static::$secondFactorMethods as $secondFactorMethod) {
if (!class_available($secondFactorMethod)) {
continue;
}
$secondFactorMethod::init();
}
}
/*! \brief All login steps in the right order for standard POST login */
static function loginProcess ()
{
......@@ -50,6 +66,16 @@ class LoginPost extends LoginMethod
'runSchemaCheck',
]);
/* If needed redirect to second factor page */
foreach (static::$secondFactorMethods as $secondFactorMethod) {
if (!class_available($secondFactorMethod)) {
continue;
}
if ($secondFactorMethod::hasSecondFactor()) {
static::redirectSecondFactorPage();
}
}
if ($success) {
/* Everything went well, redirect to main.php */
static::redirect();
......@@ -62,6 +88,14 @@ class LoginPost extends LoginMethod
static::displayLogin();
}
/*! \brief Redirect to the second factor page */
static protected function redirectSecondFactorPage ()
{
session::un_set('connected');
header('Location: secondfactor.php');
exit;
}
/*! \brief Display the login page and exit() */
static protected function displayLogin ()
{
......@@ -134,4 +168,66 @@ class LoginPost extends LoginMethod
$smarty->display(get_template_path('login.tpl'));
exit();
}
/*! \brief Display the second factor page and exit() */
static function displaySecondFactorPage ()
{
global $smarty,$message,$config,$ssl,$error_collector,$error_collector_mailto;
$lang = session::get('lang');
error_reporting(E_ALL | E_STRICT);
/* Fill template with required values */
$username = '';
if (isset($_POST['username'])) {
$username = trim($_POST['username']);
}
$smarty->assign('date', gmdate('D, d M Y H:i:s'));
$smarty->assign('username', $username);
$smarty->assign('revision', FD_VERSION);
$smarty->assign('year', date('Y'));
$smarty->append('css_files', get_template_path('login.css'));
$smarty->assign('title', _('Second factor'));
/* Some error to display? */
if (!isset($message)) {
$message = '';
}
$smarty->assign('message', $message);
/* show login screen */
$smarty->assign('PHPSESSID', session_id());
if ($error_collector != '') {
$smarty->assign('php_errors', preg_replace('/%BUGBODY%/', $error_collector_mailto, $error_collector).'</div>');
} else {
$smarty->assign('php_errors', '');
}
$smarty->assign('msg_dialogs', msg_dialog::get_dialogs());
$smarty->assign('usePrototype', 'false');
$smarty->assign('date', date('l, dS F Y H:i:s O'));
$smarty->assign('lang', preg_replace('/_.*$/', '', $lang));
$smarty->assign('rtl', Language::isRTL($lang));
$methodOutputs = [];
/* Run second factor methods */
foreach (static::$secondFactorMethods as $secondFactorMethod) {
if (!class_available($secondFactorMethod)) {
continue;
}
$methodOutput = $secondFactorMethod::execute();
if ($methodOutput !== NULL) {
$methodOutputs[$secondFactorMethod] = $methodOutput;
}
}
$smarty->assign('methodOutputs', $methodOutputs);
$smarty->display(get_template_path('headers.tpl'));
$smarty->assign('version', FD_VERSION);
$smarty->display(get_template_path('secondfactor.tpl'));
exit();
}
}