".
($_SESSION['ldap_import']['mode']?__('No user to be synchronized')
:__('No user to be imported'))."
";
}
} else {
echo "
".
($_SESSION['ldap_import']['mode']?__('No user to be synchronized')
:__('No user to be imported'))."
";
}
}
static function searchForUsers($ds, $values, $filter, $attrs, &$limitexceeded, &$user_infos,
&$ldap_users, $config_ldap) {
//If paged results cannot be used (PHP < 5.4)
$cookie = ''; //Cookie used to perform query using pages
$count = 0; //Store the number of results ldap_search
do {
if (self::isLdapPageSizeAvailable($config_ldap)) {
ldap_control_paged_result($ds, $config_ldap->fields['pagesize'], true, $cookie);
}
$filter = Toolbox::unclean_cross_side_scripting_deep($filter);
$sr = @ldap_search($ds, $values['basedn'], $filter, $attrs);
if ($sr) {
if (in_array(ldap_errno($ds),array(4,11))) {
// openldap return 4 for Size limit exceeded
$limitexceeded = true;
}
$info = self::get_entries_clean($ds, $sr);
if (in_array(ldap_errno($ds),array(4,11))) {
$limitexceeded = true;
}
$count += $info['count'];
//If page results are enabled and the number of results is greater than the maximum allowed
//warn user that limit is exceeded and stop search
if (self::isLdapPageSizeAvailable($config_ldap)
&& $config_ldap->fields['ldap_maxlimit']
&& ($count > $config_ldap->fields['ldap_maxlimit'])) {
$limitexceeded = true;
break;
}
for ($ligne = 0 ; $ligne < $info["count"] ; $ligne++) {
//If ldap add
if ($values['mode'] == self::ACTION_IMPORT) {
if (in_array($config_ldap->fields['login_field'], $info[$ligne])) {
$ldap_users[$info[$ligne][$config_ldap->fields['login_field']][0]]
= $info[$ligne][$config_ldap->fields['login_field']][0];
$user_infos[$info[$ligne][$config_ldap->fields['login_field']][0]]["timestamp"]
= self::ldapStamp2UnixStamp($info[$ligne]['modifytimestamp'][0],
$config_ldap->fields['time_offset']);
$user_infos[$info[$ligne][$config_ldap->fields['login_field']][0]]["user_dn"]
= $info[$ligne]['dn'];
}
} else {
//If ldap synchronisation
if (in_array($config_ldap->fields['login_field'],$info[$ligne])) {
$ldap_users[$info[$ligne][$config_ldap->fields['login_field']][0]]
= self::ldapStamp2UnixStamp($info[$ligne]['modifytimestamp'][0],
$config_ldap->fields['time_offset']);
$user_infos[$info[$ligne][$config_ldap->fields['login_field']][0]]["timestamp"]
= self::ldapStamp2UnixStamp($info[$ligne]['modifytimestamp'][0],
$config_ldap->fields['time_offset']);
$user_infos[$info[$ligne][$config_ldap->fields['login_field']][0]]["user_dn"]
= $info[$ligne]['dn'];
$user_infos[$info[$ligne][$config_ldap->fields['login_field']][0]]["name"]
= $info[$ligne][$config_ldap->fields['login_field']][0];
}
}
}
} else {
return false;
}
if (self::isLdapPageSizeAvailable($config_ldap)) {
ldap_control_paged_result_response($ds, $sr, $cookie);
}
} while (($cookie !== null) && ($cookie != ''));
return true;
}
/** Get the list of LDAP users to add/synchronize
*
* @param $options array of possible options:
* - authldaps_id ID of the server to use
* - mode user to synchronise or add ?
* - ldap_filter ldap filter to use
* - basedn force basedn (default authldaps_id one)
* - order display order
* - begin_date begin date to time limit
* - end_date end date to time limit
* - script true if called by an external script
* @param &$results result stats
* @param &$limitexceeded limit exceeded exception
*
* @return array of the user
**/
static function getAllUsers($options=array(), &$results, &$limitexceeded) {
global $DB, $CFG_GLPI;
$config_ldap = new self();
$res = $config_ldap->getFromDB($options['authldaps_id']);
$values['order'] = 'DESC';
$values['mode'] = self::ACTION_SYNCHRONIZE;
$values['ldap_filter'] = '';
$values['basedn'] = $config_ldap->fields['basedn'];
$values['begin_date'] = NULL;
$values['end_date'] = date('Y-m-d H:i:s', time()-DAY_TIMESTAMP);
//Called by an external script or not
$values['script'] = 0;
foreach ($options as $option => $value) {
// this test break mode detection - if ($value != '') {
$values[$option] = $value;
//}
}
$ldap_users = array();
$user_infos = array();
$limitexceeded = false;
// we prevent some delay...
if (!$res) {
return false;
}
if ($values['order'] != "DESC") {
$values['order'] = "ASC";
}
$ds = $config_ldap->connect();
if ($ds) {
//Search for ldap login AND modifyTimestamp,
//which indicates the last update of the object in directory
$attrs = array($config_ldap->fields['login_field'], "modifyTimestamp");
// Try a search to find the DN
if ($values['ldap_filter'] == '') {
$filter = "(".$config_ldap->fields['login_field']."=*)";
} else {
$filter = $values['ldap_filter'];
}
if ($values['script'] && !empty($values['begin_date'])) {
$filter_timestamp = self::addTimestampRestrictions($values['begin_date'],
$values['end_date']);
$filter = "(&$filter $filter_timestamp)";
}
$result = self::searchForUsers($ds, $values, $filter, $attrs, $limitexceeded,
$user_infos, $ldap_users, $config_ldap);
if (!$result) {
return false;
}
} else {
return false;
}
$glpi_users = array();
$sql = "SELECT *
FROM `glpi_users`";
if ($values['mode'] != self::ACTION_IMPORT) {
$sql .= " WHERE `authtype` IN (-1,".Auth::NOT_YET_AUTHENTIFIED.",".Auth::LDAP.",".Auth::EXTERNAL.", ". Auth::CAS.")
AND `auths_id` = '".$options['authldaps_id']."'";
}
$sql .= " ORDER BY `name` ".$values['order'];
foreach ($DB->request($sql) as $user) {
$tmpuser = new User();
//Ldap add : fill the array with the login of the user
if ($values['mode'] == self::ACTION_IMPORT) {
$glpi_users[$user['name']] = $user['name'];
} else {
//Ldap synchronisation : look if the user exists in the directory
//and compares the modifications dates (ldap and glpi db)
$userfound = false;
if (!empty($ldap_users[$user['name']])
|| ($userfound = self::dnExistsInLdap($user_infos, $user['user_dn']))) {
// userfound seems that user dn is present in GLPI DB but do not correspond to an GLPI user
// -> renaming case
if ($userfound) {
//Get user in DB with this dn
if (!$tmpuser->getFromDBByDn(Toolbox::addslashes_deep($user['user_dn']))) {
//This should never happened
//If a user_dn is present more than one time in database
//Just skip user synchronization to avoid errors
continue;
}
$glpi_users[] = array('id' => $user['id'],
'user' => $userfound['name'],
'timestamp' => $user_infos[$userfound['name']]['timestamp'],
'date_sync' => $tmpuser->fields['date_sync'],
'dn' => $user['user_dn']);
//If entry was modified or if script should synchronize all the users
} else if (($values['action'] == self::ACTION_ALL)
|| (($ldap_users[$user['name']] - strtotime($user['date_sync'])) > 0)) {
$glpi_users[] = array('id' => $user['id'],
'user' => $user['name'],
'timestamp' => $user_infos[$user['name']]['timestamp'],
'date_sync' => $user['date_sync'],
'dn' => $user['user_dn']);
}
// Only manage deleted user if ALL (because of entity visibility in delegated mode)
} else if (($values['action'] == self::ACTION_ALL)
&& !$limitexceeded) {
//If user is marked as coming from LDAP, but is not present in it anymore
if (!$user['is_deleted']
&& ($user['auths_id'] == $options['ldapservers_id'])) {
User::manageDeletedUserInLdap($user['id']);
$results[self::USER_DELETED_LDAP] ++;
}
}
}
}
//If add, do the difference between ldap users and glpi users
if ($values['mode'] == self::ACTION_IMPORT) {
$diff = array_diff_ukey($ldap_users,$glpi_users,'strcasecmp');
$list = array();
$tmpuser = new User();
foreach ($diff as $user) {
//If user dn exists in DB, it means that user login field has changed
if (!$tmpuser->getFromDBByDn(toolbox::addslashes_deep($user_infos[$user]["user_dn"]))) {
$list[] = array("user" => $user,
"timestamp" => $user_infos[$user]["timestamp"],
"date_sync" => Dropdown::EMPTY_VALUE);
}
}
if ($values['order'] == 'DESC') {
rsort($list);
} else {
sort($list);
}
return $list;
}
return $glpi_users;
}
/**
* Check if a user DN exists in a ldap user search result
*
* @since version 0.84
*
* @param $ldap_infos ldap user search result
* @param $user_dn user dn to look for
*
* @return false if the user dn doesn't exist, user ldap infos otherwise
**/
static function dnExistsInLdap($ldap_infos, $user_dn) {
$found = false;
foreach ($ldap_infos as $ldap_info) {
if ($ldap_info['user_dn'] == $user_dn) {
$found = $ldap_info;
break;
}
}
return $found;
}
/** Show LDAP groups to add or synchronise in an entity
*
* @param $target target page for the form
* @param $start where to start the list
* @param $sync synchronise or add ? (default 0)
* @param $filter ldap filter to use (default '')
* @param $filter2 second ldap filter to use (which case ?) (default '')
* @param $entity working entity
* @param $order display order (default DESC)
*
* @return nothing
**/
static function showLdapGroups($target, $start, $sync=0, $filter='', $filter2='',
$entity, $order='DESC') {
echo " ";
$limitexceeded = false;
$ldap_groups = self::getAllGroups($_SESSION["ldap_server"], $filter, $filter2, $entity,
$limitexceeded, $order);
if (is_array($ldap_groups)) {
$numrows = count($ldap_groups);
$rand = mt_rand();
$colspan = (Session::isMultiEntitiesMode()?5:4);
if ($numrows > 0) {
self::displaySizeLimitWarning($limitexceeded);
$parameters = '';
Html::printPager($start, $numrows, $target,$parameters);
// delete end
array_splice($ldap_groups, $start + $_SESSION['glpilist_limit']);
// delete begin
if ($start > 0) {
array_splice($ldap_groups, 0, $start);
}
echo "
";
}
}
/** Get all LDAP groups from a ldap server which are not already in an entity
*
* @since version 0.84 new parameter $limitexceeded
*
* @param $auths_id ID of the server to use
* @param $filter ldap filter to use
* @param $filter2 second ldap filter to use if needed
* @param $entity entity to search
* @param $limitexceeded
* @param $order order to use (default DESC)
*
* @return array of the groups
**/
static function getAllGroups($auths_id, $filter, $filter2, $entity, &$limitexceeded,
$order='DESC') {
global $DB;
$config_ldap = new self();
$res = $config_ldap->getFromDB($auths_id);
$infos = array();
$groups = array();
$ds = $config_ldap->connect();
if ($ds) {
switch ($config_ldap->fields["group_search_type"]) {
case 0 :
$infos = self::getGroupsFromLDAP($ds, $config_ldap, $filter, false, $infos,
$limitexceeded);
break;
case 1 :
$infos = self::getGroupsFromLDAP($ds, $config_ldap, $filter, true, $infos,
$limitexceeded);
break;
case 2 :
$infos = self::getGroupsFromLDAP($ds, $config_ldap, $filter ,true, $infos,
$limitexceeded);
$infos = self::getGroupsFromLDAP($ds, $config_ldap, $filter2, false, $infos,
$limitexceeded);
break;
}
if (!empty($infos)) {
$glpi_groups = array();
//Get all groups from GLPI DB for the current entity and the subentities
$sql = "SELECT `name`
FROM `glpi_groups` ".
getEntitiesRestrictRequest("WHERE","glpi_groups");
$res = $DB->query($sql);
//If the group exists in DB -> unset it from the LDAP groups
while ($group = $DB->fetch_assoc($res)) {
$glpi_groups[$group["name"]] = 1;
}
$ligne = 0;
foreach ($infos as $dn => $info) {
if (!isset($glpi_groups[$info["cn"]])) {
$groups[$ligne]["dn"] = $dn;
$groups[$ligne]["cn"] = $info["cn"];
$groups[$ligne]["search_type"] = $info["search_type"];
$ligne++;
}
}
}
if ($order == 'DESC') {
function local_cmp($b, $a) {
return strcasecmp($a['cn'], $b['cn']);
}
} else {
function local_cmp($a ,$b) {
return strcasecmp($a['cn'], $b['cn']);
}
}
usort($groups,'local_cmp');
}
return $groups;
}
/**
* Get the group's cn by giving his DN
*
* @param $ldap_connection ldap connection to use
* @param $group_dn the group's dn
*
* @return the group cn
**/
static function getGroupCNByDn($ldap_connection, $group_dn) {
$sr = @ ldap_read($ldap_connection, $group_dn, "objectClass=*", array("cn"));
$v = self::get_entries_clean($ldap_connection, $sr);
if (!is_array($v) || (count($v) == 0) || empty($v[0]["cn"][0])) {
return false;
}
return $v[0]["cn"][0];
}
/**
* @since version 0.84 new parameter $limitexceeded
*
* @param $ldap_connection
* @param $config_ldap
* @param $filter
* @param $search_in_groups (true by default)
* @param $groups array
* @param $limitexceeded
**/
static function getGroupsFromLDAP($ldap_connection, $config_ldap, $filter,
$search_in_groups=true, $groups=array(),
&$limitexceeded) {
global $DB;
//First look for groups in group objects
$extra_attribute = ($search_in_groups?"cn":$config_ldap->fields["group_field"]);
$attrs = array("dn", $extra_attribute);
if ($filter == '') {
if ($search_in_groups) {
$filter = (!empty($config_ldap->fields['group_condition'])
? $config_ldap->fields['group_condition'] : "(objectclass=*)");
} else {
$filter = (!empty($config_ldap->fields['condition'])
? $config_ldap->fields['condition'] : "(objectclass=*)");
}
}
$cookie = '';
$count = 0;
do {
if (self::isLdapPageSizeAvailable($config_ldap)) {
ldap_control_paged_result($ldap_connection, $config_ldap->fields['pagesize'],
true, $cookie);
}
$filter = Toolbox::unclean_cross_side_scripting_deep($filter);
$sr = @ldap_search($ldap_connection, $config_ldap->fields['basedn'], $filter ,
$attrs);
if ($sr) {
if (in_array(ldap_errno($ldap_connection),array(4,11))) {
// openldap return 4 for Size limit exceeded
$limitexceeded = true;
}
$infos = self::get_entries_clean($ldap_connection, $sr);
if (in_array(ldap_errno($ldap_connection),array(4,11))) {
// openldap return 4 for Size limit exceeded
$limitexceeded = true;
}
$count += $infos['count'];
//If page results are enabled and the number of results is greater than the maximum allowed
//warn user that limit is exceeded and stop search
if (self::isLdapPageSizeAvailable($config_ldap)
&& $config_ldap->fields['ldap_maxlimit']
&& ($count > $config_ldap->fields['ldap_maxlimit'])) {
$limitexceeded = true;
break;
}
for ($ligne=0 ; $ligne < $infos["count"] ; $ligne++) {
if ($search_in_groups) {
// No cn : not a real object
if (isset($infos[$ligne]["cn"][0])) {
$cn = $infos[$ligne]["cn"][0];
$groups[$infos[$ligne]["dn"]] = (array("cn" => $infos[$ligne]["cn"][0],
"search_type" => "groups"));
}
} else {
if (isset($infos[$ligne][$extra_attribute])) {
if (($config_ldap->fields["group_field"] == 'dn')
|| in_array('ou', $groups)) {
$dn = $infos[$ligne][$extra_attribute];
$ou = array();
for ($tmp=$dn ; count($tmptab=explode(',',$tmp,2))==2 ; $tmp=$tmptab[1]) {
$ou[] = $tmptab[1];
}
/// Search in DB for group with ldap_group_dn
if (($config_ldap->fields["group_field"] == 'dn')
&& (count($ou) > 0)) {
$query = "SELECT `ldap_value`
FROM `glpi_groups`
WHERE `ldap_group_dn`
IN ('".implode("', '",
Toolbox::addslashes_deep($ou))."')";
foreach ($DB->request($query) as $group) {
$groups[$group['ldap_value']] = array("cn" => $group['ldap_value'],
"search_type"
=> "users");
}
}
} else {
for ($ligne_extra=0 ; $ligne_extra<$infos[$ligne][$extra_attribute]["count"] ;
$ligne_extra++) {
$groups[$infos[$ligne][$extra_attribute][$ligne_extra]]
= array("cn" => self::getGroupCNByDn($ldap_connection,
$infos[$ligne][$extra_attribute][$ligne_extra]),
"search_type"
=> "users");
}
}
}
}
}
}
if (self::isLdapPageSizeAvailable($config_ldap)) {
ldap_control_paged_result_response($ldap_connection, $sr, $cookie);
}
} while (($cookie !== null) && ($cookie != ''));
return $groups;
}
/** Form to choose a ldap server
*
* @param $target target page for the form
*
* @return nothing
**/
static function ldapChooseDirectory($target) {
global $DB;
$query = "SELECT *
FROM `glpi_authldaps`
WHERE `is_active` = '1'
ORDER BY `name` ASC";
$result = $DB->query($query);
if ($DB->numrows($result) == 1) {
//If only one server, do not show the choose ldap server window
$ldap = $DB->fetch_assoc($result);
$_SESSION["ldap_server"] = $ldap["id"];
Html::redirect($_SERVER['PHP_SELF']);
}
echo "
";
echo "
";
}
/** Import a user from a specific ldap server
*
* @param $params array of parameters: method (IDENTIFIER_LOGIN or IDENTIFIER_EMAIL) + value
* @param $action synchoronize (true) or import (false)
* @param $ldap_server ID of the LDAP server to use
* @param $display display message information on redirect (false by default)
*
* @return array with state, else false
**/
static function ldapImportUserByServerId($params=array(), $action, $ldap_server,
$display=false) {
global $DB;
static $conn_cache = array();
$params = Toolbox::stripslashes_deep($params);
$config_ldap = new self();
$res = $config_ldap->getFromDB($ldap_server);
$ldap_users = array();
$input = array();
// we prevent some delay...
if (!$res) {
return false;
}
$search_parameters = array();
//Connect to the directory
if (isset($conn_cache[$ldap_server])) {
$ds = $conn_cache[$ldap_server];
} else {
$ds = $config_ldap->connect();
}
if ($ds) {
$conn_cache[$ldap_server] = $ds;
$search_parameters['method'] = $params['method'];
$search_parameters['fields'][self::IDENTIFIER_LOGIN] = $config_ldap->fields['login_field'];
if ($params['method'] == self::IDENTIFIER_EMAIL) {
$search_parameters['fields'][self::IDENTIFIER_EMAIL]
= $config_ldap->fields['email1_field'];
}
//Get the user's dn & login
$attribs = array('basedn' => $config_ldap->fields['basedn'],
'login_field' => $search_parameters['fields'][$search_parameters['method']],
'search_parameters'
=> $search_parameters,
'user_params' => $params,
'condition' => $config_ldap->fields['condition']);
$infos = self::searchUserDn($ds,$attribs);
if ($infos && $infos['dn']) {
$user_dn = $infos['dn'];
$login = $infos[$config_ldap->fields['login_field']];
$groups = array();
$user = new User();
//Get information from LDAP
if ($user->getFromLDAP($ds, $config_ldap->fields, $user_dn, addslashes($login),
($action == self::ACTION_IMPORT))) {
// Add the auth method
// Force date sync
$user->fields["date_sync"] = $_SESSION["glpi_currenttime"];
$user->fields['is_deleted_ldap'] = 0;
//Save information in database !
$input = $user->fields;
//clean picture from input
// (picture managed in User::post_addItem and prepareInputForUpdate)
unset($input['picture']);
if ($action == self::ACTION_IMPORT) {
$input["authtype"] = Auth::LDAP;
$input["auths_id"] = $ldap_server;
// Display message after redirect
if ($display) {
$input['add'] = 1;
}
$user->fields["id"] = $user->add($input);
return array('action' => self::USER_IMPORTED,
'id' => $user->fields["id"]);
}
//Get the ID by user name
if (!($id = User::getIdByfield('name', $login))) {
//In case user id as changed : get id by dn
$id = User::getIdByfield('user_dn', $user_dn);
}
$input['id'] = $id;
if ($display) {
$input['update'] = 1;
}
$user->update($input);
return array('action' => self::USER_SYNCHRONIZED,
'id' => $input['id']);
}
return false;
}
if ($action != self::ACTION_IMPORT) {
$users_id = User::getIdByField('name', $params['value']);
User::manageDeletedUserInLdap($users_id);
return array('action' => self::USER_DELETED_LDAP,
'id' => $users_id);
}
} else {
return false;
}
}
/** Converts an array of parameters into a query string to be appended to a URL.
*
* @param $group_dn dn of the group to import
* @param $options array for
* - authldaps_id
* - entities_id where group must to be imported
* - is_recursive
*
* @return nothing
**/
static function ldapImportGroup ($group_dn, $options=array()) {
$config_ldap = new self();
$res = $config_ldap->getFromDB($options['authldaps_id']);
$ldap_users = array();
$group_dn = $group_dn;
// we prevent some delay...
if (!$res) {
return false;
}
//Connect to the directory
$ds = $config_ldap->connect();
if ($ds) {
$group_infos = self::getGroupByDn($ds, stripslashes($group_dn));
$group = new Group();
if ($options['type'] == "groups") {
return $group->add(array("name" => addslashes($group_infos["cn"][0]),
"ldap_group_dn" => addslashes($group_infos["dn"]),
"entities_id" => $options['entities_id'],
"is_recursive" => $options['is_recursive']));
}
return $group->add(array("name" => addslashes($group_infos["cn"][0]),
"ldap_field" => $config_ldap->fields["group_field"],
"ldap_value" => addslashes($group_infos["dn"]),
"entities_id" => $options['entities_id'],
"is_recursive" => $options['is_recursive']));
}
return false;
}
/**
* Open LDAP connexion to current serveur
**/
function connect() {
return $this->connectToServer($this->fields['host'], $this->fields['port'],
$this->fields['rootdn'],
Toolbox::decrypt($this->fields['rootdn_passwd'], GLPIKEY),
$this->fields['use_tls'],
$this->fields['deref_option']);
}
/**
* Connect to a LDAP serveur
*
* @param $host LDAP host to connect
* @param $port port to use
* @param $login login to use (default '')
* @param $password password to use (default '')
* @param $use_tls use a tls connection ? (false by default)
* @param $deref_options deref options used
*
* @return link to the LDAP server : false if connection failed
**/
static function connectToServer($host, $port, $login="", $password="", $use_tls=false,
$deref_options) {
$ds = @ldap_connect($host, intval($port));
if ($ds) {
@ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
@ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
@ldap_set_option($ds, LDAP_OPT_DEREF, $deref_options);
if ($use_tls) {
if (!@ldap_start_tls($ds)) {
return false;
}
}
// Auth bind
if ($login != '') {
$b = @ldap_bind($ds, $login, $password);
} else { // Anonymous bind
$b = @ldap_bind($ds);
}
if ($b) {
return $ds;
}
}
return false;
}
/**
* Try to connect to a ldap server
*
* @param $ldap_method ldap_method array to use
* @param $login User Login
* @param $password User Password
*
* @return link to the LDAP server : false if connection failed
**/
static function tryToConnectToServer($ldap_method, $login, $password) {
$ds = self::connectToServer($ldap_method['host'], $ldap_method['port'],
$ldap_method['rootdn'],
Toolbox::decrypt($ldap_method['rootdn_passwd'], GLPIKEY),
$ldap_method['use_tls'], $ldap_method['deref_option']);
// Test with login and password of the user if exists
if (!$ds
&& !empty($login)) {
$ds = self::connectToServer($ldap_method['host'], $ldap_method['port'], $login,
$password, $ldap_method['use_tls'],
$ldap_method['deref_option']);
}
//If connection is not successfull on this directory, try replicates (if replicates exists)
if (!$ds
&& ($ldap_method['id'] > 0)) {
foreach (self::getAllReplicateForAMaster($ldap_method['id']) as $replicate) {
$ds = self::connectToServer($replicate["host"], $replicate["port"],
$ldap_method['rootdn'],
Toolbox::decrypt($ldap_method['rootdn_passwd'], GLPIKEY),
$ldap_method['use_tls'], $ldap_method['deref_option']);
// Test with login and password of the user
if (!$ds
&& !empty($login)) {
$ds = self::connectToServer($replicate["host"], $replicate["port"], $login,
$password, $ldap_method['use_tls'],
$ldap_method['deref_option']);
}
if ($ds) {
return $ds;
}
}
}
return $ds;
}
static function getLdapServers() {
return getAllDatasFromTable('glpi_authldaps', '', false, '`is_default` DESC');
}
/**
* Is the LDAP authentication used ?
*
* @return boolean
**/
static function useAuthLdap() {
global $DB;
//Get all the ldap directories
$sql = "SELECT COUNT(*)
FROM `glpi_authldaps`
WHERE `is_active` = 1";
$result = $DB->query($sql);
if ($DB->result($result,0,0) > 0) {
return true;
}
return false;
}
/**
* Import a user from ldap
* Check all the directories. When the user is found, then import it
*
* @param $options array containing condition:
* array('name'=>'glpi') or array('email' => 'test at test.com')
**/
static function importUserFromServers($options=array()) {
$auth = new Auth();
$params = array();
if (isset($options['name'])) {
$params['value'] = $options['name'];
$params['method'] = self::IDENTIFIER_LOGIN;
}
if (isset($options['email'])) {
$params['value'] = $options['email'];
$params['method'] = self::IDENTIFIER_EMAIL;
}
$auth->user_present = $auth->userExists($options);
//If the user does not exists
if ($auth->user_present == 0) {
$auth->getAuthMethods();
$ldap_methods = $auth->authtypes["ldap"];
$userid = -1;
foreach ($ldap_methods as $ldap_method) {
if ($ldap_method['is_active']) {
$result = self::ldapImportUserByServerId($params, 0, $ldap_method["id"], true);
if ($result != false) {
return $result;
}
}
}
Session::addMessageAfterRedirect(__('User not found or several users found'), false, ERROR);
} else {
Session::addMessageAfterRedirect(__('Unable to add. The user already exist.'), false,
ERROR);
}
return false;
}
/**
* Authentify a user by checking a specific directory
*
* @param $auth identification object
* @param $login user login
* @param $password user password
* @param $ldap_method ldap_method array to use
* @param $user_dn user LDAP DN if present
*
* @return identification object
**/
static function ldapAuth($auth, $login, $password, $ldap_method, $user_dn) {
$oldlevel = error_reporting(0);
$user_dn = $auth->connection_ldap($ldap_method, $login, $password);
error_reporting($oldlevel);
$auth->auth_succeded = false;
$auth->extauth = 1;
if ($user_dn) {
$auth->auth_succeded = true;
//There's already an existing user in DB with the same DN but its login field has changed
if ($auth->user->getFromDBbyDn(toolbox::addslashes_deep($user_dn))) {
//Change user login
$auth->user->fields['name'] = $login;
$auth->user_present = true;
//The user is a new user
} else {
$auth->user_present = $auth->user->getFromDBbyName(addslashes($login));
}
$auth->user->getFromLDAP($auth->ldap_connection, $ldap_method, $user_dn, $login,
!$auth->user_present);
$auth->user->fields["authtype"] = Auth::LDAP;
$auth->user->fields["auths_id"] = $ldap_method["id"];
}
return $auth;
}
/**
* Try to authentify a user by checking all the directories
*
* @param $auth identification object
* @param $login user login
* @param $password user password
* @param $auths_id auths_id already used for the user (default 0)
* @param $user_dn user LDAP DN if present (false by default)
* @param $break if user is not found in the first directory,
* stop searching or try the following ones (true by default)
*
* @return identification object
**/
static function tryLdapAuth($auth, $login, $password, $auths_id=0, $user_dn=false, $break=true) {
//If no specific source is given, test all ldap directories
if ($auths_id <= 0) {
foreach ($auth->authtypes["ldap"] as $ldap_method) {
if (!$auth->auth_succeded
&& $ldap_method['is_active']) {
$auth = self::ldapAuth($auth, $login, $password, $ldap_method, $user_dn);
} else {
if ($break) {
break;
}
}
}
//Check if the ldap server indicated as the last good one still exists !
} else if (array_key_exists($auths_id, $auth->authtypes["ldap"])) {
//A specific ldap directory is given, test it and only this one !
$auth = self::ldapAuth($auth, $login, $password, $auth->authtypes["ldap"][$auths_id],
$user_dn);
}
return $auth;
}
/**
* Get dn for a user
*
* @param $ds LDAP link
* @param $options array of possible options:
* - basedn : base dn used to search
* - login_field : attribute to store login
* - search_parameters array of search parameters
* - user_params array of parameters : method (IDENTIFIER_LOGIN or IDENTIFIER_EMAIL) + value
* - condition : ldap condition used
*
* @return dn of the user, else false
**/
static function searchUserDn($ds, $options=array()) {
$values['basedn'] = '';
$values['login_field'] = '';
$values['search_parameters'] = array();
$values['user_params'] = '';
$values['condition'] = '';
$values['user_dn'] = false;
foreach ($options as $key => $value) {
$values[$key] = $value;
}
//By default authentify users by login
//$authentification_value = '';
$login_attr = $values['search_parameters']['fields'][self::IDENTIFIER_LOGIN];
$ldap_parameters = array("dn");
foreach ($values['search_parameters']['fields'] as $parameter) {
$ldap_parameters[] = $parameter;
}
//First : if a user dn is provided, look for it in the directory
//Before trying to find the user using his login_field
if ($values['user_dn']) {
$info = self::getUserByDn($ds, $values['user_dn'], $ldap_parameters);
if ($info) {
return array('dn' => $values['user_dn'],
$login_attr => $info[$login_attr][0]);
}
}
//$authentification_value = $values['user_params']['value'];
// Tenter une recherche pour essayer de retrouver le DN
$filter = "(".$values['login_field']."=".$values['user_params']['value'].")";
if (!empty($values['condition'])) {
$filter = "(& $filter ".$values['condition'].")";
}
$filter = Toolbox::unclean_cross_side_scripting_deep($filter);
if ($result = @ldap_search($ds, $values['basedn'], $filter, $ldap_parameters)) {
$info = self::get_entries_clean($ds, $result);
if (is_array($info) && ($info['count'] == 1)) {
return array('dn' => $info[0]['dn'],
$login_attr => $info[0][$login_attr][0]);
}
}
return false;
}
/**
* Get an object from LDAP by giving his DN
*
* @param ds the active connection to the directory
* @param condition the LDAP filter to use for the search
* @param $dn string DN of the object
* @param attrs array of the attributes to retreive
* @param $clean (true by default)
**/
static function getObjectByDn($ds, $condition, $dn, $attrs=array(), $clean=true) {
if ($result = @ ldap_read($ds, $dn, $condition, $attrs)) {
if ($clean) {
$info = self::get_entries_clean($ds, $result);
} else $info = ldap_get_entries($ds, $result);
if (is_array($info) && ($info['count'] == 1)) {
return $info[0];
}
}
return false;
}
/**
* @param $ds
* @param $user_dn
* @param $attrs
* @param $clean (true by default)
**/
static function getUserByDn($ds, $user_dn, $attrs, $clean=true) {
return self::getObjectByDn($ds, "objectClass=*", $user_dn, $attrs, $clean);
}
/**
* Get infos for groups
*
* @param $ds LDAP link
* @param $group_dn dn of the group
*
* @return group infos if found, else false
**/
static function getGroupByDn($ds, $group_dn) {
return self::getObjectByDn($ds, "objectClass=*", $group_dn, array("cn"));
}
/**
* @param $options array
* @param $delete (false by default)
**/
static function manageValuesInSession($options=array(), $delete=false) {
$fields = array('action', 'authldaps_id', 'basedn', 'begin_date', 'criterias', 'end_date',
'entities_id', 'interface', 'ldap_filter', 'mode');
//If form accessed via modal, do not show expert mode link
// Manage new value is set : entity or mode
if (isset($options['entity'])
|| isset($options['mode'])) {
if (isset($options['_in_modal']) && $options['_in_modal']) {
//If coming form the helpdesk form : reset all criterias
$_SESSION['ldap_import']['_in_modal'] = 1;
$_SESSION['ldap_import']['no_expert_mode'] = 1;
$_SESSION['ldap_import']['action'] = 'show';
$_SESSION['ldap_import']['interface'] = self::SIMPLE_INTERFACE;
$_SESSION['ldap_import']['mode'] = self::ACTION_IMPORT;
} else {
$_SESSION['ldap_import']['_in_modal'] = 0;
}
}
if (!$delete) {
if (!isset($_SESSION['ldap_import']['entities_id'])) {
$options['entities_id'] = $_SESSION['glpiactive_entity'];
}
if (isset($options['toprocess'])) {
$_SESSION['ldap_import']['action'] = 'process';
}
if (isset($options['change_directory'])) {
$options['ldap_filter'] = '';
}
if (!isset($_SESSION['ldap_import']['authldaps_id'])) {
$_SESSION['ldap_import']['authldaps_id'] = NOT_AVAILABLE;
}
if ((!Config::canUpdate()
&& !Entity::canUpdate())
|| (!isset($_SESSION['ldap_import']['interface']) && !isset($options['interface']))) {
$options['interface'] = self::SIMPLE_INTERFACE;
}
foreach ($fields as $field) {
if (isset($options[$field])) {
$_SESSION['ldap_import'][$field] = $options[$field];
}
}
if (isset($_SESSION['ldap_import']['begin_date'])
&& ($_SESSION['ldap_import']['begin_date'] == 'NULL')) {
$_SESSION['ldap_import']['begin_date'] = '';
}
if (isset($_SESSION['ldap_import']['end_date'])
&& ($_SESSION['ldap_import']['end_date'] == 'NULL')) {
$_SESSION['ldap_import']['end_date'] = '';
}
if (!isset($_SESSION['ldap_import']['criterias'])) {
$_SESSION['ldap_import']['criterias'] = array();
}
$authldap = new self();
//Filter computation
if ($_SESSION['ldap_import']['interface'] == self::SIMPLE_INTERFACE) {
$entity = new Entity();
if ($entity->getFromDB($_SESSION['ldap_import']['entities_id'])
&& ($entity->getField('authldaps_id') > 0)) {
$authldap->getFromDB($_SESSION['ldap_import']['authldaps_id']);
$_SESSION['ldap_import']['authldaps_id'] = $entity->getField('authldaps_id');
$_SESSION['ldap_import']['basedn'] = $entity->getField('ldap_dn');
// No dn specified in entity : use standard one
if (empty($_SESSION['ldap_import']['basedn'])) {
$_SESSION['ldap_import']['basedn'] = $authldap->getField('basedn');
}
if ($entity->getField('entity_ldapfilter') != NOT_AVAILABLE) {
$_SESSION['ldap_import']['entity_filter']
= $entity->getField('entity_ldapfilter');
}
} else {
$_SESSION['ldap_import']['authldaps_id'] = self::getDefault();
if ($_SESSION['ldap_import']['authldaps_id'] > 0) {
$authldap->getFromDB($_SESSION['ldap_import']['authldaps_id']);
$_SESSION['ldap_import']['basedn'] = $authldap->getField('basedn');
}
}
if ($_SESSION['ldap_import']['authldaps_id'] > 0) {
$_SESSION['ldap_import']['ldap_filter'] = self::buildLdapFilter($authldap);
}
} else {
if ($_SESSION['ldap_import']['authldaps_id'] == NOT_AVAILABLE
|| !$_SESSION['ldap_import']['authldaps_id']) {
$_SESSION['ldap_import']['authldaps_id'] = self::getDefault();
if ($_SESSION['ldap_import']['authldaps_id'] > 0) {
$authldap->getFromDB($_SESSION['ldap_import']['authldaps_id']);
$_SESSION['ldap_import']['basedn'] = $authldap->getField('basedn');
}
}
if (!isset($_SESSION['ldap_import']['ldap_filter'])
|| $_SESSION['ldap_import']['ldap_filter'] == '') {
$authldap->getFromDB($_SESSION['ldap_import']['authldaps_id']);
$_SESSION['ldap_import']['basedn'] = $authldap->getField('basedn');
$_SESSION['ldap_import']['ldap_filter'] = self::buildLdapFilter($authldap);
}
}
//Unset all values in session
} else {
unset($_SESSION['ldap_import']);
}
}
/**
* @param $authldap AuthLDAP object
**/
static function showUserImportForm(AuthLDAP $authldap) {
global $DB;
//Get data related to entity (directory and ldap filter)
$authldap->getFromDB($_SESSION['ldap_import']['authldaps_id']);
echo "