コード例 #1
0
ファイル: SSI.php プロジェクト: scripple/Elkarte
/**
 * Check the passed id_member/password.
 *  If $is_username is true, treats $id as a username.
 *
 * @param int|null $id
 * @param string|null $password
 * @param bool $is_username
 */
function ssi_checkPassword($id = null, $password = null, $is_username = false)
{
    // If $id is null, this was most likely called from a query string and should do nothing.
    if ($id === null) {
        return;
    }
    require_once SUBSDIR . '/Auth.subs.php';
    $member = loadExistingMember($id, !$is_username);
    return validateLoginPassword($password, $member['passwd'], $member['member_name']) && $member['is_activated'] == 1;
}
コード例 #2
0
ファイル: Auth.controller.php プロジェクト: KeiroD/Elkarte
 /**
  * Actually logs you in.
  *
  * What it does:
  * - checks credentials and checks that login was successful.
  * - it employs protection against a specific IP or user trying to brute force
  *   a login to an account.
  * - upgrades password encryption on login, if necessary.
  * - after successful login, redirects you to $_SESSION['login_url'].
  * - accessed from ?action=login2, by forms.
  *
  * On error, uses the same templates action_login() uses.
  */
 public function action_login2()
 {
     global $txt, $scripturl, $user_info, $user_settings, $modSettings, $context, $sc;
     // Load cookie authentication and all stuff.
     require_once SUBSDIR . '/Auth.subs.php';
     // Beyond this point you are assumed to be a guest trying to login.
     if (!$user_info['is_guest']) {
         redirectexit();
     }
     // Are you guessing with a script?
     checkSession('post');
     validateToken('login');
     spamProtection('login');
     // Set the login_url if it's not already set (but careful not to send us to an attachment).
     if (empty($_SESSION['login_url']) && isset($_SESSION['old_url']) && strpos($_SESSION['old_url'], 'dlattach') === false && preg_match('~(board|topic)[=,]~', $_SESSION['old_url']) != 0 || isset($_GET['quicklogin']) && isset($_SESSION['old_url']) && strpos($_SESSION['old_url'], 'login') === false) {
         $_SESSION['login_url'] = $_SESSION['old_url'];
     }
     // Been guessing a lot, haven't we?
     if (isset($_SESSION['failed_login']) && $_SESSION['failed_login'] >= $modSettings['failed_login_threshold'] * 3) {
         fatal_lang_error('login_threshold_fail', 'critical');
     }
     // Set up the cookie length.  (if it's invalid, just fall through and use the default.)
     if (isset($_POST['cookieneverexp']) || !empty($_POST['cookielength']) && $_POST['cookielength'] == -1) {
         $modSettings['cookieTime'] = 3153600;
     } elseif (!empty($_POST['cookielength']) && ($_POST['cookielength'] >= 1 || $_POST['cookielength'] <= 525600)) {
         $modSettings['cookieTime'] = (int) $_POST['cookielength'];
     }
     loadLanguage('Login');
     // Load the template stuff
     loadTemplate('Login');
     loadJavascriptFile('sha256.js', array('defer' => true));
     $context['sub_template'] = 'login';
     // Set up the default/fallback stuff.
     $context['default_username'] = isset($_POST['user']) ? preg_replace('~&amp;#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', htmlspecialchars($_POST['user'], ENT_COMPAT, 'UTF-8')) : '';
     $context['default_password'] = '';
     $context['never_expire'] = $modSettings['cookieTime'] == 525600 || $modSettings['cookieTime'] == 3153600;
     $context['login_errors'] = array($txt['error_occurred']);
     $context['page_title'] = $txt['login'];
     // Add the login chain to the link tree.
     $context['linktree'][] = array('url' => $scripturl . '?action=login', 'name' => $txt['login']);
     // This is an OpenID login. Let's validate...
     if (!empty($_POST['openid_identifier']) && !empty($modSettings['enableOpenID'])) {
         require_once SUBSDIR . '/OpenID.subs.php';
         $open_id = new OpenID();
         if ($open_id->validate($_POST['openid_identifier']) !== 'no_data') {
             return $open_id;
         } else {
             $context['login_errors'] = array($txt['openid_not_found']);
             return;
         }
     }
     // You forgot to type your username, dummy!
     if (!isset($_POST['user']) || $_POST['user'] == '') {
         $context['login_errors'] = array($txt['need_username']);
         return;
     }
     // No one needs a username that long, plus we only support 80 chars in the db
     if (Util::strlen($_POST['user']) > 80) {
         $_POST['user'] = Util::substr($_POST['user'], 0, 80);
     }
     // Can't use a password > 64 characters sorry, to long and only good for a DoS attack
     // Plus we expect a 64 character one from SHA-256
     if (isset($_POST['passwrd']) && strlen($_POST['passwrd']) > 64 || isset($_POST['hash_passwrd']) && strlen($_POST['hash_passwrd']) > 64) {
         $context['login_errors'] = array($txt['improper_password']);
         return;
     }
     // Hmm... maybe 'admin' will login with no password. Uhh... NO!
     if ((!isset($_POST['passwrd']) || $_POST['passwrd'] == '') && (!isset($_POST['hash_passwrd']) || strlen($_POST['hash_passwrd']) != 64)) {
         $context['login_errors'] = array($txt['no_password']);
         return;
     }
     // No funky symbols either.
     if (preg_match('~[<>&"\'=\\\\]~', preg_replace('~(&#(\\d{1,7}|x[0-9a-fA-F]{1,6});)~', '', $_POST['user'])) != 0) {
         $context['login_errors'] = array($txt['error_invalid_characters_username']);
         return;
     }
     // Are we using any sort of integration to validate the login?
     if (in_array('retry', call_integration_hook('integrate_validate_login', array($_POST['user'], isset($_POST['hash_passwrd']) && strlen($_POST['hash_passwrd']) == 40 ? $_POST['hash_passwrd'] : null, $modSettings['cookieTime'])), true)) {
         $context['login_errors'] = array($txt['login_hash_error']);
         $context['disable_login_hashing'] = true;
         return;
     }
     // Find them... if we can
     $user_settings = loadExistingMember($_POST['user']);
     // Let them try again, it didn't match anything...
     if (empty($user_settings)) {
         $context['login_errors'] = array($txt['username_no_exist']);
         return;
     }
     // Figure out if the password is using Elk's encryption - if what they typed is right.
     if (isset($_POST['hash_passwrd']) && strlen($_POST['hash_passwrd']) === 64) {
         // Challenge what was passed
         $valid_password = validateLoginPassword($_POST['hash_passwrd'], $user_settings['passwd']);
         // Let them in
         if ($valid_password) {
             $sha_passwd = $_POST['hash_passwrd'];
             $valid_password = true;
         } elseif (preg_match('/^[0-9a-f]{40}$/i', $user_settings['passwd']) && isset($_POST['old_hash_passwrd']) && $_POST['old_hash_passwrd'] === hash('sha1', $user_settings['passwd'] . $sc)) {
             // Old password passed, turn off hashing and ask for it again so we can update the db to something more secure.
             $context['login_errors'] = array($txt['login_hash_error']);
             $context['disable_login_hashing'] = true;
             unset($user_settings);
             return;
         } else {
             // Don't allow this!
             validatePasswordFlood($user_settings['id_member'], $user_settings['passwd_flood']);
             $_SESSION['failed_login'] = isset($_SESSION['failed_login']) ? $_SESSION['failed_login'] + 1 : 1;
             // To many tries, maybe they need a reminder
             if ($_SESSION['failed_login'] >= $modSettings['failed_login_threshold']) {
                 redirectexit('action=reminder');
             } else {
                 log_error($txt['incorrect_password'] . ' - <span class="remove">' . $user_settings['member_name'] . '</span>', 'user');
                 // Wrong password, lets enable plain text responses in case form hashing is causing problems
                 $context['disable_login_hashing'] = true;
                 $context['login_errors'] = array($txt['incorrect_password']);
                 unset($user_settings);
                 return;
             }
         }
     } else {
         // validateLoginPassword will hash this like the form normally would and check its valid
         $sha_passwd = $_POST['passwrd'];
         $valid_password = validateLoginPassword($sha_passwd, $user_settings['passwd'], $user_settings['member_name']);
     }
     // Bad password!  Thought you could fool the database?!
     if ($valid_password === false) {
         // Let's be cautious, no hacking please. thanx.
         validatePasswordFlood($user_settings['id_member'], $user_settings['passwd_flood']);
         // Maybe we were too hasty... let's try some other authentication methods.
         $other_passwords = $this->_other_passwords($user_settings);
         // Whichever encryption it was using, let's make it use ElkArte's now ;).
         if (in_array($user_settings['passwd'], $other_passwords)) {
             $user_settings['passwd'] = validateLoginPassword($sha_passwd, '', '', true);
             $user_settings['password_salt'] = substr(md5(mt_rand()), 0, 4);
             // Update the password hash and set up the salt.
             updateMemberData($user_settings['id_member'], array('passwd' => $user_settings['passwd'], 'password_salt' => $user_settings['password_salt'], 'passwd_flood' => ''));
         } else {
             // They've messed up again - keep a count to see if they need a hand.
             $_SESSION['failed_login'] = isset($_SESSION['failed_login']) ? $_SESSION['failed_login'] + 1 : 1;
             // Hmm... don't remember it, do you?  Here, try the password reminder ;).
             if ($_SESSION['failed_login'] >= $modSettings['failed_login_threshold']) {
                 redirectexit('action=reminder');
             } else {
                 // Log an error so we know that it didn't go well in the error log.
                 log_error($txt['incorrect_password'] . ' - <span class="remove">' . $user_settings['member_name'] . '</span>', 'user');
                 $context['login_errors'] = array($txt['incorrect_password']);
                 return;
             }
         }
     } elseif (!empty($user_settings['passwd_flood'])) {
         // Let's be sure they weren't a little hacker.
         validatePasswordFlood($user_settings['id_member'], $user_settings['passwd_flood'], true);
         // If we got here then we can reset the flood counter.
         updateMemberData($user_settings['id_member'], array('passwd_flood' => ''));
     }
     // Correct password, but they've got no salt; fix it!
     if ($user_settings['password_salt'] == '') {
         $user_settings['password_salt'] = substr(md5(mt_rand()), 0, 4);
         updateMemberData($user_settings['id_member'], array('password_salt' => $user_settings['password_salt']));
     }
     // Check their activation status.
     if (!checkActivation()) {
         return;
     }
     doLogin();
 }