В одной из обслуживаемых мной организаций однажды началась весьма заметная ротация кадров, в связи с чем я решил процесс создания и блокирования пользователей AD возложить на отдел кадров. Понятное дело, что прямиком на сервер запускать HRов можно только под угрозой смертной казни, поэтому решил выкрутится из ситуации созданием странички на PHP, в котором будут необходимые поля для заполнения и кнопочки для нажимания, понятные простым смертным, далеким от понимания того, что они делают на самом деле. C PHP я знаком только в том ключе, что я знаю, что он есть, специально ему не обучался, поэтому дергал по интернету разные конструкции и собирал воедино то, что мне было необходимо, а потом более-менее приводил в порядок.
На данный момент, скрипт поддерживает AD авторизацию через модуль Apache с соответствующим ограничением свободы действий авторизованного пользователя. По сути в скрипте указываются две группы — администраторы и отдел кадров, в которых указываются учётные записи AD, которым доступны соответствующие функции скрипта. Всем остальным доступ запрещён. Скрипт прописывает в учётную запись имя и фамилию пользователя и заполняет поля e-mail, мобильный телефон, должность, отдел, организация и поле «Область, Край», которое в моём случае обозначает офис компании. Также пользователи добавляются в обязательные группы AD, которые указываются в переменных скрипта, и в группу AD, соответствующую офису, к которому «приписывается» пользователь.
Также можно редактировать некоторые свойства учётной записи, менять пароль, блокировать, разблокировать и удалять учётную запись. Функции установки и смены пароля работают, только если включен протокол LDAPS на контроллере домена, к которому подключается скрипт. Также необходимо создать специальную учетную запись с правами управления учётными записями в домене, от имени которой и будет выполняться управление пользователями из скрипта.
Интерфейс выглядит так:
Скрипт «заточен» под конкретную организацию, но на его основе Вы можете сделать свой скрипт — универсальный или заточенный под Вашу компанию. Для работы скрипта необходимо включить модули PHP mbstring, ldap и openssl.
В файл /etc/openldap/ldap.conf надо добавить строку:
# Instruct client to NOT request a server's cert.
TLS_REQCERT never
Сам OpenLDAP должен быть установлен =)
Итак, текст скрипта:
<?php ini_set('display_errors','On'); error_reporting(E_ALL | E_STRICT); /* Parameters */ $groupadmin = array("admin","director"); // пользователи "группы админов", указываются учётки из AD $grouphr = array("kadry","pupkin"); // пользователи "отдела кадров", указываются учётки из AD $basedn = "DC=domain,DC=local"; // домен AD в формате LDAP поиска $OU = "CN=Users"; // OU в домене, в которой ищем и создаем пользователей, тоже в формате LDAP поиска $ldap_host = "ldaps://dc.domain.local"; // LDAPS сервер к которому подключаемся $ldap_user = "domain\operator"; // специальная учётная запись, с которой авторизуемся по LDAPS $ldap_pass = "SeCrEt"; // пароль специальной учётной записи $newuserdomain = "DOMAIN"; // домен, в котором создаём новых пользователей $newpassword = gen_pass(8); // пароль для новых учётных записей. gen_pass(8) создаёт случайный пароль из 8-ми символов $orgs = array('ООО "Компания 1"','ООО "Компания 2"'); // список юр.лиц компании $offices = array("Главный офис","Доп. офис"); // список офисов $officesgroups = array("sokol","peshki"); // список групп в AD, соответствующих по порядку списку офисов, группы должны быть созданы заранее. $addtogroups = array("all","inet_users","JabberUsers"); // список групп в AD, в которые надо добавлять всех создаваемых пользователей, группы должны быть созданы заранее. $usersbasedn = $OU.",".$basedn; /* Функция генерирования пароля */ function gen_pass($number) { /* можно использовать все доступные символы $arr = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','r','s','t','u','v','x','y','z', 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','R','S','T','U','V','X','Y','Z', '1','2','3','4','5','6','7','8','9','0', '.',',','(',')','[',']','!','?','&','^','%','@','*','$','<','>','/','|','+','-','{','}','`','~'); */ // а можно использовать и только те, которые хочется $arr = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','r','s','t','u','v','x','y','z', 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','R','S','T','U','V','X','Y','Z', '1','2','3','4','5','6','7','8','9','0'); // Генерируем пароль $pass = ""; for ($i = 0; $i < $number; $i++) { $index = rand(0, count($arr) - 1); $pass .= $arr[$index]; } return $pass; } /* Функция транслитерации кириллицы */ function translit($text) { $alphabet_ru = array ( 'ё','й','ц','у','к','е','н','г', 'ш','щ','з','х','ъ','ф','ы','в', 'а','п','р','о','л','д','ж','э', 'я','ч','с','м','и','т','ь','б','ю', 'Ё','Й','Ц','У','К','Е','Н','Г', 'Ш','Щ','З','Х','Ъ','Ф','Ы','В', 'А','П','Р','О','Л','Д','Ж','Э', 'Я','Ч','С','М','И','Т','Ь','Б','Ю', ' ' ); $alphabet_eng = array ( 'e','i','ts','u','k','e','n','g', 'sh','sch','z','h','','f','y','v', 'a','p','r','o','l','d','j','e', 'ya','ch','s','m','i','t','','b', 'yu', 'E','I','Ts','U','K','E','N','G', 'Sh','Sch','Z','H','','F','Y','V', 'A','P','R','O','L','D','J','E', 'Ya','Ch','S','M','I','T','','B', 'Yu', '_' ); return str_replace($alphabet_ru, $alphabet_eng, $text); } echo "<head><title>Управление пользователями</title><meta charset='UTF-8'></head>"; echo "<body bgcolor=#cccccc>"; echo "<style> .errors {margin:10px 0px; background: #ffaaaa; border: 3px dotted red; padding:10px; position: fixed; top: 420px; left: 100px; height: 100px; width: 350px } .success {margin:10px 0px; background: #aaffaa; border: 3px dotted green; padding:10px; position: fixed; top: 420px; left: 100px; height: 100px; width: 350px } .success_big {margin:10px 0px; background: #aaffaa; border: 3px dotted green; padding:10px; position: fixed; top: 420px; left: 100px; height: 300px; width: 400px } </style>"; /* Open connection */ $accessallowed = 0; $connect = ldap_connect($ldap_host) or die( "Could not connect!" ); ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($connect, LDAP_OPT_REFERRALS, 0); $bind = ldap_bind($connect, $ldap_user, $ldap_pass) or print'<meta http-equiv="refresh" content="1; url='.$_SERVER["PHP_SELF"].'">'; if (isset($_SERVER["REDIRECT_REMOTE_USER"])) { $remuser = substr(strstr($_SERVER["REDIRECT_REMOTE_USER"], "\\",false),1); $filter = "(samaccountname=".$remuser.")"; $sr = ldap_search($connect, $basedn, $filter) or die("ldap search failed"); $ent = ldap_get_entries($connect,$sr); if (in_array($remuser, $groupadmin)) { echo '<font size=5 color=#33aa33> Вы авторизованы под именем "' . $ent[0]["displayname"][0] . '"</font><br />'; echo '<font size=5 color=#33aa33> Уровень доступа: администратор</font><br />'; $accessallowed = 1; } elseif (in_array($remuser, $grouphr)) { echo '<font size=5 color=#33aa33> Вы авторизованы под именем "' . $ent[0]["displayname"][0] . '"</font><br />'; echo '<font size=5 color=#33aa33> уровень доступа: отдел кадров</font><br />'; $accessallowed = 1; } else { echo '<font size=5 color=#888888> Вы авторизованы под именем "' . $ent[0]["displayname"][0] . '"</font><br />'; echo '<font size=5 color=#880000>ДОСТУП К УПРАВЛЕНИЮ ПОЛЬЗОВАТЕЛЯМИ ЗАПРЕЩЁН</font><br />'; } } /* Input check */ $errors = ''; $arr = array("new_employee" => "", "edit_employee" => "", "old_employee" => "", "save" => "", "family_name" => "Фамилия", "first_name" => "Имя", "tel_num" => "Номер мобильного телефона", "position" => "Должность", "organization" => "Организация", "dep" => "Подразделение", "office" => "Офис"); if(isset($_POST['new_employee'])) { foreach($_POST as $key => $value) { if('' == $value || $arr[$key] == $value) {$errors .= 'Поле "'.$arr[$key].'" не заполнено<br/>'; break;} else {$$key = trim($value);} } /* Creating employee */ if('' == $errors) { $trans_family_name = translit($family_name); $trans_first_name = translit($first_name); $account = strtolower($trans_family_name); $newuser["cn"] = $first_name.' '.$family_name; $newuser["objectclass"][0] = "top"; $newuser["objectclass"][1] = "person"; $newuser["objectclass"][2] = "organizationalPerson"; $newuser["objectclass"][3] = "user"; $newuser["displayname"] = $first_name.' '.$family_name; $newuser["givenname"] = $first_name; $newuser["name"] = $first_name.' '.$family_name; $newuser["sn"] = $family_name; $newuser["department"] = $dep; $newuser["mobile"] = $tel_num; $newuser["mail"] = $account."@plamya-ei.ru"; $newuser["title"] = $position; $newuser["company"] = $organization; $newuser["st"] = $office; $newuser["sAMAccountName"] = $account; $newuser["userPrincipalName"] = $account.'@'.$newuserdomain; $newuser["useraccountcontrol"] = 544; $dn = 'CN=' . $newuser['cn'] . ',' . $usersbasedn; $result = ldap_add($connect, $dn, $newuser); if($result) { $newadpass = "\"" . $newpassword . "\""; $newPass = mb_convert_encoding($newadpass, "UTF-16LE"); $pwdarr = array('unicodePwd' => $newPass); $result = ldap_modify ($connect, $dn, $pwdarr); if($result) { for ($i = 0; $i < count($offices); $i++) { if ($offices[$i] == $office) { array_push($addtogroups,$officesgroups[$i]); } } $group_info['member'] = $dn; for ($i = 0; $i < count($addtogroups); $i++) { $group_name = "CN=".$addtogroups[$i].",".$usersbasedn; $result = ldap_mod_add($connect,$group_name,$group_info); } } if($result) { echo "<div class='success_big'><font size=5>Добавлен новый сотрудник:</font><br /> ".$arr['first_name'].": ".$first_name." <br/> ".$arr['family_name'].": ".$family_name." <br/> ".$arr['tel_num'].": ".$tel_num." <br/> ".$arr['position'].": ".$position." <br/> ".$arr['dep'].": ".$dep." <br/> ".$arr['organization'].": ".$organization." <br/> ".$arr['office'].": ".$office." <br/> <br/> <font size=5>Данные учетной записи сотрудника:</font> Имя пользователя: FLAME\\".$account."<br/> Электронная почта: ".$account."@plamya-ei.ru<br/> Пароль: " . $newpassword . "<br/></div>"; } else { $errors = ldap_error($connect); } } } } if (isset($_POST['employee'])) { if (isset($_REQUEST['block'])) { foreach($_POST as $key => $value) { if('' == $value || "Пользователь (Должность)" == $value) {$errors .= 'Не выбран пользователь для блокировки<br/>'; break;} else {$$key = $value;} } if('' == $errors){ $user = strstr($user, " (", true); $result = userblock($user,0,$ldap_user,$ldap_pass,$ldap_host,$basedn); if($result == 0) { echo "<div class='success'><font size=5>Пользователь заблокирован:</font></br></br>"; echo $user."<br /></div>"; } } } if (isset($_REQUEST['edit'])) { foreach($_POST as $key => $value) { if('' == $value || "Пользователь (Должность)" == $value) {$errors .= 'Не выбран пользователь для редактирования<br/>'; break;} else {$$key = $value;} } if('' == $errors){ $user = strstr($user, " (", true); $filter = "(displayName=".$user.")"; $sr = ldap_search($connect, $basedn, $filter) or die("ldap search failed"); $ent = ldap_get_entries($connect,$sr); if (!isset($ent[0]["givenname"][0])) $ent[0]["givenname"][0] = $arr["first_name"]; if (!isset($ent[0]["sn"][0])) $ent[0]["sn"][0] = $arr["family_name"]; if (!isset($ent[0]["mobile"][0])) $ent[0]["mobile"][0] = $arr["tel_num"]; if (!isset($ent[0]["title"][0])) $ent[0]["title"][0] = $arr["position"]; if (!isset($ent[0]["company"][0])) $ent[0]["company"][0] = $arr["organization"]; if (!isset($ent[0]["department"][0])) $ent[0]["department"][0] = $arr["dep"]; if (!isset($ent[0]["st"][0])) $ent[0]["st"][0] = $arr["office"]; echo ' <style> #create { display:none; } #block { display:none; } #edit { display:none; } #changepass { display:none; } #unblock { display:none; } #remove { display:none; } </style> <table style="position:absolute; top:150px; left:420px; z-index:2; text-align: left; background-color: #dddddd; border: ridge 3px #999999; width: 450px" border="1" cellpadding="4" cellspacing="0"><tr><td width=400 rowspan="2"> <form method="POST" action="'.$_SERVER['REQUEST_URI'].'"> <input type="hidden" name="edit_employee" value="1" /> <input type="hidden" name="old_employee" value="'.$ent[0]["samaccountname"][0].'" /> <h3> Редактировать сотрудника:</h3> <input type="text" name="first_name" value="'.$ent[0]["givenname"][0].'" size="20" /> <input type="text" name="family_name" value="'.$ent[0]["sn"][0].'" size="25" /> <br/> <br/> <input type="tel" placeholder="+7 (999) 111-22-33" name="tel_num" value="'.$ent[0]["mobile"][0].'" size="25" /> формат: +7 (999) 111-22-33<br/> <br/> <input type="text" name="position" value="'.$ent[0]["title"][0].'" size="50" /> <br/> <br/> <select name="organization" placeholder=$ent[0]["company"][0]><option>'.$ent[0]["company"][0].'</option> <option>'.$orgs[0].'</option> <option>'.$orgs[1].'</option> </select> <br/> <br/> <div> <select name="dep"><option>'.$ent[0]["department"][0].'</option> '.build_spoiler($ldap_host,$basedn,$ldap_user,$ldap_pass).' </div> <br/> <select name="office"><option>'.$ent[0]["st"][0].'</option> <option>'.$offices[0].'</option> <option>'.$offices[1].'</option> </select> <br/><br/><br/> <input type="submit" value="Изменить" name="save" /> <input type="submit" value="Отменить" name="cancel" formnovalidate /> </form> </td></tr></table>'; } } if (isset($_REQUEST['password'])) { foreach($_POST as $key => $value){ if("Пользователь (Должность)" == $value) {$errors .= 'Не выбран пользователь для смены пароля<br/>'; break;} else {$$key = $value;} } if('' == $errors) { $newpass = $newpassword; $user = strstr($user, " (", true); $filter = "(cn=".$user.")"; $sr = ldap_search($connect, $basedn, $filter) or die("ldap search failed"); $ent = ldap_get_entries($connect,$sr); $dn = $ent[0]["dn"]; echo ' <style> #create { display:none; } #block { display:none; } #edit { display:none; } #changepass { display:none; } #unblock { display:none; } #remove { display:none; } </style> <table style="position:absolute; top:150px; left:420px; z-index:2; text-align: left; background-color: #dddddd; border: ridge 3px #999999; width: 300px" border="1" cellpadding="10" cellspacing="0"><tr><td rowspan="2"> <form method="POST" action="'.$_SERVER['REQUEST_URI'].'"> <input type="hidden" name="change_pass" value="1" /> <input type="hidden" name="employee" value="'.$user.'" /> <h3> Введите новый пароль:</h3> Пользователь: ' . $user . '</br></br> Сгенерированный пароль: '.$newpass.'</br></br> <input type="password" name="pass1" placeholder="Введите пароль" size="25" minlength="6" maxlength="20" pattern=".{6,20}" title="Введите от 6 до 20 символов (букв и\или цифр)" required /></br></br> <input type="password" name="pass2" placeholder="Введите пароль повторно" size="25" minlength="6" maxlength="20" pattern=".{6,20}" title="Введите от 6 до 20 символов (букв и\или цифр)" required /> <br/></br> <input type="submit" value="Установить пароль" name="savepass" /> <input type="submit" value="Отменить" name="cancel" formnovalidate /> </form> </td></tr></table>'; } } } if(isset($_POST['change_pass'])) { if (isset($_REQUEST['savepass'])) { foreach($_POST as $key => $value){ $$key = $value; } if ($pass1 != $pass2) { $errors .= 'Введённые пароли не совпадают!!!<br/>';} else { $pass = $pass1; if('' == $pass) {$errors .= 'Пароль не может быть пустым!!!<br/>';} } if ('' == $errors) { $newpass = "\"" . $pass . "\""; $newpass = mb_convert_encoding($newpass, "UTF-16LE"); $pwdarr = array('unicodePwd' => $newpass); $filter = "(cn=".$employee.")"; $sr = ldap_search($connect, $basedn, $filter) or die("ldap search failed"); $ent = ldap_get_entries($connect,$sr); $dn = $ent[0]["dn"]; $result = ldap_modify ($connect, $dn, $pwdarr); if($result) { echo "<div class='success'><font size=5>Пароль успешно изменён!</font><br /> <br /> Имя пользователя: FLAME\\".$ent[0]['samaccountname'][0]."<br/> Электронная почта: ".$ent[0]['mail'][0]."<br/> Пароль: " . $pass . "<br/></div>"; } else { $errors = ldap_error($connect); } } } } if(isset($_POST['edit_employee'])) { if (isset($_REQUEST['save'])) { foreach($_POST as $key => $value) { if($arr[$key] == $value) {$errors .= 'Поле "'.$arr[$key].'" не заполнено<br/>'; break;} else {$$key = $value;} } /* Edit employee */ if('' == $errors) { $editcn["cn"] = $first_name.' '.$family_name; $edituser["displayname"] = $first_name.' '.$family_name; $edituser["givenname"] = $first_name; $edituser["sn"] = $family_name; $edituser["department"] = $dep; $edituser["mobile"] = $tel_num; $edituser["title"] = $position; $edituser["company"] = $organization; $edituser["st"] = $office; for ($i = 0; $i < count($offices); $i++) { if ($offices[$i] == $office) { $group = $officesgroups[$i]; } } $filter = "(sAMAccountname=".$old_employee.")"; $sr = ldap_search($connect, $basedn, $filter) or die("ldap search failed"); $ent = ldap_get_entries($connect,$sr); $dn = $ent[0]["dn"]; $group_info['member'] = $dn; for ($i = 0; $i < count($offices); $i++) { $filter = "(&(sAMAccountName=".$old_employee.")(memberOf=cn=".$officesgroups[$i].",".$usersbasedn."))"; $sr = ldap_search($connect, $basedn, $filter); $ent = ldap_get_entries($connect,$sr); if ($ent['count'] != 0) { $group_name = "CN=".$officesgroups[$i].",".$usersbasedn; $result = ldap_mod_del($connect,$group_name,$group_info); } if ($offices[$i] == $office) { $group = $officesgroups[$i]; } } $filter = "(sAMAccountname=".$old_employee.")"; $sr = ldap_search($connect, $basedn, $filter) or die("ldap search failed"); $ent = ldap_get_entries($connect,$sr); $group_name = "CN=".$group.",".$usersbasedn; $group_info['member'] = $dn; $result = ldap_mod_add($connect,$group_name,$group_info); $dn = $ent[0]["dn"]; $result=ldap_mod_replace($connect, $dn, $edituser); $str = 'cn='.$first_name.' '.$family_name; $result = ldap_rename($connect, $dn, $str, NULL, true); if($result) { $filter = $filter = "(sAMAccountName=".$old_employee.")"; $result = ldap_search($connect, $basedn, $filter); $ent = ldap_get_entries($connect,$result); echo "<div class='success_big'><font size=5>Новые данные сотрудника:</font><br /> ".$arr['first_name'].": ".$ent[0]['givenname'][0]." <br/> ".$arr['family_name'].": ".$ent[0]['sn'][0]." <br/> ".$arr['tel_num'].": ".$ent[0]['mobile'][0]." <br/> ".$arr['position'].": ".$ent[0]['title'][0]." <br/> ".$arr['dep'].": ".$ent[0]['department'][0]." <br/> ".$arr['organization'].": ".$ent[0]['company'][0]." <br/> ".$arr['office'].": ".$ent[0]['st'][0]." <br/> <br/> <font size=5>Учетная запись сотрудника:</font><br /> Имя пользователя: FLAME\\".$ent[0]['samaccountname'][0]."<br/> Электронная почта: ".$ent[0]['samaccountname'][0]."@plamya-ei.ru<br/></div>"; } else { $errors = ldap_error($connect); } } } } if(isset($_POST['blocked_employee'])) { if (isset($_REQUEST['unblock'])) { foreach($_POST as $key => $value){ if("Пользователь (Должность)" == $value) {$errors .= 'Не выбран пользователь для разблокировки<br/>'; break;} else {$$key = $value;} } if('' == $errors) { $user = strstr($user, " (", true); $result = userblock($user,1,$ldap_user,$ldap_pass,$ldap_host,$basedn); if($result == 1) { echo "<div class='success'><font size=5>Пользователь разблокирован:</font></br></br>"; echo $user."<br /></div>"; } } } if (isset($_REQUEST['remove'])) { foreach($_POST as $key => $value){ if("Пользователь (Должность)" == $value) {$errors .= 'Не выбран пользователь для удаления<br/>'; break;} else {$$key = $value;} } if('' == $errors) { $user = strstr($user, " (", true); $filter = "(displayName=".$user.")"; $sr = ldap_search($connect, $basedn, $filter) or die("ldap search failed"); $ent = ldap_get_entries($connect,$sr); $dn = $ent[0]["dn"]; $result = ldap_delete($connect,$dn); if($result) { echo "<div class='success'><font size=5>Пользователь удален:</font></br></br>"; echo $user."<br /></div>"; } else { $errors = ldap_error($connect); } } } } if('' != $errors) {echo '<div class="errors"><font color="red" size=5>Ошибка:</font><br /><br />'.$errors.'</div>';} function userblock($username,$state,$domadlogin,$domadpw,$ldapServer,$ldapBase) { $ds = ldap_connect($ldapServer) or die('Cannot Connect to LDAP server'); ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($ds, LDAP_OPT_REFERRALS, 0) or die ("Could not set ldap protocol"); ldap_bind($ds,$domadlogin,$domadpw) or print'<meta http-equiv="refresh" content="1; url='.$_SERVER["PHP_SELF"].'">'; $filter = "(displayName=".$username.")"; $sr = ldap_search($ds, $ldapBase, $filter) or die("ldap search failed"); $ent= ldap_get_entries($ds,$sr); $dn = $ent[0]["dn"]; $ac = $ent[0]["useraccountcontrol"][0]; $disable=($ac | 2); // set all bits plus bit 1 (=dec2) $enable =($ac & ~2); // set all bits minus bit 1 (=dec2) $userdata=array(); if ($state==1) $new=$enable; else $new=$disable; //enable or disable? $userdata["useraccountcontrol"][0]=$new; $result = ldap_modify($ds, $dn, $userdata); //change state if ($result){ $sr = ldap_search($ds, $ldapBase, $filter); $ent= ldap_get_entries($ds,$sr); $ac = $ent[0]["useraccountcontrol"][0]; if (($ac & 2)==2) $status=0; else $status=1; } else { $status = ldap_error($ds); } ldap_close($ds); return $status; //return current status (1=enabled, 0=disabled or errors) } function build_spoiler($host,$dn,$user,$pswd) { $result = ""; $ad = ldap_connect($host) or die( "Could not connect!" ); ldap_set_option($ad, LDAP_OPT_PROTOCOL_VERSION, 3) or die ("Could not set ldap protocol"); ldap_set_option($ad, LDAP_OPT_REFERRALS, 0) or die ("Could not set ldap protocol"); ldap_bind($ad, $user, $pswd) or print'<meta http-equiv="refresh" content="1; url='.$_SERVER["PHP_SELF"].'">'; $attrs = array("displayname","mail","telephonenumber","department"); $filter = "(department=*)"; $search = ldap_search($ad, $dn, $filter, $attrs) or die ("ldap search failed"); $entries = ldap_get_entries($ad, $search); if ($entries["count"] > 0) { for ($i=0; $i<$entries["count"]; $i++) { $arrresult[] = $entries[$i]["department"][0]; } natcasesort($arrresult); foreach ($arrresult as $i => $value) { if (stripos($result, $arrresult[$i]) == FALSE) { $result .= '<option>'.$arrresult[$i].'</option>'; } } } $result .= '</select>'; ldap_close($ad); return $result; } function build_spoiler_users($host,$dn,$user,$pswd,$active) { $result = ""; $ad = ldap_connect($host) or die( "Could not connect!" ); ldap_set_option($ad, LDAP_OPT_PROTOCOL_VERSION, 3) or die ("Could not set ldap protocol"); ldap_set_option($ad, LDAP_OPT_REFERRALS, 0) or die ("Could not set ldap protocol"); ldap_bind($ad, $user, $pswd) or print'<meta http-equiv="refresh" content="1; url='.$_SERVER["PHP_SELF"].'">'; $attrs = array("displayname","title"); if ($active == 'active') { $filter = "(&(objectCategory=person)(objectClass=user)(sn=*)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"; } if ($active == 'blocked') { $filter = "(&(objectCategory=person)(objectClass=user)(sn=*)(userAccountControl:1.2.840.113556.1.4.803:=2))"; } $search = ldap_search($ad, $dn, $filter, $attrs) or die ("ldap search failed"); $entries = ldap_get_entries($ad, $search); if ($entries["count"] > 0) { for ($i=0; $i<$entries["count"]; $i++) { if (!isset($entries[$i]["title"][0])) { $entries[$i]["title"][0] = "Не указана"; } $arrresult[] = $entries[$i]["displayname"][0]." (".$entries[$i]["title"][0].")"; } natcasesort($arrresult); foreach ($arrresult as $i => $value) { $result .= '<option>'.$arrresult[$i].'</option>'; } } $result .= '</select>'; ldap_close($ad); return $result; } function build_spoiler_OU($host,$dn,$user,$pswd) { $result = ""; $ad = ldap_connect($host) or die( "Could not connect!" ); ldap_set_option($ad, LDAP_OPT_PROTOCOL_VERSION, 3) or die ("Could not set ldap protocol"); ldap_set_option($ad, LDAP_OPT_REFERRALS, 0) or die ("Could not set ldap protocol"); ldap_bind($ad, $user, $pswd) or print'<meta http-equiv="refresh" content="1; url='.$_SERVER["PHP_SELF"].'">'; $attrs = array("displayname","mail","telephonenumber","department"); $filter = "(department=*)"; $search = ldap_search($ad, $dn, $filter, $attrs) or die ("ldap search failed"); $entries = ldap_get_entries($ad, $search); if ($entries["count"] > 0) { for ($i=0; $i<$entries["count"]; $i++) { $arrresult[] = $entries[$i]["department"][0]; } natcasesort($arrresult); foreach ($arrresult as $i => $value) { if (stripos($result, $arrresult[$i]) == FALSE) { $result .= '<option>'.$arrresult[$i].'</option>'; } } } $result .= '</select>'; ldap_close($ad); return $result; } if ($accessallowed == 1) { echo ' <table id="main" height=320 style="position:absolute; top:100px; left:50px; z-index:1; text-align: left; background-color: #eeeeee;" border="1" cellpadding="4" cellspacing="0"><tr><td width=400 rowspan="2" align=left valign=top > <form id="main_form" method="POST" action="'.$_SERVER['REQUEST_URI'].'"> <input type="hidden" name="new_employee" value="1" /> <h3>Добавить нового сотрудника:</h3> <input id="name" type="text" name="first_name" placeholder="'.$arr["first_name"].'" size="20" required /> <input id="family_name" type="text" name="family_name" placeholder="'.$arr["family_name"].'" size="25" required /> <br/> <br/> <input type="tel" pattern="\+7\s?[\(][0-9]{3}[\)]{0,1}\s?\d{3}[-]{0,1}\d{2}[-]{0,1}\d{2}" placeholder="+7 (999) 111-22-33" name="tel_num" placeholder="'.$arr["tel_num"].'" size="23" required /> формат: +7 (999) 111-22-33 <br/> <br/> <input type="text" name="position" placeholder="'.$arr["position"].'" size="50" required /> <br/> <br/> <select name="organization"><option>'.$arr["organization"].'</option> <option>'.$orgs[0].'</option> <option>'.$orgs[1].'</option> </select> <br/> <br/> <div> <select name="dep"><option>'.$arr["dep"].'</option> '.build_spoiler($ldap_host,$basedn,$ldap_user,$ldap_pass).' </div> <br/> <select name="office"><option>'.$arr["office"].'</option> <option>'.$offices[0].'</option> <option>'.$offices[1].'</option> </select> <br/><br/> <input id="create" type="submit" value="Добавить пользователя" /> </form> <th width=400 align=left valign=top height=50%> <form method="POST" action="'.$_SERVER['REQUEST_URI'].'"> <input type="hidden" name="employee" value="1" /> <h3>Активные пользователи:</h3> <div> <select name="user"><option>Пользователь (Должность)</option> '.build_spoiler_users($ldap_host,$basedn,$ldap_user,$ldap_pass,"active").' </div><br /> <input id="block" type="submit" value="Заблокировать" name="block" /> <input id="edit" type="submit" value="Редактировать" name="edit" />'; if (in_array($remuser, $groupadmin)) { echo ' <input id="changepass" type="submit" value="Сменить пароль" name="password" />'; } else { echo ' <input id="changepass" type="submit" value="Сменить пароль" name="password" disabled />'; } echo '</form> </th></tr><tr><th align=left valign=top> <form method="POST" action="'.$_SERVER['REQUEST_URI'].'"> <input type="hidden" name="blocked_employee" value="1" /> <h3>Заблокированные пользователи:</h3> <div> <select name="user"><option>Пользователь (Должность)</option> '.build_spoiler_users($ldap_host,$basedn,$ldap_user,$ldap_pass,"blocked").' </div><br /> <input id="unblock" type="submit" value="Разблокировать" name="unblock" />'; if (in_array($remuser, $groupadmin)) { echo ' <input id="remove" type="submit" value="Удалить" name="remove" onclick="return confirm(\'Вы уверены, что хотите удалить пользователя?\n\nВНИМАНИЕ!!!\nВосстановление пользователя будет невозможно!!!\')" />'; } else { echo ' <input id="remove" type="submit" value="Удалить" name="remove" onclick="return confirm(\'Вы уверены, что хотите удалить пользователя?\n\nВНИМАНИЕ!!!\nВосстановление пользователя будет невозможно!!!\')" disabled />'; } echo '</form> </th></tr></table>'; } /* Close connection */ ldap_close($connect); echo "</body>"; ?>
Чтобы работала авторизация в AD, необходимо в настройках Apache включить модуль auth_ntlm_winbind и добавить в конфиг следующие настройки:
<Directory "/var/www/ad"> AllowOverride all AuthType NTLM NTLMAuth on NTLMAuthHelper "/usr/bin/ntlm_auth --helper-protocol=squid-2.5-ntlmssp" NTLMBasicAuthoritative on require user DOMAIN\\admin DOMAIN\\kadry DOMAIN\\director DOMAIN\\pupkin </Directory>
Само собой разумеется, что на сервере должен быть установлен Winbind, а сам сервер должен быть «привязан» к домену.