从 python-ldap 代码更新 AD 密码:INSUFF_ACCESS_RIGHTS

从 python-ldap 代码更新 AD 密码:INSUFF_ACCESS_RIGHTS

我需要在 Python Web 应用程序 (Flask) 中实现“更新密码”功能。目标是允许用户在远程 Active Directory 服务器上自行更新密码。

我以这个快速单元测试结束

import os
import ldap

def test_change_passwd():
    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_complicated_password'
    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
    l.simple_bind_s(ad_dn.format(username), old_pwd)

    # 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)

当我运行它时,它在最后一行(l.modify_s())失败并出现以下错误:

INSUFFICIENT_ACCESS: {'info': u'00000005: SecErr: DSID-031A11D7, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0\n', 'desc': u'Insufficient access'}

我不知道问题出在我的 Python 代码上还是目录上用户配置错误。另外,我不是 AD 服务器的管理员(对此也没有任何了解)。

我是否需要对用户进行一些特殊设置以允许他自行更新密码?我是否使用正确的方法来更新密码?

注意:我也尝试过这种方法更新密码,但没有成功:

l.passwd_s(dn.format(username), old_pwd, new_pwd)

失败并出现错误:

PROTOCOL_ERROR({'info': u'0000203D: LdapErr: DSID-0C0911D4, comment: Unknown extended request OID, data 0, v3839', 'desc': u'Protocol error'},)

我到处都看到说此功能不应与 AD 服务器一起使用...

答案1

MS Active Directory 区分两种不同的用例。

注意:old_passwd_value并且new_passwd_value两者都必须是像您的代码片段中那样奇怪的双引号低端 UTF-16 编码。

如果管理员设置了其他用户的密码,您可以使用您的代码:

mod_list = [ (ldap0.MOD_REPLACE, 'unicodePwd', [new_passwd_value]), ]

如果用户更改了自己的密码,则必须使用:

mod_list = [ (ldap0.MOD_DELETE, 'unicodePwd', [old_passwd_value]), (ldap0.MOD_ADD, 'unicodePwd', [new_passwd_value]), ]

相关内容