b2evolution PHP Cross Reference Blogging Systems

Source: /inc/_init_login.inc.php - 442 lines - 17106 bytes - Text - Print

Description: This file initializes everything BUT the blog! It is useful when you want to do very customized templates! It is also called by more complete initializers.

   1  <?php
   2  /**
   3   * This file initializes everything BUT the blog!
   4   *
   5   * It is useful when you want to do very customized templates!
   6   * It is also called by more complete initializers.
   7   *
   8   * This file is part of the evoCore framework - {@link http://evocore.net/}
   9   * See also {@link http://sourceforge.net/projects/evocms/}.
  10   *
  11   * @copyright (c)2003-2014 by Francois Planque - {@link http://fplanque.com/}
  12   * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.
  13   * Parts of this file are copyright (c)2005-2006 by PROGIDISTRI - {@link http://progidistri.com/}.
  14   *
  15   * {@internal License choice
  16   * - If you have received this file as part of a package, please find the license.txt file in
  17   *   the same folder or the closest folder above for complete license terms.
  18   * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
  19   *   then you must choose one of the following licenses before using the file:
  20   *   - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
  21   *   - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
  22   * }}
  23   *
  24   * {@internal Open Source relicensing agreement:
  25   * Daniel HAHLER grants Francois PLANQUE the right to license
  26   * Daniel HAHLER's contributions to this file and the b2evolution project
  27   * under any OSI approved OSS license (http://www.opensource.org/licenses/).
  28   *
  29   * Matt FOLLETT grants Francois PLANQUE the right to license
  30   * Matt FOLLETT's contributions to this file and the b2evolution project
  31   * under any OSI approved OSS license (http://www.opensource.org/licenses/).
  32   * }}
  33   *
  34   * @package evocore
  35   *
  36   * @version $Id: _init_login.inc.php 6136 2014-03-08 07:59:48Z manuel $
  37   */
  38  if( !defined('EVO_CONFIG_LOADED') ) die( 'Please, do not access this page directly.' );
  39  
  40  
  41  $Timer->resume( '_init_login' );
  42  
  43  
  44  /*
  45   * Login procedure:
  46   * TODO: dh> if a "logged in"-session exists (in most cases) it should not trigger parsing the meat of this code.
  47   * fp> mind you, most hits will be on the font end and will not be loggedin sessions
  48   *     However, I agree that the login stuff should only be included when the user is actually attempting to log in.
  49   */
  50  if( !isset($login_required) )
  51  {
  52      $login_required = false;
  53  }
  54  if( !isset($validate_required) )
  55  {
  56      $validate_required = param( 'validate_required', 'boolean', false );
  57  }
  58  
  59  global $login_error;
  60  /**
  61   * Login error message
  62   * @global string
  63   */
  64  $login_error = '';
  65  
  66  $login = NULL;
  67  $pass = NULL;
  68  $pass_md5 = NULL;
  69  $email_login = false;
  70  
  71  if( isset($_POST[ $dummy_fields[ 'login' ] ] ) && isset($_POST[ $dummy_fields[ 'pwd' ] ] ) )
  72  { // Trying to log in with a POST
  73      $login = $_POST[ $dummy_fields[ 'login' ] ];
  74      $pass = $_POST[ $dummy_fields[ 'pwd' ] ];
  75      unset($_POST[ $dummy_fields[ 'pwd' ] ]); // password will be hashed below
  76  }
  77  elseif( isset($_GET[ $dummy_fields[ 'login' ] ] ) )
  78  { // Trying to log in with a GET; we might only provide a user here.
  79      $login = $_GET[ $dummy_fields[ 'login' ] ];
  80      $pass = isset($_GET[ $dummy_fields[ 'pwd' ] ]) ? $_GET[ $dummy_fields[ 'pwd' ] ] : '';
  81      unset($_GET[ $dummy_fields[ 'pwd' ] ]); // password will be hashed below
  82  }
  83  
  84  $Debuglog->add( 'Login: login: '.var_export($login, true), '_init_login' );
  85  $Debuglog->add( 'Login: pass: '.( empty($pass) ? '' : 'not' ).' empty', '_init_login' );
  86  
  87  // either 'login' (normal) or 'redirect_to_backoffice' may be set here. This also helps to display the login form again, if either login or pass were empty.
  88  $login_action = param_arrayindex( 'login_action' );
  89  
  90  if( ( $login != NULL ) && ( ! is_string( $login ) ) )
  91  { // Login must be string
  92      $login = NULL;
  93      if( ! empty( $login_action ) )
  94      { // This was a login request with an invalid login parameter type, so it must be a doctored request
  95          debug_die('The type of the received login parameter is invalid!');
  96      }
  97  }
  98  if( ( $pass != NULL ) && ( ! is_string( $pass ) ) )
  99  { // Password must be string
 100      $pass = NULL;
 101      if( ! empty( $login_action ) )
 102      { // This was a login request with an invalid pwd parameter type, so it must be a doctored request
 103          debug_die('The type of the received password parameter is invalid!');
 104      }
 105  }
 106  
 107  $UserCache = & get_UserCache();
 108  
 109  if( ! empty($login_action) || (! empty($login) && ! empty($pass)) )
 110  { // User is trying to login right now
 111  
 112      // Stop a request from the blocked IP addresses
 113      antispam_block_ip();
 114  
 115      global $action;
 116      // Set $action so it can be recorded in the hitlog:
 117      $action = 'login';
 118  
 119      $Debuglog->add( 'Login: User is trying to log in.', '_init_login' );
 120  
 121      header_nocache();        // Don't take risks here :p
 122  
 123      // Check that this login request is not a CSRF hacked request:
 124      $Session->assert_received_crumb( 'loginform' );
 125      // fp> NOTE: TODO: now that we require goign through the login form, all the login logic that is here can probably be moved to login.php ?
 126  
 127      // Note: login and password cannot include ' or " or > or <
 128      // Note: login cannot include @
 129      $login = evo_strtolower(strip_tags(remove_magic_quotes($login)));
 130      $pass = strip_tags(remove_magic_quotes($pass));
 131      $pass_md5 = md5( $pass );
 132  
 133  
 134      /*
 135       * Handle javascript-hashed password:
 136       * If possible, the login form will hash the entered password with a salt that changes everytime.
 137       */
 138      param('pwd_salt', 'string', ''); // just for comparison with the one from Session
 139      $pwd_salt_sess = $Session->get('core.pwd_salt');
 140  
 141      // $Debuglog->add( 'Login: salt: '.var_export($pwd_salt, true).', session salt: '.var_export($pwd_salt_sess, true), '_init_login' );
 142  
 143      $transmit_hashed_password = (bool)$Settings->get('js_passwd_hashing') && !(bool)$Plugins->trigger_event_first_true('LoginAttemptNeedsRawPassword');
 144      if( $transmit_hashed_password )
 145      {
 146          param( 'pwd_hashed', 'string', '' );
 147      }
 148      else
 149      { // at least one plugin requests the password un-hashed:
 150          $pwd_hashed = '';
 151      }
 152  
 153      // $Debuglog->add( 'Login: pwd_hashed: '.var_export($pwd_hashed, true).', pass: '.var_export($pass, true), '_init_login' );
 154  
 155      $pass_ok = false;
 156      // Trigger Plugin event, which could create the user, according to another database:
 157      if( $Plugins->trigger_event( 'LoginAttempt', array(
 158              'login' => & $login,
 159              'pass' => & $pass,
 160              'pass_md5' => & $pass_md5,
 161              'pass_salt' => & $pwd_salt_sess,
 162              'pass_hashed' => & $pwd_hashed,
 163              'pass_ok' => & $pass_ok ) ) )
 164      { // clear the UserCache, if a plugin has been called - it may have changed user(s)
 165          $UserCache->clear();
 166      }
 167  
 168      if( ! empty( $login_error ) )
 169      { // A plugin has thrown a login error..
 170          // Do nothing, the error will get displayed in the login form..
 171  
 172          // TODO: dh> make sure that the user gets logged out?! (a Plugin might have logged him in and another one thrown an error)
 173      }
 174      else
 175      { // Check login and password
 176          if( is_email( $login ) )
 177          { // we have an email address instead of login name
 178              // get user by email and password
 179              list( $User, $exists_more ) = $UserCache->get_by_emailAndPwd( $login, $pass_md5, $pwd_hashed, $pwd_salt );
 180              if( $User )
 181              { // user was found
 182                  $email_login = $User->get( 'login' );
 183              }
 184          }
 185          elseif( param_check_valid_login( $dummy_fields[ 'login' ] ) )
 186          { // Make sure that we can load the user:
 187              $User = & $UserCache->get_by_login($login);
 188          }
 189          else
 190          {
 191              $User = false;
 192          }
 193  
 194          if( $User && ! $pass_ok )
 195          { // check the password, if no plugin has said "it's ok":
 196              if( ! empty($pwd_hashed) )
 197              { // password hashed by JavaScript:
 198  
 199                  $Debuglog->add( 'Login: Hashed password available.', '_init_login' );
 200  
 201                  if( empty($pwd_salt_sess) )
 202                  { // no salt stored in session: either cookie problem or the user had already tried logging in (from another window for example)
 203                      $Debuglog->add( 'Login: Empty salt_sess!', '_init_login' );
 204                      if( ($pos = strpos( $pass, '_hashed_' ) ) && substr($pass, $pos+8) == $Session->ID )
 205                      { // session ID matches, no cookie problem
 206                          $login_error = T_('The login window has expired. Please try again.');
 207                          $Debuglog->add( 'Login: Session ID matches.', '_init_login' );
 208                      }
 209                      else
 210                      { // more general error:
 211                          $login_error = T_('Either you have not enabled cookies or this login window has expired.');
 212                          $Debuglog->add( 'Login: Session ID does not match.', '_init_login' );
 213                      }
 214                  }
 215                  elseif( $pwd_salt != $pwd_salt_sess )
 216                  { // submitted salt differs from the one stored in the session
 217                      $login_error = T_('The login window has expired. Please try again.');
 218                      $Debuglog->add( 'Login: Submitted salt and salt from Session do not match.', '_init_login' );
 219                  }
 220                  else
 221                  { // compare the password, using the salt stored in the Session:
 222                      #pre_dump( sha1($User->pass.$pwd_salt), $pwd_hashed );
 223                      $pass_ok = sha1($User->pass.$pwd_salt) == $pwd_hashed;
 224                      $Session->delete('core.pwd_salt');
 225                      $Debuglog->add( 'Login: Compared hashed passwords. Result: '.(int)$pass_ok, '_init_login' );
 226                  }
 227              }
 228              else
 229              {
 230                  $pass_ok = ( $User->pass == $pass_md5 );
 231                  $Debuglog->add( 'Login: Compared raw passwords. Result: '.(int)$pass_ok, '_init_login' );
 232              }
 233          }
 234      }
 235  
 236      if( $pass_ok )
 237      { // Login succeeded, set cookies
 238          $Debuglog->add( 'Login: User successfully logged in with username and password...', '_init_login');
 239          // set the user from the login that succeeded
 240          if( $email_login )
 241          {
 242              $login = $email_login;
 243          }
 244          $current_User = & $UserCache->get_by_login($login);
 245          // check and don't login if the current user account was closed
 246          if( $current_User->check_status( 'is_closed' ) )
 247          { // user account was closed
 248              unset( $current_User );
 249              $login_error = T_('This account is closed. You cannot log in.');
 250          }
 251          elseif( $Settings->get('system_lock') && !$current_User->check_perm( 'users', 'edit' ) )
 252          { // System is locked for maintenance and current user has no permission to log in this mode
 253              unset( $current_User );
 254              $login_error = T_('You cannot log in at this time because the system is under maintenance. Please try again in a few moments.');
 255          }
 256          else
 257          { // save the user for later hits
 258              $Session->set_User( $current_User );
 259  
 260              if( $Settings->get('system_lock') && $current_User->check_perm( 'users', 'edit' ) )
 261              { // System is locked for maintenance but current user has permission to log in, Display a message about this mode
 262                  $system_lock_url = ' href="'.$admin_url.'?ctrl=gensettings"';
 263                  $Messages->add( sprintf( T_('The site is currently locked for maintenance. Click <a %s>here</a> to access lock settings.'), $system_lock_url ), 'warning' );
 264              }
 265          }
 266      }
 267      elseif( empty( $login_error ) )
 268      { // if the login_error wasn't set yet, add the default one:
 269          // This will cause the login screen to "popup" (again)
 270          $login_error = T_('Wrong login/password.');
 271      }
 272  
 273  }
 274  elseif( $Session->has_User() /* logged in */
 275      && /* No login param given or the same as current user: */
 276      ( empty($login) || ( ( $tmp_User = & $UserCache->get_by_ID($Session->user_ID) ) && $login == $tmp_User->login ) ) )
 277  { /* if the session has a user assigned to it:
 278       * User was not trying to log in, but he was already logged in:
 279       */
 280      // get the user ID from the session and set up the user again
 281      $current_User = & $UserCache->get_by_ID( $Session->user_ID );
 282  
 283      if( $Settings->get('system_lock') )
 284      { // System is locked for maintenance
 285          if( $current_User->check_perm( 'users', 'edit' ) )
 286          { // Current user is a "super admin"
 287              if( ! $Messages->count() )
 288              { // If there are no other messages yet, display a warning about the system lock
 289                  $system_lock_url = ' href="'.$admin_url.'?ctrl=gensettings"';
 290                  $Messages->add( sprintf( T_('The site is currently locked for maintenance. Click <a %s>here</a> to access lock settings.'), $system_lock_url ), 'warning' );
 291              }
 292          }
 293          else
 294          { // Current user has no permission to be logged in on this mode, we must logout it
 295              logout();
 296              $login_error = T_('You have been logged out because the system is under maintenance. Please log in again in a few moments.');
 297          }
 298      }
 299      else
 300      {
 301          $Debuglog->add( 'Login: Was already logged in... ['.$current_User->get('login').']', '_init_login' );
 302      }
 303  }
 304  else
 305  { // The Session has no user or $login is given (and differs from current user), allow alternate authentication through Plugin:
 306      if( ($event_return = $Plugins->trigger_event_first_true( 'AlternateAuthentication' ))
 307          && $Session->has_User()  # the plugin should have attached the user to $Session
 308      )
 309      {
 310          $Debuglog->add( 'Login: User has been authenticated through plugin #'.$event_return['plugin_ID'].' (AlternateAuthentication)', '_init_login' );
 311          $current_User = & $UserCache->get_by_ID( $Session->user_ID );
 312      }
 313      elseif( $login_required )
 314      {    /*
 315           * ---------------------------------------------------------
 316           * User was not logged in at all, but login is required
 317           * ---------------------------------------------------------
 318           */
 319          // echo ' NOT logged in...';
 320          $Debuglog->add( 'Login: NOT logged in... (did not try)', '_init_login' );
 321  
 322          $login_error = T_('You must log in!');
 323      }
 324  }
 325  unset($pass);
 326  
 327  $action = param( 'action', 'string', NULL );
 328  // Check if the user needs to be validated, but is not yet:
 329  if( check_user_status( 'can_be_validated' ) // user is logged in but not validated and validation is required
 330      && $action != 'logout'
 331      && $action != 'req_validatemail' && $action != 'validatemail' && $validate_required )
 332  { // we're not in that action already:
 333      $action = 'req_validatemail'; // for login.php
 334      if( $is_admin_page )
 335      {
 336          $login_error = T_('In order to access the admin interface, you must first activate your account by clicking on the activation link in the email we sent you. <b>See below:</b>');
 337      }
 338  }
 339  // asimo> If login action is not empty and there was no login error, and action is not logut the we must log in
 340  if( !empty($login_action) && empty( $login_error ) && ( $action != 'logout' ) )
 341  { // Trigger plugin event that allows the plugins to re-act on the login event:
 342      // TODO: dh> these events should provide a flag "login_attempt_failed".
 343      if( empty($current_User) )
 344      {
 345          $Plugins->trigger_event( 'AfterLoginAnonymousUser', array() );
 346      }
 347      else
 348      {
 349          $Plugins->trigger_event( 'AfterLoginRegisteredUser', array() );
 350  
 351          if( ! empty($login_action) )
 352          { // We're coming from the Login form and need to redirect to the requested page:
 353              if( $login_action == 'redirect_to_backoffice' )
 354              { // user pressed the "Log into backoffice!" button
 355                  $redirect_to = $admin_url;
 356              }
 357              else
 358              {
 359                  $redirect_to = param( 'redirect_to', 'url', $baseurl );
 360                  if( preg_match( '#/login.php([&?].*)?$#', $redirect_to ) ||
 361                      preg_match( '#/register.php([&?].*)?$#', $redirect_to ) ||
 362                      preg_match( '#disp=(login|register|lostpassword)#', $redirect_to ) )
 363                  { // avoid redirect back to login/register screen. This shouldn't occur.
 364                      $redirect_to = $baseurl;
 365                  }
 366              }
 367  
 368              if( $email_login )
 369              {
 370                  $Messages->add( sprintf( T_( 'You are now logged in as <b>%s</b>' ), $login ), ( $exists_more ? 'error' : 'success' ) );
 371              }
 372  
 373              header_redirect( $redirect_to );
 374              exit(0);
 375          }
 376      }
 377  }
 378  
 379  if( ! empty( $login_error ) )
 380  {    // ----- LOGIN FAILED -----
 381      $Debuglog->add( 'Login error: '.$login_error, '_init_login' );
 382      // inskin param is set when the login request come from the front office
 383      // we need this to decide if we should use display in-skin login from or not
 384      param( 'inskin', 'boolean', 0 );
 385      $Debuglog->add( 'Param inskin: '.$inskin, '_init_login' );
 386      if( $inskin || use_in_skin_login() )
 387      { // Use in-skin login
 388          $Debuglog->add( 'Trying to use in-skin login', '_init_login' );
 389  
 390          if( is_logged_in() )
 391          { // user is logged in, but the email address is not validated yet
 392              $login = $current_User->login;
 393              $email = $current_User->email;
 394          }
 395  
 396          if( empty( $Blog ) && init_requested_blog() )
 397          { // $blog is set, init $Blog also
 398              $BlogCache = & get_BlogCache();
 399              $Blog = $BlogCache->get_by_ID( $blog, false, false );
 400          }
 401  
 402          $blog_skin_ID = NULL;
 403          if( !empty( $Blog ) )
 404          { // Blog was set
 405              $blog_skin_ID = $Blog->get_skin_ID();
 406          }
 407  
 408          if( !empty( $blog_skin_ID ) )
 409          { // Blog exists and skin ID is set
 410              // Init charset handling:
 411              init_charsets( $current_charset );
 412              locale_activate( $Blog->get('locale') );
 413              $Messages->add( $login_error );
 414              $SkinCache = & get_SkinCache();
 415              $Skin = & $SkinCache->get_by_ID( $blog_skin_ID );
 416              $skin = $Skin->folder;
 417              $disp = 'login';
 418              // fp> We ABSOLUTELY want to recover the previous redirect_to so that after a new login attempt that may be successful,
 419              // we will finally reach our intended destination. This is paramount with emails telling people to come back to the site
 420              // to read a message or sth like that. They must log in first and they may enter the wrong password multiple times.
 421              param( 'redirect_to', 'url', $Blog->gen_blogurl() );
 422              $ads_current_skin_path = $skins_path.$skin.'/';
 423              require $ads_current_skin_path.'index.main.php';
 424              exit(0);
 425              // --- EXITED !! ---
 426          }
 427  
 428          $Debuglog->add( 'we have NO valid blog to use for inskin login', '_init_login' );
 429      }
 430  
 431      // Use standard login
 432      $Debuglog->add( 'Using standard login', '_init_login' );
 433      // Init charset handling:
 434      init_charsets( $current_charset );
 435      require $htsrv_path.'login.php';
 436      exit(0);
 437      // --- EXITED !! ---
 438  }
 439  
 440  $Timer->pause( '_init_login' );
 441  
 442  ?>

title

Description

title

Description

title

Description

title

title

Body