diff --git a/lam/HISTORY b/lam/HISTORY
index e72db953..aa8daf2b 100644
--- a/lam/HISTORY
+++ b/lam/HISTORY
@@ -1,4 +1,5 @@
December 2014 4.8
+ - Active Directory: support paged result as workaround for size limit exceeded
- FreeRadius: support dialupAccess and radiusProfileDn
- Usability improvements
- LAM Pro:
diff --git a/lam/docs/manual-sources/howto.xml b/lam/docs/manual-sources/howto.xml
index b4310dce..15aabfd6 100644
--- a/lam/docs/manual-sources/howto.xml
+++ b/lam/docs/manual-sources/howto.xml
@@ -1291,10 +1291,16 @@ Have fun!
linkend="a_accessLevelPasswordReset">this page for details on
the different access levels.
+ Advanced options
+
By default LAM will not follow LDAP referrals. This is ok for
most installations. If you use LDAP referrals please activate the
referral option in advanced settings.
+ Paged results should be activated only if you encounter any
+ problems regarding size limits on Active Directory. LAM will then
+ query LDAP to return results in chunks of 999 entries.
+
diff --git a/lam/docs/manual-sources/images/configProfiles4.png b/lam/docs/manual-sources/images/configProfiles4.png
index a1adea61..9b0c8ceb 100644
Binary files a/lam/docs/manual-sources/images/configProfiles4.png and b/lam/docs/manual-sources/images/configProfiles4.png differ
diff --git a/lam/docs/manual-sources/images/lamdaemonServers.png b/lam/docs/manual-sources/images/lamdaemonServers.png
new file mode 100644
index 00000000..c0ace848
Binary files /dev/null and b/lam/docs/manual-sources/images/lamdaemonServers.png differ
diff --git a/lam/help/help.inc b/lam/help/help.inc
index 83cb7ab0..5f6f7810 100644
--- a/lam/help/help.inc
+++ b/lam/help/help.inc
@@ -181,6 +181,8 @@ $helpArray = array (
"Text" => _('Here you can overwrite the display name for this account type.')),
"265" => array ("Headline" => _('Read-only'),
"Text" => _('Sets this account type to read-only.')),
+ "266" => array ("Headline" => _("Paged results"),
+ "Text" => _("This is a workaround for Active Directory. Enable it if you get messages about size limit exceeded.")),
// 300 - 399
// profile editor, file upload
"301" => array ("Headline" => _("RDN identifier"),
diff --git a/lam/lib/account.inc b/lam/lib/account.inc
index 3d1df2a3..5b2430a6 100644
--- a/lam/lib/account.inc
+++ b/lam/lib/account.inc
@@ -668,19 +668,12 @@ function searchLDAPByAttribute($name, $value, $objectClass, $attributes, $scopes
continue; // skip non-active account types
}
// search LDAP
- $sr = @ldap_search($_SESSION['ldap']->server(), escapeDN($_SESSION['config']->get_Suffix($scopes[$s])),
- $filter, $attributes, 0, $_SESSION['config']->get_searchLimit(), 0, LDAP_DEREF_NEVER);
+ $entries = searchLDAPPaged($_SESSION['ldap']->server(), escapeDN($_SESSION['config']->get_Suffix($scopes[$s])),
+ $filter, $attributes, 0, $_SESSION['config']->get_searchLimit());
if (ldap_errno($_SESSION['ldap']->server()) == 4) {
logNewMessage(LOG_WARNING, 'LDAP size limit exeeded. Please increase the limit on your server.');
}
- if ($sr) {
- $entries = ldap_get_entries($_SESSION['ldap']->server(), $sr);
- if ($entries) {
- cleanLDAPResult($entries);
- $return = array_merge($return, $entries);
- }
- @ldap_free_result($sr);
- }
+ $return = array_merge($return, $entries);
}
return $return;
}
@@ -702,19 +695,12 @@ function searchLDAPByFilter($filter, $attributes, $scopes, $attrsOnly = false) {
}
for ($s = 0; $s < sizeof($scopes); $s++) {
// search LDAP
- $sr = @ldap_search($_SESSION['ldap']->server(), escapeDN($_SESSION['config']->get_Suffix($scopes[$s])),
- $filter, $attributes, $readAttributesOnly, $_SESSION['config']->get_searchLimit(), 0, LDAP_DEREF_NEVER);
+ $entries = searchLDAPPaged($_SESSION['ldap']->server(), escapeDN($_SESSION['config']->get_Suffix($scopes[$s])),
+ $filter, $attributes, $readAttributesOnly, $_SESSION['config']->get_searchLimit());
if (ldap_errno($_SESSION['ldap']->server()) == 4) {
logNewMessage(LOG_WARNING, 'LDAP size limit exeeded. Please increase the limit on your server.');
}
- if ($sr) {
- $entries = ldap_get_entries($_SESSION['ldap']->server(), $sr);
- if ($entries) {
- cleanLDAPResult($entries);
- $return = array_merge($return, $entries);
- }
- @ldap_free_result($sr);
- }
+ $return = array_merge($return, $entries);
}
return $return;
}
@@ -728,20 +714,56 @@ function searchLDAPByFilter($filter, $attributes, $scopes, $attrsOnly = false) {
* @return array list of found entries
*/
function searchLDAP($suffix, $filter, $attributes) {
- $return = array();
- $sr = @ldap_search($_SESSION['ldap']->server(), escapeDN($suffix), $filter, $attributes,
- 0, $_SESSION['config']->get_searchLimit(), 0, LDAP_DEREF_NEVER);
+ $return = searchLDAPPaged($_SESSION['ldap']->server(), escapeDN($suffix), $filter, $attributes,
+ 0, $_SESSION['config']->get_searchLimit());
if (ldap_errno($_SESSION['ldap']->server()) == 4) {
logNewMessage(LOG_WARNING, 'LDAP size limit exeeded. Please increase the limit on your server.');
}
- if ($sr) {
- $entries = ldap_get_entries($_SESSION['ldap']->server(), $sr);
- if ($entries) {
+ return $return;
+}
+
+/**
+ * Runs an LDAP search and uses paging if configured.
+ *
+ * @param handle $server LDAP connection handle
+ * @param String $dn DN
+ * @param String $filter filter
+ * @param array $attributes attribute list
+ * @param boolean $attrsOnly return only attribute names
+ * @param int $limit size limit
+ */
+function searchLDAPPaged($server, $dn, $filter, $attributes, $attrsOnly, $limit) {
+ if (empty($_SESSION['config']) || ($_SESSION['config']->getPagedResults() !== 'true')) {
+ $sr = @ldap_search($server, $dn, $filter, $attributes, $attrsOnly, $limit, 0, LDAP_DEREF_NEVER);
+ if ($sr) {
+ $entries = ldap_get_entries($server, $sr);
+ if (!$entries) {
+ return array();
+ }
cleanLDAPResult($entries);
- @ldap_free_result($sr);
return $entries;
}
+ else {
+ return array();
+ }
}
+ $pageSize = 999;
+ $cookie = '';
+ $return = array();
+ do {
+ @ldap_control_paged_result($server, $pageSize, true, $cookie);
+ $sr = @ldap_search($server, $dn, $filter, $attributes, $attrsOnly, $limit, 0, LDAP_DEREF_NEVER);
+ if (!$sr) {
+ break;
+ }
+ $entries = ldap_get_entries($server, $sr);
+ if (!$entries) {
+ break;
+ }
+ $return = array_merge($return, $entries);
+ @ldap_control_paged_result_response($server, $sr, $cookie);
+ } while($cookie !== null && $cookie != '');
+ cleanLDAPResult($return);
return $return;
}
diff --git a/lam/lib/config.inc b/lam/lib/config.inc
index 3e9570f6..5a798be6 100644
--- a/lam/lib/config.inc
+++ b/lam/lib/config.inc
@@ -362,6 +362,9 @@ class LAMConfig {
/** automatically follow referrals */
private $followReferrals = 'false';
+ /** use paged results */
+ private $pagedResults = 'false';
+
/** Array of string: users with admin rights */
private $Admins;
@@ -456,7 +459,7 @@ class LAMConfig {
private $lamProMailText = '';
/** List of all settings in config file */
- private $settings = array("ServerURL", "useTLS", "followReferrals", "Passwd", "Admins", "treesuffix",
+ private $settings = array("ServerURL", "useTLS", "followReferrals", 'pagedResults', "Passwd", "Admins", "treesuffix",
"defaultLanguage", "scriptPath", "scriptServer", "scriptRights", "cachetimeout",
"modules", "activeTypes", "types", "tools", "accessLevel", 'loginMethod', 'loginSearchSuffix',
'loginSearchFilter', 'searchLimit', 'lamProMailFrom', 'lamProMailReplyTo', 'lamProMailSubject',
@@ -625,6 +628,7 @@ class LAMConfig {
if (!in_array("ServerURL", $saved)) array_push($file_array, "\n\n# server address (e.g. ldap://localhost:389 or ldaps://localhost:636)\n" . "serverURL: " . $this->ServerURL . "\n");
if (!in_array("useTLS", $saved)) array_push($file_array, "\n\n# enable TLS encryption\n" . "useTLS: " . $this->useTLS . "\n");
if (!in_array("followReferrals", $saved)) array_push($file_array, "\n\n# follow referrals\n" . "followReferrals: " . $this->followReferrals . "\n");
+ if (!in_array("pagedResults", $saved)) array_push($file_array, "\n\n# paged results\n" . "pagedResults: " . $this->pagedResults . "\n");
if (!in_array("Passwd", $saved)) array_push($file_array, "\n\n# password to change these preferences via webfrontend\n" . "passwd: " . $this->Passwd . "\n");
if (!in_array("Admins", $saved)) array_push($file_array, "\n\n# list of users who are allowed to use LDAP Account Manager\n" .
"# names have to be seperated by semicolons\n" .
@@ -777,6 +781,24 @@ class LAMConfig {
$this->followReferrals = $followReferrals;
}
+ /**
+ * Returns if paged results should be used.
+ *
+ * @return String true or false
+ */
+ public function getPagedResults() {
+ return $this->pagedResults;
+ }
+
+ /**
+ * Sets if paged results should be used.
+ *
+ * @param String $pagedResults true or false
+ */
+ public function setPagedResults($pagedResults) {
+ $this->pagedResults = $pagedResults;
+ }
+
/**
* Returns an array of string with all admin names
*
diff --git a/lam/lib/types/group.inc b/lam/lib/types/group.inc
index f56f8689..b1041854 100644
--- a/lam/lib/types/group.inc
+++ b/lam/lib/types/group.inc
@@ -405,6 +405,9 @@ class lamGroupList extends lamList {
$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])) {
+ continue;
+ }
$gid = $this->entries[$i]['gidnumber'][0];
$filter = "(&(&" . $module_filter . ")(gidNumber=" . $gid . "))";
$entries = searchLDAPByFilter($filter, $attrs, array($scope));
diff --git a/lam/templates/config/confmain.php b/lam/templates/config/confmain.php
index b15d187c..40b151dd 100644
--- a/lam/templates/config/confmain.php
+++ b/lam/templates/config/confmain.php
@@ -270,7 +270,10 @@ if (isLAMProVersion()) {
$advancedOptionsContent = new htmlTable();
// referrals
$followReferrals = ($conf->getFollowReferrals() === 'true');
-$advancedOptionsContent->addElement(new htmlTableExtendedInputCheckbox('followReferrals',$followReferrals , _('Follow referrals'), '205'), true);
+$advancedOptionsContent->addElement(new htmlTableExtendedInputCheckbox('followReferrals', $followReferrals , _('Follow referrals'), '205'), true);
+// paged results
+$pagedResults = ($conf->getPagedResults() === 'true');
+$advancedOptionsContent->addElement(new htmlTableExtendedInputCheckbox('pagedResults', $pagedResults , _('Paged results'), '266'), true);
// build advanced options box
$advancedOptions = new htmlAccordion('advancedOptions_server', array(_('Advanced options') => $advancedOptionsContent), false);
@@ -509,6 +512,12 @@ function checkInput() {
else {
$conf->setFollowReferrals('false');
}
+ if (isset($_POST['pagedResults']) && ($_POST['pagedResults'] == 'on')) {
+ $conf->setPagedResults('true');
+ }
+ else {
+ $conf->setPagedResults('false');
+ }
/* if (!$conf->set_cacheTimeout($_POST['cachetimeout'])) {
$errors[] = array("ERROR", _("Cache timeout is invalid!"));
}*/