|
|
|
|
File: [Development] / advokit-installer / SessionHandler.class.php
(download)
/
(as text)
Revision: 1.6, Wed Aug 25 03:13:03 2004 UTC (6 years ago) by travislow Branch: MAIN CVS Tags: r1-x-dev, r0-9-9, r0-9-8, footag0, HEAD Changes since 1.5: +74 -69 lines - Fixed minor security issues relating to uninitialized variables. - Enhanced bug reporting. If a DB error occurs, a form is displayed. The user can choose to use it, or not. - Change app maintainers to ak@voter2voter.org |
<?
# ======================================================================
# AdvoKit -- a campaign managment tool
# Copyright (C) 2004 OrchidSuites, Inc. (info@orchidsuites.net)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the AFFERO GENERAL PUBLIC LICENSE
# as published by Affero, Inc.; either version 1
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# AFFERO GENERAL PUBLIC LICENSE for more details.
#
# You should have received a copy of the AFFERO GENERAL PUBLIC LICENSE
# along with this program; if not, write to Affero, Inc. at
# 510 Third Street - Suite 225, San Francisco, CA 94107, USA
# or visit <http://www.affero.org>.
# ======================================================================
# ======================================================================
# Checks to see if there is a user with a valid login session.
# If a session exists, create a user object for that user.
# ======================================================================
# SessionHandler wraps the fetch/set of persistent SessionCookies.
require_once "$t_root".DIRSEP."SessionCookie.class.php";
class SessionHandler
{
var $config;
var $logger;
var $db;
var $request;
var $te;
var $ustate;
var $sessiontype;
var $sessionname;
var $sessioncookie;
var $encryption_key;
var $user;
#------------------------------------------------------------
# Instance functions
#------------------------------------------------------------
#.................................................. SessionHandler
#
# Create and authenticate users based on submitted
# information. (not the same as logging them in)
#
function SessionHandler( &$config, &$logger, &$db, &$request, &$te, &$ustate )
{
$this->config =& $config;
$this->logger =& $logger;
$this->db =& $db;
$this->request =& $request;
$this->te =& $te;
$this->ustate =& $ustate;
$this->sessionname = $config->get( "login_cookie_name" );
if( !$this->sessionname )
{
$logger->error( __FILE__, "No session name specified! You need to set 'login_cookie_name' in your ini file." );
return;
}
$this->sessiontype = $config->get( "login_session_type" );
if( $config->get( "use_http_auth" ) || $this->sessiontype == "http_auth" )
{
global $t_root;
require_once "$t_root".DIRSEP."auth-utils.inc.php";
if ( !isset($_SERVER['HTTP_AUTHORIZATION']) && function_exists('apache_request_headers') )
{
// work around odd bug when php is not invoked as a CGI.
$headers = apache_request_headers();
$_SERVER['HTTP_AUTHORIZATION'] = $headers['Authorization'];
}
$clrsess = ($request->get( "action" ) == "clearsession" );
$authused= ( $_SERVER['REMOTE_USER'] || $_SERVER['PHP_AUTH_USER'] || $_SERVER['HTTP_AUTHORIZATION'] );
if ($clrsess)
{
if (!$authused)
{
// make sure we generate the WWW-Authenticate header
// so that the browser sends us the login credentials
makeAuthenticateHeader( $config, $request->get( "timestamp" ));
// unfriendly messaage; should rarely be seen!
?>
<h1>Login Error</h1>
<p>You're probably using a non-secure connection
from a browser that doesn't support http digest
authentication.
</p>
<?
exit;
}
else
{
// helper for login/logout; remove 'username:password@'
// from url shown in browser.
$protocol = ( strtolower($_SERVER['HTTPS']) == "on" ) ? 'https' : 'http';
$query=implode ('&', preg_grep('/^(action|timestamp)=/', explode('&',$_SERVER['QUERY_STRING']), PREG_GREP_INVERT));
if ($query != "")
{
$query="?$query";
}
session_write_close();
header("Location: $protocol://".$_SERVER['HTTP_HOST']. $_SERVER['PHP_SELF'].$query);
exit;
}
}
if ($authused)
{
$this->sessiontype = "http_auth";
}
}
$this->sessioncookie = $this->initSessionCookie();
$logger->debug( __FILE__, "SessionHandler created:" );
$logger->debug( __FILE__, " - session type is '".$this->sessiontype."'" );
$logger->debug( __FILE__, " - session name is '".$this->sessionname."'" );
$logger->debug( __FILE__, " - session id is '".$this->sessioncookie->toString($config)."'" );
}
#.................................................. getSessionType
#
# Return the session type.
#
function getSessionType()
{
return $this->sessiontype;
}
#.................................................. getSessionName
#
# Return the session name.
#
function getSessionName()
{
return $this->sessionname;
}
#.................................................. initSessionCookie
#
# Initialize the sessioncookie associated with the session name.
# This function should only be used to initialize $this->sessioncookie
#
function initSessionCookie()
{
switch( $this->getSessionType() )
{
case "cookie":
{
return SessionCookie::fromString
( $this->config, $_COOKIE[ $this->getSessionName() ] );
}
case "request":
{
return SessionCookie::fromString
( $this->config, $this->request->get( $this->getSessionName() ) );
}
case "phpsession":
{
//----------------------------------------------------------
// Explicitly start a session. This is necessary
// because we use $_SESSION[], rather than
// session_register(), to manipulate session variables.
//------------------------------------------------------------
session_start();
return SessionCookie::fromString ( $this->config, $_SESSION[ $this->getSessionName() ] );
}
case "http_auth":
{
return SessionCookie::fromHeaders( $this->config );
}
default:
{
$this->logger->error( __FILE__, "Invalid session type specified: '".$this->getSessionType()."'" );
}
}
}
#.................................................. refreshSession
#
# Refresh login session information.
#
function refreshSession()
{
$this->logger->debug( __FILE__, "Refreshing session: " );
$this->logger->debug( __FILE__, " - session type is '".$this->getSessionType()."'" );
$this->logger->debug( __FILE__, " - session name is '".$this->getSessionName()."'" );
$this->logger->debug( __FILE__, " - session id is '".$this->sessioncookie->toString($this->config)."' (but not for long)" );
switch( $this->getSessionType() )
{
case "cookie":
{
$this->logger->debug( __FILE__, "Refreshing cookie-based session." );
if ( ! setcookie( $this->getSessionName(), $this->sessioncookie->toString( $this->config ), time() + $this->config->get( "login_timeout" ), "/" ) )
{
$this->logger->error( __FILE__, "Unable to set cookie!" );
}
break;
}
case "request":
{
# A bit of a hack. The filter adds the session info
# to each page emitted from the Template Engine.
$this->request->set( $this->getSessionName(), $this->sessioncookie->toString( $this->config) );
$this->logger->debug( __FILE__, "Refreshing request-based session." );
$this->te->registerPostfilter( "addSessionInfoToPage" );
break;
}
case "phpsession":
{
$this->logger->debug( __FILE__, "Refreshing phpsession-based session." );
$_SESSION[ $this->getSessionName() ] = $this->sessioncookie->toString( $this->config );
break;
}
default:
{
$this->logger->error( __FILE__, "Invalid session type specified: '".$this->getSessionType()."'" );
}
}
}
#.................................................. createSession
#
# Create a new login session, overwriting any old one.
#
function createSession( $newsessioncookie )
{
$this->sessioncookie = $newsessioncookie;
$this->logger->debug( __FILE__, "Creating new session." );
// change the php session_id in order to prevent
// session fixation attacks.
if ($this->getSessionType() == "phpsession" )
{
session_regenerate_id();
}
$this->refreshSession();
}
#.................................................. expireSession
#
# Expire the session (log the user out)
#
function expireSession()
{
$this->logger->debug( __FILE__, "Expiring session: " );
$this->logger->debug( __FILE__, " - session type is '".$this->getSessionType()."'" );
$this->logger->debug( __FILE__, " - session name is '".$this->getSessionName()."'" );
$this->logger->debug( __FILE__, " - session id is '".$this->sessioncookie->toString( $this->config )."' (but not for long)" );
switch( $this->getSessionType() )
{
case "cookie":
{
$_COOKIE[ $this->getSessionName() ] = NULL;
if ( ! setcookie( $this->getSessionName(), "", 0, "/" ) )
{
$this->logger->error( __FILE__, "Unable to set cookie! User is still logged in!" );
}
break;
}
case "request":
{
$this->request->set( $this->getSessionName(), NULL );
break;
}
case "phpsession":
{
$_SESSION[ $this->getSessionName() ] = NULL;
// change the php session_id to be safe.
session_regenerate_id();
break;
}
default:
{
$this->logger->error( __FILE__, "Invalid session type specified: '".$this->getSessionType()."'" );
}
}
}
#.................................................. getUser
#
# Get the current logged in user, based on the login
# session information passed in the request, in a cookie,
# or in the session.
#
# If no one is logged in, create an anonymous user.
#
function getUser()
{
if( $this->sessioncookie )
{
$sesscookie = $this->sessioncookie;
$username = $sesscookie->username;
if( $username )
{
$user = new User( $this->config, $this->logger, $this->db, $username );
if( $user->isAnonymous() )
{
$this->logger->warning( __FILE__, "Failed login attempt by '".$username."'. No such active user." );
return $user;
}
# If user exists, compare password hashes.
if( "md5" == $this->config->get( "hash_algorithm" ) )
{
$password = $user->getPassword(); // really already a hash.
if( $sesscookie->passhash == md5($password.":".$sesscookie->nonce) )
{
if( ! $this->config->get( "login_allow_simultaneous" ) )
{
$login_timestamp = $this->ustate->getValue( $user->getId(), 0, '', '', "login_timestamp" );
if( $login_timestamp == $sesscookie->timestamp )
{
$this->refreshSession();
$user->updateLastActivity();
$this->logger->debug( __FILE__, "'".$username."' is currently logged in" );
return $user;
}
else
{
$this->expireSession();
$this->request->set( "display", $this->config->get( "forcedlogout_display" ) );
$this->logger->warning( __FILE__, "User '$username' was logged out due to a login from a different location." );
}
}
else
{
$this->refreshSession();
$user->updateLastActivity();
$this->logger->debug( __FILE__, "'".$username."' is currently logged in" );
return $user;
}
}
else
{
$this->logger->warning( __FILE__, "Invalid password hash in cookie for user '$username'!" );
}
}
else
{
$this->logger->error( __FILE__, "Invalid hashing algorithm specified: '$hash_algorithm'" );
}
}
}
return new User( $this->config, $this->logger, $this->db, "anonymous" );
}
}
?>
| cvsadmin@voter2voter.org | CVS Snapshots (updated daily) |