1

I'm currently trying to modify the password of a user on an AD with Python (3) and LDAP module. When my script is finished, everything looks like to be OK. However, the password is the same as before.

Here is my script:

LDAP_SERVER = <domain>
LDAP_USERNAME = <admin_username>
LDAP_PASSWORD = <admin_password>
dn = <DN>
quoted_new_password = '\"' + <new_password> + '\"'
quoted_new_password_bytes = quoted_new_password.encode('UTF-16LE')

ldap_client = ldap.initialize(LDAP_SERVER)
ldap_client.set_option(ldap.OPT_REFERRALS, 0)
ldap_client.simple_bind_s(LDAP_USERNAME, LDAP_PASSWORD)
ad_user_filter = '(&(objectClass=user)(sAMAccountName=<username-for-password-modification>))'
res = ldap_client.search_s(dn, ldap.SCOPE_SUBTREE, ad_user_filter)
user_dn = (res[0][1]['distinguishedName'][0]).decode("utf-8")
modlist = [ (ldap.MOD_REPLACE, "userPassword", quoted_new_password_bytes)]
ldap_client.modify_s(user_dn, modlist)

The result is a tuple like

(<number>, [], <number>, [])

Then, when I try to connect to the AD (with the same domain), the old password works, but not the new one.

Did I forget something?

EDIT: The result is the same when I put, for example, an empty string as a new password, even if my AD requires at least 14 characters.

EDIT: The last result of "modify_s" is

(103, [], 3, [])

However, 103 code doesn't correspond to anything...

Saikat
  • 14,222
  • 20
  • 104
  • 125
Jérémie RPK
  • 297
  • 4
  • 13
  • 1
    You should check the result of the ldapmodify operation. Most likely it was rejected. Note that AD may not allow you to change the password if the connection is not secured (TLS). – Ludovic Poitou Mar 14 '19 at 08:04
  • Thank you Ludovic Poitou, your comment helped me to guide myself on the right way. In fact, the server what I tried is not secured. – Jérémie RPK Mar 15 '19 at 22:19
  • The 103 or 3 code 'corresponds' to one of the error codes documented in the LDAP RFCs. – user207421 Mar 15 '19 at 22:45

2 Answers2

0

RESOLVED

The domain was ldap://the_domain:389. But it couldn't work because I had to use the secured server: ldaps and not ldap, port 636 and not 389.

So I changed LDAP_SERVER to ldaps://the_domain:636

However, my script didn't work anymore. I taked this script from another post before adapt it:

import ldap3

SERVER = 'ldaps://thedomain:636'
BASE_DN = "DC=domain,DC=com"
LDAP_USERNAME = "admin_username@thedomain.com"
LDAP_PASSWORD = "admin_password"
CURRENT_PWD = "the_current_password"
NEW_PWD = "the_new_password"
SEARCHED_USERNAME = "M_tete_en_l_air"

SEARCH_FILTER = '(&(objectClass=User)(samaccountname='+SEARCHED_USERNAME +'))'

USER_DN = ""

ldap_server = ldap3.Server(SERVER, get_info=ldap3.ALL)
conn = ldap3.Connection(ldap_server, LDAP_USERNAME, LDAP_PASSWORD, auto_bind=True)
conn.start_tls()

conn.search(search_base = BASE_DN,
         search_filter = SEARCH_FILTER,
         search_scope = ldap3.SUBTREE,
         attributes = ['cn', 'givenName'],
         paged_size = 5)

for entry in conn.response:
    if entry.get("dn") and entry.get("attributes"):
        if entry.get("attributes").get("cn"):
            USER_DN=entry.get("dn")

print(USER_DN)
success = ldap3.extend.microsoft.modifyPassword.ad_modify_password(conn, USER_DN, NEW_PWD, CURRENT_PWD,  controls=None)
print("Password modified: ", success)

(I don't have exactly this script)

Source (StackOverflow answer)

Jérémie RPK
  • 297
  • 4
  • 13
0

Here's how to change your AD user password via LDAP in Python3:

We are using the python-ldap module here. You must know the current password to successfully change to the new one.

import ldap


def update_pass():
    ad_server = "ldaps://ldap.server.com"
    ad_dn = "CN={0},OU=xx,DC=yy,DC=zz,DC=org"

    username = 'my-username'
    old_pwd = 'my-old-passwd'
    new_pwd = 'my-new-passwd'

    # LDAP connection initialization
    ldap_conn = ldap.initialize(ad_server)
    # Set LDAP protocol version used
    ldap_conn.protocol_version = ldap.VERSION3

    # Bind
    ldap_conn.simple_bind_s(ad_dn.format(username), old_pwd)

    # Now, perform the password update
    old_pwd_utf16 = '"{0}"'.format(old_pwd).encode('utf-16-le')
    new_pwd_utf16 = '"{0}"'.format(new_pwd).encode('utf-16-le')

    mod_list = [
        (ldap.MOD_DELETE, "unicodePwd", old_pwd_utf16),
        (ldap.MOD_ADD, "unicodePwd", new_pwd_utf16),
    ]

    ldap_conn.modify_s(ad_dn.format(username), mod_list)
    print("Password successfully updated.")


if __name__ == '__main__':
    update_pass()

Saikat
  • 14,222
  • 20
  • 104
  • 125