Простое управление пользователями AD через Веб-интерфейс

В одной из обслуживаемых мной организаций однажды началась весьма заметная ротация кадров, в связи с чем я решил процесс создания и блокирования пользователей 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, а сам сервер должен быть «привязан» к домену.

 

 

 

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *