From 2285eec431fef0864bd41c4260b345388583f863 Mon Sep 17 00:00:00 2001 From: Till Brehm Date: Tue, 19 Oct 2021 10:12:07 +0200 Subject: [PATCH 1/4] Updated Debian version in readme file --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e0eea359d..022897c584 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Development branch: [![pipeline status](https://git.ispconfig.org/ispconfig/ispc [^1]: not actively tested ## Supported operating systems -- Debian 9, 10, and testing +- Debian 9, 11, and testing - Ubuntu 16.04 - 20.04 - CentOS 7 and 8 -- GitLab From 139bbcaf8646e3ad7ab42b82bc31e4756feaba7f Mon Sep 17 00:00:00 2001 From: Till Brehm Date: Tue, 19 Oct 2021 15:21:46 +0200 Subject: [PATCH 2/4] Various security improvments in API and server code. --- README.md | 2 +- .../sql/incremental/upd_dev_collection.sql | 1 + install/sql/ispconfig3.sql | 1 + interface/lib/classes/remoting.inc.php | 118 ++++++++++++++++-- interface/lib/classes/remoting_lib.inc.php | 6 +- interface/lib/classes/session.inc.php | 12 +- interface/web/login/index.php | 12 +- server/lib/classes/system.inc.php | 96 +++++++++++--- server/mods-available/web_module.inc.php | 23 +++- 9 files changed, 222 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 022897c584..901cb2a7b9 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Development branch: [![pipeline status](https://git.ispconfig.org/ispconfig/ispc [^1]: not actively tested ## Supported operating systems -- Debian 9, 11, and testing +- Debian 9 - 11, and testing - Ubuntu 16.04 - 20.04 - CentOS 7 and 8 diff --git a/install/sql/incremental/upd_dev_collection.sql b/install/sql/incremental/upd_dev_collection.sql index e69de29bb2..0a17c38737 100644 --- a/install/sql/incremental/upd_dev_collection.sql +++ b/install/sql/incremental/upd_dev_collection.sql @@ -0,0 +1 @@ +ALTER TABLE `remote_session` ADD `remote_ip` VARCHAR(39) NOT NULL DEFAULT '' AFTER `tstamp`; \ No newline at end of file diff --git a/install/sql/ispconfig3.sql b/install/sql/ispconfig3.sql index 51106cc183..4d61c38d8f 100644 --- a/install/sql/ispconfig3.sql +++ b/install/sql/ispconfig3.sql @@ -1317,6 +1317,7 @@ CREATE TABLE `remote_session` ( `remote_functions` text, `client_login` tinyint(1) unsigned NOT NULL default '0', `tstamp` int(10) unsigned NOT NULL DEFAULT '0', + `remote_ip` varchar(39) NOT NULL DEFAULT '', PRIMARY KEY (`remote_session`) ) DEFAULT CHARSET=utf8 ; diff --git a/interface/lib/classes/remoting.inc.php b/interface/lib/classes/remoting.inc.php index fbadebd777..20181102ae 100644 --- a/interface/lib/classes/remoting.inc.php +++ b/interface/lib/classes/remoting.inc.php @@ -85,10 +85,20 @@ class remoting { //* Delete old remoting sessions $sql = "DELETE FROM remote_session WHERE tstamp < UNIX_TIMESTAMP()"; $app->db->query($sql); + + //* Check for max. login attempts + $ip_md5 = md5($_SERVER['REMOTE_ADDR']); + $sql = "SELECT * FROM `attempts_login` WHERE `ip`= ? AND `login_time` > (NOW() - INTERVAL 5 MINUTE) LIMIT 1"; + $alreadyfailed = $app->db->queryOneRecord($sql, $ip_md5); + + if($alreadyfailed['times'] > 10) { + throw new SoapFault('login_failure_limit', 'The login failure limit has been reached.'); + return false; + } if($client_login == true) { $sql = "SELECT * FROM sys_user WHERE USERNAME = ?"; - $user = $app->db->queryOneRecord($sql, $username); + $user = $app->db->queryOneRecord($sql, (string)$username); if($user) { $saved_password = stripslashes($user['passwort']); @@ -104,6 +114,16 @@ class remoting { } } } else { + if(!$alreadyfailed['times'] ) + { + //* user login the first time wrong + $sql = "INSERT INTO `attempts_login` (`ip`, `times`, `login_time`) VALUES (?, 1, NOW())"; + $app->db->query($sql, $ip_md5); + } elseif($alreadyfailed['times'] >= 1) { + //* update times wrong + $sql = "UPDATE `attempts_login` SET `times`=`times`+1, `login_time`=NOW() WHERE `ip` = ? AND `login_time` < NOW() ORDER BY `login_time` DESC LIMIT 1"; + $app->db->query($sql, $ip_md5); + } throw new SoapFault('client_login_failed', 'The login failed. Username or password wrong.'); } if($user['active'] != 1) { @@ -119,17 +139,23 @@ class remoting { //* Create a remote user session //srand ((double)microtime()*1000000); - $remote_session = md5(mt_rand().uniqid('ispco')); + $remote_session = substr(str_shuffle('abcdefghijklmnopqrstuvwxyz'),0,1).sha1(mt_rand().uniqid('ispco',true)); $remote_userid = $user['userid']; $remote_functions = ''; $tstamp = time() + $this->session_timeout; - $sql = 'INSERT INTO remote_session (remote_session,remote_userid,remote_functions,client_login,tstamp' - .') VALUES (?, ?, ?, 1, ?)'; - $app->db->query($sql, $remote_session,$remote_userid,$remote_functions,$tstamp); + $ip = $_SERVER['REMOTE_ADDR']; + $sql = 'INSERT INTO remote_session (remote_session,remote_userid,remote_functions,client_login,tstamp,remote_ip' + .') VALUES (?, ?, ?, 1, ?, ?)'; + $app->db->query($sql, $remote_session,$remote_userid,$remote_functions,$tstamp,$ip); + + //* Delete login attempts after successful login + $sql = "DELETE FROM `attempts_login` WHERE `ip`=?"; + $app->db->query($sql, $ip_md5); + return $remote_session; } else { $sql = "SELECT * FROM remote_user WHERE remote_username = ?"; - $remote_user = $app->db->queryOneRecord($sql, $username); + $remote_user = $app->db->queryOneRecord($sql, (string)$username); if($remote_user) { if(substr($remote_user['remote_password'], 0, 1) === '$') { if(crypt(stripslashes($password), $remote_user['remote_password']) != $remote_user['remote_password']) { @@ -138,7 +164,7 @@ class remoting { } elseif(md5($password) == $remote_user['remote_password']) { // update hash algo $sql = 'UPDATE `remote_user` SET `remote_password` = ? WHERE `remote_username` = ?'; - $app->db->query($sql, $app->auth->crypt_password($password), $username); + $app->db->query($sql, $app->auth->crypt_password($password), (string)$username); } else { $remote_user = null; } @@ -185,15 +211,32 @@ class remoting { } //* Create a remote user session //srand ((double)microtime()*1000000); - $remote_session = md5(mt_rand().uniqid('ispco')); + $remote_session = substr(str_shuffle('abcdefghijklmnopqrstuvwxyz'),0,1).sha1(mt_rand().uniqid('ispco',true)); $remote_userid = $remote_user['remote_userid']; $remote_functions = $remote_user['remote_functions']; $tstamp = time() + $this->session_timeout; - $sql = 'INSERT INTO remote_session (remote_session,remote_userid,remote_functions,tstamp' - .') VALUES (?, ?, ?, ?)'; - $app->db->query($sql, $remote_session,$remote_userid,$remote_functions,$tstamp); + $sql = 'INSERT INTO remote_session (remote_session,remote_userid,remote_functions,tstamp,remote_ip' + .') VALUES (?, ?, ?, ?, ?)'; + $app->db->query($sql, $remote_session,$remote_userid,$remote_functions,$tstamp, $ip); + + //* Delete login attempts after successful login + $sql = "DELETE FROM `attempts_login` WHERE `ip`=?"; + $app->db->query($sql, $ip_md5); + return $remote_session; } else { + + if(!$alreadyfailed['times'] ) + { + //* user login the first time wrong + $sql = "INSERT INTO `attempts_login` (`ip`, `times`, `login_time`) VALUES (?, 1, NOW())"; + $app->db->query($sql, $ip_md5); + } elseif($alreadyfailed['times'] >= 1) { + //* update times wrong + $sql = "UPDATE `attempts_login` SET `times`=`times`+1, `login_time`=NOW() WHERE `ip` = ? AND `login_time` < NOW() ORDER BY `login_time` DESC LIMIT 1"; + $app->db->query($sql, $ip_md5); + } + throw new SoapFault('login_failed', 'The login failed. Username or password wrong.'); return false; } @@ -212,7 +255,7 @@ class remoting { } $sql = "DELETE FROM remote_session WHERE remote_session = ?"; - if($app->db->query($sql, $session_id) != false) { + if($app->db->query($sql, (string)$session_id) != false) { return true; } else { return false; @@ -522,12 +565,61 @@ class remoting { throw new SoapFault('session_id_empty', 'The SessionID is empty.'); return false; } + + if(!is_string($session_id)) { + throw new SoapFault('session_id_nostring', 'Wrong SessionID datatype.'); + return false; + } + + $ip_md5 = md5($_SERVER['REMOTE_ADDR']); + $sql = "SELECT * FROM `attempts_login` WHERE `ip`= ? AND `login_time` > (NOW() - INTERVAL 5 MINUTE) LIMIT 1"; + $alreadyfailed = $app->db->queryOneRecord($sql, $ip_md5); + + if($alreadyfailed['times'] > 10) { + throw new SoapFault('session_failure_limit', 'The Session failure limit has been reached.'); + return false; + } $sql = "SELECT * FROM remote_session WHERE remote_session = ? AND tstamp >= UNIX_TIMESTAMP()"; - $session = $app->db->queryOneRecord($sql, $session_id); + $session = $app->db->queryOneRecord($sql, (string)$session_id); + + if(!is_array($session)) { + if(!$alreadyfailed['times'] ) + { + //* user login the first time wrong + $sql = "INSERT INTO `attempts_login` (`ip`, `times`, `login_time`) VALUES (?, 1, NOW())"; + $app->db->query($sql, $ip_md5); + } elseif($alreadyfailed['times'] >= 1) { + //* update times wrong + $sql = "UPDATE `attempts_login` SET `times`=`times`+1, `login_time`=NOW() WHERE `ip` = ? AND `login_time` < NOW() ORDER BY `login_time` DESC LIMIT 1"; + $app->db->query($sql, $ip_md5); + } + + throw new SoapFault('session_does_not_exist', 'The Session is expired or does not exist.'); + return false; + } + + $ip = $_SERVER['REMOTE_ADDR']; + if($session['remote_ip'] != $ip) { + throw new SoapFault('session_ip_mismatch', 'Session IP mismatch.'); + return false; + } + if($session['remote_userid'] > 0) { return $session; } else { + + if(!$alreadyfailed['times'] ) + { + //* user login the first time wrong + $sql = "INSERT INTO `attempts_login` (`ip`, `times`, `login_time`) VALUES (?, 1, NOW())"; + $app->db->query($sql, $ip_md5); + } elseif($alreadyfailed['times'] >= 1) { + //* update times wrong + $sql = "UPDATE `attempts_login` SET `times`=`times`+1, `login_time`=NOW() WHERE `ip` = ? AND `login_time` < NOW() ORDER BY `login_time` DESC LIMIT 1"; + $app->db->query($sql, $ip_md5); + } + throw new SoapFault('session_does_not_exist', 'The Session is expired or does not exist.'); return false; } diff --git a/interface/lib/classes/remoting_lib.inc.php b/interface/lib/classes/remoting_lib.inc.php index 6436e6e792..c496cb7e22 100644 --- a/interface/lib/classes/remoting_lib.inc.php +++ b/interface/lib/classes/remoting_lib.inc.php @@ -232,7 +232,7 @@ class remoting_lib extends tform_base { if(@is_numeric($primary_id)) { if($primary_id > 0) { // Return a single record - return parent::getDataRecord($primary_id); + return parent::getDataRecord(intval($primary_id)); } elseif($primary_id == -1) { // Return a array with all records $sql = "SELECT * FROM ??"; @@ -255,8 +255,8 @@ class remoting_lib extends tform_base { } else { $sql_where .= "?? = ? AND "; } - $params[] = $key; - $params[] = $val; + $params[] = (string)$key; + $params[] = (string)$val; } $sql_where = substr($sql_where, 0, -5); if($sql_where == '') $sql_where = '1'; diff --git a/interface/lib/classes/session.inc.php b/interface/lib/classes/session.inc.php index 3e93cd4314..55247621a3 100644 --- a/interface/lib/classes/session.inc.php +++ b/interface/lib/classes/session.inc.php @@ -70,9 +70,9 @@ class session { function read ($session_id) { if($this->timeout > 0) { - $rec = $this->db->queryOneRecord("SELECT * FROM sys_session WHERE session_id = ? AND (`permanent` = 'y' OR last_updated >= DATE_SUB(NOW(), INTERVAL ? MINUTE))", $session_id, $this->timeout); + $rec = $this->db->queryOneRecord("SELECT * FROM sys_session WHERE session_id = ? AND (`permanent` = 'y' OR last_updated >= DATE_SUB(NOW(), INTERVAL ? MINUTE))", (string)$session_id, $this->timeout); } else { - $rec = $this->db->queryOneRecord("SELECT * FROM sys_session WHERE session_id = ?", $session_id); + $rec = $this->db->queryOneRecord("SELECT * FROM sys_session WHERE session_id = ?", (string)$session_id); } if (is_array($rec)) { @@ -91,18 +91,18 @@ class session { // Dont write session_data to DB if session data has not been changed after reading it. if(isset($this->session_array['session_data']) && $this->session_array['session_data'] != '' && $this->session_array['session_data'] == $session_data) { - $this->db->query("UPDATE sys_session SET last_updated = NOW() WHERE session_id = ?", $session_id); + $this->db->query("UPDATE sys_session SET last_updated = NOW() WHERE session_id = ?", (string)$session_id); return true; } if (@$this->session_array['session_id'] == '') { $sql = "REPLACE INTO sys_session (session_id,date_created,last_updated,session_data,permanent) VALUES (?,NOW(),NOW(),?,?)"; - $this->db->query($sql, $session_id, $session_data, ($this->permanent ? 'y' : 'n')); + $this->db->query($sql, (string)$session_id, $session_data, ($this->permanent ? 'y' : 'n')); } else { $sql = "UPDATE sys_session SET last_updated = NOW(), session_data = ?" . ($this->permanent ? ", `permanent` = 'y'" : "") . " WHERE session_id = ?"; - $this->db->query($sql, $session_data, $session_id); + $this->db->query($sql, $session_data, (string)$session_id); } @@ -112,7 +112,7 @@ class session { function destroy ($session_id) { $sql = "DELETE FROM sys_session WHERE session_id = ?"; - $this->db->query($sql, $session_id); + $this->db->query($sql, (string)$session_id); return true; } diff --git a/interface/web/login/index.php b/interface/web/login/index.php index 58456dea0e..70c3dbe055 100644 --- a/interface/web/login/index.php +++ b/interface/web/login/index.php @@ -96,7 +96,7 @@ if(count($_POST) > 0) { /* this is the reseller, that shall be re-logged in */ $sql = "SELECT * FROM sys_user WHERE USERNAME = ? and PASSWORT = ?"; - $tmp = $app->db->queryOneRecord($sql, $username, $password); + $tmp = $app->db->queryOneRecord($sql, (string)$username, (string)$password); $client_group_id = $app->functions->intval($tmp['default_group']); $tmp_client = $app->db->queryOneRecord("SELECT client.client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id); @@ -118,7 +118,7 @@ if(count($_POST) > 0) { /* this is the user the reseller wants to 'login as' */ $sql = "SELECT * FROM sys_user WHERE USERNAME = ? and PASSWORT = ?"; - $tmp = $app->db->queryOneRecord($sql, $username, $password); + $tmp = $app->db->queryOneRecord($sql, (string)$username, (string)$password); $tmp_client = $app->db->queryOneRecord("SELECT client.client_id, client.parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $tmp["default_group"]); if(!$tmp || $tmp_client["parent_client_id"] != $res_client["client_id"]) { @@ -146,13 +146,13 @@ if(count($_POST) > 0) { if ($loginAs){ $sql = "SELECT * FROM sys_user WHERE USERNAME = ? and PASSWORT = ?"; - $user = $app->db->queryOneRecord($sql, $username, $password); + $user = $app->db->queryOneRecord($sql, (string)$username, (string)$password); } else { if(stristr($username, '@')) { //* mailuser login $sql = "SELECT * FROM mail_user WHERE login = ? or email = ?"; - $mailuser = $app->db->queryOneRecord($sql, $username, $app->functions->idn_encode($username)); + $mailuser = $app->db->queryOneRecord($sql, (string)$username, $app->functions->idn_encode($username)); $user = false; if($mailuser) { $saved_password = stripslashes($mailuser['password']); @@ -184,7 +184,7 @@ if(count($_POST) > 0) { } else { //* normal cp user login $sql = "SELECT * FROM sys_user WHERE USERNAME = ?"; - $user = $app->db->queryOneRecord($sql, $username); + $user = $app->db->queryOneRecord($sql, (string)$username); if($user) { $saved_password = stripslashes($user['passwort']); if(substr($saved_password, 0, 1) == '$') { @@ -199,7 +199,7 @@ if(count($_POST) > 0) { } else { // update password with secure algo $sql = 'UPDATE `sys_user` SET `passwort` = ? WHERE `username` = ?'; - $app->db->query($sql, $app->auth->crypt_password($password), $username); + $app->db->query($sql, $app->auth->crypt_password($password), (string)$username); } } } else { diff --git a/server/lib/classes/system.inc.php b/server/lib/classes/system.inc.php index 9c202542e8..37418149ae 100644 --- a/server/lib/classes/system.inc.php +++ b/server/lib/classes/system.inc.php @@ -1371,6 +1371,7 @@ class system{ * Control services to restart etc * */ + /* function daemon_init($daemon, $action){ //* $action = start|stop|restart|reload global $app; @@ -1409,7 +1410,7 @@ class system{ } } } - } + } */ function netmask($netmask){ list($f1, $f2, $f3, $f4) = explode('.', trim($netmask)); @@ -2064,36 +2065,103 @@ class system{ } function _getinitcommand($servicename, $action, $init_script_directory = '', $check_service) { - global $conf; + global $conf, $app; + // upstart + /* removed upstart support - deprecated if(is_executable('/sbin/initctl')){ exec('/sbin/initctl version 2>/dev/null | /bin/grep -q upstart', $retval['output'], $retval['retval']); if(intval($retval['retval']) == 0) return 'service '.$servicename.' '.$action; } + */ + + if(!in_array($action,array('restart','reload','force-reload'))) { + $app->log('Invalid init command action '.$action,LOGLEVEL_WARN); + return false; + } - // systemd + //* systemd (now default in all supported OS) if(is_executable('/bin/systemd') || is_executable('/usr/bin/systemctl')){ - if ($check_service) { - $this->exec_safe("systemctl is-enabled ? 2>&1", $servicename); - $ret_val = $this->last_exec_retcode(); - } - if ($ret_val == 0 || !$check_service) { - return 'systemctl '.$action.' '.$servicename.'.service'; + $app->log('Trying to use Systemd to restart service',LOGLEVEL_DEBUG); + + //* Test service name via regex + if(preg_match('/[a-zA-Z0-9\.\-\_]/',$servicename)) { + + //* Test if systemd service is enabled + if ($check_service) { + $this->exec_safe("systemctl is-enabled ? 2>&1", $servicename); + $ret_val = $this->last_exec_retcode(); + } else { + $app->log('Systemd service '.$servicename.' not found or not enabled.',LOGLEVEL_DEBUG); + } + + //* Return service command + if ($ret_val == 0 || !$check_service) { + return 'systemctl '.$action.' '.$servicename.'.service'; + } else { + $app->log('Failed to use Systemd to restart service '.$servicename.', we try init script instead.',LOGLEVEL_DEBUG); + } + } else { + $app->log('Systemd service name contains invalid chars: '.$servicename,LOGLEVEL_DEBUG); } + } else { + $app->log('Not using Systemd to restart services',LOGLEVEL_DEBUG); } - // sysvinit + //* sysvinit fallback + $app->log('Using init script to restart service',LOGLEVEL_DEBUG); + + //* Get init script directory if($init_script_directory == '') $init_script_directory = $conf['init_scripts']; if(substr($init_script_directory, -1) === '/') $init_script_directory = substr($init_script_directory, 0, -1); - if($check_service && is_executable($init_script_directory.'/'.$servicename)) { - return $init_script_directory.'/'.$servicename.' '.$action; + $init_script_directory = realpath($init_script_directory); + + //* Check init script dir + if(!is_dir($init_script_directory)) { + $app->log('Init script directory '.$init_script_directory.' not found',LOGLEVEL_WARN); + return false; + } + + //* Forbidden init script paths + if(substr($init_script_directory,0,4) == '/var' || substr($init_script_directory,0,4) == '/tmp') { + $app->log('Do not put init scripts in /var or /tmp folder.',LOGLEVEL_WARN); + return false; + } + + //* Check init script dir owner + if(fileowner($init_script_directory) !== 0) { + $app->log('Init script directory '.$init_script_directory.' not owned by root user',LOGLEVEL_WARN); + return false; + } + + $full_init_script_path = realpath($init_script_directory.'/'.$servicename); + + if($full_init_script_path == '') { + $app->log('No init script, we quit here.',LOGLEVEL_WARN); + return false; + } + + //* Check init script + if(!is_file($full_init_script_path)) { + $app->log('Init script '.$full_init_script_path.' not found',LOGLEVEL_WARN); + return false; + } + + //* Check init script owner + if(fileowner($full_init_script_path) !== 0) { + $app->log('Init script '.$full_init_script_path.' not owned by root user',LOGLEVEL_WARN); + return false; + } + + if($check_service && is_executable($full_init_script_path)) { + return $full_init_script_path.' '.$action; } if (!$check_service) { - return $init_script_directory.'/'.$servicename.' '.$action; + return $full_init_script_path.' '.$action; } } - function getinitcommand($servicename, $action, $init_script_directory = '', $check_service=false) { + function getinitcommand($servicename, $action, $init_script_directory = '', $check_service=true) { if (is_array($servicename)) { foreach($servicename as $service) { $out = $this->_getinitcommand($service, $action, $init_script_directory, true); diff --git a/server/mods-available/web_module.inc.php b/server/mods-available/web_module.inc.php index 6019100ed7..bb2de0d1de 100644 --- a/server/mods-available/web_module.inc.php +++ b/server/mods-available/web_module.inc.php @@ -242,15 +242,20 @@ class web_module { return $retval; } } - - exec($cmd.' 2>&1', $retval['output'], $retval['retval']); + + $app->log("Restarting httpd: $cmd", LOGLEVEL_DEBUG); + + if($cmd != '') { + exec($cmd.' 2>&1', $retval['output'], $retval['retval']); + } else { + $app->log('We got no init command, restart or reload of service aborted.',LOGLEVEL_WARN); + } // if restart failed despite successful syntax check => try again if($web_config['server_type'] == 'nginx' && $retval['retval'] > 0){ sleep(2); exec($cmd.' 2>&1', $retval['output'], $retval['retval']); } - $app->log("Restarting httpd: $cmd", LOGLEVEL_DEBUG); // nginx: do a syntax check because on some distributions, the init script always returns 0 - even if the syntax is not ok (how stupid is that?) //if($web_config['server_type'] == 'nginx' && $retval['retval'] == 0){ @@ -307,10 +312,16 @@ class web_module { } */ } - - $retval = array('output' => '', 'retval' => 0); - exec($initcommand.' 2>&1', $retval['output'], $retval['retval']); + $app->log("Restarting php-fpm: $initcommand", LOGLEVEL_DEBUG); + + if($initcommand != '') { + $retval = array('output' => '', 'retval' => 0); + exec($initcommand.' 2>&1', $retval['output'], $retval['retval']); + } else { + $app->log('We got no init command, restart or reload of php-fpm service aborted.',LOGLEVEL_WARN); + } + return $retval; } -- GitLab From cfe9bd3fb2b8a9ee33ca25c82b764607a4e75ac2 Mon Sep 17 00:00:00 2001 From: Till Brehm Date: Tue, 19 Oct 2021 15:39:22 +0200 Subject: [PATCH 3/4] Changed lockout conditions. --- interface/lib/classes/remoting.inc.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/lib/classes/remoting.inc.php b/interface/lib/classes/remoting.inc.php index 20181102ae..80e30bf849 100644 --- a/interface/lib/classes/remoting.inc.php +++ b/interface/lib/classes/remoting.inc.php @@ -91,7 +91,7 @@ class remoting { $sql = "SELECT * FROM `attempts_login` WHERE `ip`= ? AND `login_time` > (NOW() - INTERVAL 5 MINUTE) LIMIT 1"; $alreadyfailed = $app->db->queryOneRecord($sql, $ip_md5); - if($alreadyfailed['times'] > 10) { + if($alreadyfailed['times'] >= 10) { throw new SoapFault('login_failure_limit', 'The login failure limit has been reached.'); return false; } @@ -121,7 +121,7 @@ class remoting { $app->db->query($sql, $ip_md5); } elseif($alreadyfailed['times'] >= 1) { //* update times wrong - $sql = "UPDATE `attempts_login` SET `times`=`times`+1, `login_time`=NOW() WHERE `ip` = ? AND `login_time` < NOW() ORDER BY `login_time` DESC LIMIT 1"; + $sql = "UPDATE `attempts_login` SET `times`=`times`+1, `login_time`=NOW() WHERE `ip` = ? ORDER BY `login_time` DESC LIMIT 1"; $app->db->query($sql, $ip_md5); } throw new SoapFault('client_login_failed', 'The login failed. Username or password wrong.'); @@ -233,7 +233,7 @@ class remoting { $app->db->query($sql, $ip_md5); } elseif($alreadyfailed['times'] >= 1) { //* update times wrong - $sql = "UPDATE `attempts_login` SET `times`=`times`+1, `login_time`=NOW() WHERE `ip` = ? AND `login_time` < NOW() ORDER BY `login_time` DESC LIMIT 1"; + $sql = "UPDATE `attempts_login` SET `times`=`times`+1, `login_time`=NOW() WHERE `ip` = ? ORDER BY `login_time` DESC LIMIT 1"; $app->db->query($sql, $ip_md5); } @@ -575,7 +575,7 @@ class remoting { $sql = "SELECT * FROM `attempts_login` WHERE `ip`= ? AND `login_time` > (NOW() - INTERVAL 5 MINUTE) LIMIT 1"; $alreadyfailed = $app->db->queryOneRecord($sql, $ip_md5); - if($alreadyfailed['times'] > 10) { + if($alreadyfailed['times'] >= 10) { throw new SoapFault('session_failure_limit', 'The Session failure limit has been reached.'); return false; } @@ -591,7 +591,7 @@ class remoting { $app->db->query($sql, $ip_md5); } elseif($alreadyfailed['times'] >= 1) { //* update times wrong - $sql = "UPDATE `attempts_login` SET `times`=`times`+1, `login_time`=NOW() WHERE `ip` = ? AND `login_time` < NOW() ORDER BY `login_time` DESC LIMIT 1"; + $sql = "UPDATE `attempts_login` SET `times`=`times`+1, `login_time`=NOW() WHERE `ip` = ? ORDER BY `login_time` DESC LIMIT 1"; $app->db->query($sql, $ip_md5); } -- GitLab From 99b8b423453979ea97849889ad209670ce9d730b Mon Sep 17 00:00:00 2001 From: Marius Burkard Date: Wed, 20 Oct 2021 10:35:53 +0200 Subject: [PATCH 4/4] - hide mail whilelist / blacklist from menu of client when limit is 0 --- interface/web/mail/lib/module.conf.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/web/mail/lib/module.conf.php b/interface/web/mail/lib/module.conf.php index fbe8ffbcb5..05910e6c46 100644 --- a/interface/web/mail/lib/module.conf.php +++ b/interface/web/mail/lib/module.conf.php @@ -61,7 +61,7 @@ if($app->auth->get_client_limit($userid, 'mailcatchall') != 0) 'html_id' => 'mail_domain_catchall_list'); } -if(! $app->auth->is_admin()) +if(! $app->auth->is_admin() && $app->auth->get_client_limit($userid, 'mail_wblist') != 0) { $items[] = array( 'title' => 'Email Whitelist', 'target' => 'content', -- GitLab