How do I resolve "WILL_NOT_PERFORM" MS AD reply when trying to change password in scala w/ the unboundid LDAP 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:
- Not connecting via SSL. (Not the case here, and I've che开发者_StackOverflowcked to be 100% sure I'm on port 636 using netstat)
- 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.
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
secure the connection
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)))
-
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.
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...
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($"\"{newPassword}\"");
connection.Modify(userDn, new LdapModification(LdapModification.Replace, new LdapAttribute("unicodePwd", passwordBytes)));
精彩评论