package.xml 0000644 0001750 0001750 00000112556 11461311104 013761 0 ustar clockwerx clockwerx
Authpear.php.netCreating an authentication system.The PEAR::Auth package provides methods for creating an authentication
system using PHP.
Currently it supports the following storage containers to read/write
the login data:
* All databases supported by the PEAR database layer
* All databases supported by the MDB database layer
* All databases supported by the MDB2 database layer
* Plaintext files
* LDAP servers
* POP3 servers
* IMAP servers
* vpopmail accounts (Using either PECL vpopmail or PEAR Net_Vpopmaild)
* RADIUS
* SAMBA password files
* SOAP (Using either PEAR SOAP package or PHP5 SOAP extension)
* PEAR website
* Kerberos V servers
* SAP serversMartin JansenMJmj@php.netnoYavor Shahpasovyavoyavo@siava.orgnoAdam Ashleyaashleyphp@adamashley.nameyesJames E. Flemerjflemerjflemer@acm.jhu.edunoAdam Harveyaharveyaharvey@php.netyes2010-10-261.6.41.5.0stablestablePHP License
Fix baseinstalldir
4.3.31.4.0b1Logpear.php.net1.9.10File_Passwdpear.php.net1.1.0Net_POP3pear.php.net1.3.0DBpear.php.net1.6.0MDBpear.php.netMDB2pear.php.net2.0.0RC1Auth_RADIUSpear.php.netCrypt_CHAPpear.php.net1.0.0File_SMBPasswdpear.php.net1.0.0HTTP_Clientpear.php.net1.1.0SOAPpear.php.net0.9.0Net_Vpopmaildpear.php.net0.1.0vpopmailpecl.php.net0.2vpopmailkadm5pecl.php.net0.2.3kadm5imapsaprfcsoap1.2.21.2.2stablestable2003-07-29PHP License
* Added support for passing contaner as an object
* Added fix when db_fileds is *
* Added Test Suite (experimental)
* Added generic support for arbitrary password crypting functions
different than MD5, DES and plain text. (Patch by Tom Anderson)
* Added new MDB storage container written by Lorenzo Alberton
* Added new Container for SAMBA password files (SMBPasswd)
1.2.31.2.3stablestable2003-09-08PHP License
* new Method to auth_container getUser()
* New Auth_Container_File, using new File_Passwd class. Provided by Michael Wallner <mike@php.net>
* Login/Logout callbacks now get a reference to auth
* New Login Failed Callback added (method setFailedLoginCallback)
* SOAP container patch to keep a reference to the Soap responce by Bruno Pedro <bpedro@co.sapo.pt>
* Auth is now installed in /pear-dir/Auth.php instead of /pear-dir/Auth/Auth.php, an
empty file /pear-dev/Auth/Auth.php wich includes Auth.php is added for BC
* The contaner now gets a reference to the auth object ($auth->storage->_auth_obj)
*Some patches from the pear-dev list bellow
-maka3d@yahoo.com.br - Patch to use a method of the container in Auth_Container::verifyPassword
-Lorenzo Alberton <l.alberton@quipo.it> - Patch to use variable session variable name, untill now the variable auth was used
-Marcos Neves <maka3d@yahoo.com.br> - Avaoid error when calling getAuthData() before the login
1.3.0r11.3.0r1betabeta2004-06-04PHP License
* Changes to LDAP container:
- check for loaded ldap extension at startup as suggested by Markku Turunen
- make ldap version configurable via config array
- documentation fix for active directory default user container
[ 14/Jun/2004 - jw]
* Added an Auth_Controller class, to manage automatic redirection to login page and redirect back
to the calling page [04/06/2004 - Yavo]
* Changes to LDAP container:
- additional attribute fetching to authData via new option attributes
- utf8 encoding username for ldapv3 (fixes german umlaut problem)
- make scope definable for user and group searching seperately
- remove useroc, groupoc and replace them with userfilter, groupfilter which is way more flexible
- updated documentation on all new and changed parameters
As some of the parameters changed this one is not backwards compatible to earlier versions.
Look at the top of the class where all parameters are explained in detail.
[08/April/2004 - jw]
* Added new MDB2 container [30/March/2004 - quipo]
* Implements changePassword and CS fixed, patch from Cipriano Groenendal <cipri@cipri.com>
[29/March/2004 - yavo]
* Added options for changing the post variables, patch supplied by Moritz Heidkamp <moritz.heidkamp@invision-team.de>
[03/March/2004 - yavo]
* Added method setAdvancedSecurity and set advanced security to off by default, if turned on auth will perform additional
security checks if ip or user agent has changed across requests
* Login is now performed only if showLogin is true, do not allow for logins to be performed from any page which calls auth->start
spotted by Matt Eaton <pear@divinehawk.com> [16/Jan/2004 - yavo]
* Fixed bug noted by Jeroen Houben <jeroen@terena.nl>, calling loginFailedCallback
would not have the proper status set [16/Jan/2004 - yavo]
* Added PEAR container, authenticate the user against the pear web site
(probably php.net also) [16/Dec/2003 - yavo]
1.3.0r31.3.0r3betabeta2004-08-07PHP License
* Moved login screen generation code to Auth/Frontend/Html.php
In the future the frontend will be configurable.
* Implemented support for Challenge / Responce password authenthication
have to enable advanced security $auth->setAdvancedSecurity
will work only with DB container and cryptType = none|md5
* Implemented setAllowLogin to control which pages are allowed to perform login,
to preservce BC. Previusly the showLogin flag was used to control this - yavo
* Implmented lazy loading for the storage constructor, constructor is only created when needed
to make Auth more lightweight (this might be adding a bit more overhead to login and usermanagement functions)
* Removed include of PEAR, was not used anywhare in Auth.php
* Created a new storage container DBLite same as DB but with the user manipulation functions removed (50% smaller)
* Added a new method staticCheckAuth which can be called statically with only the auth options
* Auth::importGlobalVariable method was removed and replaced by references to global variables
* Removed all calls to $session[$this->_sessionName], made local reference session point to that instead
* Changed call_user_func to call_user_func_array for the callbacks, to avoid using @ for passing variables by reference
* Code Cleanup, removed most vi comments
1.3.0r41.3.0r4betabeta2006-02-14PHP License
This release fixes a security issue that allows an attacker to perform
injection attacks against the underlying storage containers. Upgrading
is strongly recommended if you are using beta releases of the Auth
package.
* Improved parameter validation in the DB and LPAP containers. (Patch
provided by Matthew Van Gundy.)
* Fixed Bug #3101: Wrong variable names in Auth/Container/File.php (mike)
* renamed supportsChallengeResponce() to supportsChallengeResponse()
in the DB container (quipo)
* Fixed Bug #4347: recognition of DB and MDB objects passed as dsn
* Fixed Bug #6324: updated MDB2 container
* Fixed Bug #5174: "Only variable references should be returned by reference"
bug in _factory()
* Fixed Bug #2446: english language typos.
This results in a BC break for any custom containers that have implemented
supportsChallengeResponce(). Also all containers already
supportsChallengeResponse() instead of supportsChallengeResponce() and
therefore the call in Auth_Frontend_Html always called the default
implementation and not the container implementation.
1.3.0r51.3.0r5betabeta2006-02-21PHP License
* Fixed Bug #2873: Allow calling programs to gracefully handle being unable
to connect/bind to LDAP server.
* Fixed Bug #4918: Added support to specify which authentication method to
prefer when authenticating against a POP3 backend.
* Fixed Bug #6644: Added support for LDAP_OPT_REFERRALS. Setting to false can
improve compatibility with Active Directory.
* Fixed Bug #6791: Made all calls to call_user_func() call_user_func_array and
made calls consistant per change done in 1.3.0r3.
* Fixed Bug #6803: depreciated DB function. Now requires DB >= 1.6.0
* Fixed Bug #6808: Whenever Auth_Container_DB attempts to change the database
make sure the connection/DB object exists and is correct before attempting to
use the DB quoting features.
1.3.0RC61.3.0RC6betabeta2006-02-22PHP License1.3.0RC71.3.0RC7betabeta2006-03-01PHP License
This release is primarily a coding standard clean-up before the 1.3.0 final
release.
In addition the following improvements to the LDAP Container where supplied
by Hugues Peeters <hugues.peeters@claroline.net>.
* Changed default attrformat to AUTH so that loaded attributes are
presented in the same format as other backends provide.
* Added compatibility support to 1.2 style configuration options
* Attributes option now accepts a comma seperated string as well as
as array the same as db_fields in the DB, MDB and MDB2 backends.
Finally there are additional checks that the relevant PHP module is loaded
when loading the IMAP and VPOPMail Containers.
1.3.01.3.0stablestable2006-03-03PHP License
This is the final stable release of Auth 1.3.0. This version contains many new
features over previous versions. Summary of changes:
* New MDB2 container [30/March/2004 - quipo]
* New PEAR container, authenticate against pear.php.net [16/Dec/2003 - yavo]
* New Advanced Security mode to catch man-in-the-middle attacks.
* Added options for changing the post variables, patch supplied by Moritz
Heidkamp <moritz.heidkamp@invision-team.de>
* New DBLite container, same as DB but with the user manipulation functions
removed (50% smaller).
* Split login form to Auth_Frontend_HTML with goal to make it easily
customisable.
Numerous other small fixes and improvements to all storage containers thanks
to the following people: Matt Eaton, Jeroen Houben, Cipriano Groenendal,
Markku Turunen, Matthew Van Gundy, marc at practeo dot ch and I'm sure many
others that have contributed over the years it's taken to get this release
out.
1.3.1RC11.3.1RC1betabeta2006-08-11PHP License
This release candidate is test the numerous fixes described below. It is also
to get feedback on the change made for Bug #8407. Bug #8407 adds automatic
quoting of table and field names used in SQL in the Database backends.
* Fixed Bug #7031: session_regenerate_id() not cleaning up old session storage.
Fix for this bug in PHP5.1.0+ has been done, still a problem in older versions
of PHP.
* Fixed Bug #7421: Allow false to be passed in for allowLogin and advancedSecurity
options.
* Fixed Bug #7434: Enable start_tls support for LDAP Container by Stuart Prescott
<php.net@nanonanonano.net>
* Fixed Bug #7537: Made File Container capable of using all File_Passwd backends.
* Fixed Bug #7841: Added missing </center>. Really the whole frontend needs
reworking.
* Fixed Bug #7860: Removed deprecated session_register call.
* Fixed Bug #7899: sessionValidThru() returning incorrect value when no idle
timeout set.
* Fixed Bug #7956: Session handling had several security bugs before PHP4.3.3.
Bumped PHP dependancy so we don't have to deal with them.
* Fixed Bug #8076: MDB & MDB2 Containers not using default db_fields values
* Fixed Bug #8351: Documentation of $loginFailedCallback pointed to incorrect
set function.
* Fixed Bug #8406: Error message updates by Adam Harvey <pear@adamharvey.name>
* Fixed Bug #8407: Database containers don't quote table/field names by Adam
Harvey <pear@adamharvey.name>
1.3.11.3.1stablestable2006-08-21PHP License
* Fixed Bug #7031: session_regenerate_id() not cleaning up old session storage.
Fix for this bug in PHP5.1.0+ has been done, still a problem in older versions
of PHP.
* Fixed Bug #7421: Allow false to be passed in for allowLogin and advancedSecurity
options.
* Fixed Bug #7434: Enable start_tls support for LDAP Container by Stuart Prescott
<php.net@nanonanonano.net>
* Fixed Bug #7537: Made File Container capable of using all File_Passwd backends.
* Fixed Bug #7841: Added missing </center>. Really the whole frontend needs
reworking.
* Fixed Bug #7860: Removed deprecated session_register call.
* Fixed Bug #7899: sessionValidThru() returning incorrect value when no idle
timeout set.
* Fixed Bug #7956: Session handling had several security bugs before PHP4.3.3.
Bumped PHP dependancy so we don't have to deal with them.
* Fixed Bug #8076: MDB & MDB2 Containers not using default db_fields values
* Fixed Bug #8351: Documentation of $loginFailedCallback pointed to incorrect
set function.
* Fixed Bug #8406: Error message updates by Adam Harvey <pear@adamharvey.name>
* Fixed Bug #8407: Database containers don't quote table/field names by Adam
Harvey <pear@adamharvey.name>
1.3.21.3.2stablestable2006-08-31PHP License
* Fixed Bug #8524: Notice from attempting to perform string operation on what
might be an array in DB, DBLite, MDB and MDB2. Thanks to dozoyousan at gmail
dot com.
* Remove debug message from RADIUS Container when using CHAP_MD5 or MSCHAPv1
style passwords. Thanks to Stoyan Stefanov <ssttoo at gmail dot com> for
pointing out this 3yr old bug.
2006-09-111.4.0RC11.4.0betastablePHP License
* Added new SOAP container that makes use of the PHP5 SOAP Client. Thanks to
Marcel Oelke <puRe at rednoize dot com>. Fixes #2612.
* Added support for trying all the user accounts returned from an LDAP server
not just the first one so as to support authenticating against Lotus Notes
which allows identical usernames where the only difference is the password.
Fixes #5365.
* Added new Array container for simple authentication setups where it's easier
to list users in the file than setup some sort of backend. Thanks to
georg_1 at have2 dot com. Fixes #5832.
* Added KADM5 container that makes use of the PECL kadm5 extension to
authenticate against Kerberos 5 servers. Thanks to Andrew Teixeira
<ateixeira at gmail dot com>. Fixes #6671.
* Fixed #8597. Remove references to $GLOBALS['HTTP_*_VARS'] now that we require
PHP 4.3.3+ for other reasons.
* Added SAP container that makes use of the SAPRFC extension available from
http://saprfc.sourceforge.net/. Thanks to Stoyan Stefanov <ssttoo at gmail dot com>.
Fixes #8637.
* Fix #8599. Allow identifier quoting in DB, DBLite, MDB and MDB2 backends to
be switched off by developer.
2006-09-211.4.0RC31.4.0betastablePHP License
* Fix Bug #8732: Auth_Container_DB having problems with SQLite databases.
SQLite returns the name of quoted field names including the quotes instead
of stripping the quotes like all other DBs.
* Fix Bug #8735: Auth_Container_File::addUser() working on different instances
of File_Passwrd object.
2006-10-201.4.01.4.0stablestablePHP License
* Added new SOAP container that makes use of the PHP5 SOAP Client. Thanks to
Marcel Oelke <puRe at rednoize dot com>. Fixes #2612.
* Added support for trying all the user accounts returned from an LDAP server
not just the first one so as to support authenticating against Lotus Notes
which allows identical usernames where the only difference is the password.
Fixes #5365.
* Added new Array container for simple authentication setups where it's easier
to list users in the file than setup some sort of backend. Thanks to
georg_1 at have2 dot com. Fixes #5832.
* Added KADM5 container that makes use of the PECL kadm5 extension to
authenticate against Kerberos 5 servers. Thanks to Andrew Teixeira
<ateixeira at gmail dot com>. Fixes #6671.
* Fixed #8597. Remove references to $GLOBALS['HTTP_*_VARS'] now that we require
PHP 4.3.3+ for other reasons.
* Added SAP container that makes use of the SAPRFC extension available from
http://saprfc.sourceforge.net/. Thanks to Stoyan Stefanov <ssttoo at gmail dot com>.
Fixes #8637.
* Fix #8599. Allow identifier quoting in DB, DBLite, MDB and MDB2 backends to
be switched off by developer.
* Fix Bug #8732: Auth_Container_DB having problems with SQLite databases.
SQLite returns the name of quoted field names including the quotes instead
of stripping the quotes like all other DBs.
* Fix Bug #8735: Auth_Container_File::addUser() working on different instances
of File_Passwrd object.
2006-10-281.4.11.4.0stablestablePHP License
* Forgot to add Auth/Container/Array.php to package2.xml.
2006-11-101.4.21.4.0stablestablePHP License
* Fixed Bug #9241: Callback functions where being passed a copy of
the login object instead of a reference to it under PHP4.
* Fixed Bug #9286: Comparison of passwords and their hashes could give
false positive.
2006-12-061.4.31.4.0stablestablePHP License
* Fixed Bug #9380: Default Auth_Container_POP3 configuration not
working.
* Fixed Bug #9407: Add callback in checkAuth() process.
* Fixed Bug #9479: Typo in Auth_Container_KADM5::_checkServer causes
failure. Thanks to Matt T. Proud (khanreaper at nerp dot net).
2007-01-171.5.0RC11.5.0betastablePHP License
* Completed Request #2229: Ability to attach fall through containers. This
is implemented through the use of a new container Auth_Container_Multiple.
See multi-container.php in examples directory.
* Completed Request #4126: Enhancements to Advanced Security Mode. Thanks
to makler at man dot torun dot pl.
* Completed Request #6949: Use Log package for debugging messages. See logging.php
in examples directory.
* Completed Request #7089: Add optional extra WHERE options to DB and MDB(2)
containers.
* Add ability to pass an instanciated DB, MDB or MDB2 database connection to each
of the respective Auth Containers.
2007-02-021.5.0RC21.5.0betastablePHP License
* Fixed Bug #9944: Logging constants not defined when logging disabled.
* Fixed Bug #10000: Stupid developer didn't stop to look what he was doing
and broke things.
* Fixed Bug #10004: Logging of connection failures in LDAP container missing.
2007-02-131.5.01.5.0stablestablePHP License
* Completed Request #2229: Ability to attach fall through containers. This
is implemented through the use of a new container Auth_Container_Multiple.
See multi-container.php in examples directory.
* Completed Request #4126: Enhancements to Advanced Security Mode. Thanks
to makler at man dot torun dot pl.
* Completed Request #6949: Use Log package for debugging messages. See logging.php
in examples directory.
* Completed Request #7089: Add optional extra WHERE options to DB and MDB(2)
containers.
* Fixed Bug #9944: Logging constants not defined when logging disabled.
* Fixed Bug #10000: Stupid developer didn't stop to look what he was doing
and broke things.
* Fixed Bug #10004: Logging of connection failures in LDAP container missing.
2007-03-231.5.11.5.0stablestablePHP License
* Added missing optional dependancy on PEAR Log to package.xml
* Fixed Bug #10125: Auth_Container_LDAP::fetchData only fetching attributes for
first entry.
2007-06-121.5.21.5.0stablestablePHP License
* Feature Request #10729: Optionally regenerate session id on every page request.
Thanks to Bernhard for patch.
* Fixed Bug #10785: Notice when Auth::logout() called with a login callback
defined but no user logged in. Suggested fix thanks to Sascha Grossenbacher.
2007-07-021.5.31.5.0stablestablePHP License
* Fixed Bug: If Auth::setSessionName() is called new session name variable is
not initialised so checks for session storage fail.
* Fixed Bug #11396: Auth_Container_Pear doesn't work with latest changes to
pear.php.net. Fix by Adam Harvey.
* Fixed Bug #11476: SOAP5 container's _validateOptions() and _setDefaults()
functions where setting options into the wrong object parameter. Thanks to
Köles Mihály for fix.
2007-07-021.5.41.5.0stablestablePHP License
* Fixed Bug #11499: Redundant parameter in Auth_Container_SOAP5::_validateOptions()
definition. Thanks to Koles Mihaly for spotting this.
2008-04-041.6.01.5.0stablestablePHP License
* Fixed Bug #12112: Advanced Security Cookie has different settings to
session cookie.
* Implemented Request #13337: New vpopmail container utilising Net_Vpopmaild.
Patch supplied by Bill Shupp (shupp)
* Implemented Request #13418: Karma support for PEAR Container. Patch supplied
by Christian Weiske (cweiske).
* Added correct debug message for when no login has occured instead of session
storage not found.
* Implemented Request #12061: Auto Quote handle database schema changes. ie
schema.tableName -> "schema"."tableName"
* Implemented Request #12087: Ability to select which Advanced Security options
are used.
* Fixed Doc Bug #12156: Correction to doc page for Auth::setSessionName() by
Adam Harvey (aharvey)
2008-04-041.6.11.5.0stablestablePHP License
* Actually included the new NetVPOPMaild container file.
*mutter*grumble*stupid package.xml*grumble*mutter*
* Fix Bug #13578: Parse errors in DB Containers
1.6.21.5.0stablestable2010-02-12PHP License
* Fix Bug #13756: Variable name mispelling in SAP container
* Fix Bug #13757: AUTH_LOG_ERR used but not defined
* Fix Bug #14248: Typo and documentation fixes
* Fix Bug #16676: Notices in PEAR container (cweiske)
1.6.31.5.0stablestable2010-10-26PHP License
Automatically built QA release
Bug #17691 PATCH: Using explode instead of split - doconnor
1.6.41.5.0stablestable2010-10-26PHP License
Fix baseinstalldir
Auth-1.6.4/Auth/Anonymous.php 0000600 0001750 0001750 00000007542 11461311103 016600 0 ustar clockwerx clockwerx
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: Anonymous.php 289651 2009-10-15 04:39:07Z aashley $
* @link http://pear.php.net/package/Auth
* @since File available since Release 1.3.0
*/
/**
* Include Auth package
*/
require_once 'Auth.php';
/**
* Anonymous Authentication
*
* This class provides anonymous authentication if username and password
* were not supplied
*
* @category Authentication
* @package Auth
* @author Yavor Shahpasov
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 289651 $
* @link http://pear.php.net/package/Auth
* @since Class available since Release 1.3.0
*/
class Auth_Anonymous extends Auth
{
// {{{ properties
/**
* Whether to allow anonymous authentication
*
* @var boolean
*/
var $allow_anonymous = true;
/**
* Username to use for anonymous user
*
* @var string
*/
var $anonymous_username = 'anonymous';
// }}}
// {{{ Auth_Anonymous() [constructor]
/**
* Pass all parameters to Parent Auth class
*
* Set up the storage driver.
*
* @param string Type of the storage driver
* @param mixed Additional options for the storage driver
* (example: if you are using DB as the storage
* driver, you have to pass the dsn string here)
*
* @param string Name of the function that creates the login form
* @param boolean Should the login form be displayed if necessary?
* @return void
* @see Auth::Auth()
*/
function Auth_Anonymous($storageDriver, $options = '', $loginFunction = '', $showLogin = true) {
parent::Auth($storageDriver, $options, $loginFunction, $showLogin);
}
// }}}
// {{{ login()
/**
* Login function
*
* If no username & password is passed then login as the username
* provided in $this->anonymous_username else call standard login()
* function.
*
* @return void
* @access private
* @see Auth::login()
*/
function login() {
if ( $this->allow_anonymous
&& empty($this->username)
&& empty($this->password) ) {
$this->setAuth($this->anonymous_username);
if (is_callable($this->loginCallback)) {
call_user_func_array($this->loginCallback, array($this->username, $this) );
}
} else {
// Call normal login system
parent::login();
}
}
// }}}
// {{{ forceLogin()
/**
* Force the user to login
*
* Calling this function forces the user to provide a real username and
* password before continuing.
*
* @return void
*/
function forceLogin() {
$this->allow_anonymous = false;
if( !empty($this->session['username']) && $this->session['username'] == $this->anonymous_username ) {
$this->logout();
}
}
// }}}
}
?>
Auth-1.6.4/Auth/Auth.php 0000600 0001750 0001750 00000001733 11461311103 015505 0 ustar clockwerx clockwerx
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: Auth.php 208437 2006-03-02 06:53:08Z aashley $
* @link http://pear.php.net/package/Auth
* @deprecated File deprecated since Release 1.2.0
*/
/**
* Include Auth package
*/
require_once 'Auth.php';
?>
Auth-1.6.4/Auth/Container.php 0000600 0001750 0001750 00000014632 11461311103 016530 0 ustar clockwerx clockwerx
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: Container.php 294935 2010-02-12 00:05:45Z clockwerx $
* @link http://pear.php.net/package/Auth
*/
/**
* Storage class for fetching login data
*
* @category Authentication
* @package Auth
* @author Martin Jansen
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 294935 $
* @link http://pear.php.net/package/Auth
*/
class Auth_Container
{
// {{{ properties
/**
* User that is currently selected from the storage container.
*
* @access public
*/
var $activeUser = "";
/**
* The Auth object this container is attached to.
*
* @access public
*/
var $_auth_obj = null;
// }}}
// {{{ Auth_Container() [constructor]
/**
* Constructor
*
* Has to be overwritten by each storage class
*
* @access public
*/
function Auth_Container()
{
}
// }}}
// {{{ fetchData()
/**
* Fetch data from storage container
*
* Has to be overwritten by each storage class
*
* @access public
*/
function fetchData($username, $password, $isChallengeResponse=false)
{
$this->log('Auth_Container::fetchData() called.', AUTH_LOG_DEBUG);
}
// }}}
// {{{ verifyPassword()
/**
* Crypt and verfiy the entered password
*
* @param string Entered password
* @param string Password from the data container (usually this password
* is already encrypted.
* @param string Type of algorithm with which the password from
* the container has been crypted. (md5, crypt etc.)
* Defaults to "md5".
* @return bool True, if the passwords match
*/
function verifyPassword($password1, $password2, $cryptType = "md5")
{
$this->log('Auth_Container::verifyPassword() called.', AUTH_LOG_DEBUG);
switch ($cryptType) {
case "crypt" :
return ((string)crypt($password1, $password2) === (string)$password2);
break;
case "none" :
case "" :
return ((string)$password1 === (string)$password2);
break;
case "md5" :
return ((string)md5($password1) === (string)$password2);
break;
default :
if (function_exists($cryptType)) {
return ((string)$cryptType($password1) === (string)$password2);
} elseif (method_exists($this,$cryptType)) {
return ((string)$this->$cryptType($password1) === (string)$password2);
} else {
return false;
}
break;
}
}
// }}}
// {{{ supportsChallengeResponse()
/**
* Returns true if the container supports Challenge Response
* password authentication
*/
function supportsChallengeResponse()
{
return(false);
}
// }}}
// {{{ getCryptType()
/**
* Returns the crypt current crypt type of the container
*
* @return string
*/
function getCryptType()
{
return('');
}
// }}}
// {{{ listUsers()
/**
* List all users that are available from the storage container
*/
function listUsers()
{
$this->log('Auth_Container::listUsers() called.', AUTH_LOG_DEBUG);
return AUTH_METHOD_NOT_SUPPORTED;
}
// }}}
// {{{ getUser()
/**
* Returns a user assoc array
*
* Containers which want should overide this
*
* @param string The username
*/
function getUser($username)
{
$this->log('Auth_Container::getUser() called.', AUTH_LOG_DEBUG);
$users = $this->listUsers();
if ($users === AUTH_METHOD_NOT_SUPPORTED) {
return AUTH_METHOD_NOT_SUPPORTED;
}
for ($i=0; $c = count($users), $i<$c; $i++) {
if ($users[$i]['username'] == $username) {
return $users[$i];
}
}
return false;
}
// }}}
// {{{ addUser()
/**
* Add a new user to the storage container
*
* @param string Username
* @param string Password
* @param array Additional information
*
* @return boolean
*/
function addUser($username, $password, $additional=null)
{
$this->log('Auth_Container::addUser() called.', AUTH_LOG_DEBUG);
return AUTH_METHOD_NOT_SUPPORTED;
}
// }}}
// {{{ removeUser()
/**
* Remove user from the storage container
*
* @param string Username
*/
function removeUser($username)
{
$this->log('Auth_Container::removeUser() called.', AUTH_LOG_DEBUG);
return AUTH_METHOD_NOT_SUPPORTED;
}
// }}}
// {{{ changePassword()
/**
* Change password for user in the storage container
*
* @param string Username
* @param string The new password
*/
function changePassword($username, $password)
{
$this->log('Auth_Container::changePassword() called.', AUTH_LOG_DEBUG);
return AUTH_METHOD_NOT_SUPPORTED;
}
// }}}
// {{{ log()
/**
* Log a message to the Auth log
*
* @param string The message
* @param int
* @return boolean
*/
function log($message, $level = AUTH_LOG_DEBUG) {
if (is_null($this->_auth_obj)) {
return false;
} else {
return $this->_auth_obj->log($message, $level);
}
}
// }}}
}
?>
Auth-1.6.4/Auth/Controller.php 0000600 0001750 0001750 00000017132 11461311103 016727 0 ustar clockwerx clockwerx
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: Controller.php 237449 2007-06-12 03:11:27Z aashley $
* @link http://pear.php.net/package/Auth
* @since File available since Release 1.3.0
*/
/**
* Controlls access to a group of php access
* and redirects to a predefined login page as
* needed
*
* In all pages
*
* include_once('Auth.php');
* include_once('Auth/Controller.php');
* $_auth = new Auth('File', 'passwd');
* $authController = new Auth_Controller($_auth, 'login.php', 'index.php');
* $authController->start();
*
*
* In login.php
*
* include_once('Auth.php');
* include_once('Auth/Controller.php');
* $_auth = new Auth('File', 'passwd');
* $authController = new Auth_Controller($_auth, 'login.php', 'index.php');
* $authController->start();
* if( $authController->isAuthorised() ){
* $authController->redirectBack();
* }
*
*
* @category Authentication
* @author Yavor Shahpasov
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 237449 $
* @link http://pear.php.net/package/Auth
* @since Class available since Release 1.3.0
*/
class Auth_Controller
{
// {{{ properties
/**
* The Auth instance this controller is managing
*
* @var object Auth
*/
var $auth = null;
/**
* The login URL
* @var string
* */
var $login = null;
/**
* The default index page to use when the caller page is not set
*
* @var string
*/
var $default = null;
/**
* If this is set to true after a succesfull login the
* Auth_Controller::redirectBack() is invoked automatically
*
* @var boolean
*/
var $autoRedirectBack = false;
// }}}
// {{{ Auth_Controller() [constructor]
/**
* Constructor
*
* @param Auth An auth instance
* @param string The login page
* @param string The default page to go to if return page is not set
* @param array Some rules about which urls need to be sent to the login page
* @return void
* @todo Add a list of urls which need redirection
*/
function Auth_Controller(&$auth_obj, $login='login.php', $default='index.php', $accessList=array())
{
$this->auth =& $auth_obj;
$this->_loginPage = $login;
$this->_defaultPage = $default;
@session_start();
if (!empty($_GET['return']) && $_GET['return'] && !strstr($_GET['return'], $this->_loginPage)) {
$this->auth->setAuthData('returnUrl', $_GET['return']);
}
if(!empty($_GET['authstatus']) && $this->auth->status == '') {
$this->auth->status = $_GET['authstatus'];
}
}
// }}}
// {{{ setAutoRedirectBack()
/**
* Enables auto redirection when login is done
*
* @param bool Sets the autoRedirectBack flag to this
* @see Auth_Controller::autoRedirectBack
* @return void
*/
function setAutoRedirectBack($flag = true)
{
$this->autoRedirectBack = $flag;
}
// }}}
// {{{ redirectBack()
/**
* Redirects Back to the calling page
*
* @return void
*/
function redirectBack()
{
// If redirectback go there
// else go to the default page
$returnUrl = $this->auth->getAuthData('returnUrl');
if(!$returnUrl) {
$returnUrl = $this->_defaultPage;
}
// Add some entropy to the return to make it unique
// avoind problems with cached pages and proxies
if(strpos($returnUrl, '?') === false) {
$returnUrl .= '?';
}
$returnUrl .= uniqid('');
// Track the auth status
if($this->auth->status != '') {
$url .= '&authstatus='.$this->auth->status;
}
header('Location:'.$returnUrl);
print("You could not be redirected to $returnUrl");
}
// }}}
// {{{ redirectLogin()
/**
* Redirects to the login Page if not authorised
*
* put return page on the query or in auth
*
* @return void
*/
function redirectLogin()
{
// Go to the login Page
// For Auth, put some check to avoid infinite redirects, this should at least exclude
// the login page
$url = $this->_loginPage;
if(strpos($url, '?') === false) {
$url .= '?';
}
if(!strstr($_SERVER['PHP_SELF'], $this->_loginPage)) {
$url .= 'return='.urlencode($_SERVER['PHP_SELF']);
}
// Track the auth status
if($this->auth->status != '') {
$url .= '&authstatus='.$this->auth->status;
}
header('Location:'.$url);
print("You could not be redirected to $url");
}
// }}}
// {{{ start()
/**
* Starts the Auth Procedure
*
* If the page requires login the user is redirected to the login page
* otherwise the Auth::start is called to initialize Auth
*
* @return void
* @todo Implement an access list which specifies which urls/pages need login and which do not
*/
function start()
{
// Check the accessList here
// ACL should be a list of urls with allow/deny
// If allow set allowLogin to false
// Some wild card matching should be implemented ?,*
if(!strstr($_SERVER['PHP_SELF'], $this->_loginPage) && !$this->auth->checkAuth()) {
$this->redirectLogin();
} else {
$this->auth->start();
// Logged on and on login page
if(strstr($_SERVER['PHP_SELF'], $this->_loginPage) && $this->auth->checkAuth()){
$this->autoRedirectBack ?
$this->redirectBack() :
null ;
}
}
}
// }}}
// {{{ isAuthorised()
/**
* Checks is the user is logged on
* @see Auth::checkAuth()
*/
function isAuthorised()
{
return($this->auth->checkAuth());
}
// }}}
// {{{ checkAuth()
/**
* Proxy call to auth
* @see Auth::checkAuth()
*/
function checkAuth()
{
return($this->auth->checkAuth());
}
// }}}
// {{{ logout()
/**
* Proxy call to auth
* @see Auth::logout()
*/
function logout()
{
return($this->auth->logout());
}
// }}}
// {{{ getUsername()
/**
* Proxy call to auth
* @see Auth::getUsername()
*/
function getUsername()
{
return($this->auth->getUsername());
}
// }}}
// {{{ getStatus()
/**
* Proxy call to auth
* @see Auth::getStatus()
*/
function getStatus()
{
return($this->auth->getStatus());
}
// }}}
}
?>
Auth-1.6.4/Auth/Container/Array.php 0000600 0001750 0001750 00000010761 11461311103 017605 0 ustar clockwerx clockwerx
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: Array.php 237449 2007-06-12 03:11:27Z aashley $
* @since File available since Release 1.4.0
*/
/**
* Include Auth_Container base class
*/
require_once "Auth/Container.php";
/**
* Include PEAR package for error handling
*/
require_once "PEAR.php";
/**
* Storage driver for fetching authentication data from a PHP Array
*
* This container takes two options when configuring:
*
* cryptType: The crypt used to store the password. Currently recognised
* are: none, md5 and crypt. default: none
* users: A named array of usernames and passwords.
* Ex:
* array(
* 'guest' => '084e0343a0486ff05530df6c705c8bb4', // password guest
* 'georg' => 'fc77dba827fcc88e0243404572c51325' // password georg
* )
*
* Usage Example:
* array(
* 'guest' => '084e0343a0486ff05530df6c705c8bb4', // password guest
* 'georg' => 'fc77dba827fcc88e0243404572c51325' // password georg
* ),
* 'cryptType'=>'md5',
* );
*
* $auth = new Auth("Array", $AuthOptions);
* ?>
*
* @category Authentication
* @package Auth
* @author georg_1 at have2 dot com
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 237449 $
* @since File available since Release 1.4.0
*/
class Auth_Container_Array extends Auth_Container {
// {{{ properties
/**
* The users and their password to authenticate against
*
* @var array $users
*/
var $users;
/**
* The cryptType used on the passwords
*
* @var string $cryptType
*/
var $cryptType = 'none';
// }}}
// {{{ Auth_Container_Array()
/**
* Constructor for Array Container
*
* @param array $data Options for the container
* @return void
*/
function Auth_Container_Array($data)
{
if (!is_array($data)) {
PEAR::raiseError('The options for Auth_Container_Array must be an array');
}
if (isset($data['users']) && is_array($data['users'])) {
$this->users = $data['users'];
} else {
$this->users = array();
PEAR::raiseError('Auth_Container_Array: no user data found in options array');
}
if (isset($data['cryptType'])) {
$this->cryptType = $data['cryptType'];
}
}
// }}}
// {{{ fetchData()
/**
* Get user information from array
*
* This function uses the given username to fetch the corresponding
* login data from the array. If an account that matches the passed
* username and password is found, the function returns true.
* Otherwise it returns false.
*
* @param string Username
* @param string Password
* @return boolean|PEAR_Error Error object or boolean
*/
function fetchData($user, $pass)
{
$this->log('Auth_Container_Array::fetchData() called.', AUTH_LOG_DEBUG);
if ( isset($this->users[$user])
&& $this->verifyPassword($pass, $this->users[$user], $this->cryptType)) {
return true;
}
return false;
}
// }}}
// {{{ listUsers()
/**
* Returns a list of users available within the container
*
* @return array
*/
function listUsers()
{
$this->log('Auth_Container_Array::listUsers() called.', AUTH_LOG_DEBUG);
$ret = array();
foreach ($this->users as $username => $password) {
$ret[]['username'] = $username;
}
return $ret;
}
// }}}
}
?>
Auth-1.6.4/Auth/Container/DB.php 0000600 0001750 0001750 00000047747 11461311103 017032 0 ustar clockwerx clockwerx
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: DB.php 256753 2008-04-04 07:57:02Z aashley $
* @link http://pear.php.net/package/Auth
*/
/**
* Include Auth_Container base class
*/
require_once 'Auth/Container.php';
/**
* Include PEAR DB
*/
require_once 'DB.php';
/**
* Storage driver for fetching login data from a database
*
* This storage driver can use all databases which are supported
* by the PEAR DB abstraction layer to fetch login data.
*
* @category Authentication
* @package Auth
* @author Martin Jansen
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 256753 $
* @link http://pear.php.net/package/Auth
*/
class Auth_Container_DB extends Auth_Container
{
// {{{ properties
/**
* Additional options for the storage container
* @var array
*/
var $options = array();
/**
* DB object
* @var object
*/
var $db = null;
var $dsn = '';
/**
* User that is currently selected from the DB.
* @var string
*/
var $activeUser = '';
// }}}
// {{{ Auth_Container_DB [constructor]
/**
* Constructor of the container class
*
* Save the initial options passed to the container. Initiation of the DB
* connection is no longer performed here and is only done when needed.
*
* @param string Connection data or DB object
* @return object Returns an error object if something went wrong
*/
function Auth_Container_DB($dsn)
{
$this->_setDefaults();
if (is_array($dsn)) {
$this->_parseOptions($dsn);
if (empty($this->options['dsn'])) {
PEAR::raiseError('No connection parameters specified!');
}
} else {
$this->options['dsn'] = $dsn;
}
}
// }}}
// {{{ _connect()
/**
* Connect to database by using the given DSN string
*
* @access private
* @param string DSN string
* @return mixed Object on error, otherwise bool
*/
function _connect($dsn)
{
$this->log('Auth_Container_DB::_connect() called.', AUTH_LOG_DEBUG);
if (is_string($dsn) || is_array($dsn)) {
$this->db = DB::Connect($dsn, $this->options['db_options']);
} elseif (is_subclass_of($dsn, 'db_common')) {
$this->db = $dsn;
} elseif (DB::isError($dsn)) {
return PEAR::raiseError($dsn->getMessage(), $dsn->getCode());
} else {
return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__,
41,
PEAR_ERROR_RETURN,
null,
null
);
}
if (DB::isError($this->db) || PEAR::isError($this->db)) {
return PEAR::raiseError($this->db->getMessage(), $this->db->getCode());
} else {
return true;
}
}
// }}}
// {{{ _prepare()
/**
* Prepare database connection
*
* This function checks if we have already opened a connection to
* the database. If that's not the case, a new connection is opened.
*
* @access private
* @return mixed True or a DB error object.
*/
function _prepare()
{
if (!DB::isConnection($this->db)) {
$res = $this->_connect($this->options['dsn']);
if (DB::isError($res) || PEAR::isError($res)) {
return $res;
}
}
if ($this->options['auto_quote'] && $this->db->dsn['phptype'] != 'sqlite') {
if (strpos('.', $this->options['table']) === false) {
$this->options['final_table'] = $this->db->quoteIdentifier($this->options['table']);
} else {
$t = explode('.', $this->options['table']);
for ($i = 0, $count = count($t); $i < $count; $i++)
$t[$i] = $this->db->quoteIdentifier($t[$i]);
$this->options['final_table'] = implode('.', $t);
}
$this->options['final_usernamecol'] = $this->db->quoteIdentifier($this->options['usernamecol']);
$this->options['final_passwordcol'] = $this->db->quoteIdentifier($this->options['passwordcol']);
} else {
$this->options['final_table'] = $this->options['table'];
$this->options['final_usernamecol'] = $this->options['usernamecol'];
$this->options['final_passwordcol'] = $this->options['passwordcol'];
}
return true;
}
// }}}
// {{{ query()
/**
* Prepare query to the database
*
* This function checks if we have already opened a connection to
* the database. If that's not the case, a new connection is opened.
* After that the query is passed to the database.
*
* @access public
* @param string Query string
* @return mixed a DB_result object or DB_OK on success, a DB
* or PEAR error on failure
*/
function query($query)
{
$err = $this->_prepare();
if ($err !== true) {
return $err;
}
return $this->db->query($query);
}
// }}}
// {{{ _setDefaults()
/**
* Set some default options
*
* @access private
* @return void
*/
function _setDefaults()
{
$this->options['table'] = 'auth';
$this->options['usernamecol'] = 'username';
$this->options['passwordcol'] = 'password';
$this->options['dsn'] = '';
$this->options['db_fields'] = '';
$this->options['cryptType'] = 'md5';
$this->options['db_options'] = array();
$this->options['db_where'] = '';
$this->options['auto_quote'] = true;
}
// }}}
// {{{ _parseOptions()
/**
* Parse options passed to the container class
*
* @access private
* @param array
*/
function _parseOptions($array)
{
foreach ($array as $key => $value) {
if (isset($this->options[$key])) {
$this->options[$key] = $value;
}
}
}
// }}}
// {{{ _quoteDBFields()
/**
* Quote the db_fields option to avoid the possibility of SQL injection.
*
* @access private
* @return string A properly quoted string that can be concatenated into a
* SELECT clause.
*/
function _quoteDBFields()
{
if (isset($this->options['db_fields'])) {
if (is_array($this->options['db_fields'])) {
if ($this->options['auto_quote']) {
$fields = array();
foreach ($this->options['db_fields'] as $field) {
$fields[] = $this->db->quoteIdentifier($field);
}
return implode(', ', $fields);
} else {
return implode(', ', $this->options['db_fields']);
}
} else {
if (strlen($this->options['db_fields']) > 0) {
if ($this->options['auto_quote']) {
return $this->db->quoteIdentifier($this->options['db_fields']);
} else {
return $this->options['db_fields'];
}
}
}
}
return '';
}
// }}}
// {{{ fetchData()
/**
* Get user information from database
*
* This function uses the given username to fetch
* the corresponding login data from the database
* table. If an account that matches the passed username
* and password is found, the function returns true.
* Otherwise it returns false.
*
* @param string Username
* @param string Password
* @param boolean If true password is secured using a md5 hash
* the frontend and auth are responsible for making sure the container supports
* challenge response password authentication
* @return mixed Error object or boolean
*/
function fetchData($username, $password, $isChallengeResponse=false)
{
$this->log('Auth_Container_DB::fetchData() called.', AUTH_LOG_DEBUG);
// Prepare for a database query
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
// Find if db_fields contains a *, if so assume all columns are selected
if (is_string($this->options['db_fields'])
&& strstr($this->options['db_fields'], '*')) {
$sql_from = "*";
} else {
$sql_from = $this->options['final_usernamecol'].
", ".$this->options['final_passwordcol'];
if (strlen($fields = $this->_quoteDBFields()) > 0) {
$sql_from .= ', '.$fields;
}
}
$query = "SELECT ".$sql_from.
" FROM ".$this->options['final_table'].
" WHERE ".$this->options['final_usernamecol']." = ".$this->db->quoteSmart($username);
// check if there is an optional parameter db_where
if ($this->options['db_where'] != '') {
// there is one, so add it to the query
$query .= " AND ".$this->options['db_where'];
}
$this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
$res = $this->db->getRow($query, null, DB_FETCHMODE_ASSOC);
if (DB::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->getCode());
}
if (!is_array($res)) {
$this->activeUser = '';
return false;
}
// Perform trimming here before the hashihg
$password = trim($password, "\r\n");
$res[$this->options['passwordcol']] = trim($res[$this->options['passwordcol']], "\r\n");
// If using Challenge Response md5 the pass with the secret
if ($isChallengeResponse) {
$res[$this->options['passwordcol']] = md5($res[$this->options['passwordcol']]
.$this->_auth_obj->session['loginchallenege']);
// UGLY cannot avoid without modifying verifyPassword
if ($this->options['cryptType'] == 'md5') {
$res[$this->options['passwordcol']] = md5($res[$this->options['passwordcol']]);
}
//print " Hashed Password [{$res[$this->options['passwordcol']]}] \n";
}
if ($this->verifyPassword($password,
$res[$this->options['passwordcol']],
$this->options['cryptType'])) {
// Store additional field values in the session
foreach ($res as $key => $value) {
if ($key == $this->options['passwordcol'] ||
$key == $this->options['usernamecol']) {
continue;
}
$this->log('Storing additional field: '.$key, AUTH_LOG_DEBUG);
// Use reference to the auth object if exists
// This is because the auth session variable can change so a
// static call to setAuthData does not make sence
$this->_auth_obj->setAuthData($key, $value);
}
return true;
}
$this->activeUser = $res[$this->options['usernamecol']];
return false;
}
// }}}
// {{{ listUsers()
/**
* Returns a list of users from the container
*
* @return mixed
* @access public
*/
function listUsers()
{
$this->log('Auth_Container_DB::listUsers() called.', AUTH_LOG_DEBUG);
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
$retVal = array();
// Find if db_fields contains a *, if so assume all col are selected
if ( is_string($this->options['db_fields'])
&& strstr($this->options['db_fields'], '*')) {
$sql_from = "*";
} else {
$sql_from = $this->options['final_usernamecol'].
", ".$this->options['final_passwordcol'];
if (strlen($fields = $this->_quoteDBFields()) > 0) {
$sql_from .= ', '.$fields;
}
}
$query = sprintf("SELECT %s FROM %s",
$sql_from,
$this->options['final_table']
);
// check if there is an optional parameter db_where
if ($this->options['db_where'] != '') {
// there is one, so add it to the query
$query .= " WHERE ".$this->options['db_where'];
}
$this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
$res = $this->db->getAll($query, null, DB_FETCHMODE_ASSOC);
if (DB::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->getCode());
} else {
foreach ($res as $user) {
$user['username'] = $user[$this->options['usernamecol']];
$retVal[] = $user;
}
}
$this->log('Found '.count($retVal).' users.', AUTH_LOG_DEBUG);
return $retVal;
}
// }}}
// {{{ addUser()
/**
* Add user to the storage container
*
* @access public
* @param string Username
* @param string Password
* @param mixed Additional information that are stored in the DB
*
* @return mixed True on success, otherwise error object
*/
function addUser($username, $password, $additional = "")
{
$this->log('Auth_Container_DB::addUser() called.', AUTH_LOG_DEBUG);
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
if ( isset($this->options['cryptType'])
&& $this->options['cryptType'] == 'none') {
$cryptFunction = 'strval';
} elseif ( isset($this->options['cryptType'])
&& function_exists($this->options['cryptType'])) {
$cryptFunction = $this->options['cryptType'];
} else {
$cryptFunction = 'md5';
}
$password = $cryptFunction($password);
$additional_key = '';
$additional_value = '';
if (is_array($additional)) {
foreach ($additional as $key => $value) {
if ($this->options['auto_quote']) {
$additional_key .= ', ' . $this->db->quoteIdentifier($key);
} else {
$additional_key .= ', ' . $key;
}
$additional_value .= ", " . $this->db->quoteSmart($value);
}
}
$query = sprintf("INSERT INTO %s (%s, %s%s) VALUES (%s, %s%s)",
$this->options['final_table'],
$this->options['final_usernamecol'],
$this->options['final_passwordcol'],
$additional_key,
$this->db->quoteSmart($username),
$this->db->quoteSmart($password),
$additional_value
);
$this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
$res = $this->query($query);
if (DB::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->getCode());
} else {
return true;
}
}
// }}}
// {{{ removeUser()
/**
* Remove user from the storage container
*
* @access public
* @param string Username
*
* @return mixed True on success, otherwise error object
*/
function removeUser($username)
{
$this->log('Auth_Container_DB::removeUser() called.', AUTH_LOG_DEBUG);
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
// check if there is an optional parameter db_where
if ($this->options['db_where'] != '') {
// there is one, so add it to the query
$where = " AND ".$this->options['db_where'];
} else {
$where = '';
}
$query = sprintf("DELETE FROM %s WHERE %s = %s %s",
$this->options['final_table'],
$this->options['final_usernamecol'],
$this->db->quoteSmart($username),
$where
);
$this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
$res = $this->query($query);
if (DB::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->getCode());
} else {
return true;
}
}
// }}}
// {{{ changePassword()
/**
* Change password for user in the storage container
*
* @param string Username
* @param string The new password (plain text)
*/
function changePassword($username, $password)
{
$this->log('Auth_Container_DB::changePassword() called.', AUTH_LOG_DEBUG);
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
if ( isset($this->options['cryptType'])
&& $this->options['cryptType'] == 'none') {
$cryptFunction = 'strval';
} elseif ( isset($this->options['cryptType'])
&& function_exists($this->options['cryptType'])) {
$cryptFunction = $this->options['cryptType'];
} else {
$cryptFunction = 'md5';
}
$password = $cryptFunction($password);
// check if there is an optional parameter db_where
if ($this->options['db_where'] != '') {
// there is one, so add it to the query
$where = " AND ".$this->options['db_where'];
} else {
$where = '';
}
$query = sprintf("UPDATE %s SET %s = %s WHERE %s = %s %s",
$this->options['final_table'],
$this->options['final_passwordcol'],
$this->db->quoteSmart($password),
$this->options['final_usernamecol'],
$this->db->quoteSmart($username),
$where
);
$this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
$res = $this->query($query);
if (DB::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->getCode());
} else {
return true;
}
}
// }}}
// {{{ supportsChallengeResponse()
/**
* Determine if this container supports
* password authentication with challenge response
*
* @return bool
* @access public
*/
function supportsChallengeResponse()
{
return in_array($this->options['cryptType'], array('md5', 'none', ''));
}
// }}}
// {{{ getCryptType()
/**
* Returns the selected crypt type for this container
*/
function getCryptType()
{
return($this->options['cryptType']);
}
// }}}
}
?>
Auth-1.6.4/Auth/Container/DBLite.php 0000600 0001750 0001750 00000024514 11461311103 017633 0 ustar clockwerx clockwerx
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: DBLite.php 256753 2008-04-04 07:57:02Z aashley $
* @link http://pear.php.net/package/Auth
* @since File available since Release 1.3.0
*/
/**
* Include Auth_Container base class
*/
require_once 'Auth/Container.php';
/**
* Include PEAR DB package
*/
require_once 'DB.php';
/**
* A lighter storage driver for fetching login data from a database
*
* This driver is derived from the DB storage container but
* with the user manipulation function removed for smaller file size
* by the PEAR DB abstraction layer to fetch login data.
*
* @category Authentication
* @package Auth
* @author Martin Jansen
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 256753 $
* @link http://pear.php.net/package/Auth
* @since Class available since Release 1.3.0
*/
class Auth_Container_DBLite extends Auth_Container
{
// {{{ properties
/**
* Additional options for the storage container
* @var array
*/
var $options = array();
/**
* DB object
* @var object
*/
var $db = null;
var $dsn = '';
/**
* User that is currently selected from the DB.
* @var string
*/
var $activeUser = '';
// }}}
// {{{ Auth_Container_DBLite() [constructor]
/**
* Constructor of the container class
*
* Initate connection to the database via PEAR::DB
*
* @param string Connection data or DB object
* @return object Returns an error object if something went wrong
*/
function Auth_Container_DBLite($dsn)
{
$this->options['table'] = 'auth';
$this->options['usernamecol'] = 'username';
$this->options['passwordcol'] = 'password';
$this->options['dsn'] = '';
$this->options['db_fields'] = '';
$this->options['cryptType'] = 'md5';
$this->options['db_options'] = array();
$this->options['db_where'] = '';
$this->options['auto_quote'] = true;
if (is_array($dsn)) {
$this->_parseOptions($dsn);
if (empty($this->options['dsn'])) {
PEAR::raiseError('No connection parameters specified!');
}
} else {
$this->options['dsn'] = $dsn;
}
}
// }}}
// {{{ _connect()
/**
* Connect to database by using the given DSN string
*
* @access private
* @param string DSN string
* @return mixed Object on error, otherwise bool
*/
function _connect(&$dsn)
{
$this->log('Auth_Container_DBLite::_connect() called.', AUTH_LOG_DEBUG);
if (is_string($dsn) || is_array($dsn)) {
$this->db =& DB::connect($dsn, $this->options['db_options']);
} elseif (is_subclass_of($dsn, "db_common")) {
$this->db =& $dsn;
} else {
return PEAR::raiseError("Invalid dsn or db object given");
}
if (DB::isError($this->db) || PEAR::isError($this->db)) {
return PEAR::raiseError($this->db->getMessage(), $this->db->getCode());
} else {
return true;
}
}
// }}}
// {{{ _prepare()
/**
* Prepare database connection
*
* This function checks if we have already opened a connection to
* the database. If that's not the case, a new connection is opened.
*
* @access private
* @return mixed True or a DB error object.
*/
function _prepare()
{
if (!DB::isConnection($this->db)) {
$res = $this->_connect($this->options['dsn']);
if (DB::isError($res) || PEAR::isError($res)) {
return $res;
}
}
if ($this->options['auto_quote'] && $this->db->dsn['phptype'] != 'sqlite') {
if (strpos('.', $this->options['table']) === false) {
$this->options['final_table'] = $this->db->quoteIdentifier($this->options['table']);
} else {
$t = explode('.', $this->options['table']);
for ($i = 0, $count = count($t); $i < $count; $i++)
$t[$i] = $this->db->quoteIdentifier($t[$i]);
$this->options['final_table'] = implode('.', $t);
}
$this->options['final_usernamecol'] = $this->db->quoteIdentifier($this->options['usernamecol']);
$this->options['final_passwordcol'] = $this->db->quoteIdentifier($this->options['passwordcol']);
} else {
$this->options['final_table'] = $this->options['table'];
$this->options['final_usernamecol'] = $this->options['usernamecol'];
$this->options['final_passwordcol'] = $this->options['passwordcol'];
}
return true;
}
// }}}
// {{{ _parseOptions()
/**
* Parse options passed to the container class
*
* @access private
* @param array
*/
function _parseOptions($array)
{
foreach ($array as $key => $value) {
if (isset($this->options[$key])) {
$this->options[$key] = $value;
}
}
}
// }}}
// {{{ _quoteDBFields()
/**
* Quote the db_fields option to avoid the possibility of SQL injection.
*
* @access private
* @return string A properly quoted string that can be concatenated into a
* SELECT clause.
*/
function _quoteDBFields()
{
if (isset($this->options['db_fields'])) {
if (is_array($this->options['db_fields'])) {
if ($this->options['auto_quote']) {
$fields = array();
foreach ($this->options['db_fields'] as $field) {
$fields[] = $this->db->quoteIdentifier($field);
}
return implode(', ', $fields);
} else {
return implode(', ', $this->options['db_fields']);
}
} else {
if (strlen($this->options['db_fields']) > 0) {
if ($this->options['auto_quote']) {
return $this->db->quoteIdentifier($this->options['db_fields']);
} else {
$this->options['db_fields'];
}
}
}
}
return '';
}
// }}}
// {{{ fetchData()
/**
* Get user information from database
*
* This function uses the given username to fetch
* the corresponding login data from the database
* table. If an account that matches the passed username
* and password is found, the function returns true.
* Otherwise it returns false.
*
* @param string Username
* @param string Password
* @return mixed Error object or boolean
*/
function fetchData($username, $password)
{
$this->log('Auth_Container_DBLite::fetchData() called.', AUTH_LOG_DEBUG);
// Prepare for a database query
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
// Find if db_fields contains a *, if so assume all col are selected
if (is_string($this->options['db_fields'])
&& strstr($this->options['db_fields'], '*')) {
$sql_from = "*";
} else {
$sql_from = $this->options['final_usernamecol'].
", ".$this->options['final_passwordcol'];
if (strlen($fields = $this->_quoteDBFields()) > 0) {
$sql_from .= ', '.$fields;
}
}
$query = "SELECT ".$sql_from.
" FROM ".$this->options['final_table'].
" WHERE ".$this->options['final_usernamecol']." = ".$this->db->quoteSmart($username);
// check if there is an optional parameter db_where
if ($this->options['db_where'] != '') {
// there is one, so add it to the query
$query .= " AND ".$this->options['db_where'];
}
$this->log('Running SQL against DB: '.$query, AUTH_LOG_DEBUG);
$res = $this->db->getRow($query, null, DB_FETCHMODE_ASSOC);
if (DB::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->getCode());
}
if (!is_array($res)) {
$this->activeUser = '';
return false;
}
if ($this->verifyPassword(trim($password, "\r\n"),
trim($res[$this->options['passwordcol']], "\r\n"),
$this->options['cryptType'])) {
// Store additional field values in the session
foreach ($res as $key => $value) {
if ($key == $this->options['passwordcol'] ||
$key == $this->options['usernamecol']) {
continue;
}
$this->log('Storing additional field: '.$key, AUTH_LOG_DEBUG);
// Use reference to the auth object if exists
// This is because the auth session variable can change so a static call to setAuthData does not make sence
if (is_object($this->_auth_obj)) {
$this->_auth_obj->setAuthData($key, $value);
} else {
Auth::setAuthData($key, $value);
}
}
$this->activeUser = $res[$this->options['usernamecol']];
return true;
}
$this->activeUser = $res[$this->options['usernamecol']];
return false;
}
// }}}
}
?>
Auth-1.6.4/Auth/Container/File.php 0000600 0001750 0001750 00000017020 11461311103 017401 0 ustar clockwerx clockwerx
* @author Martin Jansen
* @author Mika Tuupola
* @author Michael Wallner
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: File.php 237449 2007-06-12 03:11:27Z aashley $
* @link http://pear.php.net/package/Auth
*/
/**
* Include PEAR File_Passwd package
*/
require_once "File/Passwd.php";
/**
* Include Auth_Container base class
*/
require_once "Auth/Container.php";
/**
* Include PEAR package for error handling
*/
require_once "PEAR.php";
/**
* Storage driver for fetching login data from an encrypted password file.
*
* This storage container can handle CVS pserver style passwd files.
*
* @category Authentication
* @package Auth
* @author Stefan Ekman
* @author Martin Jansen
* @author Mika Tuupola
* @author Michael Wallner
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 237449 $
* @link http://pear.php.net/package/Auth
*/
class Auth_Container_File extends Auth_Container
{
// {{{ properties
/**
* Path to passwd file
*
* @var string
*/
var $pwfile = '';
/**
* Options for container
*
* @var array
*/
var $options = array();
// }}}
// {{{ Auth_Container_File() [constructor]
/**
* Constructor of the container class
*
* @param string $filename path to passwd file
* @return object Auth_Container_File new Auth_Container_File object
*/
function Auth_Container_File($filename) {
$this->_setDefaults();
// Only file is a valid option here
if(is_array($filename)) {
$this->pwfile = $filename['file'];
$this->_parseOptions($filename);
} else {
$this->pwfile = $filename;
}
}
// }}}
// {{{ fetchData()
/**
* Authenticate an user
*
* @param string username
* @param string password
* @return mixed boolean|PEAR_Error
*/
function fetchData($user, $pass)
{
$this->log('Auth_Container_File::fetchData() called.', AUTH_LOG_DEBUG);
return File_Passwd::staticAuth($this->options['type'], $this->pwfile, $user, $pass);
}
// }}}
// {{{ listUsers()
/**
* List all available users
*
* @return array
*/
function listUsers()
{
$this->log('Auth_Container_File::listUsers() called.', AUTH_LOG_DEBUG);
$pw_obj = &$this->_load();
if (PEAR::isError($pw_obj)) {
return array();
}
$users = $pw_obj->listUser();
if (!is_array($users)) {
return array();
}
foreach ($users as $key => $value) {
$retVal[] = array("username" => $key,
"password" => $value['passwd'],
"cvsuser" => $value['system']);
}
$this->log('Found '.count($retVal).' users.', AUTH_LOG_DEBUG);
return $retVal;
}
// }}}
// {{{ addUser()
/**
* Add a new user to the storage container
*
* @param string username
* @param string password
* @param mixed Additional parameters to File_Password_*::addUser()
*
* @return boolean
*/
function addUser($user, $pass, $additional='')
{
$this->log('Auth_Container_File::addUser() called.', AUTH_LOG_DEBUG);
$params = array($user, $pass);
if (is_array($additional)) {
foreach ($additional as $item) {
$params[] = $item;
}
} else {
$params[] = $additional;
}
$pw_obj = &$this->_load();
if (PEAR::isError($pw_obj)) {
return false;
}
$res = call_user_func_array(array(&$pw_obj, 'addUser'), $params);
if (PEAR::isError($res)) {
return false;
}
$res = $pw_obj->save();
if (PEAR::isError($res)) {
return false;
}
return true;
}
// }}}
// {{{ removeUser()
/**
* Remove user from the storage container
*
* @param string Username
* @return boolean
*/
function removeUser($user)
{
$this->log('Auth_Container_File::removeUser() called.', AUTH_LOG_DEBUG);
$pw_obj = &$this->_load();
if (PEAR::isError($pw_obj)) {
return false;
}
$res = $pw_obj->delUser($user);
if (PEAR::isError($res)) {
return false;
}
$res = $pw_obj->save();
if (PEAR::isError($res)) {
return false;
}
return true;
}
// }}}
// {{{ changePassword()
/**
* Change password for user in the storage container
*
* @param string Username
* @param string The new password
*/
function changePassword($username, $password)
{
$this->log('Auth_Container_File::changePassword() called.', AUTH_LOG_DEBUG);
$pw_obj = &$this->_load();
if (PEAR::isError($pw_obj)) {
return false;
}
$res = $pw_obj->changePasswd($username, $password);
if (PEAR::isError($res)) {
return false;
}
$res = $pw_obj->save();
if (PEAR::isError($res)) {
return false;
}
return true;
}
// }}}
// {{{ _load()
/**
* Load and initialize the File_Passwd object
*
* @return object File_Passwd_Cvs|PEAR_Error
*/
function &_load()
{
static $pw_obj;
if (!isset($pw_obj)) {
$this->log('Instanciating File_Password object of type '.$this->options['type'], AUTH_LOG_DEBUG);
$pw_obj = File_Passwd::factory($this->options['type']);
if (PEAR::isError($pw_obj)) {
return $pw_obj;
}
$pw_obj->setFile($this->pwfile);
$res = $pw_obj->load();
if (PEAR::isError($res)) {
return $res;
}
}
return $pw_obj;
}
// }}}
// {{{ _setDefaults()
/**
* Set some default options
*
* @access private
* @return void
*/
function _setDefaults()
{
$this->options['type'] = 'Cvs';
}
// }}}
// {{{ _parseOptions()
/**
* Parse options passed to the container class
*
* @access private
* @param array
*/
function _parseOptions($array)
{
foreach ($array as $key => $value) {
if (isset($this->options[$key])) {
$this->options[$key] = $value;
}
}
}
// }}}
}
?>
Auth-1.6.4/Auth/Container/IMAP.php 0000600 0001750 0001750 00000014123 11461311103 017251 0 ustar clockwerx clockwerx
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: IMAP.php 237449 2007-06-12 03:11:27Z aashley $
* @link http://pear.php.net/package/Auth
* @since File available since Release 1.2.0
*/
/**
* Include Auth_Container base class
*/
require_once "Auth/Container.php";
/**
* Include PEAR class for error handling
*/
require_once "PEAR.php";
/**
* Storage driver for fetching login data from an IMAP server
*
* This class is based on LDAP containers, but it very simple.
* By default it connects to localhost:143
* The constructor will first check if the host:port combination is
* actually reachable. This behaviour can be disabled.
* It then tries to create an IMAP stream (without opening a mailbox)
* If you wish to pass extended options to the connections, you may
* do so by specifying protocol options.
*
* To use this storage containers, you have to use the
* following syntax:
*
* 'mail.example.com',
* 'port' => 143,
* );
* $myAuth = new Auth('IMAP', $params);
* ...
*
* By default we connect without any protocol options set. However, some
* servers require you to connect with the notls or norsh options set.
* To do this you need to add the following value to the params array:
* 'baseDSN' => '/imap/notls/norsh'
*
* To connect to an SSL IMAP server:
* 'baseDSN' => '/imap/ssl'
*
* To connect to an SSL IMAP server with a self-signed certificate:
* 'baseDSN' => '/imap/ssl/novalidate-cert'
*
* Further options may be available and can be found on the php site at
* http://www.php.net/manual/function.imap-open.php
*
* @category Authentication
* @package Auth
* @author Jeroen Houben
* @author Cipriano Groenendal
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 237449 $
* @link http://pear.php.net/package/Auth
* @since Class available since Release 1.2.0
*/
class Auth_Container_IMAP extends Auth_Container
{
// {{{ properties
/**
* Options for the class
* @var array
*/
var $options = array();
// }}}
// {{{ Auth_Container_IMAP() [constructor]
/**
* Constructor of the container class
*
* @param $params associative array with host, port, baseDSN, checkServer
* and userattr key
* @return object Returns an error object if something went wrong
* @todo Use PEAR Net_IMAP if IMAP extension not loaded
*/
function Auth_Container_IMAP($params)
{
if (!extension_loaded('imap')) {
return PEAR::raiseError('Cannot use IMAP authentication, '
.'IMAP extension not loaded!', 41, PEAR_ERROR_DIE);
}
$this->_setDefaults();
// set parameters (if any)
if (is_array($params)) {
$this->_parseOptions($params);
}
if ($this->options['checkServer']) {
$this->_checkServer($this->options['timeout']);
}
return true;
}
// }}}
// {{{ _setDefaults()
/**
* Set some default options
*
* @access private
*/
function _setDefaults()
{
$this->options['host'] = 'localhost';
$this->options['port'] = 143;
$this->options['baseDSN'] = '';
$this->options['checkServer'] = true;
$this->options['timeout'] = 20;
}
// }}}
// {{{ _checkServer()
/**
* Check if the given server and port are reachable
*
* @access private
*/
function _checkServer() {
$this->log('Auth_Container_IMAP::_checkServer() called.', AUTH_LOG_DEBUG);
$fp = @fsockopen ($this->options['host'], $this->options['port'],
$errno, $errstr, $this->options['timeout']);
if (is_resource($fp)) {
@fclose($fp);
} else {
$message = "Error connecting to IMAP server "
. $this->options['host']
. ":" . $this->options['port'];
return PEAR::raiseError($message, 41);
}
}
// }}}
// {{{ _parseOptions()
/**
* Parse options passed to the container class
*
* @access private
* @param array
*/
function _parseOptions($array)
{
foreach ($array as $key => $value) {
$this->options[$key] = $value;
}
}
// }}}
// {{{ fetchData()
/**
* Try to open a IMAP stream using $username / $password
*
* @param string Username
* @param string Password
* @return boolean
*/
function fetchData($username, $password)
{
$this->log('Auth_Container_IMAP::fetchData() called.', AUTH_LOG_DEBUG);
$dsn = '{'.$this->options['host'].':'.$this->options['port'].$this->options['baseDSN'].'}';
$conn = @imap_open ($dsn, $username, $password, OP_HALFOPEN);
if (is_resource($conn)) {
$this->log('Successfully connected to IMAP server.', AUTH_LOG_DEBUG);
$this->activeUser = $username;
@imap_close($conn);
return true;
} else {
$this->log('Connection to IMAP server failed.', AUTH_LOG_DEBUG);
$this->activeUser = '';
return false;
}
}
// }}}
}
?>
Auth-1.6.4/Auth/Container/KADM5.php 0000600 0001750 0001750 00000011703 11461311103 017325 0 ustar clockwerx clockwerx
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: KADM5.php 237449 2007-06-12 03:11:27Z aashley $
* @link http://pear.php.net/package/Auth
* @since File available since Release 1.4.0
*/
/**
* Include Auth_Container base class
*/
require_once 'Auth/Container.php';
/**
* Include PEAR for error handling
*/
require_once 'PEAR.php';
/**
* Storage driver for Authentication on a Kerberos V server.
*
* Available options:
* hostname: The hostname of the kerberos server
* realm: The Kerberos V realm
* timeout: The timeout for checking the server
* checkServer: Set to true to check if the server is running when
* constructing the object
*
* @category Authentication
* @package Auth
* @author Andrew Teixeira
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 237449 $
* @link http://pear.php.net/package/Auth
* @since Class available since Release 1.4.0
*/
class Auth_Container_KADM5 extends Auth_Container {
// {{{ properties
/**
* Options for the class
* @var string
*/
var $options = array();
// }}}
// {{{ Auth_Container_KADM5()
/**
* Constructor of the container class
*
* $options can have these keys:
* 'hostname' The hostname of the kerberos server
* 'realm' The Kerberos V realm
* 'timeout' The timeout for checking the server
* 'checkServer' Set to true to check if the server is running when
* constructing the object
*
* @param $options associative array
* @return object Returns an error object if something went wrong
*/
function Auth_Container_KADM5($options) {
if (!extension_loaded('kadm5')) {
return PEAR::raiseError("Cannot use Kerberos V authentication, KADM5 extension not loaded!", 41, PEAR_ERROR_DIE);
}
$this->_setDefaults();
if (isset($options['hostname'])) {
$this->options['hostname'] = $options['hostname'];
}
if (isset($options['realm'])) {
$this->options['realm'] = $options['realm'];
}
if (isset($options['timeout'])) {
$this->options['timeout'] = $options['timeout'];
}
if (isset($options['checkServer'])) {
$this->options['checkServer'] = $options['checkServer'];
}
if ($this->options['checkServer']) {
$this->_checkServer();
}
}
// }}}
// {{{ fetchData()
/**
* Try to login to the KADM5 server
*
* @param string Username
* @param string Password
* @return boolean
*/
function fetchData($username, $password) {
$this->log('Auth_Container_KADM5::fetchData() called.', AUTH_LOG_DEBUG);
if ( ($username == NULL) || ($password == NULL) ) {
return false;
}
$server = $this->options['hostname'];
$realm = $this->options['realm'];
$check = @kadm5_init_with_password($server, $realm, $username, $password);
if ($check == false) {
return false;
} else {
return true;
}
}
// }}}
// {{{ _setDefaults()
/**
* Set some default options
*
* @access private
*/
function _setDefaults() {
$this->options['hostname'] = 'localhost';
$this->options['realm'] = NULL;
$this->options['timeout'] = 10;
$this->options['checkServer'] = false;
}
// }}}
// {{{ _checkServer()
/**
* Check if the given server and port are reachable
*
* @access private
*/
function _checkServer() {
$fp = @fsockopen ($this->options['hostname'], 88, $errno, $errstr, $this->options['timeout']);
if (is_resource($fp)) {
@fclose($fp);
} else {
$message = "Error connecting to Kerberos V server "
.$this->options['hostname'].":".$this->options['port'];
return PEAR::raiseError($message, 41, PEAR_ERROR_DIE);
}
}
// }}}
}
?>
Auth-1.6.4/Auth/Container/LDAP.php 0000600 0001750 0001750 00000071515 11461311103 017253 0 ustar clockwerx clockwerx
* @author Adam Ashley
* @author Hugues Peeters
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: LDAP.php 237449 2007-06-12 03:11:27Z aashley $
* @link http://pear.php.net/package/Auth
*/
/**
* Include Auth_Container base class
*/
require_once "Auth/Container.php";
/**
* Include PEAR package for error handling
*/
require_once "PEAR.php";
/**
* Storage driver for fetching login data from LDAP
*
* This class is heavily based on the DB and File containers. By default it
* connects to localhost:389 and searches for uid=$username with the scope
* "sub". If no search base is specified, it will try to determine it via
* the namingContexts attribute. It takes its parameters in a hash, connects
* to the ldap server, binds anonymously, searches for the user, and tries
* to bind as the user with the supplied password. When a group was set, it
* will look for group membership of the authenticated user. If all goes
* well the authentication was successful.
*
* Parameters:
*
* host: localhost (default), ldap.netsols.de or 127.0.0.1
* port: 389 (default) or 636 or whereever your server runs
* url: ldap://localhost:389/
* useful for ldaps://, works only with openldap2 ?
* it will be preferred over host and port
* version: LDAP version to use, ususally 2 (default) or 3,
* must be an integer!
* referrals: If set, determines whether the LDAP library automatically
* follows referrals returned by LDAP servers or not. Possible
* values are true (default) or false.
* binddn: If set, searching for user will be done after binding
* as this user, if not set the bind will be anonymous.
* This is reported to make the container work with MS
* Active Directory, but should work with any server that
* is configured this way.
* This has to be a complete dn for now (basedn and
* userdn will not be appended).
* bindpw: The password to use for binding with binddn
* basedn: the base dn of your server
* userdn: gets prepended to basedn when searching for user
* userscope: Scope for user searching: one, sub (default), or base
* userattr: the user attribute to search for (default: uid)
* userfilter: filter that will be added to the search filter
* this way: (&(userattr=username)(userfilter))
* default: (objectClass=posixAccount)
* attributes: array of additional attributes to fetch from entry.
* these will added to auth data and can be retrieved via
* Auth::getAuthData(). An empty array will fetch all attributes,
* array('') will fetch no attributes at all (default)
* If you add 'dn' as a value to this array, the users DN that was
* used for binding will be added to auth data as well.
* attrformat: The returned format of the additional data defined in the
* 'attributes' option. Two formats are available.
* LDAP returns data formatted in a
* multidimensional array where each array starts with a
* 'count' element providing the number of attributes in the
* entry, or the number of values for attributes. When set
* to this format, the only way to retrieve data from the
* Auth object is by calling getAuthData('attributes').
* AUTH returns data formatted in a
* structure more compliant with other Auth Containers,
* where each attribute element can be directly called by
* getAuthData() method from Auth.
* For compatibily with previous LDAP container versions,
* the default format is LDAP.
* groupdn: gets prepended to basedn when searching for group
* groupattr: the group attribute to search for (default: cn)
* groupfilter: filter that will be added to the search filter when
* searching for a group:
* (&(groupattr=group)(memberattr=username)(groupfilter))
* default: (objectClass=groupOfUniqueNames)
* memberattr : the attribute of the group object where the user dn
* may be found (default: uniqueMember)
* memberisdn: whether the memberattr is the dn of the user (default)
* or the value of userattr (usually uid)
* group: the name of group to search for
* groupscope: Scope for group searching: one, sub (default), or base
* start_tls: enable/disable the use of START_TLS encrypted connection
* (default: false)
* debug: Enable/Disable debugging output (default: false)
* try_all: Whether to try all user accounts returned from the search
* or just the first one. (default: false)
*
* To use this storage container, you have to use the following syntax:
*
* 'localhost',
* 'port' => '389',
* 'version' => 3,
* 'basedn' => 'o=netsols,c=de',
* 'userattr' => 'uid'
* 'binddn' => 'cn=admin,o=netsols,c=de',
* 'bindpw' => 'password'));
*
* $a2 = new Auth('LDAP', array(
* 'url' => 'ldaps://ldap.netsols.de',
* 'basedn' => 'o=netsols,c=de',
* 'userscope' => 'one',
* 'userdn' => 'ou=People',
* 'groupdn' => 'ou=Groups',
* 'groupfilter' => '(objectClass=posixGroup)',
* 'memberattr' => 'memberUid',
* 'memberisdn' => false,
* 'group' => 'admin'
* ));
*
* $a3 = new Auth('LDAP', array(
* 'host' => 'ldap.netsols.de',
* 'port' => 389,
* 'version' => 3,
* 'referrals' => false,
* 'basedn' => 'dc=netsols,dc=de',
* 'binddn' => 'cn=Jan Wagner,cn=Users,dc=netsols,dc=de',
* 'bindpw' => 'password',
* 'userattr' => 'samAccountName',
* 'userfilter' => '(objectClass=user)',
* 'attributes' => array(''),
* 'group' => 'testing',
* 'groupattr' => 'samAccountName',
* 'groupfilter' => '(objectClass=group)',
* 'memberattr' => 'member',
* 'memberisdn' => true,
* 'groupdn' => 'cn=Users',
* 'groupscope' => 'one',
* 'debug' => true);
*
* The parameter values have to correspond
* to the ones for your LDAP server of course.
*
* When talking to a Microsoft ActiveDirectory server you have to
* use 'samaccountname' as the 'userattr' and follow special rules
* to translate the ActiveDirectory directory names into 'basedn'.
* The 'basedn' for the default 'Users' folder on an ActiveDirectory
* server for the ActiveDirectory Domain (which is not related to
* its DNS name) "win2000.example.org" would be:
* "CN=Users, DC=win2000, DC=example, DC=org'
* where every component of the domain name becomes a DC attribute
* of its own. If you want to use a custom users folder you have to
* replace "CN=Users" with a sequence of "OU" attributes that specify
* the path to your custom folder in reverse order.
* So the ActiveDirectory folder
* "win2000.example.org\Custom\Accounts"
* would become
* "OU=Accounts, OU=Custom, DC=win2000, DC=example, DC=org'
*
* It seems that binding anonymously to an Active Directory
* is not allowed, so you have to set binddn and bindpw for
* user searching.
*
* LDAP Referrals need to be set to false for AD to work sometimes.
*
* Example a3 shows a full blown and tested example for connection to
* Windows 2000 Active Directory with group mebership checking
*
* Note also that if you want an encrypted connection to an MS LDAP
* server, then, on your webserver, you must specify
* TLS_REQCERT never
* in /etc/ldap/ldap.conf or in the webserver user's ~/.ldaprc (which
* may or may not be read depending on your configuration).
*
*
* @category Authentication
* @package Auth
* @author Jan Wagner
* @author Adam Ashley
* @author Hugues Peeters
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 237449 $
* @link http://pear.php.net/package/Auth
*/
class Auth_Container_LDAP extends Auth_Container
{
// {{{ properties
/**
* Options for the class
* @var array
*/
var $options = array();
/**
* Connection ID of LDAP Link
* @var string
*/
var $conn_id = false;
// }}}
// {{{ Auth_Container_LDAP() [constructor]
/**
* Constructor of the container class
*
* @param $params, associative hash with host,port,basedn and userattr key
* @return object Returns an error object if something went wrong
*/
function Auth_Container_LDAP($params)
{
if (false === extension_loaded('ldap')) {
return PEAR::raiseError('Auth_Container_LDAP: LDAP Extension not loaded',
41, PEAR_ERROR_DIE);
}
$this->_setDefaults();
if (is_array($params)) {
$this->_parseOptions($params);
}
}
// }}}
// {{{ _prepare()
/**
* Prepare LDAP connection
*
* This function checks if we have already opened a connection to
* the LDAP server. If that's not the case, a new connection is opened.
*
* @access private
* @return mixed True or a PEAR error object.
*/
function _prepare()
{
if (!$this->_isValidLink()) {
$res = $this->_connect();
if (PEAR::isError($res)) {
return $res;
}
}
return true;
}
// }}}
// {{{ _connect()
/**
* Connect to the LDAP server using the global options
*
* @access private
* @return object Returns a PEAR error object if an error occurs.
*/
function _connect()
{
$this->log('Auth_Container_LDAP::_connect() called.', AUTH_LOG_DEBUG);
// connect
if (isset($this->options['url']) && $this->options['url'] != '') {
$this->log('Connecting with URL', AUTH_LOG_DEBUG);
$conn_params = array($this->options['url']);
} else {
$this->log('Connecting with host:port', AUTH_LOG_DEBUG);
$conn_params = array($this->options['host'], $this->options['port']);
}
if (($this->conn_id = @call_user_func_array('ldap_connect', $conn_params)) === false) {
$this->log('Connection to server failed.', AUTH_LOG_DEBUG);
$this->log('LDAP ERROR: '.ldap_errno($this->conn_id).': '.ldap_error($this->conn_id), AUTH_LOG_DEBUG);
return PEAR::raiseError('Auth_Container_LDAP: Could not connect to server.', 41);
}
$this->log('Successfully connected to server', AUTH_LOG_DEBUG);
// switch LDAP version
if (is_numeric($this->options['version']) && $this->options['version'] > 2) {
$this->log("Switching to LDAP version {$this->options['version']}", AUTH_LOG_DEBUG);
@ldap_set_option($this->conn_id, LDAP_OPT_PROTOCOL_VERSION, $this->options['version']);
// start TLS if available
if (isset($this->options['start_tls']) && $this->options['start_tls']) {
$this->log("Starting TLS session", AUTH_LOG_DEBUG);
if (@ldap_start_tls($this->conn_id) === false) {
$this->log('Could not start TLS session', AUTH_LOG_DEBUG);
$this->log('LDAP ERROR: '.ldap_errno($this->conn_id).': '.ldap_error($this->conn_id), AUTH_LOG_DEBUG);
return PEAR::raiseError('Auth_Container_LDAP: Could not start tls.', 41);
}
}
}
// switch LDAP referrals
if (is_bool($this->options['referrals'])) {
$this->log("Switching LDAP referrals to " . (($this->options['referrals']) ? 'true' : 'false'), AUTH_LOG_DEBUG);
if (@ldap_set_option($this->conn_id, LDAP_OPT_REFERRALS, $this->options['referrals']) === false) {
$this->log('Could not change LDAP referrals options', AUTH_LOG_DEBUG);
$this->log('LDAP ERROR: '.ldap_errno($this->conn_id).': '.ldap_error($this->conn_id), AUTH_LOG_DEBUG);
}
}
// bind with credentials or anonymously
if (strlen($this->options['binddn']) && strlen($this->options['bindpw'])) {
$this->log('Binding with credentials', AUTH_LOG_DEBUG);
$bind_params = array($this->conn_id, $this->options['binddn'], $this->options['bindpw']);
} else {
$this->log('Binding anonymously', AUTH_LOG_DEBUG);
$bind_params = array($this->conn_id);
}
// bind for searching
if ((@call_user_func_array('ldap_bind', $bind_params)) === false) {
$this->log('Bind failed', AUTH_LOG_DEBUG);
$this->log('LDAP ERROR: '.ldap_errno($this->conn_id).': '.ldap_error($this->conn_id), AUTH_LOG_DEBUG);
$this->_disconnect();
return PEAR::raiseError("Auth_Container_LDAP: Could not bind to LDAP server.", 41);
}
$this->log('Binding was successful', AUTH_LOG_DEBUG);
return true;
}
// }}}
// {{{ _disconnect()
/**
* Disconnects (unbinds) from ldap server
*
* @access private
*/
function _disconnect()
{
$this->log('Auth_Container_LDAP::_disconnect() called.', AUTH_LOG_DEBUG);
if ($this->_isValidLink()) {
$this->log('disconnecting from server');
@ldap_unbind($this->conn_id);
}
}
// }}}
// {{{ _getBaseDN()
/**
* Tries to find Basedn via namingContext Attribute
*
* @access private
*/
function _getBaseDN()
{
$this->log('Auth_Container_LDAP::_getBaseDN() called.', AUTH_LOG_DEBUG);
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
if ($this->options['basedn'] == "" && $this->_isValidLink()) {
$this->log("basedn not set, searching via namingContexts.", AUTH_LOG_DEBUG);
$result_id = @ldap_read($this->conn_id, "", "(objectclass=*)", array("namingContexts"));
if (@ldap_count_entries($this->conn_id, $result_id) == 1) {
$this->log("got result for namingContexts", AUTH_LOG_DEBUG);
$entry_id = @ldap_first_entry($this->conn_id, $result_id);
$attrs = @ldap_get_attributes($this->conn_id, $entry_id);
$basedn = $attrs['namingContexts'][0];
if ($basedn != "") {
$this->log("result for namingContexts was $basedn", AUTH_LOG_DEBUG);
$this->options['basedn'] = $basedn;
}
}
@ldap_free_result($result_id);
}
// if base ist still not set, raise error
if ($this->options['basedn'] == "") {
return PEAR::raiseError("Auth_Container_LDAP: LDAP search base not specified!", 41);
}
return true;
}
// }}}
// {{{ _isValidLink()
/**
* determines whether there is a valid ldap conenction or not
*
* @accessd private
* @return boolean
*/
function _isValidLink()
{
if (is_resource($this->conn_id)) {
if (get_resource_type($this->conn_id) == 'ldap link') {
return true;
}
}
return false;
}
// }}}
// {{{ _setDefaults()
/**
* Set some default options
*
* @access private
*/
function _setDefaults()
{
$this->options['url'] = '';
$this->options['host'] = 'localhost';
$this->options['port'] = '389';
$this->options['version'] = 2;
$this->options['referrals'] = true;
$this->options['binddn'] = '';
$this->options['bindpw'] = '';
$this->options['basedn'] = '';
$this->options['userdn'] = '';
$this->options['userscope'] = 'sub';
$this->options['userattr'] = 'uid';
$this->options['userfilter'] = '(objectClass=posixAccount)';
$this->options['attributes'] = array(''); // no attributes
$this->options['attrformat'] = 'AUTH'; // returns attribute like other Auth containers
$this->options['group'] = '';
$this->options['groupdn'] = '';
$this->options['groupscope'] = 'sub';
$this->options['groupattr'] = 'cn';
$this->options['groupfilter'] = '(objectClass=groupOfUniqueNames)';
$this->options['memberattr'] = 'uniqueMember';
$this->options['memberisdn'] = true;
$this->options['start_tls'] = false;
$this->options['debug'] = false;
$this->options['try_all'] = false; // Try all user ids returned not just the first one
}
// }}}
// {{{ _parseOptions()
/**
* Parse options passed to the container class
*
* @access private
* @param array
*/
function _parseOptions($array)
{
$array = $this->_setV12OptionsToV13($array);
foreach ($array as $key => $value) {
if (array_key_exists($key, $this->options)) {
if ($key == 'attributes') {
if (is_array($value)) {
$this->options[$key] = $value;
} else {
$this->options[$key] = explode(',', $value);
}
} else {
$this->options[$key] = $value;
}
}
}
}
// }}}
// {{{ _setV12OptionsToV13()
/**
* Adapt deprecated options from Auth 1.2 LDAP to Auth 1.3 LDAP
*
* @author Hugues Peeters
* @access private
* @param array
* @return array
*/
function _setV12OptionsToV13($array)
{
if (isset($array['useroc']))
$array['userfilter'] = "(objectClass=".$array['useroc'].")";
if (isset($array['groupoc']))
$array['groupfilter'] = "(objectClass=".$array['groupoc'].")";
if (isset($array['scope']))
$array['userscope'] = $array['scope'];
return $array;
}
// }}}
// {{{ _scope2function()
/**
* Get search function for scope
*
* @param string scope
* @return string ldap search function
*/
function _scope2function($scope)
{
switch($scope) {
case 'one':
$function = 'ldap_list';
break;
case 'base':
$function = 'ldap_read';
break;
default:
$function = 'ldap_search';
break;
}
return $function;
}
// }}}
// {{{ fetchData()
/**
* Fetch data from LDAP server
*
* Searches the LDAP server for the given username/password
* combination. Escapes all LDAP meta characters in username
* before performing the query.
*
* @param string Username
* @param string Password
* @return boolean
*/
function fetchData($username, $password)
{
$this->log('Auth_Container_LDAP::fetchData() called.', AUTH_LOG_DEBUG);
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
$err = $this->_getBaseDN();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
// UTF8 Encode username for LDAPv3
if (@ldap_get_option($this->conn_id, LDAP_OPT_PROTOCOL_VERSION, $ver) && $ver == 3) {
$this->log('UTF8 encoding username for LDAPv3', AUTH_LOG_DEBUG);
$username = utf8_encode($username);
}
// make search filter
$filter = sprintf('(&(%s=%s)%s)',
$this->options['userattr'],
$this->_quoteFilterString($username),
$this->options['userfilter']);
// make search base dn
$search_basedn = $this->options['userdn'];
if ($search_basedn != '' && substr($search_basedn, -1) != ',') {
$search_basedn .= ',';
}
$search_basedn .= $this->options['basedn'];
// attributes
$searchAttributes = $this->options['attributes'];
// make functions params array
$func_params = array($this->conn_id, $search_basedn, $filter, $searchAttributes);
// search function to use
$func_name = $this->_scope2function($this->options['userscope']);
$this->log("Searching with $func_name and filter $filter in $search_basedn", AUTH_LOG_DEBUG);
// search
if (($result_id = @call_user_func_array($func_name, $func_params)) === false) {
$this->log('User not found', AUTH_LOG_DEBUG);
} elseif (@ldap_count_entries($this->conn_id, $result_id) >= 1) { // did we get some possible results?
$this->log('User(s) found', AUTH_LOG_DEBUG);
$first = true;
$entry_id = null;
do {
// then get the user dn
if ($first) {
$entry_id = @ldap_first_entry($this->conn_id, $result_id);
$first = false;
} else {
$entry_id = @ldap_next_entry($this->conn_id, $entry_id);
if ($entry_id === false)
break;
}
$user_dn = @ldap_get_dn($this->conn_id, $entry_id);
// as the dn is not fetched as an attribute, we save it anyway
if (is_array($searchAttributes) && in_array('dn', $searchAttributes)) {
$this->log('Saving DN to AuthData', AUTH_LOG_DEBUG);
$this->_auth_obj->setAuthData('dn', $user_dn);
}
// fetch attributes
if ($attributes = @ldap_get_attributes($this->conn_id, $entry_id)) {
if (is_array($attributes) && isset($attributes['count']) &&
$attributes['count'] > 0) {
// ldap_get_attributes() returns a specific multi dimensional array
// format containing all the attributes and where each array starts
// with a 'count' element providing the number of attributes in the
// entry, or the number of values for attribute. For compatibility
// reasons, it remains the default format returned by LDAP container
// setAuthData().
// The code below optionally returns attributes in another format,
// more compliant with other Auth containers, where each attribute
// element are directly set in the 'authData' list. This option is
// enabled by setting 'attrformat' to
// 'AUTH' in the 'options' array.
// eg. $this->options['attrformat'] = 'AUTH'
if ( strtoupper($this->options['attrformat']) == 'AUTH' ) {
$this->log('Saving attributes to Auth data in AUTH format', AUTH_LOG_DEBUG);
unset ($attributes['count']);
foreach ($attributes as $attributeName => $attributeValue ) {
if (is_int($attributeName)) continue;
if (is_array($attributeValue) && isset($attributeValue['count'])) {
unset ($attributeValue['count']);
}
if (count($attributeValue)<=1) $attributeValue = $attributeValue[0];
$this->log('Storing additional field: '.$attributeName, AUTH_LOG_DEBUG);
$this->_auth_obj->setAuthData($attributeName, $attributeValue);
}
}
else
{
$this->log('Saving attributes to Auth data in LDAP format', AUTH_LOG_DEBUG);
$this->_auth_obj->setAuthData('attributes', $attributes);
}
}
}
@ldap_free_result($result_id);
// need to catch an empty password as openldap seems to return TRUE
// if anonymous binding is allowed
if ($password != "") {
$this->log("Bind as $user_dn", AUTH_LOG_DEBUG);
// try binding as this user with the supplied password
if (@ldap_bind($this->conn_id, $user_dn, $password)) {
$this->log('Bind successful', AUTH_LOG_DEBUG);
// check group if appropiate
if (strlen($this->options['group'])) {
// decide whether memberattr value is a dn or the username
$this->log('Checking group membership', AUTH_LOG_DEBUG);
$return = $this->checkGroup(($this->options['memberisdn']) ? $user_dn : $username);
$this->_disconnect();
return $return;
} else {
$this->log('Authenticated', AUTH_LOG_DEBUG);
$this->_disconnect();
return true; // user authenticated
} // checkGroup
} // bind
} // non-empty password
} while ($this->options['try_all'] == true); // interate through entries
} // get results
// default
$this->log('NOT authenticated!', AUTH_LOG_DEBUG);
$this->_disconnect();
return false;
}
// }}}
// {{{ checkGroup()
/**
* Validate group membership
*
* Searches the LDAP server for group membership of the
* supplied username. Quotes all LDAP filter meta characters in
* the user name before querying the LDAP server.
*
* @param string Distinguished Name of the authenticated User
* @return boolean
*/
function checkGroup($user)
{
$this->log('Auth_Container_LDAP::checkGroup() called.', AUTH_LOG_DEBUG);
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
// make filter
$filter = sprintf('(&(%s=%s)(%s=%s)%s)',
$this->options['groupattr'],
$this->options['group'],
$this->options['memberattr'],
$this->_quoteFilterString($user),
$this->options['groupfilter']);
// make search base dn
$search_basedn = $this->options['groupdn'];
if ($search_basedn != '' && substr($search_basedn, -1) != ',') {
$search_basedn .= ',';
}
$search_basedn .= $this->options['basedn'];
$func_params = array($this->conn_id, $search_basedn, $filter,
array($this->options['memberattr']));
$func_name = $this->_scope2function($this->options['groupscope']);
$this->log("Searching with $func_name and filter $filter in $search_basedn", AUTH_LOG_DEBUG);
// search
if (($result_id = @call_user_func_array($func_name, $func_params)) != false) {
if (@ldap_count_entries($this->conn_id, $result_id) == 1) {
@ldap_free_result($result_id);
$this->log('User is member of group', AUTH_LOG_DEBUG);
return true;
}
}
// default
$this->log('User is NOT member of group', AUTH_LOG_DEBUG);
return false;
}
// }}}
// {{{ _quoteFilterString()
/**
* Escapes LDAP filter special characters as defined in RFC 2254.
*
* @access private
* @param string Filter String
*/
function _quoteFilterString($filter_str)
{
$metas = array( '\\', '*', '(', ')', "\x00");
$quoted_metas = array('\\\\', '\*', '\(', '\)', "\\\x00");
return str_replace($metas, $quoted_metas, $filter_str);
}
// }}}
}
?>
Auth-1.6.4/Auth/Container/MDB.php 0000600 0001750 0001750 00000047557 11461311103 017146 0 ustar clockwerx clockwerx
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: MDB.php 256753 2008-04-04 07:57:02Z aashley $
* @link http://pear.php.net/package/Auth
* @since File available since Release 1.2.3
*/
/**
* Include Auth_Container base class
*/
require_once 'Auth/Container.php';
/**
* Include PEAR MDB package
*/
require_once 'MDB.php';
/**
* Storage driver for fetching login data from a database
*
* This storage driver can use all databases which are supported
* by the PEAR MDB abstraction layer to fetch login data.
*
* @category Authentication
* @package Auth
* @author Lorenzo Alberton
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 256753 $
* @link http://pear.php.net/package/Auth
* @since Class available since Release 1.2.3
*/
class Auth_Container_MDB extends Auth_Container
{
// {{{ properties
/**
* Additional options for the storage container
* @var array
*/
var $options = array();
/**
* MDB object
* @var object
*/
var $db = null;
var $dsn = '';
/**
* User that is currently selected from the DB.
* @var string
*/
var $activeUser = '';
// }}}
// {{{ Auth_Container_MDB() [constructor]
/**
* Constructor of the container class
*
* Initate connection to the database via PEAR::MDB
*
* @param string Connection data or MDB object
* @return object Returns an error object if something went wrong
*/
function Auth_Container_MDB($dsn)
{
$this->_setDefaults();
if (is_array($dsn)) {
$this->_parseOptions($dsn);
if (empty($this->options['dsn'])) {
PEAR::raiseError('No connection parameters specified!');
}
} else {
$this->options['dsn'] = $dsn;
}
}
// }}}
// {{{ _connect()
/**
* Connect to database by using the given DSN string
*
* @access private
* @param mixed DSN string | array | mdb object
* @return mixed Object on error, otherwise bool
*/
function _connect($dsn)
{
$this->log('Auth_Container_MDB::_connect() called.', AUTH_LOG_DEBUG);
if (is_string($dsn) || is_array($dsn)) {
$this->db =& MDB::connect($dsn, $this->options['db_options']);
} elseif (is_subclass_of($dsn, 'mdb_common')) {
$this->db = $dsn;
} elseif (is_object($dsn) && MDB::isError($dsn)) {
return PEAR::raiseError($dsn->getMessage(), $dsn->code);
} else {
return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__,
41,
PEAR_ERROR_RETURN,
null,
null
);
}
if (MDB::isError($this->db) || PEAR::isError($this->db)) {
return PEAR::raiseError($this->db->getMessage(), $this->db->code);
}
if ($this->options['auto_quote']) {
if (strpos('.', $this->options['table']) === false) {
$this->options['final_table'] = $this->db->quoteIdentifier($this->options['table']);
} else {
$t = explode('.', $this->options['table']);
for ($i = 0, $count = count($t); $i < $count; $i++)
$t[$i] = $this->db->quoteIdentifier($t[$i]);
$this->options['final_table'] = implode('.', $t);
}
$this->options['final_usernamecol'] = $this->db->quoteIdentifier($this->options['usernamecol']);
$this->options['final_passwordcol'] = $this->db->quoteIdentifier($this->options['passwordcol']);
} else {
$this->options['final_table'] = $this->options['table'];
$this->options['final_usernamecol'] = $this->options['usernamecol'];
$this->options['final_passwordcol'] = $this->options['passwordcol'];
}
return true;
}
// }}}
// {{{ _prepare()
/**
* Prepare database connection
*
* This function checks if we have already opened a connection to
* the database. If that's not the case, a new connection is opened.
*
* @access private
* @return mixed True or a MDB error object.
*/
function _prepare()
{
if (is_subclass_of($this->db, 'mdb_common')) {
return true;
}
return $this->_connect($this->options['dsn']);
}
// }}}
// {{{ query()
/**
* Prepare query to the database
*
* This function checks if we have already opened a connection to
* the database. If that's not the case, a new connection is opened.
* After that the query is passed to the database.
*
* @access public
* @param string Query string
* @return mixed a MDB_result object or MDB_OK on success, a MDB
* or PEAR error on failure
*/
function query($query)
{
$this->log('Auth_Container_MDB::query() called.', AUTH_LOG_DEBUG);
$err = $this->_prepare();
if ($err !== true) {
return $err;
}
return $this->db->query($query);
}
// }}}
// {{{ _setDefaults()
/**
* Set some default options
*
* @access private
* @return void
*/
function _setDefaults()
{
$this->options['table'] = 'auth';
$this->options['usernamecol'] = 'username';
$this->options['passwordcol'] = 'password';
$this->options['dsn'] = '';
$this->options['db_fields'] = '';
$this->options['cryptType'] = 'md5';
$this->options['db_options'] = array();
$this->options['db_where'] = '';
$this->options['auto_quote'] = true;
}
// }}}
// {{{ _parseOptions()
/**
* Parse options passed to the container class
*
* @access private
* @param array
*/
function _parseOptions($array)
{
foreach ($array as $key => $value) {
if (isset($this->options[$key])) {
$this->options[$key] = $value;
}
}
}
// }}}
// {{{ _quoteDBFields()
/**
* Quote the db_fields option to avoid the possibility of SQL injection.
*
* @access private
* @return string A properly quoted string that can be concatenated into a
* SELECT clause.
*/
function _quoteDBFields()
{
if (isset($this->options['db_fields'])) {
if (is_array($this->options['db_fields'])) {
if ($this->options['auto_quote']) {
$fields = array();
foreach ($this->options['db_fields'] as $field) {
$fields[] = $this->db->quoteIdentifier($field);
}
return implode(', ', $fields);
} else {
return implode(', ', $this->options['db_fields']);
}
} else {
if (strlen($this->options['db_fields']) > 0) {
if ($this->options['auto_quote']) {
return $this->db->quoteIdentifier($this->options['db_fields']);
} else {
return $this->options['db_fields'];
}
}
}
}
return '';
}
// }}}
// {{{ fetchData()
/**
* Get user information from database
*
* This function uses the given username to fetch
* the corresponding login data from the database
* table. If an account that matches the passed username
* and password is found, the function returns true.
* Otherwise it returns false.
*
* @param string Username
* @param string Password
* @param boolean If true password is secured using a md5 hash
* the frontend and auth are responsible for making sure the container supports
* challenge response password authentication
* @return mixed Error object or boolean
*/
function fetchData($username, $password, $isChallengeResponse=false)
{
$this->log('Auth_Container_MDB::fetchData() called.', AUTH_LOG_DEBUG);
// Prepare for a database query
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
//Check if db_fields contains a *, if so assume all columns are selected
if (is_string($this->options['db_fields'])
&& strstr($this->options['db_fields'], '*')) {
$sql_from = '*';
} else {
$sql_from = $this->options['final_usernamecol'].
", ".$this->options['final_passwordcol'];
if (strlen($fields = $this->_quoteDBFields()) > 0) {
$sql_from .= ', '.$fields;
}
}
$query = sprintf("SELECT %s FROM %s WHERE %s = %s",
$sql_from,
$this->options['final_table'],
$this->options['final_usernamecol'],
$this->db->getTextValue($username)
);
// check if there is an optional parameter db_where
if ($this->options['db_where'] != '') {
// there is one, so add it to the query
$query .= " AND ".$this->options['db_where'];
}
$this->log('Running SQL against MDB: '.$query, AUTH_LOG_DEBUG);
$res = $this->db->getRow($query, null, null, null, MDB_FETCHMODE_ASSOC);
if (MDB::isError($res) || PEAR::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->getCode());
}
if (!is_array($res)) {
$this->activeUser = '';
return false;
}
// Perform trimming here before the hashing
$password = trim($password, "\r\n");
$res[$this->options['passwordcol']] = trim($res[$this->options['passwordcol']], "\r\n");
// If using Challenge Response md5 the pass with the secret
if ($isChallengeResponse) {
$res[$this->options['passwordcol']] =
md5($res[$this->options['passwordcol']].$this->_auth_obj->session['loginchallenege']);
// UGLY cannot avoid without modifying verifyPassword
if ($this->options['cryptType'] == 'md5') {
$res[$this->options['passwordcol']] = md5($res[$this->options['passwordcol']]);
}
}
if ($this->verifyPassword($password,
$res[$this->options['passwordcol']],
$this->options['cryptType'])) {
// Store additional field values in the session
foreach ($res as $key => $value) {
if ($key == $this->options['passwordcol'] ||
$key == $this->options['usernamecol']) {
continue;
}
$this->log('Storing additional field: '.$key, AUTH_LOG_DEBUG);
// Use reference to the auth object if exists
// This is because the auth session variable can change so a static
// call to setAuthData does not make sense
$this->_auth_obj->setAuthData($key, $value);
}
return true;
}
$this->activeUser = $res[$this->options['usernamecol']];
return false;
}
// }}}
// {{{ listUsers()
/**
* Returns a list of users from the container
*
* @return mixed array|PEAR_Error
* @access public
*/
function listUsers()
{
$this->log('Auth_Container_MDB::listUsers() called.', AUTH_LOG_DEBUG);
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
$retVal = array();
//Check if db_fields contains a *, if so assume all columns are selected
if ( is_string($this->options['db_fields'])
&& strstr($this->options['db_fields'], '*')) {
$sql_from = '*';
} else {
$sql_from = $this->options['final_usernamecol']
.', '.$this->options['final_passwordcol'];
if (strlen($fields = $this->_quoteDBFields()) > 0) {
$sql_from .= ', '.$fields;
}
}
$query = sprintf('SELECT %s FROM %s',
$sql_from,
$this->options['final_table']
);
// check if there is an optional parameter db_where
if ($this->options['db_where'] != '') {
// there is one, so add it to the query
$query .= " WHERE ".$this->options['db_where'];
}
$this->log('Running SQL against MDB: '.$query, AUTH_LOG_DEBUG);
$res = $this->db->getAll($query, null, null, null, MDB_FETCHMODE_ASSOC);
if (MDB::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->getCode());
} else {
foreach ($res as $user) {
$user['username'] = $user[$this->options['usernamecol']];
$retVal[] = $user;
}
}
$this->log('Found '.count($retVal).' users.', AUTH_LOG_DEBUG);
return $retVal;
}
// }}}
// {{{ addUser()
/**
* Add user to the storage container
*
* @access public
* @param string Username
* @param string Password
* @param mixed Additional information that are stored in the DB
*
* @return mixed True on success, otherwise error object
*/
function addUser($username, $password, $additional = "")
{
$this->log('Auth_Container_MDB::addUser() called.', AUTH_LOG_DEBUG);
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
if (isset($this->options['cryptType']) && $this->options['cryptType'] == 'none') {
$cryptFunction = 'strval';
} elseif (isset($this->options['cryptType']) && function_exists($this->options['cryptType'])) {
$cryptFunction = $this->options['cryptType'];
} else {
$cryptFunction = 'md5';
}
$password = $cryptFunction($password);
$additional_key = '';
$additional_value = '';
if (is_array($additional)) {
foreach ($additional as $key => $value) {
if ($this->options['auto_quote']) {
$additional_key .= ', ' . $this->db->quoteIdentifier($key);
} else {
$additional_key .= ', ' . $key;
}
$additional_value .= ', ' . $this->db->getTextValue($value);
}
}
$query = sprintf("INSERT INTO %s (%s, %s%s) VALUES (%s, %s%s)",
$this->options['final_table'],
$this->options['final_usernamecol'],
$this->options['final_passwordcol'],
$additional_key,
$this->db->getTextValue($username),
$this->db->getTextValue($password),
$additional_value
);
$this->log('Running SQL against MDB: '.$query, AUTH_LOG_DEBUG);
$res = $this->query($query);
if (MDB::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->code);
}
return true;
}
// }}}
// {{{ removeUser()
/**
* Remove user from the storage container
*
* @access public
* @param string Username
*
* @return mixed True on success, otherwise error object
*/
function removeUser($username)
{
$this->log('Auth_Container_MDB::removeUser() called.', AUTH_LOG_DEBUG);
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
$query = sprintf("DELETE FROM %s WHERE %s = %s",
$this->options['final_table'],
$this->options['final_usernamecol'],
$this->db->getTextValue($username)
);
// check if there is an optional parameter db_where
if ($this->options['db_where'] != '') {
// there is one, so add it to the query
$query .= " AND ".$this->options['db_where'];
}
$this->log('Running SQL against MDB: '.$query, AUTH_LOG_DEBUG);
$res = $this->query($query);
if (MDB::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->code);
}
return true;
}
// }}}
// {{{ changePassword()
/**
* Change password for user in the storage container
*
* @param string Username
* @param string The new password (plain text)
*/
function changePassword($username, $password)
{
$this->log('Auth_Container_MDB::changePassword() called.', AUTH_LOG_DEBUG);
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
if (isset($this->options['cryptType']) && $this->options['cryptType'] == 'none') {
$cryptFunction = 'strval';
} elseif (isset($this->options['cryptType']) && function_exists($this->options['cryptType'])) {
$cryptFunction = $this->options['cryptType'];
} else {
$cryptFunction = 'md5';
}
$password = $cryptFunction($password);
$query = sprintf("UPDATE %s SET %s = %s WHERE %s = %s",
$this->options['final_table'],
$this->options['final_passwordcol'],
$this->db->getTextValue($password),
$this->options['final_usernamecol'],
$this->db->getTextValue($username)
);
// check if there is an optional parameter db_where
if ($this->options['db_where'] != '') {
// there is one, so add it to the query
$query .= " AND ".$this->options['db_where'];
}
$this->log('Running SQL against MDB: '.$query, AUTH_LOG_DEBUG);
$res = $this->query($query);
if (MDB::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->code);
}
return true;
}
// }}}
// {{{ supportsChallengeResponse()
/**
* Determine if this container supports
* password authentication with challenge response
*
* @return bool
* @access public
*/
function supportsChallengeResponse()
{
return in_array($this->options['cryptType'], array('md5', 'none', ''));
}
// }}}
// {{{ getCryptType()
/**
* Returns the selected crypt type for this container
*
* @return string Function used to crypt the password
*/
function getCryptType()
{
return $this->options['cryptType'];
}
// }}}
}
?>
Auth-1.6.4/Auth/Container/MDB2.php 0000600 0001750 0001750 00000050035 11461311103 017211 0 ustar clockwerx clockwerx
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: MDB2.php 256753 2008-04-04 07:57:02Z aashley $
* @link http://pear.php.net/package/Auth
* @since File available since Release 1.3.0
*/
/**
* Include Auth_Container base class
*/
require_once 'Auth/Container.php';
/**
* Include PEAR MDB2 package
*/
require_once 'MDB2.php';
/**
* Storage driver for fetching login data from a database
*
* This storage driver can use all databases which are supported
* by the PEAR MDB2 abstraction layer to fetch login data.
*
* @category Authentication
* @package Auth
* @author Lorenzo Alberton
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 256753 $
* @link http://pear.php.net/package/Auth
* @since Class available since Release 1.3.0
*/
class Auth_Container_MDB2 extends Auth_Container
{
// {{{ properties
/**
* Additional options for the storage container
* @var array
*/
var $options = array();
/**
* MDB object
* @var object
*/
var $db = null;
var $dsn = '';
/**
* User that is currently selected from the DB.
* @var string
*/
var $activeUser = '';
// }}}
// {{{ Auth_Container_MDB2() [constructor]
/**
* Constructor of the container class
*
* Initate connection to the database via PEAR::MDB2
*
* @param string Connection data or MDB2 object
* @return object Returns an error object if something went wrong
*/
function Auth_Container_MDB2($dsn)
{
$this->_setDefaults();
if (is_array($dsn)) {
$this->_parseOptions($dsn);
if (empty($this->options['dsn'])) {
PEAR::raiseError('No connection parameters specified!');
}
} else {
$this->options['dsn'] = $dsn;
}
}
// }}}
// {{{ _connect()
/**
* Connect to database by using the given DSN string
*
* @access private
* @param mixed DSN string | array | mdb object
* @return mixed Object on error, otherwise bool
*/
function _connect($dsn)
{
$this->log('Auth_Container_MDB2::_connect() called.', AUTH_LOG_DEBUG);
if (is_string($dsn) || is_array($dsn)) {
$this->db =& MDB2::connect($dsn, $this->options['db_options']);
} elseif (is_subclass_of($dsn, 'MDB2_Driver_Common')) {
$this->db = $dsn;
} elseif (is_object($dsn) && MDB2::isError($dsn)) {
return PEAR::raiseError($dsn->getMessage(), $dsn->code);
} else {
return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__,
41,
PEAR_ERROR_RETURN,
null,
null
);
}
if (MDB2::isError($this->db) || PEAR::isError($this->db)) {
return PEAR::raiseError($this->db->getMessage(), $this->db->code);
}
if ($this->options['auto_quote']) {
if (strpos('.', $this->options['table']) === false) {
$this->options['final_table'] = $this->db->quoteIdentifier($this->options['table'], true);
} else {
$t = explode('.', $this->options['table']);
for ($i = 0, $count = count($t); $i < $count; $i++)
$t[$i] = $this->db->quoteIdentifier($t[$i], true);
$this->options['final_table'] = implode('.', $t);
}
$this->options['final_usernamecol'] = $this->db->quoteIdentifier($this->options['usernamecol'], true);
$this->options['final_passwordcol'] = $this->db->quoteIdentifier($this->options['passwordcol'], true);
} else {
$this->options['final_table'] = $this->options['table'];
$this->options['final_usernamecol'] = $this->options['usernamecol'];
$this->options['final_passwordcol'] = $this->options['passwordcol'];
}
return true;
}
// }}}
// {{{ _prepare()
/**
* Prepare database connection
*
* This function checks if we have already opened a connection to
* the database. If that's not the case, a new connection is opened.
*
* @access private
* @return mixed True or a MDB error object.
*/
function _prepare()
{
if (is_subclass_of($this->db, 'MDB2_Driver_Common')) {
return true;
}
return $this->_connect($this->options['dsn']);
}
// }}}
// {{{ query()
/**
* Prepare query to the database
*
* This function checks if we have already opened a connection to
* the database. If that's not the case, a new connection is opened.
* After that the query is passed to the database.
*
* @access public
* @param string Query string
* @return mixed a MDB_result object or MDB_OK on success, a MDB
* or PEAR error on failure
*/
function query($query)
{
$this->log('Auth_Container_MDB2::query() called.', AUTH_LOG_DEBUG);
$err = $this->_prepare();
if ($err !== true) {
return $err;
}
return $this->db->exec($query);
}
// }}}
// {{{ _setDefaults()
/**
* Set some default options
*
* @access private
* @return void
*/
function _setDefaults()
{
$this->options['table'] = 'auth';
$this->options['usernamecol'] = 'username';
$this->options['passwordcol'] = 'password';
$this->options['dsn'] = '';
$this->options['db_fields'] = '';
$this->options['cryptType'] = 'md5';
$this->options['db_options'] = array();
$this->options['db_where'] = '';
$this->options['auto_quote'] = true;
}
// }}}
// {{{ _parseOptions()
/**
* Parse options passed to the container class
*
* @access private
* @param array
*/
function _parseOptions($array)
{
foreach ($array as $key => $value) {
if (isset($this->options[$key])) {
$this->options[$key] = $value;
}
}
}
// }}}
// {{{ _quoteDBFields()
/**
* Quote the db_fields option to avoid the possibility of SQL injection.
*
* @access private
* @return string A properly quoted string that can be concatenated into a
* SELECT clause.
*/
function _quoteDBFields()
{
if (isset($this->options['db_fields'])) {
if (is_array($this->options['db_fields'])) {
if ($this->options['auto_quote']) {
$fields = array();
foreach ($this->options['db_fields'] as $field) {
$fields[] = $this->db->quoteIdentifier($field, true);
}
return implode(', ', $fields);
} else {
return implode(', ', $this->options['db_fields']);
}
} else {
if (strlen($this->options['db_fields']) > 0) {
if ($this->options['auto_quote']) {
return $this->db->quoteIdentifier($this->options['db_fields'], true);
} else {
return $this->options['db_fields'];
}
}
}
}
return '';
}
// }}}
// {{{ fetchData()
/**
* Get user information from database
*
* This function uses the given username to fetch
* the corresponding login data from the database
* table. If an account that matches the passed username
* and password is found, the function returns true.
* Otherwise it returns false.
*
* @param string Username
* @param string Password
* @param boolean If true password is secured using a md5 hash
* the frontend and auth are responsible for making sure the container supports
* challenge response password authentication
* @return mixed Error object or boolean
*/
function fetchData($username, $password, $isChallengeResponse=false)
{
$this->log('Auth_Container_MDB2::fetchData() called.', AUTH_LOG_DEBUG);
// Prepare for a database query
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
//Check if db_fields contains a *, if so assume all columns are selected
if (is_string($this->options['db_fields'])
&& strstr($this->options['db_fields'], '*')) {
$sql_from = '*';
} else {
$sql_from = $this->options['final_usernamecol'].
", ".$this->options['final_passwordcol'];
if (strlen($fields = $this->_quoteDBFields()) > 0) {
$sql_from .= ', '.$fields;
}
}
$query = sprintf("SELECT %s FROM %s WHERE %s = %s",
$sql_from,
$this->options['final_table'],
$this->options['final_usernamecol'],
$this->db->quote($username, 'text')
);
// check if there is an optional parameter db_where
if ($this->options['db_where'] != '') {
// there is one, so add it to the query
$query .= " AND ".$this->options['db_where'];
}
$this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG);
$res = $this->db->queryRow($query, null, MDB2_FETCHMODE_ASSOC);
if (MDB2::isError($res) || PEAR::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->getCode());
}
if (!is_array($res)) {
$this->activeUser = '';
return false;
}
// Perform trimming here before the hashing
$password = trim($password, "\r\n");
$res[$this->options['passwordcol']] = trim($res[$this->options['passwordcol']], "\r\n");
// If using Challenge Response md5 the pass with the secret
if ($isChallengeResponse) {
$res[$this->options['passwordcol']] =
md5($res[$this->options['passwordcol']].$this->_auth_obj->session['loginchallenege']);
// UGLY cannot avoid without modifying verifyPassword
if ($this->options['cryptType'] == 'md5') {
$res[$this->options['passwordcol']] = md5($res[$this->options['passwordcol']]);
}
}
if ($this->verifyPassword($password,
$res[$this->options['passwordcol']],
$this->options['cryptType'])) {
// Store additional field values in the session
foreach ($res as $key => $value) {
if ($key == $this->options['passwordcol'] ||
$key == $this->options['usernamecol']) {
continue;
}
$this->log('Storing additional field: '.$key, AUTH_LOG_DEBUG);
// Use reference to the auth object if exists
// This is because the auth session variable can change so a static call to setAuthData does not make sense
$this->_auth_obj->setAuthData($key, $value);
}
return true;
}
$this->activeUser = $res[$this->options['usernamecol']];
return false;
}
// }}}
// {{{ listUsers()
/**
* Returns a list of users from the container
*
* @return mixed array|PEAR_Error
* @access public
*/
function listUsers()
{
$this->log('Auth_Container_MDB2::listUsers() called.', AUTH_LOG_DEBUG);
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
$retVal = array();
//Check if db_fields contains a *, if so assume all columns are selected
if ( is_string($this->options['db_fields'])
&& strstr($this->options['db_fields'], '*')) {
$sql_from = '*';
} else {
$sql_from = $this->options['final_usernamecol'].
", ".$this->options['final_passwordcol'];
if (strlen($fields = $this->_quoteDBFields()) > 0) {
$sql_from .= ', '.$fields;
}
}
$query = sprintf('SELECT %s FROM %s',
$sql_from,
$this->options['final_table']
);
// check if there is an optional parameter db_where
if ($this->options['db_where'] != '') {
// there is one, so add it to the query
$query .= " WHERE ".$this->options['db_where'];
}
$this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG);
$res = $this->db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
if (MDB2::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->getCode());
} else {
foreach ($res as $user) {
$user['username'] = $user[$this->options['usernamecol']];
$retVal[] = $user;
}
}
$this->log('Found '.count($retVal).' users.', AUTH_LOG_DEBUG);
return $retVal;
}
// }}}
// {{{ addUser()
/**
* Add user to the storage container
*
* @access public
* @param string Username
* @param string Password
* @param mixed Additional information that are stored in the DB
*
* @return mixed True on success, otherwise error object
*/
function addUser($username, $password, $additional = "")
{
$this->log('Auth_Container_MDB2::addUser() called.', AUTH_LOG_DEBUG);
// Prepare for a database query
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
if (isset($this->options['cryptType']) && $this->options['cryptType'] == 'none') {
$cryptFunction = 'strval';
} elseif (isset($this->options['cryptType']) && function_exists($this->options['cryptType'])) {
$cryptFunction = $this->options['cryptType'];
} else {
$cryptFunction = 'md5';
}
$password = $cryptFunction($password);
$additional_key = '';
$additional_value = '';
if (is_array($additional)) {
foreach ($additional as $key => $value) {
if ($this->options['auto_quote']) {
$additional_key .= ', ' . $this->db->quoteIdentifier($key, true);
} else {
$additional_key .= ', ' . $key;
}
$additional_value .= ', ' . $this->db->quote($value, 'text');
}
}
$query = sprintf("INSERT INTO %s (%s, %s%s) VALUES (%s, %s%s)",
$this->options['final_table'],
$this->options['final_usernamecol'],
$this->options['final_passwordcol'],
$additional_key,
$this->db->quote($username, 'text'),
$this->db->quote($password, 'text'),
$additional_value
);
$this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG);
$res = $this->query($query);
if (MDB2::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->code);
}
return true;
}
// }}}
// {{{ removeUser()
/**
* Remove user from the storage container
*
* @access public
* @param string Username
*
* @return mixed True on success, otherwise error object
*/
function removeUser($username)
{
$this->log('Auth_Container_MDB2::removeUser() called.', AUTH_LOG_DEBUG);
// Prepare for a database query
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
$query = sprintf("DELETE FROM %s WHERE %s = %s",
$this->options['final_table'],
$this->options['final_usernamecol'],
$this->db->quote($username, 'text')
);
// check if there is an optional parameter db_where
if ($this->options['db_where'] != '') {
// there is one, so add it to the query
$query .= " AND ".$this->options['db_where'];
}
$this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG);
$res = $this->query($query);
if (MDB2::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->code);
}
return true;
}
// }}}
// {{{ changePassword()
/**
* Change password for user in the storage container
*
* @param string Username
* @param string The new password (plain text)
*/
function changePassword($username, $password)
{
$this->log('Auth_Container_MDB2::changePassword() called.', AUTH_LOG_DEBUG);
// Prepare for a database query
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
if (isset($this->options['cryptType']) && $this->options['cryptType'] == 'none') {
$cryptFunction = 'strval';
} elseif (isset($this->options['cryptType']) && function_exists($this->options['cryptType'])) {
$cryptFunction = $this->options['cryptType'];
} else {
$cryptFunction = 'md5';
}
$password = $cryptFunction($password);
$query = sprintf("UPDATE %s SET %s = %s WHERE %s = %s",
$this->options['final_table'],
$this->options['final_passwordcol'],
$this->db->quote($password, 'text'),
$this->options['final_usernamecol'],
$this->db->quote($username, 'text')
);
// check if there is an optional parameter db_where
if ($this->options['db_where'] != '') {
// there is one, so add it to the query
$query .= " AND ".$this->options['db_where'];
}
$this->log('Running SQL against MDB2: '.$query, AUTH_LOG_DEBUG);
$res = $this->query($query);
if (MDB2::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->code);
}
return true;
}
// }}}
// {{{ supportsChallengeResponse()
/**
* Determine if this container supports
* password authentication with challenge response
*
* @return bool
* @access public
*/
function supportsChallengeResponse()
{
return in_array($this->options['cryptType'], array('md5', 'none', ''));
}
// }}}
// {{{ getCryptType()
/**
* Returns the selected crypt type for this container
*
* @return string Function used to crypt the password
*/
function getCryptType()
{
return $this->options['cryptType'];
}
// }}}
}
?>
Auth-1.6.4/Auth/Container/Multiple.php 0000600 0001750 0001750 00000012157 11461311103 020323 0 ustar clockwerx clockwerx
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: Multiple.php 289653 2009-10-15 04:50:43Z aashley $
* @since File available since Release 1.5.0
*/
/**
* Include Auth_Container base class
*/
require_once "Auth/Container.php";
/**
* Include PEAR package for error handling
*/
require_once "PEAR.php";
/**
* Storage driver for using multiple storage drivers in a fall through fashion
*
* This storage driver provides a mechanism for working through multiple
* storage drivers until either one allows successful login or the list is
* exhausted.
*
* This container takes an array of options of the following form:
*
* array(
* array(
* 'type' => ,
* 'options' => ,
* ),
* );
*
* Full example:
*
* $options = array(
* array(
* 'type' => 'DB',
* 'options' => array(
* 'dsn' => "mysql://user:password@localhost/database",
* ),
* ),
* array(
* 'type' => 'Array',
* 'options' => array(
* 'cryptType' => 'md5',
* 'users' => array(
* 'admin' => md5('password'),
* ),
* ),
* ),
* );
*
* $auth = new Auth('Multiple', $options);
*
* @category Authentication
* @package Auth
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 289653 $
* @since File available since Release 1.5.0
*/
class Auth_Container_Multiple extends Auth_Container {
// {{{ properties
/**
* The options for each container
*
* @var array $options
*/
var $options = array();
/**
* The instanciated containers
*
* @var array $containers
*/
var $containers = array();
// }}}
// {{{ Auth_Container_Multiple()
/**
* Constructor for Array Container
*
* @param array $data Options for the container
* @return void
*/
function Auth_Container_Multiple($options)
{
if (!is_array($options)) {
PEAR::raiseError('The options for Auth_Container_Multiple must be an array');
}
if (count($options) < 1) {
PEAR::raiseError('You must define at least one sub container to use in Auth_Container_Multiple');
}
foreach ($options as $option) {
if (!isset($option['type'])) {
PEAR::raiseError('No type defined for sub container');
}
}
$this->options = $options;
}
// }}}
// {{{ fetchData()
/**
* Get user information from array
*
* This function uses the given username to fetch the corresponding
* login data from the array. If an account that matches the passed
* username and password is found, the function returns true.
* Otherwise it returns false.
*
* @param string Username
* @param string Password
* @return boolean|PEAR_Error Error object or boolean
*/
function fetchData($user, $pass)
{
$this->log('Auth_Container_Multiple::fetchData() called.', AUTH_LOG_DEBUG);
foreach ($this->options as $key => $options) {
$this->log('Using Container '.$key.' of type '.$options['type'].'.', AUTH_LOG_DEBUG);
if (isset($this->containers[$key]) && is_a($this->containers[$key], 'Auth_Container')) {
$container = &$this->containers[$key];
} else {
$this->containers[$key] = &$this->_auth_obj->_factory($options['type'], $options['options']);
$this->containers[$key]->_auth_obj = &$this->_auth_obj;
$container = &$this->containers[$key];
}
$result = $container->fetchData($user, $pass);
if (PEAR::isError($result)) {
$this->log('Container '.$key.': '.$result->getMessage(), AUTH_LOG_DEBUG);
return $result;
} elseif ($result == true) {
$this->log('Container '.$key.': Authentication successful.', AUTH_LOG_DEBUG);
return true;
} else {
$this->log('Container '.$key.': Authentication failed.', AUTH_LOG_DEBUG);
}
}
$this->log('Auth_Container_Multiple: All containers rejected user credentials.', AUTH_LOG_DEBUG);
return false;
}
// }}}
}
?>
Auth-1.6.4/Auth/Container/NetVPOPMaild.php 0000600 0001750 0001750 00000007553 11461311103 020736 0 ustar clockwerx clockwerx
* @author Stefan Ekman
* @author Martin Jansen
* @author Mika Tuupola
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @link http://pear.php.net/package/Auth
* @since File available since Release 1.2.0
*/
/**
* Include Auth_Container base class
*/
require_once 'Auth/Container.php';
/**
* Include PEAR package for error handling
*/
require_once 'PEAR.php';
/**
* Include PEAR Net_Vpopmaild package
*/
require_once 'Net/Vpopmaild.php';
/**
* Storage driver for Authentication on a Vpopmaild server.
*
* @category Authentication
* @package Auth
* @author Martin Jansen
* @author Mika Tuupola
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: 1.5.4 File: $Revision: 256741 $
* @link http://pear.php.net/package/Auth
* @since Class available since Release 1.6.0
*/
class Auth_Container_Vpopmaild extends Auth_Container
{
/**
* Vpopmaild Server
* @var string
*/
var $server = 'localhost';
/**
* Vpopmaild Server port
* @var string
*/
var $port = 89;
/**
* Constructor of the container class
*
* @param $server string server or server:port combination
* @return object Returns an error object if something went wrong
*/
function Auth_Container_Vpopmaild($server=null)
{
if (isset($server) && !is_null($server)) {
if (is_array($server)) {
if (isset($server['host'])) {
$this->server = $server['host'];
}
if (isset($server['port'])) {
$this->port = $server['port'];
}
} else {
if (strstr($server, ':')) {
$serverparts = explode(':', trim($server));
$this->server = $serverparts[0];
$this->port = $serverparts[1];
} else {
$this->server = $server;
}
}
}
}
/**
* fetchData()
*
* Try to login to the Vpopmaild server
*
* @param string username
* @param string password
*
* @return boolean
*/
function fetchData($username, $password)
{
$this->log('Auth_Container_Vpopmaild::fetchData() called.', AUTH_LOG_DEBUG);
$vpopmaild =& new Net_Vpopmaild();
// Connect
try {
$res = $vpopmaild->connect($this->server, $this->port, $this->method);
} catch (Net_Vpopmaild_FatalException $e) {
$this->log('Connection to Vpopmaild server failed.', AUTH_LOG_DEBUG);
return PEAR::raiseError($e->getMessage(), $e->getCode());
}
// Authenticate
try {
$result = $vpopmaild->clogin($username, $password);
$vpopmaild->quit();
} catch (Net_Vpopmaild_Exception $e) {
return PEAR::raiseError($e->getMessage(), $e->getCode());
}
return $result;
}
}
?>
Auth-1.6.4/Auth/Container/PEAR.php 0000600 0001750 0001750 00000011535 11461311103 017256 0 ustar clockwerx clockwerx
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: PEAR.php 289652 2009-10-15 04:42:18Z aashley $
* @link http://pear.php.net/package/Auth
* @since File available since Release 1.3.0
*/
/**
* Include PEAR HTTP_Client.
*/
require_once 'HTTP/Client.php';
/**
* Include Auth_Container base class
*/
require_once 'Auth/Container.php';
/**
* Storage driver for authenticating against PEAR website
*
* This driver provides a method for authenticating against the pear.php.net
* authentication system.
*
* Supports two options:
* - "url": The base URL with schema to authenticate against
* - "karma": An array of karma levels which the user needs one of.
* When empty, no karma level is required.
*
* @category Authentication
* @package Auth
* @author Yavor Shahpasov
* @author Adam Ashley
* @author Adam Harvey
* @copyright 2001-2007 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 289652 $
* @link http://pear.php.net/package/Auth
* @since Class available since Release 1.3.0
*/
class Auth_Container_Pear extends Auth_Container
{
// {{{ properties
/**
* URL to connect to, with schema
*
* @var string
*/
var $url = 'https://pear.php.net/rest-login.php/';
/**
* Array of karma levels the user can have.
* A user needs only one of the levels to succeed login.
* No levels mean that only username and password need to match
*
* @var array
*/
var $karma = array();
// }}}
// {{{ Auth_Container_Pear() [constructor]
/**
* Constructor
*
* Accepts options "url" and "karma", see class docs.
*
* @param array $data Array of options
*
* @return void
*/
function Auth_Container_Pear($data = null)
{
if (!is_array($data)) {
PEAR::raiseError('The options for Auth_Container_Pear must be an array');
}
if (isset($data['karma'])) {
if (is_array($data['karma'])) {
$this->karma = $data['karma'];
} else {
$this->karma = array($data['karma']);
}
}
if (isset($data['url'])) {
$this->url = $data['url'];
}
}
// }}}
// {{{ fetchData()
/**
* Get user information from pear.php.net
*
* This function uses the given username and password to authenticate
* against the pear.php.net website
*
* @param string Username
* @param string Password
* @return mixed Error object or boolean
*/
function fetchData($username, $password)
{
$this->log('Auth_Container_PEAR::fetchData() called.', AUTH_LOG_DEBUG);
$client = new HTTP_Client;
$this->log('Auth_Container_PEAR::fetchData() getting salt.', AUTH_LOG_DEBUG);
$code = $client->get($this->url . '/getsalt');
if ($code instanceof PEAR_Error) {
return $code;
}
if ($code != 200) {
return PEAR::raiseError('Bad response to salt request.', $code);
}
$resp = $client->currentResponse();
$salt = $resp['body'];
$this->log('Auth_Container_PEAR::fetchData() calling validate.', AUTH_LOG_DEBUG);
$postOptions = array(
'username' => $username,
'password' => md5($salt . md5($password))
);
if (is_array($this->karma) && count($this->karma) > 0) {
$postOptions['karma'] = implode(',', $this->karma);
}
$code = $client->post($this->url . '/validate', $postOptions);
if ($code instanceof PEAR_Error) {
return $code;
}
if ($code != 200) {
return PEAR::raiseError('Bad response to validate request.', $code);
}
$resp = $client->currentResponse();
list($code, $message) = explode(' ', $resp['body'], 2);
if ($code != 8) {
return PEAR::raiseError($message, $code);
}
return true;
}
// }}}
}
?>
Auth-1.6.4/Auth/Container/POP3.php 0000600 0001750 0001750 00000010261 11461311103 017243 0 ustar clockwerx clockwerx
* @author Martin Jansen
* @author Mika Tuupola
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: POP3.php 237449 2007-06-12 03:11:27Z aashley $
* @link http://pear.php.net/package/Auth
* @since File available since Release 1.2.0
*/
/**
* Include Auth_Container base class
*/
require_once 'Auth/Container.php';
/**
* Include PEAR package for error handling
*/
require_once 'PEAR.php';
/**
* Include PEAR Net_POP3 package
*/
require_once 'Net/POP3.php';
/**
* Storage driver for Authentication on a POP3 server.
*
* @category Authentication
* @package Auth
* @author Martin Jansen
* @author Mika Tuupola
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 237449 $
* @link http://pear.php.net/package/Auth
* @since Class available since Release 1.2.0
*/
class Auth_Container_POP3 extends Auth_Container
{
// {{{ properties
/**
* POP3 Server
* @var string
*/
var $server='localhost';
/**
* POP3 Server port
* @var string
*/
var $port='110';
/**
* POP3 Authentication method
*
* Prefered POP3 authentication method. Acceptable values:
* Boolean TRUE - Use Net_POP3's autodetection
* String 'DIGEST-MD5','CRAM-MD5','LOGIN','PLAIN','APOP','USER'
* - Attempt this authentication style first
* then fallback to autodetection.
* @var mixed
*/
var $method=true;
// }}}
// {{{ Auth_Container_POP3() [constructor]
/**
* Constructor of the container class
*
* @param $server string server or server:port combination
* @return object Returns an error object if something went wrong
*/
function Auth_Container_POP3($server=null)
{
if (isset($server) && !is_null($server)) {
if (is_array($server)) {
if (isset($server['host'])) {
$this->server = $server['host'];
}
if (isset($server['port'])) {
$this->port = $server['port'];
}
if (isset($server['method'])) {
$this->method = $server['method'];
}
} else {
if (strstr($server, ':')) {
$serverparts = explode(':', trim($server));
$this->server = $serverparts[0];
$this->port = $serverparts[1];
} else {
$this->server = $server;
}
}
}
}
// }}}
// {{{ fetchData()
/**
* Try to login to the POP3 server
*
* @param string Username
* @param string Password
* @return boolean
*/
function fetchData($username, $password)
{
$this->log('Auth_Container_POP3::fetchData() called.', AUTH_LOG_DEBUG);
$pop3 =& new Net_POP3();
$res = $pop3->connect($this->server, $this->port, $this->method);
if (!$res) {
$this->log('Connection to POP3 server failed.', AUTH_LOG_DEBUG);
return $res;
}
$result = $pop3->login($username, $password);
$pop3->disconnect();
return $result;
}
// }}}
}
?>
Auth-1.6.4/Auth/Container/RADIUS.php 0000600 0001750 0001750 00000013457 11461311103 017523 0 ustar clockwerx clockwerx
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: RADIUS.php 237449 2007-06-12 03:11:27Z aashley $
* @link http://pear.php.net/package/Auth
* @since File available since Release 1.2.0
*/
/**
* Include Auth_Container base class
*/
require_once "Auth/Container.php";
/**
* Include PEAR Auth_RADIUS package
*/
require_once "Auth/RADIUS.php";
/**
* Storage driver for authenticating users against RADIUS servers.
*
* @category Authentication
* @package Auth
* @author Michael Bretterklieber
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 237449 $
* @link http://pear.php.net/package/Auth
* @since Class available since Release 1.2.0
*/
class Auth_Container_RADIUS extends Auth_Container
{
// {{{ properties
/**
* Contains a RADIUS object
* @var object
*/
var $radius;
/**
* Contains the authentication type
* @var string
*/
var $authtype;
// }}}
// {{{ Auth_Container_RADIUS() [constructor]
/**
* Constructor of the container class.
*
* $options can have these keys:
* 'servers' an array containing an array: servername, port,
* sharedsecret, timeout, maxtries
* 'configfile' The filename of the configuration file
* 'authtype' The type of authentication, one of: PAP, CHAP_MD5,
* MSCHAPv1, MSCHAPv2, default is PAP
*
* @param $options associative array
* @return object Returns an error object if something went wrong
*/
function Auth_Container_RADIUS($options)
{
$this->authtype = 'PAP';
if (isset($options['authtype'])) {
$this->authtype = $options['authtype'];
}
$classname = 'Auth_RADIUS_' . $this->authtype;
if (!class_exists($classname)) {
PEAR::raiseError("Unknown Authtype, please use one of: "
."PAP, CHAP_MD5, MSCHAPv1, MSCHAPv2!", 41, PEAR_ERROR_DIE);
}
$this->radius = new $classname;
if (isset($options['configfile'])) {
$this->radius->setConfigfile($options['configfile']);
}
$servers = $options['servers'];
if (is_array($servers)) {
foreach ($servers as $server) {
$servername = $server[0];
$port = isset($server[1]) ? $server[1] : 0;
$sharedsecret = isset($server[2]) ? $server[2] : 'testing123';
$timeout = isset($server[3]) ? $server[3] : 3;
$maxtries = isset($server[4]) ? $server[4] : 3;
$this->radius->addServer($servername, $port, $sharedsecret, $timeout, $maxtries);
}
}
if (!$this->radius->start()) {
PEAR::raiseError($this->radius->getError(), 41, PEAR_ERROR_DIE);
}
}
// }}}
// {{{ fetchData()
/**
* Authenticate
*
* @param string Username
* @param string Password
* @return bool true on success, false on reject
*/
function fetchData($username, $password, $challenge = null)
{
$this->log('Auth_Container_RADIUS::fetchData() called.', AUTH_LOG_DEBUG);
switch($this->authtype) {
case 'CHAP_MD5':
case 'MSCHAPv1':
if (isset($challenge)) {
$this->radius->challenge = $challenge;
$this->radius->chapid = 1;
$this->radius->response = pack('H*', $password);
} else {
require_once 'Crypt/CHAP.php';
$classname = 'Crypt_' . $this->authtype;
$crpt = new $classname;
$crpt->password = $password;
$this->radius->challenge = $crpt->challenge;
$this->radius->chapid = $crpt->chapid;
$this->radius->response = $crpt->challengeResponse();
}
break;
case 'MSCHAPv2':
require_once 'Crypt/CHAP.php';
$crpt = new Crypt_MSCHAPv2;
$crpt->username = $username;
$crpt->password = $password;
$this->radius->challenge = $crpt->authChallenge;
$this->radius->peerChallenge = $crpt->peerChallenge;
$this->radius->chapid = $crpt->chapid;
$this->radius->response = $crpt->challengeResponse();
break;
default:
$this->radius->password = $password;
break;
}
$this->radius->username = $username;
$this->radius->putAuthAttributes();
$result = $this->radius->send();
if (PEAR::isError($result)) {
return false;
}
$this->radius->getAttributes();
// just for debugging
// $this->radius->dumpAttributes();
return $result;
}
// }}}
}
?>
Auth-1.6.4/Auth/Container/SAP.php 0000600 0001750 0001750 00000012362 11461311103 017151 0 ustar clockwerx clockwerx
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: SAP.php 302205 2010-08-14 14:08:08Z clockwerx $
* @link http://pear.php.net/package/Auth
* @since File available since Release 1.4.0
*/
/**
* Include Auth_Container base class
*/
require_once 'Auth/Container.php';
/**
* Include PEAR for error handling
*/
require_once 'PEAR.php';
/**
* Performs authentication against a SAP system using the SAPRFC PHP extension.
*
* When the option GETSSO2 is TRUE (default)
* the Single Sign-On (SSO) ticket is retrieved
* and stored as an Auth attribute called 'sap'
* in order to be reused for consecutive connections.
*
* @category Authentication
* @package Auth
* @author Stoyan Stefanov
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 302205 $
* @since Class available since Release 1.4.0
*/
class Auth_Container_SAP extends Auth_Container {
// {{{ properties
/**
* @var array Default options
*/
var $options = array(
'CLIENT' => '000',
'LANG' => 'EN',
'GETSSO2' => true,
);
// }}}
// {{{ Auth_Container_SAP()
/**
* Class constructor. Checks that required options
* are present and that the SAPRFC extension is loaded
*
* Options that can be passed and their defaults:
*
'
.'AUTH_LOG_INFO level messages: ';
foreach ($infoObserver->messages as $event) {
print $event['priority'].': '.$event['message'].' ';
}
print ' '
.'AUTH_LOG_DEBUG level messages: ';
foreach ($debugObserver->messages as $event) {
print $event['priority'].': '.$event['message'].' ';
}
print ' ';
?>
Auth-1.6.4/tests/AllTests.php 0000600 0001750 0001750 00000002224 11461311103 016574 0 ustar clockwerx clockwerx addTestSuite('DBContainer');
$suite->addTestSuite('MDBContainer');
//$suite->addTestSuite('MBD2Container');
$suite->addTestSuite('DBLiteContainer');
$suite->addTestSuite('POP3Container');
$suite->addTestSuite('POP3aContainer');
$suite->addTestSuite('FileContainer');
$suite->addTestSuite('IMAPContainer');
return $suite;
}
}
// exec test suite
if (PHPUnit_MAIN_METHOD == 'Auth_AllTests::main') {
Auth_AllTests::main();
}
?>
Auth-1.6.4/tests/auth_container_db_options.php 0000600 0001750 0001750 00000001107 11461311103 022263 0 ustar clockwerx clockwerx options['table'] = "auth";
$this->options['usernamecol'] = "username";
$this->options['passwordcol'] = "password";
$this->options['dsn'] = "";
$this->options['db_fields'] = "";
$this->options['cryptType'] = "md5";
*/
$options = array(
'dsn'=>'mysql://root:@localhost/authtest',
'table'=>'temp',
'usernamecol'=>'username',
'passwordcol'=>'password',
'cryptType'=>'md5',
'db_fields'=>'*'
);
$extra_options['username'] = 'test_user';
$extra_options['passwd'] = 'test_user';
?>
Auth-1.6.4/tests/auth_container_file_options.php 0000600 0001750 0001750 00000000162 11461311103 022615 0 ustar clockwerx clockwerx
Auth-1.6.4/tests/auth_container_imap_options.php 0000600 0001750 0001750 00000000240 11461311103 022621 0 ustar clockwerx clockwerx 'example.com',
'port'=>'110'
);
$extra_options['username'] = 'test_user';
$extra_options['passwd'] = 'test_user';
?>
Auth-1.6.4/tests/auth_container_mdb2_options.php 0000600 0001750 0001750 00000001052 11461311103 022521 0 ustar clockwerx clockwerx 'mysql://root:@localhost/authtest',
'table' => 'temp',
'usernamecol' => 'username',
'passwordcol' => 'password',
'db_fields' => '*',
'cryptType' => 'md5'
);
$extra_options['username'] = 'test_user';
$extra_options['passwd'] = 'test_user';
?>
Auth-1.6.4/tests/auth_container_mdb_options.php 0000600 0001750 0001750 00000001052 11461311104 022440 0 ustar clockwerx clockwerx 'mysql://root:@localhost/authtest',
'table' => 'temp',
'usernamecol' => 'username',
'passwordcol' => 'password',
'db_fields' => '*',
'cryptType' => 'md5'
);
$extra_options['username'] = 'test_user';
$extra_options['passwd'] = 'test_user';
?>
Auth-1.6.4/tests/auth_container_pop3a_options.php 0000600 0001750 0001750 00000000201 11461311104 022713 0 ustar clockwerx clockwerx
Auth-1.6.4/tests/auth_container_pop3_options.php 0000600 0001750 0001750 00000000245 11461311104 022562 0 ustar clockwerx clockwerx 'mail.example.com',
'port'=>'110'
);
$extra_options['username'] = 'test_user';
$extra_options['passwd'] = 'test_user';
?>
Auth-1.6.4/tests/bug8735.passwd 0000600 0001750 0001750 00000000023 11461311104 016653 0 ustar clockwerx clockwerx test:fcfKBtvEwG4g.
Auth-1.6.4/tests/bug8735.phpt 0000600 0001750 0001750 00000001563 11461311104 016337 0 ustar clockwerx clockwerx --TEST--
Regression test for bug #8735
--FILE--
$datasrc,
'type' => 'AuthBasic'),
'displayLogin');
if (PEAR::isError($a)) {
print $a->getMessage();
exit;
}
$error = $a->removeUser('username');
if (PEAR::isError($error)) {
print $error->getMessage();
exit;
}
readfile($datasrc);
print "-- cut --\n";
$error = $a->addUser('username', 'password');
if (PEAR::isError($error) || $error === false) {
print "Error happened when adding.\n";
print $error->getMessage();
exit;
}
readfile($datasrc);
$a->removeUser('username');
?>
--EXPECT--
test:fcfKBtvEwG4g.
-- cut --
test:fcfKBtvEwG4g.
username:{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
Auth-1.6.4/tests/DBContainer.php 0000600 0001750 0001750 00000001353 11461311104 017174 0 ustar clockwerx clockwerx _prepare();
}
if (!DB::isConnection($container->db)) {
$this->markTestSkipped("DB is not a connection object, check dsn");
}
return($container);
}
function &getExtraOptions() {
include 'auth_container_db_options.php';
return($extra_options);
}
}
?>
Auth-1.6.4/tests/DBLiteContainer.php 0000600 0001750 0001750 00000001467 11461311104 020020 0 ustar clockwerx clockwerx skip_tests}\n";
if(!isset($container)){
include 'auth_container_db_options.php';
$container = new Auth_Container_DBLite($options);
// Catch if DB connection cannot be made
$res = $container->_prepare();
}
if(!DB::isConnection($container->db)){
$this->markTestSkipped("DB is not a connection object, check dsn");
}
return($container);
}
function &getExtraOptions() {
include 'auth_container_db_options.php';
return($extra_options);
}
}
?>
Auth-1.6.4/tests/FileContainer.php 0000600 0001750 0001750 00000001006 11461311104 017561 0 ustar clockwerx clockwerx
Auth-1.6.4/tests/IMAPContainer.php 0000600 0001750 0001750 00000001270 11461311104 017433 0 ustar clockwerx clockwerx markTestSkipped("This test needs the IMAP extension");
}
if(!isset($container)){
include 'auth_container_imap_options.php';
$container = new Auth_Container_IMAP($options);
}
return($container);
}
function &getExtraOptions() {
print "IMAPContainer::getExtraOptions\n";
include 'auth_container_imap_options.php';
return($extra_options);
}
}
?>
Auth-1.6.4/tests/MDB2Container.php 0000600 0001750 0001750 00000001364 11461311104 017375 0 ustar clockwerx clockwerx _prepare();
}
if (!MDB2::isConnection($container->db)) {
$this->markTestSkipped("MDB2 is not a connection object, check dsn");
}
return $container;
}
function &getExtraOptions() {
include 'auth_container_mdb2_options.php';
return $extra_options;
}
}
?>
Auth-1.6.4/tests/MDBContainer.php 0000600 0001750 0001750 00000001464 11461311104 017314 0 ustar clockwerx clockwerx skip_tests}\n";
if(!isset($container)){
include 'auth_container_mdb_options.php';
$container = new Auth_Container_MDB($options);
// Catch if DB connection cannot be made
$res = $container->_prepare();
}
if (!MDB::isConnection($container->db)) {
$this->markTestSkipped("MDB is not a connection object, check dsn");
}
return $container;
}
function &getExtraOptions() {
include 'auth_container_mdb_options.php';
return $extra_options;
}
}
?>
Auth-1.6.4/tests/mysql_test_db.sql 0000600 0001750 0001750 00000000243 11461311104 017722 0 ustar clockwerx clockwerx CREATE TABLE `temp` (
`username` varchar(150) NOT NULL default '',
`password` varchar(200) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Auth-1.6.4/tests/POP3aContainer.php 0000600 0001750 0001750 00000001012 11461311104 017561 0 ustar clockwerx clockwerx
Auth-1.6.4/tests/POP3Container.php 0000600 0001750 0001750 00000001006 11461311104 017423 0 ustar clockwerx clockwerx
Auth-1.6.4/tests/TestAuthContainer.php 0000600 0001750 0001750 00000011260 11461311104 020446 0 ustar clockwerx clockwerx container =& $this->getContainer();
$this->user = 'joe';
$this->pass = 'doe';
$this->opt = 'VeryCoolUser';
// Nedded since lazy loading of container was introduced
$this->container->_auth_obj =& new Auth(&$this);
$opt = $this->getExtraOptions();
// Add the default user to be used for some testing
$this->container->addUser($opt['username'], $opt['passwd']);
}
function tearDown()
{
$opt = $this->getExtraOptions();
// Remove default user
$this->container->removeUser($opt['username']);
}
function testListUsers()
{
$users = $this->container->listUsers();
if (AUTH_METHOD_NOT_SUPPORTED === $users) {
$this->markTestSkipped('This operation is not supported by '.get_class($this->container));
}
$opt = $this->getExtraOptions();
$this->assertTrue(is_array($users[0]), 'First array element from result was not an array');
$this->assertTrue($users[0]['username'] == $opt['username'], sprintf('First username was not equal to default username "%s" ', $opt['username']));
}
function testAddUser()
{
$cb = count($this->container->listUsers());
$res = $this->container->addUser($this->user, $this->pass, $this->opt);
if (AUTH_METHOD_NOT_SUPPORTED === $res) {
$this->markTestSkipped("This operation is not supported by ".get_class($this->container));
}
if (PEAR::isError($res)) {
$error = $res->getMessage().' ['.$res->getUserInfo().']';
} else {
$error = '';
}
$this->assertTrue(!PEAR::isError($res), 'error:'.$error);
$ca = count($this->container->listUsers());
$users = $this->container->listUsers();
$last_username = $users[$ca-1]['username'];
$this->assertTrue( ($cb === $ca-1) , sprintf('Count of users before (%s) and after (%s) does not differ by one', $cb, $ca));
$this->assertTrue( $this->container->fetchData($this->user, $this->pass) , sprintf('Could not verify with the newly created user %s',$this->user));
// Remove the user we just added, assumes removeUser works
$this->container->removeUser($this->user);
}
function testFetchData()
{
$opt = $this->getExtraOptions();
$fetch_res = $this->container->fetchData($opt['username'], $opt['passwd']);
if (AUTH_METHOD_NOT_SUPPORTED === $fetch_res) {
$this->markTestSkipped("This operation is not supported by ".get_class($this->container));
}
$this->assertTrue($fetch_res,sprintf('Could not verify with the default username (%s) and passwd (%s)', $opt['username'], $opt['passwd']));
// Test for fail fetchData
$opt = $this->getExtraOptions();
$this->assertFalse(
$this->container->fetchData(md5($opt['username']), $opt['passwd']),
"fetchData returned true with invalid username and pass"
);
}
/**
* Tjis test depends on add user & remove user to work
*/
function testFetchDataSpaceInPassword()
{
$user = uniqid('user');
$pass = 'Some Pass ';
$res = $this->container->addUser($user, $pass, array());
if (AUTH_METHOD_NOT_SUPPORTED === $res) {
$this->markTestSkipped("This operation is not supported by ".get_class($this->container));
}
$fetch_res = $this->container->fetchData($user, $pass);
if (AUTH_METHOD_NOT_SUPPORTED === $fetch_res) {
$this->markTestSkipped("This operation is not supported by ".get_class($this->container));
}
$this->assertTrue($fetch_res, 'Could not verify user with space password');
$remove_res = $this->container->removeUser($user);
}
function testRemoveUser()
{
// Add a user to be removed when testing removeUuser method
// Assume add user works
$this->container->addUser('for_remove', 'for_remove');
$cb = count($this->container->listUsers());
$remove_res = $this->container->removeUser('for_remove');
if (AUTH_METHOD_NOT_SUPPORTED === $remove_res) {
$this->markTestSkipped("This operation is not supported by ".get_class($this->container));
}
$ca = count($this->container->listUsers());
$this->assertTrue($cb === $ca+1, sprintf('Could not remove user "%s", count before:%s count after:%s ', 'for_remove', $cb, $ca));
}
}
?>
Auth-1.6.4/tests/tests.php 0000600 0001750 0001750 00000002520 11461311104 016203 0 ustar clockwerx clockwerx getCode())."\n";
print "Message:".trim($err->getMessage())."\n";
#print "UserInfo:".trim($err->getUserInfo())."\n";
#print "DebugInfo:".trim($err->getDebugInfo())."\n";
}
#error_reporting(0);
PEAR::setErrorHandling(PEAR_ERROR_PRINT, "\nPear Error:%s \n");
#PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, "error");
set_time_limit(0);
$suite = new PHPUnit_TestSuite();
// File Container
#$suite->addTest(new PHPUnit_TestSuite('IMAPContainer'));
$suite->addTest(new PHPUnit_TestSuite('FileContainer'));
$suite->addTest(new PHPUnit_TestSuite('DBContainer'));
//$suite->addTest(new PHPUnit_TestSuite('DBLiteContainer'));
// MDB Container
$suite->addTest(new PHPUnit_TestSuite('MDBContainer'));
// MDB2 Container
$suite->addTest(new PHPUnit_TestSuite('MDB2Container'));
// POP3 Container
$suite->addTest(new PHPUnit_TestSuite('POP3Container'));
$result = PHPUnit::run($suite);
echo $result->toString();
?>
Auth-1.6.4/tests/users 0000600 0001750 0001750 00000000001 11461311104 015404 0 ustar clockwerx clockwerx
Auth-1.6.4/Auth.php 0000600 0001750 0001750 00000114632 11461311104 014610 0 ustar clockwerx clockwerx
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: Auth.php 289651 2009-10-15 04:39:07Z aashley $
* @link http://pear.php.net/package/Auth
*/
/**
* Returned if session exceeds idle time
*/
define('AUTH_IDLED', -1);
/**
* Returned if session has expired
*/
define('AUTH_EXPIRED', -2);
/**
* Returned if container is unable to authenticate user/password pair
*/
define('AUTH_WRONG_LOGIN', -3);
/**
* Returned if a container method is not supported.
*/
define('AUTH_METHOD_NOT_SUPPORTED', -4);
/**
* Returned if new Advanced security system detects a breach
*/
define('AUTH_SECURITY_BREACH', -5);
/**
* Returned if checkAuthCallback says session should not continue.
*/
define('AUTH_CALLBACK_ABORT', -6);
/**
* Auth Log level - INFO
*/
define('AUTH_LOG_INFO', 6);
/**
* Auth Log level - DEBUG
*/
define('AUTH_LOG_DEBUG', 7);
/**
* Auth Advanced Security - IP Checks
*/
define('AUTH_ADV_IPCHECK', 1);
/**
* Auth Advanced Security - User Agent Checks
*/
define('AUTH_ADV_USERAGENT', 2);
/**
* Auth Advanced Security - Challenge Response
*/
define('AUTH_ADV_CHALLENGE', 3);
/**
* PEAR::Auth
*
* The PEAR::Auth class provides methods for creating an
* authentication system using PHP.
*
* @category Authentication
* @package Auth
* @author Martin Jansen
* @author Adam Ashley
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision: 289651 $
* @link http://pear.php.net/package/Auth
*/
class Auth {
// {{{ properties
/**
* Auth lifetime in seconds
*
* If this variable is set to 0, auth never expires
*
* @var integer
* @see setExpire(), checkAuth()
*/
var $expire = 0;
/**
* Has the auth session expired?
*
* @var bool
* @see checkAuth()
*/
var $expired = false;
/**
* Maximum idletime in seconds
*
* The difference to $expire is, that the idletime gets
* refreshed each time checkAuth() is called. If this
* variable is set to 0, idletime is never checked.
*
* @var integer
* @see setIdle(), checkAuth()
*/
var $idle = 0;
/**
* Is the maximum idletime over?
*
* @var boolean
* @see checkAuth()
*/
var $idled = false;
/**
* Storage object
*
* @var object
* @see Auth(), validateLogin()
*/
var $storage = '';
/**
* User-defined function that creates the login screen
*
* @var string
*/
var $loginFunction = '';
/**
* Should the login form be displayed
*
* @var bool
* @see setShowlogin()
*/
var $showLogin = true;
/**
* Is Login Allowed from this page
*
* @var bool
* @see setAllowLogin
*/
var $allowLogin = true;
/**
* Current authentication status
*
* @var string
*/
var $status = '';
/**
* Username
*
* @var string
*/
var $username = '';
/**
* Password
*
* @var string
*/
var $password = '';
/**
* checkAuth callback function name
*
* @var string
* @see setCheckAuthCallback()
*/
var $checkAuthCallback = '';
/**
* Login callback function name
*
* @var string
* @see setLoginCallback()
*/
var $loginCallback = '';
/**
* Failed Login callback function name
*
* @var string
* @see setFailedLoginCallback()
*/
var $loginFailedCallback = '';
/**
* Logout callback function name
*
* @var string
* @see setLogoutCallback()
*/
var $logoutCallback = '';
/**
* Auth session-array name
*
* @var string
*/
var $_sessionName = '_authsession';
/**
* Package Version
*
* @var string
*/
var $version = "@version@";
/**
* Flag to use advanced security
* When set extra checks will be made to see if the
* user's IP or useragent have changed across requests.
* Turned off by default to preserve BC.
*
* @var mixed Boolean to turn all advanced security options on or off
* Array containing named values turning specific advanced
* security features on or off individually
* array(
* AUTH_ADV_IPCHECK => true,
* AUTH_ADV_USERAGENT => true,
* AUTH_ADV_CHALLENGE => true,
* );
*/
var $advancedsecurity = false;
/**
* Username key in POST array
*
* @var string
*/
var $_postUsername = 'username';
/**
* Password key in POST array
*
* @var string
*/
var $_postPassword = 'password';
/**
* Holds a reference to the session auth variable
* @var array
*/
var $session;
/**
* Holds a reference to the global server variable
* @var array
*/
var $server;
/**
* Holds a reference to the global post variable
* @var array
*/
var $post;
/**
* Holds a reference to the global cookie variable
* @var array
*/
var $cookie;
/**
* A hash to hold various superglobals as reference
* @var array
*/
var $authdata;
/**
* How many times has checkAuth been called
* @var int
*/
var $authChecks = 0;
/**
* PEAR::Log object
*
* @var object Log
*/
var $logger = null;
/**
* Whether to enable logging of behaviour
*
* @var boolean
*/
var $enableLogging = false;
/**
* Whether to regenerate session id everytime start is called
*
* @var boolean
*/
var $regenerateSessionId = false;
// }}}
// {{{ Auth() [constructor]
/**
* Constructor
*
* Set up the storage driver.
*
* @param string Type of the storage driver
* @param mixed Additional options for the storage driver
* (example: if you are using DB as the storage
* driver, you have to pass the dsn string here)
*
* @param string Name of the function that creates the login form
* @param boolean Should the login form be displayed if necessary?
* @return void
*/
function Auth($storageDriver, $options = '', $loginFunction = '', $showLogin = true)
{
$this->applyAuthOptions($options);
// Start the session suppress error if already started
if(!session_id()){
@session_start();
if(!session_id()) {
// Throw error
include_once 'PEAR.php';
PEAR::throwError('Session could not be started by Auth, '
.'possibly headers are already sent, try putting '
.'ob_start in the beginning of your script');
}
}
// Make Sure Auth session variable is there
if(!isset($_SESSION[$this->_sessionName])) {
$_SESSION[$this->_sessionName] = array();
}
// Assign Some globals to internal references, this will replace _importGlobalVariable
$this->session =& $_SESSION[$this->_sessionName];
$this->server =& $_SERVER;
$this->post =& $_POST;
$this->cookie =& $_COOKIE;
if ($loginFunction != '' && is_callable($loginFunction)) {
$this->loginFunction = $loginFunction;
}
if (is_bool($showLogin)) {
$this->showLogin = $showLogin;
}
if (is_object($storageDriver)) {
$this->storage =& $storageDriver;
// Pass a reference to auth to the container, ugly but works
// this is used by the DB container to use method setAuthData not staticaly.
$this->storage->_auth_obj =& $this;
} else {
// $this->storage = $this->_factory($storageDriver, $options);
//
$this->storage_driver = $storageDriver;
$this->storage_options =& $options;
}
}
// }}}
// {{{ applyAuthOptions()
/**
* Set the Auth options
*
* Some options which are Auth specific will be applied
* the rest will be left for usage by the container
*
* @param array An array of Auth options
* @return array The options which were not applied
* @access private
*/
function &applyAuthOptions(&$options)
{
if(is_array($options)){
if (!empty($options['sessionName'])) {
$this->_sessionName = $options['sessionName'];
unset($options['sessionName']);
}
if (isset($options['allowLogin'])) {
$this->allowLogin = $options['allowLogin'];
unset($options['allowLogin']);
}
if (!empty($options['postUsername'])) {
$this->_postUsername = $options['postUsername'];
unset($options['postUsername']);
}
if (!empty($options['postPassword'])) {
$this->_postPassword = $options['postPassword'];
unset($options['postPassword']);
}
if (isset($options['advancedsecurity'])) {
$this->advancedsecurity = $options['advancedsecurity'];
unset($options['advancedsecurity']);
}
if (isset($options['enableLogging'])) {
$this->enableLogging = $options['enableLogging'];
unset($options['enableLogging']);
}
if (isset($options['regenerateSessionId']) && is_bool($options['regenerateSessionId'])) {
$this->regenerateSessionId = $options['regenerateSessionId'];
}
}
return($options);
}
// }}}
// {{{ _loadStorage()
/**
* Load Storage Driver if not already loaded
*
* Suspend storage instantiation to make Auth lighter to use
* for calls which do not require login
*
* @return bool True if the conainer is loaded, false if the container
* is already loaded
* @access private
*/
function _loadStorage()
{
if(!is_object($this->storage)) {
$this->storage =& $this->_factory($this->storage_driver,
$this->storage_options);
$this->storage->_auth_obj =& $this;
$this->log('Loaded storage container ('.$this->storage_driver.')', AUTH_LOG_DEBUG);
return(true);
}
return(false);
}
// }}}
// {{{ _factory()
/**
* Return a storage driver based on $driver and $options
*
* @static
* @param string $driver Type of storage class to return
* @param string $options Optional parameters for the storage class
* @return object Object Storage object
* @access private
*/
function &_factory($driver, $options = '')
{
$storage_class = 'Auth_Container_' . $driver;
include_once 'Auth/Container/' . $driver . '.php';
$obj =& new $storage_class($options);
return $obj;
}
// }}}
// {{{ assignData()
/**
* Assign data from login form to internal values
*
* This function takes the values for username and password
* from $HTTP_POST_VARS/$_POST and assigns them to internal variables.
* If you wish to use another source apart from $HTTP_POST_VARS/$_POST,
* you have to derive this function.
*
* @global $HTTP_POST_VARS, $_POST
* @see Auth
* @return void
* @access private
*/
function assignData()
{
$this->log('Auth::assignData() called.', AUTH_LOG_DEBUG);
if ( isset($this->post[$this->_postUsername])
&& $this->post[$this->_postUsername] != '') {
$this->username = (get_magic_quotes_gpc() == 1
? stripslashes($this->post[$this->_postUsername])
: $this->post[$this->_postUsername]);
}
if ( isset($this->post[$this->_postPassword])
&& $this->post[$this->_postPassword] != '') {
$this->password = (get_magic_quotes_gpc() == 1
? stripslashes($this->post[$this->_postPassword])
: $this->post[$this->_postPassword] );
}
}
// }}}
// {{{ start()
/**
* Start new auth session
*
* @return void
* @access public
*/
function start()
{
$this->log('Auth::start() called.', AUTH_LOG_DEBUG);
// #10729 - Regenerate session id here if we are generating it on every
// page load.
if ($this->regenerateSessionId) {
session_regenerate_id(true);
}
$this->assignData();
if (!$this->checkAuth() && $this->allowLogin) {
$this->login();
}
}
// }}}
// {{{ login()
/**
* Login function
*
* @return void
* @access private
*/
function login()
{
$this->log('Auth::login() called.', AUTH_LOG_DEBUG);
$login_ok = false;
$this->_loadStorage();
// Check if using challenge response
(isset($this->post['authsecret']) && $this->post['authsecret'] == 1)
? $usingChap = true
: $usingChap = false;
// When the user has already entered a username, we have to validate it.
if (!empty($this->username)) {
if (true === $this->storage->fetchData($this->username, $this->password, $usingChap)) {
$this->session['challengekey'] = md5($this->username.$this->password);
$login_ok = true;
$this->log('Successful login.', AUTH_LOG_INFO);
}
}
if (!empty($this->username) && $login_ok) {
$this->setAuth($this->username);
if (is_callable($this->loginCallback)) {
$this->log('Calling loginCallback ('.$this->loginCallback.').', AUTH_LOG_DEBUG);
call_user_func_array($this->loginCallback, array($this->username, &$this));
}
}
// If the login failed or the user entered no username,
// output the login screen again.
if (!empty($this->username) && !$login_ok) {
$this->log('Incorrect login.', AUTH_LOG_INFO);
$this->status = AUTH_WRONG_LOGIN;
if (is_callable($this->loginFailedCallback)) {
$this->log('Calling loginFailedCallback ('.$this->loginFailedCallback.').', AUTH_LOG_DEBUG);
call_user_func_array($this->loginFailedCallback, array($this->username, &$this));
}
}
if ((empty($this->username) || !$login_ok) && $this->showLogin) {
$this->log('Rendering Login Form.', AUTH_LOG_INFO);
if (is_callable($this->loginFunction)) {
$this->log('Calling loginFunction ('.$this->loginFunction.').', AUTH_LOG_DEBUG);
call_user_func_array($this->loginFunction, array($this->username, $this->status, &$this));
} else {
// BC fix Auth used to use drawLogin for this
// call is sub classes implement this
if (is_callable(array($this, 'drawLogin'))) {
$this->log('Calling Auth::drawLogin()', AUTH_LOG_DEBUG);
return $this->drawLogin($this->username, $this);
}
$this->log('Using default Auth_Frontend_Html', AUTH_LOG_DEBUG);
// New Login form
include_once 'Auth/Frontend/Html.php';
return Auth_Frontend_Html::render($this, $this->username);
}
} else {
return;
}
}
// }}}
// {{{ setExpire()
/**
* Set the maximum expire time
*
* @param integer time in seconds
* @param bool add time to current expire time or not
* @return void
* @access public
*/
function setExpire($time, $add = false)
{
$add ? $this->expire += $time : $this->expire = $time;
}
// }}}
// {{{ setIdle()
/**
* Set the maximum idle time
*
* @param integer time in seconds
* @param bool add time to current maximum idle time or not
* @return void
* @access public
*/
function setIdle($time, $add = false)
{
$add ? $this->idle += $time : $this->idle = $time;
}
// }}}
// {{{ setSessionName()
/**
* Set name of the session to a customized value.
*
* If you are using multiple instances of PEAR::Auth
* on the same domain, you can change the name of
* session per application via this function.
* This will chnage the name of the session variable
* auth uses to store it's data in the session
*
* @param string New name for the session
* @return void
* @access public
*/
function setSessionName($name = 'session')
{
$this->_sessionName = '_auth_'.$name;
// Make Sure Auth session variable is there
if(!isset($_SESSION[$this->_sessionName])) {
$_SESSION[$this->_sessionName] = array();
}
$this->session =& $_SESSION[$this->_sessionName];
}
// }}}
// {{{ setShowLogin()
/**
* Should the login form be displayed if necessary?
*
* @param bool show login form or not
* @return void
* @access public
*/
function setShowLogin($showLogin = true)
{
$this->showLogin = $showLogin;
}
// }}}
// {{{ setAllowLogin()
/**
* Is Login Allowed from this page?
*
* @param bool allow login from this page or not
* @return void
* @access public
*/
function setAllowLogin($allowLogin = true)
{
$this->allowLogin = $allowLogin;
}
// }}}
// {{{ setCheckAuthCallback()
/**
* Register a callback function to be called whenever the validity of the login is checked
* The function will receive two parameters, the username and a reference to the auth object.
*
* @param string callback function name
* @return void
* @access public
* @since Method available since Release 1.4.3
*/
function setCheckAuthCallback($checkAuthCallback)
{
$this->checkAuthCallback = $checkAuthCallback;
}
// }}}
// {{{ setLoginCallback()
/**
* Register a callback function to be called on user login.
* The function will receive two parameters, the username and a reference to the auth object.
*
* @param string callback function name
* @return void
* @see setLogoutCallback()
* @access public
*/
function setLoginCallback($loginCallback)
{
$this->loginCallback = $loginCallback;
}
// }}}
// {{{ setFailedLoginCallback()
/**
* Register a callback function to be called on failed user login.
* The function will receive two parameters, the username and a reference to the auth object.
*
* @param string callback function name
* @return void
* @access public
*/
function setFailedLoginCallback($loginFailedCallback)
{
$this->loginFailedCallback = $loginFailedCallback;
}
// }}}
// {{{ setLogoutCallback()
/**
* Register a callback function to be called on user logout.
* The function will receive three parameters, the username and a reference to the auth object.
*
* @param string callback function name
* @return void
* @see setLoginCallback()
* @access public
*/
function setLogoutCallback($logoutCallback)
{
$this->logoutCallback = $logoutCallback;
}
// }}}
// {{{ setAuthData()
/**
* Register additional information that is to be stored
* in the session.
*
* @param string Name of the data field
* @param mixed Value of the data field
* @param boolean Should existing data be overwritten? (default
* is true)
* @return void
* @access public
*/
function setAuthData($name, $value, $overwrite = true)
{
if (!empty($this->session['data'][$name]) && $overwrite == false) {
return;
}
$this->session['data'][$name] = $value;
}
// }}}
// {{{ getAuthData()
/**
* Get additional information that is stored in the session.
*
* If no value for the first parameter is passed, the method will
* return all data that is currently stored.
*
* @param string Name of the data field
* @return mixed Value of the data field.
* @access public
*/
function getAuthData($name = null)
{
if (!isset($this->session['data'])) {
return null;
}
if(!isset($name)) {
return $this->session['data'];
}
if (isset($name) && isset($this->session['data'][$name])) {
return $this->session['data'][$name];
}
return null;
}
// }}}
// {{{ setAuth()
/**
* Register variable in a session telling that the user
* has logged in successfully
*
* @param string Username
* @return void
* @access public
*/
function setAuth($username)
{
$this->log('Auth::setAuth() called.', AUTH_LOG_DEBUG);
// #10729 - Regenerate session id here only if generating at login only
// Don't do it if we are regenerating on every request so we don't
// regenerate it twice in one request.
if (!$this->regenerateSessionId) {
// #2021 - Change the session id to avoid session fixation attacks php 4.3.3 >
session_regenerate_id(true);
}
if (!isset($this->session) || !is_array($this->session)) {
$this->session = array();
}
if (!isset($this->session['data'])) {
$this->session['data'] = array();
}
$this->session['sessionip'] = isset($this->server['REMOTE_ADDR'])
? $this->server['REMOTE_ADDR']
: '';
$this->session['sessionuseragent'] = isset($this->server['HTTP_USER_AGENT'])
? $this->server['HTTP_USER_AGENT']
: '';
$this->session['sessionforwardedfor'] = isset($this->server['HTTP_X_FORWARDED_FOR'])
? $this->server['HTTP_X_FORWARDED_FOR']
: '';
// This should be set by the container to something more safe
// Like md5(passwd.microtime)
if(empty($this->session['challengekey'])) {
$this->session['challengekey'] = md5($username.microtime());
}
$this->session['challengecookie'] = md5($this->session['challengekey'].microtime());
setcookie('authchallenge', $this->session['challengecookie'], 0, '/');
$this->session['registered'] = true;
$this->session['username'] = $username;
$this->session['timestamp'] = time();
$this->session['idle'] = time();
}
// }}}
// {{{ setAdvancedSecurity()
/**
* Enables advanced security checks
*
* Currently only ip change and useragent change
* are detected
* @todo Add challenge cookies - Create a cookie which changes every time
* and contains some challenge key which the server can verify with
* a session var cookie might need to be crypted (user pass)
* @param bool Enable or disable
* @return void
* @access public
*/
function setAdvancedSecurity($flag=true)
{
$this->advancedsecurity = $flag;
}
// }}}
// {{{ checkAuth()
/**
* Checks if there is a session with valid auth information.
*
* @access public
* @return boolean Whether or not the user is authenticated.
*/
function checkAuth()
{
$this->log('Auth::checkAuth() called.', AUTH_LOG_DEBUG);
$this->authChecks++;
if (isset($this->session)) {
// Check if authentication session is expired
if ( $this->expire > 0
&& isset($this->session['timestamp'])
&& ($this->session['timestamp'] + $this->expire) < time()) {
$this->log('Session Expired', AUTH_LOG_INFO);
$this->expired = true;
$this->status = AUTH_EXPIRED;
$this->logout();
return false;
}
// Check if maximum idle time is reached
if ( $this->idle > 0
&& isset($this->session['idle'])
&& ($this->session['idle'] + $this->idle) < time()) {
$this->log('Session Idle Time Reached', AUTH_LOG_INFO);
$this->idled = true;
$this->status = AUTH_IDLED;
$this->logout();
return false;
}
if ( isset($this->session['registered'])
&& isset($this->session['username'])
&& $this->session['registered'] == true
&& $this->session['username'] != '') {
Auth::updateIdle();
if ($this->_isAdvancedSecurityEnabled()) {
$this->log('Advanced Security Mode Enabled.', AUTH_LOG_DEBUG);
// Only Generate the challenge once
if ( $this->authChecks == 1
&& $this->_isAdvancedSecurityEnabled(AUTH_ADV_CHALLENGE)) {
$this->log('Generating new Challenge Cookie.', AUTH_LOG_DEBUG);
$this->session['challengecookieold'] = $this->session['challengecookie'];
$this->session['challengecookie'] = md5($this->session['challengekey'].microtime());
setcookie('authchallenge', $this->session['challengecookie'], 0, '/');
}
// Check for ip change
if ( $this->_isAdvancedSecurityEnabled(AUTH_ADV_IPCHECK)
&& isset($this->server['REMOTE_ADDR'])
&& $this->session['sessionip'] != $this->server['REMOTE_ADDR']) {
$this->log('Security Breach. Remote IP Address changed.', AUTH_LOG_INFO);
// Check if the IP of the user has changed, if so we
// assume a man in the middle attack and log him out
$this->expired = true;
$this->status = AUTH_SECURITY_BREACH;
$this->logout();
return false;
}
// Check for ip change (if connected via proxy)
if ( $this->_isAdvancedSecurityEnabled(AUTH_ADV_IPCHECK)
&& isset($this->server['HTTP_X_FORWARDED_FOR'])
&& $this->session['sessionforwardedfor'] != $this->server['HTTP_X_FORWARDED_FOR']) {
$this->log('Security Breach. Forwarded For IP Address changed.', AUTH_LOG_INFO);
// Check if the IP of the user connecting via proxy has
// changed, if so we assume a man in the middle attack
// and log him out.
$this->expired = true;
$this->status = AUTH_SECURITY_BREACH;
$this->logout();
return false;
}
// Check for useragent change
if ( $this->_isAdvancedSecurityEnabled(AUTH_ADV_USERAGENT)
&& isset($this->server['HTTP_USER_AGENT'])
&& $this->session['sessionuseragent'] != $this->server['HTTP_USER_AGENT']) {
$this->log('Security Breach. User Agent changed.', AUTH_LOG_INFO);
// Check if the User-Agent of the user has changed, if
// so we assume a man in the middle attack and log him out
$this->expired = true;
$this->status = AUTH_SECURITY_BREACH;
$this->logout();
return false;
}
// Check challenge cookie here, if challengecookieold is not set
// this is the first time and check is skipped
// TODO when user open two pages similtaneuly (open in new window,open
// in tab) auth breach is caused find out a way around that if possible
if ( $this->_isAdvancedSecurityEnabled(AUTH_ADV_CHALLENGE)
&& isset($this->session['challengecookieold'])
&& $this->session['challengecookieold'] != $this->cookie['authchallenge']) {
$this->log('Security Breach. Challenge Cookie mismatch.', AUTH_LOG_INFO);
$this->expired = true;
$this->status = AUTH_SECURITY_BREACH;
$this->logout();
$this->login();
return false;
}
}
if (is_callable($this->checkAuthCallback)) {
$this->log('Calling checkAuthCallback ('.$this->checkAuthCallback.').', AUTH_LOG_DEBUG);
$checkCallback = call_user_func_array($this->checkAuthCallback, array($this->username, &$this));
if ($checkCallback == false) {
$this->log('checkAuthCallback failed.', AUTH_LOG_INFO);
$this->expired = true;
$this->status = AUTH_CALLBACK_ABORT;
$this->logout();
return false;
}
}
$this->log('Session OK.', AUTH_LOG_INFO);
return true;
}
} else {
$this->log('Unable to locate session storage.', AUTH_LOG_DEBUG);
return false;
}
$this->log('No login session.', AUTH_LOG_DEBUG);
return false;
}
// }}}
// {{{ staticCheckAuth() [static]
/**
* Statically checks if there is a session with valid auth information.
*
* @access public
* @see checkAuth
* @return boolean Whether or not the user is authenticated.
* @static
*/
function staticCheckAuth($options = null)
{
static $staticAuth;
if(!isset($staticAuth)) {
$staticAuth = new Auth('null', $options);
}
$staticAuth->log('Auth::staticCheckAuth() called', AUTH_LOG_DEBUG);
return $staticAuth->checkAuth();
}
// }}}
// {{{ getAuth()
/**
* Has the user been authenticated?
*
* Is there a valid login session. Previously this was different from
* checkAuth() but now it is just an alias.
*
* @access public
* @return bool True if the user is logged in, otherwise false.
*/
function getAuth()
{
$this->log('Auth::getAuth() called.', AUTH_LOG_DEBUG);
return $this->checkAuth();
}
// }}}
// {{{ logout()
/**
* Logout function
*
* This function clears any auth tokens in the currently
* active session and executes the logout callback function,
* if any
*
* @access public
* @return void
*/
function logout()
{
$this->log('Auth::logout() called.', AUTH_LOG_DEBUG);
if (is_callable($this->logoutCallback) && isset($this->session['username'])) {
$this->log('Calling logoutCallback ('.$this->logoutCallback.').', AUTH_LOG_DEBUG);
call_user_func_array($this->logoutCallback, array($this->session['username'], &$this));
}
$this->username = '';
$this->password = '';
$this->session = null;
}
// }}}
// {{{ updateIdle()
/**
* Update the idletime
*
* @access private
* @return void
*/
function updateIdle()
{
$this->session['idle'] = time();
}
// }}}
// {{{ getUsername()
/**
* Get the username
*
* @return string
* @access public
*/
function getUsername()
{
if (isset($this->session['username'])) {
return($this->session['username']);
}
return('');
}
// }}}
// {{{ getStatus()
/**
* Get the current status
*
* @return string
* @access public
*/
function getStatus()
{
return $this->status;
}
// }}}
// {{{ getPostUsernameField()
/**
* Gets the post varible used for the username
*
* @return string
* @access public
*/
function getPostUsernameField()
{
return($this->_postUsername);
}
// }}}
// {{{ getPostPasswordField()
/**
* Gets the post varible used for the username
*
* @return string
* @access public
*/
function getPostPasswordField()
{
return($this->_postPassword);
}
// }}}
// {{{ sessionValidThru()
/**
* Returns the time up to the session is valid
*
* @access public
* @return integer
*/
function sessionValidThru()
{
if (!isset($this->session['idle'])) {
return 0;
}
if ($this->idle == 0) {
return 0;
}
return ($this->session['idle'] + $this->idle);
}
// }}}
// {{{ listUsers()
/**
* List all users that are currently available in the storage
* container
*
* @access public
* @return array
*/
function listUsers()
{
$this->log('Auth::listUsers() called.', AUTH_LOG_DEBUG);
$this->_loadStorage();
return $this->storage->listUsers();
}
// }}}
// {{{ addUser()
/**
* Add user to the storage container
*
* @access public
* @param string Username
* @param string Password
* @param mixed Additional parameters
* @return mixed True on success, PEAR error object on error
* and AUTH_METHOD_NOT_SUPPORTED otherwise.
*/
function addUser($username, $password, $additional = '')
{
$this->log('Auth::addUser() called.', AUTH_LOG_DEBUG);
$this->_loadStorage();
return $this->storage->addUser($username, $password, $additional);
}
// }}}
// {{{ removeUser()
/**
* Remove user from the storage container
*
* @access public
* @param string Username
* @return mixed True on success, PEAR error object on error
* and AUTH_METHOD_NOT_SUPPORTED otherwise.
*/
function removeUser($username)
{
$this->log('Auth::removeUser() called.', AUTH_LOG_DEBUG);
$this->_loadStorage();
return $this->storage->removeUser($username);
}
// }}}
// {{{ changePassword()
/**
* Change password for user in the storage container
*
* @access public
* @param string Username
* @param string The new password
* @return mixed True on success, PEAR error object on error
* and AUTH_METHOD_NOT_SUPPORTED otherwise.
*/
function changePassword($username, $password)
{
$this->log('Auth::changePassword() called', AUTH_LOG_DEBUG);
$this->_loadStorage();
return $this->storage->changePassword($username, $password);
}
// }}}
// {{{ log()
/**
* Log a message from the Auth system
*
* @access public
* @param string The message to log
* @param string The log level to log the message under. See the Log documentation for more info.
* @return boolean
*/
function log($message, $level = AUTH_LOG_DEBUG)
{
if (!$this->enableLogging) return false;
$this->_loadLogger();
$this->logger->log('AUTH: '.$message, $level);
}
// }}}
// {{{ _loadLogger()
/**
* Load Log object if not already loaded
*
* Suspend logger instantiation to make Auth lighter to use
* for calls which do not require logging
*
* @return bool True if the logger is loaded, false if the logger
* is already loaded
* @access private
*/
function _loadLogger()
{
if(is_null($this->logger)) {
if (!class_exists('Log')) {
include_once 'Log.php';
}
$this->logger =& Log::singleton('null',
null,
'auth['.getmypid().']',
array(),
AUTH_LOG_DEBUG);
return(true);
}
return(false);
}
// }}}
// {{{ attachLogObserver()
/**
* Attach an Observer to the Auth Log Source
*
* @param object Log_Observer A Log Observer instance
* @return boolean
*/
function attachLogObserver(&$observer) {
$this->_loadLogger();
return $this->logger->attach($observer);
}
// }}}
// {{{ _isAdvancedSecurityEnabled()
/**
* Is advanced security enabled?
*
* Pass one of the Advanced Security constants as the first parameter
* to check if that advanced security check is enabled.
*
* @param integer
* @return boolean
*/
function _isAdvancedSecurityEnabled($feature = null) {
if (is_null($feature)) {
if ($this->advancedsecurity === true)
return true;
if ( is_array($this->advancedsecurity)
&& in_array(true, $this->advancedsecurity, true))
return true;
return false;
} else {
if (is_array($this->advancedsecurity)) {
if ( isset($this->advancedsecurity[$feature])
&& $this->advancedsecurity[$feature] == true)
return true;
return false;
}
return (bool)$this->advancedsecurity;
}
}
// }}}
}
?>
Auth-1.6.4/README.AdvancedSecurity 0000600 0001750 0001750 00000006235 11461311104 017311 0 ustar clockwerx clockwerx 03 July 2004
TODO
* Session fixation attack (BUG #2021)
* Fix multiple open windows and challenge responce cookies (use a list of cookies which are allowed)
Since Auth 1.3 new security functionality has been added.
The main purpose for these advanced security checks is to avoid man-in-the-middle attacks and
session hijacking.
Session hijacking example
- Login to an Auth protected page. Write down the session id (should be something like PHPSESSID=36916b0aa1180386010f304b6160e3e8)
- Open a different browser (FireFox <> IE), or a browser on a different computer
- Type down the address of the secure page and add ?PHPSESSID=36916b0aa1180386010f304b6160e3e8 where
PHPSESSID is the php session name and 36916b0aa1180386010f304b6160e3e8 is the valid session id which you wrote down earlier
- You should be logged in with the same creditentials
To enable the advanced scurity checks you have to call
$auth->setAdvancedSecurity();
If this has been enabled the following security checks will be performed
- Login screen will use md5 when submitting the password if java script is enabled in the browser
- If user ip address has been changed betwin requests the user will be logged out
- If user User-Agent string has been changed the user will be logged out
- If user does not provide a valid auth challenge cookied he will be logged out (read below for explanation)
Limitations
* Challenge responce cookies would not allow a user to open multiple windows of the same page (Open in new window/tab). If
the user accesses the protected area from two browser windows he will be logged out. It can also create a problem if you
create dynamic images with php and that code passes through the auth layer. One way to avoid it is to disable advanced security for
those pages only selectively.
* Password saving does not work with login screens which use challenge responce (md5 hashing) of password
* Challenge responce on login only works with DB container and plain or md5 hashing
Challenge Responce cookies
The challenge responce cookies provide a way to avoid most of the session hijacking problems. Since User-Agent headers
and IP address can be spoofed, or in the case of IP a proxy can be used an extra security step has been added using a
challenge cookie.
After the user is authenthicated by Auth he is presented with a challenge cookie. For his next request to be succesfull
he must present that cookie on his next request. If that is successfull he will be presented with a new
challenge cookie. This will be reapeated for each request the user makes.
While this method is not fool proof it does limit the possibilities for an attack.
First the attacker must must obtain the challenge cookie and use it before the user does.
If the user makes a request after the attacker the session will be logged out and both of them
will need to login again.
A problem which this scheme does not address well is users leaving their sessions without preforming a logout
in this case the attacker is free to abuse the user session (provided he has met all the prerequisites).
Ideas and sujestions for improvements are more than welcome.
send to yavo@siava.org
Auth-1.6.4/README.Auth 0000600 0001750 0001750 00000000122 11461311104 014742 0 ustar clockwerx clockwerx The documentation for PEAR::Auth is available at
http://pear.php.net/manual/