Beispiel #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();
}
Beispiel #2
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();
 }
Beispiel #3
0
 /**
  * Callback action handler for OpenID
  */
 public function action_openidreturn()
 {
     global $modSettings, $context, $user_settings;
     // We'll need our subs.
     require_once SUBSDIR . '/OpenID.subs.php';
     // Is OpenID even enabled?
     if (empty($modSettings['enableOpenID'])) {
         fatal_lang_error('no_access', false);
     }
     // The OpenID provider did not respond with the OpenID mode? Throw an error..
     if (!isset($_GET['openid_mode'])) {
         fatal_lang_error('openid_return_no_mode', false);
     }
     // @todo Check for error status!
     if ($_GET['openid_mode'] != 'id_res') {
         fatal_lang_error('openid_not_resolved');
     }
     // this has annoying habit of removing the + from the base64 encoding.  So lets put them back.
     foreach (array('openid_assoc_handle', 'openid_invalidate_handle', 'openid_sig', 'sf') as $key) {
         if (isset($_GET[$key])) {
             $_GET[$key] = str_replace(' ', '+', $_GET[$key]);
         }
     }
     $openID = new OpenID();
     // Did they tell us to remove any associations?
     if (!empty($_GET['openid_invalidate_handle'])) {
         $openID->removeAssociation($_GET['openid_invalidate_handle']);
     }
     // Get the OpenID server info.
     $server_info = $openID->getServerInfo($_GET['openid_identity']);
     // Get the association data.
     $assoc = $openID->getAssociation($server_info['server'], $_GET['openid_assoc_handle'], true);
     if ($assoc === null) {
         fatal_lang_error('openid_no_assoc');
     }
     $secret = base64_decode($assoc['secret']);
     $signed = explode(',', $_GET['openid_signed']);
     $verify_str = '';
     foreach ($signed as $sign) {
         $verify_str .= $sign . ':' . strtr($_GET['openid_' . str_replace('.', '_', $sign)], array('&amp;' => '&')) . "\n";
     }
     $verify_str = base64_encode(hash_hmac('sha1', $verify_str, $secret, true));
     // Verify the OpenID signature.
     if ($verify_str != $_GET['openid_sig']) {
         fatal_lang_error('openid_sig_invalid', 'critical');
     }
     if (!isset($_SESSION['openid']['saved_data'][$_GET['t']])) {
         fatal_lang_error('openid_load_data');
     }
     $openid_uri = $_SESSION['openid']['saved_data'][$_GET['t']]['openid_uri'];
     $modSettings['cookieTime'] = $_SESSION['openid']['saved_data'][$_GET['t']]['cookieTime'];
     if (empty($openid_uri)) {
         fatal_lang_error('openid_load_data');
     }
     // Any save fields to restore?
     $context['openid_save_fields'] = isset($_GET['sf']) ? unserialize(base64_decode($_GET['sf'])) : array();
     $context['openid_claimed_id'] = $_GET['openid_claimed_id'];
     // Is there a user with this OpenID_uri?
     $member_found = memberByOpenID($context['openid_claimed_id']);
     if (empty($member_found) && isset($_GET['sa']) && $_GET['sa'] == 'change_uri' && !empty($_SESSION['new_openid_uri']) && $_SESSION['new_openid_uri'] == $context['openid_claimed_id']) {
         // Update the member.
         updateMemberData($user_settings['id_member'], array('openid_uri' => $context['openid_claimed_id']));
         unset($_SESSION['new_openid_uri']);
         $_SESSION['openid'] = array('verified' => true, 'openid_uri' => $context['openid_claimed_id']);
         // Send them back to profile.
         redirectexit('action=profile;area=authentication;updated');
     } elseif (empty($member_found)) {
         // Store the received openid info for the user when returned to the registration page.
         $_SESSION['openid'] = array('verified' => true, 'openid_uri' => $context['openid_claimed_id']);
         if (isset($_GET['openid_sreg_nickname'])) {
             $_SESSION['openid']['nickname'] = $_GET['openid_sreg_nickname'];
         }
         if (isset($_GET['openid_sreg_email'])) {
             $_SESSION['openid']['email'] = $_GET['openid_sreg_email'];
         }
         if (isset($_GET['openid_sreg_dob'])) {
             $_SESSION['openid']['dob'] = $_GET['openid_sreg_dob'];
         }
         if (isset($_GET['openid_sreg_gender'])) {
             $_SESSION['openid']['gender'] = $_GET['openid_sreg_gender'];
         }
         // Were we just verifying the registration state?
         if (isset($_GET['sa']) && $_GET['sa'] == 'register2') {
             require_once CONTROLLERDIR . '/Register.controller.php';
             $controller = new Register_Controller();
             return $controller->action_register2(true);
         } else {
             redirectexit('action=register');
         }
     } elseif (isset($_GET['sa']) && $_GET['sa'] == 'revalidate' && $user_settings['openid_uri'] == $openid_uri) {
         $_SESSION['openid_revalidate_time'] = time();
         // Restore the get data.
         require_once SUBSDIR . '/Auth.subs.php';
         $_SESSION['openid']['saved_data'][$_GET['t']]['get']['openid_restore_post'] = $_GET['t'];
         $query_string = construct_query_string($_SESSION['openid']['saved_data'][$_GET['t']]['get']);
         redirectexit($query_string);
     } else {
         $user_settings = $member_found;
         // @Todo: this seems outdated?
         $user_settings['passwd'] = sha1(strtolower($user_settings['member_name']) . $secret);
         $user_settings['password_salt'] = substr(md5(mt_rand()), 0, 4);
         updateMemberData($user_settings['id_member'], array('passwd' => $user_settings['passwd'], 'password_salt' => $user_settings['password_salt']));
         // Cleanup on Aisle 5.
         $_SESSION['openid'] = array('verified' => true, 'openid_uri' => $context['openid_claimed_id']);
         require_once CONTROLLERDIR . '/Auth.controller.php';
         // Activation required?
         if (!checkActivation()) {
             return;
         }
         // Finally do the login.
         doLogin();
     }
 }
Beispiel #4
0
function smf_openID_return()
{
    global $smcFunc, $user_info, $user_profile, $sourcedir, $modSettings, $context, $sc, $user_settings;
    // Is OpenID even enabled?
    if (empty($modSettings['enableOpenID'])) {
        fatal_lang_error('no_access', false);
    }
    if (!isset($_GET['openid_mode'])) {
        fatal_lang_error('openid_return_no_mode', false);
    }
    // @todo Check for error status!
    if ($_GET['openid_mode'] != 'id_res') {
        fatal_lang_error('openid_not_resolved');
    }
    // SMF has this annoying habit of removing the + from the base64 encoding.  So lets put them back.
    foreach (array('openid_assoc_handle', 'openid_invalidate_handle', 'openid_sig', 'sf') as $key) {
        if (isset($_GET[$key])) {
            $_GET[$key] = str_replace(' ', '+', $_GET[$key]);
        }
    }
    // Did they tell us to remove any associations?
    if (!empty($_GET['openid_invalidate_handle'])) {
        smf_openid_removeAssociation($_GET['openid_invalidate_handle']);
    }
    $server_info = smf_openid_getServerInfo($_GET['openid_identity']);
    // Get the association data.
    $assoc = smf_openID_getAssociation($server_info['server'], $_GET['openid_assoc_handle'], true);
    if ($assoc === null) {
        fatal_lang_error('openid_no_assoc');
    }
    $secret = base64_decode($assoc['secret']);
    $signed = explode(',', $_GET['openid_signed']);
    $verify_str = '';
    foreach ($signed as $sign) {
        $verify_str .= $sign . ':' . strtr($_GET['openid_' . str_replace('.', '_', $sign)], array('&amp;' => '&')) . "\n";
    }
    $verify_str = base64_encode(sha1_hmac($verify_str, $secret));
    if ($verify_str != $_GET['openid_sig']) {
        fatal_lang_error('openid_sig_invalid', 'critical');
    }
    if (!isset($_SESSION['openid']['saved_data'][$_GET['t']])) {
        fatal_lang_error('openid_load_data');
    }
    $openid_uri = $_SESSION['openid']['saved_data'][$_GET['t']]['openid_uri'];
    $modSettings['cookieTime'] = $_SESSION['openid']['saved_data'][$_GET['t']]['cookieTime'];
    if (empty($openid_uri)) {
        fatal_lang_error('openid_load_data');
    }
    // Any save fields to restore?
    $context['openid_save_fields'] = isset($_GET['sf']) ? unserialize(base64_decode($_GET['sf'])) : array();
    // Is there a user with this OpenID_uri?
    $result = $smcFunc['db_query']('', '
		SELECT passwd, id_member, id_group, lngfile, is_activated, email_address, additional_groups, member_name, password_salt,
			openid_uri
		FROM {db_prefix}members
		WHERE openid_uri = {string:openid_uri}', array('openid_uri' => $openid_uri));
    $member_found = $smcFunc['db_num_rows']($result);
    if (!$member_found && isset($_GET['sa']) && $_GET['sa'] == 'change_uri' && !empty($_SESSION['new_openid_uri']) && $_SESSION['new_openid_uri'] == $openid_uri) {
        // Update the member.
        updateMemberData($user_settings['id_member'], array('openid_uri' => $openid_uri));
        unset($_SESSION['new_openid_uri']);
        $_SESSION['openid'] = array('verified' => true, 'openid_uri' => $openid_uri);
        // Send them back to profile.
        redirectexit('action=profile;area=authentication;updated');
    } elseif (!$member_found) {
        // Store the received openid info for the user when returned to the registration page.
        $_SESSION['openid'] = array('verified' => true, 'openid_uri' => $openid_uri);
        if (isset($_GET['openid_sreg_nickname'])) {
            $_SESSION['openid']['nickname'] = $_GET['openid_sreg_nickname'];
        }
        if (isset($_GET['openid_sreg_email'])) {
            $_SESSION['openid']['email'] = $_GET['openid_sreg_email'];
        }
        if (isset($_GET['openid_sreg_dob'])) {
            $_SESSION['openid']['dob'] = $_GET['openid_sreg_dob'];
        }
        if (isset($_GET['openid_sreg_gender'])) {
            $_SESSION['openid']['gender'] = $_GET['openid_sreg_gender'];
        }
        // Were we just verifying the registration state?
        if (isset($_GET['sa']) && $_GET['sa'] == 'register2') {
            require_once $sourcedir . '/Register.php';
            return Register2(true);
        } else {
            redirectexit('action=register');
        }
    } elseif (isset($_GET['sa']) && $_GET['sa'] == 'revalidate' && $user_settings['openid_uri'] == $openid_uri) {
        $_SESSION['openid_revalidate_time'] = time();
        // Restore the get data.
        require_once $sourcedir . '/Subs-Auth.php';
        $_SESSION['openid']['saved_data'][$_GET['t']]['get']['openid_restore_post'] = $_GET['t'];
        $query_string = construct_query_string($_SESSION['openid']['saved_data'][$_GET['t']]['get']);
        redirectexit($query_string);
    } else {
        $user_settings = $smcFunc['db_fetch_assoc']($result);
        $smcFunc['db_free_result']($result);
        $user_settings['passwd'] = sha1(strtolower($user_settings['member_name']) . $secret);
        $user_settings['password_salt'] = substr(md5(mt_rand()), 0, 4);
        updateMemberData($user_settings['id_member'], array('passwd' => $user_settings['passwd'], 'password_salt' => $user_settings['password_salt']));
        // Cleanup on Aisle 5.
        $_SESSION['openid'] = array('verified' => true, 'openid_uri' => $openid_uri);
        require_once $sourcedir . '/LogInOut.php';
        if (!checkActivation()) {
            return;
        }
        DoLogin();
    }
}
 /**
  * Attempt to authenticate them with HybridAuth
  *
  * What it does:
  *  - takes the provider ID from GET var and attempts HybridAuth login.
  */
 public function action_extlogin()
 {
     global $context, $user_settings, $user_info, $modSettings;
     require_once SUBSDIR . '/Extauth.subs.php';
     // No provider? Not the user's fault. Silently go back to login.
     if (!isset($_GET['provider'])) {
         redirectexit('action=login');
     }
     // Include the HybridAuth external libaray and configuration
     $config = EXTDIR . '/hybridauth/config.php';
     require_once EXTDIR . '/hybridauth/Hybrid/Auth.php';
     try {
         $hybridauth = new Hybrid_Auth($config);
         // If it exists, go ahead and try it
         $provider = $_GET['provider'];
         $adapter = $hybridauth->authenticate($provider);
         $profile = $adapter->getUserProfile();
         $member_found = memberByExtUID($provider, $profile->identifier);
         // Test here whether it already exists or not and if so, login the user
         if ($member_found) {
             // Here, stuff happens to log the person in
             $user_settings = $member_found;
             require_once CONTROLLERDIR . '/Auth.controller.php';
             // Activation required?
             if (!checkActivation()) {
                 return;
             }
             // And then do the login. Bye!
             doLogin();
         } elseif (isset($_GET['member'])) {
             checkSession('get');
             $member = $_GET['member'];
             // Create an authentication
             addAuth($member, $provider, $profile->identifier, $profile->displayName);
             redirectexit('action=profile;area=extauth');
         } else {
             $_SESSION['extauth_info'] = array('provider' => $provider, 'uid' => $profile->identifier, 'name' => $profile->displayName);
             redirectexit('action=extauth;sa=register;provider=' . $provider);
         }
     } catch (Exception $e) {
         // In case we have errors 6 or 7, then we have to use Hybrid_Provider_Adapter::logout() to
         // let hybridauth forget all about the user so we can try to authenticate again.
         // Display the received error,
         // to know more please refer to Exceptions handling section on the userguide
         switch ($e->getCode()) {
             case 0:
                 echo "Unspecified error.";
                 break;
             case 1:
                 echo "Hybridauth configuration error.";
                 break;
             case 2:
                 echo "Provider not properly configured.";
                 break;
             case 3:
                 redirectexit('action=login');
                 break;
                 // Unknown or disabled provider
             // Unknown or disabled provider
             case 4:
                 echo "Missing provider application credentials.";
                 break;
             case 5:
                 echo "Authentication failed. " . "The user has canceled the authentication or the provider refused the connection.";
                 break;
             case 6:
                 echo "User profile request failed. Most likely the user is not connected " . "to the provider and he should to authenticate again.";
                 $adapter->logout();
                 break;
             case 7:
                 echo "User not connected to the provider.";
                 $adapter->logout();
                 break;
             case 8:
                 echo "Provider does not support this feature.";
                 break;
         }
     }
 }