В заметке ejabberd с авторизацией через LDAP я описал основные моменты по настройке сервера ejabberd и подключения его к LDAP. К сожалению возможностей стандартного модуля LDAP-аутентификации нам не хватило. Однако ejabberd позволяет использовать внешние, в том числе собственные, программы для этой цели.
Итак. В прошлый раз я остановился на такой конфигурации:
Сейчас все пользователи, имеющие учётные записи LDAP, могут пользоваться нашим сервером. Это меня не совсем устраивает, я хочу дать эту возможность только сотрудникам. Все сотрудники входят у нас в группу employees (cn=employees,ou=groups,dc=company,dc=local).
На первый взгляд, добиться поставленной цели можно с помощью параметра ldap_filter. Но это только на первый. Во всех примерах, которые я нашёл (а пересмотрел я их не мало), используется атрибут memberOf объекта учётной записи или аналогичный ему по смыслу. К сожалению в нашей конфигурации (на основе OpenLDAP) такого атрибута не было.
После нескольких часов изучения руководств по фильтрам LDAP и возможностям ejabberd, я решил попробовать собственную программу аутентификации.
Делается это очень просто:
Здесь
Всё очень просто. Программа работает в бесконечном цикле, читая запросы со стандартного входа и записывая в стандартный вывод результат.
Запросы и ответы предваряются двумя байтами, содержащими длину запроса/ответа.
Запросы могут быть следующие:
В ответ программа должна отправлять 1 в случае успешного выполнения запроса и 0 в случае неудачи.
Вот простой пример внешней программы аутентификации на PHP. PHP использован потому, что для него у нас уже была готовая библиотека работы с нашим LDAP-сервером.
Итак. В прошлый раз я остановился на такой конфигурации:
{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); } }