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

Andrew Arensburger arensb at users.sourceforge.net
Mon Oct 7 02:34:27 CEST 2002


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





More information about the Koha-cvs mailing list