koha-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Koha-cvs] CVS: koha/C4 Auth.pm,1.11,1.12


From: Andrew Arensburger
Subject: [Koha-cvs] CVS: koha/C4 Auth.pm,1.11,1.12
Date: Sun, 06 Oct 2002 17:34:27 -0700

Update of /cvsroot/koha/koha/C4
In directory usw-pr-cvs1:/tmp/cvs-serv7631

Modified Files:
        Auth.pm 
Log Message:
Added POD and some comments.


Index: Auth.pm
===================================================================
RCS file: /cvsroot/koha/koha/C4/Auth.pm,v
retrieving revision 1.11
retrieving revision 1.12
diff -C2 -r1.11 -r1.12
*** Auth.pm     5 Oct 2002 09:48:35 -0000       1.11
--- Auth.pm     7 Oct 2002 00:34:24 -0000       1.12
***************
*** 31,34 ****
--- 31,56 ----
  $VERSION = 0.01;
  
+ =head1 NAME
+ 
+ C4::Auth - Authenticates Koha users
+ 
+ =head1 SYNOPSIS
+ 
+   use CGI;
+   use C4::Auth;
+ 
+   $query = new CGI;
+   ($userid, $cookie, $sessionID) = &checkauth($query);
+ 
+ =head1 DESCRIPTION
+ 
+ This module provides authentication for Koha users.
+ 
+ =head1 FUNCTIONS
+ 
+ =over 2
+ 
+ =cut
+ 
  @ISA = qw(Exporter);
  @EXPORT = qw(
***************
*** 36,40 ****
--- 58,118 ----
  );
  
+ =item checkauth
+ 
+   ($userid, $cookie, $sessionID) = &checkauth($query, $noauth);
  
+ Verifies that the user is authorized to run this script. Note that
+ C<&checkauth> will return if and only if the user is authorized, so it
+ should be called early on, before any unfinished operations (i.e., if
+ you've opened a file, then C<&checkauth> won't close it for you).
+ 
+ C<$query> is the CGI object for the script calling C<&checkauth>.
+ 
+ The C<$noauth> argument is optional. If it is set, then no
+ authorization is required for the script.
+ 
+ C<&checkauth> fetches user and session information from C<$query> and
+ ensures that the user is authorized to run scripts that require
+ authorization.
+ 
+ If C<$query> does not have a valid session ID associated with it
+ (i.e., the user has not logged in) or if the session has expired,
+ C<&checkauth> presents the user with a login page (from the point of
+ view of the original script, C<&checkauth> does not return). Once the
+ user has authenticated, C<&checkauth> restarts the original script
+ (this time, C<&checkauth> returns).
+ 
+ C<&checkauth> returns a user ID, a cookie, and a session ID. The
+ cookie should be sent back to the browser; it verifies that the user
+ has authenticated.
+ 
+ =cut
+ #'
+ # FIXME - (Or rather, proofreadme)
+ # As I understand it, the 'sessionqueries' table in the Koha database
+ # is supposed to save state while the user authenticates. If
+ # (re-)authentication is required, &checkauth saves the browser's
+ # original call to a new entry in sessionqueries, then presents a form
+ # for the user to authenticate. Once the user has authenticated
+ # visself, &checkauth retrieves the stored information from
+ # sessionqueries and allows the original request to proceed.
+ #
+ # One problem, however, is that sessionqueries only stores the URL,
+ # not the various values passed along from an HTML form. Thus, if the
+ # request came from a form and contains information on stuff to change
+ # (e.g., modify the contents of a virtual bookshelf), but the session
+ # has timed out, then when &checkauth finally allows the request to
+ # proceed, it will not contain the user's modifications. This is bad.
+ #
+ # Another problem is that entries in sessionqueries are supposed to be
+ # temporary, but there's no mechanism for removing them in case of
+ # error (e.g., the user can't remember vis password and walks away, or
+ # if the user's machine crashes in the middle of authentication).
+ #
+ # Perhaps a better implementation would be to use $query->param to get
+ # the parameter with which the original script was invoked, and pass
+ # that along through all of the authentication pages. That way, all of
+ # the pertinent information would be preserved, and the sessionqueries
+ # table could be removed.
  
  sub checkauth {
***************
*** 49,55 ****
--- 127,140 ----
        return ($userid, $cookie, '');
      }
+ 
+     # Get session ID from cookie.
      my $sessionID=$query->cookie('sessionID');
+       # FIXME - Error-checking: if the user isn't allowing cookies,
+       # $sessionID will be undefined. Don't confuse this with an
+       # expired cookie.
+ 
      my $message='';
  
+     # Make sure the session ID is (still) good.
      my $dbh = C4::Context->dbh;
      my $sth=$dbh->prepare("select userid,ip,lasttime from sessions where 
sessionid=?");
***************
*** 57,69 ****
      if ($sth->rows) {
        my ($userid, $ip, $lasttime) = $sth->fetchrow;
        if ($lasttime<time()-45 && $userid ne 'tonnesen') {
!           # timed logout
            $message="You have been logged out due to inactivity.";
            my $sti=$dbh->prepare("delete from sessions where sessionID=?");
            $sti->execute($sessionID);
!           my $scriptname=$ENV{'SCRIPT_NAME'};
            my $selfurl=$query->self_url();
            $sti=$dbh->prepare("insert into sessionqueries (sessionID, userid, 
value) values (?, ?, ?)");
            $sti->execute($sessionID, $userid, $selfurl);
            open L, ">>/tmp/sessionlog";
            my $time=localtime(time());
--- 142,169 ----
      if ($sth->rows) {
        my ($userid, $ip, $lasttime) = $sth->fetchrow;
+       # FIXME - Back door for tonnensen
        if ($lasttime<time()-45 && $userid ne 'tonnesen') {
!           # This session has been inactive for >45 seconds, and
!           # doesn't belong to user tonnensen. It has expired.
            $message="You have been logged out due to inactivity.";
+ 
+           # Remove this session ID from the list of active sessions.
+           # FIXME - Ought to have a cron job clean this up as well.
            my $sti=$dbh->prepare("delete from sessions where sessionID=?");
            $sti->execute($sessionID);
! 
!           # Add an entry to sessionqueries, so that we can restart
!           # the script once the user has authenticated.
!           my $scriptname=$ENV{'SCRIPT_NAME'}; # FIXME - Unused
            my $selfurl=$query->self_url();
            $sti=$dbh->prepare("insert into sessionqueries (sessionID, userid, 
value) values (?, ?, ?)");
            $sti->execute($sessionID, $userid, $selfurl);
+ 
+           # Log the fact that someone tried to use an expired session ID.
+           # FIXME - Ought to have a better logging mechanism,
+           # ideally some wrapper that logs either to a
+           # user-specified file, or to syslog, as determined by
+           # either an entry in /etc/koha.conf, or a system
+           # preference.
            open L, ">>/tmp/sessionlog";
            my $time=localtime(time());
***************
*** 71,79 ****
            close L;
        } elsif ($ip ne $ENV{'REMOTE_ADDR'}) {
!           # Different ip than originally logged in from
            my $newip=$ENV{'REMOTE_ADDR'};
  
            $message="ERROR ERROR ERROR ERROR<br>Attempt to re-use a cookie 
from a different ip address.<br>(authenticated from $ip, this request from 
$newip)";
        } else {
            my $cookie=$query->cookie(-name => 'sessionID',
                                      -value => $sessionID,
--- 171,183 ----
            close L;
        } elsif ($ip ne $ENV{'REMOTE_ADDR'}) {
!           # This session is coming from an IP address other than the
!           # one where it was set. The user might be doing something
!           # naughty.
            my $newip=$ENV{'REMOTE_ADDR'};
  
            $message="ERROR ERROR ERROR ERROR<br>Attempt to re-use a cookie 
from a different ip address.<br>(authenticated from $ip, this request from 
$newip)";
        } else {
+           # This appears to be a valid session. Update the time
+           # stamp on it and return.
            my $cookie=$query->cookie(-name => 'sessionID',
                                      -value => $sessionID,
***************
*** 85,91 ****
      }
  
! 
  
      if ($authnotrequired) {
        my $cookie=$query->cookie(-name => 'sessionID',
                                  -value => '',
--- 189,199 ----
      }
  
!     # If we get this far, it's because we haven't received a cookie
!     # with a valid session ID. Need to start a new session and set a
!     # new cookie.
  
      if ($authnotrequired) {
+       # This script doesn't require the user to be logged in. Return
+       # just the cookie, without user ID or session ID information.
        my $cookie=$query->cookie(-name => 'sessionID',
                                  -value => '',
***************
*** 93,105 ****
--- 201,228 ----
        return('', $cookie, '');
      } else {
+       # This script requires authorization. Assume that we were
+       # given user and password information; generate a new session.
+ 
+       # Generate a new session ID.
        ($sessionID) || ($sessionID=int(rand()*100000).'-'.time());
        my $userid=$query->param('userid');
        my $password=$query->param('password');
        if (checkpw($dbh, $userid, $password)) {
+           # The given password is valid
+ 
+           # Delete any old copies of this session.
            my $sti=$dbh->prepare("delete from sessions where sessionID=? and 
userid=?");
            $sti->execute($sessionID, $userid);
+ 
+           # Add this new session to the 'sessions' table.
            $sti=$dbh->prepare("insert into sessions (sessionID, userid, 
ip,lasttime) values (?, ?, ?, ?)");
            $sti->execute($sessionID, $userid, $ENV{'REMOTE_ADDR'}, time());
+ 
+           # See if there's an entry for this session ID and user in
+           # the 'sessionqueries' table. If so, then use that entry
+           # to generate an HTTP redirect that'll take the user to
+           # where ve wanted to go in the first place.
            $sti=$dbh->prepare("select value from sessionqueries where 
sessionID=? and userid=?");
+                       # FIXME - There is no sessionqueries.value
            $sti->execute($sessionID, $userid);
            if ($sti->rows) {
***************
*** 119,122 ****
--- 242,248 ----
            return ($userid, $cookie, $sessionID);
        } else {
+           # Either we weren't given a user id and password, or else
+           # the password was invalid.
+ 
            if ($userid) {
                $message="Invalid userid or password entered.";
***************
*** 175,179 ****
  }
  
! 
  sub checkpw {
  
--- 301,309 ----
  }
  
! # checkpw
! # Takes a database handle, user ID, and password, and verifies that
! # the password is good. The user ID may be either a user ID or a card
! # number.
! # Returns 1 if the password is good, or 0 otherwise.
  sub checkpw {
  
***************
*** 182,205 ****
  #
      my ($dbh, $userid, $password) = @_;
!     my $sth=$dbh->prepare("select password from borrowers where userid=?");
      $sth->execute($userid);
      if ($sth->rows) {
        my ($md5password) = $sth->fetchrow;
        if (md5_base64($password) eq $md5password) {
!           return 1;
        }
      }
!     # FIXME - There's already a $sth in this scope.
!     my $sth=$dbh->prepare("select password from borrowers where 
cardnumber=?");
      $sth->execute($userid);
      if ($sth->rows) {
        my ($md5password) = $sth->fetchrow;
        if (md5_base64($password) eq $md5password) {
!           return 1;
        }
      }
!     return 0;
  }
  
  
  END { }       # module clean-up code here (global destructor)
--- 312,352 ----
  #
      my ($dbh, $userid, $password) = @_;
!     my $sth;
! 
!     # Try the user ID.
!     $sth = $dbh->prepare("select password from borrowers where userid=?");
      $sth->execute($userid);
      if ($sth->rows) {
        my ($md5password) = $sth->fetchrow;
        if (md5_base64($password) eq $md5password) {
!           return 1;           # The password matches
        }
      }
! 
!     # Try the card number.
!     $sth = $dbh->prepare("select password from borrowers where cardnumber=?");
      $sth->execute($userid);
      if ($sth->rows) {
        my ($md5password) = $sth->fetchrow;
        if (md5_base64($password) eq $md5password) {
!           return 1;           # The password matches
        }
      }
!     return 0;         # Either there's no such user, or the password
!                       # doesn't match.
  }
  
  
  END { }       # module clean-up code here (global destructor)
+ 
+ 1;
+ __END__
+ =back
+ 
+ =head1 SEE ALSO
+ 
+ L<CGI(3)|CGI>
+ 
+ L<Digest::MD5(3)|Digest::MD5>
+ 
+ =cut




reply via email to

[Prev in Thread] Current Thread [Next in Thread]