LiveUser
[ class tree: LiveUser ] [ index: LiveUser ] [ all elements ]

Source for file Common.php

Documentation is available at Common.php

  1. <?php
  2. // LiveUser: A framework for authentication and authorization in PHP applications
  3. // Copyright (C) 2002-2003 Markus Wolff
  4. //
  5. // This library is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU Lesser General Public
  7. // License as published by the Free Software Foundation; either
  8. // version 2.1 of the License, or (at your option) any later version.
  9. //
  10. // This library is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13. // Lesser General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU Lesser General Public
  16. // License along with this library; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  
  19. /**
  20.  * This class provides a set of functions for implementing a user
  21.  * authorisation system on live websites. All authorisation
  22.  * backends/containers must be extensions of this base class.
  23.  *
  24.  * Requirements:
  25.  * - When using "DB" backend:
  26.  *   PEAR::DB database abstraction layer
  27.  * - LiveUser admin GUI for easy user administration and setup of
  28.  *   authorisation areas and rights
  29.  *
  30.  * @author   Markus Wolff <wolff@21st.de>
  31.  * @version  $Id: Common.php,v 1.56 2004/10/10 01:24:15 dufuz Exp $
  32.  * @package  LiveUser
  33.  * @category authentication
  34.  */
  35. {
  36.     /**
  37.      * The handle (username) of the current user
  38.      *
  39.      * @access protected
  40.      * @var    string 
  41.      */
  42.     var $handle = '';
  43.  
  44.     /**
  45.      * The password of the current user as given to the
  46.      * login() method.
  47.      *
  48.      * @access protected
  49.      * @var    string 
  50.      */
  51.     var $passwd = '';
  52.  
  53.     /**
  54.      * Current user's database record id
  55.      *
  56.      * @access protected
  57.      * @var    integer 
  58.      */
  59.     var $authUserId = 0;
  60.  
  61.     /**
  62.      * Is the current user allowed to login at all? If false,
  63.      * a call to login() will not set $logged_in to true, even
  64.      * if handle and password were submitted correctly. This is
  65.      * useful when you want your users to be activated by an
  66.      * administrator before they can actually use your application.
  67.      * Default: false
  68.      *
  69.      * @access protected
  70.      * @var    boolean 
  71.      * @see    LiveUser_Auth_Common::loggedIn
  72.      */
  73.     var $isActive = null;
  74.  
  75.     /**
  76.      * Has the current user successfully logged in?
  77.      * Default: false
  78.      *
  79.      * @access protected
  80.      * @var    boolean 
  81.      * @see    LiveUser_Auth_Common::isActive
  82.      */
  83.     var $loggedIn = null;
  84.  
  85.     /**
  86.      * Timestamp of last login (previous to currentLogin)
  87.      *
  88.      * @access protected
  89.      * @var    integer 
  90.      */
  91.     var $lastLogin = 0;
  92.  
  93.     /**
  94.      * Timestamp of current login (last to be written)
  95.      *
  96.      * @access protected
  97.      * @var    integer 
  98.      */
  99.     var $currentLogin = 0;
  100.  
  101.     /**
  102.      * Number of hours that must pass between two logins
  103.      * to be counted as a new login. Comes in handy in
  104.      * some situations. Default: 12
  105.      *
  106.      * @access protected
  107.      * @var    integer 
  108.      */
  109.     var $loginTimeout = 12;
  110.  
  111.     /**
  112.      * Auth lifetime in seconds
  113.      *
  114.      * If this variable is set to 0, auth never expires
  115.      *
  116.      * @access protected
  117.      * @var    integer 
  118.      */
  119.     var $expireTime = 0;
  120.  
  121.     /**
  122.      * Maximum time of idleness in seconds
  123.      *
  124.      * Idletime gets refreshed each time, init() is called. If this
  125.      * variable is set to 0, idle time is never checked.
  126.      *
  127.      * @access protected
  128.      * @var    integer 
  129.      */
  130.     var $idleTime = 0;
  131.  
  132.     /**
  133.      * Allow multiple users in the database to have the same
  134.      * login handle. Default: false.
  135.      *
  136.      * @access protected
  137.      * @var    boolean 
  138.      */
  139.     var $allowDuplicateHandles = false;
  140.  
  141.     /**
  142.      * Set posible encryption modes.
  143.      *
  144.      * @access protected
  145.      * @var    array 
  146.      */
  147.     var $encryptionModes = array('MD5'   => 'MD5',
  148.                                  'PLAIN' => 'PLAIN',
  149.                                  'RC4'   => 'RC4',
  150.                                  'SHA1'  => 'SHA1');
  151.  
  152.  
  153.     /**
  154.      * Defines the algorithm used for encrypting/decrypting
  155.      * passwords. Default: "MD5".
  156.      *
  157.      * @access protected
  158.      * @var    string 
  159.      */
  160.     var $passwordEncryptionMode = 'MD5';
  161.  
  162.     /**
  163.      * Defines the array index number of the LoginManager?s "backends" property.
  164.      *
  165.      * @access protected
  166.      * @var    integer 
  167.      */
  168.     var $backendArrayIndex = 0;
  169.  
  170.     /**
  171.      * Indicates if backend module initialized correctly. If yes,
  172.      * true, if not false. Backend module won't initialize if the
  173.      * init value (usually an object or resource handle that
  174.      * identifies the backend to be used) is not of the required
  175.      * type.
  176.      *
  177.      * @access protected
  178.      * @var    boolean 
  179.      */
  180.     var $init_ok = false;
  181.  
  182.     /**
  183.      * Error stack
  184.      *
  185.      * @access protected
  186.      * @var    PEAR_ErrorStack 
  187.      */
  188.     var $_stack = null;
  189.  
  190.     /**
  191.      * Class constructor. Feel free to override in backend subclasses.
  192.      *
  193.      * @access protected
  194.      * @var    array     configuration options
  195.      * @return void 
  196.      */
  197.     function LiveUser_Auth_Common($connectOptions)
  198.     {
  199.         $this->_stack = &PEAR_ErrorStack::singleton('LiveUser');
  200.  
  201.         if (is_array($connectOptions)) {
  202.             foreach ($connectOptions as $key => $value{
  203.                 if (isset($this->$key)) {
  204.                     $this->$key $value;
  205.                 }
  206.             }
  207.         }
  208.     }
  209.  
  210.     /**
  211.      * store all properties in an array
  212.      *
  213.      * @access  public
  214.      * @return  array 
  215.      */
  216.     function freeze()
  217.     {
  218.         $propertyValues = array(
  219.             'handle'       => $this->handle,
  220.             'passwd'       => $this->passwd,
  221.             'authUserId'   => $this->authUserId,
  222.             'isActive'     => $this->isActive,
  223.             'loggedIn'     => $this->loggedIn,
  224.             'lastLogin'    => $this->lastLogin,
  225.             'currentLogin' => $this->currentLogin,
  226.         );
  227.         if (isset($this->authTableCols['custom'])) {
  228.             foreach ($this->authTableCols['custom'as $alias => $value{
  229.                 $propertyValues[$alias=  $this->$alias;
  230.             }
  231.         }
  232.         return $propertyValues;
  233.     }
  234.  
  235.     /**
  236.      * properly disconnect from resources
  237.      *
  238.      * @access  public
  239.      * @return  void 
  240.      */
  241.     function disconnect()
  242.     {
  243.     }
  244.  
  245.     /**
  246.      * Reinitializes properties
  247.      *
  248.      * @access  public
  249.      * @param   array  $propertyValues 
  250.      * @return  void 
  251.      */
  252.     function unfreeze($propertyValues)
  253.     {
  254.         foreach ($propertyValues as $key => $value{
  255.             $this->{$key$value;
  256.         }
  257.     // end func unfreeze
  258.  
  259.     /**
  260.      * Decrypts a password so that it can be compared with the user
  261.      * input. Uses the algorithm defined in the passwordEncryptionMode
  262.      * property.
  263.      *
  264.      * @param  string the encrypted password
  265.      * @return string The decrypted password
  266.      */
  267.     function decryptPW($encryptedPW)
  268.     {
  269.         $decryptedPW 'Encryption type not supported.';
  270.  
  271.         switch (strtoupper($this->passwordEncryptionMode)) {
  272.             case 'PLAIN':
  273.                 $decryptedPW $encryptedPW;
  274.                 break;
  275.             case 'MD5':
  276.                 // MD5 can't be decoded, so return the string unmodified
  277.                 $decryptedPW $encryptedPW;
  278.                 break;
  279.             case 'RC4':
  280.                 if (!is_object($this->rc4)) {
  281.                     $rc4 =LiveUser::CryptRC4Factory($this->_options['cookie']['secret']);
  282.                     if (!$rc4{
  283.                         return false;
  284.                     }
  285.                     $this->rc4 =$rc4;
  286.                 }
  287.                 $decryptedPW $encryptedPW;
  288.                 $this->rc4->decrypt($decryptedPW);
  289.                 break;
  290.             case 'SHA1':
  291.                 // SHA1 can't be decoded, so return the string unmodified
  292.                 $decryptedPW $encryptedPW;
  293.                 break;
  294.         }
  295.  
  296.         return $decryptedPW;
  297.     }
  298.  
  299.     /**
  300.      * Encrypts a password for storage in a backend container.
  301.      * Uses the algorithm defined in the passwordEncryptionMode
  302.      * property.
  303.      *
  304.      * @param string  encryption type
  305.      * @return string The encrypted password
  306.      */
  307.     function encryptPW($plainPW)
  308.     {
  309.         $encryptedPW 'Encryption type not supported.';
  310.  
  311.         switch (strtoupper($this->passwordEncryptionMode)) {
  312.             case 'PLAIN':
  313.                 $encryptedPW $plainPW;
  314.                 break;
  315.             case 'MD5':
  316.                 $encryptedPW md5($plainPW);
  317.                 break;
  318.             case 'RC4':
  319.                 if (!is_object($this->rc4)) {
  320.                     $rc4 =LiveUser::CryptRC4Factory($this->_options['cookie']['secret']);
  321.                     if (!$rc4{
  322.                         return false;
  323.                     }
  324.                     $this->rc4 =$rc4;
  325.                 }
  326.                 $encryptedPW $plainPW;
  327.                 $this->rc4->crypt($encryptedPW);
  328.                 break;
  329.             case 'SHA1':
  330.                 if (!function_exists('sha1')) {
  331.                         $this->_stack->push(LIVEUSER_ERROR_NOT_SUPPORTED,
  332.                             'exception'array()'SHA1 function doesn\'t exist. Upgrade your PHP version');
  333.                         return false;
  334.                 }
  335.                 $encryptedPW sha1($plainPW);
  336.                 break;
  337.         }
  338.  
  339.         return $encryptedPW;
  340.     }
  341.  
  342.     /**
  343.      * Checks if there's enough time between lastLogin
  344.      * and current login (now) to count as a new login.
  345.      *
  346.      * @access public
  347.      * @return boolean  true if it is a new login, false if not
  348.      */
  349.     function isNewLogin()
  350.     {
  351.         $meantime $this->loginTimeout * 3600;
  352.         if (time(>= $this->lastLogin + $meantime{
  353.             return true;
  354.         else {
  355.             return false;
  356.         }
  357.     }
  358.  
  359.     /**
  360.      * Tries to make a login with the given handle and password.
  361.      * If $checkpw is set to false, the password won't be
  362.      * validated and the user will be logged in anyway. Set this
  363.      * option if you want to allow your users to be
  364.      * authenticated by a simple cookie... however, this is
  365.      * NOT RECOMMENDED !!!
  366.      * In any case, a user can't login if he's not active.
  367.      *
  368.      * @param string   user handle
  369.      * @param string   user password
  370.      * @param boolean  check password ? useful for some backends like LDAP
  371.      * @param boolean  update the last login data ?
  372.      */
  373.     function login($handle$passwd$checkpw = true$updateLastLogin = true)
  374.     {
  375.         // Init value: Has user data successfully been read?
  376.         $success        = false;
  377.         // Init value: Is user logged in?
  378.         $this->loggedIn = false;
  379.         // Read user data from database
  380.         if ($this->allowDuplicateHandles == true || $checkpw == true{
  381.             // If duplicate handles are allowed or the password _has_
  382.             // to be checked, only read in data if a matching user is found
  383.             $success $this->_readUserData($handle$passwd);
  384.         else {
  385.             // If duplicate handles are not allowed or the password
  386.             // doesn't need to be checked, just read in the data based
  387.             // on the handle
  388.             $success $this->_readUserData($handle);
  389.         }
  390.  
  391.         // If login is successful (user data has been read)
  392.         if ($success == true{
  393.             $pwCheck = false; // Init value
  394.  
  395.             // Just in case: Some databases will return whitespace when using
  396.             // CHAR fields to store passwords, so we?ll remove it.
  397.             $this->passwd = trim($this->passwd);
  398.  
  399.             // ...check again if we have to check the password...
  400.             if ($checkpw == true{
  401.                 // If yes, does the password from the database match the given one?
  402.                 if (strtoupper($this->passwordEncryptionMode== 'MD5'
  403.                         && $this->passwd == $this->encryptPW($passwd)){
  404.                     // If yes, set pwCheck Flag
  405.                     $pwCheck = true;
  406.                 else if ($this->passwd == $passwd{
  407.                     // If yes, set pwCheck Flag
  408.                     $pwCheck = true;
  409.                 }
  410.             else {
  411.                 // We don't have to check for the password, so set the pwCheck Flag
  412.                 // regardless of the user's input
  413.                 $pwCheck = true;
  414.             }
  415.  
  416.             // ...we still need to check if this user is declared active and
  417.             // if the pwCheck Flag is set to true...
  418.             if ($this->isActive != false && $pwCheck == true{
  419.                 // ...and if so, we have a successful login (hooray)!
  420.                 $this->loggedIn = true;
  421.                 $this->currentLogin = time();
  422.             }
  423.         }
  424.  
  425.         // In case Login was successful, check if this can be counted
  426.         // as a _new_ login by definition...
  427.         if ($updateLastLogin == true && $this->isNewLogin(== true && $this->loggedIn == true{
  428.             $this->_updateUserData();
  429.         }
  430.     }
  431.  
  432.     /**
  433.      * Writes current values for user back to the database.
  434.      * This method does nothing in the base class and is supposed to
  435.      * be overridden in subclasses according to the supported backend.
  436.      *
  437.      * @access private
  438.      * @return void 
  439.      */
  440.     function _updateUserData()
  441.     {
  442.         $this->_stack->push(LIVEUSER_ERROR_NOT_SUPPORTED'exception');
  443.     }
  444.  
  445.     /**
  446.      * Reads auth_user_id, passwd, is_active flag
  447.      * lastlogin timestamp from the database
  448.      * If only $handle is given, it will read the data
  449.      * from the first user with that handle and return
  450.      * true on success.
  451.      * If $handle and $passwd are given, it will try to
  452.      * find the first user with both handle and password
  453.      * matching and return true on success (this allows
  454.      * multiple users having the same handle but different
  455.      * passwords - yep, some people want this).
  456.      * If no match is found, false is being returned.
  457.      *
  458.      * Again, this does nothing in the base class. The
  459.      * described functionality must be implemented in a
  460.      * subclass overriding this method.
  461.      *
  462.      * @access private
  463.      * @param  string  user handle
  464.      * @param  boolean user password
  465.      * @return void 
  466.      */
  467.     function _readUserData($handle$passwd = false)
  468.     {
  469.         $this->_stack->push(LIVEUSER_ERROR_NOT_SUPPORTED'exception',
  470.             array('feature' => '_readUserData'));
  471.         return false;
  472.     }
  473.  
  474.     /**
  475.      * Helper function that checks if there is a user in
  476.      * the database who's matching the given parameters.
  477.      * If $checkHandle is given and $checkPW is set to
  478.      * false, it only checks if a user with that handle
  479.      * exists. If only $checkPW is given and $checkHandle
  480.      * is set to false, it will check if there exists a
  481.      * user with that password. If both values are set to
  482.      * anything but false, it will find the first user in
  483.      * the database with both values matching.
  484.      * Please note:
  485.      * - If no match was found, the return value is false
  486.      * - If a match was found, the auth_user_id from the database
  487.      *   is being returned
  488.      * Whatever is returned, please keep in mind that this
  489.      * function only searches for the _first_ occurence
  490.      * of the search values in the database. So when you
  491.      * have multiple users with the same handle, only the
  492.      * ID of the first one is returned. Same goes for
  493.      * passwords. Searching for both password and handle
  494.      * should be pretty safe, though - having more than
  495.      * one user with the same handle/password combination
  496.      * in the database would be pretty stupid anyway.
  497.      *
  498.      * Again, this does nothing in the base class. The
  499.      * described functionality must be implemented in a
  500.      * subclass overriding this method.
  501.      *
  502.      * @param  boolean check handle ?
  503.      * @param  boolean check password ?
  504.      * @return mixed  user id when there is a match, false otherwise
  505.      */
  506.     function userExists($checkHandle = false$checkPW = false)
  507.     {
  508.         $this->_stack->push(LIVEUSER_ERROR_NOT_SUPPORTED'exception',
  509.             array('feature' => 'userExists'));
  510.             return false;
  511.     }
  512.  
  513.     /**
  514.      * Function returns the inquired value if it exists in the class.
  515.      *
  516.      * @param  string   Name of the property to be returned.
  517.      * @return mixed    null, a value or an array.
  518.      */
  519.     function getProperty($what)
  520.     {
  521.         $that = null;
  522.         if (isset($this->$what)) {
  523.             $that $this->$what;
  524.         }
  525.         return $that;
  526.     }
  527. }
  528. ?>

Documentation generated on Mon, 11 Mar 2019 13:56:59 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.