/** * Will authenticate the username/password combo * * Use this before setting the cookie to check if the username password are correct. * * @param mixed $username the user's member name, email or member id * @param string $password the password plaintext or encrypted in any of several * methods including smf's method: sha1(strtolower($username) . $password) * @param bool $encrypted whether the password is encrypted or not. If you get this wrong we'll figure it out anyways, just saves some work if it's right * @return bool whether the user is authenticated or not * @since 0.1.0 */ function smfapi_authenticate($username = '', $password = '', $encrypted = true) { global $scripturl, $user_info, $user_settings, $smcFunc; global $cookiename, $modSettings, $sc, $sourcedir; if ('' == $username || '' == $password) { return false; } // just in case they used the email or member id... $data = smfapi_getUserData($username); if (empty($data)) { return false; } else { $username = $data['member_name']; } // 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($username) : $username)); // no user data found... invalid username if ($smcFunc['db_num_rows']($request) == 0) { return false; } $user_settings = $smcFunc['db_fetch_assoc']($request); $smcFunc['db_free_result']($request); if (40 != strlen($user_settings['passwd'])) { // invalid hash in the db return false; } // if it's not encrypted, do it now if (!$encrypted) { $sha_passwd = sha1(strtolower($user_settings['member_name']) . smfapi_unHtmlspecialchars($password)); } else { $sha_passwd = $password; } // if they match the password/hash is correct if ($user_settings['passwd'] == $sha_passwd) { $user_info["id"] = $user_settings['id_member']; return true; } else { // try other hashing schemes $other_passwords = array(); // in case they sent the encrypted password into this as unencrypted $other_passwords[] = $password; // 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($password, substr($password, 0, 2)); $other_passwords[] = crypt($password, substr($user_settings['passwd'], 0, 2)); $other_passwords[] = md5($password); $other_passwords[] = sha1($password); $other_passwords[] = md5_hmac($password, strtolower($user_settings['member_name'])); $other_passwords[] = md5($password . strtolower($user_settings['member_name'])); $other_passwords[] = md5(md5($password)); $other_passwords[] = $password; // this one is a strange one... MyPHP, crypt() on the MD5 hash $other_passwords[] = crypt(md5($password), md5($password)); // 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, $password)); } // phpBB3 users new hashing. We now support it as well ;) $other_passwords[] = phpBB3_password_check($password, $user_settings['passwd']); // APBoard 2 login method $other_passwords[] = md5(crypt($password, 'CRYPT_MD5')); } elseif (strlen($user_settings['passwd']) == 32) { // vBulletin 3 style hashing? Let's welcome them with open arms \o/ $other_passwords[] = md5(md5($password) . $user_settings['password_salt']); // hmm.. p'raps it's Invision 2 style? $other_passwords[] = md5(md5($user_settings['password_salt']) . md5($password)); // some common md5 ones $other_passwords[] = md5($user_settings['password_salt'] . $password); $other_passwords[] = md5($password . $user_settings['password_salt']); } 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']) . smfapi_unHtmlspecialchars($password)); // BurningBoard3 style of hashing $other_passwords[] = sha1($user_settings['password_salt'] . sha1($user_settings['password_salt'] . sha1($password))); // perhaps we converted to UTF-8 and have a valid password being // hashed differently if (!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'], $password))); } // 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($password, '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']) . smfapi_unHtmlspecialchars($password)); } // if ANY of these other hashes match we'll accept it if (in_array($user_settings['passwd'], $other_passwords)) { // we're not going to update the password or the hash. whatever was // used worked, so it will work again through this api, or SMF will // update it if the user authenticates through there. No sense messing // with it if it's not broken imo. Authentication successful $user_info["id"] = $user_settings['id_member']; return true; } } //authentication failed return false; }
/** * @param array $data */ public function OnUserChangePassword(array $data) { if (!defined('SMF') || SMF != 'API') { return; } if (!smfapi_getUserByUsername($data['user']->username)) { if (!$this->addUserToSMF($data['user']->username)) { return; } } smfapi_updateMemberData($data['user']->username, array('password' => sha1(strtolower($data['user']->username) . smfapi_unHtmlspecialchars($data['newpassword'])))); $contexts = $this->smfGetContexts(); if (in_array($this->modx->context->key, $contexts) && $this->modx->user->username == $data['user']->username) { smfapi_logout($data['user']->username); smfapi_login($data['user']->username); @session_write_close(); } }