这个问题以前在StackOverflow,因为我认为这是一个编程问题。 看来这是更正确地设置Active Directory的问题,所以我把它移到了这里。
好吧,我已经有一段时间了,但还没有find我的解决scheme。 我经常使用我所在的服务器连接到OpenLDAP,并且SSL和LDAP都可以正常工作。 但是,现在我需要切换到Active Directory,并遇到麻烦。
为了build立系统,我做了以下工作: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)validation我的ldap.conf文件是指向我的证书的正确位置。
繁荣! 我能够通过ldap_connect()连接,并能够与我的用户绑定。 但是,当我去修改密码的时候,我收到了“服务器不愿意执行”这个有用的错误信息。
有人build议这是SSL的问题。 所以,我用命令做了一些testing:
*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
所以看起来我是连接的,而且我的证书是有效的。
尝试从命令行search:
ldapsearch -H "ldaps://my.domain.tld:636" -D "[email protected]" -W -x -b "CN=Person IM Lookingfor,CN=Users,DC=my,DC=domain,DC=tld"
返回所有我希望检索的信息。
在这一点上,我不认为这是代码的问题,尽pipe我相信有一些设置我仍然在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"; }
我将“域用户”组更改为“pipe理”我的pipe理员用户帐户。 然后,我以pipe理员的身份在PowerShell中运行ldifde命令,并在没有成为“pipe理者”之前就运行了它:
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服务器,所以我知道我的PHP的LDAP设置是正确的。
我的问题似乎更多的是设置Active Directory服务器用于编程更新。 我已经尝试了Python的密码更新,但结果是一样的。
更新我看了瑞安( http://technet.microsoft.com/en-us/magazine/ff848710.aspx )提供的链接,并确认我尝试转换密码实际上转换为正确的编码(即“车”转换为文章中的IgBjAGEAcgAiAA ==)。 现在看来,要弄清楚如何将扩展权限添加到我的LDAPpipe理器。
如您所知,远程更新用户帐户的unicodePwd属性需要128位或更高的SSL / TLS连接到域控制器,默认情况下。 或SASL,如果2008R2或2012年。看起来你已经覆盖了那里,因为你有一个证书,你正在利用LDAPS。
此外,仅用于公共信息, unicodePwd属性是只写的 。 它从来没有在LDAPsearch的结果中返回。
我也看到你用引号括起纯文本密码,然后用base64编码整个东西,这两个都是正确的。 你太亲近了!
但是我在代码中看不到的是确保编码是UTF-16的地方。 它必须是UTF-16。 UTF-16小端, 然后 base64编码,确切地说。
“… DC要求使用UTF-16编码的Unicodestring指定密码值,该string包含用引号括起来的密码,该密码已经根据对象(副本链接)语法进行了BER编码为八位字节串。
另外,为了不让我们错过显而易见的事情,请确保正确的权限:
为使密码更改操作成功,服务器强制要求密码正在更改的用户或inetOrgPerson对象必须拥有自己的“用户更改密码”控制权限,
(即帐户没有“用户不能更改密码”标志设置),
并且Vdel必须是对象上的当前密码。 为了使密码重置成功,服务器强制要求客户端拥有要重置密码的用户或inetOrgPerson对象上的“User-Force-Change-Password”控制访问权限。
再说一次,我们不要忽略这个明显的问题,确保你设定的新值符合域的密码策略。
我不会说如此好的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
也作为补充阅读,检查这个职位: