Update Active Directory Password using ldap python

2020-05-06 18:12发布

Basically trying to reset the user's password using LDAP python. I've gone through various posts here but no luck :(.

Tried using :

  • a) modify_s() - returns "No such object" every time. Tried with different user DN.

    {'info': "0000208D: NameErr: DSID-0310020A, problem 2001 (NO_OBJECT), data 0, best match of:\n\t'DC=mydomain,DC=com'\n", 'matched': 'DC=mydomain,DC=com', 'desc': 'No such object'}

    Here is the code Snippet:

    def changePassword(userEmail, oldPassword, newPassword):
     try:
        ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
    
        ldap_client = ldap.initialize("ldap://127.0.01.1:389")
        ldap_client.set_option(ldap.OPT_REFERRALS, 0)
        ldap_client.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
        ldap_client.set_option(ldap.OPT_X_TLS,ldap.OPT_X_TLS_DEMAND)
        ldap_client.set_option( ldap.OPT_X_TLS_DEMAND, True )
        ldap_client.set_option( ldap.OPT_DEBUG_LEVEL, 255 )
        ldap_client.simple_bind_s(ADMIN_EMAIL, ADMIN_PASSWORD)
    
        # Set AD password
        #unicode_pass = unicode('\"' + newPassword + '\"', "iso-8859-1")
        unicode_pass = newPassword
        password_value = unicode_pass.encode("utf-16-le")
        add_pass = [(ldap.MOD_REPLACE, 'unicodePwd', [password_value]),( ldap.MOD_REPLACE, 'unicodePwd', [password_value])]
    
        # Replace password
        try:
          user_dn = 'CN=%s,DC=mydomain,DC=com' % username
          ldap_client.modify_s(user_dn, add_pass)
          print "Active Directory password for", username, \
                "was set successfully!"
        except ldap.LDAPError, e:
          sys.stderr.write('Error setting AD password for: ' + username + '\n')
          sys.stderr.write('Message: ' + str(e) + '\n')
          ldap_client.unbind_s()
          return 'SOME_PROBLEM'
        ldap_client.unbind_s()
        return 'AUTHENTICATED'
    except ldap.INVALID_CREDENTIALS:
        ldap_client.unbind()
        return 'INVALID_CREDENTIALS'
    except ldap.SERVER_DOWN:
        return 'SERVER_UNAVAILABLE'
    
  • b) passwd(userEmail, oldPassword, newPassword). It gets executed well but password is not updated.

Need help in identifying the problem.

Reference Links: Python+LDAP+SSL

python-ldap and Microsoft Active Directory: connect and delete user

how to set lockoutTime and password of a user of Active Directory

How can I change password for domain user(windows Active Directory) using Python?

https://groups.google.com/forum/#!topic/macromedia.coldfusion.security/Rq7xx15OeBs

http://www.grotan.com/ldap/python-ldap-samples.html#add

http://marcitland.blogspot.in/2011/02/python-active-directory-linux.html

https://snipt.net/Fotinakis/change-active-directory-password-via-ldap-modify-call/

3条回答
▲ chillily
2楼-- · 2020-05-06 18:45

I had the very same issue and decided to ask on Server Fault. The answer I got helped me to figure out what was wrong in my code. To summarize, there is 2 diifferent methods to update an AD password: 1 for regular user updating his own password, and another 1 for administrator (or any account with sufficient access rights) resetting the password for another user.

Method 1: User update his own password

ad_server = "ldaps://ad.xxx_domain.com"
ad_dn = "CN={0},OU=Users,OU=AF,DC=xxx_domain,DC=com"

username = 'my_username'
old_pwd = 'the_old_pa55word'
new_pwd = 'the_new_pa55word'

cert = os.path.join('/path', "to", 'server_cert.cer')

# LDAP connection initialization
l = ldap.initialize(ad_server)
# Set LDAP protocol version used
l.protocol_version = ldap.VERSION3
# Force cert validation
l.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND)
# Set path name of file containing all trusted CA certificates
l.set_option(ldap.OPT_X_TLS_CACERTFILE, cert)
# Force libldap to create a new SSL context (must be last TLS option!)
l.set_option(ldap.OPT_X_TLS_NEWCTX, 0)

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

# Now, perform the password update
oldpwd_utf16 = '"{0}"'.format(old_pwd).encode('utf-16-le')
newpwd_utf16 = '"{0}"'.format(new_pwd).encode('utf-16-le')
mod_list = [
    (ldap.MOD_DELETE, "unicodePwd", oldpwd_utf16),
    (ldap.MOD_ADD, "unicodePwd", newpwd_utf16),
]
l.modify_s(ad_dn.format(username), mod_list)

Method 2: Admin account update regular user's password

ad_server = "ldaps://ad.xxx_domain.com"
ad_dn = "CN={0},OU=Users,OU=AF,DC=xxx_domain,DC=com"

admin_username = "i_am_the_admin"
admin_password = "admin123"

username = 'my_username'
new_pwd = 'the_new_complicated_password'

cert = os.path.join('/path', "to", 'server_cert.cer')

# LDAP connection initialization
l = ldap.initialize(ad_server)
# Set LDAP protocol version used
l.protocol_version = ldap.VERSION3
# Force cert validation
l.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND)
# Set path name of file containing all trusted CA certificates
l.set_option(ldap.OPT_X_TLS_CACERTFILE, cert)
# Force libldap to create a new SSL context (must be last TLS option!)
l.set_option(ldap.OPT_X_TLS_NEWCTX, 0)

# Bind (as admin user)
l.simple_bind_s(ad_dn.format(admin_username), admin_password)

# Now, perform the password update
newpwd_utf16 = '"{0}"'.format(new_pwd).encode('utf-16-le')
mod_list = [
    (ldap.MOD_REPLACE, "unicodePwd", newpwd_utf16),
]
l.modify_s(ad_dn.format(username), mod_list)

Please note that the second method needs to Bind with a different account (with sufficient rights) but allows to set the new password without re-typing the old one.

查看更多
beautiful°
3楼-- · 2020-05-06 18:48

I think below program helpful for you.. windows active directory use password attribute as unicode method https://technet.microsoft.com/en-us/magazine/ff848710.aspx

import ldap
import ldap.modlist as modlist
import base64
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
l = ldap.initialize('ldaps://exam.local')
l.simple_bind_s('Administrator@exam.local', 'p@ssw0rd1') 
dn="cn=map6,ou=Police,dc=exam,dc=local" 
new_password='p@ssw0rd3'
unicode_pass = unicode('\"' + new_password + '\"', 'iso-8859-1')
print (unicode_pass)
password_value = unicode_pass.encode('utf-16-le')
add_pass = [(ldap.MOD_REPLACE, 'unicodePwd', [password_value])]
print (password_value)
l.modify_s(dn, add_pass)
l.modify_s(dn, add_pass)
l.unbind_s()      
查看更多
forever°为你锁心
4楼-- · 2020-05-06 18:51

From what I can see is that you user_dn is not correctly set. Double check and ensure you full DN actually exists in the Directory Server. Check your username variable is correctly parsed (No newline or tab characters) and the Base DN is verified.

sys.stderr.write('Error setting AD password for: ' + username + '\n')
sys.stderr.write('DN: ' + user_dn + '\n')
sys.stderr.write('Message: ' + str(e) + '\n')

The error message is pretty clear that AD cannot find the object (DN) it wishes to modify **(NO_OBJECT)

{'info': "0000208D: NameErr: DSID-0310020A, problem 2001 (NO_OBJECT), 
data 0, best match of:\n\t'DC=mydomain,DC=com'\n", 'matched': 
'DC=mydomain,DC=com', 'desc': 'No such object'}
查看更多
登录 后发表回答