2010-01-20 16:55:27 +00:00
< ? php
/**
2010-01-22 15:03:14 +00:00
* This file is part of the Froxlor project .
* Copyright ( c ) 2010 the Froxlor Team ( see authors ) .
2010-01-20 16:55:27 +00:00
*
2022-04-28 18:48:00 +00:00
* 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 .
2010-01-20 16:55:27 +00:00
*
2022-04-28 18:48:00 +00:00
* 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 .
2011-05-04 09:59:20 +00:00
*
2022-04-28 18:48:00 +00:00
* You should have received a copy of the GNU General Public License
* along with this program ; if not , you can also view it online at
* https :// files . froxlor . org / misc / COPYING . txt
*
* @ copyright the authors
* @ author Froxlor team < team @ froxlor . org >
* @ license https :// files . froxlor . org / misc / COPYING . txt GPLv2
2010-01-20 16:55:27 +00:00
*/
2022-04-28 18:48:00 +00:00
const AREA = 'login' ;
2022-02-20 17:00:44 +00:00
require __DIR__ . '/lib/init.php' ;
2010-01-20 16:55:27 +00:00
2023-05-24 14:02:07 +00:00
use Froxlor\Api\FroxlorRPC ;
2022-04-28 18:48:00 +00:00
use Froxlor\CurrentUser ;
use Froxlor\Customer\Customer ;
2018-12-19 15:57:03 +00:00
use Froxlor\Database\Database ;
2022-04-28 18:48:00 +00:00
use Froxlor\FileDir ;
use Froxlor\Froxlor ;
2018-12-19 15:57:03 +00:00
use Froxlor\FroxlorLogger ;
2022-04-28 18:48:00 +00:00
use Froxlor\FroxlorTwoFactorAuth ;
use Froxlor\PhpHelper ;
use Froxlor\Settings ;
use Froxlor\System\Crypt ;
2022-02-15 19:37:27 +00:00
use Froxlor\UI\Panel\UI ;
2023-05-24 14:02:07 +00:00
use Froxlor\UI\Request ;
2022-04-28 18:48:00 +00:00
use Froxlor\UI\Response ;
use Froxlor\User ;
use Froxlor\Validate\Validate ;
2018-12-18 12:45:05 +00:00
2013-04-27 07:06:19 +00:00
if ( $action == '' ) {
2010-01-20 16:55:27 +00:00
$action = 'login' ;
}
2018-11-30 12:45:17 +00:00
if ( $action == '2fa_entercode' ) {
// page for entering the 2FA code after successful login
2022-02-15 19:37:27 +00:00
if ( ! isset ( $_SESSION ) || ! isset ( $_SESSION [ 'secret_2fa' ])) {
2018-11-30 12:45:17 +00:00
// no session - redirect to index
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'index.php' );
2018-11-30 12:45:17 +00:00
exit ();
}
2024-05-09 14:03:46 +00:00
$smessage = ( int ) Request :: get ( 'showmessage' , 0 );
2023-05-12 08:36:27 +00:00
$message = " " ;
if ( $smessage > 0 ) {
$message = lng ( 'error.2fa_wrongcode' );
}
2018-11-30 12:45:17 +00:00
// show template to enter code
2022-03-18 11:53:34 +00:00
UI :: view ( 'login/enter2fa.html.twig' , [
2023-05-12 08:36:27 +00:00
'pagetitle' => lng ( 'login.2fa' ),
2024-08-29 06:19:45 +00:00
'remember_me' => ( Settings :: Get ( 'panel.db_version' ) >= 202407200 ) ? true : false ,
2023-05-12 08:36:27 +00:00
'message' => $message
2022-03-18 10:41:07 +00:00
]);
2018-11-30 12:45:17 +00:00
} elseif ( $action == '2fa_verify' ) {
// verify code from 2fa code-enter form
2022-02-15 19:37:27 +00:00
if ( ! isset ( $_SESSION ) || ! isset ( $_SESSION [ 'secret_2fa' ])) {
2018-11-30 12:45:17 +00:00
// no session - redirect to index
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'index.php' );
2018-11-30 12:45:17 +00:00
exit ();
}
2024-05-09 13:48:23 +00:00
$code = Request :: post ( '2fa_code' );
2024-07-20 08:16:48 +00:00
$remember = Request :: post ( '2fa_remember' );
2018-11-30 12:45:17 +00:00
// verify entered code
2022-05-15 10:27:48 +00:00
$tfa = new FroxlorTwoFactorAuth ( 'Froxlor ' . Settings :: Get ( 'system.hostname' ));
2023-05-12 08:36:27 +00:00
// get user-data
$table = $_SESSION [ 'uidtable_2fa' ];
$field = $_SESSION [ 'uidfield_2fa' ];
$uid = $_SESSION [ 'uid_2fa' ];
$isadmin = $_SESSION [ 'unfo_2fa' ];
2023-12-13 15:20:28 +00:00
if ( $_SESSION [ 'secret_2fa' ] == 'email' ) {
// verify code set to user's data_2fa field
$sel_stmt = Database :: prepare ( " SELECT `data_2fa` FROM " . $table . " WHERE ` " . $field . " ` = :uid " );
$userinfo_code = Database :: pexecute_first ( $sel_stmt , [ 'uid' => $uid ]);
2024-08-12 16:37:38 +00:00
// 60sec discrepancy (possible slow email delivery)
$result = $tfa -> verifyCode ( $userinfo_code [ 'data_2fa' ], $code , 60 );
2023-12-13 15:20:28 +00:00
} else {
$result = $tfa -> verifyCode ( $_SESSION [ 'secret_2fa' ], $code , 3 );
}
2018-11-30 12:45:17 +00:00
// either the code is valid when using authenticator-app, or we will select userdata by id and entered code
// which is temporarily stored for the customer when using email-2fa
if ( $result ) {
2022-04-28 18:48:00 +00:00
$sel_param = [
2018-11-30 12:45:17 +00:00
'uid' => $uid
2022-04-28 18:48:00 +00:00
];
2023-12-13 15:20:28 +00:00
$sel_stmt = Database :: prepare ( " SELECT * FROM " . $table . " WHERE ` " . $field . " ` = :uid " );
2018-12-22 07:15:31 +00:00
$userinfo = Database :: pexecute_first ( $sel_stmt , $sel_param );
2018-11-30 12:45:17 +00:00
// whoops, no (valid) user? Start again
2018-12-22 07:15:31 +00:00
if ( empty ( $userinfo )) {
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'index.php' , [
2018-11-30 12:45:17 +00:00
'showmessage' => '2'
2022-04-28 18:48:00 +00:00
]);
2018-11-30 12:45:17 +00:00
}
2018-12-22 07:15:31 +00:00
// set fields in $userinfo required for finishLogin()
$userinfo [ 'adminsession' ] = $isadmin ;
$userinfo [ 'userid' ] = $uid ;
2018-11-30 12:45:17 +00:00
// when using email-2fa, remove the one-time-code
2018-12-22 07:15:31 +00:00
if ( $userinfo [ 'type_2fa' ] == '1' ) {
2023-05-12 08:36:27 +00:00
$del_stmt = Database :: prepare ( " UPDATE " . $table . " SET `data_2fa` = '' WHERE ` " . $field . " ` = :uid " );
2022-04-28 18:48:00 +00:00
$userinfo = Database :: pexecute_first ( $del_stmt , [
2018-11-30 12:45:17 +00:00
'uid' => $uid
2022-04-28 18:48:00 +00:00
]);
2018-11-30 12:45:17 +00:00
}
2024-07-20 08:16:48 +00:00
// when remember is activated, set the cookie
if ( $remember ) {
$selector = base64_encode ( Froxlor :: genSessionId ( 9 ));
$authenticator = Froxlor :: genSessionId ( 33 );
$valid_until = time () + 60 * 60 * 24 * 30 ;
$ins_stmt = Database :: prepare ( "
INSERT INTO `".TABLE_PANEL_2FA_TOKENS."` SET
`selector` = : selector ,
`token` = : authenticator ,
`userid` = : userid ,
`valid_until` = : valid_until
" );
Database :: pexecute ( $ins_stmt , [
'selector' => $selector ,
'authenticator' => hash ( 'sha256' , $authenticator ),
'userid' => $uid ,
'valid_until' => $valid_until
]);
$cookie_params = [
'expires' => $valid_until , // 30 days
'path' => '/' ,
'domain' => UI :: getCookieHost (),
'secure' => UI :: requestIsHttps (),
'httponly' => true ,
'samesite' => 'Strict'
];
setcookie ( 'frx_2fa_remember' , $selector . ':' . base64_encode ( $authenticator ), $cookie_params );
}
// if not successful somehow - start again
if ( ! finishLogin ( $userinfo )) {
Response :: redirectTo ( 'index.php' , [
'showmessage' => '2'
]);
}
2018-11-30 12:45:17 +00:00
exit ();
}
2023-05-12 08:36:27 +00:00
// wrong 2fa code - treat like "wrong password"
$stmt = Database :: prepare ( "
UPDATE " . $table . "
SET `lastlogin_fail` = : lastlogin_fail , `loginfail_count` = `loginfail_count` + 1
WHERE `" . $field . "` = : uid
" );
Database :: pexecute ( $stmt , [
" lastlogin_fail " => time (),
" uid " => $uid
]);
// get data for processing further
$stmt = Database :: prepare ( "
SELECT `loginname` , `loginfail_count` , `lastlogin_fail` FROM " . $table . "
WHERE `" . $field . "` = : uid
" );
$fail_user = Database :: pexecute_first ( $stmt , [
" uid " => $uid
]);
if ( $fail_user [ 'loginfail_count' ] >= Settings :: Get ( 'login.maxloginattempts' ) && $fail_user [ 'lastlogin_fail' ] > ( time () - Settings :: Get ( 'login.deactivatetime' ))) {
// Log failed login
$rstlog = FroxlorLogger :: getInstanceOf ([
'loginname' => $_SERVER [ 'REMOTE_ADDR' ]
]);
$rstlog -> logAction ( FroxlorLogger :: LOGIN_ACTION , LOG_WARNING , " User ' " . $fail_user [ 'loginname' ] . " ' entered wrong 2fa code too often. " );
unset ( $fail_user );
Response :: redirectTo ( 'index.php' , [
'showmessage' => '3'
]);
exit ();
}
unset ( $fail_user );
// back to form
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'index.php' , [
2023-05-12 08:36:27 +00:00
'action' => '2fa_entercode' ,
'showmessage' => '1'
2022-04-28 18:48:00 +00:00
]);
2018-11-30 12:45:17 +00:00
exit ();
} elseif ( $action == 'login' ) {
2023-06-05 10:10:39 +00:00
if ( ! empty ( $_POST )) {
2024-05-09 13:48:23 +00:00
$loginname = Validate :: validate ( Request :: post ( 'loginname' ), 'loginname' );
$password = Validate :: validate ( Request :: post ( 'password' ), 'password' );
2013-11-18 12:02:59 +00:00
2024-01-14 08:40:33 +00:00
$select_additional = '' ;
if ( Settings :: Get ( 'panel.db_version' ) >= 202312230 ) {
$select_additional = ' AND `gui_access` = 1' ;
}
2024-01-07 09:23:02 +00:00
$stmt = Database :: prepare ( "
SELECT `loginname` AS `customer`
FROM `" . TABLE_PANEL_CUSTOMERS . "`
2024-01-14 08:40:33 +00:00
WHERE `loginname` = : loginname " .
$select_additional
);
2022-04-28 18:48:00 +00:00
Database :: pexecute ( $stmt , [
2018-11-30 12:45:17 +00:00
" loginname " => $loginname
2022-04-28 18:48:00 +00:00
]);
2013-11-04 14:23:52 +00:00
$row = $stmt -> fetch ( PDO :: FETCH_ASSOC );
2013-11-18 12:02:59 +00:00
2024-01-07 09:23:02 +00:00
$is_admin = false ;
2024-05-31 06:41:18 +00:00
$table = " " ;
2021-02-16 11:38:01 +00:00
if ( $row && $row [ 'customer' ] == $loginname ) {
2010-01-26 09:45:57 +00:00
$table = " ` " . TABLE_PANEL_CUSTOMERS . " ` " ;
$uid = 'customerid' ;
$adminsession = '0' ;
2013-04-27 07:06:19 +00:00
} else {
2022-04-28 18:48:00 +00:00
if (( int ) Settings :: Get ( 'login.domain_login' ) == 1 ) {
$domainname = $idna_convert -> encode ( preg_replace ([
2018-11-30 12:45:17 +00:00
'/\:(\d)+$/' ,
'/^https?\:\/\//'
2022-04-28 18:48:00 +00:00
], '' , $loginname ));
2024-01-07 09:23:02 +00:00
$stmt = Database :: prepare ( "
SELECT `customerid`
FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `domain` = : domain
" );
2022-04-28 18:48:00 +00:00
Database :: pexecute ( $stmt , [
2018-11-30 12:45:17 +00:00
" domain " => $domainname
2022-04-28 18:48:00 +00:00
]);
2013-11-04 14:23:52 +00:00
$row2 = $stmt -> fetch ( PDO :: FETCH_ASSOC );
2013-11-18 12:02:59 +00:00
2013-04-27 07:06:19 +00:00
if ( isset ( $row2 [ 'customerid' ]) && $row2 [ 'customerid' ] > 0 ) {
2022-04-28 18:48:00 +00:00
$loginname = Customer :: getCustomerDetail ( $row2 [ 'customerid' ], 'loginname' );
2013-04-27 07:06:19 +00:00
if ( $loginname !== false ) {
2024-01-07 09:23:02 +00:00
$stmt = Database :: prepare ( "
SELECT `loginname` AS `customer`
FROM `" . TABLE_PANEL_CUSTOMERS . "`
WHERE `loginname` = : loginname
" );
2022-04-28 18:48:00 +00:00
Database :: pexecute ( $stmt , [
2018-11-30 12:45:17 +00:00
" loginname " => $loginname
2022-04-28 18:48:00 +00:00
]);
2013-11-04 14:23:52 +00:00
$row3 = $stmt -> fetch ( PDO :: FETCH_ASSOC );
2021-02-16 11:38:01 +00:00
if ( $row3 && $row3 [ 'customer' ] == $loginname ) {
2010-10-15 11:48:05 +00:00
$table = " ` " . TABLE_PANEL_CUSTOMERS . " ` " ;
$uid = 'customerid' ;
$adminsession = '0' ;
}
}
}
}
2010-01-26 09:45:57 +00:00
}
2024-05-31 06:41:18 +00:00
if ( empty ( $table )) {
// try login as admin of no customer-login method worked
$is_admin = true ;
}
2022-04-28 18:48:00 +00:00
if (( Froxlor :: hasUpdates () || Froxlor :: hasDbUpdates ()) && $is_admin == false ) {
Response :: redirectTo ( 'index.php' );
2018-11-30 12:45:17 +00:00
exit ();
2010-01-26 08:59:19 +00:00
}
2010-01-26 09:45:57 +00:00
2013-04-27 07:06:19 +00:00
if ( $is_admin ) {
2022-04-28 18:48:00 +00:00
if ( Froxlor :: hasUpdates () || Froxlor :: hasDbUpdates ()) {
2024-01-07 09:23:02 +00:00
$stmt = Database :: prepare ( "
SELECT `loginname` AS `admin` FROM `" . TABLE_PANEL_ADMINS . "`
2013-11-04 14:23:52 +00:00
WHERE `loginname` = : loginname
2024-01-07 09:23:02 +00:00
AND `change_serversettings` = '1'
" );
2022-04-28 18:48:00 +00:00
Database :: pexecute ( $stmt , [
2018-11-30 12:45:17 +00:00
" loginname " => $loginname
2022-04-28 18:48:00 +00:00
]);
2013-11-04 14:23:52 +00:00
$row = $stmt -> fetch ( PDO :: FETCH_ASSOC );
2022-02-15 19:37:27 +00:00
if ( ! isset ( $row [ 'admin' ])) {
2013-11-04 14:23:52 +00:00
// not an admin who can see updates
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'index.php' );
2018-11-30 12:45:17 +00:00
exit ();
2010-01-26 08:59:19 +00:00
}
2013-04-27 07:06:19 +00:00
} else {
2024-01-14 08:40:33 +00:00
$select_additional = '' ;
if ( Settings :: Get ( 'panel.db_version' ) >= 202312230 ) {
$select_additional = ' AND `gui_access` = 1' ;
}
2024-01-07 09:23:02 +00:00
$stmt = Database :: prepare ( "
SELECT `loginname` AS `admin`
FROM `" . TABLE_PANEL_ADMINS . "`
2024-01-14 08:40:33 +00:00
WHERE `loginname` = : loginname " .
$select_additional
);
2022-04-28 18:48:00 +00:00
Database :: pexecute ( $stmt , [
2018-11-30 12:45:17 +00:00
" loginname " => $loginname
2022-04-28 18:48:00 +00:00
]);
2013-11-04 14:23:52 +00:00
$row = $stmt -> fetch ( PDO :: FETCH_ASSOC );
2010-01-26 08:59:19 +00:00
}
2010-01-26 09:45:57 +00:00
2021-02-16 11:38:01 +00:00
if ( $row && $row [ 'admin' ] == $loginname ) {
2010-01-20 16:55:27 +00:00
$table = " ` " . TABLE_PANEL_ADMINS . " ` " ;
$uid = 'adminid' ;
$adminsession = '1' ;
2013-04-27 07:06:19 +00:00
} else {
2013-12-14 09:28:33 +00:00
// Log failed login
2022-04-28 18:48:00 +00:00
$rstlog = FroxlorLogger :: getInstanceOf ([
2018-11-30 12:45:17 +00:00
'loginname' => $_SERVER [ 'REMOTE_ADDR' ]
2022-04-28 18:48:00 +00:00
]);
2024-05-03 05:54:13 +00:00
$rstlog -> logAction ( FroxlorLogger :: LOGIN_ACTION , LOG_WARNING , " Unknown user tried to login. " );
2013-12-14 09:28:33 +00:00
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'index.php' , [
2018-11-30 12:45:17 +00:00
'showmessage' => '2'
2022-04-28 18:48:00 +00:00
]);
2018-11-30 12:45:17 +00:00
exit ();
2010-01-20 16:55:27 +00:00
}
}
2024-01-07 09:23:02 +00:00
$userinfo_stmt = Database :: prepare ( "
SELECT * FROM $table WHERE `loginname` = : loginname
" );
2022-04-28 18:48:00 +00:00
Database :: pexecute ( $userinfo_stmt , [
2018-11-30 12:45:17 +00:00
" loginname " => $loginname
2022-04-28 18:48:00 +00:00
]);
2018-12-22 07:15:31 +00:00
$userinfo = $userinfo_stmt -> fetch ( PDO :: FETCH_ASSOC );
2010-01-20 16:55:27 +00:00
2018-12-22 07:15:31 +00:00
if ( $userinfo [ 'loginfail_count' ] >= Settings :: Get ( 'login.maxloginattempts' ) && $userinfo [ 'lastlogin_fail' ] > ( time () - Settings :: Get ( 'login.deactivatetime' ))) {
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'index.php' , [
2018-11-30 12:45:17 +00:00
'showmessage' => '3'
2022-04-28 18:48:00 +00:00
]);
2018-11-30 12:45:17 +00:00
exit ();
2022-04-28 18:48:00 +00:00
} elseif ( Crypt :: validatePasswordLogin ( $userinfo , $password , $table , $uid )) {
2018-11-30 12:45:17 +00:00
// only show "you're banned" if the login was successful
// because we don't want to publish that the user does exist
2018-12-22 07:15:31 +00:00
if ( $userinfo [ 'deactivated' ]) {
unset ( $userinfo );
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'index.php' , [
2018-11-30 12:45:17 +00:00
'showmessage' => '5'
2022-04-28 18:48:00 +00:00
]);
2018-11-30 12:45:17 +00:00
exit ();
} else {
// login correct
// reset loginfail_counter, set lastlogin_succ
2024-01-07 09:23:02 +00:00
$stmt = Database :: prepare ( "
UPDATE $table
SET `lastlogin_succ` = : lastlogin_succ , `loginfail_count` = '0'
WHERE `$uid` = : uid
" );
2022-04-28 18:48:00 +00:00
Database :: pexecute ( $stmt , [
2018-11-30 12:45:17 +00:00
" lastlogin_succ " => time (),
2018-12-22 07:15:31 +00:00
" uid " => $userinfo [ $uid ]
2022-04-28 18:48:00 +00:00
]);
2018-12-22 07:15:31 +00:00
$userinfo [ 'userid' ] = $userinfo [ $uid ];
$userinfo [ 'adminsession' ] = $adminsession ;
2018-11-30 12:45:17 +00:00
}
2013-04-27 07:06:19 +00:00
} else {
2010-01-20 16:55:27 +00:00
// login incorrect
2024-01-07 09:23:02 +00:00
$stmt = Database :: prepare ( "
UPDATE $table
2013-11-04 14:23:52 +00:00
SET `lastlogin_fail` = : lastlogin_fail , `loginfail_count` = `loginfail_count` + 1
2024-01-07 09:23:02 +00:00
WHERE `$uid` = : uid
" );
2022-04-28 18:48:00 +00:00
Database :: pexecute ( $stmt , [
2018-11-30 12:45:17 +00:00
" lastlogin_fail " => time (),
2018-12-22 07:15:31 +00:00
" uid " => $userinfo [ $uid ]
2022-04-28 18:48:00 +00:00
]);
2013-12-14 09:28:33 +00:00
// Log failed login
2022-04-28 18:48:00 +00:00
$rstlog = FroxlorLogger :: getInstanceOf ([
2018-11-30 12:45:17 +00:00
'loginname' => $_SERVER [ 'REMOTE_ADDR' ]
2022-04-28 18:48:00 +00:00
]);
2024-05-03 05:54:13 +00:00
$rstlog -> logAction ( FroxlorLogger :: LOGIN_ACTION , LOG_WARNING , " User tried to login with wrong password. " );
2013-12-14 09:28:33 +00:00
2018-12-22 07:15:31 +00:00
unset ( $userinfo );
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'index.php' , [
2018-11-30 12:45:17 +00:00
'showmessage' => '2'
2022-04-28 18:48:00 +00:00
]);
2018-11-30 12:45:17 +00:00
exit ();
2010-01-20 16:55:27 +00:00
}
2018-11-30 12:45:17 +00:00
// 2FA activated
2018-12-22 07:15:31 +00:00
if ( Settings :: Get ( '2fa.enabled' ) == '1' && $userinfo [ 'type_2fa' ] > 0 ) {
2024-07-20 08:16:48 +00:00
// check for remember cookie
if ( ! empty ( $_COOKIE [ 'frx_2fa_remember' ])) {
list ( $selector , $authenticator ) = explode ( ':' , $_COOKIE [ 'frx_2fa_remember' ]);
$sel_stmt = Database :: prepare ( " SELECT `token` FROM ` " . TABLE_PANEL_2FA_TOKENS . " ` WHERE `selector` = :selector AND `userid` = :uid AND `valid_until` >= UNIX_TIMESTAMP() " );
$token_check = Database :: pexecute_first ( $sel_stmt , [ 'selector' => $selector , 'uid' => $userinfo [ $uid ]]);
if ( $token_check && hash_equals ( $token_check [ 'token' ], hash ( 'sha256' , base64_decode ( $authenticator )))) {
if ( ! finishLogin ( $userinfo )) {
Response :: redirectTo ( 'index.php' , [
'showmessage' => '2'
]);
}
exit ();
}
2024-08-14 18:24:24 +00:00
// not found or invalid, this cookie is useless, get rid of it
unset ( $_COOKIE [ 'frx_2fa_remember' ]);
setcookie ( 'frx_2fa_remember' , " " , time () - 3600 );
2024-07-20 08:16:48 +00:00
}
2018-11-30 12:45:17 +00:00
// redirect to code-enter-page
2018-12-22 07:15:31 +00:00
$_SESSION [ 'secret_2fa' ] = ( $userinfo [ 'type_2fa' ] == 2 ? $userinfo [ 'data_2fa' ] : 'email' );
$_SESSION [ 'uid_2fa' ] = $userinfo [ $uid ];
2018-11-30 12:45:17 +00:00
$_SESSION [ 'uidfield_2fa' ] = $uid ;
$_SESSION [ 'uidtable_2fa' ] = $table ;
$_SESSION [ 'unfo_2fa' ] = $is_admin ;
// send mail if type_2fa = 1 (email)
2018-12-22 07:15:31 +00:00
if ( $userinfo [ 'type_2fa' ] == 1 ) {
2018-11-30 12:45:17 +00:00
// generate code
2022-05-15 10:27:48 +00:00
$tfa = new FroxlorTwoFactorAuth ( 'Froxlor ' . Settings :: Get ( 'system.hostname' ));
2023-11-08 10:50:33 +00:00
$secret = $tfa -> createSecret ();
$code = $tfa -> getCode ( $secret );
2018-11-30 12:45:17 +00:00
// set code for user
$stmt = Database :: prepare ( " UPDATE $table SET `data_2fa` = :d2fa WHERE ` $uid ` = :uid " );
2022-04-28 18:48:00 +00:00
Database :: pexecute ( $stmt , [
2023-11-08 10:50:33 +00:00
" d2fa " => $secret ,
2018-12-22 07:15:31 +00:00
" uid " => $userinfo [ $uid ]
2022-04-28 18:48:00 +00:00
]);
2018-11-30 12:45:17 +00:00
// build up & send email
$_mailerror = false ;
$mailerr_msg = " " ;
2022-04-28 18:48:00 +00:00
$replace_arr = [
2018-11-30 12:45:17 +00:00
'CODE' => $code
2022-04-28 18:48:00 +00:00
];
$mail_body = html_entity_decode ( PhpHelper :: replaceVariables ( lng ( 'mails.2fa.mailbody' ), $replace_arr ));
2018-11-30 12:45:17 +00:00
try {
2022-04-28 18:48:00 +00:00
$mail -> Subject = lng ( 'mails.2fa.subject' );
2018-11-30 12:45:17 +00:00
$mail -> AltBody = $mail_body ;
$mail -> MsgHTML ( str_replace ( " \n " , " <br /> " , $mail_body ));
2022-04-28 18:48:00 +00:00
$mail -> AddAddress ( $userinfo [ 'email' ], User :: getCorrectUserSalutation ( $userinfo ));
2018-11-30 12:45:17 +00:00
$mail -> Send ();
2018-12-18 12:45:05 +00:00
} catch ( \PHPMailer\PHPMailer\Exception $e ) {
2018-11-30 12:45:17 +00:00
$mailerr_msg = $e -> errorMessage ();
$_mailerror = true ;
} catch ( Exception $e ) {
$mailerr_msg = $e -> getMessage ();
$_mailerror = true ;
2013-11-04 14:23:52 +00:00
}
2013-11-18 12:02:59 +00:00
2018-11-30 12:45:17 +00:00
if ( $_mailerror ) {
2022-04-28 18:48:00 +00:00
$rstlog = FroxlorLogger :: getInstanceOf ([
2018-11-30 12:45:17 +00:00
'loginname' => '2fa code-sending'
2022-04-28 18:48:00 +00:00
]);
$rstlog -> logAction ( FroxlorLogger :: ADM_ACTION , LOG_ERR , " Error sending mail: " . $mailerr_msg );
Response :: redirectTo ( 'index.php' , [
2018-11-30 12:45:17 +00:00
'showmessage' => '4' ,
2018-12-22 07:15:31 +00:00
'customermail' => $userinfo [ 'email' ]
2022-04-28 18:48:00 +00:00
]);
2018-11-30 12:45:17 +00:00
exit ();
}
2014-02-19 10:08:43 +00:00
2018-11-30 12:45:17 +00:00
$mail -> ClearAddresses ();
2014-01-05 21:35:26 +00:00
}
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'index.php' , [
2018-11-30 12:45:17 +00:00
'action' => '2fa_entercode'
2022-04-28 18:48:00 +00:00
]);
2018-11-30 12:45:17 +00:00
exit ();
}
2014-02-19 10:08:43 +00:00
2022-02-15 19:37:27 +00:00
if ( ! finishLogin ( $userinfo )) {
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'index.php' , [
2018-11-30 12:45:17 +00:00
'showmessage' => '2'
2022-04-28 18:48:00 +00:00
]);
2010-01-20 16:55:27 +00:00
}
2018-11-30 12:45:17 +00:00
exit ();
2013-04-27 07:06:19 +00:00
} else {
2024-05-09 14:03:46 +00:00
$smessage = ( int ) Request :: get ( 'showmessage' , 0 );
2010-01-20 16:55:27 +00:00
$message = '' ;
2011-02-08 11:53:24 +00:00
$successmessage = '' ;
2010-01-20 16:55:27 +00:00
2013-04-27 07:06:19 +00:00
switch ( $smessage ) {
2018-11-30 12:45:17 +00:00
case 1 :
2022-04-28 18:48:00 +00:00
$successmessage = lng ( 'pwdreminder.success' );
2018-11-30 12:45:17 +00:00
break ;
case 2 :
2022-04-28 18:48:00 +00:00
$message = lng ( 'error.login' );
2018-11-30 12:45:17 +00:00
break ;
case 3 :
2022-04-28 18:48:00 +00:00
$message = lng ( 'error.login_blocked' , [ Settings :: Get ( 'login.deactivatetime' )]);
2018-11-30 12:45:17 +00:00
break ;
case 4 :
2022-11-05 11:51:23 +00:00
$message = lng ( 'error.errorsendingmailpub' );
2018-11-30 12:45:17 +00:00
break ;
case 5 :
2022-04-28 18:48:00 +00:00
$message = lng ( 'error.user_banned' );
2018-11-30 12:45:17 +00:00
break ;
case 6 :
2022-04-28 18:48:00 +00:00
$successmessage = lng ( 'pwdreminder.changed' );
2018-11-30 12:45:17 +00:00
break ;
case 7 :
2022-04-28 18:48:00 +00:00
$message = lng ( 'pwdreminder.wrongcode' );
2018-11-30 12:45:17 +00:00
break ;
case 8 :
2022-04-28 18:48:00 +00:00
$message = lng ( 'pwdreminder.notallowed' );
2018-11-30 12:45:17 +00:00
break ;
2010-01-20 16:55:27 +00:00
}
2010-01-26 09:45:57 +00:00
2022-02-15 19:37:27 +00:00
$update_in_progress = false ;
2022-04-28 18:48:00 +00:00
if ( Froxlor :: hasUpdates () || Froxlor :: hasDbUpdates ()) {
2022-02-15 19:37:27 +00:00
$update_in_progress = true ;
2010-01-26 09:45:57 +00:00
}
2018-11-30 12:45:17 +00:00
2014-01-05 21:35:26 +00:00
// Pass the last used page if needed
2024-05-16 06:30:35 +00:00
$lastscript = Request :: any ( 'script' , '' );
if ( ! empty ( $lastscript )) {
2022-01-18 08:29:13 +00:00
$lastscript = str_replace ( " .. " , " " , $lastscript );
$lastscript = htmlspecialchars ( $lastscript , ENT_QUOTES );
2014-11-04 12:01:42 +00:00
2024-05-16 06:30:35 +00:00
if ( file_exists ( __DIR__ . " / " . $lastscript )) {
$_SESSION [ 'lastscript' ] = $lastscript ;
} else {
2014-11-04 12:01:42 +00:00
$lastscript = " " ;
}
2014-01-05 21:35:26 +00:00
}
2024-05-16 06:30:35 +00:00
$lastqrystr = Request :: any ( 'qrystr' , '' );
2023-08-11 10:09:23 +00:00
if ( ! empty ( $lastqrystr )) {
2024-05-16 06:30:35 +00:00
$lastqrystr = urlencode ( $lastqrystr );
2023-08-11 10:09:23 +00:00
$_SESSION [ 'lastqrystr' ] = $lastqrystr ;
}
2010-01-20 16:55:27 +00:00
2022-03-18 11:53:34 +00:00
UI :: view ( 'login/login.html.twig' , [
2022-02-15 19:37:27 +00:00
'pagetitle' => 'Login' ,
'upd_in_progress' => $update_in_progress ,
'message' => $message ,
'successmsg' => $successmessage
]);
2010-01-20 16:55:27 +00:00
}
}
2013-04-27 07:06:19 +00:00
if ( $action == 'forgotpwd' ) {
2010-04-14 10:09:31 +00:00
$adminchecked = false ;
2010-04-14 10:27:28 +00:00
$message = '' ;
2023-06-05 10:10:39 +00:00
if ( ! empty ( $_POST )) {
2024-05-09 13:48:23 +00:00
$loginname = Validate :: validate ( Request :: post ( 'loginname' ), 'loginname' );
$email = Validate :: validateEmail ( Request :: post ( 'loginemail' ));
2020-02-29 07:16:55 +00:00
$result_stmt = Database :: prepare ( " SELECT `adminid`, `customerid`, `customernumber`, `firstname`, `name`, `company`, `email`, `loginname`, `def_language`, `deactivated` FROM ` " . TABLE_PANEL_CUSTOMERS . " `
2013-11-04 14:23:52 +00:00
WHERE `loginname` = : loginname
2018-11-30 12:45:17 +00:00
AND `email` = : email " );
2022-04-28 18:48:00 +00:00
Database :: pexecute ( $result_stmt , [
2018-11-30 12:45:17 +00:00
" loginname " => $loginname ,
" email " => $email
2022-04-28 18:48:00 +00:00
]);
2013-11-04 14:23:52 +00:00
if ( Database :: num_rows () == 0 ) {
2013-11-30 20:30:24 +00:00
$result_stmt = Database :: prepare ( " SELECT `adminid`, `name`, `email`, `loginname`, `def_language`, `deactivated` FROM ` " . TABLE_PANEL_ADMINS . " `
2013-11-04 14:23:52 +00:00
WHERE `loginname` = : loginname
2018-11-30 12:45:17 +00:00
AND `email` = : email " );
2022-04-28 18:48:00 +00:00
Database :: pexecute ( $result_stmt , [
2018-11-30 12:45:17 +00:00
" loginname " => $loginname ,
" email " => $email
2022-04-28 18:48:00 +00:00
]);
2013-11-18 12:02:59 +00:00
2013-11-04 14:23:52 +00:00
if ( Database :: num_rows () > 0 ) {
2010-04-14 10:27:28 +00:00
$adminchecked = true ;
2013-04-27 07:06:19 +00:00
} else {
2013-11-04 14:23:52 +00:00
$result_stmt = null ;
2010-04-14 10:27:28 +00:00
}
2010-01-20 16:55:27 +00:00
}
2022-11-06 09:11:40 +00:00
if ( $adminchecked ) {
if ( Settings :: Get ( 'panel.allow_preset_admin' ) != '1' ) {
$message = lng ( 'pwdreminder.notallowed' );
unset ( $adminchecked );
2011-04-16 11:32:11 +00:00
}
2022-11-06 09:11:40 +00:00
} else {
if ( Settings :: Get ( 'panel.allow_preset' ) != '1' ) {
$message = lng ( 'pwdreminder.notallowed' );
}
}
2010-04-14 10:27:28 +00:00
2022-11-06 09:11:40 +00:00
if ( empty ( $message )) {
if ( $result_stmt !== null ) {
$user = $result_stmt -> fetch ( PDO :: FETCH_ASSOC );
2010-01-20 16:55:27 +00:00
2022-11-06 09:11:40 +00:00
/* Check whether user is banned */
if ( $user [ 'deactivated' ]) {
$message = lng ( 'pwdreminder.notallowed' );
} else {
if (( $adminchecked && Settings :: Get ( 'panel.allow_preset_admin' ) == '1' ) || $adminchecked == false ) {
if ( $user !== false ) {
// build a activation code
$timestamp = time ();
$first = substr ( md5 ( $user [ 'loginname' ] . $timestamp . PhpHelper :: randomStr ( 16 )), 0 , 15 );
$third = substr ( md5 ( $user [ 'email' ] . $timestamp . PhpHelper :: randomStr ( 16 )), - 15 );
$activationcode = $first . $timestamp . $third . substr ( md5 ( $third . $timestamp ), 0 , 10 );
// Drop all existing activation codes for this user
$stmt = Database :: prepare ( " DELETE FROM ` " . TABLE_PANEL_ACTIVATION . " `
WHERE `userid` = : userid
AND `admin` = : admin " );
$params = [
" userid " => $adminchecked ? $user [ 'adminid' ] : $user [ 'customerid' ],
" admin " => $adminchecked ? 1 : 0
];
Database :: pexecute ( $stmt , $params );
// Add new activation code to database
$stmt = Database :: prepare ( " INSERT INTO ` " . TABLE_PANEL_ACTIVATION . " `
( userid , admin , creation , activationcode )
VALUES ( : userid , : admin , : creation , : activationcode ) " );
$params = [
" userid " => $adminchecked ? $user [ 'adminid' ] : $user [ 'customerid' ],
" admin " => $adminchecked ? 1 : 0 ,
" creation " => $timestamp ,
" activationcode " => $activationcode
];
Database :: pexecute ( $stmt , $params );
$rstlog = FroxlorLogger :: getInstanceOf ([
'loginname' => 'password_reset'
]);
$rstlog -> logAction ( FroxlorLogger :: USR_ACTION , LOG_WARNING , " User ' " . $user [ 'loginname' ] . " ' requested a link for setting a new password. " );
// Set together our activation link
$protocol = empty ( $_SERVER [ 'HTTPS' ]) ? 'http' : 'https' ;
// this can be a fixed value to avoid potential exploiting by modifying headers
$host = Settings :: Get ( 'system.hostname' ); // $_SERVER['HTTP_HOST'];
$port = $_SERVER [ 'SERVER_PORT' ] != 80 ? ':' . $_SERVER [ 'SERVER_PORT' ] : '' ;
// don't add :443 when https is used, as it is default (and just looks weird!)
if ( $protocol == 'https' && $_SERVER [ 'SERVER_PORT' ] == '443' ) {
$port = '' ;
}
// there can be only one script to handle this so we can use a fixed value here
$script = " /index.php " ; // $_SERVER['SCRIPT_NAME'];
if ( Settings :: Get ( 'system.froxlordirectlyviahostname' ) == 0 ) {
$script = FileDir :: makeCorrectFile ( " / " . basename ( __DIR__ ) . " / " . $script );
}
$activationlink = $protocol . '://' . $host . $port . $script . '?action=resetpwd&resetcode=' . $activationcode ;
$replace_arr = [
'SALUTATION' => User :: getCorrectUserSalutation ( $user ),
'NAME' => $user [ 'name' ],
'FIRSTNAME' => $user [ 'firstname' ] ? ? " " ,
'COMPANY' => $user [ 'company' ] ? ? " " ,
'CUSTOMER_NO' => $user [ 'customernumber' ] ? ? 0 ,
'USERNAME' => $loginname ,
'LINK' => $activationlink
];
$def_language = ( $user [ 'def_language' ] != '' ) ? $user [ 'def_language' ] : Settings :: Get ( 'panel.standardlanguage' );
$result_stmt = Database :: prepare ( 'SELECT `value` FROM `' . TABLE_PANEL_TEMPLATES . ' `
WHERE `adminid` = : adminid
AND `language` = : lang
AND `templategroup` = \ ' mails\ '
AND `varname` = \ 'password_reset_subject\'' );
Database :: pexecute ( $result_stmt , [
" adminid " => $user [ 'adminid' ],
" lang " => $def_language
]);
$result = $result_stmt -> fetch ( PDO :: FETCH_ASSOC );
$mail_subject = html_entity_decode ( PhpHelper :: replaceVariables ((( $result [ 'value' ] != '' ) ? $result [ 'value' ] : lng ( 'mails.password_reset.subject' )), $replace_arr ));
$result_stmt = Database :: prepare ( 'SELECT `value` FROM `' . TABLE_PANEL_TEMPLATES . ' `
WHERE `adminid` = : adminid
AND `language` = : lang
AND `templategroup` = \ ' mails\ '
AND `varname` = \ 'password_reset_mailbody\'' );
Database :: pexecute ( $result_stmt , [
" adminid " => $user [ 'adminid' ],
" lang " => $def_language
]);
$result = $result_stmt -> fetch ( PDO :: FETCH_ASSOC );
$mail_body = html_entity_decode ( PhpHelper :: replaceVariables ((( $result [ 'value' ] != '' ) ? $result [ 'value' ] : lng ( 'mails.password_reset.mailbody' )), $replace_arr ));
$_mailerror = false ;
$mailerr_msg = " " ;
try {
$mail -> Subject = $mail_subject ;
$mail -> AltBody = $mail_body ;
$mail -> MsgHTML ( str_replace ( " \n " , " <br /> " , $mail_body ));
$mail -> AddAddress ( $user [ 'email' ], User :: getCorrectUserSalutation ( $user ));
$mail -> Send ();
} catch ( \PHPMailer\PHPMailer\Exception $e ) {
$mailerr_msg = $e -> errorMessage ();
$_mailerror = true ;
} catch ( Exception $e ) {
$mailerr_msg = $e -> getMessage ();
$_mailerror = true ;
}
if ( $_mailerror ) {
$rstlog = FroxlorLogger :: getInstanceOf ([
'loginname' => 'password_reset'
]);
$rstlog -> logAction ( FroxlorLogger :: ADM_ACTION , LOG_ERR , " Error sending mail: " . $mailerr_msg );
Response :: redirectTo ( 'index.php' , [
'showmessage' => '4' ,
'customermail' => $user [ 'email' ]
]);
exit ();
}
$mail -> ClearAddresses ();
Response :: redirectTo ( 'index.php' , [
'showmessage' => '1'
]);
exit ();
} else {
$rstlog = FroxlorLogger :: getInstanceOf ([
'loginname' => 'password_reset'
]);
2024-05-03 05:54:13 +00:00
$rstlog -> logAction ( FroxlorLogger :: USR_ACTION , LOG_WARNING , " Unknown user requested to set a new password, but was not found in database! " );
2022-11-06 09:11:40 +00:00
$message = lng ( 'login.usernotfound' );
}
2010-04-14 10:27:28 +00:00
2022-11-06 09:11:40 +00:00
unset ( $user );
2010-04-14 10:27:28 +00:00
}
2010-01-20 16:55:27 +00:00
}
2022-11-06 09:11:40 +00:00
} else {
2022-12-02 12:25:17 +00:00
$message = lng ( 'pwdreminder.notallowed' );
2010-01-20 16:55:27 +00:00
}
2010-03-01 07:42:07 +00:00
}
2010-01-20 16:55:27 +00:00
}
2022-03-18 11:53:34 +00:00
UI :: view ( 'login/fpwd.html.twig' , [
2022-04-28 18:48:00 +00:00
'pagetitle' => lng ( 'login.presend' ),
2023-08-11 10:09:23 +00:00
'formaction' => 'index.php?action=' . $action ,
2022-02-16 20:08:25 +00:00
'message' => $message ,
]);
2010-01-20 16:55:27 +00:00
}
2013-11-30 20:30:24 +00:00
if ( $action == 'resetpwd' ) {
$message = '' ;
2013-12-15 11:24:32 +00:00
2013-12-01 09:34:31 +00:00
// Remove old activation codes
$stmt = Database :: prepare ( " DELETE FROM ` " . TABLE_PANEL_ACTIVATION . " `
2018-11-30 12:45:17 +00:00
WHERE creation < : oldest " );
2022-04-28 18:48:00 +00:00
Database :: pexecute ( $stmt , [
2018-11-30 12:45:17 +00:00
" oldest " => time () - 86400
2022-04-28 18:48:00 +00:00
]);
2013-12-15 11:24:32 +00:00
2024-05-09 14:03:46 +00:00
$activationcode = Request :: get ( 'resetcode' );
if ( ! empty ( $activationcode ) && strlen ( $activationcode ) == 50 ) {
2013-11-30 20:30:24 +00:00
// Check if activation code is valid
$timestamp = substr ( $activationcode , 15 , 10 );
$third = substr ( $activationcode , 25 , 15 );
$check = substr ( $activationcode , 40 , 10 );
2013-12-15 11:24:32 +00:00
2013-11-30 20:30:24 +00:00
if ( substr ( md5 ( $third . $timestamp ), 0 , 10 ) == $check && $timestamp >= time () - 86400 ) {
2023-06-05 10:10:39 +00:00
if ( ! empty ( $_POST )) {
2013-11-30 20:30:24 +00:00
$stmt = Database :: prepare ( " SELECT `userid`, `admin` FROM ` " . TABLE_PANEL_ACTIVATION . " `
2018-11-30 12:45:17 +00:00
WHERE `activationcode` = : activationcode " );
2022-04-28 18:48:00 +00:00
$result = Database :: pexecute_first ( $stmt , [
2018-11-30 12:45:17 +00:00
" activationcode " => $activationcode
2022-04-28 18:48:00 +00:00
]);
2013-12-15 11:24:32 +00:00
2013-11-30 20:30:24 +00:00
if ( $result !== false ) {
2020-02-08 09:03:41 +00:00
try {
2024-05-09 13:48:23 +00:00
$new_password = Crypt :: validatePassword ( Request :: post ( 'new_password' ), true );
$new_password_confirm = Crypt :: validatePassword ( Request :: post ( 'new_password_confirm' ), true );
2020-02-08 09:03:41 +00:00
} catch ( Exception $e ) {
$message = $e -> getMessage ();
}
if ( empty ( $message ) && ( empty ( $new_password ) || $new_password != $new_password_confirm )) {
2022-04-28 18:48:00 +00:00
$message = lng ( 'error.newpasswordconfirmerror' );
2013-11-30 20:30:24 +00:00
}
2013-12-15 11:24:32 +00:00
2020-02-08 09:03:41 +00:00
if ( empty ( $message )) {
2013-11-30 20:30:24 +00:00
// Update user password
if ( $result [ 'admin' ] == 1 ) {
$stmt = Database :: prepare ( " UPDATE ` " . TABLE_PANEL_ADMINS . " `
SET `password` = : newpassword
2018-11-30 12:45:17 +00:00
WHERE `adminid` = : userid " );
2013-11-30 20:30:24 +00:00
} else {
$stmt = Database :: prepare ( " UPDATE ` " . TABLE_PANEL_CUSTOMERS . " `
SET `password` = : newpassword
2018-11-30 12:45:17 +00:00
WHERE `customerid` = : userid " );
2013-11-30 20:30:24 +00:00
}
2022-04-28 18:48:00 +00:00
Database :: pexecute ( $stmt , [
" newpassword " => Crypt :: makeCryptPassword ( $new_password ),
2018-11-30 12:45:17 +00:00
" userid " => $result [ 'userid' ]
2022-04-28 18:48:00 +00:00
]);
2018-11-30 12:45:17 +00:00
2022-04-28 18:48:00 +00:00
$rstlog = FroxlorLogger :: getInstanceOf ([
2018-11-30 12:45:17 +00:00
'loginname' => 'password_reset'
2022-04-28 18:48:00 +00:00
]);
$rstlog -> logAction ( FroxlorLogger :: USR_ACTION , LOG_NOTICE , " changed password using password reset. " );
2013-12-15 11:24:32 +00:00
2013-11-30 20:30:24 +00:00
// Remove activation code from DB
$stmt = Database :: prepare ( " DELETE FROM ` " . TABLE_PANEL_ACTIVATION . " `
WHERE `activationcode` = : activationcode
2018-11-30 12:45:17 +00:00
AND `userid` = : userid " );
2022-04-28 18:48:00 +00:00
Database :: pexecute ( $stmt , [
2018-11-30 12:45:17 +00:00
" activationcode " => $activationcode ,
" userid " => $result [ 'userid' ]
2022-04-28 18:48:00 +00:00
]);
Response :: redirectTo ( 'index.php' , [
2018-11-30 12:45:17 +00:00
" showmessage " => '6'
2022-04-28 18:48:00 +00:00
]);
2013-11-30 20:30:24 +00:00
}
} else {
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'index.php' , [
2018-11-30 12:45:17 +00:00
" showmessage " => '7'
2022-04-28 18:48:00 +00:00
]);
2013-11-30 20:30:24 +00:00
}
}
2013-12-15 11:24:32 +00:00
2022-03-18 11:53:34 +00:00
UI :: view ( 'login/rpwd.html.twig' , [
2022-04-28 18:48:00 +00:00
'pagetitle' => lng ( 'pwdreminder.choosenew' ),
2022-03-18 10:41:07 +00:00
'formaction' => 'index.php?action=resetpwd&resetcode=' . $activationcode ,
'message' => $message ,
]);
2013-11-30 20:30:24 +00:00
} else {
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'index.php' , [
2018-11-30 12:45:17 +00:00
" showmessage " => '7'
2022-04-28 18:48:00 +00:00
]);
2013-11-30 20:30:24 +00:00
}
} else {
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'index.php' );
2013-11-30 20:30:24 +00:00
}
}
2018-11-30 12:45:17 +00:00
2023-05-24 14:02:07 +00:00
// one-time link login
if ( $action == 'll' ) {
if ( ! Froxlor :: hasUpdates () && ! Froxlor :: hasDbUpdates ()) {
$loginname = Request :: get ( 'ln' );
$hash = Request :: get ( 'h' );
if ( $loginname && $hash ) {
$sel_stmt = Database :: prepare ( "
SELECT * FROM `" . TABLE_PANEL_LOGINLINKS . "`
WHERE `loginname` = : loginname AND `hash` = : hash
" );
try {
$entry = Database :: pexecute_first ( $sel_stmt , [ 'loginname' => $loginname , 'hash' => $hash ]);
} catch ( Exception $e ) {
$entry = false ;
}
if ( $entry ) {
// delete entry
$del_stmt = Database :: prepare ( " DELETE FROM ` " . TABLE_PANEL_LOGINLINKS . " ` WHERE `loginname` = :loginname AND `hash` = :hash " );
Database :: pexecute ( $del_stmt , [ 'loginname' => $loginname , 'hash' => $hash ]);
if ( time () <= $entry [ 'valid_until' ]) {
$valid = true ;
// validate source ip if specified
if ( ! empty ( $entry [ 'allowed_from' ])) {
$valid = false ;
$ip_list = explode ( " , " , $entry [ 'allowed_from' ]);
if ( FroxlorRPC :: validateAllowedFrom ( $ip_list , $_SERVER [ 'REMOTE_ADDR' ])) {
$valid = true ;
}
}
if ( $valid ) {
// login user / select only non-deactivated (in case the user got deactivated after generating the link)
$userinfo_stmt = Database :: prepare ( " SELECT * FROM ` " . TABLE_PANEL_CUSTOMERS . " ` WHERE `loginname`= :loginname AND `deactivated` = 0 " );
try {
$userinfo = Database :: pexecute_first ( $userinfo_stmt , [
" loginname " => $loginname
]);
} catch ( Exception $e ) {
$userinfo = false ;
}
if ( $userinfo ) {
$userinfo [ 'userid' ] = $userinfo [ 'customerid' ];
$userinfo [ 'adminsession' ] = 0 ;
finishLogin ( $userinfo );
}
}
}
}
}
}
Response :: redirectTo ( 'index.php' );
}
2018-12-22 07:15:31 +00:00
function finishLogin ( $userinfo )
2018-11-30 12:45:17 +00:00
{
2018-12-22 07:15:31 +00:00
if ( isset ( $userinfo [ 'userid' ]) && $userinfo [ 'userid' ] != '' ) {
2023-08-11 10:09:23 +00:00
session_regenerate_id ( true );
2022-04-28 18:48:00 +00:00
CurrentUser :: setData ( $userinfo );
2018-11-30 12:45:17 +00:00
2022-10-16 13:28:30 +00:00
$language = $userinfo [ 'def_language' ] ? ? Settings :: Get ( 'panel.standardlanguage' );
2022-04-28 18:48:00 +00:00
CurrentUser :: setField ( 'language' , $language );
2018-11-30 12:45:17 +00:00
2018-12-22 07:15:31 +00:00
if ( isset ( $userinfo [ 'theme' ]) && $userinfo [ 'theme' ] != '' ) {
$theme = $userinfo [ 'theme' ];
2018-11-30 12:45:17 +00:00
} else {
$theme = Settings :: Get ( 'panel.default_theme' );
}
2024-07-20 08:16:48 +00:00
CurrentUser :: setField ( 'theme' , $theme );
2018-11-30 12:45:17 +00:00
2022-04-28 18:48:00 +00:00
$qryparams = [];
2023-08-11 10:09:23 +00:00
if ( ! empty ( $_SESSION [ 'lastqrystr' ])) {
2023-06-05 10:10:39 +00:00
parse_str ( urldecode ( $_SESSION [ 'lastqrystr' ]), $qryparams );
unset ( $_SESSION [ 'lastqrystr' ]);
2018-11-30 12:45:17 +00:00
}
2018-12-22 07:15:31 +00:00
if ( $userinfo [ 'adminsession' ] == '1' ) {
2022-04-28 18:48:00 +00:00
if ( Froxlor :: hasUpdates () || Froxlor :: hasDbUpdates ()) {
Response :: redirectTo ( 'admin_updates.php?page=overview' );
2018-11-30 12:45:17 +00:00
} else {
2023-08-11 10:09:23 +00:00
if ( ! empty ( $_SESSION [ 'lastscript' ])) {
2023-06-05 10:10:39 +00:00
$lastscript = $_SESSION [ 'lastscript' ];
unset ( $_SESSION [ 'lastscript' ]);
if ( preg_match ( " /customer \ _/ " , $lastscript ) === 1 ) {
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'admin_customers.php' , [
2018-11-30 12:45:17 +00:00
" page " => " customers "
2022-04-28 18:48:00 +00:00
]);
2018-11-30 12:45:17 +00:00
} else {
2023-06-05 10:10:39 +00:00
Response :: redirectTo ( $lastscript , $qryparams );
2018-11-30 12:45:17 +00:00
}
} else {
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'admin_index.php' , $qryparams );
2018-11-30 12:45:17 +00:00
}
}
} else {
2023-08-11 10:09:23 +00:00
if ( ! empty ( $_SESSION [ 'lastscript' ])) {
2023-06-05 10:10:39 +00:00
$lastscript = $_SESSION [ 'lastscript' ];
unset ( $_SESSION [ 'lastscript' ]);
Response :: redirectTo ( $lastscript , $qryparams );
2018-11-30 12:45:17 +00:00
} else {
2022-04-28 18:48:00 +00:00
Response :: redirectTo ( 'customer_index.php' , $qryparams );
2018-11-30 12:45:17 +00:00
}
}
}
return false ;
2018-12-20 11:38:18 +00:00
}