LDAP аутентификация (Active Directory)

Мучался я с этой фигней долго, но... я победил! И поскольку не я один такой то вот мой рецепт:

- Во-первых. Встроеная LDAP-аутентификация - полный отстой. Соединение-то устанавливается, а вот привязка не проходит. Автор,судя по всему, привязывается анонимусом, а для для AD все равно что ничего. Привязаться можно только от имени зарегистрированного в домене пользователя.

- Во-вторых. Аутентифицировать пользователя в AD совсем не то, что в, допустим, OpenLDAP. AD не вернет тебе пароль пользователя. Посему - просто взять пароль из AD и сравнить с тем, что загнал пользователь в eJabberD не получится. Но, такое впечатление, что eJabberD это и делает.

Вывод: на сейчас (0.7.5) можно аутентифицировать зверей тока через внешний скрипт. Причем та заготовка что валяется на сайтах (check_pass_null.pl) хорошая точка отсчета, но не более того.
Вот полный исходник моего скрипта. Умный да разберется.

#######################################
# Name : check_pass_win32.pl
# Data : 10.04.2005
# Decription : Внешняя аутентификация пользователей
# : системы мнгновенных сообщений Jabber
# Author : Игорь С. Коваленко
#############################################################################################

use Win32::NetAdmin;
use Win32::OLE;
use Win32::OLE::Variant;

my $domain = $ENV{UserDomain};
my $server = $ENV{ComputerName};

# Дополнительное условие: пользователь входит в группу AccessGroup
$AccessGroup = "Domain Users";

while(1)
{

my $nread;
my $buf = "";

$nread = sysread STDIN,$buf,2;

do {
exit;
}
unless $nread == 2;

my $len = unpack "n",$buf;
$nread = sysread STDIN,$buf,$len;

my ($op,$user,$password) = split /:/,$buf;

my $result;

my $DC;
Win32::NetAdmin::GetDomainController($server, $domain, $DC);

SWITCH:
{
$op eq 'auth' and do
{

if (Win32::NetAdmin::GroupIsMember($DC, $AccessGroup, $user)) {
# Если пользователь член группы AccessGroup ...
my $oRoot = Win32::OLE->GetObject("LDAP:");
$Status = $oRoot->OpenDSObject("LDAP://$domain", $user, $password, 0x1);
if (defined $Status) {
# ... и удается от его имени привязаться к корню AD ...
undef $Status;
$result = 1;
# ... то говорим, что пользователь аутентифицирован!
}
}

},last SWITCH;

$op eq 'setpass' and do
{
$result = 1;
},last SWITCH;

$op eq 'isuser' and do
{
if (Win32::NetAdmin::UsersExist($DC, $user)) {
$result = 1;
}

},last SWITCH;
};
my $out = pack "nn",2,$result ? 1 : 0;
syswrite STDOUT,$out;
}

И, да, чуть не забыл: что бы это работало, сервис eJabberD должен стартовать от пользовательской учетной записи. От имени локальной системы нельзя. Ее (локальную систему) AD не знает.

Удачи!

Столько времени прошло...

Сейчас актуальна версия eJabberD 1.0, уважаемый Olos прислал мне такой скриптик, который теоретически должен быть с ней совместим:

#############################################################################
# Name : check_pass_win32.pl
# Data : 10.04.2005
# Decription : Внешняя аутентификация пользователей
# : системы мнгновенных сообщений Jabber
# Author : Игорь С. Коваленко
#############################################################################

use Win32::NetAdmin;
use Win32::OLE;
use Win32::OLE::Variant;

# Здесь указывается домен измените MyDomain на имя вашего домена
my $domain = "YourDomain.ru";
# Здесь можно указать имя хоста, но лучше указать DC
my $server = "YourServer.YourDomain.ru";

# Дополнительное условие: пользователь входит в группу AccessGroup
$AccessGroup = "Domain Users";

while(1)
{

my $nread;
my $buf = "";

$nread = sysread STDIN,$buf,2;

do {
exit;
}
unless $nread == 2;

my $len = unpack "n",$buf;
$nread = sysread STDIN,$buf,$len;

# Параметр $host добавлен для версий > 0.9.1
my ($op,$user,$host,$password) = split /:/,$buf;

my $result;

my $DC;
Win32::NetAdmin::GetDomainController($server, $domain, $DC);
#my $DC = "10.1.2.129";

SWITCH:
{
$op eq 'auth' and do
{

if (Win32::NetAdmin::GroupIsMember($DC, $AccessGroup, $user)) {
# Если пользователь член группы AccessGroup ...
my $oRoot = Win32::OLE->GetObject("LDAP:");
$Status = $oRoot->OpenDSObject("LDAP://$domain", $user, $password, 0x1);
if (defined $Status) {
# ... и удается от его имени привязаться к корню AD ...
undef $Status;
$result = 1;
# ... то говорим, что пользователь аутентифицирован!
}
}

},last SWITCH;

$op eq 'setpass' and do
{
$result = 1;
},last SWITCH;

$op eq 'isuser' and do
{
if (Win32::NetAdmin::UsersExist($DC, $user)) {
$result = 1;
}

},last SWITCH;
};
my $out = pack "nn",2,$result ? 1 : 0;
syswrite STDOUT,$out;
}

========================
Кто-либо пробовал его? Получилось?

Замеченные траблы

Этот скрипт пашет (кажись!) криво в сетях 2k, где NetBios-имя домена отличается от натив имени того же домена. Пример: домен как NetBios звучал у меня 'centralbuh', но native было 'central.com' И скрипт там пахал... ну-уу-у-у... странновато. Зато на другой конторе - все ОК! А отличия были тока в этом.
Да и вот еще... какие-то траблы перли в сетях 2k3 с полным натив 2003 (там где все контроллеры 2003-е). Там были глюки с привязкой к АД.
Я, пожалуй. разберусь со всем этим на досуге, а уважаемый Olos... он бы лучше доку подкинул о скелете скрипта... ну, там параметры принимаемые от сервера.. то-да-се.. А то рыбку есть мы все умеем, а нам бы ее еще ловить научится! Но за скрипт, естесно, большое ему спасибо.

Извиняйте барин

Ну не знаю я перла, а скрипт исправил хм, берешь WinMerge и смотришь изменения в исходниках ejabberd, там новый параметр добавился вот его то я и вставил. Так что, что писать то и не знаю. А краткая инструкция есть здесь http://ejabberd.narod.ru правда она уже устарела, а на новую как всегда времени нет :(

А когда же появится

А когда же появится обновлённая тема ??? по Ejabberd 2.0.5. + MsActive Directory ???
И вообще, я думаю что разработчики могли бы немного потрудиться и сделать нормальную авторизацию

Добавлю, что

Добавлю, что скрипт работает, только если на клиенте поставить галочку "передавать пароль открытым текстом", иначе никак.

Syndicate content