package FPanel::Login; use strict; use warnings; use utf8; use base 'CGI::Application'; use CGI::Application::Plugin::AutoRunmode; use CGI::Application::Plugin::Session; use CGI::Application::Plugin::Authentication; use CGI::Application::Plugin::Redirect; use CGI::Application::Plugin::ConfigAuto qw/cfg/; use Net::LDAP; use Authen::SASL; # This method is called right before the 'setup' method below. It # initializes the session and authentication configurations. sub cgiapp_init { my $self = shift; $self->session_config( CGI_SESSION_OPTIONS => [ 'driver:DB_File;serializer:freezethaw' , $self->query , { FileName => '/tmp/fpanel-cgisessions.db', UMask => 0600 } , { name => 'FripostAdminPanel_SessAuth' } ], DEFAULT_EXPIRY => '+24h', COOKIE_PARAMS => { -name => 'FripostAdminPanel_SessAuth' , -path => '/cgi-bin/' # Expires when the browser quits , -expires => -1 ,'-max-age' => -1 # TODO: Turn the secure flag for HTTPS connections , -secure => 0 # We are not using JavaScript in this framework , -httponly => 1 }, SEND_COOKIE => 1, ); # Configure authentication parameters $self->authen->config( DRIVER => [ 'Generic' , sub { &authenticate(@_) } ], STORE => 'Session', LOGIN_RUNMODE => 'login', RENDER_LOGIN => \&login_box, LOGIN_SESSION_TIMEOUT => { IDLE_FOR => '30m' }, LOGOUT_RUNMODE => 'logout', ); # The run modes that require authentication $self->authen->protected_runmodes( qw /okay error_rm/ ); } # This method is called by the inherited new() constructor method. sub setup { my $self = shift; $self->tmpl_path( 'template/' ); $self->mode_param( \&mymode_param ); } # This method chooses the Run Mode depending on the URL and query string. sub mymode_param { my $self = shift; my $q = $self->query; my @path = split /\//, $ENV{PATH_INFO}; pop @path if $#path > 0 and $path[$#path] eq ''; my $mode = 'DomainList'; if (defined $q->param('authen_username') and defined $q->param('authen_password')) { $mode = 'okay' } elsif (defined $q->param('a')) { my $a = $q->param('a'); if ($a eq 'login') { $mode = 'login'; } elsif ($a eq 'logout') { $mode = 'logout'; } elsif ($a eq 'AddDomain') { $mode = 'AddDomain'; } } elsif ($#path < 0) { $mode = 'DomainList'; } elsif ($path[1] ne '') { # $domain = $path[1]; $mode = 'index'; } print STDERR $q->self_url, "\n"; print STDERR $ENV{PATH_INFO} . '?' . $q->query_string . " -> " . $mode . "\n"; return $mode; } sub okay : Runmode { my $self = shift; my $destination = $self->query->param('destination') // $self->query->url; return $self->redirect($destination); } sub login : Runmode { my $self = shift; my $url = $self->query->url; # Do not come back here afterwards $self->query->delete( 'a' ) if (defined $self->query->param('a')) and $self->query->param('a') eq 'login'; # A logged user has no reason to ask for a relogin $self->authen->logout if $self->authen->is_authenticated; $self->query->param( destination => $self->query->self_url) unless (defined $self->query->param('destination')); return $self->login_box; } sub login_box { my $self = shift; my $template = $self->load_tmpl('login.html' , cache => 1 , utf8 => 1 ); my $destination = $self->query->param('destination') // $self->mymode_param(); $template->param(ERROR => $self->authen->login_attempts); $template->param(DESTINATION => $destination); return $template->output; } sub logout : Runmode { my $self = shift; if ($self->authen->is_authenticated) { $self->authen->logout; $self->session->delete; $self->session->flush; } # Do not come back here afterwards $self->query->delete( 'a' ) if (defined $self->query->param('a')) and $self->query->param('a') eq 'logout'; return $self->redirect($self->query->self_url); } sub error_rm : ErrorRunmode { my $self = shift; my $error = shift; my $template = $self->load_tmpl('error.html' , cache => 1 , utf8 => 1 ); $template->param(NAME => 'ERROR'); $template->param(MESSAGE => $error); $template->param(URL => $self->query->url); return $template->output; } #sub AUTOLOAD : Runmode { # my $self = shift; # my $rm = shift; # my $template = $self->load_tmpl("template/error.html"); # $template->param(NAME => 'AUTOLOAD'); # $template->param(MESSAGE => # "Error: could not find run mode \'$rm\'\n"); # $template->param(URL => $self->query->url); # return $template->output; #} sub authenticate { # my $self = shift; my ($u, $p) = @_; my ($l,$d) = split /@/, $u, 2; # my %CFG = $self->cfg; unless (defined $d) { $d = 'fripost.org'; $u .= '@'.$d; } my $ldap = Net::LDAP->new( 'ldap://127.0.0.1:389' ); my $mesg = $ldap->bind ( "fvu=$l,fvd=$d,ou=virtual,o=mailHosting,dc=fripost,dc=dev" , password => $p ); $mesg->code ? 0 : $u; } 1;