From dfc3dcb4c631e00d7603cd3b78ef49d9df064d3b Mon Sep 17 00:00:00 2001 From: Roland Gruber Date: Wed, 30 May 2018 19:43:44 +0200 Subject: [PATCH] limit server side filtering to known attributes --- lam/lib/lists.inc | 49 ++++++++++++++++++++++++++++++----- lam/lib/types/asteriskExt.inc | 11 ++++---- lam/lib/types/group.inc | 13 +++++----- lam/lib/types/user.inc | 43 ++++++++++++++++-------------- 4 files changed, 78 insertions(+), 38 deletions(-) diff --git a/lam/lib/lists.inc b/lam/lib/lists.inc index 8f53f459..dfe40f7d 100644 --- a/lam/lib/lists.inc +++ b/lam/lib/lists.inc @@ -74,9 +74,12 @@ class lamList { /** refresh page switch */ protected $refresh = true; - /** LDAP entries */ + /** entries to show */ protected $entries; + /** entries from LDAP */ + protected $ldapEntries; + /** sort mapping for entries array(original index => sorted index) */ protected $sortMapping; @@ -95,12 +98,20 @@ class lamList { /** tabindex for GUI elements */ protected $tabindex = 1; + /** defines if the server side filter changed */ + protected $serverSideFilterChanged; + /** ID for list size config option */ const LIST_SIZE_OPTION_NAME = "L_SIZE"; /** prefix for virtual (non-LDAP) attributes */ const VIRTUAL_ATTRIBUTE_PREFIX = 'lam_virtual_'; + const SERVER_SIDE_FILTER_ATTRIBUTES = array( + 'cn', 'uid', 'memberuid', 'description', + 'sn', 'surname', 'gn', 'givenname' + ); + /** * Constructor * @@ -151,6 +162,8 @@ class lamList { $this->tabindex = 1; // do POST actions $postFragment = $this->listDoPost(); + // update filter + $this->listBuildFilter(); // get some parameters $this->listGetParams(); // print HTML head @@ -159,7 +172,6 @@ class lamList { $this->listPrintRedirectMessages(); // refresh data if needed if ($this->refresh) { - $this->listBuildFilter(); $this->listRefreshData(); } // sort rows by sort column @@ -210,7 +222,8 @@ class lamList { if (isset($_GET['accountEditBack'])) { return; } - $filter = array(); + $oldFilter = $this->filters; + $this->serverSideFilterChanged = false; $this->filters = array(); if (!isset($_POST['clear_filter'])) { // build filter array @@ -232,6 +245,17 @@ class lamList { } } } + $filterAttrs = array_merge(array_keys($oldFilter), array_keys($this->filters)); + $filterAttrs = array_unique($filterAttrs); + foreach ($filterAttrs as $attrName) { + if (!$this->isAttributeFilteredByServer($attrName)) { + continue; + } + if (!isset($oldFilter[$attrName]) || !isset($this->filters[$attrName]) || ($oldFilter[$attrName] != $this->filters[$attrName])) { + $this->serverSideFilterChanged = true; + break; + } + } } /** @@ -931,10 +955,17 @@ class lamList { } // check if LDAP data should be refreshed $this->refresh = true; - if (isset($_GET['norefresh'])) $this->refresh = false; - if (isset($_POST['refresh']) || isset($_POST['apply_filter']) || isset($_POST['clear_filter'])) { + if (isset($_GET['norefresh'])) { + $this->refresh = false; + } + if (isset($_POST['refresh'])) { $this->refresh = true; } + if (isset($_POST['apply_filter']) || isset($_POST['clear_filter'])) { + if ($this->serverSideFilterChanged) { + $this->refresh = true; + } + } } /** @@ -963,7 +994,11 @@ class lamList { $attrs[] = $additionalAttrs[$i]; } } - $this->entries = searchLDAP($this->suffix, $filter, $attrs); + $this->ldapEntries = searchLDAP($this->suffix, $filter, $attrs); + $this->entries = array(); + foreach ($this->ldapEntries as $index => &$attrs) { + $this->entries[$index] = &$attrs; + } $lastError = getLastLDAPError(); if ($lastError != null) { call_user_func_array('StatusMessage', $lastError); @@ -995,7 +1030,7 @@ class lamList { * @return bool filter server side */ protected function isAttributeFilteredByServer($attrName) { - return true; + return in_array(strtolower($attrName), lamList::SERVER_SIDE_FILTER_ATTRIBUTES); } /** diff --git a/lam/lib/types/asteriskExt.inc b/lam/lib/types/asteriskExt.inc index 2d5a4407..14ac145e 100644 --- a/lam/lib/types/asteriskExt.inc +++ b/lam/lib/types/asteriskExt.inc @@ -1,11 +1,10 @@ type->getId()); // basic filter is provided by modules $filter = "(&" . $module_filter . $this->buildLDAPAttributeFilter() . ")"; @@ -179,8 +177,11 @@ class lamAsteriskExtList extends lamList { call_user_func_array('StatusMessage', $lastError); } - $entries = $this->normalizeLdapOutput($entries); - $this->entries = $entries; + $this->ldapEntries = $this->normalizeLdapOutput($entries); + $this->entries = array(); + foreach ($this->ldapEntries as $index => &$attrs) { + $this->entries[$index] = &$attrs; + } // generate list of possible suffixes $this->possibleSuffixes = $this->type->getSuffixList(); } diff --git a/lam/lib/types/group.inc b/lam/lib/types/group.inc index 2997e036..03fb000f 100644 --- a/lam/lib/types/group.inc +++ b/lam/lib/types/group.inc @@ -1,10 +1,9 @@ refresh_primary = false; // return unless some entries - if (sizeof($this->entries) <= 0) return; + if (sizeof($this->ldapEntries) <= 0) { + return; + } $scope = "user"; // configure search filter $module_filter = get_ldap_filter($scope); // basic filter is provided by modules $attrs = array( "uid" ); - for ($i = 0; $i < sizeof($this->entries); $i++) { - if (empty($this->entries[$i]['gidnumber'][0])) { + for ($i = 0; $i < sizeof($this->ldapEntries); $i++) { + if (empty($this->ldapEntries[$i]['gidnumber'][0])) { continue; } - $gid = $this->entries[$i]['gidnumber'][0]; + $gid = $this->ldapEntries[$i]['gidnumber'][0]; $filter = "(&(&" . $module_filter . ")(gidNumber=" . $gid . "))"; $entries = searchLDAPByFilter($filter, $attrs, array($scope)); for ($j = 0; $j < sizeof($entries); $j++) { diff --git a/lam/lib/types/user.inc b/lam/lib/types/user.inc index 337af79b..fb02cd96 100644 --- a/lam/lib/types/user.inc +++ b/lam/lib/types/user.inc @@ -930,7 +930,10 @@ class lamUserList extends lamList { */ protected function isAttributeFilteredByServer($attrName) { // do not filter status server side - return $attrName != self::ATTR_ACCOUNT_STATUS; + if ($attrName == self::ATTR_ACCOUNT_STATUS) { + return false; + } + return parent::isAttributeFilteredByServer($attrName); } /** @@ -966,20 +969,20 @@ class lamUserList extends lamList { * Injects values for the virtual account status attribute to make it sortable. */ private function injectAccountStatusAttributeAndFilterByStatus() { - $entryCount = sizeof($this->entries); + $entryCount = sizeof($this->ldapEntries); for ($i = 0; $i < $entryCount; $i++) { - $unixAvailable = self::isUnixAvailable($this->entries[$i]); - $sambaAvailable = self::isSambaAvailable($this->entries[$i]); - $ppolicyAvailable = $this->isPPolicyAvailable($this->entries[$i]); - $windowsAvailable = self::isWindowsAvailable($this->entries[$i]); - $unixLocked = self::isUnixLocked($this->entries[$i]); - $sambaLocked = self::isSambaLocked($this->entries[$i]); - $ppolicyLocked = self::isPPolicyLocked($this->entries[$i]); - $windowsLocked = self::isWindowsLocked($this->entries[$i]); - $windowsPasswordLocked = ($this->getWindowsPasswordLockedTime($this->entries[$i]) != null); - $is389dsLocked = self::is389dsLocked($this->entries[$i]); - $is389dsDeactivated = self::is389dsDeactivated($this->entries[$i]); - $is389dsPwdExpired = self::is389dsPwdExpired($this->entries[$i]); + $unixAvailable = self::isUnixAvailable($this->ldapEntries[$i]); + $sambaAvailable = self::isSambaAvailable($this->ldapEntries[$i]); + $ppolicyAvailable = $this->isPPolicyAvailable($this->ldapEntries[$i]); + $windowsAvailable = self::isWindowsAvailable($this->ldapEntries[$i]); + $unixLocked = self::isUnixLocked($this->ldapEntries[$i]); + $sambaLocked = self::isSambaLocked($this->ldapEntries[$i]); + $ppolicyLocked = self::isPPolicyLocked($this->ldapEntries[$i]); + $windowsLocked = self::isWindowsLocked($this->ldapEntries[$i]); + $windowsPasswordLocked = ($this->getWindowsPasswordLockedTime($this->ldapEntries[$i]) != null); + $is389dsLocked = self::is389dsLocked($this->ldapEntries[$i]); + $is389dsDeactivated = self::is389dsDeactivated($this->ldapEntries[$i]); + $is389dsPwdExpired = self::is389dsPwdExpired($this->ldapEntries[$i]); $hasLocked = ($unixAvailable && $unixLocked) || ($sambaAvailable && $sambaLocked) || ($ppolicyAvailable && $ppolicyLocked) @@ -990,9 +993,9 @@ class lamUserList extends lamList { || ($sambaAvailable && !$sambaLocked) || ($ppolicyAvailable && !$ppolicyLocked) || ($windowsAvailable && !$windowsLocked); - $shadowExpired = shadowAccount::isAccountExpired($this->entries[$i]); - $shadowPasswordExpired = shadowAccount::isPasswordExpired($this->entries[$i]); - $windowsExpired = windowsUser::isAccountExpired($this->entries[$i]); + $shadowExpired = shadowAccount::isAccountExpired($this->ldapEntries[$i]); + $shadowPasswordExpired = shadowAccount::isPasswordExpired($this->ldapEntries[$i]); + $windowsExpired = windowsUser::isAccountExpired($this->ldapEntries[$i]); $expired = $shadowExpired || $shadowPasswordExpired || $windowsExpired; $status = self::FILTER_UNLOCKED; if ($expired) { @@ -1007,14 +1010,14 @@ class lamUserList extends lamList { // filter accounts if (!empty($this->accountStatusFilter)) { if ($status != $this->accountStatusFilter) { - unset($this->entries[$i]); + unset($this->ldapEntries[$i]); continue; } } // add virtual attribute - $this->entries[$i][self::ATTR_ACCOUNT_STATUS][0] = $status; + $this->ldapEntries[$i][self::ATTR_ACCOUNT_STATUS][0] = $status; } - $this->entries = array_values($this->entries); + $this->ldapEntries = array_values($this->ldapEntries); } /**