Atualize a senha do AD do código python-ldap: INSUFF_ACCESS_RIGHTS

1

Eu preciso implementar um recurso de "atualização de senha" em um aplicativo da web em Python (Flask). O objetivo é permitir que o usuário atualize sua senha em um servidor remoto do Active Directory.

Eu terminei com este teste unitário rápido

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)

Quando eu o executo, ele falha na última linha ( l.modify_s() ) com este erro:

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

Eu não sei se o problema vem do meu código python ou de uma configuração ruim do meu usuário no diretório. Além disso, não sou o administrador do servidor do AD (e não tenho nenhum conhecimento sobre isso).

Preciso definir algo especial no meu usuário para permitir que ele atualize sua senha automaticamente? Eu uso o método certo para atualizar a senha?

Nota: também tentei este método para atualizar a senha, sem sucesso:

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

falha com erro:

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

Eu leio em todos os lugares que essa função não deve ser usada com servidores do AD ...

    
por Antwane 26.10.2018 / 11:09

1 resposta

2

O MS Active Directory distingue dois casos de uso diferentes.

Observação: old_passwd_value e new_passwd_value precisam ser a codificação UTF-16 de baixa frequência com cotação dupla, como em seu snippet de código.

Se um administrador definir a senha de outro usuário, você poderá usar seu código:

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

Se o usuário alterar sua própria senha, você deverá usar:

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

    
por 26.10.2018 / 14:11