1

I seem to be running into the classic error with resetting passwords in AD even though everything I have found online points generally towards the fact that I should be golden.

Code first.

from ldap3 import *

username = '<account with the proper permissions>'
password = '<totally@realpassword>'

server = Server('<fqdn of server>', use_ssl=True, get_info=ALL)
conn = Connection(server, user='<domain>\\' + username, password=password, authentication=NTLM, auto_bind=True)

print(conn)

user_dn = 'CN=Test,OU=US,OU=NA,OU=Employees,OU=Users,DC=domain,DC=com'
new_pass = 'U^mod2olla'

r = conn.extend.microsoft.modify_password(user_dn, new_pass)

print(conn.result)

This seems to be the proper way to instantiate a connection to my LDAP server over SSL as corroborated by this Connection printout:

ldaps://ldap.domain.com:636 - ssl - user: domain.com\samaccountname - not lazy - bound - open - <local: IP:62368 - remote: IP:636> - tls not started - listening - SyncStrategy - internal decoder

But I am still receiving this error:

{'result': 53, 'description': 'unwillingToPerform', 'dn': '', 'message': '0000001F: SvcErr: DSID-031A1248, problem 5003 (WILL_NOT_PERFORM), data 0\n\x00', 'referrals': None, 'type': 'modifyResponse'}

From my Googling this usually means that either the password is not being encoded properly, or the connection is not sufficiently secure according to the LDAP server.

I'm lost at this point. Thoughts?

@cannatag if you are out there...I need you :)

My Research links:

https://github.com/cannatag/ldap3/issues/130

Python 3.5, ldap3 and modify_password()

Unable to change user's password via ldap3 Python3

Changing Active Directory user password in Python 3.x

IceBawkz
  • 41
  • 1
  • 6

2 Answers2

0

You need bind to AD as Domain Admin.

After that search for userdn and modify

I'm using c.modify(user_dn,{"userAccountControl":(MODIFY_REPLACE,512)}) to make sure user can login (We can't change password if locked or password expried)

admin = CONF['admin']['user']
passwdadm = CONF['admin']['pass']
with connect_ldap(authentication=SIMPLE, user=admin, password=passwdadm) as c:
    c.bind()
    user_dn = find_user_dn(c, username)
    c.modify(user_dn,{"userAccountControl":(MODIFY_REPLACE,512)})
    print(c.result)
    c.unbind()

with connect_ldap(authentication=SIMPLE, user=admin, password=passwdadm) as c:
    c.bind()
    user_dn = find_user_dn(c, username)
    c.extend.microsoft.modify_password(user_dn, new_pass, old_pass)
    print(c.result)
    c.unbind()
0

Unfortunately, I was right in my assumption that there were no code related issues.

I chatted with some of our Domain Admins and they confirmed for me that the server I was connecting to with LDAPS is in fact an F5 and LDAPS terminates there. This means that it is impossible to establish and LDAPS connection to any of the individual Domain Controllers without a specific cert and IP. Doing that would not be scalable or realistic for my system so I am not going to be using this method to reset passwords in AD.

If anyone finds themselves in a similar situation, I recommend looking into PowerShell remoting from Linux. It is now possible to run native powershell on Linux and open a session on a Windows Server to execute commands locally. Currently you need PS 6.0 beta.

IceBawkz
  • 41
  • 1
  • 6
  • Curious what an F5 is? – Corey Feb 19 '20 at 23:12
  • @Corey, he's referring to a Load Balancer made by F5. It's fairly common to see some type of load balancer in front of several Active Directory Domain Controllers when exposing LDAP services. In the above situation the F5 is offloading the SSL such that it's terminated at the F5 (port 636) and the F5 speaks clear text to the DCs (port 389) and then re-encrypts the data on the way back out to the clients. – Marc Jul 21 '20 at 16:46