ejabberd: внешние программы аутентификации

Здесь уже были описаны основные моменты по настройке сервера ejabberd и подключения его к LDAP. К сожалению возможностей стандартного модуля LDAP-аутентификации может не хватить. Однако ejabberd позволяет использовать внешние, в том числе собственные, программы для этой цели.

Итак. В прошлый раз я остановился на такой конфигурации:

{auth_method, ldap}, % Метод аутентификации - LDAP
{ldap_servers, ["ldap.company.local"]}, % Адрес LDAP-сервера
{ldap_port, 389}, % Его порт
{ldap_base, "ou=people,dc=company,dc=local"} % Базовый DN учётных записей пользователей
<

Сейчас все пользователи, имеющие учётные записи LDAP, могут пользоваться нашим сервером. Это меня не совсем устраивает, я хочу дать эту возможность только сотрудникам. Все сотрудники входят у нас в группу employees (cn=employees,ou=groups,dc=company,dc=local).

На первый взгляд, добиться поставленной цели можно с помощью параметра ldap_filter<. Но это только на первый. Во всех примерах, которые я нашёл (а пересмотрел я их не мало), используется атрибут memberOf объекта учётной записи или аналогичный ему по смыслу. К сожалению в нашей конфигурации (на основе OpenLDAP) такого атрибута не было.

После нескольких часов изучения руководств по фильтрам LDAP и возможностям ejabberd, я решил попробовать собственную программу аутентификации.

Подключение внешней программы

Делается это очень просто:

{auth_method, external}.
{extauth_program, "/path/to/program/program_name"}.
<

Здесь /path/to/program/program_name< путь к программе аутентификации.

Устройство программы

Всё очень просто. Программа работает в бесконечном цикле, читая запросы со стандартного входа и записывая в стандартный вывод результат.

Запросы и ответы предваряются двумя байтами, содержащими длину запроса/ответа.

Запросы могут быть следующие:

  • auth:User:Server:Password (проверить аутентификационные данные)
  • isuser:User:Server (проверить наличие пользователя)
  • setpass:User:Server:Password (установить новый пароль пользователю)

В ответ программа должна отправлять 1 в случае успешного выполнения запроса и 0 в случае неудачи.

Ссылки

Простой пример

Вот простой пример внешней программы аутентификации на PHP. PHP использован потому, что для него у нас уже была готовая библиотека работы с нашим LDAP-сервером.

#!/usr/local/bin/php
<?php
require 'ldap3w.php';
$ldap = new LDAPConnection();

while (true) {
        $length = @fgets(STDIN, 3);
        $length = @unpack('n', $length);
        $length = $length[1];
        if ($length > 0) {
                $result = false;
                $account = false;

                $data = @fgets(STDIN, $length+1);
                $data = explode(':', $data);

                switch ($data[0]) {
                        case 'auth':
                                $account = $ldap->getAccount($data[1], $data[3]);
                        break;
                        case 'isuser':
                                $account = $ldap->getAccount($data[1]);
                        break;
                }

                if ($account) {
                        $groups = $account->membership();
                        $result = in_array('employees', $groups);
                }

                $result = @pack('nn', 2, intval($result));
                @fputs(STDOUT, $result);
        }
}
<
Story URL: