21 de janeiro de 2008

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}}\000"; } $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)." "; }

42 comentários:

Júnior Rocha disse...

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

Luiz Agostinho (fl0cker) disse...

Opa Júnior,

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

Abraço!

Luiz Agostinho (fl0cker) disse...

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ê!"

Naiabeng disse...

salvador da pátria !
salve ao espirito colaborativo !

Anônimo disse...

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!

Luiz Agostinho (fl0cker) disse...

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!

Anônimo disse...

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!

Anônimo disse...

Opa blza? Sua aplicação me ajudou bsatante, valeu ;). Preciso sincronizar o servidor de emails com o AD, vc sabe como faço para alterar a senha no servidor de emails? Valeu

carusoedu@hotmail.com

Luiz Agostinho (fl0cker) disse...

Opa,

Não conheço nenhuma aplicação para sincronização das senhas, acho que o que você pode fazer é colocar o servidor de e-mail's para se autenticar no AD utilizando LDAP.

Abraço!

Anônimo disse...

Olá, sou eu (carusoedu) de novo. Eu tinha feito uma aplicação para mudar senhas no AD, trocar usuários, e depois sincronizar com OpenLdap mas do nada o negócio parou de funcionar(nao mexi mais no codigo)!Adaptei esse script q vc fez e tb dá erro, aparece could not get entry. Eu vi os logs do AD e ele consegue dar bind e search normalmente, o problema é em modify e add. Outra coisa: tb dá esso se eu tentar colocar ldaps, só com ldap parece q funciona melhor. Vc tem ideia do que eu estou errando?
Obrigado, Edu

Anônimo disse...

Obs: meu inglês é pessimo, mas se a tradução para a linha abaixo for: " O servidor não está a fim de executar a linha X" eu não faço a mínima idéia de como resolver =/ Warning: ldap_modify() [function.ldap-modify]: Modify: Server is unwilling to perform in /var/www/AD/alterar-senha.php on line 126
(Se for isso mesmo: o respostinha cretina essa, era melhor responder só : Error)

Anônimo disse...

mais informações: descobri que o problema é com o atributo unicodepwd. Eu troco por exemplo description e funciona, só o pwd q não quer ir! Será algo no AD?

Luiz Agostinho (fl0cker) disse...

Opa,

Cara, eu posso estar enganado, mas você só vai conseguir alterar a senha no AD se for via SSL (LDAPS), verifique se o certificado criado no servidor AD é o mesmo, uma vez eu tive problemas e descobri que o admin do AD tinha formatado a máquina, ou seja, tive que criar o certificado novamente e copiá-lo para o servidor.

Abraço!

Novo endereço: http://blog.luizagostinho.com/

Anônimo disse...

Hmm, isso mesmo, a senha ele só troca via ldaps. Eu tenho dois servidores, o principal e o de testes. No principal funcionou legal, mas no de testes não quer pegar =/.(ele nao da bind via ldaps entao nunca vai trocar a senha). O chefe do projeto não quer saber, não quer colocar a aplicação no principal se não funciona no de testes ( por mais q funcione na principal...)
Valeu pela ajuda! Se eu descobrir a origem do problema eu posto aqui

Anônimo disse...

Opa deu certo! Tinham alterado sem me avisar arquivos de configuração. Eu arrumei mas faltava reiniciar o apache...

Anônimo disse...

Para adicionar os usuários em grupos eu preciso alterar somente o atributo member of ou eu tenho que trocar tb no grupo? C comé q eu troco no grupo oO??

Obrigado!

Luiz Agostinho (fl0cker) disse...

Opa,

Hehehe... como lhe disse, já tinha acontecido comigo isso também!

Cara não entendi direito essa tua última pergunta!

Abraço!

Anônimo disse...

hmm, não me expressei bem. O que acontece é o seguinte: aqui na empresa precisam q eu faça uma aplicação para criar usuários no AD (e openldap) e alterar senhas. Esses usuários, na hora de serem criados, precisam pertencer a determinados grupos. Eu dei uma fuçada nos ldifs e ví que existe um atributo chamado 'memberOf', e neste atributo você poe o grupo.

Estou tentando criar os usuários em um grupo pré-definido ( na verdade eu fiz um scanner para determinar todos os grupos possíveis de forma dinamica e jogar numa drop down list) mas o servidor dá aquela maldita mensagem de erro: server is unwilling to perform... :P

detalhe: eu estou conectando com ldaps, não sei pq da essa mensagem. Valeu!

Anônimo disse...

Cara, boa tarde!
Tô tentando implantar seu código no meu ldap que fica no linux Debian Etch, e temos o seguinte erro:
Warning: ldap_bind() [function.ldap-bind]: Unable to bind to server: Can't contact LDAP server in /var/www/site_Ldap/chgpassAD.php on line 22
ERRO: Can't contact LDAP server .
Além disso como posso alterar a senha do sambaLMPassord e sambaNTPassword neste processo.
Grato
Marcos (m_j_santos@hotmail.com)

Anônimo disse...

Cara, desculpe, mandei o erro de outro aplicativo. O correto é:
Warning: ldap_modify() [function.ldap-modify]: Modify: Server is unwilling to perform in /var/www/site_Ldap/chgpassAD.php on line 45
Erro! Server is unwilling to perform .
Fora isso gostaria de saber também, como incluir no procedimento a alteração das senhas do sambaLMPassord e sambaNTPassword .
Grato.
Marcos

Luiz Agostinho (fl0cker) disse...

Opa Marcos,

Acredito que esse erro pode estar relacionado a duas coisas:

- Configuração incorreta do DN (algum erro de digitação talvez);

- Servidor Web (PHP) não está com o certificado instalado corretamente ou não tem acesso ao servidor AD na porta 636 (SSL).

Não entendi direito a sua última pergunta, se eu não me engano eles são alterados assim que a senha é alterada.

Abraço!

Anônimo disse...

Bom dia LA, bele?
Seguinte to estranhando o retorno do seguinte comando:

$searchResults = ldap_search($ldap, $AD_dn, 'cn='.$uid.);

ele sempre retorna o seguinte:

Resource id #3

Vc sabe o que está pegando??

ABs
Marcos

Luiz Agostinho (fl0cker) disse...

Opa Marcos,

Não sou bom com PHP, mas acredito que esse código de retorno deve ser referente ao conteúdo retornado ser um array, pelo menos (se eu não me engano) foi isso o que me informou um amigo desenvolvedor na época que encontrei um código de retorno parecido com esse.

Abraço!

Anônimo disse...

Cara, eu desconfiava que era um array tb. Mas consegui resolver... valeu mesmo. tks...

Anônimo disse...

Cara funcionou... agora eu quero dar um passo maior, alterar a senha do samba e também do windows... eu sei que é possível. Vc tem algum código para ajudar???
abs
Marcos

Luiz Agostinho (fl0cker) disse...

Opa Marcos,

Não tenho nenhum código para fazer isso que deseja, mas não deve ser complicado de implementar, dá uma vasculhada pela Internet que você deve achar algo!

Abraço!

Unknown disse...

Olá,
Fiz todos os passos que você passou, mas mesmo assim continua dando um erro: Unknown attribute in the data in

Tentei fazer de uma outra forma também, mas deu outro erro: Modify: Server is unwilling to perform in
A outra forma que eu tentei fazer é a seguinte:

$entry["unicodePwd"] = sha1('teste');
if (ldap_modify($ds,"CN=$usuario;ou=$ou,dc=$dc,dc=com,dc=br",$entry) === false){
$error = ldap_error($ds);
echo "Erro: ".$error."
";
} else {
$error = ldap_error($ds);
echo "ALTEROU: ".$error."
";
}
echo "
";
echo "Fechando conexão";
ldap_close($ds);


Você poderia me ajudar? tem alguma idéia do que pode ser?

abraço

Luiz Agostinho (fl0cker) disse...

Opa Gabriel,

Conforme comentário anterior que deixei para o Marcos, acredito que esse erro pode estar relacionado a duas coisas:

- Configuração incorreta do DN (algum erro de digitação talvez);

- Servidor Web (PHP) não está com o certificado instalado corretamente ou não tem acesso ao servidor AD na porta 636 (SSL).

Abraço! (http://blog.luizagostinho.com)

Anônimo disse...

Boa Tarde.
Sobre o post que colocou para alterar a senha do AD via php.
Cara como posso verificar se o certificado criado no windows esta correto no linux?
Na minha maquina conecta com ldaps mas não da bind nenhum.

Olha o erro:

CONEXAO: Resource id #2
Warning: ldap_bind() [function.ldap-bind]: Unable to bind to server: Can't contact LDAP server in C:\projetos\autoatendimento\addAd2.php on line 32
ERRO: Can't contact LDAP server

Luiz Agostinho (fl0cker) disse...

Opa Julio,

O teste que pode-se fazer para saber se o certificado está sendo listado é com o comando c_rehash, geralmente quando não consegue conexão com o servidor LDAP pode ser firewall ou configuração do nome do host!

Abraço!

Greyson "Kazenin" disse...

olá fl0cker estou com o mesmo problema do Fellipe " Couldn't get entry" o meu endereço é greysonsilva et gmail.com agradeço desde já sua atenção

Luiz Agostinho (fl0cker) disse...

Opa Greyson,

Cara, eu posso estar enganado, mas você só vai conseguir alterar a senha no AD se for via SSL (LDAPS), verifique se o certificado criado no servidor AD é o mesmo, uma vez eu tive problemas e descobri que o admin do AD tinha formatado a máquina, ou seja, tive que criar o certificado novamente e copiá-lo para o servidor.

Abraço!

Novo endereço: http://blog.luizagostinho.com/

Anônimo disse...

E ae rapazeada blz...
Respondendo a duvida do colega Greyson, para alterações no AD é obrigatório conexão ldaps com certificado digital.
EU ja tive muito problema com ad e php e depois de muita pesquisa e ajuda dos colegas de fóruns inclusive desde blog. A interação com o AD via LDAP funciona da seguinte forma:
Para realizar apenas consulta o AD aceita conexão anonima usando ldap simples.
Para alteração de dados dentro do AD então é obrigatório a criação de certificado digital, conexão ssl usando LDAPS.
Para mais detalhes entre em contato comigo e vemos se posso te ajudar.

juliopedrogomes@gmail.com

Tobias Tromm disse...

Luiz, posso fazer alguns comentários e postar o código no meu blog? Obrigado. Tobias.

Luiz Agostinho (fl0cker) disse...

Opa Tobias,

Fique a vontade! Só lembre-se de fazer referência!

Abraço!

Unknown disse...

Saudações Luiz, primeiramente gostaria de parabenizado pelo artigo de grande valia.
Luiz, abusando um pouco a mais da sua boa vontade e necessitando de um help se possível. Construí uma página onde consigo trocar a senha da maioria dos usuários do AD. Contudo tem alguns que não vai de jeito nenhum. Já busquei em tudo e não consegui resolver o problema. A princípio acho que o problema pode estar diretamente ligado ao AD mas não consigo identificar. Você teria uma ideia ?
Desde já seguem meus agradecimentos.

Anônimo disse...

Olá Luiz, aqui é a Elora (elora.venske@lince.com.br). Parabéns pelo código. Mas estou com um probleminha na hora de fazer a alteração da senha no AD. Esta retornando a seguinte mensagem de erro:
ldap_modify(): Modify: Server is unwilling to perform
Você sabe o que poderia ser este erro? Obrigada

TheRuleS disse...

Instalasse o serviço de certificado ? liberasse a porta de comunicação ?

Unknown disse...

Luiz, esse blog ainda está ativo?
Pode me ajudar com alteração de senha no AD?

Luiz Agostinho (fl0cker) disse...

Opa Victor,

Esse blog está congelado, meu novo endereço é blog.luizagostinho.com, mas continuo respondendo aqui também, qual a dúvida?

Abraço!

rodrigo borges disse...

kkk ficou funcionando aqui e o blog que ele mudou nao existe mais..kk

Luiz Agostinho (fl0cker) disse...

Opa Rodrigo, realmente o endereço blog.luizagostinho.com não existe mais.