Этот вопрос ранее был в 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
Также в качестве дополнительного чтения проверьте этот пост: