#!/usr/bin/perl use warnings; use strict; use CGI; use CGI::Session; use CGI::Carp qw( fatalsToBrowser ); use Template; use constant LDAP_SERVER => 'ldap.mycompany.com'; use constant CSS_URL => 'http://intranet.mycompany.com/style.css'; use constant ENTRAR_IMG => 'http://intranet.mycompany.com/images/entrar.gif'; use constant SAIR_IMG => 'http://intranet.mycompany.com/images/sair.gif'; use constant APLICAR_IMG => 'http://intranet.mycompany.com/images/aplicar.gif'; my $cgi = new CGI; my $session = new CGI::Session( 'driver:File', $cgi, {Directory=>'/tmp'} ); my $tmpl = new Template( { INCLUDE_PATH=> '/home/lcampos/src/ldap' } ); if( $cgi->param( 'logout' ) ){ print STDERR "MODO: LOGOUT\n"; # usuario deu logout, despacha. $session->delete(); print $cgi->redirect( $cgi->url( full=>1, query=>0 ) ); }elsif( $session->param( 'logged_in' ) && ! $cgi->param( 'enviar' ) ){ print STDERR "MODO: LDAP_EDIT_LOOP\n"; # Usuario logado, processa alteracoes. change_ldap_loop( $cgi, $session, $tmpl ); }elsif( $session->param( 'logged_in' ) && $cgi->param( 'enviar' ) ){ print STDERR "MODO: LDAP_COMMIT_EDITION\n"; # Usuario pediu para aplicar mudancas commit_edition( $cgi, $session, $tmpl ); }elsif( $cgi->param( 'username' ) && $cgi->param( 'passwd' ) ){ print STDERR "MODO: LDAP_EDITOR_AUTH\n"; # usuario tentanto logar, autentica... authenticate_user( $cgi, $session, $tmpl ); }else{ print STDERR "MODO: ASK_FOR_CREDENTIALS\n"; # usuario acabou de chegar, pede credenciais. show_login_form( $cgi, $session, $tmpl ); } sub show_login_form{ my( $cgi, $session, $tmpl, $message ) = ( shift, shift, shift, shift ); print $cgi->header(); $tmpl->process( 'prop_login.html', { action => $cgi->url( full=>1, query=>0 ), style => CSS_URL, login_img_url => ENTRAR_IMG, message => $message || '', } ) || confess $tmpl->error(); } # # Obtem o 'Distinguished Name' deste usuario no sistema, # atraves de um query LDAP anonimo. # sub get_dn{ my( $ldap, $username ) = ( new Net::LDAP( LDAP_SERVER ), shift ); return undef unless $ldap && $username; my $msg = $ldap->bind; confess $msg->error_name if $msg->is_error(); my $search = $ldap->search( base => 'dc=integral,dc=com,dc=br', filter => "(&(objectClass=person)(uid=$username))" ); confess "Muitos usuarios com mesmo identificador?!?!" if $search->count() > 1; my $entry = $search->pop_entry(); confess "Usuario nao encontrado" unless $entry; my $dn = $entry->dn(); $ldap->unbind(); return $dn; } sub commit_edition{ my( $cgi, $session, $tmpl ) = ( shift, shift, shift ); my $ldap = new Net::LDAP( LDAP_SERVER ); my $dn = $session->param( 'dn' ); my $msg = $ldap->bind( $dn, password => $session->param( 'passwd' ) ); confess $msg->error_name if $msg->is_error(); my $search = $ldap->search( base => 'dc=integral,dc=com,dc=br', filter => "(&(objectClass=person)(uid=" . $session->param('username')."))" ); confess $search->error_name if $search->is_error; confess "Muitos registros descobertos sob um mesmo DN!??!" if $search->count() > 1; my $entry = $search->pop_entry(); undef $search; undef $msg; my @changed = do{ my %changed = map {$_=>1} split qr/;/, $cgi->param( 'changeHandler' ); keys %changed; }; my $message; # Determina a alteracao de senha do usuario; my $passwd_changed = grep m/user_passwd2?/, @changed; @changed = grep ! m/user_passwd2?/, @changed; unshift @changed, 'userPassword' if $passwd_changed; # Processa cada valor alterado, trata de acordo... foreach my $value( @changed ){ my $new = $cgi->param( $value ); # Alterar senhas eh excecao: processa separado. if( $value eq 'userPassword' ){ my( $p1, $p2 ) = ( $cgi->param( 'user_passwd' ), $cgi->param( 'user_passwd2' ) ); if ( $p1 ne $p2 ) { $message = $cgi->font( {color=>"#CC3300"}, "Senhas digitadas não conferem" ); last; }else{ $entry->replace( userPassword => $p1 ); } }else{ if( $new ){ if( $entry->exists( $value ) ){ $entry->replace( $value => $cgi->param( $value ) ); }else{ $entry->add( $value => $cgi->param( $value ) ); } }else{ $entry->delete( $value ); } } } # Atualiza valores apenas quando nao existem erros. if( @changed && ! $message ){ $msg = $entry->update( $ldap ); confess $msg->error_name . "\n" . $msg->error if $msg->is_error; $message = $cgi->font( { color=>"#0033CC"}, "Atualizado com sucesso." ); } # Exibe HTML print $session->header; $tmpl->process( 'prop_edit.html', { style => CSS_URL, action => $cgi->url( -full=>1, -query=>0 ), message => $message, displayName => $entry->get_value( 'displayName' ), department => $entry->get_value( 'ou' ), initials => $entry->get_value( 'initials' ) || '', mail => $entry->get_value( 'mail' ), mobile => $entry->get_value( 'mobile' ) || '', pager => $entry->get_value( 'pager' ) || '', uid => $entry->get_value( 'uid' ), homePhone => $entry->get_value( 'homePhone' ) || '', apply_image_url => APLICAR_IMG, logout_image_url => SAIR_IMG, } ) or confess $tmpl->error(); } # # Processa alteracoes realizadas por um # usuario jah logado no sistema # sub change_ldap_loop{ my( $cgi, $session, $tmpl ) = ( shift, shift, shift ); my $ldap = new Net::LDAP( LDAP_SERVER ); my $dn = $session->param( 'dn' ); my $msg = $ldap->bind( $dn, password => $session->param( 'passwd' ) ); confess $msg->error_name if $msg->is_error(); my $search = $ldap->search( base => 'dc=integral,dc=com,dc=br', filter => "(&(objectClass=person)(uid=" . $session->param('username')."))" ); confess $search->error_name if $search->is_error; confess "Muitos registros descobertos sob um mesmo DN!??!" if $search->count() > 1; my $entry = $search->pop_entry(); undef $search; undef $msg; # update displayName key. unless( $entry->exists( 'displayName' ) ){ (my $displayName = join ' ', map $entry->get_value( $_ ), qw,cn sn,) =~ s/[\"\']//g; $entry->exists( 'displayName' )? $entry->replace( displayName => $displayName ) : $entry->add( displayName => $displayName ); my $msg = $entry->update( $ldap ); $msg->is_error() && confess $msg->error_name; } print $session->header; $tmpl->process( 'prop_edit.html', { style => CSS_URL, action => $cgi->url( -full=>1, -query=>0 ), displayName => $entry->get_value( 'displayName' ) || '', department => $entry->get_value( 'ou' ) || '', initials => $entry->get_value( 'initials' ) || '', mail => $entry->get_value( 'mail' ) || '', mobile => $entry->get_value( 'mobile' ) || '', pager => $entry->get_value( 'pager' ) || '', uid => $entry->get_value( 'uid' ), homePhone => $entry->get_value( 'homePhone' ) || '', apply_image_url => APLICAR_IMG, logout_image_url => SAIR_IMG, } ) or confess $tmpl->error(); } # # Tenta autenticar usuarios pelos parametros passados no CGI. # sub authenticate_user{ my( $cgi, $session, $tmpl ) = ( shift, shift, shift ); my( $username, $passwd ) = map $cgi->param($_), qw,username passwd,; use Net::LDAP; my $dn = get_dn( $username ) or confess "Nao consegui encontrar o Registro LDAP do usuario $username"; my $ldap = new Net::LDAP( LDAP_SERVER ) or confess "Desculpe, nao consegui conectar com o LDAP."; my $msg = $ldap->bind( $dn, password => $passwd ); do{ show_login_form( $cgi, $session, $tmpl, "Login Inválido" ); return; } if $msg->error_name eq 'LDAP_INVALID_CREDENTIALS'; confess $msg->error_name if $msg->is_error; $session->param( 'logged_in', 'YES' ); $session->param( 'username', $cgi->param( 'username' ) ); $session->param( 'passwd', $cgi->param( 'passwd' ) ); $session->param( 'dn', $dn ); $session->expire( 'logged_in' => '+10m' ); $session->expire( '+30m' ); # chegar ate aqui da acesso ao sistema de alteracao. change_ldap_loop( $cgi, $session, $tmpl ); }