Skip to content

Commit 437360f

Browse files
committed
Added admin IP whitelist feature.
1 parent d48b2bb commit 437360f

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

interface/lib/config.inc.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,7 @@
159159
define('LOGLEVEL_WARN', 1);
160160
define('LOGLEVEL_ERROR', 2);
161161

162+
//** Admin IP whitelist file
163+
$conf['admin_ip_whitelist_file'] = '/etc/ispconfig_admin_ip_whitelist';
164+
162165
?>

interface/web/login/index.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,14 @@ function process_login_request(app $app, &$error, $conf, $module)
106106
// Maintenance mode - allow logins only when maintenance mode is off or if the user is admin
107107
if ($app->is_under_maintenance() && $user['typ'] != 'admin') return;
108108

109+
if ($user['typ'] == 'admin' && !is_admin_ip_whitelisted($_SERVER['REMOTE_ADDR'], $conf)) {
110+
// TODO: if it's not a security risk (information disclosure) to
111+
// let the user know they are not whitelisted, then change this
112+
// error message to a more appropriate one
113+
$error = $app->lng('error_user_password_incorrect');
114+
return;
115+
}
116+
109117
// User login right, so attempts can be deleted
110118
$sql = "DELETE FROM `attempts_login` WHERE `ip`=?";
111119
$app->db->query($sql, $ip);
@@ -189,6 +197,54 @@ function process_login_request(app $app, &$error, $conf, $module)
189197
}
190198
}
191199

200+
/**
201+
* Checks if the given admin's IP address is whitelisted.
202+
* @param string $ip
203+
* @return bool
204+
*/
205+
function is_admin_ip_whitelisted($ip, $conf)
206+
{
207+
// if there is no config value, we assume that webmaster doesn't use this feature
208+
if (!isset($conf['admin_ip_whitelist_file'])) return true;
209+
210+
// if the file doesn't exist, we assume that webmaster doesn't use this feature
211+
if (!file_exists($conf['admin_ip_whitelist_file'])) return true;
212+
213+
$file_content = file_get_contents($conf['admin_ip_whitelist_file']);
214+
$file_lines = explode("\n", $file_content);
215+
216+
$matches = array_filter($file_lines, function($v) use ($ip) {
217+
$line = trim($v);
218+
219+
// exclude empty lines and comments
220+
if ($line === '' || $line[0] === '#') return false;
221+
222+
return ip_matches_cidr($ip, $line);
223+
});
224+
225+
return count($matches) > 0;
226+
}
227+
228+
// based on https://www.php.net/manual/en/ref.network.php (comments)
229+
/**
230+
* Checks if the given IP address matches the given CIDR.
231+
* @param $ip
232+
* @param $cidr
233+
234+
* @return bool
235+
*/
236+
function ip_matches_cidr ($ip, $cidr) {
237+
list ($net, $mask) = explode ('/', $cidr);
238+
if (!$mask) $mask = 32;
239+
240+
$ip_net = ip2long ($net);
241+
$ip_mask = ~((1 << (32 - $mask)) - 1);
242+
243+
$ip_ip = ip2long ($ip);
244+
245+
return (($ip_ip & $ip_mask) == ($ip_net & $ip_mask));
246+
}
247+
192248
/**
193249
* Validates user credentials and fetches the user if validation succeeded
194250
* @param app $app

0 commit comments

Comments
 (0)