Kartik Domadiya
Kartik Domadiya

Reputation: 29968

Update Active Directory Password using ldap python

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

Tried using :

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/

Upvotes: 1

Views: 8891

Answers (3)

Antwane
Antwane

Reputation: 22618

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.

Upvotes: 2

ARPT
ARPT

Reputation: 141

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'}

Upvotes: 0

shan
shan

Reputation: 141

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('[email protected]', '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()      

Upvotes: 2

Related Questions