Página Inicial > Linux > Aplicação em PHP para alterar senha no AD

Aplicação em PHP para alterar senha no AD

Opa,

Primeiro a velha dica, “Este é um post técnico, para os que não entendem de Linux favor pular!” 🙂

Agora vamos ao que interessa, eu gosto de dizer que eu adoro meu trabalho pelo simples fato de não ter que mexer em lixo, mas às vezes sou obrigado a mexer no lixo para resolver algumas solicitações. Uma delas foi criar uma aplicação em PHP que pudesse alterar a senha do usuário no Active Directory da Mico$oft. No mesmo instante eu pensei: “Isso deve ser moleza, já devem ter pelo menos uns 100 scripts prontos ou até mesmo projetos no sourceforge.net!”, bem, para a minha surpresa isso demorou mais do que eu esperava. Para usar o php+ldap para acessar a base do AD é simples, para fazer consultas também é simples, mas para alterar/adicionar/excluir dados da base do AD o negócio é mais embaixo. Foi necessário criar um certificado raiz no servidor do AD e copiá-lo para o Linux, é isso mesmo que você está pensando, o AD só permite essas operações rodando sobre ssl (porta 636).

Para criar o certificado no servidor do AD será necessário (caso não esteja instalado) adicionar o serviço de certificação, se conecte no seu servidor AD, vá até adicionar/remover programas, depois adicionar/remover componentes, na lista marque a opção Serviços de Certificação e clique em OK/Finish ou qualquer outra coisa que seja, já esqueci! Após instalado abra o Serviço de Certificação (Iniciar / Ferramentas Administrativas / Autoridade de certificação), clique com o botão direito do mouse sobre o servidor que foi criado e escolha propriedades, depois clique no botão “Exibir certificado”, na janela que aparecer escolha a aba “Detalhes” e clique no botão “Copiar para arquivo…”, clique em avançar, escolha o formato codificado na base 64 e clique em avançar, escolha o local onde será gerado o certificado e depois OK/Finish ou qualquer outra coisa que seja, pronto! Criamos o certificado raiz do servidor AD, agora precisamos copiar para o servidor Linux, de preferência copie esse arquivo utilizando uma maneira segura (SSH).

Com o arquivo no servidor Linux mova-o para a pasta /etc/ssl/certs (Gentoo e OpenSuSE), ajuste as permissões (chmod 644 e chown root:) e execute o comando c_rehash. Abra o arquivo /etc/openldap/ldap.conf e adicione as seguintes linhas:

TLS_REQCERT never

TLS_CACERT /etc/ssl/certs/nome_certificado_copiado_do_ad.pem
TLS_CACERTDIR /etc/ssl/certs

Depois disso reinicie o serviço do Apache, crie sua aplicação PHP e pronto, lembrando que é necessário compilar o php com suporte a ldap e ssl! Abaixo tem um exemplo de uma aplicação para alterar a senha do usuário, lembre-se de adicionar as tags do php. Maiores informações no site do php.

$AD_server = “ldaps://srvad.teste.com”;
$AD_Auth_User = “Administrador@teste.com”;
$AD_Auth_PWD = “senha_administrador”;
$AD_dn = ‘CN=Users,DC=teste,DC=com’;
$uid = “usuario_alterar”;
$pwdold = “senha_antiga”;
$pwdtxt = “novasenha”;

$protocolVersion = 3;

$ldap = ldap_connect($AD_server);
if (!ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, $protocolVersion)) {
exit(‘Falha em definir protocolo na versao ‘.$protocolVersion);
}
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
ldap_bind($ldap);
if (ldap_errno($ldap) !== 0) {
exit(‘Nao foi possivel conectar no servidor’);
}
ldap_bind($ldap, $AD_Auth_User,$AD_Auth_PWD);
if (ldap_errno($ldap) !== 0) {
exit(‘ERRO: ‘.ldap_error($ldap));
}
$searchResults = ldap_search($ldap, $AD_dn, ‘cn=*’.$uid.’*’);
// no matching records
if ($searchResults === false){
exit(‘Usuario nao encontrado’);
}

if (!is_resource($searchResults)){
exit(‘Erro na consulta.’);
}
$newPassword = “\”” . $pwdtxt . “\””;
$len = strlen($newPassword);
$newPassw = “”;

for($i=0;$i<$len;$i++) { $newPassw .= “{$newPassword{$i}}00”; } $info[“unicodepwd”] = $newPassw; $entry = ldap_first_entry($ldap, $searchResults); if (!is_resource($entry)){ exit(‘Couldn’t get entry’); } $userDn = ldap_get_dn($ldap, $entry); $resultado = ldap_modify($ldap, $userDn, $info); if($resultado) { echo “Senha alterada com sucesso! “; }else{ echo “Erro! “; echo ldap_error($ldap).” “; }

Categories: Linux Tags: ,
  1. Júnior
    13, fevereiro, 2008 em 11:45 | #1

    Olá.
    Gostaria muito de saber onde obteve tais informações sobre o gerenciamentos de certificados ssl no linux e como chegou a desenvolver esse script, grato pela atenção.

    francisco.silva@satc.edu.br

  2. Luiz Agostinho (fl0cker)
    14, fevereiro, 2008 em 09:51 | #2

    Opa Júnior,

    Se observar no artigo tem a referência ao site do php.net onde obtive essas informações.

    Abraço!

  3. Luiz Agostinho (fl0cker)
    26, fevereiro, 2008 em 23:07 | #3

    Só mais uma dica (essa me salvou), depois que instalar o serviço de certificados no m$, favor reiniciar o mesmo! Isso me deu um danada dor de cabeça! Mas é assim mesmo; “Tem coisas… que só a mico$oft faz pra você!”

  4. Naiabeng
    12, novembro, 2008 em 19:09 | #4

    salvador da pátria !
    salve ao espirito colaborativo !

  5. Fellipe Castro
    2, dezembro, 2008 em 10:49 | #5

    Caro amigo. Depois de muitas tentativas de mudar a senha do LDAP, descobri seu blog e estou seguindo exatamente o passo-a-passo que você demonstrou! Porém, mesmo eu conseguindo me conectar e dar o bind, o seguinte erro sempre acontece: ‘Couldn’t get entry’. Ficaria muito grato se você pudesse me ajudar a solucionar esta questão. Obs: Estou usando LDAPS!

    Agradeço a atenção!

  6. Luiz Agostinho (fl0cker)
    5, dezembro, 2008 em 01:50 | #6

    Opa Fellipe,

    Bem como você não deixou um e-mail para contato vou responder aqui mesmo. Me responde uma coisa, você consegue fazer consultas pelo ldapsearch na linha de comando?

    Abraço!

  7. Fellipe Castro
    19, dezembro, 2008 em 17:20 | #7

    Não consigo amigo, o erro é o mesmo no ldapsearch! Tentamos via perl, via linha de comando, via php, e o erro permanece! Meu e-mail é: contact@fellipecastro.com! Agradeço muito a sua ajuda!

  8. 26, junho, 2009 em 19:52 | #8

    Oi Luiz,

    Após várias tentativas e vários erros, descobri finalmente onde era o problema.

    Olhe só.. qdo vc colou o código aqui no seu post, algumas “barras” (/) sumiram do código.
    aqui por exemplo : $newPassword = “\”” . $newPassword . “\””;

    Segue código que peguei do site PHP : http://www.php.net/manual/pt_BR/function.ldap-mod-replace.php

    $newPassword = “MyPassword”;
    $newPassword = “\”” . $newPassword . “\””;
    $len = strlen($newPassword);
    for ($i = 0; $i < $len; $i++)
    $newPassw .= “{$newPassword{$i}}00”;
    $newPassword = $newPassw;
    $userdata[“unicodepwd”] = $newPassword;
    $result = ldap_mod_replace($ad, $userDn, $userdata);
    if ($result) echo “User modified!” ;
    else echo “There was a problem!”;

  9. 29, junho, 2009 em 09:25 | #9

    Olá Gisele, realmente houve algum problema na postagem desse script que não apareceu as contra-barras, já atualizei o post!

    Obrigado!

  10. 1, julho, 2009 em 12:10 | #10

    @Luiz Agostinho
    oi Luiz,

    Estou tentando entender o que faz esta parte do código, poderia me ajudar?
    $len = strlen($newPassword); // tamanho da string da senha
    for ($i = 0; $i < $len; $i++)
    $newPassw .= “{$newPassword{$i}}00″; //???

    O resultado já será a senha criptografada?

  11. 1, julho, 2009 em 12:33 | #11

    @Gisele Brugger
    Achei …a resposta ..http://support.microsoft.com/kb/269190/pt-br

    A sintaxe do atributo unicodePwd é a seqüência de caracteres de octeto; no entanto, o serviço de diretório espera que o octeto-cadeia de caracteres conterá uma seqüência de caracteres UNICODE (como o nome do atributo indica). Isso significa que qualquer valor para este atributo passado LDAP deve ser seqüências de caracteres UNICODE que são codificados BER (Basic regras de codificação) como um octeto-cadeia de caracteres. Além disso, a seqüência UNICODE deve começar e terminar entre aspas que não fazem parte da senha desejada.”

  12. 1, julho, 2009 em 13:53 | #12

    Valeu Gisele, fica ai a resposta para quem tiver essa dúvida! 😉

  13. 12, abril, 2012 em 16:40 | #13

    Maravilha. Muito bom!

  14. 13, abril, 2012 em 08:34 | #14

    Opa Victor,

    Obrigado pela visita!

  15. Daniel
    5, março, 2015 em 16:08 | #15

    Olá, estou tentando implementar a rotina e estou tendo aquele erro “Couldn’t get entry”

    no ldapsearch o retorno é ‘array(1) { [“count”]=> int(0) } – Couldn’t get entry

    Acho que meu erro talvez esteja nesta linha

    $AD_dn = “CN=Users,DC=tjmmg,DC=com”;
    Quais os dados coloco aqui?

    Obrigado!

  16. 5, março, 2015 em 16:14 | #16

    Opa Daniel,

    Nessa linha em questão é onde estão os seus usuários, no seu caso aí, na OU Users no domínio TJMMG.COM.

    Abraço!

  17. Daniel
    5, março, 2015 em 16:23 | #17

    Neste caso então ela está certa? Por ex, la qdo fui criar o certificado no servidor(win server 2008) estava:
    CN = jm-SRV1-CA e qdo vou colocar alguma maquina no dominio uso o endereço: jm.mg.gov.br.

    Tentei desta forma: $AD_dn = “CN=jm-SRV1-CA,DC=jm,DC=mg,DC=gov,DC=br”;

    Mas ai o erro é Usuário não encontrado!

  18. 5, março, 2015 em 16:33 | #18

    Opa Daniel,

    Tenta dessa forma: $AD_dn = “CN=Users,DC=jm,DC=mg,DC=gov,DC=br”;

  19. Daniel
    6, março, 2015 em 10:18 | #19

    Bom dia Luiz, ainda não consegui. Aqui está o fonte:

    //Verificar jme e Cpf do usuário
    $host = ‘10.16.110.251’;
    $domain = ‘jm.mg.gov.br’;

    $AD_server = “10.16.110.251”;
    $AD_Auth_User = “usuarioAdmLdap@jm.mg.gov.br”;
    $AD_Auth_PWD = “senhaAdmLdap”;
    $AD_dn = “CN=Users,DC=jm,DC=mg,DC=gov,DC=br”;
    $uid = $_GET[‘jme’];
    $pwdold = $senhaAntiga;
    $pwdtxt = $senhaNova;

    $protocolVersion = 3;

    $ldap = ldap_connect($AD_server);
    if (!ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, $protocolVersion)) {
    exit(“Falha em definir protocolo na versao ” . $protocolVersion);
    }

    ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
    ldap_bind($ldap);

    if (ldap_errno($ldap) !== 0) {
    exit(“Nao foi possivel conectar no servidor”);
    }
    ldap_bind($ldap, $AD_Auth_User, $AD_Auth_PWD);

    if (ldap_errno($ldap) !== 0) {
    exit(“ERRO: ” . ldap_error($ldap));
    }
    $searchResults = ldap_search($ldap, $AD_dn, “cn=*” . $uid . “*”);

    $info = ldap_get_entries($ldap, $searchResults);
    echo $info[“count”] . ” registros encontrados!”;
    //>>>> RETORNA 0 REGISTROS ENCONTRADOS <<<<

    // no matching records
    if ($searchResults === false) {
    exit("Usuario nao encontrado");
    }

    if (!is_resource($searchResults)) {
    exit("Erro na consulta.");
    }
    $newPassword = "\"" . $pwdtxt . "\"";
    $len = strlen($newPassword);
    $newPassw = "";

    for ($i = 0; $i < $len; $i++) {
    $newPassw .= "{$newPassword{$i}}00";
    }
    $info["unicodepwd"] = $newPassw;
    $entry = ldap_first_entry($ldap, $searchResults);

    //echo var_dump($searchResults);

    if (!is_resource($entry)) {
    //echo var_dump(is_resource($entry));
    exit("Couldn't get entry");
    }

    Mesmo erro! Couldn't get entry Como posso montar um filtro do ldap_search manual?

    Novamente, Muito Obrigado pelo auxílio ai!

  20. 6, março, 2015 em 11:08 | #20

    Opa Daniel,

    Para fazer uma consulta pela linha de comando utilize o comando ldapsearch, dá uma verificada no man dele que tem todas as opções, inclusive com a utilização do certificado.

    Abraço!

  21. Daniel
    6, março, 2015 em 16:00 | #21

    Opa! Consegui fazer ele retornar o resultado, o problema era no $AD_dn = “CN=Users,DC=jm,DC=mg,DC=gov,DC=br”;

    Retirei o CN=Users e foi de boassa!

    Valeu!!

    Agora o próximo erro é Warning: ldap_modify() [function.ldap-modify]: Erro! Server is unwilling to perform Continuo na batalha aqui!

  22. Daniel
    6, março, 2015 em 16:27 | #22

    Outra dúvida, com aqui usamos centoS e win server 2008 o certificado não tem a extensão pem e sim cer, e há algum problema a galera da infra ter gerado um com 2048bits? ao invés de 64? me falaram isso agora!

  23. 6, março, 2015 em 16:31 | #23

    Opa Daniel, sobre as suas perguntas, o certificado pode ter qualquer nome e extensão, seu servidor CentOS não exige isso, contanto que esteja o nome certo na configuração, sobre a segunda acredito que também não tenha problema.

    Onde fica o usuário que está tentando alterar a senha? Não fica na OU Users do seu domínio?

    Abraço!

  24. Daniel
    10, março, 2015 em 09:52 | #24

    Bom dia Luiz,

    Vamos lá, esta imagem http://imgur.com/cq21o7r é a estrutura aqui! o usuário que estou usando para fazer login no AD, o que possui os direitos de alterar a senha está no OU Operadores, o usuário que loga na casa dele para alterar a senha pode estar em qualquer um desses OUs: AJME, TJM!

    Então eu teria que criar um outro $Ad_dn? buscando o usuário la no OU em que ele está?

  25. Daniel
    10, março, 2015 em 10:43 | #25

    Ele encontra o usuário perfeitamente o problema é na hora de rodar o ldap_modify!

    Mas fiz um teste aqui no Cent OS rodei um ldapsearch -H ldap://10.16.110.251 -b dc=jm,dc=mg,dc=gov,dc=br -x e ele retorna ldapsearch: comando não encontrado.

  26. 10, março, 2015 em 10:55 | #26

    Opa Daniel,

    E onde fica a conta jme que você esta tentando alterar a senha?

    Abraço!

  27. Daniel
    10, março, 2015 em 11:07 | #27

    CONSEGUIIIIIIIIII…

    Por um erro la no certificado, instalei o openldap e foi legal..! Fiz os testes e vi que ele estava procurando o certificado em um diretório e eu havia colocado um diretorio acima!

    Muito Obrigado!

  28. 10, março, 2015 em 11:09 | #28

    Opa Daniel,

    É isso aí, bom trabalho!

    Abraço!

  29. Alex
    20, maio, 2015 em 18:32 | #29

    Boa tarde,

    Estou com problema para realizar alteração de senha pelo LDAP. Copie o script do seu POST.

    Exibe o erro:
    Warning: ldap_modify(): Modify: Server is unwilling to perform.

    Pode me ajudar, agradecido.

  30. 28, maio, 2015 em 16:00 | #30

    Boa tarde Alex,

    Tenta fazer a consulta pela linha de comando utilizando o comando ldapsearch, provavelmente a consulta não está sendo realizada utilizando o certificado.

    Abraço!

  31. Vitor Reis França
    15, dezembro, 2015 em 14:46 | #31

    Boa tarde,

    Luiz, não estou conseguindo codificar a senha para mandar para o comando modificy segue erro:

    Undefined variable: newpass

    Poderia ajudar,
    Grato.

  32. Vitor Reis França
    15, dezembro, 2015 em 17:10 | #32

    Consegui consertar o problema da variável, mas não consigo codificar a senha.

  33. 20, dezembro, 2015 em 08:35 | #33

    Opa Vítor,

    É apresentada alguma mensagem de erro? Já verificou nos logs do servidor?

    Abraço!

  34. Vitor Reis França
    22, dezembro, 2015 em 17:18 | #34

    Exibe o erro:
    Warning: ldap_modify(): Modify: Server is unwilling to perform.

  35. Vitor Reis França
    22, dezembro, 2015 em 17:19 | #35

    Existe alguma forma de visualizar a senha codificada? Tentei imprimir mas exibe a senha que eu digitei

  36. 22, dezembro, 2015 em 17:45 | #36

    Opa Vitor,

    Essa mensagem aí é de erro de comunicação com o servidor, não tem nada a ver com a senha codificada! Talvez algum problema nas variáveis ou no certificado!

    Abraço!

  37. Vitor Reis França
    23, dezembro, 2015 em 15:57 | #37

    Boa tarde,

    Estou tentando alterar a senha, essa é a unica coisa que não consigo mudar.
    Consegui realizar consultas e conectar normalmente. O problema está na variável da senha.
    Eu consigo imprimir a variável depois do codigo que vc passou?

    $newPassword = “\”” . $pwdtxt . “\””;
    $len = strlen($newPassword);
    $newPassw = “”;

    for($i=0;$i<$len;$i++) { $newPassw .= “{$newPassword{$i}}00”; }

    Att,

  38. Ruan
    20, janeiro, 2016 em 09:08 | #38

    Olá, eu não estou conseguindo configurar o certificado no debian,
    ldap_bind(): Unable to bind to server: Can’t contact LDAP server.
    usando o ldaps.
    usando o ldap
    ldap_modify(): Modify: Insufficient access

  39. 10, março, 2016 em 18:53 | #39

    Opa Ruan,

    Verifica suas configurações e também o firewall no Windows.

    Abraço!

  40. Antonio
    28, setembro, 2016 em 12:19 | #40

    Bom dia… por favor me ajudem a encontrar uma solução?

    —————–

    connect success
    TLS: certdb config: configDir=’/etc/ssl/certs’ tokenDescription=’ldap(0)’ certPrefix=” keyPrefix=” flags=readOnly
    TLS: cannot open certdb ‘/etc/ssl/certs’, error -8018:Unknown PKCS #11 error.
    TLS: loaded CA certificate file /etc/ssl/certs/AD-DCON.cer.
    TLS: skipping ‘AD-DCON.cer’ – filename does not have expected format (certificate hash with numeric suffix)
    TLS: skipping ‘make-dummy-cert’ – filename does not have expected format (certificate hash with numeric suffix)
    TLS: skipping ‘ca-bundle.crt’ – filename does not have expected format (certificate hash with numeric suffix)
    TLS: skipping ‘ca-bundle.trust.crt’ – filename does not have expected format (certificate hash with numeric suffix)
    TLS: skipping ‘renew-dummy-cert’ – filename does not have expected format (certificate hash with numeric suffix)
    TLS: skipping ‘Makefile’ – filename does not have expected format (certificate hash with numeric suffix)
    TLS: certificate [(null)] is not valid – error -8179:Peer’s Certificate issuer is not recognized..
    TLS certificate verification: subject: -unknown-, issuer: CN=pom-AD-01-CA,DC=pom,DC=local, cipher: AES-256, security level: high, secret key bits: 256, total key bits: 256, cache hits: 0, cache misses: 0, cache not reusable: 0
    ldap_open_defconn: successful

    Gerei o certificado no AD, copiei o arquivo “AD-DCON.cer” pro servidor CentOS, editei o conf, atribui as permissões, r_rehash…

    O c_rehash resultou em “Doing /etc/pki/tls/certs”

    Que que eu faço pra isso funcionar?

    Quando rodo o php “ldap_modify”. resulta em:

    “read1msg: ld 0x7f927a42ed50 msgid 4 all 1
    read1msg: ld 0x7f927a42ed50 msgid 4 message type modify
    read1msg: ld 0x7f927a42ed50 0 new referrals
    read1msg: mark request completed, ld 0x7f927a42ed50 msgid 4
    request done: ld 0x7f927a42ed50 msgid 4
    res_errno: 50, res_error: <00002098: SecErr: DSID-03150BB9, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0"

  41. 28, setembro, 2016 em 17:58 | #41

    Opa Antonio,

    Me parece ser um erro na geração do seu certificado, “Unknown PKCS”, tenta gerar novamente.

    Abraço!

  1. Nenhum trackback ainda.