"Fossies" - the Fresh Open Source Software Archive

Member "absence-v2.1/cgi-bin/AbsenceAuthentication.pm" (10 Dec 2013, 10219 Bytes) of package /linux/www/web-absence-2.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Perl source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "AbsenceAuthentication.pm" see the Fossies "Dox" file reference documentation.

    1 #---------------------------------------------------------------------
    2 # authentication
    3 # $Id: AbsenceAuthentication.pm 115 2013-12-10 23:45:43Z urban $
    4 # copyright Robert Urban
    5 #---------------------------------------------------------------------
    6 
    7 #======================================================================
    8 #    This file is part of Absence.
    9 #
   10 #    Absence is free software: you can redistribute it and/or modify
   11 #    it under the terms of the GNU General Public License as published by
   12 #    the Free Software Foundation, either version 3 of the License, or
   13 #    (at your option) any later version.
   14 #
   15 #    Absence is distributed in the hope that it will be useful,
   16 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
   17 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18 #    GNU General Public License for more details.
   19 #
   20 #    You should have received a copy of the GNU General Public License
   21 #    along with Absence.  If not, see <http://www.gnu.org/licenses/>.
   22 #======================================================================
   23 
   24 package AbsenceAuthentication;
   25 
   26 use FileHandle;
   27 use Fcntl ':flock'; # import LOCK_* constants
   28 use Carp;
   29 use Data::Dumper;
   30 
   31 $Data::Dumper::Indent = 1;
   32 
   33 my $COOKIE_NAME;
   34 
   35 BEGIN {
   36     # an instance has been specified
   37     if (exists($ENV{INSTANCE_NAME})) {
   38         $COOKIE_NAME = "absence-sid-$ENV{INSTANCE_NAME}";
   39     } else {
   40         $COOKIE_NAME = 'absence-sid';
   41     }
   42 }
   43 
   44 use AbsenceConfig;
   45 use AbsenceDB;
   46 use AbsenceLog;
   47 
   48 
   49 use Digest::MD5 qw(md5_base64);
   50 
   51 #---------------------------------------------------------------------
   52 # package globals
   53 #---------------------------------------------------------------------
   54 
   55 my $AUTH_TYPE       = AbsenceConfig::fetch('auth_type');
   56 my $AUTH            = AbsenceConfig::fetch('authentication');
   57 my $SECRET          = AbsenceConfig::fetch('secret');
   58 my $TOP_PAGE        = AbsenceConfig::fetch('top_page');
   59 my $CRED_SRC        = AbsenceConfig::fetch('credential_src');
   60 my $SESSION_FILE    = AbsenceConfig::fetch('session_file');
   61 my $SESSION_TIMEOUT = AbsenceConfig::fetch('session_timeout');
   62 my $PW_HASH_FORMAT  = AbsenceConfig::fetch('pw_hash_format');
   63 my $COLOR_MAIN      = AbsenceConfig::fetch('wp_main');
   64 my $COLOR_NOPRIV    = AbsenceConfig::fetch('wp_nopriv');
   65 my $JS_RELOAD_CONTROL   = 'function reload_control() { parent.control.location.reload(); }';
   66 
   67 our $SESSION;
   68 
   69 my $DEBUG       = 0;
   70 my $VERSION     = '2.0.1';
   71 my $AUTH_UID;
   72 
   73 #---------------------------------------------------------------------
   74 # class methods
   75 #---------------------------------------------------------------------
   76 
   77 sub checkAuthentication
   78 {
   79     my $cgi = shift;
   80 
   81     $DEBUG && abslog("checkAuthentication()");
   82 
   83     my $hack = AbsenceConfig::fetch('partial_auth_hack');
   84     (!$AUTH && !$hack) && return undef;
   85 
   86     my $sid = $cgi->cookie($COOKIE_NAME);
   87 
   88     ($AUTH && !defined($sid)) && notAuthenticated($cgi);
   89 
   90     $SESSION = AbsenceDB::getSession($sid, 0);
   91     $DEBUG && abslog("  SESSION=$SESSION");
   92 
   93     (!$AUTH && $hack) && return undef;
   94 
   95     defined($SESSION) || notAuthenticated($cgi);
   96 
   97     if ($SESSION->param('authed')) {
   98         return $SESSION->param('uid');
   99     }
  100 
  101     my $cookie = $cgi->cookie(
  102         -name   => $COOKIE_NAME,
  103         -value  => $SESSION->id(),
  104     );
  105     notAuthenticated($cgi, $cookie);
  106 }
  107 
  108 sub isAuthed
  109 {
  110     defined($SESSION) || confess "SESSION undefined";
  111     return $SESSION->param('authed') ? 1 : 0;
  112 }
  113 
  114 sub session
  115 {
  116     return $SESSION;
  117 }
  118 
  119 sub authUid
  120 {
  121     if (@_) {
  122         $AUTH_UID = shift;
  123         my $username = AbsenceDB::getUser(id => $AUTH_UID, 'username');
  124         defined($username) || die "unable to get username for uid=[$AUTH_UID]";
  125         AbsenceLog::setAuthUser($username);
  126     } else {
  127         return $AUTH_UID;
  128     }
  129 }
  130 
  131 #-----------------------------------------------------------------
  132 # when logout() is called, $SESSION is already defined
  133 #-----------------------------------------------------------------
  134 sub logout
  135 {
  136     my $q = shift;
  137 
  138     dbg("logout(), SESSION=[$SESSION]");
  139 
  140     my $cook = $q->cookie(
  141         -name       => $COOKIE_NAME,
  142         -value      => $SESSION->id(),
  143         -expires    => '-10y',
  144     );
  145 
  146     my @header = (-cookie => $cook);
  147 
  148     my @js_params = (
  149     );
  150 
  151     if ($AUTH_TYPE eq 'http') {
  152         my $lo_path = AbsenceConfig::fetch('js_dir_rel') . '/logout.js' . '?' . time();
  153         @js_params = (
  154             -script     => { -type => 'JAVASCRIPT', -src => $lo_path },
  155             -onLoad     => 'parent.control.document.write(""); clearAuthenticationCache(); parent.location.reload();',
  156         );
  157     }
  158     else {
  159         @js_params = (
  160             -script     => $JS_RELOAD_CONTROL,
  161             -onLoad     => 'reload_control();',
  162         );
  163     }
  164 
  165     print $q->header(@header),
  166         $q->start_html(
  167             -title  => 'Absence: logged off',
  168             -BGCOLOR    => $COLOR_MAIN,
  169             #-script        => "top.location = '$TOP_PAGE';",
  170             @js_params,
  171         ),
  172         $q->h1({-align => 'center'},"logged off."),
  173         $q->start_form(
  174             -action     => $TOP_PAGE,
  175             -method     => 'POST',
  176             -target     => '_parent',
  177         );
  178     if ($AUTH_TYPE eq 'simple') {
  179         print '<center>',
  180             $q->submit(-name => 'go_to_login', -value => 'Login to Absence'),
  181             '</center>';
  182     }
  183     print $q->end_form(), $q->end_html();
  184 
  185     $SESSION->delete();
  186     $SESSION->flush();
  187 }
  188 
  189 sub authenticateUser
  190 {
  191     my $cgi = shift;
  192 
  193     #-----------------------------------------------------------------
  194     # first find or create a session
  195     #-----------------------------------------------------------------
  196     
  197     dbg("authenticateUser: AUTH=[$AUTH]");
  198 
  199     my $sid = $cgi->cookie($COOKIE_NAME);
  200     $SESSION = AbsenceDB::getSession($sid, 1);
  201     abslog("authenticateUser: sid=[$sid]");
  202 
  203     my $cookie = $cgi->cookie(
  204         -name   => $COOKIE_NAME,
  205         -value  => $SESSION->id(),
  206     );
  207 
  208     if (!$AUTH) {
  209         if (!AbsenceConfig::fetch('partial_auth_hack')) {
  210             return (undef, $cookie);
  211         }
  212         my $action = $cgi->param('action');
  213         if (!defined($action)) {
  214             return (undef, $cookie);
  215         }
  216         if ($action eq 'Login') {
  217             if ($cgi->param('password') eq AbsenceConfig::fetch('partial_auth_hack_pw')) {
  218                 $SESSION->param(authed => 1);
  219                 $SESSION->param(uid => 0);
  220                 $SESSION->flush();
  221                 dbg("add session: uid=[$AUTH_UID], user=[$Q::username], addr=[$ENV{REMOTE_ADDR}]");
  222                 reloadTop($cgi, $cookie);
  223             } else {
  224                 authenticationFailed($cgi, $cookie);
  225             }
  226         }
  227         elsif ($action eq 'partial_auth') {
  228             authenticationForm($cgi, 'partial', 'Please enter the SuperUser password', $cookie);
  229         }
  230         
  231         return (undef, $cookie);
  232     }
  233 
  234     if ($SESSION->param('authed')) {
  235         abslog("session is authed");
  236         return $SESSION->param('uid');
  237     }
  238 
  239     $SESSION->expire($SESSION_TIMEOUT);
  240 
  241     if ($AUTH_TYPE eq 'http') {
  242         if (exists($ENV{REMOTE_USER})) {
  243             $AUTH_UID = AbsenceDB::getUser(username => $ENV{REMOTE_USER}, 'id');
  244             if (defined($AUTH_UID)) {
  245                 $SESSION->param(authed => 1);
  246                 $SESSION->param(uid => $AUTH_UID);
  247                 $SESSION->flush();
  248                 #return $AUTH_UID;
  249                 abslog("http authenticated as uid [$AUTH_UID], remote_user=[$ENV{REMOTE_USER}");
  250                 reloadTop($cgi, $cookie);
  251             }
  252         }
  253         notAuthenticated($cgi, $cookie);
  254     } elsif ($AUTH_TYPE eq 'simple') {
  255         dbg("auth_type = simple");
  256         if (length($Q::action) && ($Q::action eq 'Login')) {
  257             $AUTH_UID = checkPassword($Q::username, $Q::password);
  258             dbg("checkPassword returned [$AUTH_UID]");
  259             if ($AUTH_UID) {
  260                 $SESSION->param(authed => 1);
  261                 $SESSION->param(uid => $AUTH_UID);
  262                 $SESSION->flush();
  263                 dbg("add session: uid=[$AUTH_UID], user=[$Q::username], addr=[$ENV{REMOTE_ADDR}]");
  264                 reloadTop($cgi, $cookie);
  265             } else {
  266                 authenticationFailed($cgi, $cookie);
  267             }
  268         } else {
  269             dbg("last clause");
  270             authenticationForm($cgi, 'normal', undef, $cookie);
  271         }
  272     }
  273 
  274     exit;
  275 }
  276 
  277 sub reloadTop
  278 {
  279     my ($q, $cook) = @_;
  280     print $q->header(
  281             -cookie => $cook,
  282         ),
  283         $q->start_html(
  284             -title      => 'Absence: Authentication OK',
  285             -BGCOLOR    => $COLOR_MAIN,
  286             -script     => $JS_RELOAD_CONTROL,
  287             -onLoad     => "reload_control(); top.location = '$TOP_PAGE';",
  288         ),
  289         $q->start_form(
  290             -action     => $TOP_PAGE,
  291             -method     => 'POST',
  292             -target     => '_parent',
  293         ),
  294         $q->submit(action => 'Authentication OK. Click to Continue...'),
  295         $q->end_form(),
  296         $q->end_html();
  297     exit;
  298 }
  299 
  300 #---------------------------------------------------------------------
  301 # looks up the password for a user and checks the stored password
  302 # against the password passed as parameter.  if the passwords match,
  303 # the user-id is returned.  if no match, returns 0
  304 #---------------------------------------------------------------------
  305 sub checkPassword
  306 {
  307     my ($user, $pass) = @_;
  308 
  309     $DEBUG && abslog("checkPassword: user=$user, pass=[$pass]");
  310 
  311     if ($CRED_SRC eq 'absence') {
  312         #-----------------------------------------------------------
  313         # simple built-in authentication
  314         #-----------------------------------------------------------
  315         my $uref = AbsenceDB::getUser(username => $user);
  316         dbg("checkPassword: uref contents:\n".Dumper($uref)."\n--end--");
  317         defined($uref) || return 0;
  318         my $pw = ($PW_HASH_FORMAT eq 'md5')
  319             ? md5_base64($pass)
  320             : $pass;
  321         ($pw eq $uref->{password}) && return $uref->{id};
  322     }
  323 
  324     return 0;
  325 }
  326 
  327 sub authenticationForm
  328 {
  329     my ($q, $type, $msg, $cookie) = @_;
  330 
  331     print $q->header(-cookie => $cookie),
  332         $q->start_html(
  333             -title      => 'Absence Authentication',
  334             -BGCOLOR    => $COLOR_MAIN,
  335         );
  336     if ($msg) { print "<H2>$msg</H2>\n<P>\n"; }
  337     print "<H2>Please log in</H2>\n",
  338         $q->start_form(-method => 'GET'),
  339         '<TABLE>';
  340     if ($type eq 'normal') {
  341         print '<TR><TH ALIGN="right">USER:</TH><TD>',
  342         $q->textfield(
  343             -name       => 'username',
  344             -size       => 16,
  345             -maxlength  => 16,
  346         ),
  347         qq[</TD></TR>\n];
  348     }
  349     print qq[<TR><TH ALIGN="right">PASSWORD:</TH><TD>],
  350         $q->password_field(
  351             -name       => 'password',
  352             -size       => 16,
  353             -maxlength  => 16,
  354         ),
  355         "</TD></TR></TABLE><P>",
  356         $q->submit(action => 'Login'),
  357         $q->end_form(),
  358         $q->end_html();
  359 }
  360 
  361 sub authenticationFailed
  362 {
  363     my ($q, $cookie) = @_;
  364 
  365     print $q->header(
  366                 -expires => 'now',
  367                 -cookie => $cookie,
  368             ),
  369         $q->start_html(
  370             -BGCOLOR    => $COLOR_NOPRIV,
  371             -title      => 'Absence authentication failed',
  372         ),
  373         $q->h1('Authentication Failed'),
  374         $q->end_html;
  375 }
  376 
  377 sub notAuthenticated
  378 {
  379     my ($q, $cookie) = @_;
  380 
  381     my @cookie = defined($cookie) ? (-cookie => $cookie) : ();
  382 
  383     print $q->header(
  384             -expires    => 'now',
  385             @cookie,
  386         ),
  387         $q->start_html(
  388             -title      => 'Absence: not authenticated',
  389             -BGCOLOR    => $COLOR_MAIN,
  390         ),
  391         $q->h1('Not Authenticated'),
  392         $q->end_html;
  393     exit;
  394 }
  395 
  396 sub dbg
  397 {
  398     my $msg = shift;
  399     $DEBUG || return;
  400     abslog("auth: $msg");
  401 }
  402 
  403 1;