From 860869796a53fe7ca9dcfa3eeb991831905d4df4 Mon Sep 17 00:00:00 2001 From: JediKev Date: Wed, 10 Apr 2019 17:07:24 -0500 Subject: [PATCH] feature: ACL (Access Control List) This adds a new feature called ACL that offers the ability to control what IP addresses are allowed to access the Login Page(s). This adds a new textfield to the System Settings to add a comma separated list of IPs. This also adds a checkbox called "Apply To Backend Only" that, if enabled, will only apply the ACL to the Agent Login Page. Lastly, this adds a validator for a simple comma-separated list of IP addresses. (eg. `111.111.111.111, 222.222.222.222, 333.333.333.333`) If the requester's IP is not in the ACL the system will show an "Access Denied" page. If the requester's IP is in the ACL they will be able to access the Login Page(s) as usual. If the ACL field is left blank anyone will be able to access the User/Agent Login Pages. --- include/class.config.php | 14 ++++++++++++++ include/class.validator.php | 10 ++++++++++ include/i18n/en_US/help/tips/settings.system.yaml | 9 +++++++++ include/staff/settings-system.inc.php | 13 +++++++++++++ login.php | 12 ++++++++++++ scp/login.php | 10 ++++++++++ 6 files changed, 68 insertions(+) diff --git a/include/class.config.php b/include/class.config.php index 7fc9715b81..04f4653aaf 100644 --- a/include/class.config.php +++ b/include/class.config.php @@ -424,6 +424,17 @@ function getAllowIframes() { return str_replace(array(', ', ','), array(' ', ' '), $this->get('allow_iframes')) ?: 'self'; } + function getACL() { + if (!($acl = $this->get('acl'))) + return null; + + return explode(',', str_replace(' ', '', $acl)); + } + + function isACLBackendOnly() { + return $this->get('acl_backend') ?: 0; + } + function isAvatarsEnabled() { return $this->get('enable_avatars'); } @@ -1125,6 +1136,7 @@ function updateSystemSettings($vars, &$errors) { $f['default_dept_id']=array('type'=>'int', 'required'=>1, 'error'=>__('Default Department is required')); $f['autolock_minutes']=array('type'=>'int', 'required'=>1, 'error'=>__('Enter lock time in minutes')); $f['allow_iframes']=array('type'=>'cs-domain', 'required'=>0, 'error'=>__('Enter comma separated list of domains')); + $f['acl']=array('type'=>'ipaddr', 'required'=>0, 'error'=>__('Enter comma separated list of IP addresses')); //Date & Time Options $f['time_format']=array('type'=>'string', 'required'=>1, 'error'=>__('Time format is required')); $f['date_format']=array('type'=>'string', 'required'=>1, 'error'=>__('Date format is required')); @@ -1184,6 +1196,8 @@ function updateSystemSettings($vars, &$errors) { 'enable_richtext' => isset($vars['enable_richtext']) ? 1 : 0, 'files_req_auth' => isset($vars['files_req_auth']) ? 1 : 0, 'allow_iframes' => Format::sanitize($vars['allow_iframes']), + 'acl' => Format::sanitize($vars['acl']), + 'acl_backend' => isset($vars['acl_backend']) ? 1 : 0, )); } diff --git a/include/class.validator.php b/include/class.validator.php index 583b25b65c..20661ac390 100644 --- a/include/class.validator.php +++ b/include/class.validator.php @@ -307,5 +307,15 @@ function process($fields,$vars,&$errors){ return (!$errors); } + + function check_acl($ip, $acl) { + if (!$ip || !$acl) + return false; + + if (!in_array($ip, $acl)) + return false; + + return true; + } } ?> diff --git a/include/i18n/en_US/help/tips/settings.system.yaml b/include/i18n/en_US/help/tips/settings.system.yaml index 3b972da6d4..97adb3a7fd 100644 --- a/include/i18n/en_US/help/tips/settings.system.yaml +++ b/include/i18n/en_US/help/tips/settings.system.yaml @@ -106,6 +106,15 @@ allow_iframes: - title: Syntax Information (host-source) href: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors#Sources" +acl: + title: ACL (Access Control List) + content: > + Enter a comma separated list of IP addresses to allow access to the system. + If left empty, anyone will be able to access the system with the appropriate + credentials. If "Apply To Backend Only" is checked the system will apply the + ACL to Agent/Admin Panels only. If left unchecked however, it will apply + to the User Portal and Agent/Admin Panels. + # Date and time options date_time_options: title: Date & Time Options diff --git a/include/staff/settings-system.inc.php b/include/staff/settings-system.inc.php index 37370df97e..610f84706e 100644 --- a/include/staff/settings-system.inc.php +++ b/include/staff/settings-system.inc.php @@ -138,6 +138,19 @@ + + : + +    + + + +   diff --git a/login.php b/login.php index 5c4a713124..7ef7e8cbb2 100644 --- a/login.php +++ b/login.php @@ -21,6 +21,18 @@ define('CLIENTINC_DIR',INCLUDE_DIR.'client/'); define('OSTCLIENTINC',TRUE); //make includes happy +// Enforce ACL (if applicable) +if (!$cfg->isACLBackendOnly() + && ($acl = $cfg->getACL()) + && !empty($acl)) { + $ip = osTicket::get_client_ip(); + if (!$ip) + die('No Valid IP Address'); + + if (!Validator::check_acl($ip, $acl)) + die('Access Denied'); +} + require_once(INCLUDE_DIR.'class.client.php'); require_once(INCLUDE_DIR.'class.ticket.php'); diff --git a/scp/login.php b/scp/login.php index 4853f7e31f..95eaa3da4e 100644 --- a/scp/login.php +++ b/scp/login.php @@ -20,6 +20,16 @@ // system or browser default TextDomain::configureForUser(); +// Enforce ACL (if applicable) +if (($acl = $cfg->getACL()) && !empty($acl)) { + $ip = osTicket::get_client_ip(); + if (!$ip) + die('No Valid IP Address'); + + if (!Validator::check_acl($ip, $acl)) + die('Access Denied'); +} + require_once(INCLUDE_DIR.'class.staff.php'); require_once(INCLUDE_DIR.'class.csrf.php');