Server 2012 上的 Active Directory - 正确设置以通过编程更改密码

mik*_*ike 5 active-directory

这个问题以前在 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*
Run Code Online (Sandbox Code Playgroud)

我收到的结果是:

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
Run Code Online (Sandbox Code Playgroud)

所以看起来我已经连接上了,而且我的证书是有效的。

尝试从命令行搜索:

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"
Run Code Online (Sandbox Code Playgroud)

返回我希望检索的所有信息。

在这一点上,我不认为这是代码的问题,因为我相信在 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;
}
Run Code Online (Sandbox Code Playgroud)

结果 LDIF:

dn: CN=Tester B. Testerton,CN=Users,DC=my,DC=domain,DC=tld
changetype: modify
replace: unicodePwd
unicodePwd:: IgBiAHUAQAAoADUAJABpAF4APQA5AGwAawBDACIA
Run Code Online (Sandbox Code Playgroud)

然后代码尝试:

$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";
}
Run Code Online (Sandbox Code Playgroud)

我将“域用户”组更改为“管理人”我的管理员用户帐户。然后,我以管理员身份在 PowerShell 中运行了ldifde命令,并且它在成为“经理”之前没有的地方工作:

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

The command has completed successfully
Run Code Online (Sandbox Code Playgroud)

但是,我仍然无法通过 PHP 修改密码;仍然缺少一些东西。我经常使用这个 Linux 服务器来更新 OpenLDAP 和 Novell eDirectory 服务器,所以我知道我的 PHP LDAP 设置是正确的。

我的问题似乎更多是设置 Active Directory 服务器以用于编程更新。我已经尝试过用 Python 更新密码,但结果是一样的。

更新 我查看了 Ryan ( http://technet.microsoft.com/en-us/magazine/ff848710.aspx )提供的链接,并确认我尝试转换密码实际上正在转换为正确的编码(即“汽车”转换为 IgBjAGEAcgAiAA==,如文章中所述)。看来现在要弄清楚如何向我的 LDAP 管理器添加扩展权限。

Rya*_*ies 5

如您所知,unicodePwd默认情况下,远程更新用户帐户的属性需要 128 位或更好的 SSL/TLS 连接到域控制器。或者 SASL,如果是 2008R2 或 2012。看起来你已经被覆盖了,因为你有一个证书并且你正在使用 LDAPS。

此外,仅用于公共信息,该unicodePwd属性是只写的。它永远不会在 LDAP 搜索的结果中返回。

我还看到您用引号将纯文本密码括起来,然后对整个内容进行 base64 编码,这都是正确的。你离得那么近!

但是我在您的代码中没有看到您确保编码为 UTF-16 的地方。它必须是 UTF-16。确切地说,UTF-16 小端,然后是base64 编码。

“... DC 要求在 UTF-16 编码的 Unicode 字符串中指定密码值,其中包含用引号括起来的密码,根据 Object(Replica-Link) 语法,该字符串已被 BER 编码为八位字节字符串。”

另外,为了我们不会错过显而易见的事情,请确保正确的权限:

为了使密码更改操作成功,服务器强制要求正在更改密码的用户或 inetOrgPerson 对象必须对自己拥有“用户-更改-密码”控制访问权限,

(即该帐户没有设置“用户无法更改密码”标志,)

并且 Vdel 必须是对象的当前密码。为了成功重置密码,服务器强制要求客户端对要重置密码的用户或 inetOrgPerson 对象拥有“User-Force-Change-Password”控制访问权限。

再一次,为了避免忽略显而易见的问题,请确保您尝试设置的新值符合域的密码策略。

我不太会说 PHP 或 Perl,但这里有一些 Powershell 可以以您需要的正确编码格式获取密码:

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

让我们仔细研究一下这个永远神秘的unicodePwd属性的文档:

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

作为补充阅读,请查看此帖子:

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