* LDAP/AD: automatic retry, if connection to LDAP server was lost

This commit is contained in:
ralf 2024-08-09 14:10:23 +02:00
parent 89d4155f23
commit bc582dedfb
2 changed files with 38 additions and 29 deletions

View File

@ -91,7 +91,7 @@ class Import
];
}
catch (\Exception $e) {
$this->logger('Error: '.$e->getMessage(), 'fatal');
$this->logger('Error: '.$e->getMessage().' ('.$e->getCode().')', 'fatal');
throw $e;
}
}
@ -273,7 +273,6 @@ class Import
$start = ['', 500, &$cookie]; // cookie must be a reference!
do
{
$contact = $reconnected = null;
foreach ($this->contacts->search('', false, '', ['account_lid', 'jpegphoto'], '', '', 'AND', $start, $filter) as $contact)
{
// if we have a regexp to filter the DN, continue on non-match
@ -580,15 +579,8 @@ class Import
// remember the users we imported, to be able to delete the ones we dont
unset($sql_users[$account_id]);
}
/* check if connection was somehow lost / timed out and reconnect
if ($initial_import && !isset($contact) && ldap_errno($this->contacts->ds) === -1)
{
$this->contacts->ds = $this->accounts->ldap_connection(true);
$reconnected = true;
$this->logger("Reconnected to LDAP server", 'info');
}*/
}
while ($reconnected || $start[2] !== '');
while ($start[2] !== '');
if ($set_members)
{
@ -668,7 +660,8 @@ class Import
}
}
catch(\Exception $e) {
$this->logger($e->getMessage(), 'fatal');
_egw_log_exception($e);
$this->logger($e->getMessage().' ('.$e->getCode().')', 'fatal');
$GLOBALS['egw']->accounts = $frontend;
throw $e;
}
@ -898,7 +891,7 @@ class Import
}
}
catch (\Exception $e) {
$this->logger("Error deleting no longer existing $type '$account_lid' (#$account_id): ".$e->getMessage(), 'error');
$this->logger("Error deleting no longer existing $type '$account_lid' (#$account_id): ".$e->getMessage().' ('.$e->getCode().')', 'error');
}
$GLOBALS['egw']->accounts = $backup_accounts;
@ -1001,11 +994,11 @@ class Import
_egw_log_exception($e);
// disable async job, something is not configured correct
self::installAsyncJob();
$import->logger('Async job for periodic import canceled', 'fatal');
$import->logger('Async job for periodic import canceled: '.$e->getMessage().' ('.$e->getCode().')', 'fatal');
}
catch (\Exception $e) {
_egw_log_exception($e);
$import->logger('Error: '.$e->getMessage(), 'fatal');
$import->logger('Error: '.$e->getMessage().' ('.$e->getCode().')', 'fatal');
}
}

View File

@ -391,30 +391,36 @@ class Ldap
$this->connect();
}
/**
* @var bool $admin parameter of last call to connect, to be able to reconnect
*/
protected bool $admin_connection;
/**
* connect to LDAP server
*
* @param boolean $admin =false true (re-)connect with admin not user credentials, eg. to modify accounts
*/
function connect($admin = false)
function connect($admin = false, $reconnect=false)
{
if ($admin)
if (($this->admin_connection = $admin))
{
$this->ds = Api\Ldap::factory();
$this->ds = Api\Ldap::factory(true, '', '', '', $reconnect);
}
// if ldap is NOT the contact repository, we only do accounts and need to use the account-data
elseif (substr($GLOBALS['egw_info']['server']['contact_repository'],-4) != 'ldap') // not (ldap or sql-ldap)
{
$this->ldap_config['ldap_contact_host'] = $this->ldap_config['ldap_host'];
$this->allContactsDN = $this->ldap_config['ldap_context'];
$this->ds = Api\Ldap::factory();
$this->ds = Api\Ldap::factory(true, '', '', '', $reconnect);
}
else
{
$this->ds = Api\Ldap::factory(true,
$this->ldap_config['ldap_contact_host'],
$GLOBALS['egw_info']['user']['account_dn'],
$GLOBALS['egw_info']['user']['passwd']
$GLOBALS['egw_info']['user']['passwd'],
$reconnect
);
}
}
@ -1273,17 +1279,27 @@ class Ldap
$this->total = 0;
}
if($_addressbooktype == self::ALL || $_ldapContext == $this->allContactsDN)
// retry, if connection to LDAP is lost
for($retry=1; $retry >= 0; --$retry)
{
$result = ldap_search($this->ds, $_ldapContext, $_filter, $_attributes, null, null, null, null, $control);
}
else
{
$result = ldap_list($this->ds, $_ldapContext, $_filter, $_attributes, null, null, null, null, $control);
}
if(!$result || ($entries = ldap_get_entries($this->ds, $result)) === false)
{
throw new \Exception(ldap_error($this->ds) ?: 'Unable to retrieve LDAP result', ldap_errno($this->ds));
if ($_addressbooktype == self::ALL || $_ldapContext == $this->allContactsDN)
{
$result = ldap_search($this->ds, $_ldapContext, $_filter, $_attributes, null, null, null, null, $control);
}
else
{
$result = ldap_list($this->ds, $_ldapContext, $_filter, $_attributes, null, null, null, null, $control);
}
if (!$result || ($entries = ldap_get_entries($this->ds, $result)) === false)
{
// retry after reconnect, if connection to LDAP server is lost
if ($retry >= 0 && in_array(ldap_errno($this->ds), [91, -1], true))
{
$this->connect($this->admin_connection, true);
continue;
}
throw new \Exception(ldap_error($this->ds) ?: 'Unable to retrieve LDAP result', ldap_errno($this->ds));
}
}
$this->total += $entries['count'];
//error_log(__METHOD__."('$_ldapContext', '$_filter', ".array2string($_attributes).", $_addressbooktype) result of $entries[count]");