如何解决“WILL_NOT_PERFORM”问题尝试使用 unboundid LDAP SDK 在 scala 中更改密码时 MS AD 回复?

发布于 2024-11-25 11:44:27 字数 1903 浏览 4 评论 0原文

我正在与 Active Directory 较量,试图让它让我更改密码。我发现了大量有用的信息,但仍然出现持续错误。

一些代码:

import com.unboundid.ldap.sdk._
import com.unboundid.util.ssl._


def main(args: Array[String]) : Unit = {

var sslUtil = new SSLUtil( new TrustAllTrustManager() )
var con = new LDAPConnection(sslUtil.createSSLSocketFactory())
con.connect("ldap.example.net", 636)
con.bind("ldapadmin", "adminpasswd")
val newPass = "Jfi8ZH8#k".getBytes("UTF-16LE");
val modRequest = new ModifyRequest("dn: cn=Tester Dude,ou=Lab,ou=Org,ou=Provider,DC=example,DC=net",
  "changetype: modify",
  "replace: unicodePwd",
  "unicodePwd: " + '"' + newPass + '"')

println("\nGoing to try to set password to " + newPass + " with: " + modRequest.toString())

try {
  con.modify(modRequest)
} catch {
  case lde:LDAPException => println("failed LDAPException: " + lde.toString())
}

}

所以,我得到这个运行时错误:

尝试将密码设置为 [B@6dd1627e:ModifyRequest(dn='cn=Tester Dude,ou=Lab,ou=Org,ou=Provider,DC=例如,DC=net', mods={REPLACE unicodePwd})

failed LDAPException: LDAPException(resultCode=53 (不愿意执行), errorMessage='0000001F: SvcErr: DSID-031A11E5,问题 5003 (WILL_NOT_PERFORM),数据 0 ',diagnosticMessage='0000001F:SvcErr:DSID-031A11E5,问题 5003 (WILL_NOT_PERFORM),数据 0 ')

所以我知道可能导致此错误的原因包括:

  1. 未通过 SSL 连接。 (此处情况并非如此,我已使用 netstat 检查以 100% 确定我位于端口 636)
  2. 传递的密码违反了 Active Directory 密码策略。 (我已经测试过手动设置确切的密码;它会拒绝短/简单的密码,但它接受我在这段代码中使用的密码)

我已经尝试过在密码周围使用和不使用额外的引号。

迄今为止最有用的信息来源是:

http://www.dirmgr.com/blog/2010/8/26/ldap-password-changes-in-active-directory.html

但是我已经用尽了那里的每一个建议(还有很多其他地方的)。

我还尝试了其他一些方法,包括为手动添加的不同有效用户设置密码。 (这个也是通过 sdk 添加的。)

其他操作运行良好。我删除了不相关的代码,但我能够毫无问题地搜索、打印属性、添加和删除用户;但此修改请求失败。如果我设置修改请求来更改其他一些属性,例如关联的电子邮件,也可以正常工作。

I'm wrestling with Active Directory, trying to get it to let me change a password. I've found tons of useful information, but I'm still getting a persistent error.

Some code:

import com.unboundid.ldap.sdk._
import com.unboundid.util.ssl._


def main(args: Array[String]) : Unit = {

var sslUtil = new SSLUtil( new TrustAllTrustManager() )
var con = new LDAPConnection(sslUtil.createSSLSocketFactory())
con.connect("ldap.example.net", 636)
con.bind("ldapadmin", "adminpasswd")
val newPass = "Jfi8ZH8#k".getBytes("UTF-16LE");
val modRequest = new ModifyRequest("dn: cn=Tester Dude,ou=Lab,ou=Org,ou=Provider,DC=example,DC=net",
  "changetype: modify",
  "replace: unicodePwd",
  "unicodePwd: " + '"' + newPass + '"')

println("\nGoing to try to set password to " + newPass + " with: " + modRequest.toString())

try {
  con.modify(modRequest)
} catch {
  case lde:LDAPException => println("failed LDAPException: " + lde.toString())
}

}

So, I get this as a runtime error:

Going to try to set password to [B@6dd1627e with: ModifyRequest(dn='cn=Tester Dude,ou=Lab,ou=Org,ou=Provider,DC=example,DC=net', mods={REPLACE unicodePwd})

failed LDAPException: LDAPException(resultCode=53 (unwilling to perform), errorMessage='0000001F: SvcErr: DSID-031A11E5, problem 5003 (WILL_NOT_PERFORM), data 0
', diagnosticMessage='0000001F: SvcErr: DSID-031A11E5, problem 5003 (WILL_NOT_PERFORM), data 0
')

So among the things I know can cause this error:

  1. Not connecting via SSL. (Not the case here, and I've checked to be 100% sure I'm on port 636 using netstat)
  2. Passing a password which violates the Active Directory password policy. (I've tested setting that exact password manually; it will reject short/simple passwords, but it accepts the one I'm using in this code)

I've tried it both with and without the extra quotes around the password.

The most useful source of info thusfar was:

http://www.dirmgr.com/blog/2010/8/26/ldap-password-changes-in-active-directory.html

But I've exhausted every suggestion there (and a lot of other places).

I've also tried several other things, including setting the password for a different valid user that was added manually. (This one was added via the sdk also.)

Other operations are working fine. I've removed the irrelevant code but I was able to search, print attributes, add, and delete a user with no problem; but this modify request fails. If I set the ModifyRequest to change some other attribute, such as the email associated, that also works fine.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

懵少女 2024-12-02 11:44:27

连接不够安全

引用自:http://support.microsoft.com/kb/269190

为了修改此属性,客户端必须与服务器建立 128 位安全套接字层 (SSL) 连接。

因此,即使其他一切看起来都正常,如果连接被认为不安全,您仍然可能会收到 SvcErr: DSID-03190F4C, Problem 5003 (WILL_NOT_PERFORM)

缺乏管理员权限

如果您尝试在没有足够权限的情况下进行替换,则修改请求可能会失败。

dn: CN=johndoe,OU=Users,DC=example,DC=com
changetype: modify
replace: unicodePwd
unicodePwd:: base64(utf16le(quoted(password)))
-

在这种情况下,您将收到 SecErr: DSID-03150E47, Problem 4003 (INSUFF_ACCESS_RIGHTS)。如果您尝试使用非特权帐户绑定,就会发生这种情况。

密码历史记录

一些管理员喜欢拥有较长的密码历史记录(例如保存的最后 24 个密码)。如果您使用历史记录中已有的旧密码,您将获得 CONSTRAINT_ATT_TYPE

普通用户

  1. 保护连接

  2. 使用删除-添加组合。

例如

dn: CN=johndoe,OU=Users,DC=example,DC=com
changetype: modify
delete: unicodePwd
unicodePwd:: base64(utf16le(quoted(old password)))
-
add: unicodePwd
unicodePwd:: base64(utf16le(quoted(new password)))
-

connection not secure enough

Quote from: http://support.microsoft.com/kb/269190

In order to modify this attribute, the client must have a 128-bit Secure Socket Layer (SSL) connection to the server.

So even if everything else looks right, you may still get an SvcErr: DSID-03190F4C, problem 5003 (WILL_NOT_PERFORM) if the connection is deemed insecure.

lacking admin rights

A modify request may fail if you try to do a replace without insufficient rights.

dn: CN=johndoe,OU=Users,DC=example,DC=com
changetype: modify
replace: unicodePwd
unicodePwd:: base64(utf16le(quoted(password)))
-

You will get an SecErr: DSID-03150E47, problem 4003 (INSUFF_ACCESS_RIGHTS) in that case. This happens if you try to bind with an unprivileged account.

password history

Some admins like to have a long password history (e.g. last 24 passwords saved). You will get a CONSTRAINT_ATT_TYPE if you are using an old password that is already in the history.

regular user

  1. secure the connection

  2. use a delete-add combo.

e.g.

dn: CN=johndoe,OU=Users,DC=example,DC=com
changetype: modify
delete: unicodePwd
unicodePwd:: base64(utf16le(quoted(old password)))
-
add: unicodePwd
unicodePwd:: base64(utf16le(quoted(new password)))
-
鸵鸟症 2024-12-02 11:44:27

事实证明,必须先进行UTF-16LE编码,然后再转换为base64。

val newPass = javax.xml.bind.DatatypeConverter.printBase64Binary(('"'+"Jfi8ZH8#k"+'"').getBytes("UTF-16LE"))

成功了。

It turns out that it has to be UTF-16LE encoded, and then converted to base64.

val newPass = javax.xml.bind.DatatypeConverter.printBase64Binary(('"'+"Jfi8ZH8#k"+'"').getBytes("UTF-16LE"))

Did the trick.

彡翼 2024-12-02 11:44:27

我的猜测是 "unicodePwd: " + '"' + newPass + '"' 正在规避您的编码(因为 String 必须再次转换为字节,我敢打赌它不是使用正确的编码)。

尝试使用采用 Modification 对象的 MofifyRequest 版本,然后使用采用字节形式的属性值的构造函数。

val newPass = "\"Jfi8ZH8#k\"".getBytes("UTF-16LE")
// note the dquotes inside the string

val mod = new Modification(ModificationType.REPLACE, "unicodePwd", newPass)

就像您链接到的博客文章中一样...

My guess is "unicodePwd: " + '"' + newPass + '"' is circumventing your encoding (as String has to be converted to bytes again and I bet it's not using the right encoding).

Try using the version of MofifyRequest that takes Modification objects and then use the constructor that takes the attributes value as bytes.

val newPass = "\"Jfi8ZH8#k\"".getBytes("UTF-16LE")
// note the dquotes inside the string

val mod = new Modification(ModificationType.REPLACE, "unicodePwd", newPass)

just like in the blog post you linked to...

眼波传意 2024-12-02 11:44:27

我也偶然发现了这个问题。我正在使用 C# 的 Novell.Directory.Ldap.NETStandard 库。我的问题是需要引用密码。这段代码对我有用:

var passwordBytes = Encoding.Unicode.GetBytes($"\"{newPassword}\"");
connection.Modify(userDn, new LdapModification(LdapModification.Replace, new LdapAttribute("unicodePwd", passwordBytes)));

I've also stumbled on this issue. I'm using Novell.Directory.Ldap.NETStandard library for C#. The issue in my case was that the password needs to be quoted. This code worked for me:

var passwordBytes = Encoding.Unicode.GetBytes(
quot;\"{newPassword}\"");
connection.Modify(userDn, new LdapModification(LdapModification.Replace, new LdapAttribute("unicodePwd", passwordBytes)));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文