6

For some time I have been trying to change a password via cfldap. The connection is made over SSL and port 636 (cfssl_basic), tested within logins. I tried the following version of code:

<cfset password_new_retyp=charsetEncode(charsetDecode('"'&password_new_retyp&'"','UTF-16LE'),'UTF-8'))>
<!---encoded, decoded password --->
<cfldap action="modify"
    dn="#session.dn_addres#" --- i query this on login
    modifyType="replace"
    attributes="unicodePwd=#password_new_retyp#"
    server="xxxx.xxxx.xxx.xx" --- name of server thet i use on login
    secure = "cfssl_basic" 
    port=636
    username="#session.username#" ---username thet is used on login
    password="#password_old#">  ---- pass before changing

and error is somthing like this :

An error has occured while trying to execute query :[LDAP: error code 49 - 80090308: LdapErr: DSID-0C0903C5, comment: AcceptSecurityContext error, data 52e, v23f0 ].

I also tried this method without encoding password:

<cfldap action="modify"
    dn="#session.dn_addres#"
    modifyType="replace"
    attributes="password=#password_new_retyp#"
    server="xxxx.xxxx.xxx.xx"
    secure = "cfssl_basic"
    port=636
    username="#session.username#"
    password="#password_old#" >

and eror is the same:

An error has occured while trying to execute query :[LDAP: error code 49 - 80090308: LdapErr: DSID-0C0903C5, comment: AcceptSecurityContext error, data 52e, v23f0 ]. One or more of the required attributes may be missing or incorrect or you do not have permissions to execute this operation on the server.

Any idea?

duncan
  • 31,401
  • 13
  • 78
  • 99
Aleksandar
  • 73
  • 1
  • 10
  • Error code 49 and 52e refers to invalid credentials. You are trying to change the password of the same account you are logging in as? – abbottmw Apr 24 '14 at 13:21
  • I am.And with this same code, (you just change attributes) may change any of the data for the user, but not password. – Aleksandar Apr 24 '14 at 14:15
  • What is the value of `session.dn_addres`? More specifically, are you sure the value matches the unique account that you are trying to update? – Miguel-F Apr 24 '14 at 15:24
  • session.dn_addres gain from the logging, hear I also uses cfldap but action QUERY and then take DN attribute, that attribute set to the session. – Aleksandar Apr 24 '14 at 20:30
  • The problem is that with this code when I change the attribute works properly, for example, can put attributes = "postalcode = 10007" and everything will go well. – Aleksandar Apr 24 '14 at 20:36
  • Do you know if you have write permission on that attribute? Can you try logging in as a root account and try changing the users password? – abbottmw Apr 24 '14 at 21:34
  • Each user has the right to change password in AD. – Aleksandar Apr 24 '14 at 21:56
  • I wonder if the user that the ColdFusion service is running under is getting in your way. Can you give the ColdFusion user rights to change a particular users password to test? – Miguel-F Apr 25 '14 at 00:55
  • I tried to put service Log on as a AD admin(has all rights to all users)I got the same message - error,(although it was not clear this idea, I think communication is done via the protocol, and the rights over the AD specifies by the username and password I submit?). – Aleksandar Apr 25 '14 at 09:35
  • Any other suggestions, ideas? – Aleksandar Apr 25 '14 at 09:38
  • Yes, I agree. Since everything else seems to be working I thought that may be the issue. Look back at the error message you are getting. It is pretty specific. _One or more of the required attributes may be missing or incorrect or you do not have permissions to execute this operation on the server._ Have you tried using the credentials of the AD admin and see if that one can change the password? With the credentials that you are using now, based on what you have told us, it either does not have rights to change the PW or you are missing a required attribute. Per the error message. – Miguel-F Apr 26 '14 at 13:10
  • You may have found this already but I saw an OLD post that is trying to do what you are doing. http://yhoo.it/1j6CXtg Not sure if this will help. I don't have an AD server to test on. One thing I noticed is you are changing "password" attribute. Change that to unicodePwd (which I see you are doing at the top code example) – abbottmw May 08 '14 at 12:53

1 Answers1

5

It was a long and hard road but I got there. I hope this helps anyone else trying to change passwords and enforce LDAP password policy.

Source: Based on code from Edward Smith in archived CFTalk thread

<cftry>
    <cfscript>
        // You are going to use  the user's credentials to login to LDAP
        // Assuming your LDAP is set up to do so

        // Set up varibles
        newPassword = '"#newPassword#"';
        oldPassword = '"#currentPassword#"';
        // You would probably pass in a variable here, I typed it out so you would ss the format its expecting
        distinguishedName = "CN=theUser,OU=someOU,DC=DDDD,DC=CCC,DC=AAA,DC=ZZZ";
        newUnicodePassword = newPassword.getBytes("UnicodeLittleUnmarked");
        oldUnicodePassword = oldPassword.getBytes("UnicodeLittleUnmarked");
        ldapsURL = "ldap://#ldapServer#:#ldapPort#";

        // Create a Java Hashtable
        javaEnv = CreateObject("java", "java.util.Hashtable").Init();

        // Put stuff in the Hashtable
        javaEnv.put("java.naming.provider.url", ldapsURL);
        // The user's Full DN and Password
        javaEnv.put("java.naming.security.principal", "#distinguishedName#");
        javaEnv.put("java.naming.security.credentials", "#currentPassword#");
        javaEnv.put("java.naming.security.authentication", "simple");
        javaEnv.put("java.naming.security.protocol", "ssl");
        javaEnv.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");

        // Create a Java InitialDirContext
        javaCtx = CreateObject("java", "javax.naming.directory.InitialDirContext").Init(javaEnv);

        // Create two Java BasicAttributes
        oldBA = CreateObject("java", "javax.naming.directory.BasicAttribute").Init("unicodePwd", oldUnicodePassword);
        newBA = CreateObject("java", "javax.naming.directory.BasicAttribute").Init("unicodePwd", newUnicodePassword);

        /***********************************************
        *   Stick the attributes into an Java Array and tell it what to do with them
        *   Guess what? A CF Array = a Java Array
        *   1 = DirContext.ADD_ATTRIBUTE
        *   2 = DirContext.REPLACE_ATTRIBUTE
        *   3 = DirContext.REMOVE_ATTRIBUTE
        *  This is the big trick 
        *   If you login above as an admin then you only need to do a 2 Replace but will not run LDAP passoword policy (lenght, complexity, history... etc.)
        *       It will let you change password to anything
        *   If you want to check the LDAP password policy then you need to create the array and first Remove (3) then Add (1)
        *       Error Code 19 means something in the LDAP password policy was violated
        *           I haven't figured out how to read what the error is (like "password length too short" or "you have used this password in the past")
        *       Error Code 49 means invalid username/password
        ************************************************/
        mods = [
            createObject( "java", "javax.naming.directory.ModificationItem").init(3, oldBA),
            createObject( "java", "javax.naming.directory.ModificationItem").init(1, newBA)
        ]; 
        // Run it
        javaCtx.modifyAttributes(distinguishedName,mods);
        javaCtx.close();
    </cfscript>
    // Yeah! I could have scripted the cfcatch but this was easier.
    <cfcatch>
        <cfif find('error code 19',cfcatch.message)>
            <!--- I am using cfwheels so this just displays a nice error message on the next page --->
            <cfset flashInsert(error="New password does not meet requirements defined in the password rules.")>
        <cfelseif isDefined('cfcatch.RootCause.cause.Explanation') and find('error code 49', cfcatch.RootCause.cause.Explanation)>
            <!--- I am using cfwheels so this just displays a nice error message on the next page --->
            <cfset flashInsert(error="Current Password IS incorrect.")>
        <cfelse>    
            <!--- This just pukes the error up hard and uncaught --->
            <cfrethrow>
        </cfif>
        <cfset hasError = true>
    </cfcatch>  
</cftry>
Leigh
  • 28,765
  • 10
  • 55
  • 103
Mr.Black
  • 465
  • 5
  • 9
  • Thanks for posting the final solution. Side note, I had never heard of "UnicodeLittleUnmarked" :) Sounds like it is a [synonym for "UTF-16LE"](http://docs.oracle.com/javase/7/docs/technotes/guides/intl/encoding.doc.html). I prefer the latter, more reminiscent of Gulliver's Travels ;-) – Leigh Jun 10 '15 at 23:03
  • I am unable to get this to work on my end and only get a black screen. Will someone please help me to get this working for me? – David Brierton Feb 10 '17 at 20:45
  • @Leigh Any chance you can help me get this to work for me? I am just getting a white screen with no errors even when I try a catch. http://stackoverflow.com/questions/42168696/unlock-and-reset-active-directory-password-coldfusion – David Brierton Feb 10 '17 at 21:33
  • CF2021.. I've found that this was the only solution I could get working. Thanks. – madcolor Aug 24 '21 at 22:24