Example #1
0
function Login2()
{
    global $txt, $scripturl, $user_info, $user_settings, $smcFunc;
    global $cookiename, $maintenance, $modSettings, $context, $sc, $sourcedir;
    // Load cookie authentication stuff.
    require_once $sourcedir . '/Subs-Auth.php';
    if (isset($_GET['sa']) && $_GET['sa'] == 'salt' && !$user_info['is_guest']) {
        if (isset($_COOKIE[$cookiename]) && preg_match('~^a:[34]:\\{i:0;(i:\\d{1,6}|s:[1-8]:"\\d{1,8}");i:1;s:(0|40):"([a-fA-F0-9]{40})?";i:2;[id]:\\d{1,14};(i:3;i:\\d;)?\\}$~', $_COOKIE[$cookiename]) === 1) {
            list(, , $timeout) = @unserialize($_COOKIE[$cookiename]);
        } elseif (isset($_SESSION['login_' . $cookiename])) {
            list(, , $timeout) = @unserialize($_SESSION['login_' . $cookiename]);
        } else {
            trigger_error('Login2(): Cannot be logged in without a session or cookie', E_USER_ERROR);
        }
        $user_settings['password_salt'] = substr(md5(mt_rand()), 0, 4);
        updateMemberData($user_info['id'], array('password_salt' => $user_settings['password_salt']));
        setLoginCookie($timeout - time(), $user_info['id'], sha1($user_settings['passwd'] . $user_settings['password_salt']));
        redirectexit('action=login2;sa=check;member=' . $user_info['id'], $context['server']['needs_login_fix']);
    } elseif (isset($_GET['sa']) && $_GET['sa'] == 'check') {
        // Strike!  You're outta there!
        if ($_GET['member'] != $user_info['id']) {
            fatal_lang_error('login_cookie_error', false);
        }
        // Some whitelisting for login_url...
        if (empty($_SESSION['login_url'])) {
            redirectexit();
        } else {
            // Best not to clutter the session data too much...
            $temp = $_SESSION['login_url'];
            unset($_SESSION['login_url']);
            redirectexit($temp);
        }
    }
    // Beyond this point you are assumed to be a guest trying to login.
    if (!$user_info['is_guest']) {
        redirectexit();
    }
    // 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) {
        $_SESSION['login_url'] = $_SESSION['old_url'];
    }
    // Are you guessing with a script that doesn't keep the session id?
    spamProtection('login');
    // 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 - wireless or normal.
    if (WIRELESS) {
        $context['sub_template'] = WIRELESS_PROTOCOL . '_login';
    } else {
        loadTemplate('Login');
        $context['sub_template'] = 'login';
    }
    // Set up the default/fallback stuff.
    $context['default_username'] = isset($_REQUEST['user']) ? preg_replace('~&amp;#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', htmlspecialchars($_REQUEST['user'])) : '';
    $context['default_password'] = '';
    $context['never_expire'] = $modSettings['cookieTime'] == 525600 || $modSettings['cookieTime'] == 3153600;
    $context['login_errors'] = array($txt['error_occured']);
    $context['page_title'] = $txt['login'];
    // Add the login chain to the link tree.
    $context['linktree'][] = array('url' => $scripturl . '?action=login', 'name' => $txt['login']);
    if (!empty($_REQUEST['openid_identifier']) && !empty($modSettings['enableOpenID'])) {
        require_once $sourcedir . '/Subs-OpenID.php';
        return smf_openID_validate($_REQUEST['openid_identifier']);
    }
    // You forgot to type your username, dummy!
    if (!isset($_REQUEST['user']) || $_REQUEST['user'] == '') {
        $context['login_errors'] = array($txt['need_username']);
        return;
    }
    // Hmm... maybe 'admin' will login with no password. Uhh... NO!
    if ((!isset($_POST['passwrd']) || $_POST['passwrd'] == '') && (!isset($_REQUEST['hash_passwrd']) || strlen($_REQUEST['hash_passwrd']) != 40)) {
        $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});)~', '', $_REQUEST['user'])) != 0) {
        $context['login_errors'] = array($txt['error_invalid_characters_username']);
        return;
    }
    // Are we using any sort of integration to validate the login?
    if (isset($modSettings['integrate_validate_login']) && is_callable($modSettings['integrate_validate_login'])) {
        if (call_user_func(strpos($modSettings['integrate_validate_login'], '::') === false ? $modSettings['integrate_validate_login'] : explode('::', $modSettings['integrate_validate_login']), $_REQUEST['user'], isset($_REQUEST['hash_passwrd']) && strlen($_REQUEST['hash_passwrd']) == 40 ? $_REQUEST['hash_passwrd'] : null, $modSettings['cookieTime']) == 'retry') {
            $context['login_errors'] = array($txt['login_hash_error']);
            $context['disable_login_hashing'] = true;
            return;
        }
    }
    // Load the data up!
    $request = $smcFunc['db_query']('', '
		SELECT passwd, id_member, id_group, lngfile, is_activated, email_address, additional_groups, member_name, password_salt,
			openid_uri, passwd_flood
		FROM {db_prefix}members
		WHERE ' . ($smcFunc['db_case_sensitive'] ? 'LOWER(member_name) = LOWER({string:user_name})' : 'member_name = {string:user_name}') . '
		LIMIT 1', array('user_name' => $smcFunc['db_case_sensitive'] ? strtolower($_REQUEST['user']) : $_REQUEST['user']));
    // Probably mistyped or their email, try it as an email address. (member_name first, though!)
    if ($smcFunc['db_num_rows']($request) == 0) {
        $smcFunc['db_free_result']($request);
        $request = $smcFunc['db_query']('', '
			SELECT passwd, id_member, id_group, lngfile, is_activated, email_address, additional_groups, member_name, password_salt, openid_uri,
			passwd_flood
			FROM {db_prefix}members
			WHERE email_address = {string:user_name}
			LIMIT 1', array('user_name' => $_REQUEST['user']));
        // Let them try again, it didn't match anything...
        if ($smcFunc['db_num_rows']($request) == 0) {
            $context['login_errors'] = array($txt['username_no_exist']);
            return;
        }
    }
    $user_settings = $smcFunc['db_fetch_assoc']($request);
    $smcFunc['db_free_result']($request);
    // Figure out the password using SMF's encryption - if what they typed is right.
    if (isset($_REQUEST['hash_passwrd']) && strlen($_REQUEST['hash_passwrd']) == 40) {
        // Needs upgrading?
        if (strlen($user_settings['passwd']) != 40) {
            $context['login_errors'] = array($txt['login_hash_error']);
            $context['disable_login_hashing'] = true;
            unset($user_settings);
            return;
        } elseif ($_REQUEST['hash_passwrd'] == sha1($user_settings['passwd'] . $sc)) {
            $sha_passwd = $user_settings['passwd'];
        } else {
            // Don't allow this!
            validatePasswordFlood($user_settings['id_member'], $user_settings['passwd_flood']);
            $_SESSION['failed_login'] = @$_SESSION['failed_login'] + 1;
            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');
                $context['disable_login_hashing'] = true;
                $context['login_errors'] = array($txt['incorrect_password']);
                unset($user_settings);
                return;
            }
        }
    } else {
        $sha_passwd = sha1(strtolower($user_settings['member_name']) . un_htmlspecialchars($_POST['passwrd']));
    }
    // Bad password!  Thought you could fool the database?!
    if ($user_settings['passwd'] != $sha_passwd) {
        // 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 = array();
        // None of the below cases will be used most of the time (because the salt is normally set.)
        if ($user_settings['password_salt'] == '') {
            // YaBB SE, Discus, MD5 (used a lot), SHA-1 (used some), SMF 1.0.x, IkonBoard, and none at all.
            $other_passwords[] = crypt($_POST['passwrd'], substr($_POST['passwrd'], 0, 2));
            $other_passwords[] = crypt($_POST['passwrd'], substr($user_settings['passwd'], 0, 2));
            $other_passwords[] = md5($_POST['passwrd']);
            $other_passwords[] = sha1($_POST['passwrd']);
            $other_passwords[] = md5_hmac($_POST['passwrd'], strtolower($user_settings['member_name']));
            $other_passwords[] = md5($_POST['passwrd'] . strtolower($user_settings['member_name']));
            $other_passwords[] = $_POST['passwrd'];
            // This one is a strange one... MyPHP, crypt() on the MD5 hash.
            $other_passwords[] = crypt(md5($_POST['passwrd']), md5($_POST['passwrd']));
            // Snitz style - SHA-256.  Technically, this is a downgrade, but most PHP configurations don't support sha256 anyway.
            if (strlen($user_settings['passwd']) == 64 && function_exists('mhash') && defined('MHASH_SHA256')) {
                $other_passwords[] = bin2hex(mhash(MHASH_SHA256, $_POST['passwrd']));
            }
            // phpBB3 users new hashing.  We now support it as well ;).
            $other_passwords[] = phpBB3_password_check($_POST['passwrd'], $user_settings['passwd']);
            // APBoard 2 Login Method.
            $other_passwords[] = md5(crypt($_REQUEST['passwrd'], 'CRYPT_MD5'));
        } elseif (strlen($user_settings['passwd']) == 32) {
            // vBulletin 3 style hashing?  Let's welcome them with open arms \o/.
            $other_passwords[] = md5(md5($_POST['passwrd']) . $user_settings['password_salt']);
            // Hmm.. p'raps it's Invision 2 style?
            $other_passwords[] = md5(md5($user_settings['password_salt']) . md5($_POST['passwrd']));
            // Some common md5 ones.
            $other_passwords[] = md5($user_settings['password_salt'] . $_POST['passwrd']);
            $other_passwords[] = md5($_POST['passwrd'] . $user_settings['password_salt']);
            $other_passwords[] = md5($_POST['passwrd']);
            $other_passwords[] = md5(md5($_POST['passwrd']));
        } elseif (strlen($user_settings['passwd']) == 40) {
            // Maybe they are using a hash from before the password fix.
            $other_passwords[] = sha1(strtolower($user_settings['member_name']) . un_htmlspecialchars($_POST['passwrd']));
            // BurningBoard3 style of hashing.
            $other_passwords[] = sha1($user_settings['password_salt'] . sha1($user_settings['password_salt'] . sha1($_REQUEST['passwrd'])));
            // Perhaps we converted to UTF-8 and have a valid password being hashed differently.
            if ($context['character_set'] == 'utf8' && !empty($modSettings['previousCharacterSet']) && $modSettings['previousCharacterSet'] != 'utf8') {
                // Try iconv first, for no particular reason.
                if (function_exists('iconv')) {
                    $other_passwords['iconv'] = sha1(strtolower(iconv('UTF-8', $modSettings['previousCharacterSet'], $user_settings['member_name'])) . un_htmlspecialchars(iconv('UTF-8', $modSettings['previousCharacterSet'], $_POST['passwrd'])));
                }
                // Say it aint so, iconv failed!
                if (empty($other_passwords['iconv']) && function_exists('mb_convert_encoding')) {
                    $other_passwords[] = sha1(strtolower(mb_convert_encoding($user_settings['member_name'], 'UTF-8', $modSettings['previousCharacterSet'])) . un_htmlspecialchars(mb_convert_encoding($_POST['passwrd'], 'UTF-8', $modSettings['previousCharacterSet'])));
                }
            }
        }
        // SMF's sha1 function can give a funny result on Linux (Not our fault!). If we've now got the real one let the old one be valid!
        if (strpos(strtolower(PHP_OS), 'win') !== 0) {
            require_once $sourcedir . '/Subs-Compat.php';
            $other_passwords[] = sha1_smf(strtolower($user_settings['member_name']) . un_htmlspecialchars($_POST['passwrd']));
        }
        // Whichever encryption it was using, let's make it use SMF's now ;).
        if (in_array($user_settings['passwd'], $other_passwords)) {
            $user_settings['passwd'] = $sha_passwd;
            $user_settings['password_salt'] = substr(md5(mt_rand()), 0, 4);
            // Update the password and set up the hash.
            updateMemberData($user_settings['id_member'], array('passwd' => $user_settings['passwd'], 'password_salt' => $user_settings['password_salt']));
        } else {
            // They've messed up again - keep a count to see if they need a hand.
            $_SESSION['failed_login'] = @$_SESSION['failed_login'] + 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 wern'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();
}
Example #2
0
function loadUserSettings()
{
    global $modSettings, $user_settings, $sourcedir;
    global $cookiename, $user_info, $language, $context;
    // Check first the integration, then the cookie, and last the session.
    if (count($integration_ids = HookAPI::callHook('integrate_verify_user')) > 0) {
        $id_member = 0;
        foreach ($integration_ids as $integration_id) {
            $integration_id = (int) $integration_id;
            if ($integration_id > 0) {
                $id_member = $integration_id;
                $already_verified = true;
                break;
            }
        }
    } else {
        $id_member = 0;
    }
    if (empty($id_member) && isset($_COOKIE[$cookiename])) {
        // Fix a security hole in PHP 4.3.9 and below...
        if (preg_match('~^a:[34]:\\{i:0;(i:\\d{1,6}|s:[1-8]:"\\d{1,8}");i:1;s:(0|40):"([a-fA-F0-9]{40})?";i:2;[id]:\\d{1,14};(i:3;i:\\d;)?\\}$~i', $_COOKIE[$cookiename]) == 1) {
            list($id_member, $password) = @unserialize($_COOKIE[$cookiename]);
            $id_member = !empty($id_member) && strlen($password) > 0 ? (int) $id_member : 0;
        } else {
            $id_member = 0;
        }
    } elseif (empty($id_member) && isset($_SESSION['login_' . $cookiename]) && ($_SESSION['USER_AGENT'] == $_SERVER['HTTP_USER_AGENT'] || !empty($modSettings['disableCheckUA']))) {
        // !!! Perhaps we can do some more checking on this, such as on the first octet of the IP?
        list($id_member, $password, $login_span) = @unserialize($_SESSION['login_' . $cookiename]);
        $id_member = !empty($id_member) && strlen($password) == 40 && $login_span > time() ? (int) $id_member : 0;
    }
    // Only load this stuff if the user isn't a guest.
    $_reload = $_to_cache = false;
    if ($id_member != 0) {
        // do we have a notification to dismiss (mark as seen) with this request? (we can only mark one per request, but that should be sufficient)
        if (isset($_REQUEST['nmdismiss']) && (int) $_REQUEST['nmdismiss'] > 0) {
            smf_db_query('UPDATE {db_prefix}log_notifications SET unread = 0 WHERE id_member = {int:id_user} AND id_act = {int:idact}', array('id_user' => $id_member, 'idact' => (int) $_REQUEST['nmdismiss']));
            $_reload = $_to_cache = true;
        }
        // Is the member data cached?
        if ($modSettings['cache_enable'] < 2 || ($user_settings = CacheAPI::getCache('user_settings-' . $id_member, 600)) == null) {
            $request = smf_db_query('
				SELECT mem.*, IFNULL(a.id_attach, 0) AS id_attach, a.filename, a.attachment_type
				FROM {db_prefix}members AS mem
					LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = {int:id_member})
				WHERE mem.id_member = {int:id_member}
				LIMIT 1', array('id_member' => $id_member));
            $user_settings = mysql_fetch_assoc($request);
            mysql_free_result($request);
        }
        // Did we find 'im?  If not, junk it.
        if (!empty($user_settings)) {
            // As much as the password should be right, we can assume the integration set things up.
            if (!empty($already_verified) && $already_verified === true) {
                $check = true;
            } elseif (strlen($password) == 40) {
                $check = sha1($user_settings['passwd'] . $user_settings['password_salt']) == $password;
            } else {
                $check = false;
            }
            // Wrong password or not activated - either way, you're going nowhere.
            $id_member = $check && ($user_settings['is_activated'] == 1 || $user_settings['is_activated'] == 11) ? $user_settings['id_member'] : 0;
        } else {
            $id_member = 0;
        }
        // If we no longer have the member maybe they're being all hackey, stop brute force!
        if (!$id_member) {
            require_once $sourcedir . '/LogInOut.php';
            validatePasswordFlood(!empty($user_settings['id_member']) ? $user_settings['id_member'] : $id_member, !empty($user_settings['passwd_flood']) ? $user_settings['passwd_flood'] : false, $id_member != 0);
        }
    }
    // Found 'im, let's set up the variables.
    if ($id_member != 0) {
        // Let's not update the last visit time in these cases...
        // 1. SSI doesn't count as visiting the forum.
        // 2. RSS feeds and XMLHTTP requests don't count either.
        // 3. If it was set within this session, no need to set it again.
        // 4. New session, yet updated < five hours ago? Maybe cache can help.
        if (SMF != 'SSI' && !isset($_REQUEST['xml']) && (!isset($_REQUEST['action']) || $_REQUEST['action'] != '.xml') && empty($_SESSION['id_msg_last_visit']) && (empty($modSettings['cache_enable']) || ($_SESSION['id_msg_last_visit'] = CacheAPI::getCache('user_last_visit-' . $id_member, 5 * 3600)) === null)) {
            // Do a quick query to make sure this isn't a mistake.
            $result = smf_db_query('
				SELECT poster_time
				FROM {db_prefix}messages
				WHERE id_msg = {int:id_msg}
				LIMIT 1', array('id_msg' => $user_settings['id_msg_last_visit']));
            list($visitTime) = mysql_fetch_row($result);
            mysql_free_result($result);
            $_SESSION['id_msg_last_visit'] = $user_settings['id_msg_last_visit'];
            // If it was *at least* five hours ago...
            if ($visitTime < time() - 5 * 3600) {
                updateMemberData($id_member, array('id_msg_last_visit' => (int) $modSettings['maxMsgID'], 'last_login' => time(), 'member_ip' => $_SERVER['REMOTE_ADDR'], 'member_ip2' => $_SERVER['BAN_CHECK_IP']));
                $user_settings['last_login'] = time();
                if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2) {
                    CacheAPI::putCache('user_settings-' . $id_member, $user_settings, 60);
                }
                if (!empty($modSettings['cache_enable'])) {
                    CacheAPI::putCache('user_last_visit-' . $id_member, $_SESSION['id_msg_last_visit'], 5 * 3600);
                }
            }
        } elseif (empty($_SESSION['id_msg_last_visit'])) {
            $_SESSION['id_msg_last_visit'] = $user_settings['id_msg_last_visit'];
        }
        $username = $user_settings['member_name'];
        if (empty($user_settings['additional_groups'])) {
            $user_info = array('groups' => array($user_settings['id_group'], $user_settings['id_post_group']));
        } else {
            $user_info = array('groups' => array_merge(array($user_settings['id_group'], $user_settings['id_post_group']), explode(',', $user_settings['additional_groups'])));
        }
        // Because history has proven that it is possible for groups to go bad - clean up in case.
        foreach ($user_info['groups'] as $k => $v) {
            $user_info['groups'][$k] = (int) $v;
        }
        // This is a logged in user, so definitely not a spider.
        $user_info['possibly_robot'] = false;
        $user_info['show_online'] = $user_settings['show_online'];
        $user_info['time_offset'] = empty($user_settings['time_offset']) ? 0 : $user_settings['time_offset'];
    } else {
        // This is what a guest's variables should be.
        $username = '';
        $user_info = array('groups' => array(-1));
        $user_settings = array();
        if (isset($_COOKIE[$cookiename])) {
            $_COOKIE[$cookiename] = '';
        }
        // Do we perhaps think this is a search robot? Check every five minutes just in case...
        if ((!empty($modSettings['spider_mode']) || !empty($modSettings['spider_group'])) && (!isset($_SESSION['robot_check']) || $_SESSION['robot_check'] < time() - 300)) {
            $user_info['possibly_robot'] = SpiderCheck();
        } elseif (!empty($modSettings['spider_mode'])) {
            $user_info['possibly_robot'] = isset($_SESSION['id_robot']) ? $_SESSION['id_robot'] : 0;
        } else {
            $ci_user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
            $user_info['possibly_robot'] = strpos($_SERVER['HTTP_USER_AGENT'], 'Mozilla') === false && strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') === false || strpos($ci_user_agent, 'googlebot') !== false || strpos($ci_user_agent, 'slurp') !== false || strpos($ci_user_agent, 'crawl') !== false;
        }
        $user_info['time_offset'] = isset($_SESSION['tzoffset']) ? $_SESSION['tzoffset'] : 0;
        $user_info['guest_need_tzoffset'] = !isset($_SESSION['tzoffset']);
        // don't have it yet, embed the js to determine tz offset for *guests only*
    }
    // Set up the $user_info array.
    $user_info += array('id' => $id_member, 'username' => $username, 'name' => isset($user_settings['real_name']) ? $user_settings['real_name'] : '', 'email' => isset($user_settings['email_address']) ? $user_settings['email_address'] : '', 'passwd' => isset($user_settings['passwd']) ? $user_settings['passwd'] : '', 'language' => empty($user_settings['lngfile']) || empty($modSettings['userLanguage']) ? $language : $user_settings['lngfile'], 'is_guest' => $id_member == 0, 'is_admin' => in_array(1, $user_info['groups']), 'theme' => empty($user_settings['id_theme']) ? 0 : $user_settings['id_theme'], 'last_login' => empty($user_settings['last_login']) ? 0 : $user_settings['last_login'], 'ip' => $_SERVER['REMOTE_ADDR'], 'ip2' => $_SERVER['BAN_CHECK_IP'], 'posts' => empty($user_settings['posts']) ? 0 : $user_settings['posts'], 'time_format' => empty($user_settings['time_format']) ? $modSettings['time_format'] : $user_settings['time_format'], 'avatar' => array('url' => isset($user_settings['avatar']) ? $user_settings['avatar'] : '', 'filename' => empty($user_settings['filename']) ? '' : $user_settings['filename'], 'custom_dir' => !empty($user_settings['attachment_type']) && $user_settings['attachment_type'] == 1, 'id_attach' => isset($user_settings['id_attach']) ? $user_settings['id_attach'] : 0), 'smiley_set' => isset($user_settings['smiley_set']) ? $user_settings['smiley_set'] : '', 'messages' => empty($user_settings['instant_messages']) ? 0 : $user_settings['instant_messages'], 'unread_messages' => empty($user_settings['unread_messages']) ? 0 : $user_settings['unread_messages'], 'total_time_logged_in' => empty($user_settings['total_time_logged_in']) ? 0 : $user_settings['total_time_logged_in'], 'buddies' => !empty($modSettings['enable_buddylist']) && !empty($user_settings['buddy_list']) ? explode(',', $user_settings['buddy_list']) : array(), 'ignoreboards' => !empty($user_settings['ignore_boards']) && !empty($modSettings['allow_ignore_boards']) ? explode(',', $user_settings['ignore_boards']) : array(), 'ignoreusers' => !empty($user_settings['pm_ignore_list']) ? explode(',', $user_settings['pm_ignore_list']) : array(), 'warning' => isset($user_settings['warning']) ? $user_settings['warning'] : 0, 'likesgiven' => isset($user_settings['likes_given']) ? $user_settings['likes_given'] : 0, 'likesreceived' => isset($user_settings['likes_received']) ? $user_settings['likes_received'] : 0, 'permissions' => array(), 'act_optout' => isset($user_settings['act_optout']) ? $user_settings['act_optout'] : '', 'notify_optout' => isset($user_settings['notify_optout']) ? $user_settings['notify_optout'] : '', 'meta' => !empty($user_settings['meta']) ? @unserialize($user_settings['meta']) : array());
    $user_info['smf_sidebar_disabled'] = 0;
    $user_info['groups'] = array_unique($user_info['groups']);
    // Make sure that the last item in the ignore boards array is valid.  If the list was too long it could have an ending comma that could cause problems.
    if (!empty($user_info['ignoreboards']) && empty($user_info['ignoreboards'][$tmp = count($user_info['ignoreboards']) - 1])) {
        unset($user_info['ignoreboards'][$tmp]);
    }
    // Do we have any languages to validate this?
    if (!empty($modSettings['userLanguage']) && (!empty($_GET['language']) || !empty($_SESSION['language']))) {
        $languages = getLanguages();
    }
    // Allow the user to change their language if its valid.
    if (!empty($modSettings['userLanguage']) && !empty($_GET['language']) && isset($languages[strtr($_GET['language'], './\\:', '____')])) {
        $user_info['language'] = strtr($_GET['language'], './\\:', '____');
        $_SESSION['language'] = $user_info['language'];
    } elseif (!empty($modSettings['userLanguage']) && !empty($_SESSION['language']) && isset($languages[strtr($_SESSION['language'], './\\:', '____')])) {
        $user_info['language'] = strtr($_SESSION['language'], './\\:', '____');
    }
    // map language to a numeric id
    $n = 0;
    if (isset($context['languages'])) {
        foreach ($context['languages'] as $key => $lang) {
            if ($key == $user_info['language']) {
                break;
            }
            $n++;
        }
    }
    $user_info['language_id'] = $n + 1;
    // Just build this here, it makes it easier to change/use - administrators can see all boards.
    if ($user_info['is_admin']) {
        $user_info['query_see_board'] = '1=1';
    } else {
        $user_info['query_see_board'] = '(FIND_IN_SET(' . implode(', b.member_groups) != 0 OR FIND_IN_SET(', $user_info['groups']) . ', b.member_groups) != 0' . (isset($user_info['mod_cache']) ? ' OR ' . $user_info['mod_cache']['mq'] : '') . ')';
    }
    // Build the list of boards they WANT to see.
    // This will take the place of query_see_boards in certain spots, so it better include the boards they can see also
    // If they aren't ignoring any boards then they want to see all the boards they can see
    if (empty($user_info['ignoreboards'])) {
        $user_info['query_wanna_see_board'] = $user_info['query_see_board'];
    } else {
        $user_info['query_wanna_see_board'] = '(' . $user_info['query_see_board'] . ' AND b.id_board NOT IN (' . implode(',', $user_info['ignoreboards']) . '))';
    }
    /*
     * figure out unread notifications
     * 
     * the reason why this is here in an extra query is that we need query_see_board.
     * e.g. when a user gets a notification for a topic that has been moved to a board he
     * is not permitted to access, we want to filter out the notifications.
     */
    if ($id_member != 0 && (!isset($user_settings['notify_count']) || $_reload)) {
        // this is actually cached, unless $user_settings was re-fetched from the db.
        $_to_cache = true;
        $request = smf_db_query('
					SELECT COUNT(n.id_act) AS notify_count FROM {db_prefix}log_notifications AS n
						LEFT JOIN {db_prefix}log_activities AS a ON (a.id_act = n.id_act)
						LEFT JOIN {db_prefix}boards AS b ON(b.id_board = a.id_board)
						WHERE n.id_member = {int:id_member} AND n.unread = 1 AND ' . (!empty($user_info['ignoreusers']) ? 'a.id_member NOT IN({array_int:ignoredusers}) AND ' : '') . ' ({query_wanna_see_board} OR a.id_board = 0)', array('id_member' => $id_member, 'ignoredusers' => $user_info['ignoreusers']));
        if (mysql_num_rows($request) > 0) {
            list($unread) = mysql_fetch_row($request);
            $user_settings['notify_count'] = $unread;
        } else {
            $user_settings['notify_count'] = 0;
        }
        mysql_free_result($request);
    }
    if ($modSettings['cache_enable'] >= 2 && $id_member != 0 && $_to_cache) {
        CacheAPI::putCache('user_settings-' . $id_member, $user_settings, 600);
    }
    $user_info['notify_count'] = isset($user_settings['notify_count']) ? $user_settings['notify_count'] : 0;
    if ($user_info['unread_messages'] && $user_info['notify_count'] == 0) {
        $user_info['notify_count']++;
    }
    // record the user in the list of users who were online today. todo: there should be an option for this feature.
    if (!empty($modSettings['who_track_daily_visitors']) && $user_info['id'] > 0 && !isset($modSettings['online_today'][$user_info['id']])) {
        $modSettings['online_today'][$user_info['id']] = array('name' => $user_info['name'], 'show_online' => $user_info['show_online'], 'link' => '<a class="member group_' . (empty($user_settings['id_group']) ? $user_settings['id_post_group'] : $user_settings['id_group']) . '" href="' . URL::user($user_info['id'], $user_info['name']) . '">' . $user_info['name'] . '</a>');
        updateSettings(array('log_online_today' => @serialize($modSettings['online_today'])));
    }
    $user_info['font_class'] = isset($_COOKIE['EOS_Fontstyle']) ? $_COOKIE['EOS_Fontstyle'] : '0';
    HookAPI::callHook('load_userdata', array(&$user_info, &$user_settings));
}
Example #3
0
function loadUserSettings()
{
    global $modSettings, $user_settings, $sourcedir, $smcFunc;
    global $cookiename, $user_info, $language;
    // Check first the integration, then the cookie, and last the session.
    if (count($integration_ids = call_integration_hook('integrate_verify_user')) > 0) {
        $id_member = 0;
        foreach ($integration_ids as $integration_id) {
            $integration_id = (int) $integration_id;
            if ($integration_id > 0) {
                $id_member = $integration_id;
                $already_verified = true;
                break;
            }
        }
    } else {
        $id_member = 0;
    }
    if (empty($id_member) && isset($_COOKIE[$cookiename])) {
        // Fix a security hole in PHP 4.3.9 and below...
        if (preg_match('~^a:[34]:\\{i:0;(i:\\d{1,6}|s:[1-8]:"\\d{1,8}");i:1;s:(0|40):"([a-fA-F0-9]{40})?";i:2;[id]:\\d{1,14};(i:3;i:\\d;)?\\}$~i', $_COOKIE[$cookiename]) == 1) {
            list($id_member, $password) = @unserialize($_COOKIE[$cookiename]);
            $id_member = !empty($id_member) && strlen($password) > 0 ? (int) $id_member : 0;
        } else {
            $id_member = 0;
        }
    } elseif (empty($id_member) && isset($_SESSION['login_' . $cookiename]) && ($_SESSION['USER_AGENT'] == $_SERVER['HTTP_USER_AGENT'] || !empty($modSettings['disableCheckUA']))) {
        // !!! Perhaps we can do some more checking on this, such as on the first octet of the IP?
        list($id_member, $password, $login_span) = @unserialize($_SESSION['login_' . $cookiename]);
        $id_member = !empty($id_member) && strlen($password) == 40 && $login_span > time() ? (int) $id_member : 0;
    }
    // Only load this stuff if the user isn't a guest.
    if ($id_member != 0) {
        // Is the member data cached?
        if (empty($modSettings['cache_enable']) || $modSettings['cache_enable'] < 2 || ($user_settings = cache_get_data('user_settings-' . $id_member, 60)) == null) {
            $request = $smcFunc['db_query']('', '
				SELECT mem.*, IFNULL(a.id_attach, 0) AS id_attach, a.filename, a.attachment_type
				FROM {db_prefix}members AS mem
					LEFT JOIN {db_prefix}attachments AS a ON (a.id_member = {int:id_member})
				WHERE mem.id_member = {int:id_member}
				LIMIT 1', array('id_member' => $id_member));
            $user_settings = $smcFunc['db_fetch_assoc']($request);
            $smcFunc['db_free_result']($request);
            if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2) {
                cache_put_data('user_settings-' . $id_member, $user_settings, 60);
            }
        }
        // Did we find 'im?  If not, junk it.
        if (!empty($user_settings)) {
            // As much as the password should be right, we can assume the integration set things up.
            if (!empty($already_verified) && $already_verified === true) {
                $check = true;
            } elseif (strlen($password) == 40) {
                $check = sha1($user_settings['passwd'] . $user_settings['password_salt']) == $password;
            } else {
                $check = false;
            }
            // Wrong password or not activated - either way, you're going nowhere.
            $id_member = $check && ($user_settings['is_activated'] == 1 || $user_settings['is_activated'] == 11) ? $user_settings['id_member'] : 0;
        } else {
            $id_member = 0;
        }
        // If we no longer have the member maybe they're being all hackey, stop brute force!
        if (!$id_member) {
            require_once $sourcedir . '/LogInOut.php';
            validatePasswordFlood(!empty($user_settings['id_member']) ? $user_settings['id_member'] : $id_member, !empty($user_settings['passwd_flood']) ? $user_settings['passwd_flood'] : false, $id_member != 0);
        }
    }
    // Found 'im, let's set up the variables.
    if ($id_member != 0) {
        // Let's not update the last visit time in these cases...
        // 1. SSI doesn't count as visiting the forum.
        // 2. RSS feeds and XMLHTTP requests don't count either.
        // 3. If it was set within this session, no need to set it again.
        // 4. New session, yet updated < five hours ago? Maybe cache can help.
        if (SMF != 'SSI' && !isset($_REQUEST['xml']) && (!isset($_REQUEST['action']) || $_REQUEST['action'] != '.xml') && empty($_SESSION['id_msg_last_visit']) && (empty($modSettings['cache_enable']) || ($_SESSION['id_msg_last_visit'] = cache_get_data('user_last_visit-' . $id_member, 5 * 3600)) === null)) {
            // Do a quick query to make sure this isn't a mistake.
            $result = $smcFunc['db_query']('', '
				SELECT poster_time
				FROM {db_prefix}messages
				WHERE id_msg = {int:id_msg}
				LIMIT 1', array('id_msg' => $user_settings['id_msg_last_visit']));
            list($visitTime) = $smcFunc['db_fetch_row']($result);
            $smcFunc['db_free_result']($result);
            $_SESSION['id_msg_last_visit'] = $user_settings['id_msg_last_visit'];
            // If it was *at least* five hours ago...
            if ($visitTime < time() - 5 * 3600) {
                updateMemberData($id_member, array('id_msg_last_visit' => (int) $modSettings['maxMsgID'], 'last_login' => time(), 'member_ip' => $_SERVER['REMOTE_ADDR'], 'member_ip2' => $_SERVER['BAN_CHECK_IP']));
                $user_settings['last_login'] = time();
                if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2) {
                    cache_put_data('user_settings-' . $id_member, $user_settings, 60);
                }
                if (!empty($modSettings['cache_enable'])) {
                    cache_put_data('user_last_visit-' . $id_member, $_SESSION['id_msg_last_visit'], 5 * 3600);
                }
            }
        } elseif (empty($_SESSION['id_msg_last_visit'])) {
            $_SESSION['id_msg_last_visit'] = $user_settings['id_msg_last_visit'];
        }
        $username = $user_settings['member_name'];
        if (empty($user_settings['additional_groups'])) {
            $user_info = array('groups' => array($user_settings['id_group'], $user_settings['id_post_group']));
        } else {
            $user_info = array('groups' => array_merge(array($user_settings['id_group'], $user_settings['id_post_group']), explode(',', $user_settings['additional_groups'])));
        }
        // Because history has proven that it is possible for groups to go bad - clean up in case.
        foreach ($user_info['groups'] as $k => $v) {
            $user_info['groups'][$k] = (int) $v;
        }
        // This is a logged in user, so definitely not a spider.
        $user_info['possibly_robot'] = false;
    } else {
        // This is what a guest's variables should be.
        $username = '';
        $user_info = array('groups' => array(-1));
        $user_settings = array();
        if (isset($_COOKIE[$cookiename])) {
            $_COOKIE[$cookiename] = '';
        }
        // Do we perhaps think this is a search robot? Check every five minutes just in case...
        if ((!empty($modSettings['spider_mode']) || !empty($modSettings['spider_group'])) && (!isset($_SESSION['robot_check']) || $_SESSION['robot_check'] < time() - 300)) {
            require_once $sourcedir . '/ManageSearchEngines.php';
            $user_info['possibly_robot'] = SpiderCheck();
        } elseif (!empty($modSettings['spider_mode'])) {
            $user_info['possibly_robot'] = isset($_SESSION['id_robot']) ? $_SESSION['id_robot'] : 0;
        } else {
            $ci_user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
            $user_info['possibly_robot'] = strpos($_SERVER['HTTP_USER_AGENT'], 'Mozilla') === false && strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') === false || strpos($ci_user_agent, 'googlebot') !== false || strpos($ci_user_agent, 'slurp') !== false || strpos($ci_user_agent, 'crawl') !== false;
        }
    }
    // Set up the $user_info array.
    $user_info += array('id' => $id_member, 'username' => $username, 'name' => isset($user_settings['real_name']) ? $user_settings['real_name'] : '', 'email' => isset($user_settings['email_address']) ? $user_settings['email_address'] : '', 'passwd' => isset($user_settings['passwd']) ? $user_settings['passwd'] : '', 'language' => empty($user_settings['lngfile']) || empty($modSettings['userLanguage']) ? $language : $user_settings['lngfile'], 'is_guest' => $id_member == 0, 'is_admin' => in_array(1, $user_info['groups']), 'theme' => empty($user_settings['id_theme']) ? 0 : $user_settings['id_theme'], 'last_login' => empty($user_settings['last_login']) ? 0 : $user_settings['last_login'], 'ip' => $_SERVER['REMOTE_ADDR'], 'ip2' => $_SERVER['BAN_CHECK_IP'], 'posts' => empty($user_settings['posts']) ? 0 : $user_settings['posts'], 'time_format' => empty($user_settings['time_format']) ? $modSettings['time_format'] : $user_settings['time_format'], 'time_offset' => empty($user_settings['time_offset']) ? 0 : $user_settings['time_offset'], 'avatar' => array('url' => isset($user_settings['avatar']) ? $user_settings['avatar'] : '', 'filename' => empty($user_settings['filename']) ? '' : $user_settings['filename'], 'custom_dir' => !empty($user_settings['attachment_type']) && $user_settings['attachment_type'] == 1, 'id_attach' => isset($user_settings['id_attach']) ? $user_settings['id_attach'] : 0), 'smiley_set' => isset($user_settings['smiley_set']) ? $user_settings['smiley_set'] : '', 'messages' => empty($user_settings['instant_messages']) ? 0 : $user_settings['instant_messages'], 'unread_messages' => empty($user_settings['unread_messages']) ? 0 : $user_settings['unread_messages'], 'total_time_logged_in' => empty($user_settings['total_time_logged_in']) ? 0 : $user_settings['total_time_logged_in'], 'buddies' => !empty($modSettings['enable_buddylist']) && !empty($user_settings['buddy_list']) ? explode(',', $user_settings['buddy_list']) : array(), 'ignoreboards' => !empty($user_settings['ignore_boards']) && !empty($modSettings['allow_ignore_boards']) ? explode(',', $user_settings['ignore_boards']) : array(), 'ignoreusers' => !empty($user_settings['pm_ignore_list']) ? explode(',', $user_settings['pm_ignore_list']) : array(), 'warning' => isset($user_settings['warning']) ? $user_settings['warning'] : 0, 'permissions' => array());
    $user_info['groups'] = array_unique($user_info['groups']);
    // Make sure that the last item in the ignore boards array is valid.  If the list was too long it could have an ending comma that could cause problems.
    if (!empty($user_info['ignoreboards']) && empty($user_info['ignoreboards'][$tmp = count($user_info['ignoreboards']) - 1])) {
        unset($user_info['ignoreboards'][$tmp]);
    }
    // Do we have any languages to validate this?
    if (!empty($modSettings['userLanguage']) && (!empty($_GET['language']) || !empty($_SESSION['language']))) {
        $languages = getLanguages();
    }
    // Allow the user to change their language if its valid.
    if (!empty($modSettings['userLanguage']) && !empty($_GET['language']) && isset($languages[strtr($_GET['language'], './\\:', '____')])) {
        $user_info['language'] = strtr($_GET['language'], './\\:', '____');
        $_SESSION['language'] = $user_info['language'];
    } elseif (!empty($modSettings['userLanguage']) && !empty($_SESSION['language']) && isset($languages[strtr($_SESSION['language'], './\\:', '____')])) {
        $user_info['language'] = strtr($_SESSION['language'], './\\:', '____');
    }
    // Just build this here, it makes it easier to change/use - administrators can see all boards.
    if ($user_info['is_admin']) {
        $user_info['query_see_board'] = '1=1';
    } else {
        $user_info['query_see_board'] = '(FIND_IN_SET(' . implode(', b.member_groups) != 0 OR FIND_IN_SET(', $user_info['groups']) . ', b.member_groups) != 0' . (isset($user_info['mod_cache']) ? ' OR ' . $user_info['mod_cache']['mq'] : '') . ')';
    }
    // Build the list of boards they WANT to see.
    // This will take the place of query_see_boards in certain spots, so it better include the boards they can see also
    // If they aren't ignoring any boards then they want to see all the boards they can see
    if (empty($user_info['ignoreboards'])) {
        $user_info['query_wanna_see_board'] = $user_info['query_see_board'];
    } else {
        $user_info['query_wanna_see_board'] = '(' . $user_info['query_see_board'] . ' AND b.id_board NOT IN (' . implode(',', $user_info['ignoreboards']) . '))';
    }
}
Example #4
0
 /**
  * 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();
 }
Example #5
0
function setPassword2()
{
    global $context, $txt, $modSettings, $smcFunc, $sourcedir;
    checkSession();
    if (empty($_POST['u']) || !isset($_POST['passwrd1']) || !isset($_POST['passwrd2'])) {
        fatal_lang_error('no_access', false);
    }
    $_POST['u'] = (int) $_POST['u'];
    if ($_POST['passwrd1'] != $_POST['passwrd2']) {
        fatal_lang_error('passwords_dont_match', false);
    }
    if ($_POST['passwrd1'] == '') {
        fatal_lang_error('no_password', false);
    }
    loadLanguage('Login');
    // Get the code as it should be from the database.
    $request = $smcFunc['db_query']('', '
		SELECT validation_code, member_name, email_address, passwd_flood
		FROM {db_prefix}members
		WHERE id_member = {int:id_member}
			AND is_activated = {int:is_activated}
			AND validation_code != {string:blank_string}
		LIMIT 1', array('id_member' => $_POST['u'], 'is_activated' => 1, 'blank_string' => ''));
    // Does this user exist at all?
    if ($smcFunc['db_num_rows']($request) == 0) {
        fatal_lang_error('invalid_userid', false);
    }
    list($realCode, $username, $email, $flood_value) = $smcFunc['db_fetch_row']($request);
    $smcFunc['db_free_result']($request);
    // Is the password actually valid?
    require_once $sourcedir . '/Subs-Auth.php';
    $passwordError = validatePassword($_POST['passwrd1'], $username, array($email));
    // What - it's not?
    if ($passwordError != null) {
        fatal_lang_error('profile_error_password_' . $passwordError, false);
    }
    require_once $sourcedir . '/LogInOut.php';
    // Quit if this code is not right.
    if (empty($_POST['code']) || substr($realCode, 0, 10) !== substr(md5($_POST['code']), 0, 10)) {
        // Stop brute force attacks like this.
        validatePasswordFlood($_POST['u'], $flood_value, false);
        fatal_error($txt['invalid_activation_code'], false);
    }
    // Just in case, flood control.
    validatePasswordFlood($_POST['u'], $flood_value, true);
    // User validated.  Update the database!
    updateMemberData($_POST['u'], array('validation_code' => '', 'passwd' => sha1(strtolower($username) . $_POST['passwrd1'])));
    call_integration_hook('integrate_reset_pass', array($username, $username, $_POST['passwrd1']));
    loadTemplate('Login');
    $context += array('page_title' => $txt['reminder_password_set'], 'sub_template' => 'login', 'default_username' => $username, 'default_password' => $_POST['passwrd1'], 'never_expire' => false, 'description' => $txt['reminder_password_set']);
}
Example #6
0
 /**
  * Handle the password change.
  * sa=setpassword2
  */
 public function action_setpassword2()
 {
     global $context, $txt;
     checkSession();
     validateToken('remind-sp');
     if (empty($_POST['u']) || !isset($_POST['passwrd1']) || !isset($_POST['passwrd2'])) {
         fatal_lang_error('no_access', false);
     }
     $_POST['u'] = (int) $_POST['u'];
     if ($_POST['passwrd1'] != $_POST['passwrd2']) {
         fatal_lang_error('passwords_dont_match', false);
     }
     if ($_POST['passwrd1'] == '') {
         fatal_lang_error('no_password', false);
     }
     loadLanguage('Login');
     // Get the code as it should be from the database.
     require_once SUBSDIR . '/Members.subs.php';
     $member = getBasicMemberData((int) $_POST['u'], array('authentication' => true));
     // Does this user exist at all? Is he activated? Does he have a validation code?
     if (empty($member) || $member['is_activated'] != 1 || $member['validation_code'] == '') {
         fatal_lang_error('invalid_userid', false);
     }
     // Is the password actually valid?
     require_once SUBSDIR . '/Auth.subs.php';
     $passwordError = validatePassword($_POST['passwrd1'], $member['member_name'], array($member['email_address']));
     // What - it's not?
     if ($passwordError != null) {
         fatal_lang_error('profile_error_password_' . $passwordError, false);
     }
     // Quit if this code is not right.
     if (empty($_POST['code']) || substr($member['validation_code'], 0, 10) !== substr(md5($_POST['code']), 0, 10)) {
         // Stop brute force attacks like this.
         validatePasswordFlood($_POST['u'], $member['passwd_flood'], false);
         fatal_error($txt['invalid_activation_code'], false);
     }
     // Just in case, flood control.
     validatePasswordFlood($_POST['u'], $member['passwd_flood'], true);
     // User validated.  Update the database!
     require_once SUBSDIR . '/Auth.subs.php';
     $sha_passwd = $_POST['passwrd1'];
     updateMemberData($_POST['u'], array('validation_code' => '', 'passwd' => validateLoginPassword($sha_passwd, '', $member['member_name'], true)));
     call_integration_hook('integrate_reset_pass', array($member['member_name'], $member['member_name'], $_POST['passwrd1']));
     loadTemplate('Login');
     loadJavascriptFile('sha256.js', array('defer' => true));
     $context += array('page_title' => $txt['reminder_password_set'], 'sub_template' => 'login', 'default_username' => $member['member_name'], 'default_password' => $_POST['passwrd1'], 'never_expire' => false, 'description' => $txt['reminder_password_set']);
     createToken('login');
 }