Segunda-feira, Janeiro 21, 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)." "; }

18 comentários:

Júnior 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 !

Fellipe Castro 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!

Fellipe Castro 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!