@link http://www.sys1.fr @licence Copyright Sys1 @version 1.0.0 @description Plugin pour l'identification sur Active Directory (LDAP) */ //Recuperation d'un instance ldap avec les configuraiton serveur function ldap_instance($ssl = false){ require_once(__DIR__.SLASH.'ActiveDirectory.class.php'); global $conf; $ldap = new ActiveDirectory(); $ldap->server = ($ssl ? 'ldaps://':'' ).$conf->get('activedirectory_server'); $ldap->port = $ssl ? $conf->get('activedirectory_ssl_port'): $conf->get('activedirectory_port'); $ldap->userRoot = $conf->get('activedirectory_users_root'); $ldap->groupRoot = $conf->get('activedirectory_groups_root'); $ldap->domain = $conf->get('activedirectory_domain'); $ldap->protocolVersion = 3; return $ldap; } //Récuperation de l'ensemble des utilisateurs en LDAP (appellé par User::getAll) function ldap_plugin_all_users(&$users, $loadRights=false){ require_once(__DIR__.SLASH.'ActiveDirectory.class.php'); global $conf; try{ $ldap = ldap_instance(); $ldap->connect($conf->get('activedirectory_reader_login'),$conf->get('activedirectory_reader_password')); $attributes = ActiveDirectory::USER_SEARCH_DEFAULT_ATTRIBUTES; foreach(activedirectory_meta_data() as $data) $attributes .= ','.$data['adslug']; $infos = $ldap->search($conf->get('activedirectory_users_root'), null, $attributes); if(empty($infos)) return $ldap->disconnect(); $allUsers = array(); $authentificationAttribute = ActiveDirectory::authentification_attribute($conf->get('activedirectory_authentification')); foreach($infos as $info){ if(isset($info[$authentificationAttribute][0]) && trim($info[$authentificationAttribute][0])!=''){ $newUser = new User(); ldap_user_fill($ldap,$newUser,$info,true,false); if($loadRights) user_rank_firm_by_group($newUser); $manager = new User(); if(isset($info['manager'][0])){ foreach($infos as $info2){ if($info2['dn'] != $info['manager'][0]) continue; ldap_user_fill($ldap,$manager,$info2,false,false); } } $newUser->manager = $manager; $allUsers[] = $newUser; } } $users = $allUsers; }catch(Exception $e){ $ldap->disconnect(); //Décommenter la ligne qui suit pour avoir un message d'erreur si pb de connexion à l'AD //throw new Exception("Une erreur est survenue lors de la connexion à l'AD"); } } //Récuperation d'un utilisateur précis en LDAP (appellé par User::check) function ldap_plugin_identification(&$user,$login,$password,$loadRight,$loadManager=true,$noPassword=false){ global $_,$conf; require_once(__DIR__.SLASH.'ActiveDirectory.class.php'); if($user != false) return; $ldap = ldap_instance(); try{ if($noPassword) $ldap->connect($conf->get('activedirectory_reader_login'), $conf->get('activedirectory_reader_password')); else $ldap->connect($login.$ldap->domain, $password); $attributes = ActiveDirectory::USER_SEARCH_DEFAULT_ATTRIBUTES; foreach(activedirectory_meta_data() as $data) $attributes .= ','.$data['adslug']; $infos = $ldap->search($conf->get('activedirectory_users_root'), $ldap->authentification_filter($login, $conf->get('activedirectory_authentification')), $attributes); if(!empty($infos)){ $user = new User(); ldap_user_fill($ldap,$user,$infos[0],$loadRight,$loadManager); user_rank_firm_by_group($user); foreach($user->firms as $firm){ if($firm->has_plugin('fr.sys1.activedirectory')){ $firmHasPlugin = true; break; } } } // if(!isset($firmHasPlugin)) throw new Exception("Ce compte n'est actif sur aucun établissement",403); $avatarPath = __ROOT__.FILE_PATH.AVATAR_PATH.$user->login.'.jpg'; if(isset($user->meta['ldap_avatar'])){ if(!file_exists(__ROOT__.FILE_PATH.AVATAR_PATH)) mkdir(__ROOT__.FILE_PATH.AVATAR_PATH,0755,true); file_put_contents($avatarPath,base64_decode($user->meta['ldap_avatar'])); } }catch(Exception $e){ switch ($e->getCode()) { case 403: // throw new Exception($e->getMessage(), 403); break; default: break; } } $ldap->disconnect(); } //Remplissage d'une classe User en fonction des atttributs LDAPS function ldap_user_fill($ldap,&$user,$infos,$loadRight=false,$loadManager = false){ global $conf; require_once(__DIR__.SLASH.'ActiveDirectory.class.php'); //Vérifie que le compte n'est pas expiré (nb : 0 et 9223372036854775807 sont les deux valeurs possibles pour un n'expire jamais (allez comprendre la logique microsoft...)) if(isset($infos['accountexpires'][0]) && $infos['accountexpires'][0]!=0 && $infos['accountexpires'][0]!=9223372036854775807){ //Convertion en seconds $seconds = (float)($infos['accountexpires'][0] / 10000000); //Convertion d'un timestamp AD en timestamp UNIX $timestamp = round($seconds - (((1970-1601) * 365.242190) * 86400)); if($timestamp <= time()) return; } // récupération du login en fonction de l'attribut AD que l'on va contrôler $attribute = ActiveDirectory::authentification_attribute($conf->get('activedirectory_authentification')); if(isset($infos[$attribute][0])) $user->login = $ldap->attribute_to_login(mb_strtolower($infos[$attribute][0])); if(isset($infos['sn'][0])) $user->setName($infos['sn'][0]); if(isset($infos['givenname'][0])) $user->setFirstName($infos['givenname'][0]); if(isset($infos['mail'][0])) $user->setMail($infos['mail'][0]); if(isset($infos['telephonenumber'][0])) $user->setPhone($infos['telephonenumber'][0]); if(isset($infos['mobile'][0])) $user->setMobile($infos['mobile'][0]); if(isset($infos['title'][0])) $user->setFunction($infos['title'][0]); if(isset($infos['department'][0])) $user->service = $infos['department'][0]; if(isset($infos['thumbnailphoto'][0])) $user->meta['ldap_avatar'] = base64_encode($infos['thumbnailphoto'][0]); if(isset($infos['jpegphoto'][0])) $user->meta['ldap_avatar'] = base64_encode($infos['jpegphoto'][0]); foreach(activedirectory_meta_data() as $data) if(isset($infos[$data['adslug']][0])) $user->meta[$data['slug']] = $infos[$data['adslug']][0]; if(isset($infos['whencreated'][0]) && strlen($infos['whencreated'][0])>=12 ){ $created = substr($infos['whencreated'][0],0,8).' '.substr($infos['whencreated'][0],8,2).':'.substr($infos['whencreated'][0],10,2); $user->created = strtotime($created); } if(isset($infos['manager'][0])){ $user->manager = $infos['manager'][0]; if($loadManager){ $managerEntry = $ldap->userFromCn($infos['manager'][0]); if(isset($managerEntry) && !empty($managerEntry)){ $manager = new User(); ldap_user_fill($ldap,$manager,$managerEntry[0],$loadRight,false); if(isset($managerEntry['sn'][0])) $manager->setName($managerEntry[0]['sn'][0]); if(isset($managerEntry['givenname'][0])) $manager->setFirstName($managerEntry[0]['givenname'][0]); if(isset($managerEntry['mail'][0])) $manager->setMail($managerEntry[0]['mail'][0]); if(isset($managerEntry['telephonenumber'][0])) $manager->setPhone($managerEntry[0]['telephonenumber'][0]); if(isset($managerEntry['mobile'][0])) $manager->setMobile($managerEntry[0]['mobile'][0]); if(isset($managerEntry['title'][0])) $manager->function = $managerEntry[0]['title'][0]; if(isset($managerEntry[$attribute][0])) $manager->login = $ldap->attribute_to_login(mb_strtolower($managerEntry[0][$attribute][0])); $user->manager = $manager; } } } $user->origin = 'active_directory'; if($loadRight){ $groups = array(); if(isset($infos['memberof'])){ for($i=0; $irecursiveGroups($groups,$groupCN); $groups[] = $group; } } $user->groups = $groups; } } function activedirectory_user_save(&$user,$userForm,&$response){ if($user->origin != 'active_directory') return; if($user->login != $userForm->login) throw new Exception("L'identifiant n'est pas modifiable"); global $_,$conf; require_once(__DIR__.SLASH.'ActiveDirectory.class.php'); //Régles de définition de mot de passe if(!empty($userForm->password)){ if(strlen($userForm->password)<7) throw new Exception("Le mot de passe doit être supérieur à 7 caractères"); if(!preg_match('|[0-9]|i', $userForm->password)) throw new Exception("Le mot de passe doit contenir au moins un chiffre"); if(!preg_match('|[a-z]|i', $userForm->password)) throw new Exception("Le mot de passe doit contenir au moins une lettre"); if(!preg_match('|[a-z]|', $userForm->password)) throw new Exception("Le mot de passe doit contenir au moins une lettre Minuscule"); if(!preg_match('|[A-Z]|', $userForm->password)) throw new Exception("Le mot de passe doit contenir au moins une lettre Majuscule"); } $ldap = ldap_instance(true); if($conf->get('activedirectory_admin_login')=='') throw new Exception("Le compte AD admin n'est pas configuré, veuillez contacter un administrateur"); $ldap->connect($conf->get('activedirectory_admin_login'),$conf->get('activedirectory_admin_password')); $cn = $ldap->cnFromLogin($user->login, $conf->get('activedirectory_authentification')); if(!$cn) throw new Exception("Impossible de trouver l'utilisateur dans la base active directory"); $user->phone = $userForm->phone; $user->mobile = $userForm->mobile; $infos = $ldap->search($conf->get('activedirectory_users_root'),$ldap->authentification_filter($user->login, $conf->get('activedirectory_authentification'))); $ldap->set($cn,'telephonenumber',$userForm->phone); $ldap->set($cn,'mobile',$userForm->mobile); $avatarPath = glob(__ROOT__.FILE_PATH.AVATAR_PATH.$user->login.'.*'); if(!empty($avatarPath)){ $avatarPath = $avatarPath[0]; $temp = File::temp().rand(0,10000).basename($avatarPath); copy($avatarPath,$temp); Image::toJpg($temp); $temp = explode('.', $temp); array_pop($temp); $temp = implode('.',$temp).'.jpg'; $ldap->set($cn,'jpegphoto',file_get_contents($temp)); unlink($temp); } if(!empty($userForm->password)){ $ldap->change_password($cn,$userForm->password); $user->preference('passwordTime',time()); } $response['warning'] = 'Vous êtes sur un compte de société, seules les informations suivantes ont été modifiées :
- Téléphone
- Mobile
- Mot de passe (7 caracteres minimum : Majuscules, minucules et chiffres)
- Avatar (JPG uniquement)
'; $ldap->disconnect(); } function user_rank_firm_by_group(&$user){ require_once(__DIR__.SLASH.'ActiveDirectoryGroup.class.php'); global $conf, $myFirm; $firms = array(); $ranks = array(); if(!isset($user->groups)) $user->groups = array(); foreach(ActiveDirectoryGroup::loadAll(array(), null, null, array('*'),1) as $group){ if(!in_array($group->adgroup,$user->groups)) continue; $firm = $group->join('firm'); $rank = $group->join('rank'); if(is_null($firm->id)) continue; $firms[$firm->id] = $firm; if(!isset($ranks[$firm->id])) $ranks[$firm->id] = array(); $ranks[$firm->id][$rank->id] = $rank; } if(empty($ranks) && $conf->get('activedirectory_default_rank')!=''){ foreach(Firm::loadAll() as $firm){ if(!$firm->has_plugin('fr.sys1.activedirectory')) continue; $firms[$firm->id] = $firm; $ranks[$firm->id][$conf->get('activedirectory_default_rank')] = Rank::getById($conf->get('activedirectory_default_rank')); } } if(!empty($ranks)) { $user->setFirms($firms); $defaultFirm = !empty($user->preference('default_firm')) ? $user->preferences['default_firm'] : key($firms); $myFirm = $firms[$defaultFirm]; } $user->ranks = $ranks; $user->loadRights(); } function activedirectory_action(){ global $_; require_once(__DIR__.SLASH.'action.php'); } function activedirectory_plugin_menu(&$settingMenu){ global $_, $myUser; if($myUser->can('activedirectory','configure')) $settingMenu[]= array( 'sort' =>1, 'url' => 'setting.php?section=activedirectory', 'icon' => 'fas fa-angle-right', 'label' => 'Active Directory' ); } function activedirectory_plugin_page(){ global $_; if(in_array($_['section'],array('activedirectory')) && file_exists(__DIR__.SLASH.'setting.'.$_['section'].'.php')) require_once(__DIR__.SLASH.'setting.'.$_['section'].'.php'); } function activedirectory_plugin_section(&$sections){ $sections['activedirectory'] = 'Gestion des droits sur les échanges avec l\'AD'; } function activedirectory_plugin_install($id){ if($id != 'fr.sys1.activedirectory') return; Entity::install(__DIR__); } function activedirectory_plugin_uninstall($id){ if($id != 'fr.sys1.activedirectory') return; Entity::uninstall(__DIR__); } function activedirectory_directory_list(&$usermapping){ foreach ($usermapping as $login => $infos) { $user = $infos['object']; //todo à dynamiser en fct de plugin_activedirectory_metafields if(isset($user->meta['personalPhone'])) $usermapping[$login]['values']['Portable (perso)'] = ''.$user->meta['personalPhone'].''; // if(isset($user->meta['jobstart'])) $usermapping[$login]['values']['Date début contrat'] = $user->meta['jobstart']; } } function activedirectory_account_global(){ global $myUser; ?>
get('activedirectory_metafields'),-1, PREG_SPLIT_NO_EMPTY); $metas = array('label','type','adslug','slug'); foreach($metaFields as $line){ $metaInfos = explode(':',$line); if(count($metaInfos)<4) continue; $lineData = array_combine($metas,$metaInfos); $data[] = $lineData; } return $data; } //Déclaration des settings de base //Types possibles : text,select ( + "values"=> array('1'=>'Val 1'),password,checkbox. Un simple string définit une catégorie. Configuration::setting('activedirectory',array( "Configuration de l'AD", 'activedirectory_server' => array("label"=>"Serveur","type"=>"text","legend"=>"L'adresse IP du serveur AD","placeholder"=>"192.168.XXX.XXX"), 'activedirectory_port' => array("label"=>"Port","type"=>"number","legend"=>"Le port sur lequel attaquer le serveur AD","placeholder"=>"389"), 'activedirectory_ssl_port' => array("label"=>"Port SSL","type"=>"number","legend"=>"Le port SSL sur lequel attaquer le serveur AD","placeholder"=>"636"), 'activedirectory_domain' => array("label"=>"Domaine","type"=>"text","legend"=>"Le domaine sur lequel se base l'AD","placeholder"=>"@EXAMPLE.LOCAL"), 'activedirectory_users_root' => array("label"=>'Racine des utilisateurs Ajouter une racine supplémentaire',"type"=>"text","legend"=>"La racine où chercher les users","placeholder"=>"OU=SYS1,OU=UTILISATEURS,OU=sys1.fr,DC=SYS1,DC=LOCAL","parameters"=>array("data-root"=>"users")), 'activedirectory_groups_root' => array("label"=>'Racine des groupes Ajouter une racine supplémentaire',"type"=>"text","legend"=>"La racine où chercher les groupes","placeholder"=>"OU=SYS1,OU=UTILISATEURS,OU=sys1.fr,DC=SYS1,DC=LOCAL","parameters"=>array("data-root"=>"groups")), "Compte Lecture seule", 'activedirectory_reader_login' => array("label"=>"CN","type"=>"text","legend"=>"Le Common Name du compte de lecture seule","placeholder"=>"CN=reader_account,OU=EXAMPLE,OU=APPLICATIONS,OU=example.fr,..."), 'activedirectory_reader_password' => array("label"=>"Mot de passe","type"=>"password","legend"=>"Le mot de passe du compte de lecture seule","placeholder"=>""), "Compte Administrateur", 'activedirectory_admin_login' => array("label"=>"CN","type"=>"text","legend"=>"Le Common Name du compte administrateur","placeholder"=>"CN=administrator_account,OU=EXAMPLE,OU=APPLICATIONS,OU=example.fr,..."), 'activedirectory_admin_password' => array("label"=>"Mot de passe","type"=>"password","legend"=>"Le mot de passe du compte administrateur","placeholder"=>""), "Champs de méta informations", 'activedirectory_metafields' => array("label"=>"Méta informations","type"=>"textarea","legend"=>"Vous pouvez remplir des méta champs pour les utilisateurs (un champ par ligne).
Ces métas champs sont requis par certains plugins et peuvent être renseignés depuis l'AD via la syntaxe : Libellé:Type:nom-champ-ad:nom-meta","placeholder"=>"Date début contrat:date:description:jobstart","parameters"=>array("cols"=>"100")), "Authentification", 'activedirectory_authentification' => array("label"=>"Authentification via l'attribut","type"=>"select","values"=>array("userprincipalname"=>"userPrincipalName","samaccountname"=>"sAMAccountName"),"default"=>"userprincipalname"), "Utilisateurs de l'AD", 'activedirectory_default_rank' => array("label"=>"Rang par défaut","legend"=>"Utilisé si aucun groupe AD n'a été défini pour le rang \"Utilisateur\" standard","type"=>"rank") )); Plugin::addJs('/js/main.js'); Plugin::addCss('/css/main.css'); Plugin::addHook('directory_list',"activedirectory_directory_list"); Plugin::addHook("account_global", "activedirectory_account_global"); Plugin::addHook("install", "activedirectory_plugin_install"); Plugin::addHook("uninstall", "activedirectory_plugin_uninstall"); Plugin::addHook("user_login", "ldap_plugin_identification"); Plugin::addHook("user_load", "ldap_plugin_all_users"); Plugin::addHook("user_save","activedirectory_user_save"); Plugin::addHook("user_rank_firm", "user_rank_firm_by_group"); Plugin::addHook("section", "activedirectory_plugin_section"); Plugin::addHook("action", "activedirectory_action"); Plugin::addHook("menu_setting", "activedirectory_plugin_menu"); Plugin::addHook("content_setting", "activedirectory_plugin_page"); ?>