Source for file joomla.php

Documentation is available at joomla.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Plugin
  4.  * @subpackage  Authentication.joomla
  5.  *
  6.  * @copyright   Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7.  * @license     GNU General Public License version 2 or later; see LICENSE.txt
  8.  */
  9.  
  10. defined('_JEXEC'or die;
  11.  
  12. /**
  13.  * Joomla Authentication plugin
  14.  *
  15.  * @package     Joomla.Plugin
  16.  * @subpackage  Authentication.joomla
  17.  * @since       1.5
  18.  */
  19. {
  20.     /**
  21.      * This method should handle any authentication and report back to the subject
  22.      *
  23.      * @param   array   $credentials  Array holding the user credentials
  24.      * @param   array   $options      Array of extra options
  25.      * @param   object  &$response    Authentication response object
  26.      *
  27.      * @return  boolean 
  28.      *
  29.      * @since   1.5
  30.      */
  31.     public function onUserAuthenticate($credentials$options&$response)
  32.     {
  33.         $response->type 'Joomla';
  34.  
  35.         // Joomla does not like blank passwords
  36.         if (empty($credentials['password']))
  37.         {
  38.             $response->status JAuthentication::STATUS_FAILURE;
  39.             $response->error_message JText::_('JGLOBAL_AUTH_EMPTY_PASS_NOT_ALLOWED');
  40.  
  41.             return false;
  42.         }
  43.  
  44.         // Get a database object
  45.         $db    JFactory::getDbo();
  46.         $query $db->getQuery(true)
  47.             ->select('id, password')
  48.             ->from('#__users')
  49.             ->where('username=' $db->quote($credentials['username']));
  50.  
  51.         $db->setQuery($query);
  52.         $result $db->loadObject();
  53.  
  54.         if ($result)
  55.         {
  56.             if (substr($result->password04== '$2y$')
  57.             {
  58.                 // BCrypt passwords are always 60 characters, but it is possible that salt is appended although non standard.
  59.                 $password60 substr($result->password060);
  60.  
  61.                 if (JCrypt::hasStrongPasswordSupport())
  62.                 {
  63.                     $match password_verify($credentials['password']$password60);
  64.                 }
  65.             }
  66.             elseif (substr($result->password08== '{SHA256}')
  67.             {
  68.                 // Check the password
  69.                 $parts    explode(':'$result->password);
  70.                 $crypt    $parts[0];
  71.                 $salt    @$parts[1];
  72.                 $testcrypt JUserHelper::getCryptedPassword($credentials['password']$salt'sha256'false);
  73.  
  74.                 if ($result->password == $testcrypt)
  75.                 {
  76.                     $match true;
  77.                 }
  78.             }
  79.             else
  80.             {
  81.                 // Check the password
  82.                 $parts    explode(':'$result->password);
  83.                 $crypt    $parts[0];
  84.                 $salt    @$parts[1];
  85.  
  86.                 $testcrypt JUserHelper::getCryptedPassword($credentials['password']$salt'md5-hex'false);
  87.  
  88.                 if ($crypt == $testcrypt)
  89.                 {
  90.                     $match true;
  91.                 }
  92.             }
  93.  
  94.             if (isset($match&& $match === true)
  95.             {
  96.                 // Bring this in line with the rest of the system
  97.                 $user JUser::getInstance($result->id);
  98.                 $response->email $user->email;
  99.                 $response->fullname $user->name;
  100.  
  101.                 if (JFactory::getApplication()->isAdmin())
  102.                 {
  103.                     $response->language $user->getParam('admin_language');
  104.                 }
  105.                 else
  106.                 {
  107.                     $response->language $user->getParam('language');
  108.                 }
  109.  
  110.                 $response->status JAuthentication::STATUS_SUCCESS;
  111.                 $response->error_message '';
  112.             }
  113.             else
  114.             {
  115.                 // Invalid password
  116.                 $response->status JAuthentication::STATUS_FAILURE;
  117.                 $response->error_message JText::_('JGLOBAL_AUTH_INVALID_PASS');
  118.             }
  119.         }
  120.         else
  121.         {
  122.             // Invalid user
  123.             $response->status JAuthentication::STATUS_FAILURE;
  124.             $response->error_message JText::_('JGLOBAL_AUTH_NO_USER');
  125.         }
  126.  
  127.         // Check the two factor authentication
  128.         if ($response->status == JAuthentication::STATUS_SUCCESS)
  129.         {
  130.             require_once JPATH_ADMINISTRATOR '/components/com_users/helpers/users.php';
  131.  
  132.             $methods UsersHelper::getTwoFactorMethods();
  133.  
  134.             if (count($methods<= 1)
  135.             {
  136.                 // No two factor authentication method is enabled
  137.                 return;
  138.             }
  139.  
  140.             require_once JPATH_ADMINISTRATOR '/components/com_users/models/user.php';
  141.  
  142.             $model new UsersModelUser;
  143.  
  144.             // Load the user's OTP (one time password, a.k.a. two factor auth) configuration
  145.             if (!array_key_exists('otp_config'$options))
  146.             {
  147.                 $otpConfig $model->getOtpConfig($result->id);
  148.                 $options['otp_config'$otpConfig;
  149.             }
  150.             else
  151.             {
  152.                 $otpConfig $options['otp_config'];
  153.             }
  154.  
  155.             // Check if the user has enabled two factor authentication
  156.             if (empty($otpConfig->method|| ($otpConfig->method == 'none'))
  157.             {
  158.                 // Warn the user if he's using a secret code but he has not
  159.                 // enabed two factor auth in his account.
  160.                 if (!empty($credentials['secretkey']))
  161.                 {
  162.                     try
  163.                     {
  164.                         $app JFactory::getApplication();
  165.  
  166.                         $this->loadLanguage();
  167.  
  168.                         $app->enqueueMessage(JText::_('PLG_AUTH_JOOMLA_ERR_SECRET_CODE_WITHOUT_TFA')'warning');
  169.                     }
  170.                     catch (Exception $exc)
  171.                     {
  172.                         // This happens when we are in CLI mode. In this case
  173.                         // no warning is issued
  174.                         return;
  175.                     }
  176.                 }
  177.  
  178.                 return;
  179.             }
  180.  
  181.             // Load the Joomla! RAD layer
  182.             if (!defined('FOF_INCLUDED'))
  183.             {
  184.                 include_once JPATH_LIBRARIES '/fof/include.php';
  185.             }
  186.  
  187.             // Try to validate the OTP
  188.             FOFPlatform::getInstance()->importPlugin('twofactorauth');
  189.  
  190.             $otpAuthReplies FOFPlatform::getInstance()->runPlugins('onUserTwofactorAuthenticate'array($credentials$options));
  191.  
  192.             $check false;
  193.  
  194.             /*
  195.              * This looks like noob code but DO NOT TOUCH IT and do not convert
  196.              * to in_array(). During testing in_array() inexplicably returned
  197.              * null when the OTEP begins with a zero! o_O
  198.              */
  199.             if (!empty($otpAuthReplies))
  200.             {
  201.                 foreach ($otpAuthReplies as $authReply)
  202.                 {
  203.                     $check $check || $authReply;
  204.                 }
  205.             }
  206.  
  207.             // Fall back to one time emergency passwords
  208.             if (!$check)
  209.             {
  210.                 // Did the user use an OTEP instead?
  211.                 if (empty($otpConfig->otep))
  212.                 {
  213.                     if (empty($otpConfig->method|| ($otpConfig->method == 'none'))
  214.                     {
  215.                         // Two factor authentication is not enabled on this account.
  216.                         // Any string is assumed to be a valid OTEP.
  217.  
  218.                         return true;
  219.                     }
  220.                     else
  221.                     {
  222.                         /*
  223.                          * Two factor authentication enabled and no OTEPs defined. The
  224.                          * user has used them all up. Therefore anything he enters is
  225.                          * an invalid OTEP.
  226.                          */
  227.                         return false;
  228.                     }
  229.                     }
  230.  
  231.                 // Clean up the OTEP (remove dashes, spaces and other funny stuff
  232.                 // our beloved users may have unwittingly stuffed in it)
  233.                 $otep $credentials['secretkey'];
  234.                 $otep filter_var($otepFILTER_SANITIZE_NUMBER_INT);
  235.                 $otep str_replace('-'''$otep);
  236.  
  237.                 $check false;
  238.  
  239.                 // Did we find a valid OTEP?
  240.                 if (in_array($otep$otpConfig->otep))
  241.                 {
  242.                     // Remove the OTEP from the array
  243.                     $otpConfig->otep array_diff($otpConfig->oteparray($otep));
  244.  
  245.                     $model->setOtpConfig($result->id$otpConfig);
  246.  
  247.                     // Return true; the OTEP was a valid one
  248.                     $check true;
  249.                 }
  250.             }
  251.  
  252.             if (!$check)
  253.             {
  254.                 $response->status JAuthentication::STATUS_FAILURE;
  255.                 $response->error_message JText::_('JGLOBAL_AUTH_INVALID_SECRETKEY');
  256.             }
  257.         }
  258.     }
  259. }

Documentation generated on Tue, 19 Nov 2013 15:06:08 +0100 by phpDocumentor 1.4.3