示例#1
0
 /**
  * Formats a password using the current encryption. If the user ID is given
  * and the hash does not fit the current hashing algorithm, it automatically
  * updates the hash.
  *
  * @param   string   $password  The plaintext password to check.
  * @param   string   $hash      The hash to verify against.
  * @param   integer  $user_id   ID of the user if the password hash should be updated
  *
  * @return  boolean  True if the password and hash match, false otherwise
  *
  * @since   3.2.1
  */
 public static function verifyPassword($password, $hash, $user_id = 0)
 {
     $rehash = false;
     $match = false;
     // If we are using phpass
     if (strpos($hash, '$P$') === 0) {
         // Use PHPass's portable hashes with a cost of 10.
         $phpass = new PasswordHash(10, true);
         $match = $phpass->CheckPassword($password, $hash);
         $rehash = true;
     } elseif ($hash[0] == '$') {
         // JCrypt::hasStrongPasswordSupport() includes a fallback for us in the worst case
         JCrypt::hasStrongPasswordSupport();
         $match = password_verify($password, $hash);
         // Uncomment this line if we actually move to bcrypt.
         $rehash = password_needs_rehash($hash, PASSWORD_DEFAULT);
     } elseif (substr($hash, 0, 8) == '{SHA256}') {
         // Check the password
         $parts = explode(':', $hash);
         $crypt = $parts[0];
         $salt = @$parts[1];
         $testcrypt = static::getCryptedPassword($password, $salt, 'sha256', true);
         $match = JCrypt::timingSafeCompare($hash, $testcrypt);
         $rehash = true;
     } else {
         // Check the password
         $parts = explode(':', $hash);
         $crypt = $parts[0];
         $salt = @$parts[1];
         $rehash = true;
         // Compile the hash to compare
         // If the salt is empty AND there is a ':' in the original hash, we must append ':' at the end
         $testcrypt = md5($password . $salt) . ($salt ? ':' . $salt : (strpos($hash, ':') !== false ? ':' : ''));
         $match = JCrypt::timingSafeCompare($hash, $testcrypt);
     }
     // If we have a match and rehash = true, rehash the password with the current algorithm.
     if ((int) $user_id > 0 && $match && $rehash) {
         $user = new JUser($user_id);
         $user->password = static::hashPassword($password);
         $user->save();
     }
     return $match;
 }
示例#2
0
 /**
  * Verifies a password hash
  *
  * @param   string  $password  The password to verify.
  * @param   string  $hash      The password hash to check.
  *
  * @return  boolean  True if the password is valid, false otherwise.
  *
  * @since   12.2
  * @deprecated  4.0  Use PHP 5.5's native password hashing API
  */
 public function verify($password, $hash)
 {
     // Check if the hash is a blowfish hash.
     if (substr($hash, 0, 4) == '$2a$' || substr($hash, 0, 4) == '$2y$') {
         $type = '$2a$';
         if (JCrypt::hasStrongPasswordSupport()) {
             $type = '$2y$';
         }
         return password_verify($password, $hash);
     }
     // Check if the hash is an MD5 hash.
     if (substr($hash, 0, 3) == '$1$') {
         return JCrypt::timingSafeCompare(crypt($password, $hash), $hash);
     }
     // Check if the hash is a Joomla hash.
     if (preg_match('#[a-z0-9]{32}:[A-Za-z0-9]{32}#', $hash) === 1) {
         // Check the password
         $parts = explode(':', $hash);
         $salt = @$parts[1];
         // Compile the hash to compare
         // If the salt is empty AND there is a ':' in the original hash, we must append ':' at the end
         $testcrypt = md5($password . $salt) . ($salt ? ':' . $salt : (strpos($hash, ':') !== false ? ':' : ''));
         return JCrypt::timingSafeCompare($hash, $testcrypt);
     }
     return false;
 }
示例#3
0
 function plgSystemImproved_Ajax_Login(&$subject, $config)
 {
     parent::__construct($subject, $config);
     $GLOBALS['username=email'] = $this->params->get('generate', 1) < 1;
     if (isset($_REQUEST['ialCheck'])) {
         $check = JRequest::getString('ialCheck');
         $json = array('error' => '', 'msg' => '');
         switch ($check) {
             case 'ialLogin':
                 $json['field'] = 'password';
                 if (JSession::checkToken()) {
                     $user = JRequest::getVar(isset($_REQUEST['username']) ? 'username' : 'email', '');
                     $password = JRequest::getString('password', '', 'method', JREQUEST_ALLOWRAW);
                     if (!empty($password)) {
                         $result = isset($_REQUEST['username']) ? OUserHelper::getUser($user) : OUserHelper::getUserByEmail($user);
                         if ($result) {
                             $match = 0;
                             if (method_exists('JUserHelper', 'verifyPassword')) {
                                 $match = JUserHelper::verifyPassword($password, $result->password, $result->id);
                             } elseif (substr($result->password, 0, 4) == '$2y$') {
                                 $password60 = substr($result->password, 0, 60);
                                 if (JCrypt::hasStrongPasswordSupport()) {
                                     $match = password_verify($password, $password60);
                                 }
                             } else {
                                 $parts = explode(':', $result->password);
                                 $crypt = $parts[0];
                                 $salt = @$parts[1];
                                 $cryptmode = substr($result->password, 0, 8) == '{SHA256}' ? 'sha256' : 'md5-hex';
                                 $testcrypt = JUserHelper::getCryptedPassword($password, $salt, $cryptmode, false);
                                 $match = $crypt == $testcrypt || $result->password == $testcrypt;
                             }
                             if ($match) {
                                 $json['username'] = $result->username;
                             } else {
                                 $json['error'] = 'JGLOBAL_AUTH_INVALID_PASS';
                             }
                         } else {
                             $json['error'] = 'JGLOBAL_AUTH_NO_USER';
                         }
                     } else {
                         $json['error'] = 'JGLOBAL_AUTH_EMPTY_PASS_NOT_ALLOWED';
                     }
                 } else {
                     $json['error'] = 'JINVALID_TOKEN';
                 }
                 $json['msg'] = JText::_($json['error']);
                 die(json_encode($json));
             case 'data[register][username]':
             case 'jform[username]':
             case 'username':
                 $username = JRequest::getString('value');
                 if (OUserHelper::getId($username)) {
                     $json['error'] = 'COM_USERS_REGISTER_USERNAME_MESSAGE';
                 }
                 $json['msg'] = JText::_($json['error']);
                 die(json_encode($json));
             case 'data[register][email]':
             case 'jform[email1]':
             case 'email':
                 $email = JRequest::getString('value');
                 if (OUserHelper::getIdByEmail($email)) {
                     $json['error'] = 'COM_USERS_REGISTER_EMAIL1_MESSAGE';
                 }
                 $json['msg'] = JText::_($json['error']);
                 die(json_encode($json));
             case 'ialRegister':
                 // com_users
                 if ($jf = JRequest::getVar('jform', null, 'array')) {
                     if (!JSession::checkToken()) {
                         $json['error'] = 'JINVALID_TOKEN';
                         $json['msg'] = JText::_($json['error']);
                         die(json_encode($json));
                     }
                     if (!isset($jf['email1'])) {
                         $json['error'] = 'JGLOBAL_EMAIL';
                         $json['msg'] = JText::_('JGLOBAL_EMAIL') . ' ' . JText::_('JREQUIRED');
                         die(json_encode($json));
                     }
                     if (!isset($jf['password1'])) {
                         $json['error'] = 'JGLOBAL_PASSWORD';
                         $json['msg'] = JText::_('JGLOBAL_PASSWORD') . ' ' . JText::_('JREQUIRED');
                         die(json_encode($json));
                     }
                     if (!isset($jf['username'])) {
                         if ($this->params->get('generate', 1) > 0) {
                             list($jf['username']) = explode('@', $jf['email1']);
                             if (OUserHelper::getId($jf['username'])) {
                                 $jf['username'] .= OUserHelper::getNewId();
                             }
                         } else {
                             $jf['username'] = $jf['email1'];
                         }
                     }
                     if (!isset($jf['name'])) {
                         $jf['name'] = $jf['username'];
                     }
                     if (!isset($jf['email2'])) {
                         $jf['email2'] = $jf['email1'];
                     }
                     if (!isset($jf['password2'])) {
                         $jf['password2'] = $jf['password1'];
                     }
                     JRequest::setVar('jform', $jf);
                     JFactory::getApplication()->input->post->set('jform', $jf);
                 }
                 $_SESSION['ialRegister'] = $jf['username'];
                 break;
         }
     }
 }
 /**
  * This method should handle any authentication and report back to the subject
  *
  * @param   array   $credentials  Array holding the user credentials
  * @param   array   $options      Array of extra options
  * @param   object  &$response    Authentication response object
  *
  * @return  boolean
  *
  * @since   1.5
  */
 public function onUserAuthenticate($credentials, $options, &$response)
 {
     $response->type = 'Joomla';
     // Joomla does not like blank passwords
     if (empty($credentials['password'])) {
         $response->status = JAuthentication::STATUS_FAILURE;
         $response->error_message = JText::_('JGLOBAL_AUTH_EMPTY_PASS_NOT_ALLOWED');
         return false;
     }
     // Get a database object
     $db = JFactory::getDbo();
     $query = $db->getQuery(true)->select('id, password')->from('#__users')->where('username='******'username']));
     $db->setQuery($query);
     $result = $db->loadObject();
     if ($result) {
         if (substr($result->password, 0, 4) == '$2y$') {
             // BCrypt passwords are always 60 characters, but it is possible that salt is appended although non standard.
             $password60 = substr($result->password, 0, 60);
             if (JCrypt::hasStrongPasswordSupport()) {
                 $match = password_verify($credentials['password'], $password60);
             }
         } elseif (substr($result->password, 0, 8) == '{SHA256}') {
             // Check the password
             $parts = explode(':', $result->password);
             $crypt = $parts[0];
             $salt = @$parts[1];
             $testcrypt = JUserHelper::getCryptedPassword($credentials['password'], $salt, 'sha256', false);
             if ($result->password == $testcrypt) {
                 $match = true;
             }
         } else {
             // Check the password
             $parts = explode(':', $result->password);
             $crypt = $parts[0];
             $salt = @$parts[1];
             $testcrypt = JUserHelper::getCryptedPassword($credentials['password'], $salt, 'md5-hex', false);
             if ($crypt == $testcrypt) {
                 $match = true;
             }
         }
         if (isset($match) && $match === true) {
             // Bring this in line with the rest of the system
             $user = JUser::getInstance($result->id);
             $response->email = $user->email;
             $response->fullname = $user->name;
             if (JFactory::getApplication()->isAdmin()) {
                 $response->language = $user->getParam('admin_language');
             } else {
                 $response->language = $user->getParam('language');
             }
             $response->status = JAuthentication::STATUS_SUCCESS;
             $response->error_message = '';
         } else {
             // Invalid password
             $response->status = JAuthentication::STATUS_FAILURE;
             $response->error_message = JText::_('JGLOBAL_AUTH_INVALID_PASS');
         }
     } else {
         // Invalid user
         $response->status = JAuthentication::STATUS_FAILURE;
         $response->error_message = JText::_('JGLOBAL_AUTH_NO_USER');
     }
     // Check the two factor authentication
     if ($response->status == JAuthentication::STATUS_SUCCESS) {
         require_once JPATH_ADMINISTRATOR . '/components/com_users/helpers/users.php';
         $methods = UsersHelper::getTwoFactorMethods();
         if (count($methods) <= 1) {
             // No two factor authentication method is enabled
             return;
         }
         require_once JPATH_ADMINISTRATOR . '/components/com_users/models/user.php';
         $model = new UsersModelUser();
         // Load the user's OTP (one time password, a.k.a. two factor auth) configuration
         if (!array_key_exists('otp_config', $options)) {
             $otpConfig = $model->getOtpConfig($result->id);
             $options['otp_config'] = $otpConfig;
         } else {
             $otpConfig = $options['otp_config'];
         }
         // Check if the user has enabled two factor authentication
         if (empty($otpConfig->method) || $otpConfig->method == 'none') {
             // Warn the user if he's using a secret code but he has not
             // enabed two factor auth in his account.
             if (!empty($credentials['secretkey'])) {
                 try {
                     $app = JFactory::getApplication();
                     $this->loadLanguage();
                     $app->enqueueMessage(JText::_('PLG_AUTH_JOOMLA_ERR_SECRET_CODE_WITHOUT_TFA'), 'warning');
                 } catch (Exception $exc) {
                     // This happens when we are in CLI mode. In this case
                     // no warning is issued
                     return;
                 }
             }
             return;
         }
         // Load the Joomla! RAD layer
         if (!defined('FOF_INCLUDED')) {
             include_once JPATH_LIBRARIES . '/fof/include.php';
         }
         // Try to validate the OTP
         FOFPlatform::getInstance()->importPlugin('twofactorauth');
         $otpAuthReplies = FOFPlatform::getInstance()->runPlugins('onUserTwofactorAuthenticate', array($credentials, $options));
         $check = false;
         /*
          * This looks like noob code but DO NOT TOUCH IT and do not convert
          * to in_array(). During testing in_array() inexplicably returned
          * null when the OTEP begins with a zero! o_O
          */
         if (!empty($otpAuthReplies)) {
             foreach ($otpAuthReplies as $authReply) {
                 $check = $check || $authReply;
             }
         }
         // Fall back to one time emergency passwords
         if (!$check) {
             // Did the user use an OTEP instead?
             if (empty($otpConfig->otep)) {
                 if (empty($otpConfig->method) || $otpConfig->method == 'none') {
                     // Two factor authentication is not enabled on this account.
                     // Any string is assumed to be a valid OTEP.
                     return true;
                 } else {
                     /*
                      * Two factor authentication enabled and no OTEPs defined. The
                      * user has used them all up. Therefore anything he enters is
                      * an invalid OTEP.
                      */
                     return false;
                 }
             }
             // Clean up the OTEP (remove dashes, spaces and other funny stuff
             // our beloved users may have unwittingly stuffed in it)
             $otep = $credentials['secretkey'];
             $otep = filter_var($otep, FILTER_SANITIZE_NUMBER_INT);
             $otep = str_replace('-', '', $otep);
             $check = false;
             // Did we find a valid OTEP?
             if (in_array($otep, $otpConfig->otep)) {
                 // Remove the OTEP from the array
                 $otpConfig->otep = array_diff($otpConfig->otep, array($otep));
                 $model->setOtpConfig($result->id, $otpConfig);
                 // Return true; the OTEP was a valid one
                 $check = true;
             }
         }
         if (!$check) {
             $response->status = JAuthentication::STATUS_FAILURE;
             $response->error_message = JText::_('JGLOBAL_AUTH_INVALID_SECRETKEY');
         }
     }
 }
示例#5
0
 /**
  * Verifies a password hash
  *
  * @param   string  $password  The password to verify.
  * @param   string  $hash      The password hash to check.
  *
  * @return  boolean  True if the password is valid, false otherwise.
  *
  * @since   12.2
  * @deprecated  4.0  Use PHP 5.5's native password hashing API
  */
 public function verify($password, $hash)
 {
     // Check if the hash is a blowfish hash.
     if (substr($hash, 0, 4) == '$2a$' || substr($hash, 0, 4) == '$2y$') {
         $type = '$2a$';
         if (JCrypt::hasStrongPasswordSupport()) {
             $type = '$2y$';
         }
         $hash = $type . substr($hash, 4);
         return crypt($password, $hash) === $hash;
     }
     // Check if the hash is an MD5 hash.
     if (substr($hash, 0, 3) == '$1$') {
         return crypt($password, $hash) === $hash;
     }
     // Check if the hash is a Joomla hash.
     if (preg_match('#[a-z0-9]{32}:[A-Za-z0-9]{32}#', $hash) === 1) {
         return md5($password . substr($hash, 33)) === substr($hash, 0, 32);
     }
     return false;
 }
示例#6
0
 /**
  * Method to unlock a password protected category
  *
  * @param   int     $catid    ID of the category to unlock
  * @param   string  $password Password of the category to check
  * @return  boolean True on success, false otherwise
  * @since   3.1
  */
 public function unlock($catid, $password)
 {
     $query = $this->_db->getQuery(true)->select('cid, password')->from($this->_db->quoteName(_JOOM_TABLE_CATEGORIES))->where('cid = ' . (int) $catid);
     $this->_db->setQuery($query);
     if (!($category = $this->_db->loadObject())) {
         throw new Exception($this->_db->getErrorMsg());
     }
     if (!$category->password) {
         throw new Exception('Category is not protected.');
     }
     $match = false;
     if (substr($category->password, 0, 4) == '$2y$') {
         // BCrypt passwords are always 60 characters, but it is possible that salt is appended although non standard.
         $password60 = substr($category->password, 0, 60);
         if (JCrypt::hasStrongPasswordSupport()) {
             $match = password_verify($password, $password60);
         }
     } else {
         if (substr($category->password, 0, 8) == '{SHA256}') {
             // Check the password
             $parts = explode(':', $category->password);
             $crypt = $parts[0];
             $salt = @$parts[1];
             $testcrypt = JUserHelper::getCryptedPassword($password, $salt, 'sha256', false);
             if ($category->password == $testcrypt) {
                 $match = true;
             }
         } else {
             // Check the password
             $parts = explode(':', $category->password);
             $crypt = $parts[0];
             $salt = @$parts[1];
             $testcrypt = JUserHelper::getCryptedPassword($password, $salt, 'md5-hex', false);
             if ($crypt == $testcrypt) {
                 $match = true;
             }
         }
     }
     if (!$match) {
         throw new Exception(JText::_('COM_JOOMGALLERY_CATEGORY_WRONG_PASSWORD'));
     }
     $categories = $this->_mainframe->getUserState('joom.unlockedCategories', array(0));
     $categories = array_unique(array_merge($categories, array($catid)));
     $this->_mainframe->setUserState('joom.unlockedCategories', $categories);
     return true;
 }
 /**
  * Method to create the root user for the site
  *
  * @param   object  $options  The session options
  *
  * @return  boolean  True on success
  *
  * @since   3.1
  */
 private function _createRootUser($options)
 {
     // Get the application
     /* @var InstallationApplicationWeb $app */
     $app = JFactory::getApplication();
     // Get a database object.
     try {
         $db = InstallationHelperDatabase::getDBO($options->db_type, $options->db_host, $options->db_user, $options->db_pass, $options->db_name, $options->db_prefix);
     } catch (RuntimeException $e) {
         $app->enqueueMessage(JText::sprintf('INSTL_ERROR_CONNECT_DB', $e->getMessage()), 'notice');
         return false;
     }
     $useStrongPasswords = JCrypt::hasStrongPasswordSupport();
     if ($useStrongPasswords) {
         $cryptpass = JUserHelper::getCryptedPassword($options->admin_password);
     } else {
         $salt = JUserHelper::genRandomPassword(16);
         //$cryptpass = JUserHelper::getCryptedPassword($options->admin_password, $salt, 'sha256') . ':' . $salt;
         $cryptpass = JUserHelper::getCryptedPassword($options->admin_password, $salt, 'sha256');
     }
     // Take the admin user id
     $userId = InstallationModelDatabase::getUserId();
     // We don't need the randUserId in the session any longer, let's remove it
     InstallationModelDatabase::resetRandUserId();
     // Create the admin user
     date_default_timezone_set('UTC');
     $installdate = date('Y-m-d H:i:s');
     $nullDate = $db->getNullDate();
     // Sqlsrv change
     $query = $db->getQuery(true)->select($db->quoteName('id'))->from($db->quoteName('#__users'))->where($db->quoteName('id') . ' = ' . $db->quote($userId));
     $db->setQuery($query);
     if ($db->loadResult()) {
         $query->clear()->update($db->quoteName('#__users'))->set($db->quoteName('name') . ' = ' . $db->quote('Super User'))->set($db->quoteName('username') . ' = ' . $db->quote($options->admin_user))->set($db->quoteName('email') . ' = ' . $db->quote($options->admin_email))->set($db->quoteName('password') . ' = ' . $db->quote($cryptpass))->set($db->quoteName('block') . ' = 0')->set($db->quoteName('sendEmail') . ' = 1')->set($db->quoteName('registerDate') . ' = ' . $db->quote($installdate))->set($db->quoteName('lastvisitDate') . ' = ' . $db->quote($nullDate))->set($db->quoteName('activation') . ' = ' . $db->quote('0'))->set($db->quoteName('params') . ' = ' . $db->quote(''))->where($db->quoteName('id') . ' = ' . $db->quote($userId));
     } else {
         $columns = array($db->quoteName('id'), $db->quoteName('name'), $db->quoteName('username'), $db->quoteName('email'), $db->quoteName('password'), $db->quoteName('block'), $db->quoteName('sendEmail'), $db->quoteName('registerDate'), $db->quoteName('lastvisitDate'), $db->quoteName('activation'), $db->quoteName('params'));
         $query->clear()->insert('#__users', true)->columns($columns)->values($db->quote($userId) . ', ' . $db->quote('Super User') . ', ' . $db->quote($options->admin_user) . ', ' . $db->quote($options->admin_email) . ', ' . $db->quote($cryptpass) . ', ' . $db->quote('0') . ', ' . $db->quote('1') . ', ' . $db->quote($installdate) . ', ' . $db->quote($nullDate) . ', ' . $db->quote('0') . ', ' . $db->quote(''));
     }
     $db->setQuery($query);
     try {
         $db->execute();
     } catch (RuntimeException $e) {
         $app->enqueueMessage($e->getMessage(), 'notice');
         return false;
     }
     // Map the super admin to the Super Admin Group
     $query->clear()->select($db->quoteName('user_id'))->from($db->quoteName('#__user_usergroup_map'))->where($db->quoteName('user_id') . ' = ' . $db->quote($userId));
     $db->setQuery($query);
     if ($db->loadResult()) {
         $query->clear()->update($db->quoteName('#__user_usergroup_map'))->set($db->quoteName('user_id') . ' = ' . $db->quote($userId))->set($db->quoteName('group_id') . ' = 8');
     } else {
         $query->clear()->insert($db->quoteName('#__user_usergroup_map'), false)->columns(array($db->quoteName('user_id'), $db->quoteName('group_id')))->values($db->quote($userId) . ', 8');
     }
     $db->setQuery($query);
     try {
         $db->execute();
     } catch (RuntimeException $e) {
         $app->enqueueMessage($e->getMessage(), 'notice');
         return false;
     }
     return true;
 }
 /**
  * This method should handle any authentication and report back to the subject
  *
  * @param   array   $credentials  Array holding the user credentials
  * @param   array   $options      Array of extra options
  * @param   object  &$response    Authentication response object
  *
  * @return  boolean
  *
  * @since   3.2
  */
 public function onUserAuthenticate($credentials, $options, &$response)
 {
     // No remember me for admin
     if ($this->app->isAdmin()) {
         return false;
     }
     JLoader::register('JAuthentication', JPATH_LIBRARIES . '/joomla/user/authentication.php');
     $response->type = 'Cookie';
     // We need to validate the cookie data because there may be no Remember Me plugin to do it.
     // Create the cookie name and data.
     $rememberArray = JUserHelper::getRememberCookieData();
     if ($rememberArray == false) {
         return false;
     }
     list($privateKey, $series, $uastring) = $rememberArray;
     // Find the matching record if it exists.
     $query = $this->db->getQuery(true)->select($this->db->quoteName(array('user_id', 'token', 'series', 'time', 'invalid')))->from($this->db->quoteName('#__user_keys'))->where($this->db->quoteName('series') . ' = ' . $this->db->quote(base64_encode($series)))->where($this->db->quoteName('uastring') . ' = ' . $this->db->quote($uastring))->order($this->db->quoteName('time') . ' DESC');
     $results = $this->db->setQuery($query)->loadObjectList();
     $countResults = count($results);
     if ($countResults !== 1) {
         $response->status = JAuthentication::STATUS_FAILURE;
         return;
     } else {
         if (substr($results[0]->token, 0, 4) === '$2y$') {
             if (JCrypt::hasStrongPasswordSupport()) {
                 $match = password_verify($privateKey, $results[0]->token);
             }
         } else {
             if (JCrypt::timingSafeCompare($results[0]->token, $privateKey)) {
                 $match = true;
             }
         }
         if (empty($match)) {
             JUserHelper::invalidateCookie($results[0]->user_id, $uastring);
             JLog::add(JText::sprintf('PLG_SYSTEM_REMEMBER_ERROR_LOG_LOGIN_FAILED', $user->username), JLog::WARNING, 'security');
             $response->status = JAuthentication::STATUS_FAILURE;
             return false;
         }
     }
     // Set cookie params.
     if (!empty($options['lifetime']) && !empty($options['length']) && !empty($options['secure'])) {
         $response->lifetime = $options['lifetime'];
         $response->length = $options['length'];
         $response->secure = $options['secure'];
     }
     // Make sure there really is a user with this name and get the data for the session.
     $query = $this->db->getQuery(true)->select($this->db->quoteName(array('id', 'username', 'password')))->from($this->db->quoteName('#__users'))->where($this->db->quoteName('username') . ' = ' . $this->db->quote($credentials['username']));
     $result = $this->db->setQuery($query)->loadObject();
     if ($result) {
         // Bring this in line with the rest of the system
         $user = JUser::getInstance($result->id);
         $cookieName = JUserHelper::getShortHashedUserAgent();
         // If there is no cookie, bail out
         if (!$this->app->input->cookie->get($cookieName)) {
             return;
         }
         // Set response data.
         $response->username = $result->username;
         $response->email = $user->email;
         $response->fullname = $user->name;
         $response->password = $result->password;
         $response->language = $user->getParam('language');
         // Set response status.
         $response->status = JAuthentication::STATUS_SUCCESS;
         $response->error_message = '';
     } else {
         $response->status = JAuthentication::STATUS_FAILURE;
         $response->error_message = JText::_('JGLOBAL_AUTH_NO_USER');
     }
 }
 /**
  * Remember me method to run onAfterInitialise
  *
  * @return  boolean
  *
  * @since   1.5
  * @throws  InvalidArgumentException
  */
 public function onAfterInitialise()
 {
     // No remember me for admin
     if ($this->app->isAdmin()) {
         return false;
     }
     $user = JFactory::getUser();
     $this->app->rememberCookieLifetime = $this->lifetime;
     $this->app->rememberCookieSecure = $this->secure;
     $this->app->rememberCookieLength = $this->length;
     // Check for a cookie
     if ($user->get('guest') == 1) {
         // Create the cookie name and data
         $rememberArray = JUserHelper::getRememberCookieData();
         if ($rememberArray !== false) {
             if (count($rememberArray) != 3) {
                 // Destroy the cookie in the browser.
                 $this->app->input->cookie->set(end($rememberArray), false, time() - 42000, $this->app->get('cookie_path'), $this->app->get('cookie_domain'));
                 JLog::add('Invalid cookie detected.', JLog::WARNING, 'error');
                 return false;
             }
             list($privateKey, $series, $uastring) = $rememberArray;
             if (!JUserHelper::clearExpiredTokens($this)) {
                 JLog::add('Error in deleting expired cookie tokens.', JLog::WARNING, 'error');
             }
             // Find the matching record if it exists
             $query = $this->db->getQuery(true)->select($this->db->quoteName(array('user_id', 'token', 'series', 'time', 'invalid')))->from($this->db->quoteName('#__user_keys'))->where($this->db->quoteName('series') . ' = ' . $this->db->quote(base64_encode($series)))->where($this->db->quoteName('uastring') . ' = ' . $this->db->quote($uastring))->order($this->db->quoteName('time') . ' DESC');
             $results = $this->db->setQuery($query)->loadObjectList();
             $countResults = count($results);
             // We have a user but a cookie that is not in the database, or it is invalid. This is a possible attack, so invalidate everything.
             if (($countResults === 0 || $results[0]->invalid != 0) && !empty($results[0]->user_id)) {
                 JUserHelper::invalidateCookie($results[0]->user_id, $uastring);
                 JLog::add(JText::sprintf('PLG_SYSTEM_REMEMBER_ERROR_LOG_INVALIDATED_COOKIES', $user->username), JLog::WARNING, 'security');
                 // Possibly e-mail user and admin here.
                 return false;
             }
             // We have a user with one cookie with a valid series and a corresponding record in the database.
             if ($countResults === 1) {
                 if (substr($results[0]->token, 0, 4) === '$2y$') {
                     if (JCrypt::hasStrongPasswordSupport()) {
                         $match = password_verify($privateKey, $results[0]->token);
                     }
                 } else {
                     if (JCrypt::timingSafeCompare($results[0]->token, $privateKey)) {
                         $match = true;
                     }
                 }
                 if (empty($match)) {
                     JUserHelper::invalidateCookie($results[0]->user_id, $uastring);
                     JLog::add(JText::sprintf('PLG_SYSTEM_REMEMBER_ERROR_LOG_LOGIN_FAILED', $user->username), JLog::WARNING, 'security');
                     return false;
                 }
                 // Set up the credentials array to pass to onUserAuthenticate
                 $credentials = array('username' => $results[0]->user_id);
                 return $this->app->login($credentials, array('silent' => true, 'lifetime' => $this->lifetime, 'secure' => $this->secure, 'length' => $this->length));
             }
         }
     }
     return false;
 }
 /**
  * Formats a password using the current encryption.
  *
  * @param   string   $plaintext     The plaintext password to encrypt.
  * @param   string   $salt          The salt to use to encrypt the password. []
  *                                  If not present, a new salt will be
  *                                  generated.
  * @param   string   $encryption    The kind of password encryption to use.
  *                                  Defaults to md5-hex.
  * @param   boolean  $show_encrypt  Some password systems prepend the kind of
  *                                  encryption to the crypted password ({SHA},
  *                                  etc). Defaults to false.
  *
  * @return  string  The encrypted password.
  *
  * @since   11.1
  * @note    In Joomla! CMS 3.2 the default encrytion has been changed to bcrypt. When PHP 5.5 is the minimum
  *          supported version it will be changed to the PHP PASSWORD_DEFAULT constant.
  */
 public static function getCryptedPassword($plaintext, $salt = '', $encryption = 'bcrypt', $show_encrypt = false)
 {
     $app = JFactory::getApplication();
     if ($app->getClientId() != 2) {
         $joomlaPluginEnabled = JPluginHelper::isEnabled('user', 'joomla');
     }
     // The Joomla user plugin allows you to use weaker passwords if necessary.
     if (!empty($joomlaPluginEnabled)) {
         JPluginHelper::importPlugin('user', 'joomla');
         $userPlugin = JPluginHelper::getPlugin('user', 'joomla');
         $userPluginParams = new JRegistry($userPlugin->params);
         PlgUserJoomla::setDefaultEncryption($userPluginParams);
     }
     // Not all controllers check the length, although they should to avoid DOS attacks.
     // The maximum password length for bcrypt is 55:
     if (strlen($plaintext) > 55) {
         $app->enqueueMessage(JText::_('JLIB_USER_ERROR_PASSWORD_TOO_LONG'), 'error');
         return false;
     }
     // Get the salt to use.
     if (empty($salt)) {
         $salt = self::getSalt($encryption, $salt, $plaintext);
     }
     // Encrypt the password.
     switch ($encryption) {
         case 'plain':
             return $plaintext;
         case 'sha':
             $encrypted = base64_encode(mhash(MHASH_SHA1, $plaintext));
             return $show_encrypt ? '{SHA}' . $encrypted : $encrypted;
         case 'crypt':
         case 'crypt-des':
         case 'crypt-md5':
         case 'crypt-blowfish':
             return ($show_encrypt ? '{crypt}' : '') . crypt($plaintext, $salt);
         case 'md5-base64':
             $encrypted = base64_encode(mhash(MHASH_MD5, $plaintext));
             return $show_encrypt ? '{MD5}' . $encrypted : $encrypted;
         case 'ssha':
             $encrypted = base64_encode(mhash(MHASH_SHA1, $plaintext . $salt) . $salt);
             return $show_encrypt ? '{SSHA}' . $encrypted : $encrypted;
         case 'smd5':
             $encrypted = base64_encode(mhash(MHASH_MD5, $plaintext . $salt) . $salt);
             return $show_encrypt ? '{SMD5}' . $encrypted : $encrypted;
         case 'aprmd5':
             $length = strlen($plaintext);
             $context = $plaintext . '$apr1$' . $salt;
             $binary = self::_bin(md5($plaintext . $salt . $plaintext));
             for ($i = $length; $i > 0; $i -= 16) {
                 $context .= substr($binary, 0, $i > 16 ? 16 : $i);
             }
             for ($i = $length; $i > 0; $i >>= 1) {
                 $context .= $i & 1 ? chr(0) : $plaintext[0];
             }
             $binary = self::_bin(md5($context));
             for ($i = 0; $i < 1000; $i++) {
                 $new = $i & 1 ? $plaintext : substr($binary, 0, 16);
                 if ($i % 3) {
                     $new .= $salt;
                 }
                 if ($i % 7) {
                     $new .= $plaintext;
                 }
                 $new .= $i & 1 ? substr($binary, 0, 16) : $plaintext;
                 $binary = self::_bin(md5($new));
             }
             $p = array();
             for ($i = 0; $i < 5; $i++) {
                 $k = $i + 6;
                 $j = $i + 12;
                 if ($j == 16) {
                     $j = 5;
                 }
                 $p[] = self::_toAPRMD5(ord($binary[$i]) << 16 | ord($binary[$k]) << 8 | ord($binary[$j]), 5);
             }
             return '$apr1$' . $salt . '$' . implode('', $p) . self::_toAPRMD5(ord($binary[11]), 3);
         case 'md5-hex':
             $encrypted = $salt ? md5($plaintext . $salt) : md5($plaintext);
             return $show_encrypt ? '{MD5}' . $encrypted : $encrypted;
         case 'sha256':
             $encrypted = $salt ? hash('sha256', $plaintext . $salt) . ':' . $salt : hash('sha256', $plaintext);
             return $show_encrypt ? '{SHA256}' . $encrypted : '{SHA256}' . $encrypted;
             // 'bcrypt' is the default case starting in CMS 3.2.
         // 'bcrypt' is the default case starting in CMS 3.2.
         case 'bcrypt':
         default:
             $useStrongEncryption = JCrypt::hasStrongPasswordSupport();
             if ($useStrongEncryption === true) {
                 $encrypted = password_hash($plaintext, PASSWORD_BCRYPT);
                 if (!$encrypted) {
                     // Something went wrong fall back to sha256.
                     return static::getCryptedPassword($plaintext, '', 'sha256', false);
                 }
                 return $show_encrypt ? '{BCRYPT}' . $encrypted : $encrypted;
             } else {
                 // BCrypt isn't available but we want strong passwords, fall back to sha256.
                 return static::getCryptedPassword($plaintext, '', 'sha256', false);
             }
     }
 }
示例#11
0
 public function verifyUserPassword($userid, $password)
 {
     $db = Jfactory::getDbo();
     $query = $db->getQuery(true)->select('password')->from('#__users')->where('id=' . $db->quote($userid));
     $db->setQuery($query);
     $result = $db->loadResult();
     $match = false;
     if (!empty($result)) {
         if (strpos($result, '$P$') === 0) {
             $phpass = new PasswordHash(10, true);
             $match = $phpass->CheckPassword($password, $result);
         } elseif (substr($result, 0, 4) == '$2y$') {
             $password60 = substr($result, 0, 60);
             if (JCrypt::hasStrongPasswordSupport()) {
                 $match = password_verify($password, $password60);
             }
         } elseif (substr($result, 0, 8) == '{SHA256}') {
             $parts = explode(':', $result);
             $crypt = $parts[0];
             $salt = @$parts[1];
             $testcrypt = JUserHelper::getCryptedPassword($password, $salt, 'sha256', false);
             $match = $result == $testcrypt;
         } else {
             $parts = explode(':', $result);
             $crypt = $parts[0];
             $salt = @$parts[1];
             $testcrypt = JUserHelper::getCryptedPassword($password, $salt, 'md5-hex', false);
             $match = $crypt == $testcrypt;
         }
     }
     return $match;
 }
 /**
  * This method should handle any login logic and report back to the subject
  *
  * @param   array  $user     Holds the user data
  * @param   array  $options  Array holding options (remember, autoregister, group)
  *
  * @return  boolean  True on success
  *
  * @since   1.5
  */
 public function onUserLogin($user, $options = array())
 {
     $instance = $this->_getUser($user, $options);
     // If _getUser returned an error, then pass it back.
     if ($instance instanceof Exception) {
         return false;
     }
     // If the user is blocked, redirect with an error
     if ($instance->get('block') == 1) {
         $this->app->enqueueMessage(JText::_('JERROR_NOLOGIN_BLOCKED'), 'warning');
         return false;
     }
     // Authorise the user based on the group information
     if (!isset($options['group'])) {
         $options['group'] = 'USERS';
     }
     // Check the user can login.
     $result = $instance->authorise($options['action']);
     if (!$result) {
         $this->app->enqueueMessage(JText::_('JERROR_LOGIN_DENIED'), 'warning');
         return false;
     }
     // Mark the user as logged in
     $instance->set('guest', 0);
     // If the user has an outdated hash, update it.
     if (substr($user['password'], 0, 4) != '$2y$' && $this->useStrongEncryption && JCrypt::hasStrongPasswordSupport() == true) {
         if (strlen($user['password']) > 55) {
             $user['password'] = substr($user['password'], 0, 55);
             JFactory::getApplication()->enqueueMessage(JText::_('JLIB_USER_ERROR_PASSWORD_TRUNCATED'), 'notice');
         }
         $instance->password = password_hash($user['password'], PASSWORD_BCRYPT);
         $instance->save();
     }
     // Register the needed session variables
     $session = JFactory::getSession();
     $session->set('user', $instance);
     // Check to see the the session already exists.
     $this->app->checkSession();
     // Update the user related fields for the Joomla sessions table.
     $query = $this->db->getQuery(true)->update($this->db->quoteName('#__session'))->set($this->db->quoteName('guest') . ' = ' . $this->db->quote($instance->guest))->set($this->db->quoteName('username') . ' = ' . $this->db->quote($instance->username))->set($this->db->quoteName('userid') . ' = ' . (int) $instance->id)->where($this->db->quoteName('session_id') . ' = ' . $this->db->quote($session->getId()));
     $this->db->setQuery($query)->execute();
     // Hit the user last visit field
     $instance->setLastVisit();
     return true;
 }