package DADA::App::Session; use strict; use lib qw(./ ../ ../DADA ../DADA/perllib); use DADA::Config; use DADA::Security::Password; use DADA::MailingList::Settings; use DADA::App::Guts; sub new { my $class = shift; my %args = (-List => undef, @_); my $self = {}; bless $self, $class; $self->_init(\%args); return $self; } sub _init { my $self = shift; $self->{can_use_cgi_session} = $self->can_use_cgi_session(); $self->{can_use_data_dumper} = $self->can_use_data_dumper(); } sub login_cookie { my $self = shift; my %args = ( -cgi_obj => undef, -list => undef, -password => undef, @_); die 'no CGI Object (-cgi_obj)' if ! $args{-cgi_obj}; my $cookie; my $q = $args{-cgi_obj}; my $list = $args{-list}; my $ls = DADA::MailingList::Settings->new(-List => $list); my $li = $ls->get; my $cipher_pass = DADA::Security::Password::cipher_encrypt($li->{cipher_key}, $args{-password}); if($self->{can_use_cgi_session} == 1 && $self->{can_use_data_dumper} ==1){ require CGI::Session; CGI::Session->name($LOGIN_COOKIE_NAME); my $session = new CGI::Session(undef, undef, {Directory=>$TMP}); $session->expire($COOKIE_PARAMS{-expires}); $session->param('Admin_List', $args{-list}); $session->param('Admin_Password', $cipher_pass); $cookie = $q->cookie(-name => $LOGIN_COOKIE_NAME, -value => $session->id, %COOKIE_PARAMS); }else{ $cookie = $q->cookie(-name => $LOGIN_COOKIE_NAME, -value => { admin_list => $args{-list}, admin_password => $cipher_pass }, %COOKIE_PARAMS ); } return $cookie; } sub change_login { my $self = shift; my %args = (-cgi_obj => undef, -list => undef, @_ ); die "no list!" if ! $args{-list}; my $q = $args{-cgi_obj}; my $cookie; if($self->{can_use_cgi_session} == 1 && $self->{can_use_data_dumper} == 1){ require CGI::Session; CGI::Session->name($LOGIN_COOKIE_NAME); my $old_session = new CGI::Session(undef, $q, {Directory=>$TMP}); my $phr = $old_session->param_hashref(); my $old_password = $old_session->param('Admin_Password'); my $old_list = $old_session->param('Admin_List'); $old_session->delete(); my $session = new CGI::Session(undef, undef, {Directory=>$TMP}); $session->expire($COOKIE_PARAMS{-expires}); my $old_ls = DADA::MailingList::Settings->new(-List => $old_list); my $old_li = $old_ls->get; my $ue_old_password = DADA::Security::Password::cipher_decrypt($old_li->{cipher_key}, $old_password); my $ls = DADA::MailingList::Settings->new(-List => $args{-list}); my $li = $ls->get; my $cipher_pass = DADA::Security::Password::cipher_encrypt($li->{cipher_key}, $ue_old_password); $session->param('Admin_List', $args{-list}); $session->param('Admin_Password', $cipher_pass); $cookie = $q->cookie(-name => $LOGIN_COOKIE_NAME, -value => $session->id, %COOKIE_PARAMS); return $cookie; }else{ my %old_cookie = $q->cookie($LOGIN_COOKIE_NAME); my $old_password = $old_cookie{admin_password}; my $old_list = $old_cookie{admin_list}; my $old_ls = DADA::MailingList::Settings->new(-List => $old_list); my $old_li = $old_ls->get; my $ue_old_password = DADA::Security::Password::cipher_decrypt($old_li->{cipher_key}, $old_password); my $ls = DADA::MailingList::Settings->new(-List => $args{-list}); my $li = $ls->get; my $cipher_pass = DADA::Security::Password::cipher_encrypt($li->{cipher_key}, $ue_old_password); $cookie = $q->cookie(-name => $LOGIN_COOKIE_NAME, -value => { admin_list => $args{-list}, admin_password => $cipher_pass, }, %COOKIE_PARAMS ); } return $cookie; } sub logout_cookie { my $self = shift; my %args = ( -cgi_obj => undef, @_, ); die 'no CGI Object (-cgi_obj)' if ! $args{-cgi_obj}; my $q = $args{-cgi_obj}; my $cookie; if($self->{can_use_cgi_session} == 1 && $self->{can_use_data_dumper} == 1){ require CGI::Session; CGI::Session->name($LOGIN_COOKIE_NAME); my $session = new CGI::Session(undef, $args{-cgi_obj}, {Directory=>$TMP}); $session->delete(); $cookie = $q->cookie(-name => $LOGIN_COOKIE_NAME, -value => undef, -path => '/'); }else{ $cookie = $q->cookie(-name => $LOGIN_COOKIE_NAME, -value => {admin_list => '', admin_password => ''}, -path => '/'); } return $cookie; } sub can_use_cgi_session { my $self = shift; my $can_use_cgi_session = 0; if($] >= 5.006_001){ eval {require CGI::Session}; if(!$@){ $can_use_cgi_session = 1; } } return $can_use_cgi_session; } sub can_use_data_dumper { my $self = shift; my $can_use_data_dumper = 0; if($] >= 5.006_001){ eval {require Data::Dumper}; if(!$@){ $can_use_data_dumper = 1; } } return $can_use_data_dumper; } sub check_session_list_security { my $self = shift; my %args = (-Function => undef, -cgi_obj => undef, -manual_override => 0, @_); warn '$args{-manual_override} ' . $args{-manual_override}; die 'no CGI Object (-cgi_obj)' if ! $args{-cgi_obj}; my $q = $args{-cgi_obj}; if($self->{can_use_cgi_session} == 1 && $self->{can_use_data_dumper} == 1){ require CGI::Session; CGI::Session->name($LOGIN_COOKIE_NAME); my $session = new CGI::Session(undef, $q, {Directory=>$TMP}); $args{-Admin_List} = $session->param('Admin_List'); $args{-Admin_Password} = $session->param('Admin_Password'); }else{ my %logincookie = $q->cookie($LOGIN_COOKIE_NAME); $args{-Admin_List} = $logincookie{admin_list}; $args{-Admin_Password} = $logincookie{admin_password}; } $args{-IP_Address} = $ENV{REMOTE_ADDR}; my ($problems, $flags, $root_logged_in) = $self->check_admin_cgi_security(-Admin_List => $args{-Admin_List}, -Admin_Password => $args{-Admin_Password}, -Function => $args{-Function}, -IP_Address => $ENV{REMOTE_ADDR}); if($problems){ if($args{-manual_override} == 1){ return ($args{-Admin_List}, $root_logged_in, 0); }else{ $self->enforce_admin_cgi_security(-Admin_List => $args{-Admin_List}, -Admin_Password => $args{-Admin_Password}, -Flags => $flags); } }else{ return ($args{-Admin_List}, $root_logged_in, 1); } } sub check_admin_cgi_security { my $self = shift; my %args = (-Admin_List => undef, -Admin_Password => undef, -Function => undef, -IP_Address => undef, @_); my $root_logged_in = 0; require DADA::Security::Password; require DADA::MailingList::Settings; my $problems = 0; my %flags = (); unless(defined($args{-Admin_List}) && defined($args{-Admin_Password})){ $problems++; $flags{"need_to_login"} = 1; return ($problems, \%flags, 0); } if($REFERER_CHECK == 1){ if(check_referer(CGI::referer()) != 1){ $problems++; $flags{"need_to_login"} = 1; return ($problems, \%flags, 0); } } if(@ALLOWED_IP_ADDRESSES){ my $ip_check = 0; foreach(@ALLOWED_IP_ADDRESSES){ if($_ eq $args{-IP_Address}){ $ip_check = 1; last; } } #error! no ip! if($ip_check == 0){ $problems++; $flags{"bad_ip"} = 1; } } my $list = $args{-Admin_List}; my ($list_exists) = check_if_list_exists(-List=>$list); # error! no such list if($list_exists <= 0){ $problems++; $flags{"no_list"} = 1; } my $ls = DADA::MailingList::Settings->new(-List => $list); my $list_info = $ls->get; # I do not like this anymore. unless($list_info->{cipher_key}){ $ls->save(); #this won't work anyways... $list_info = $ls->get; } my $cipher_pass = DADA::Security::Password::cipher_decrypt($list_info->{cipher_key}, $args{-Admin_Password}); my $password_check = DADA::Security::Password::check_password($list_info->{password},$cipher_pass); # if root logging in is set, let em login with the root password if($ALLOW_ROOT_LOGIN == 1){ if(defined($PROGRAM_ROOT_PASSWORD)){ my $cipher_dada_root_password = DADA::Security::Password::cipher_decrypt($list_info->{cipher_key}, $args{-Admin_Password}); if($ROOT_PASS_IS_ENCRYPTED == 1){ my $root_password_check = DADA::Security::Password::check_password($PROGRAM_ROOT_PASSWORD, $cipher_dada_root_password); if($root_password_check == 1){ $password_check++; $root_logged_in = 1; } }else{ my $cipher_dada_admin_password = DADA::Security::Password::cipher_decrypt($list_info->{cipher_key}, $args{-Admin_Password}); if($PROGRAM_ROOT_PASSWORD eq $cipher_dada_admin_password){ $password_check++; $root_logged_in = 1; } } } } if ($password_check < 1){ $problems++; $flags{"invalid_password"} = 1; } if($root_logged_in == 0){ if((!defined($list_info->{password})) || ($list_info->{password} eq "")){ die "List password for $list is blank! It is advised that you make sure your list settings file is not corrupted, or reset you list password."; $problems++; $flags{"no_list_password"} = 1; } } # last but not least, we see if they're allowed in this particular function. # we are sneaky shits, aren't we?! if($root_logged_in != 1){ require DADA::Template::Widgets::Admin_Menu; my $function_permissions = DADA::Template::Widgets::Admin_Menu::check_function_permissions(-List_Ref => $list_info, -Function => $args{-Function}); if ($function_permissions < 1){ $problems++; $flags{"no_admin_permissions"} = 1; } } return ($problems, \%flags, $root_logged_in); } sub enforce_admin_cgi_security { my $self = shift; my %args = (-Admin_List => undef, -Admin_Password => undef, -Flags => {}, @_); my $flags = $args{-Flags}; require DADA::App::Error; my @error_precedence = qw(need_to_login bad_ip no_list no_list_password invalid_password no_admin_permissions); foreach (@error_precedence){ if($flags->{$_} == 1){ my $error_msg = DADA::App::Error::cgi_user_error(-List => $args{-Admin_List}, -Error => $_); #go, errors in the... whatever shouldn't make the script process anything more print $error_msg; exit; } } } sub remove_old_session_files { # Swiped from: # Sebastian BŠr, Software Developer, OSEK Business Division # 3SOFT GmbH - Member of the Elektrobit Group my $self = shift; my $baseDir = $TMP; # Open the session directory... opendir(DIR, $baseDir) or die "Cannot open session dir: " . $!; while(my $filename = readdir(DIR)) { # Only touch session files: if($filename =~ /^cgisess_[a-f0-9]{32}$/){ my $etime = 0; my $atime = 0; my $file = $baseDir . "/" . $filename; if(open(FH, "<$file")){ $_ = ; if(/_SESSION_ETIME" => "?(\d+)/){ $etime = $1; } if(/_SESSION_ATIME" => "?(\d+)/){ $atime=$1; } close(FH); } else { warn("Unable to open file: " . $!); } # Print the filename: #print("$filename: ") if($verbose); if($etime){ # How many seconds are left? my $left=$etime+$atime-time(); # To be sure no interaction with concurrent file access occurs we only # remove files that have expired at least a minute ago. if($left<-60) { # print("Expired (at least a minute ago)\n") if($verbose); } else { if($left<0) { #print("Expired (less than a minute ago) / keep\n") if($verbose); } else { #print("Alive ($left sec remaining)\n"); } next; } } else { #print("Missing expiry time\n") if($verbose); } # Time to get rid of expired files: #unless($printOnly) { $file = make_safer($file); unlink($file); #$removed++; #} } } closedir(DIR); } sub DESTROY {} 1;