Source for file totp.php

Documentation is available at totp.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Plugin
  4.  * @subpackage  Twofactorauth.totp
  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! Two Factor Authentication using Google Authenticator TOTP Plugin
  14.  *
  15.  * @package     Joomla.Plugin
  16.  * @subpackage  Twofactorauth.totp
  17.  * @since       3.2
  18.  */
  19. class PlgTwofactorauthTotp extends JPlugin
  20. {
  21.     /**
  22.      * Affects constructor behavior. If true, language files will be loaded automatically.
  23.      *
  24.      * @var    boolean 
  25.      * @since  3.2
  26.      */
  27.     protected $autoloadLanguage = true;
  28.  
  29.     /**
  30.      * Method name
  31.      *
  32.      * @var    string 
  33.      * @since  3.2
  34.      */
  35.     protected $methodName = 'totp';
  36.  
  37.     /**
  38.      * Constructor
  39.      *
  40.      * @param   object  &$subject  The object to observe
  41.      * @param   array   $config    An optional associative array of configuration settings.
  42.      *                              Recognized key values include 'name', 'group', 'params', 'language'
  43.      *                              (this list is not meant to be comprehensive).
  44.      *
  45.      * @since   3.2
  46.      */
  47.     public function __construct(&$subject$config array())
  48.     {
  49.         parent::__construct($subject$config);
  50.  
  51.         // Load the Joomla! RAD layer
  52.         if (!defined('FOF_INCLUDED'))
  53.         {
  54.             include_once JPATH_LIBRARIES '/fof/include.php';
  55.         }
  56.     }
  57.  
  58.     /**
  59.      * This method returns the identification object for this two factor
  60.      * authentication plugin.
  61.      *
  62.      * @return  stdClass  An object with public properties method and title
  63.      *
  64.      * @since   3.2
  65.      */
  66.     public function onUserTwofactorIdentify()
  67.     {
  68.         $section = (int) $this->params->get('section'3);
  69.  
  70.         $current_section 0;
  71.  
  72.         try
  73.         {
  74.             $app JFactory::getApplication();
  75.  
  76.             if ($app->isAdmin())
  77.             {
  78.                 $current_section 2;
  79.             }
  80.             elseif ($app->isSite())
  81.             {
  82.                 $current_section 1;
  83.             }
  84.         }
  85.         catch (Exception $exc)
  86.         {
  87.             $current_section 0;
  88.         }
  89.  
  90.         if (!($current_section $section))
  91.         {
  92.             return false;
  93.         }
  94.  
  95.         return (object) array(
  96.             'method' => $this->methodName,
  97.             'title'  => JText::_('PLG_TWOFACTORAUTH_TOTP_METHOD_TITLE')
  98.         );
  99.     }
  100.  
  101.     /**
  102.      * Shows the configuration page for this two factor authentication method.
  103.      *
  104.      * @param   object   $otpConfig  The two factor auth configuration object
  105.      * @param   integer  $user_id    The numeric user ID of the user whose form we'll display
  106.      *
  107.      * @return  boolean|string False if the method is not ours, the HTML of the configuration page otherwise
  108.      *
  109.      * @see     UsersModelUser::getOtpConfig
  110.      * @since   3.2
  111.      */
  112.     public function onUserTwofactorShowConfiguration($otpConfig$user_id null)
  113.     {
  114.         // Create a new TOTP class with Google Authenticator compatible settings
  115.         $totp new FOFEncryptTotp(30610);
  116.  
  117.         if ($otpConfig->method == $this->methodName)
  118.         {
  119.             // This method is already activated. Reuse the same secret key.
  120.             $secret $otpConfig->config['code'];
  121.         }
  122.         else
  123.         {
  124.             // This methods is not activated yet. Create a new secret key.
  125.             $secret $totp->generateSecret();
  126.         }
  127.  
  128.         // These are used by Google Authenticator to tell accounts apart
  129.         $username JFactory::getUser($user_id)->username;
  130.         $hostname JFactory::getURI()->getHost();
  131.  
  132.         // This is the URL to the QR code for Google Authenticator
  133.         $url $totp->getUrl($username$hostname$secret);
  134.  
  135.         // Is this a new TOTP setup? If so, we'll have to show the code validation field.
  136.         $new_totp $otpConfig->method != 'totp';
  137.  
  138.         // Start output buffering
  139.         @ob_start();
  140.  
  141.         // Include the form.php from a template override. If none is found use the default.
  142.         $path FOFPlatform::getInstance()->getTemplateOverridePath('plg_twofactorauth_totp'true);
  143.  
  144.         JLoader::import('joomla.filesystem.file');
  145.  
  146.         if (JFile::exists($path 'form.php'))
  147.         {
  148.             include_once $path 'form.php';
  149.         }
  150.         else
  151.         {
  152.             include_once __DIR__ . '/tmpl/form.php';
  153.         }
  154.  
  155.         // Stop output buffering and get the form contents
  156.         $html @ob_get_clean();
  157.  
  158.         // Return the form contents
  159.         return array(
  160.             'method' => $this->methodName,
  161.             'form'   => $html
  162.         );
  163.     }
  164.  
  165.     /**
  166.      * The save handler of the two factor configuration method's configuration
  167.      * page.
  168.      *
  169.      * @param   string  $method  The two factor auth method for which we'll show the config page
  170.      *
  171.      * @return  boolean|stdClass False if the method doesn't match or we have an error, OTP config object if it succeeds
  172.      *
  173.      * @see     UsersModelUser::setOtpConfig
  174.      * @since   3.2
  175.      */
  176.     public function onUserTwofactorApplyConfiguration($method)
  177.     {
  178.         if ($method != $this->methodName)
  179.         {
  180.             return false;
  181.         }
  182.  
  183.         // Get a reference to the input data object
  184.         $input JFactory::getApplication()->input;
  185.  
  186.         // Load raw data
  187.         $rawData $input->get('jform'array()'array');
  188.         $data $rawData['twofactor']['totp'];
  189.  
  190.         // Warn if the securitycode is empty
  191.         if (array_key_exists('securitycode'$data&& empty($data['securitycode']))
  192.         {
  193.             try
  194.             {
  195.                 $app JFactory::getApplication();
  196.                 $app->enqueueMessage(JText::_('PLG_TWOFACTORAUTH_TOTP_ERR_VALIDATIONFAILED')'error');
  197.             }
  198.             catch (Exception $exc)
  199.             {
  200.                 // This only happens when we are in a CLI application. We cannot
  201.                 // enqueue a message, so just do nothing.
  202.             }
  203.  
  204.             return false;
  205.         }
  206.  
  207.         // Create a new TOTP class with Google Authenticator compatible settings
  208.         $totp new FOFEncryptTotp(30610);
  209.  
  210.         // Check the security code entered by the user (exact time slot match)
  211.         $code $totp->getCode($data['key']);
  212.         $check $code == $data['securitycode'];
  213.  
  214.         /*
  215.          * If the check fails, test the previous 30 second slot. This allow the
  216.          * user to enter the security code when it's becoming red in Google
  217.          * Authenticator app (reaching the end of its 30 second lifetime)
  218.          */
  219.         if (!$check)
  220.         {
  221.             $time time(30;
  222.             $code $totp->getCode($data['key']$time);
  223.             $check $code == $data['securitycode'];
  224.         }
  225.  
  226.         /*
  227.          * If the check fails, test the next 30 second slot. This allows some
  228.          * time drift between the authentication device and the server
  229.          */
  230.         if (!$check)
  231.         {
  232.             $time time(30;
  233.             $code $totp->getCode($data['key']$time);
  234.             $check $code == $data['securitycode'];
  235.         }
  236.  
  237.         if (!$check)
  238.         {
  239.             // Check failed. Do not change two factor authentication settings.
  240.             return false;
  241.         }
  242.  
  243.         // Check succeedeed; return an OTP configuration object
  244.         $otpConfig = (object) array(
  245.             'method'   => 'totp',
  246.             'config'   => array(
  247.                 'code' => $data['key']
  248.             ),
  249.             'otep'     => array()
  250.         );
  251.  
  252.         return $otpConfig;
  253.     }
  254.  
  255.     /**
  256.      * This method should handle any two factor authentication and report back
  257.      * to the subject.
  258.      *
  259.      * @param   array   $credentials  Array holding the user credentials
  260.      * @param   array   $options      Array of extra options
  261.      *
  262.      * @return  boolean  True if the user is authorised with this two-factor authentication method
  263.      *
  264.      * @since   3.2
  265.      */
  266.     public function onUserTwofactorAuthenticate($credentials$options)
  267.     {
  268.         // Get the OTP configuration object
  269.         $otpConfig $options['otp_config'];
  270.  
  271.         // Make sure it's an object
  272.         if (empty($otpConfig|| !is_object($otpConfig))
  273.         {
  274.             return false;
  275.         }
  276.  
  277.         // Check if we have the correct method
  278.         if ($otpConfig->method != $this->methodName)
  279.         {
  280.             return false;
  281.         }
  282.  
  283.         // Check if there is a security code
  284.         if (empty($credentials['secretkey']))
  285.         {
  286.             return false;
  287.         }
  288.  
  289.         // Create a new TOTP class with Google Authenticator compatible settings
  290.         $totp new FOFEncryptTotp(30610);
  291.  
  292.         // Check the code
  293.         $code $totp->getCode($otpConfig->config['code']);
  294.         $check $code == $credentials['secretkey'];
  295.  
  296.         /*
  297.          * If the check fails, test the previous 30 second slot. This allow the
  298.          * user to enter the security code when it's becoming red in Google
  299.          * Authenticator app (reaching the end of its 30 second lifetime)
  300.          */
  301.         if (!$check)
  302.         {
  303.             $time time(30;
  304.             $code $totp->getCode($otpConfig->config['code']$time);
  305.             $check $code == $credentials['secretkey'];
  306.         }
  307.  
  308.         /*
  309.          * If the check fails, test the next 30 second slot. This allows some
  310.          * time drift between the authentication device and the server
  311.          */
  312.         if (!$check)
  313.         {
  314.             $time time(30;
  315.             $code $totp->getCode($otpConfig->config['code']$time);
  316.             $check $code == $credentials['secretkey'];
  317.         }
  318.  
  319.         return $check;
  320.     }
  321. }

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