Назад | Перейти на главную страницу

Active Directory на Server 2012 - правильная настройка для изменения паролей с помощью программирования

Этот вопрос ранее был в StackOverflow, так как я думал, что это проблема программирования. Кажется, это больше проблема с правильной настройкой Active Directory, поэтому я переместил ее сюда.

Хорошо, я занимаюсь этим уже некоторое время, но не нашел своего решения. Я обычно подключаюсь к OpenLDAP с того сервера, на котором я работаю, и все отлично работает с SSL и LDAP. Однако теперь мне нужно переключиться на Active Directory, и у меня возникли проблемы.

Чтобы настроить систему, я сделал следующее: 1) Экспортировал свой сертификат с Server 2012: http://pic.dhe.ibm.com/infocenter/rdirserv/v5r1m0/index.jsp?topic=%2Fcom.ibm.rational.rds.administering.doc%2Ftopics%2Ft_Exporting_certificate_Active_Directory_server.html

2) Конвертировал мой сертификат из DER в PEM: http://www.novell.com/coolsolutions/tip/5838.html

3) Убедитесь, что для TLS_REQCERT установлено значение «никогда».

4) Подтверждено, что мой файл ldap.conf указывает на правильное расположение моего сертификата.

Бум! Я смог подключиться через ldap_connect () и смог установить связь с моим пользователем. Однако затем, когда я пошел изменять пароль, я получил очень полезное сообщение об ошибке «Сервер не желает выполнять».

Некоторые предполагают, что это проблема SSL. Итак, я провел небольшое тестирование с помощью команды:

*ldapsearch -H "ldaps://my.domain.tld" -b "" -s base -Omaxssf=0 -d7*

Я получаю следующие результаты:

ldap_send_initial_request
ldap_new_connection 1 1 0
ldap_int_open_connection
ldap_connect_to_host: TCP my.domain.tld:636
ldap_new_socket: 3
ldap_prepare_socket: 3
ldap_connect_to_host: Trying ip.add.re.ss:636
ldap_pvt_connect: fd: 3 tm: -1 async: 0

TLS: loaded CA certificate file /etc/openldap/certs/cert-name.pem
... certificate data ...
TLS: certificate [CN=my.domain.tld] **is valid**
... more certificate data ...
* host: my.domain.tld  port: 636  (default)
  refcnt: 2  status: Connected
  last used: Fri Feb 21 11:50:13 2014

Похоже, я подключен, и мой сертификат действителен.

Пробуем поиск из командной строки:

ldapsearch -H "ldaps://my.domain.tld:636" -D "user@my.domain.tld" -W -x -b "CN=Person I. M. Lookingfor,CN=Users,DC=my,DC=domain,DC=tld"

Возвращает всю информацию, которую я ожидаю получить.

На данный момент я не думаю, что это проблема с кодом, настолько, насколько я считаю, что есть некоторые настройки, которые мне все еще не хватает в AD. Я не специалист по Windows, поэтому не знаю, что еще мне могло не хватать. Любые дополнительные мысли будут оценены.

КОД ДЛЯ ГЕНЕРИРОВАНИЯ LDIF

function encodePwd($new_password) {
        $newpass = '';
        $new_password = "\"".$new_password."\"";
        $len = strlen($new_password);
        for ($i = 0; $i < $len; $i++) {
                $newpass .= "{$new_password{$i}}\000";
        }
        $newpass = base64_encode($newpass);
        return $newpass;
}

Результирующий LDIF:

dn: CN=Tester B. Testerton,CN=Users,DC=my,DC=domain,DC=tld
changetype: modify
replace: unicodePwd
unicodePwd:: IgBiAHUAQAAoADUAJABpAF4APQA5AGwAawBDACIA

Затем код пытается:

$mods["unicodePwd"] = $new_pass64;
if(ldap_modify($ldap_conx,$ldap_user_dn,$mods) === false)
{
    $e = ldap_error($ldap_conx);
    $e_no = ldap_errno($ldap_conx);
    echo "Error attempting to modify password in LDAP for user: $uname\n";
} else {
    echo "Success! Changed password for user: $uname\n";
}

Я изменил группу «Пользователи домена» на «Управляемую» моей учетной записью администратора. Затем я запустил ldifde в PowerShell в качестве администратора, и она работала там, где не работала до того, как стала «менеджером»:

Logging in as current user using SSPI
Importing directory from file ".\tester.ldif"
Loading entries..
1 entry modified successfully.

The command has completed successfully

Однако я все еще не могу изменить пароль через PHP; что-то все еще отсутствует. Я регулярно использую этот сервер Linux для обновления серверов OpenLDAP и Novell eDirectory, поэтому я знаю, что мои настройки LDAP для PHP верны.

Моя проблема, похоже, больше связана с настройкой сервера Active Directory для использования с программными обновлениями. Я пробовал обновить пароль с помощью Python, но результаты те же.

Обновить Я посмотрел ссылку, предоставленную Райаном (http://technet.microsoft.com/en-us/magazine/ff848710.aspx) и подтвердил, что моя попытка преобразовать пароль на самом деле преобразуется в правильную кодировку (т. е. "car" преобразуется в IgBjAGEAcgAiAA ==, как в статье). Похоже, теперь пришло время выяснить, как добавить расширенные права моему диспетчеру LDAP.

Как вы уже знаете, обновление unicodePwd Атрибут учетной записи пользователя удаленно требует 128-битного или лучшего соединения SSL / TLS с контроллером домена по умолчанию. Или SASL, если 2008R2 или 2012. Похоже, вы уже попали туда, поскольку у вас есть сертификат и вы используете LDAPS.

Кроме того, для публичной информации unicodePwd атрибут записывать-только. Он никогда не возвращается в результате поиска LDAP.

Я также вижу, что вы заключаете простой текстовый пароль в кавычки, а затем кодируете все в base64, что оба правильные. Вы так близко!

Но то, что я не вижу в вашем коде, - это то, где вы обеспечиваете кодировку UTF-16. Это имеет быть UTF-16. UTF-16 с прямым порядком байтов, затем В кодировке base64, если быть точным.

«... контроллер домена требует, чтобы значение пароля было указано в строке Unicode в кодировке UTF-16, содержащей пароль, заключенный в кавычки, который был закодирован BER как строка октетов в соответствии с синтаксисом объекта (Replica-Link)».

Кроме того, чтобы мы не упустили очевидное, обеспечьте правильные разрешения:

Для успешного выполнения операции смены пароля сервер требует, чтобы пользователь или объект inetOrgPerson, пароль которого изменяется, должен обладать правом доступа «User-Change-Password» на себя,

(т.е. в учетной записи не установлен флаг "пользователь не может изменить пароль")

и что Vdel должен быть текущим паролем для объекта. Для успешного сброса пароля сервер требует, чтобы клиент обладал правом доступа «User-Force-Change-Password» к пользователю или объекту inetOrgPerson, пароль которого должен быть сброшен.

И снова, чтобы не упустить из виду очевидное, убедитесь, что новое значение, которое вы пытаетесь установить, соответствует политике паролей домена.

Я не очень хорошо говорю на PHP или Perl, но вот несколько Powershell, который получает пароль в нужном вам правильно закодированном формате:

PS C:\> [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes("`"SweetNewPwd123!`""))
IgBTAHcAZQBlAHQATgBlAHcAUAB3AGQAMQAyADMAIQAiAA==

Давайте поразмышляем над документацией вечно таинственного unicodePwd атрибут:

http://msdn.microsoft.com/en-us/library/cc223248.aspx

Также в качестве дополнительного чтения проверьте этот пост:

http://technet.microsoft.com/en-us/magazine/ff848710.aspx