среда, 27 мая 2020 г.

Пароли в SHA256 в OpenLDAP

Понадобилось нам поднять для определенных целей OpenLDAP. С условием, что пароли, вернее хэши наших пользователей, мы будем брать из уже существующей SQL-базы. Из входящих данных у нас был SQL-запрос, вызвращающий пользователей с хэшами и утверждение нашего DBA, что пароли хешированы в SHA256.

Получаю хэш пользователя из базы, проверяю через
echo -n "test" | sha256sum
9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08  -
Строка совпадает. Быстро ваяем скрипт, который заполняет нужные поля в LDAP, в том числе вставляет эту строку в качестве пароля.

Пробуем авторизоваться:
ldapwhoami -vvv -h 127.0.0.1 -p 389 -D "cn=Иванов Иван,ou=staff,dc=example,dc=com" -W
Enter LDAP Password:                                                                                             
ldap_bind: Invalid credentials (49)
Что-то не работает.

Google подтверждает, что OpenLDAP умеет в SHA256, однако разные статьи говорят, что для этого надо либо использовать сторонний модуль slapd-sha2.so, либо воспользоваться услугами самой операционной системы, ведь пароли в Linux хранятся в SHA256/SHA512.

Выбираю второй вариант. Пишут, что надо добавить префикс {CRYPT}. Чтобы указать, что это хэш sha256, делаю предположение, что надо добавить $5$:
cat ./chpass.ldif 
dn: cn=Иванов Иван,ou=staff,dc=example,dc=com
changetype: modify
replace: userPassword
userPassword: {CRYPT}$5$9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

Заливаю изменение, проверяю...

ldap_bind: Invalid credentials (49)

Нахожу в OpenLDAP FAQ:
Just to state the obvious, SHA-256 and SHA-512 based "glibc" crypt algorithms $5$ and $6$ are totally different from plain (or salted) "{SHA256}" algorithms. The libc crypt variants do a lot of nonsensical transpositions to increase the computational load.

Черт, пишут что алгоритмы различаются.

Чтобы удостоверится, вставляем свой хэш из /etc/shadow в качестве пароля с префиксом {CRYPT}$6$.

Работает, конечно.

Но нам надо использовать те хэши, которые уже в базе. База уже успешно используется в другом проекте, так что хэши рабочие, чтобы "перехешировать" под наш алгоритм, нужно будет инициировать смену паролей у нескольких сотен пользователей, да еще и переписать уже существующий проект, успешно использующий имеющиеся хэши.

Параллельно в гугле находим, что идентичный команде sha256sum хэш даёт команда:
echo -n "test" | openssl dgst -sha256
(stdin)= 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
Да и онлайн сервис по распознаванию хэшей подтверждает, что это действительно sha256.
Тогда как на результат команды:
openssl passwd -5
говорит Unknown.

Ладно, читаем мануалы дальше. Различие в "соли". Passwd в Linux и в openssl делают пароль с солью, а sha256sum, понятное дело, без. И как раз-таки в OpenLDAP это должно работать, при использовании префикса {SHA256}

Видимо надо искать модуль. И находим информацию, что в актуальных версиях OpenLDAP модуль уже присутствует в системе. А файл slapd-sha2.so мы не могли найти потому, что он называется по-другому. Сотни статей по openldap+sha256 уже не актуальны, кто бы мог подумать :)

Для подтверждения этого выкачиваю исходники openldap с гита, нахожу модуль и в его Makefile'е вижу сему подтверждение. Файл на выходе действительно называется pw-sha2.la / pw-sha2.so.

Пробую просто добавить префикс {SHA256}:
cat ./chpass.ldif 
dn: cn=Иванов Иван,ou=staff,dc=example,dc=com
changetype: modify
replace: userPassword
userPassword: {SHA256}9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

Заливаю, пробую, не работает.

Может модуль не подгружен?
Конфиг OpenLDAP сейчас хранится в самом OpenLDAP, так что смотрим:

# slapcat -b cn=config -a "(objectClass=olcModuleList)"
...
olcModuleLoad: {1}pw-sha2.la
...
И видим, что модуль загружен.

Кстати, у нас уже есть выкачанные исходники OpenLDAP. Без особой надежды лезу в них поковырятся, мож пойму, что ему надо. В readme модуля sha2 до сих пор сказано, что надо собрать slapd-sha2.so, скопировать его в нужное место и подключить через конфиг slapd.conf (т.е. инструкция в исходниках сама устарела, ведь и библиотека называется по-другому, и конфиг OpanLDAP уж много лет как в самом OpenLDAP).

Но в том же readme ниже нахожу команду для создания хэша для тестирования:
$ echo -n "secret" | openssl dgst -sha256 -binary | openssl enc -base64
K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=
Что ж, мы были близки. Пароль надо завернуть в base64. И это при том, что в LDAP оно еще раз заворачивается в base64. Но не строчное его представление, а "бинарное".

Делаю base64 над своим паролем, вставляю с префиксом {SHA256}:

# echo -n "test" | openssl dgst -sha256 -binary | base64
n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=

# cat ./chpass.ldif 
dn: cn=Иванов Иван,ou=staff,dc=example,dc=com
changetype: modify
replace: userPassword
userPassword: {SHA256}n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=

Заливаю, проверяю, работает!

Result: Success (0)

В скрипте это можно сделать так:
echo -n "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" | xxd -r -p | base64

суббота, 2 мая 2020 г.

Обнулить все файлы в каталоге.

Для довольно специфической задачи понадобилось обнулить все файлы в каталоге:
while read line; do bash -c "> \"$line\""; done < <(ls -1)