Active-Directory

從 python-ldap 程式碼更新 AD 密碼:INSUFF_ACCESS_RIGHTS

  • October 26, 2018

我需要在 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 伺服器一起使用……

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]), ]

引用自:https://serverfault.com/questions/937330