private function DisplayError($message) { global $sso_header, $sso_footer, $sso_target_url, $sso_providers, $sso_selectors_url; echo $sso_header; SSO_OutputHeartbeat(); ?> <div class="sso_main_wrap"> <div class="sso_main_wrap_inner"> <div class="sso_main_messages_wrap"> <div class="sso_main_messages"> <div class="sso_main_messageerror"><?php echo htmlspecialchars($message); ?> </div> </div> </div> <div class="sso_main_info"><a href="<?php echo htmlspecialchars($sso_target_url); ?> "><?php echo htmlspecialchars(BB_Translate("Try again")); ?> </a><?php if (count($sso_providers) > 1) { ?> | <a href="<?php echo htmlspecialchars($sso_selectors_url); ?> "><?php echo htmlspecialchars(BB_Translate("Select another sign in method")); ?> </a><?php } ?> </div> </div> </div> <?php echo $sso_footer; }
public function ProcessFrontend() { global $sso_provider, $sso_settings, $sso_target_url, $sso_header, $sso_footer, $sso_providers, $sso_selectors_url; require_once SSO_ROOT_PATH . "/" . SSO_PROVIDER_PATH . "/" . $sso_provider . "/facebook.php"; $facebook = new SSO_FacebookSDK(array("appId" => $sso_settings["sso_facebook"]["app_id"], "secret" => $sso_settings["sso_facebook"]["app_secret"])); $id = $facebook->getUser(); if ($id) { try { // Calculate the required fields. $fields = array("id" => true, "first_name" => true, "last_name" => true); foreach (self::$fieldmap as $key => $info) { if ($sso_settings["sso_facebook"]["map_" . $key] != "" && !isset($info["pseudo"])) { $fields[isset($info["parent"]) ? $info["parent"] : $key] = true; } } $profile = $facebook->api("/me", "GET", array("fields" => implode(",", array_keys($fields)))); } catch (FacebookApiException $e) { // Fall through here to go to the next step. $id = 0; $exceptionmessage = $e->getMessage(); } } if (isset($_REQUEST["sso_facebook_action"]) && $_REQUEST["sso_facebook_action"] == "signin") { if ($id) { // Create a fake username based on available information. if ($sso_settings["sso_facebook"]["map_username"] != "") { if (isset($profile["email"])) { $profile["username"] = (string) @substr($profile["email"], 0, strpos($profile["email"], "@")); } else { if (isset($profile["first_name"]) && isset($profile["last_name"])) { $profile["username"] = $profile["first_name"] . @substr($profile["last_name"], 0, 1); } else { if (isset($profile["name"])) { $name = explode(" ", $name); $profile["username"] = $name[0] . @substr($name[count($name) - 1], 0, 1); } else { $profile["username"] = (string) $id; } } } $profile["username"] = preg_replace('/\\s+/', "_", trim(preg_replace('/[^a-z0-9]/', " ", strtolower((string) $profile["username"])))); } // Check username blacklist. $message = ""; if (isset($profile["username"])) { $blacklist = explode("\n", str_replace("\r", "\n", $sso_settings["sso_facebook"]["username_blacklist"])); foreach ($blacklist as $word) { $word = trim($word); if ($word != "" && stripos($profile["username"], $word) !== false) { $message = BB_Translate("Username contains a blocked word."); break; } } } // Check e-mail domain blacklist. if (isset($profile["email"])) { define("CS_TRANSLATE_FUNC", "BB_Translate"); require_once SSO_ROOT_PATH . "/" . SSO_SUPPORT_PATH . "/smtp.php"; $email = SMTP::MakeValidEmailAddress($profile["email"]); if (!$email["success"]) { $message = BB_Translate("Invalid e-mail address. %s", $email["error"]); } else { $domain = strtolower(substr($email["email"], strrpos($email["email"], "@") + 1)); $y = strlen($domain); $baddomains = explode("\n", strtolower($sso_settings["sso_facebook"]["email_bad_domains"])); foreach ($baddomains as $baddomain) { $baddomain = trim($baddomain); if ($baddomain != "") { $y2 = strlen($baddomain); if ($domain == $baddomain || $y < $y2 && substr($domain, $y - $y2 - 1, 1) == "." && substr($domain, $y - $y2) == $baddomain) { $message = BB_Translate("E-mail address is in a blacklisted domain."); break; } } } } } if ($message == "") { // Fix birthday to be in international format YYYY-MM-DD. if (isset($profile["birthday"])) { $birthday = explode("/", $profile["birthday"]); $year = array_pop($birthday); array_unshift($birthday, $year); $profile["birthday"] = implode("-", $birthday); } // Convert most profile fields into strings. foreach ($profile as $key => $val) { if (is_string($val)) { continue; } if (is_bool($val)) { $val = (string) (int) $val; } else { if (is_numeric($val)) { $val = (string) $val; } else { if (is_object($val) && isset($val->id) && isset($val->name)) { $val = $val->name; } } } $profile[$key] = $val; } // Convert specialized fields into strings. if (isset($profile["age_range"])) { $profile["age_range"] = trim($item->min . "-" . $item->max); } if (isset($profile["education"])) { $items = array(); foreach ($profile["education"] as $item) { $items[] = trim($item->year . " " . $item->type . " " . $item->school->name); } $profile["education"] = implode("\n", $items); } if (isset($profile["work"])) { $items = array(); foreach ($profile["work"] as $item) { $items[] = trim($item->employer . ", " . $item->location . ", " . $item->position); } $profile["work"] = implode("\n", $items); } $mapinfo = array(); foreach (self::$fieldmap as $key => $info) { $key2 = $sso_settings["sso_facebook"]["map_" . $key]; if ($key2 != "" && isset($profile[$key])) { $mapinfo[$key2] = $profile[$key]; } } // Process specialized fields. if (isset($profile["birthday"])) { $birthday = explode("-", $profile["birthday"]); $key = "birthday_year"; $key2 = $sso_settings["sso_facebook"]["map_" . $key]; if ($key2 != "") { $mapinfo[$key2] = $birthday[0]; } $key = "birthday_month"; $key2 = $sso_settings["sso_facebook"]["map_" . $key]; if ($key2 != "") { $mapinfo[$key2] = $birthday[1]; } $key = "birthday_day"; $key2 = $sso_settings["sso_facebook"]["map_" . $key]; if ($key2 != "") { $mapinfo[$key2] = $birthday[2]; } } SSO_ActivateUser($profile["id"], serialize($profile), $mapinfo); // Only falls through on account lockout or a fatal error. $message = BB_Translate("User activation failed."); } } else { if (isset($_REQUEST["error"]) && $_REQUEST["error"] == "access_denied") { $message = BB_Translate("The request to sign in with Facebook was denied."); } else { if (isset($_REQUEST["error_description"])) { $message = BB_Translate($_REQUEST["error_description"]); } else { $message = BB_Translate("An unknown error occurred. %s", $exceptionmessage); } } } $message = BB_Translate("Sign in failed. %s", $message); echo $sso_header; SSO_OutputHeartbeat(); ?> <div class="sso_main_wrap"> <div class="sso_main_wrap_inner"> <div class="sso_main_messages_wrap"> <div class="sso_main_messages"> <div class="sso_main_messageerror"><?php echo htmlspecialchars($message); ?> </div> </div> </div> <div class="sso_main_info"><a href="<?php echo htmlspecialchars($sso_target_url); ?> "><?php echo htmlspecialchars(BB_Translate("Try again")); ?> </a><?php if (count($sso_providers) > 1) { ?> | <a href="<?php echo htmlspecialchars($sso_selectors_url); ?> "><?php echo htmlspecialchars(BB_Translate("Select another sign in method")); ?> </a><?php } ?> </div> </div> </div> <?php echo $sso_footer; } else { // Calculate the required scope. $scope = array(); foreach (self::$fieldmap as $key => $info) { if ($info["extra"] != "" && $sso_settings["sso_facebook"]["map_" . $key] != "") { $scope[$info["extra"]] = true; } } // Get the login redirection URL. $options = array("scope" => implode(",", array_keys($scope)), "redirect_uri" => BB_GetRequestHost() . $sso_target_url . "&sso_facebook_action=signin"); $url = $facebook->getLoginUrl($options); SSO_ExternalRedirect($url); } }
$sso_target_url = SSO_ROOT_URL . "/" . $sso_indexphp . "?sso_provider=" . urlencode($sso_provider) . (isset($_REQUEST["lang"]) ? "&lang=" . urlencode($_REQUEST["lang"]) : ""); ob_start(); $sso_providers[$sso_provider]->ProcessFrontend(); $data = ob_get_contents(); ob_end_clean(); // Allow a frontend hook function to modify the output of providers. // Useful for changing class names for projects like Twitter Bootstrap. if (function_exists("FrontendHook_ProcessOutput")) { $data = FrontendHook_ProcessOutput($data); } echo $data; } else { SSO_ActivateImpersonationUser(); SSO_ActivateNamespaceUser(); echo $sso_header; SSO_OutputHeartbeat(); ?> <div class="sso_selector_wrap"> <div class="sso_selector_wrap_inner"> <div class="sso_selector_header"><?php echo htmlspecialchars(BB_Translate("Select Sign In Method")); ?> </div> <div class="sso_selectors"> <?php $outputmap = array(); foreach ($sso_providers as $sso_provider => &$instance) { $sso_target_url = SSO_ROOT_URL . "/" . $sso_indexphp . "?sso_provider=" . urlencode($sso_provider) . (isset($_REQUEST["lang"]) ? "&lang=" . urlencode($_REQUEST["lang"]) : ""); ob_start(); $sso_providers[$sso_provider]->GenerateSelector(); $order = isset($sso_settings[""]["order"][$sso_provider]) ? $sso_settings[""]["order"][$sso_provider] : $instance->DefaultOrder();
public function ProcessFrontend() { global $g_sso_login_modules, $sso_settings, $sso_rng, $sso_header, $sso_footer, $sso_target_url, $sso_db, $sso_ipaddr_info, $sso_session_info, $sso_providers; if (!isset($sso_ipaddr_info["sso_login_modules"])) { $sso_ipaddr_info["sso_login_modules"] = array(); } // Initialize active modules. $this->activemodules = array(); foreach ($g_sso_login_modules as $key => $info) { if ($sso_settings["sso_login"]["modules"][$key]["_a"]) { $module = "sso_login_module_" . $key; $this->activemodules[$key] = new $module(); } } $sso_db_sso_login_users = SSO_DB_PREFIX . "p_sso_login_users"; if (isset($_REQUEST["sso_login_action"]) && $_REQUEST["sso_login_action"] == "module" && isset($_REQUEST["sso_login_module"]) && isset($this->activemodules[$_REQUEST["sso_login_module"]])) { $this->activemodules[$_REQUEST["sso_login_module"]]->CustomFrontend(); } else { if (isset($_REQUEST["sso_login_action"]) && $_REQUEST["sso_login_action"] == "verify" && $sso_settings["sso_login"]["open_reg"]) { $messages = array("errors" => array(), "warnings" => array(), "success" => ""); foreach ($this->activemodules as &$instance) { $instance->VerifyCheck($messages); } if (!count($messages["errors"])) { if (!isset($_REQUEST["sso_v"]) || !isset($sso_session_info["sso_login_verify"])) { $messages["errors"][] = BB_Translate("Invalid URL. Verification missing."); } else { if (trim($_REQUEST["sso_v"]) !== $sso_session_info["sso_login_verify"]["v"]) { $messages["errors"][] = BB_Translate("Invalid verification string specified."); } else { try { $sso_db->Query("UPDATE", array($sso_db_sso_login_users, array("verified" => 1), "WHERE" => "id = ?"), $sso_session_info["sso_login_verify"]["id"]); } catch (Exception $e) { $messages["errors"][] = BB_Translate("Verification failed. Database query error."); } if (!count($messages["errors"])) { header("Location: " . BB_GetRequestHost() . $sso_target_url . "&sso_msg=verified"); exit; } } } } echo $sso_header; SSO_OutputHeartbeat(); ?> <div class="sso_main_wrap sso_login"> <div class="sso_main_wrap_inner"> <?php $this->DisplayMessages($messages, false); ?> <div class="sso_login_signin"><a href="<?php echo htmlspecialchars($sso_target_url); ?> "><?php echo htmlspecialchars(BB_Translate("Sign in")); ?> </a></div> </div> </div> <?php echo $sso_footer; } else { if (isset($_REQUEST["sso_login_action"]) && $_REQUEST["sso_login_action"] == "signup_check" && $sso_settings["sso_login"]["open_reg"]) { $result = $this->SignupUpdateCheck(true, false, false, false); foreach ($result["errors"] as $error) { echo "<div class=\"sso_main_formerror\">" . htmlspecialchars($error) . "</div>"; } foreach ($result["warnings"] as $warning) { echo "<div class=\"sso_main_formwarning\">" . htmlspecialchars($warning) . "</div>"; } if (!count($result["errors"]) && !count($result["warnings"])) { if ($result["success"] != "") { echo "<div class=\"sso_main_formokay\">" . htmlspecialchars($result["success"]) . "</div>"; } else { if (isset($result["htmlsuccess"]) && $result["htmlsuccess"] != "") { echo "<div class=\"sso_main_formokay\">" . $result["htmlsuccess"] . "</div>"; } } } } else { if (isset($_REQUEST["sso_login_action"]) && $_REQUEST["sso_login_action"] == "signup" && $sso_settings["sso_login"]["open_reg"]) { if (SSO_FrontendFieldValue("submit") === false) { $messages = false; } else { $messages = $this->SignupUpdateCheck(false, false, false, false); if (!count($messages["errors"])) { // Create the account. $username = SSO_FrontendFieldValue("username", ""); $email = SSO_FrontendFieldValue("email", ""); $verified = true; if ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "email") { $result = SMTP::MakeValidEmailAddress($email); $email = $result["email"]; $verified = $sso_settings["sso_login"]["email_verify_subject"] == "" || $sso_settings["sso_login"]["email_verify_msg"] == ""; } $salt = $sso_rng->GenerateString(); $data = $username . ":" . $email . ":" . $salt . ":" . SSO_FrontendFieldValue("createpass"); $passwordinfo = self::HashPasswordInfo($data, $sso_settings["sso_login"]["password_mode"], $sso_settings["sso_login"]["password_minrounds"]); if (!$passwordinfo["success"]) { $messages["errors"][] = BB_Translate("Unexpected cryptography error."); } else { $userinfo = array(); $userinfo["extra"] = $sso_rng->GenerateString(); $userinfo["two_factor_key"] = $sso_session_info["sso_login_two_factor_key"]; $userinfo["two_factor_method"] = SSO_FrontendFieldValue("two_factor_method", ""); foreach ($this->activemodules as &$instance) { $instance->SignupAddInfo($userinfo, false); } $userinfo["salt"] = $salt; $userinfo["rounds"] = (int) $passwordinfo["rounds"]; $userinfo["password"] = bin2hex($passwordinfo["hash"]); $userinfo2 = SSO_EncryptDBData($userinfo); try { if ($sso_settings["sso_login"]["install_type"] == "email_username") { $sso_db->Query("INSERT", array($sso_db_sso_login_users, array("username" => $username, "email" => $email, "verified" => (int) $verified, "created" => CSDB::ConvertToDBTime(time()), "info" => $userinfo2), "AUTO INCREMENT" => "id")); } else { if ($sso_settings["sso_login"]["install_type"] == "email") { $sso_db->Query("INSERT", array($sso_db_sso_login_users, array("email" => $email, "verified" => (int) $verified, "created" => CSDB::ConvertToDBTime(time()), "info" => $userinfo2), "AUTO INCREMENT" => "id")); } else { if ($sso_settings["sso_login"]["install_type"] == "username") { $sso_db->Query("INSERT", array($sso_db_sso_login_users, array("username" => $username, "created" => CSDB::ConvertToDBTime(time()), "info" => $userinfo2), "AUTO INCREMENT" => "id")); } else { $messages["errors"][] = BB_Translate("Fatal error: Login system is broken."); } } } // Send verification e-mail. if (!count($messages["errors"])) { $userid = $sso_db->GetInsertID(); } if (!count($messages["errors"]) && !$verified) { $this->SendVerificationEmail($userid, $userinfo, $messages, $username, $email); } } catch (Exception $e) { $messages["errors"][] = BB_Translate("Database query error."); } if (!count($messages["errors"])) { foreach ($this->activemodules as &$instance) { $instance->SignupDone($userid, false); } header("Location: " . BB_GetRequestHost() . $sso_target_url . "&sso_msg=" . ($verified ? "verified" : "verify")); exit; } } } } echo $sso_header; SSO_OutputHeartbeat(); $this->OutputJS($sso_target_url . "&sso_login_action=signup_check&sso_ajax=1"); ?> <div class="sso_main_wrap sso_login"> <div class="sso_main_wrap_inner"> <?php $this->DisplayMessages($messages); ?> <div class="sso_login_signin"><a href="<?php echo htmlspecialchars($sso_target_url); ?> "><?php echo htmlspecialchars(BB_Translate("Sign in")); ?> </a></div> <div class="sso_main_form_wrap sso_login_signup_form"> <div class="sso_main_form_header"><?php echo htmlspecialchars(BB_Translate("Sign up")); ?> </div> <form class="sso_main_form" name="sso_login_form" method="post" accept-charset="UTF-8" enctype="multipart/form-data" action="<?php echo htmlspecialchars($sso_target_url . "&sso_login_action=signup"); ?> " autocomplete="off"> <?php if ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "email") { ?> <div class="sso_main_formitem"> <div class="sso_main_formtitle"><?php echo htmlspecialchars(BB_Translate("Your E-mail Address")); ?> </div> <div class="sso_main_formdata"><input class="sso_main_text sso_login_changehook" type="text" name="<?php echo SSO_FrontendField("email"); ?> " value="<?php echo htmlspecialchars(SSO_FrontendFieldValue("email", "")); ?> " /></div> </div> <?php } if ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "username") { ?> <div class="sso_main_formitem"> <div class="sso_main_formtitle"><?php echo htmlspecialchars(BB_Translate("Choose Username")); ?> </div> <div class="sso_main_formdata"><input class="sso_main_text sso_login_changehook" type="text" name="<?php echo SSO_FrontendField("username"); ?> " value="<?php echo htmlspecialchars(SSO_FrontendFieldValue("username", "")); ?> " /></div> </div> <?php } ?> <script type="text/javascript"> jQuery('input.sso_main_text:first').focus(); </script> <div class="sso_main_formitem"> <div class="sso_main_formtitle"><?php echo htmlspecialchars(BB_Translate("Choose Password")); ?> </div> <div class="sso_main_formdata"><input class="sso_main_text sso_login_changehook" type="password" name="<?php echo SSO_FrontendField("createpass"); ?> " value="<?php echo htmlspecialchars(SSO_FrontendFieldValue("createpass", "")); ?> " /></div> </div> <?php $outputmap = array(); // Two-factor authentication dropdown. $outputmap2 = array(); $method = SSO_FrontendFieldValue("two_factor_method", ""); foreach ($this->activemodules as $key => &$instance) { $name = $instance->GetTwoFactorName(); if ($name !== false) { $order = isset($sso_settings["sso_login"]["modules"][$key]["_s"]) ? $sso_settings["sso_login"]["modules"][$key]["_s"] : $instance->DefaultOrder(); SSO_AddSortedOutput($outputmap2, $order, $key, "<option value=\"" . htmlspecialchars($key) . "\"" . ($method == $key ? " selected" : "") . ">" . htmlspecialchars($name) . "</option>"); } } if (!$sso_settings["sso_login"]["require_two_factor"] && count($outputmap2)) { SSO_AddSortedOutput($outputmap2, 0, "", "<option value=\"\"" . ($method == "" ? " selected" : "") . ">" . htmlspecialchars(BB_Translate("None")) . "</option>"); } if (count($outputmap2)) { if (!isset($sso_session_info["sso_login_two_factor_key"])) { $sso_session_info["sso_login_two_factor_key"] = self::GenerateOTPKey(10); SSO_SaveSessionInfo(); } ob_start(); ?> <div class="sso_main_formitem"> <div class="sso_main_formtitle"><?php echo htmlspecialchars(BB_Translate("Choose Two-Factor Authentication Method")); ?> </div> <div class="sso_main_formdata"><select class="sso_main_dropdown sso_login_changehook_two_factor" name="<?php echo SSO_FrontendField("two_factor_method"); ?> "> <?php SSO_DisplaySortedOutput($outputmap2); ?> </select></div> <div class="sso_main_formdesc"><?php echo htmlspecialchars(BB_Translate($sso_settings["sso_login"]["require_two_factor"] ? "Required. Two-factor authentication vastly improves the security of your account." : "Optional. Two-factor authentication vastly improves the security of your account.")); ?> </div> </div> <?php $order = $sso_settings["sso_login"]["two_factor_order"]; SSO_AddSortedOutput($outputmap, $order, "two_factor", ob_get_contents()); ob_end_clean(); } // Add active module output. foreach ($this->activemodules as $key => &$instance) { ob_start(); $instance->GenerateSignup(false); $order = isset($sso_settings["sso_login"]["modules"][$key]["_s"]) ? $sso_settings["sso_login"]["modules"][$key]["_s"] : $instance->DefaultOrder(); SSO_AddSortedOutput($outputmap, $order, $key, ob_get_contents()); ob_end_clean(); } SSO_DisplaySortedOutput($outputmap); ?> <div class="sso_main_formsubmit"> <input type="submit" name="<?php echo SSO_FrontendField("submit"); ?> " value="<?php echo htmlspecialchars(BB_Translate("Sign up")); ?> " /> </div> </form> </div> </div> </div> <?php echo $sso_footer; } else { if (isset($_REQUEST["sso_login_action"]) && $_REQUEST["sso_login_action"] == "update_info") { // Check the session and load the user account. $messages = array("errors" => array(), "warnings" => array(), "success" => ""); foreach ($this->activemodules as &$instance) { $instance->UpdateInfoCheck($messages, false, false); } $userrow = false; if (!count($messages["errors"])) { if (!isset($_REQUEST["sso_v"]) || !isset($sso_session_info["sso_login_update"])) { $messages["errors"][] = BB_Translate("Invalid URL. Verification missing."); } else { if (trim($_REQUEST["sso_v"]) !== $sso_session_info["sso_login_update"]["v"]) { $messages["errors"][] = BB_Translate("Invalid verification string specified."); } else { if (!isset($sso_session_info["sso_login_update"]["expires"]) || CSDB::ConvertFromDBTime($sso_session_info["sso_login_update"]["expires"]) < time()) { $messages["errors"][] = BB_Translate("Update information is expired or invalid."); } else { try { $userrow = $sso_db->GetRow("SELECT", array("*", "FROM" => "?", "WHERE" => "id = ?"), $sso_db_sso_login_users, $sso_session_info["sso_login_update"]["id"]); if ($userrow === false) { $messages["errors"][] = BB_Translate("Update information is expired or invalid."); } else { if (!isset($userrow->username)) { $userrow->username = ""; } if (!isset($userrow->email)) { $userrow->email = ""; } if (!isset($userrow->verified)) { $userrow->verified = 1; } } } catch (Exception $e) { $messages["errors"][] = BB_Translate("User check failed. Database query error."); } } } } } if (!count($messages["errors"])) { $userinfo = SSO_DecryptDBData($userrow->info); if ($userinfo === false) { $messages["errors"][] = BB_Translate("Error loading user information."); } } if (isset($_REQUEST["sso_ajax"])) { if (!count($messages["errors"])) { $messages = $this->SignupUpdateCheck(true, $userrow, $userinfo, false); } foreach ($messages["errors"] as $error) { echo "<div class=\"sso_main_formerror\">" . htmlspecialchars($error) . "</div>"; } foreach ($messages["warnings"] as $warning) { echo "<div class=\"sso_main_formwarning\">" . htmlspecialchars($warning) . "</div>"; } if (!count($messages["errors"]) && !count($messages["warnings"])) { if ($messages["success"] != "") { echo "<div class=\"sso_main_formokay\">" . htmlspecialchars($messages["success"]) . "</div>"; } else { if ($messages["htmlsuccess"] != "") { echo "<div class=\"sso_main_formokay\">" . $messages["htmlsuccess"] . "</div>"; } } } } else { if (count($messages["errors"])) { echo $sso_header; SSO_OutputHeartbeat(); ?> <div class="sso_main_wrap sso_login"> <div class="sso_main_wrap_inner"> <?php $this->DisplayMessages($messages, false); ?> <div class="sso_login_signin"><a href="<?php echo htmlspecialchars($sso_target_url); ?> "><?php echo htmlspecialchars(BB_Translate("Sign in")); ?> </a></div> </div> </div> <?php echo $sso_footer; } else { $messagesheader = false; $messages = false; if (SSO_FrontendFieldValue("submit") === false) { if (isset($_REQUEST["sso_msg"])) { $messages = array("errors" => array(), "warnings" => array(), "success" => ""); foreach ($this->activemodules as &$instance) { $instance->InitMessages($messages); } } } else { $messages = $this->SignupUpdateCheck(false, $userrow, $userinfo, false); if (!count($messages["errors"])) { // Update the account. if ($sso_settings["sso_login"]["change_username"] && ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "username")) { $username = SSO_FrontendFieldValue("update_username", ""); } else { $username = $userrow->username; } if ($sso_settings["sso_login"]["change_email"] && ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "email")) { $email = SSO_FrontendFieldValue("update_email", ""); $result = SMTP::MakeValidEmailAddress($email); $email = $result["email"]; $verified = $sso_settings["sso_login"]["email_verify_subject"] == "" || $sso_settings["sso_login"]["email_verify_msg"] == "" || $userrow->email == $email; } else { $email = $userrow->email; $verified = $userrow->verified; } if (SSO_FrontendFieldValue("update_pass", "") != "") { $salt = $sso_rng->GenerateString(); $data = $username . ":" . $email . ":" . $salt . ":" . SSO_FrontendFieldValue("update_pass"); $passwordinfo = self::HashPasswordInfo($data, $sso_settings["sso_login"]["password_mode"], $sso_settings["sso_login"]["password_minrounds"]); if (!$passwordinfo["success"]) { $messages["errors"][] = BB_Translate("Unexpected cryptography error."); } else { $numrounds = (int) $passwordinfo["rounds"]; $password = bin2hex($passwordinfo["hash"]); } } else { if ($username != $userrow->username || $email != $userrow->email) { $messages["errors"][] = BB_Translate("Please enter a new password."); } else { $salt = $userinfo["salt"]; $numrounds = $userinfo["rounds"]; $password = $userinfo["password"]; } } if (SSO_FrontendFieldValue("reset_two_factor_key", "") == "yes") { $sso_session_info["sso_login_two_factor_key"] = self::GenerateOTPKey(10); SSO_SaveSessionInfo(); $messages["errors"][] = BB_Translate("Two-factor authentication security key has been reset."); } if (!count($messages["errors"])) { $userinfo["two_factor_key"] = $sso_session_info["sso_login_two_factor_key"]; $userinfo["two_factor_method"] = SSO_FrontendFieldValue("update_two_factor_method", ""); foreach ($this->activemodules as &$instance) { $instance->UpdateAddInfo($userinfo); } $userinfo["salt"] = $salt; $userinfo["rounds"] = $numrounds; $userinfo["password"] = $password; $userinfo2 = SSO_EncryptDBData($userinfo); try { if ($sso_settings["sso_login"]["install_type"] == "email_username") { $sso_db->Query("UPDATE", array($sso_db_sso_login_users, array("username" => $username, "email" => $email, "verified" => (int) $verified, "info" => $userinfo2), "WHERE" => "id = ?"), $userrow->id); } else { if ($sso_settings["sso_login"]["install_type"] == "email") { $sso_db->Query("UPDATE", array($sso_db_sso_login_users, array("email" => $email, "verified" => (int) $verified, "info" => $userinfo2), "WHERE" => "id = ?"), $userrow->id); } else { if ($sso_settings["sso_login"]["install_type"] == "username") { $sso_db->Query("UPDATE", array($sso_db_sso_login_users, array("username" => $username, "info" => $userinfo2), "WHERE" => "id = ?"), $userrow->id); } else { $messages["errors"][] = BB_Translate("Fatal error: Login system is broken."); } } } // Send verification e-mail. $userid = $userrow->id; if (!count($messages["errors"]) && !$verified) { $this->SendVerificationEmail($userid, $userinfo, $messages, $username, $email); } } catch (Exception $e) { $messages["errors"][] = BB_Translate("Database query error."); } if (!count($messages["errors"])) { foreach ($this->activemodules as &$instance) { $instance->UpdateInfoDone($userid); } header("Location: " . BB_GetRequestHost() . $sso_target_url . "&sso_msg=" . ($verified ? "updated" : "verify")); exit; } } } } echo $sso_header; SSO_OutputHeartbeat(); $this->OutputJS($sso_target_url . "&sso_login_action=update_info&sso_v=" . urlencode($_REQUEST["sso_v"]) . "&sso_ajax=1"); ?> <div class="sso_main_wrap sso_login"> <div class="sso_main_wrap_inner"> <?php $this->DisplayMessages($messages); ?> <div class="sso_login_signin"><a href="<?php echo htmlspecialchars($sso_target_url); ?> "><?php echo htmlspecialchars(BB_Translate("Sign in")); ?> </a></div> <div class="sso_main_form_wrap sso_login_updateinfo_form"> <div class="sso_main_form_header"><?php echo htmlspecialchars(BB_Translate("Update Information")); ?> </div> <form class="sso_main_form" name="sso_login_form" method="post" accept-charset="UTF-8" enctype="multipart/form-data" action="<?php echo htmlspecialchars($sso_target_url . "&sso_login_action=update_info&sso_v=" . urlencode($_REQUEST["sso_v"])); ?> " autocomplete="off"> <?php if ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "email") { ?> <div class="sso_main_formitem"> <div class="sso_main_formtitle"><?php echo htmlspecialchars(BB_Translate("Your E-mail Address")); ?> </div> <div class="sso_main_formdata"><?php if ($sso_settings["sso_login"]["change_email"]) { ?> <input class="sso_main_text sso_login_changehook" type="text" name="<?php echo SSO_FrontendField("update_email"); ?> " value="<?php echo htmlspecialchars(SSO_FrontendFieldValue("update_email", $userrow->email)); ?> " /><?php } else { ?> <input type="hidden" name="<?php echo SSO_FrontendField("update_email"); ?> " value="<?php echo htmlspecialchars(SSO_FrontendFieldValue("update_email", $userrow->email)); ?> " /><div class="sso_main_static"><?php echo htmlspecialchars($userrow->email); ?> </div><?php } ?> </div> </div> <?php } if ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "username") { ?> <div class="sso_main_formitem"> <div class="sso_main_formtitle"><?php echo htmlspecialchars(BB_Translate("Your Username")); ?> </div> <div class="sso_main_formdata"><?php if ($sso_settings["sso_login"]["change_username"]) { ?> <input class="sso_main_text sso_login_changehook" type="text" name="<?php echo SSO_FrontendField("update_username"); ?> " value="<?php echo htmlspecialchars(SSO_FrontendFieldValue("update_username", $userrow->username)); ?> " /><?php } else { ?> <input type="hidden" name="<?php echo SSO_FrontendField("update_username"); ?> " value="<?php echo htmlspecialchars(SSO_FrontendFieldValue("update_username", $userrow->username)); ?> " /><div class="sso_main_static"><?php echo htmlspecialchars($userrow->username); ?> </div><?php } ?> </div> </div> <?php } ?> <div class="sso_main_formitem"> <div class="sso_main_formtitle"><?php echo htmlspecialchars(BB_Translate("New Password")); ?> </div> <div class="sso_main_formdata"><input class="sso_main_text sso_login_changehook" type="password" name="<?php echo SSO_FrontendField("update_pass"); ?> " value="<?php echo htmlspecialchars(SSO_FrontendFieldValue("update_pass", "")); ?> " /></div> <div class="sso_main_formdesc"><?php echo htmlspecialchars(BB_Translate("Optional. Will change the password for the account.")); ?> </div> </div> <script type="text/javascript"> jQuery('input.sso_main_text:first').focus(); </script> <?php $outputmap = array(); // Two-factor authentication dropdown. $outputmap2 = array(); $method = SSO_FrontendFieldValue("update_two_factor_method", isset($updateinfo["two_factor_method"]) ? $updateinfo["two_factor_method"] : ""); foreach ($this->activemodules as $key => &$instance) { $name = $instance->GetTwoFactorName(); if ($name !== false) { $order = isset($sso_settings["sso_login"]["modules"][$key]["_s"]) ? $sso_settings["sso_login"]["modules"][$key]["_s"] : $instance->DefaultOrder(); SSO_AddSortedOutput($outputmap2, $order, $key, "<option value=\"" . htmlspecialchars($key) . "\"" . ($method == $key ? " selected" : "") . ">" . htmlspecialchars($name) . "</option>"); } } if (!$sso_settings["sso_login"]["require_two_factor"] && count($outputmap2)) { SSO_AddSortedOutput($outputmap2, 0, "", "<option value=\"\"" . ($method == "" ? " selected" : "") . ">" . htmlspecialchars(BB_Translate("None")) . "</option>"); } if (count($outputmap2)) { if (!isset($sso_session_info["sso_login_two_factor_key"])) { $sso_session_info["sso_login_two_factor_key"] = self::GenerateOTPKey(10); SSO_SaveSessionInfo(); } ob_start(); ?> <div class="sso_main_formitem"> <div class="sso_main_formtitle"><?php echo htmlspecialchars(BB_Translate("Choose Two-Factor Authentication Method")); ?> </div> <div class="sso_main_formdata"><select class="sso_main_dropdown sso_login_changehook_two_factor" name="<?php echo SSO_FrontendField("update_two_factor_method"); ?> "> <?php SSO_DisplaySortedOutput($outputmap2); ?> </select></div> <div class="sso_main_formdesc"><?php echo htmlspecialchars(BB_Translate($sso_settings["sso_login"]["require_two_factor"] ? "Required. Two-factor authentication vastly improves the security of your account." : "Optional. Two-factor authentication vastly improves the security of your account.")); ?> </div> <div class="sso_main_formtwofactorreset"><input id="sso_two_factor_reset" type="checkbox" name="<?php echo SSO_FrontendField("reset_two_factor_key"); ?> " value="yes"> <label for="sso_two_factor_reset"><?php echo htmlspecialchars(BB_Translate("Reset two-factor authentication security key")); ?> </label></div> </div> <?php $order = $sso_settings["sso_login"]["two_factor_order"]; SSO_AddSortedOutput($outputmap, $order, "two_factor", ob_get_contents()); ob_end_clean(); } // Add active module output. foreach ($this->activemodules as $key => &$instance) { ob_start(); $instance->GenerateUpdateInfo($userrow, $userinfo); $order = isset($sso_settings["sso_login"]["modules"][$key]["_s"]) ? $sso_settings["sso_login"]["modules"][$key]["_s"] : $instance->DefaultOrder(); SSO_AddSortedOutput($outputmap, $order, $key, ob_get_contents()); ob_end_clean(); } SSO_DisplaySortedOutput($outputmap); ?> <div class="sso_main_formsubmit"> <input type="submit" name="<?php echo SSO_FrontendField("submit"); ?> " value="<?php echo htmlspecialchars(BB_Translate("Update")); ?> " /> </div> </form> </div> </div> </div> <?php } } } else { if (isset($_REQUEST["sso_login_action"]) && $_REQUEST["sso_login_action"] == "recover2" && isset($_REQUEST["sso_method"]) && $this->IsRecoveryAllowed()) { // Load and validate the recovery options. $userrow = false; if (isset($sso_session_info["sso_login_recover"]) && isset($sso_session_info["sso_login_recover"]["id"]) && isset($sso_session_info["sso_login_recover"]["method"]) && $sso_session_info["sso_login_recover"]["method"] == $_REQUEST["sso_method"]) { try { $userrow = $sso_db->GetRow("SELECT", array("*", "FROM" => "?", "WHERE" => "id = ?"), $sso_db_sso_login_users, $sso_session_info["sso_login_recover"]["id"]); if ($userrow) { if (!isset($userrow->username)) { $userrow->username = ""; } if (!isset($userrow->email)) { $userrow->email = ""; } if (!isset($userrow->verified)) { $userrow->verified = 1; } } } catch (Exception $e) { header("Location: " . BB_GetRequestHost() . $sso_target_url . "&sso_login_action=recover&sso_msg=recovery_db_error"); exit; } } if ($userrow === false) { header("Location: " . BB_GetRequestHost() . $sso_target_url . "&sso_login_action=recover&sso_msg=recovery_expired_invalid"); exit; } $userinfo = SSO_DecryptDBData($userrow->info); if ($userinfo === false) { header("Location: " . BB_GetRequestHost() . $sso_target_url . "&sso_login_action=recover&sso_msg=recovery_db_user_error"); exit; } $messagesheader = false; $messages = false; if (SSO_FrontendFieldValue("submit") === false) { if (isset($_REQUEST["sso_msg"])) { $messages = array("errors" => array(), "warnings" => array(), "success" => ""); foreach ($this->activemodules as &$instance) { $instance->InitMessages($messages); } } } else { $messages = array("errors" => array(), "warnings" => array(), "success" => ""); foreach ($this->activemodules as &$instance) { $instance->RecoveryCheck2($messages, false); } if (!count($messages["errors"])) { foreach ($this->activemodules as &$instance) { $instance->RecoveryCheck2($messages, $userinfo); } if (!count($messages["errors"])) { $sso_session_info["sso_login_update"] = array("id" => $userrow->id, "v" => $sso_rng->GenerateString(), "expires" => CSDB::ConvertToDBTime(time() + 30 * 60)); $sso_session_info["sso_login_two_factor_key"] = isset($userinfo["two_factor_key"]) && $userinfo["two_factor_key"] != "" ? $userinfo["two_factor_key"] : self::GenerateOTPKey(10); if (!SSO_SaveSessionInfo()) { $result["errors"][] = BB_Translate("Recovery was successful but a fatal error occurred. Fatal error: Unable to save session information."); } else { header("Location: " . BB_GetRequestHost() . $sso_target_url . "&sso_login_action=update_info&sso_v=" . urlencode($sso_session_info["sso_login_update"]["v"])); exit; } } } } echo $sso_header; SSO_OutputHeartbeat(); $this->OutputJS(); ?> <div class="sso_main_wrap sso_login"> <div class="sso_main_wrap_inner"> <?php $this->DisplayMessages($messages, $messagesheader); ?> <div class="sso_login_signin"><a href="<?php echo htmlspecialchars($sso_target_url); ?> "><?php echo htmlspecialchars(BB_Translate("Sign in")); ?> </a></div> <div class="sso_main_form_wrap sso_login_recover_form"> <div class="sso_main_form_header"><?php echo htmlspecialchars(BB_Translate("Restore Access")); ?> </div> <form class="sso_main_form" name="sso_login_form" method="post" accept-charset="UTF-8" enctype="multipart/form-data" action="<?php echo htmlspecialchars($sso_target_url . "&sso_login_action=recover2&sso_method=" . urlencode($_REQUEST["sso_method"])); ?> " autocomplete="off"> <?php $outputmap = array(); foreach ($this->activemodules as $key => &$instance) { ob_start(); $instance->GenerateRecovery2($messages); $order = isset($sso_settings["sso_login"]["modules"][$key]["_s"]) ? $sso_settings["sso_login"]["modules"][$key]["_s"] : $instance->DefaultOrder(); SSO_AddSortedOutput($outputmap, $order, $key, ob_get_contents()); ob_end_clean(); } SSO_DisplaySortedOutput($outputmap); ?> <script type="text/javascript"> jQuery('input.sso_main_text:first').focus(); </script> <div class="sso_main_formsubmit"> <input type="submit" name="<?php echo SSO_FrontendField("submit"); ?> " value="<?php echo htmlspecialchars(BB_Translate("Next")); ?> " /> </div> </form> </div> </div> </div> <?php echo $sso_footer; } else { if (isset($_REQUEST["sso_login_action"]) && $_REQUEST["sso_login_action"] == "recover" && $this->IsRecoveryAllowed()) { $messagesheader = false; $messages = false; if (SSO_FrontendFieldValue("submit") === false) { if (isset($_REQUEST["sso_msg"])) { $messages = array("errors" => array(), "warnings" => array(), "success" => ""); if ($_REQUEST["sso_msg"] == "recovery_db_error") { $messages["warnings"][] = BB_Translate("A database error occurred while attempting to load recovery information."); } else { if ($_REQUEST["sso_msg"] == "recovery_expired_invalid") { $messages["errors"][] = BB_Translate("Recovery information is expired or invalid."); } else { if ($_REQUEST["sso_msg"] == "recovery_db_user_error") { $messages["errors"][] = BB_Translate("User information in the database is corrupted."); } else { foreach ($this->activemodules as &$instance) { $instance->InitMessages($messages); } } } } } } else { $messages = array("errors" => array(), "warnings" => array(), "success" => ""); $user = SSO_FrontendFieldValue("user_recover"); $method = SSO_FrontendFieldValue("recover_method"); if ($user === false || $user == "" || $method === false || $method == "") { $messages["errors"][] = BB_Translate("Please fill in the fields."); } else { foreach ($this->activemodules as &$instance) { $instance->RecoveryCheck($messages, false); } if (!count($messages["errors"])) { $userrow = false; if ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "email") { try { $userrow = $sso_db->GetRow("SELECT", array("*", "FROM" => "?", "WHERE" => "email = ?"), $sso_db_sso_login_users, $user); if ($userrow) { if (!isset($userrow->username)) { $userrow->username = ""; } } } catch (Exception $e) { $messages["errors"][] = BB_Translate("User check failed. Database query error."); } } else { if ($sso_settings["sso_login"]["install_type"] == "username") { try { $userrow = $sso_db->GetRow("SELECT", array("*", "FROM" => "?", "WHERE" => "username = ?"), $sso_db_sso_login_users, $user); if ($userrow) { if (!isset($userrow->email)) { $userrow->email = ""; } if (!isset($userrow->verified)) { $userrow->verified = 1; } } } catch (Exception $e) { $messages["errors"][] = BB_Translate("User check failed. Database query error."); } } else { $messages["errors"][] = BB_Translate("Login system is broken."); } } if ($userrow === false) { $messages["errors"][] = BB_Translate("Invalid login."); } else { $userinfo = SSO_DecryptDBData($userrow->info); if ($userinfo === false) { $messages["errors"][] = BB_Translate("Error loading user information."); } else { foreach ($this->activemodules as &$instance) { $instance->RecoveryCheck($messages, $userinfo); } } } if (!count($messages["errors"])) { if ($method == "email" && $userrow->email != "") { $sso_session_info["sso_login_update"] = array("id" => $userrow->id, "v" => $sso_rng->GenerateString(), "expires" => CSDB::ConvertToDBTime(time() + 30 * 60)); $sso_session_info["sso_login_two_factor_key"] = isset($userinfo["two_factor_key"]) && $userinfo["two_factor_key"] != "" ? $userinfo["two_factor_key"] : self::GenerateOTPKey(10); if (!SSO_SaveSessionInfo()) { $messages["errors"][] = BB_Translate("Login exists but a fatal error occurred. Fatal error: Unable to save session information."); } else { $fromaddr = BB_PostTranslate($sso_settings["sso_login"]["email_recover_from"] != "" ? $sso_settings["sso_login"]["email_recover_from"] : SSO_SMTP_FROM); $subject = BB_Translate($sso_settings["sso_login"]["email_recover_subject"]); $verifyurl = BB_GetRequestHost() . $sso_target_url . ($sso_settings["sso_login"]["email_session"] == "all" ? "&sso_id=" . urlencode($_REQUEST["sso_id"]) : "") . "&sso_login_action=update_info&sso_v=" . urlencode($sso_session_info["sso_login_update"]["v"]); $htmlmsg = str_ireplace(array("@USERNAME@", "@EMAIL@", "@VERIFY@"), array(htmlspecialchars($userrow->username), htmlspecialchars($userrow->email), htmlspecialchars($verifyurl)), BB_PostTranslate($sso_settings["sso_login"]["email_recover_msg"])); $textmsg = str_ireplace(array("@USERNAME@", "@EMAIL@", "@VERIFY@"), array($userrow->username, $userrow->email, $verifyurl), BB_PostTranslate($sso_settings["sso_login"]["email_recover_msg_text"])); foreach ($this->activemodules as &$instance) { $instance->ModifyEmail($userinfo, $htmlmsg, $textmsg); } $result = SSO_SendEmail($fromaddr, $userrow->email, $subject, $htmlmsg, $textmsg); if (!$result["success"]) { $messages["errors"][] = BB_Translate("Login exists but a fatal error occurred. Fatal error: Unable to send verification e-mail. %s", $result["error"]); } else { foreach ($this->activemodules as &$instance) { $instance->RecoveryDone($messages, $method, $userrow, $userinfo); } if (!count($messages["errors"])) { header("Location: " . BB_GetRequestHost() . $sso_target_url . "&sso_msg=recovery_email_sent"); exit; } } } } else { foreach ($this->activemodules as &$instance) { $instance->RecoveryDone($messages, $method, $userrow, $userinfo); } } } } } } echo $sso_header; SSO_OutputHeartbeat(); $this->OutputJS(); ?> <div class="sso_main_wrap sso_login"> <div class="sso_main_wrap_inner"> <?php $this->DisplayMessages($messages, $messagesheader); ?> <div class="sso_login_signin"><a href="<?php echo htmlspecialchars($sso_target_url); ?> "><?php echo htmlspecialchars(BB_Translate("Sign in")); ?> </a></div> <div class="sso_main_form_wrap sso_login_recover_form"> <div class="sso_main_form_header"><?php echo htmlspecialchars(BB_Translate("Restore Access")); ?> </div> <form class="sso_main_form" name="sso_login_form" method="post" accept-charset="UTF-8" enctype="multipart/form-data" action="<?php echo htmlspecialchars($sso_target_url . "&sso_login_action=recover"); ?> " autocomplete="off"> <div class="sso_main_formitem"> <div class="sso_main_formtitle"><?php if ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "email") { echo htmlspecialchars(BB_Translate("E-mail Address")); } else { if ($sso_settings["sso_login"]["install_type"] == "username") { echo htmlspecialchars(BB_Translate("Username")); } else { echo htmlspecialchars(BB_Translate("Login system is broken.")); } } ?> </div> <div class="sso_main_formdata"><input class="sso_main_text" type="text" name="<?php echo SSO_FrontendField("user_recover"); ?> " /></div> </div> <script type="text/javascript"> jQuery('input.sso_main_text:first').focus(); </script> <div class="sso_main_formitem"> <div class="sso_main_formtitle"><?php echo htmlspecialchars(BB_Translate("Recovery Method")); ?> </div> <div class="sso_main_formdata"><select class="sso_main_dropdown" name="<?php echo SSO_FrontendField("recover_method"); ?> "> <?php $method = SSO_FrontendFieldValue("recover_method", ""); if ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "email") { echo "<option value=\"email\"" . ($method == "email" ? " selected" : "") . ">" . htmlspecialchars(BB_Translate("E-mail")) . "</option>"; } foreach ($this->activemodules as &$instance) { $instance->AddRecoveryMethod($method); } ?> </select></div> </div> <?php $outputmap = array(); foreach ($this->activemodules as $key => &$instance) { ob_start(); $instance->GenerateRecovery($messages); $order = isset($sso_settings["sso_login"]["modules"][$key]["_s"]) ? $sso_settings["sso_login"]["modules"][$key]["_s"] : $instance->DefaultOrder(); SSO_AddSortedOutput($outputmap, $order, $key, ob_get_contents()); ob_end_clean(); } SSO_DisplaySortedOutput($outputmap); ?> <div class="sso_main_formsubmit"> <input type="submit" name="<?php echo SSO_FrontendField("submit"); ?> " value="<?php echo htmlspecialchars(BB_Translate("Next")); ?> " /> </div> </form> </div> </div> </div> <?php echo $sso_footer; } else { if (isset($_REQUEST["sso_login_action"]) && $_REQUEST["sso_login_action"] == "two_factor") { // Check the session and load the user account. $messages = array("errors" => array(), "warnings" => array(), "success" => ""); foreach ($this->activemodules as &$instance) { $instance->TwoFactorCheck($messages, false); } $userrow = false; if (!count($messages["errors"])) { if (!isset($_REQUEST["sso_v"]) || !isset($sso_session_info["sso_login_two_factor"])) { $messages["errors"][] = BB_Translate("Invalid URL. Verification missing."); } else { if (trim($_REQUEST["sso_v"]) !== $sso_session_info["sso_login_two_factor"]["v"]) { $messages["errors"][] = BB_Translate("Invalid verification string specified."); } else { if (!isset($sso_session_info["sso_login_two_factor"]["expires"]) || CSDB::ConvertFromDBTime($sso_session_info["sso_login_two_factor"]["expires"]) < time()) { $messages["errors"][] = BB_Translate("Two-factor information is expired or invalid."); } else { try { $userrow = $sso_db->GetRow("SELECT", array("*", "FROM" => "?", "WHERE" => "id = ?"), $sso_db_sso_login_users, $sso_session_info["sso_login_two_factor"]["id"]); if ($userrow === false) { $messages["errors"][] = BB_Translate("Two-factor information is expired or invalid."); } else { if (!isset($userrow->username)) { $userrow->username = ""; } if (!isset($userrow->email)) { $userrow->email = ""; } if (!isset($userrow->verified)) { $userrow->verified = 1; } } } catch (Exception $e) { $messages["errors"][] = BB_Translate("User check failed. Database query error."); } } } } } $method = BB_Translate("Unknown/Invalid."); if (!count($messages["errors"])) { $userinfo = SSO_DecryptDBData($userrow->info); if ($userinfo === false) { $messages["errors"][] = BB_Translate("Error loading user information."); } else { // Check the two-factor authentication method. $methods = array(); foreach ($this->activemodules as $key => &$instance) { $name = $instance->GetTwoFactorName(false); if ($name !== false) { $methods[$key] = $name; } } if (isset($userinfo["two_factor_method"]) && isset($methods[$userinfo["two_factor_method"]])) { $method = $methods[$userinfo["two_factor_method"]]; } else { $messages["errors"][] = BB_Translate("A valid two-factor authentication method for this account is not available. Use account recovery to restore access to the account."); } } } if (count($messages["errors"])) { echo $sso_header; SSO_OutputHeartbeat(); ?> <div class="sso_main_wrap sso_login"> <div class="sso_main_wrap_inner"> <?php $this->DisplayMessages($messages, false); ?> <div class="sso_login_signin"><a href="<?php echo htmlspecialchars($sso_target_url); ?> "><?php echo htmlspecialchars(BB_Translate("Sign in")); ?> </a></div> </div> </div> <?php echo $sso_footer; } else { $messagesheader = false; $messages = false; if (SSO_FrontendFieldValue("submit") === false) { if (isset($_REQUEST["sso_msg"])) { $messages = array("errors" => array(), "warnings" => array(), "success" => ""); foreach ($this->activemodules as &$instance) { $instance->InitMessages($messages); } } } else { $messages = array("errors" => array(), "warnings" => array(), "success" => ""); foreach ($this->activemodules as &$instance) { $instance->TwoFactorCheck($messages, $userinfo); } if (count($messages["errors"])) { foreach ($this->activemodules as &$instance) { $instance->TwoFactorFailed($messages, $userinfo); } } else { // Login with two-factor authentication succeeded. Activate the user. $mapinfo = array(); if ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "email") { $mapinfo[$sso_settings["sso_login"]["map_email"]] = $userrow->email; } if ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "username") { $mapinfo[$sso_settings["sso_login"]["map_username"]] = $userrow->username; } $origuserinfo = $userinfo; foreach ($this->activemodules as &$instance) { $instance->LoginAddMap($mapinfo, $userrow, $userinfo, false); } // If a module updated $userinfo, then update the database. if (serialize($userinfo) !== serialize($origuserinfo)) { $userinfo2 = SSO_EncryptDBData($userinfo); try { $sso_db->Query("UPDATE", array($sso_db_sso_login_users, array("info" => $userinfo2), "WHERE" => "id = ?"), $userrow->id); } catch (Exception $e) { $messages["errors"][] = BB_Translate("Database query error."); } } if (!count($messages["errors"])) { SSO_ActivateUser($userrow->id, $userinfo["extra"], $mapinfo, CSDB::ConvertFromDBTime($userrow->created)); // Only falls through on account lockout or a fatal error. $messages["errors"][] = BB_Translate("User activation failed."); } } } echo $sso_header; SSO_OutputHeartbeat(); $this->OutputJS(); ?> <div class="sso_main_wrap sso_login"> <div class="sso_main_wrap_inner"> <?php $this->DisplayMessages($messages, $messagesheader); ?> <div class="sso_login_signin"><a href="<?php echo htmlspecialchars($sso_target_url); ?> "><?php echo htmlspecialchars(BB_Translate("Sign in")); ?> </a></div> <div class="sso_main_form_wrap sso_login_recover_form"> <div class="sso_main_form_header"><?php echo htmlspecialchars(BB_Translate("Two-Factor Authentication")); ?> </div> <form class="sso_main_form" name="sso_login_form" method="post" accept-charset="UTF-8" enctype="multipart/form-data" action="<?php echo htmlspecialchars($sso_target_url . "&sso_login_action=two_factor&sso_v=" . urlencode($_REQUEST["sso_v"])); ?> " autocomplete="off"> <div class="sso_main_formitem"> <div class="sso_main_formtitle"><?php echo htmlspecialchars(BB_Translate("Enter Two-Factor Authentication Code")); ?> </div> <div class="sso_main_formdata"><input class="sso_main_text" type="text" name="<?php echo SSO_FrontendField("two_factor_code"); ?> " /></div> <div class="sso_main_formdesc"><?php echo htmlspecialchars(BB_Translate("From %s.", $method)); ?> </div> </div> <script type="text/javascript"> jQuery('input.sso_main_text:first').focus(); </script> <div class="sso_main_formsubmit"> <input type="submit" name="<?php echo SSO_FrontendField("submit"); ?> " value="<?php echo htmlspecialchars(BB_Translate("Sign in")); ?> " /> </div> </form> </div> </div> </div> <?php echo $sso_footer; } } else { $messagesheader = false; $messages = false; if (SSO_FrontendFieldValue("submit") === false) { if (isset($_REQUEST["sso_msg"])) { $messages = array("errors" => array(), "warnings" => array(), "success" => ""); if ($_REQUEST["sso_msg"] == "verified") { $messages["success"] = BB_Translate("Your account is ready to use."); } else { if ($_REQUEST["sso_msg"] == "verify") { $messages["warnings"][] = BB_Translate("Account must be verified before it can be used. Check your e-mail."); } else { if ($_REQUEST["sso_msg"] == "recovery_email_sent") { $messages["warnings"][] = BB_Translate("Account recovery URL sent. Check your e-mail."); } else { if ($_REQUEST["sso_msg"] == "updated") { $messages["success"] = BB_Translate("Your account information has been updated and is ready to use."); } else { if ($_REQUEST["sso_msg"] == "two_factor_auth_expired") { $messages["errors"][] = BB_Translate("Two-factor authentication expired. Sign in again."); } else { foreach ($this->activemodules as &$instance) { $instance->InitMessages($messages); } } } } } } } } else { $messages = array("errors" => array(), "warnings" => array(), "success" => ""); $user = SSO_FrontendFieldValue("user"); $password = SSO_FrontendFieldValue("password"); if ($user === false || $user == "" || $password === false || $password == "") { $messages["errors"][] = BB_Translate("Please fill in the fields."); } else { $recoveryallowed = $this->IsRecoveryAllowed(false); foreach ($this->activemodules as &$instance) { $instance->LoginCheck($messages, false, $recoveryallowed); } if (!count($messages["errors"])) { $userrow = false; if (strpos($user, "@") !== false && ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "email")) { try { $userrow = $sso_db->GetRow("SELECT", array("*", "FROM" => "?", "WHERE" => "email = ?"), $sso_db_sso_login_users, $user); if ($userrow) { $userinfo = SSO_DecryptDBData($userrow->info); if ($userinfo === false) { $userrow = false; } else { if (!isset($userrow->username)) { $userrow->username = ""; } $data = $userrow->username . ":" . $userrow->email . ":" . $userinfo["salt"] . ":" . $password; if (!self::VerifyPasswordInfo($data, $userinfo["password"], $userinfo["rounds"])) { $userrow = false; } } } } catch (Exception $e) { $messages["errors"][] = BB_Translate("Login failed. Database query error."); } } if ($userrow === false && ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "username")) { try { $userrow = $sso_db->GetRow("SELECT", array("*", "FROM" => "?", "WHERE" => "username = ?"), $sso_db_sso_login_users, $user); if ($userrow) { $userinfo = SSO_DecryptDBData($userrow->info); if ($userinfo === false) { $userrow = false; } else { if (!isset($userrow->email)) { $userrow->email = ""; } if (!isset($userrow->verified)) { $userrow->verified = 1; } $data = $userrow->username . ":" . $userrow->email . ":" . $userinfo["salt"] . ":" . $password; if (!self::VerifyPasswordInfo($data, $userinfo["password"], $userinfo["rounds"])) { $userrow = false; } } } } catch (Exception $e) { $messages["errors"][] = BB_Translate("Login failed. Database query error."); } } if ($userrow === false) { $messages["errors"][] = BB_Translate("Invalid login."); } else { // Make sure the password is stored securely. If not, transparently update the hash information in the database. if ($userinfo["rounds"] < $sso_settings["sso_login"]["password_minrounds"]) { $userinfo["salt"] = $sso_rng->GenerateString(); $data = $userrow->username . ":" . $userrow->email . ":" . $userinfo["salt"] . ":" . $password; $passwordinfo = self::HashPasswordInfo($data, $sso_settings["sso_login"]["password_mode"], $sso_settings["sso_login"]["password_minrounds"]); if ($passwordinfo["success"]) { $userinfo["rounds"] = (int) $passwordinfo["rounds"]; $userinfo["password"] = bin2hex($passwordinfo["hash"]); $userinfo2 = SSO_EncryptDBData($userinfo); try { $sso_db->Query("UPDATE", array($sso_db_sso_login_users, array("info" => $userinfo2), "WHERE" => "id = ?"), $userrow->id); } catch (Exception $e) { $messages["errors"][] = BB_Translate("Database query error."); } } } foreach ($this->activemodules as &$instance) { $instance->LoginCheck($messages, $userinfo, $recoveryallowed); } } if (!count($messages["errors"])) { // Go to two-factor authentication page. $methods = array(); foreach ($this->activemodules as $key => &$instance) { $name = $instance->GetTwoFactorName(false); if ($name !== false) { $methods[$key] = true; } } // Resend the verification e-mail. if (!$userrow->verified) { $this->SendVerificationEmail($userrow->id, $userinfo, $messages, $userrow->username, $userrow->email); } else { if (!$recoveryallowed && SSO_FrontendFieldValue("update_info", "") == "yes") { $sso_session_info["sso_login_update"] = array("id" => $userrow->id, "v" => $sso_rng->GenerateString(), "expires" => CSDB::ConvertToDBTime(time() + 30 * 60)); $sso_session_info["sso_login_two_factor_key"] = isset($userinfo["two_factor_key"]) && $userinfo["two_factor_key"] != "" ? $userinfo["two_factor_key"] : self::GenerateOTPKey(10); if (!SSO_SaveSessionInfo()) { $messages["errors"][] = BB_Translate("Login exists but a fatal error occurred. Fatal error: Unable to save session information."); } else { header("Location: " . BB_GetRequestHost() . $sso_target_url . "&sso_login_action=update_info&sso_v=" . urlencode($sso_session_info["sso_login_update"]["v"])); exit; } } else { if ($sso_settings["sso_login"]["require_two_factor"] || isset($userinfo["two_factor_method"]) && $userinfo["two_factor_method"] != "" && (count($methods) || ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "email"))) { if ($sso_settings["sso_login"]["require_two_factor"] && (!isset($userinfo["two_factor_method"]) || !isset($methods[$userinfo["two_factor_method"]]))) { $messages["errors"][] = BB_Translate("A valid two-factor authentication method for this account is not available. Use account recovery to restore access to the account."); } else { $sso_session_info["sso_login_two_factor"] = array("id" => $userrow->id, "v" => $sso_rng->GenerateString(), "expires" => CSDB::ConvertToDBTime(time() + 5 * 60)); if (!SSO_SaveSessionInfo()) { $messages["errors"][] = BB_Translate("Login exists but a fatal error occurred. Fatal error: Unable to save session information."); } else { $this->activemodules[$userinfo["two_factor_method"]]->SendTwoFactorCode($messages, $userrow, $userinfo); if (!count($messages["errors"])) { header("Location: " . BB_GetRequestHost() . $sso_target_url . "&sso_login_action=two_factor&sso_v=" . urlencode($sso_session_info["sso_login_two_factor"]["v"])); exit; } } } } else { // Login succeeded. Activate the user. $mapinfo = array(); if ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "email") { $mapinfo[$sso_settings["sso_login"]["map_email"]] = $userrow->email; } if ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "username") { $mapinfo[$sso_settings["sso_login"]["map_username"]] = $userrow->username; } $origuserinfo = $userinfo; foreach ($this->activemodules as &$instance) { $instance->LoginAddMap($mapinfo, $userrow, $userinfo, false); } // If a module updated $userinfo, then update the database. if (serialize($userinfo) !== serialize($origuserinfo)) { $userinfo2 = SSO_EncryptDBData($userinfo); try { $sso_db->Query("UPDATE", array($sso_db_sso_login_users, array("info" => $userinfo2), "WHERE" => "id = ?"), $userrow->id); } catch (Exception $e) { $messages["errors"][] = BB_Translate("Database query error."); } } if (!count($messages["errors"])) { SSO_ActivateUser($userrow->id, $userinfo["extra"], $mapinfo, CSDB::ConvertFromDBTime($userrow->created)); // Only falls through on account lockout or a fatal error. $messages["errors"][] = BB_Translate("User activation failed."); } } } } } } } } echo $sso_header; SSO_OutputHeartbeat(); $this->OutputJS(); ?> <div class="sso_main_wrap sso_login"> <div class="sso_main_wrap_inner"> <?php $this->DisplayMessages($messages, $messagesheader); if ($sso_settings["sso_login"]["open_reg"]) { ?> <div class="sso_login_signup"><a href="<?php echo htmlspecialchars($sso_target_url . "&sso_login_action=signup"); ?> "><?php echo htmlspecialchars(BB_Translate("Sign up")); ?> </a></div> <?php } ?> <div class="sso_main_form_wrap sso_login_signin_form"> <div class="sso_main_form_header"><?php echo htmlspecialchars(BB_Translate("Sign in")); ?> </div> <form class="sso_main_form" name="sso_login_form" method="post" accept-charset="UTF-8" enctype="multipart/form-data" action="<?php echo htmlspecialchars($sso_target_url); ?> " autocomplete="off"> <div class="sso_main_formitem"> <div class="sso_main_formtitle"><?php if ($sso_settings["sso_login"]["install_type"] == "email_username") { echo htmlspecialchars(BB_Translate("Username or E-mail Address")); } else { if ($sso_settings["sso_login"]["install_type"] == "username") { echo htmlspecialchars(BB_Translate("Username")); } else { if ($sso_settings["sso_login"]["install_type"] == "email") { echo htmlspecialchars(BB_Translate("E-mail Address")); } else { echo htmlspecialchars(BB_Translate("Login system is broken.")); } } } ?> </div> <div class="sso_main_formdata"><input class="sso_main_text" type="text" name="<?php echo SSO_FrontendField("user"); ?> " /></div> </div> <script type="text/javascript"> jQuery('input.sso_main_text:first').focus(); </script> <div class="sso_main_formitem"> <div class="sso_main_formtitle"><?php echo htmlspecialchars(BB_Translate("Password")); ?> </div> <div class="sso_main_formdata"><input class="sso_main_text" type="password" name="<?php echo SSO_FrontendField("password"); ?> " /></div> </div> <?php $outputmap = array(); foreach ($this->activemodules as $key => &$instance) { ob_start(); $instance->GenerateLogin($messages); $order = isset($sso_settings["sso_login"]["modules"][$key]["_s"]) ? $sso_settings["sso_login"]["modules"][$key]["_s"] : $instance->DefaultOrder(); SSO_AddSortedOutput($outputmap, $order, $key, ob_get_contents()); ob_end_clean(); } SSO_DisplaySortedOutput($outputmap); if (!$this->IsRecoveryAllowed(false)) { ?> <div class="sso_main_formitem"> <div class="sso_main_formtitle"><?php echo htmlspecialchars(BB_Translate("Update Information")); ?> </div> <div class="sso_main_formdata"><input id="sso_norecovery_updateinfo" type="checkbox" name="<?php echo SSO_FrontendField("update_info"); ?> " value="yes"<?php if (SSO_FrontendFieldValue("update_info", "") == "yes") { echo " checked"; } ?> /> <label for="sso_norecovery_updateinfo">Change account information upon successful sign in</label></div> </div> <?php } ?> <div class="sso_main_formsubmit"> <input type="submit" name="<?php echo SSO_FrontendField("submit"); ?> " value="<?php echo htmlspecialchars(BB_Translate("Sign in")); ?> " /> </div> </form> </div> <?php if ($this->IsRecoveryAllowed()) { ?> <div class="sso_login_recover_changeinfo"><a href="<?php echo htmlspecialchars($sso_target_url . "&sso_login_action=recover"); ?> "><?php echo htmlspecialchars(BB_Translate("Can't access your account?")); ?> </a></div> <?php } ?> </div> </div> <?php echo $sso_footer; } } } } } } } } }
public function ProcessFrontend() { global $sso_provider, $sso_settings, $sso_target_url, $sso_header, $sso_footer, $sso_providers; $message = ""; if (SSO_FrontendFieldValue("submit") !== false) { $username = SSO_FrontendFieldValue("username"); $password = SSO_FrontendFieldValue("password"); if ($username === false || $username == "" || $password === false || $sso_settings["sso_ldap"]["password"] && $password == "") { $message = BB_Translate("Please fill in the fields."); } else { $ldap = @ldap_connect($sso_settings["sso_ldap"]["server"]); if ($ldap === false) { $message = BB_Translate("Unable to connect to the LDAP server. Error: %s", ldap_error($ldap)); } else { $replacemap = array("," => "\\,", "\\" => "\\\\", "/" => "\\/", "#" => "\\#", "+" => "\\+", "<" => "\\<", ">" => "\\>", ";" => "\\;", "\"" => "\\\"", "=" => "\\="); $dnusername = str_replace(array_keys($replacemap), array_values($replacemap), $username); if (substr($dnusername, 0, 1) === " ") { $dnusername = "******" . $dnusername; } if (strlen($dnusername) > 2 && substr($dnusername, -1) === " ") { $dnusername = substr($dnusername, 0, -1) . "\\ "; } $dn = str_replace("@USERNAME@", $dnusername, $sso_settings["sso_ldap"]["dn"]); $userinfo = array(); @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); $result = @ldap_bind($ldap, $dn, $password); if ($result === false && ldap_errno($ldap)) { $extra = ldap_error($ldap); } else { $extra = ""; $result = @ldap_read($ldap, $dn, "objectClass=*"); if (!is_resource($result)) { $extra = ldap_error($ldap); $result = false; } else { $items = @ldap_get_entries($ldap, $result); @ldap_free_result($result); $result = $items["count"] > 0; // Boil down the results to just key-value pairs. if ($result === false) { $extra = "Unable to retrieve entries"; } else { foreach ($items[0] as $key => $val) { if (is_string($key) && $key != "count") { if (is_string($val)) { $userinfo[$key] = $val; } else { if (is_array($val) && $val["count"] > 0) { $userinfo[$key] = $val[0]; } } } } if ($sso_settings["sso_ldap"]["debug"]) { echo "LDAP fields:<br />"; echo "<table>"; foreach ($userinfo as $key => $val) { echo "<tr><td style=\"padding-right: 15px;\"><b>" . htmlspecialchars($key) . "</b></td><td>" . htmlspecialchars($val) . "</td></tr>"; } echo "</table>"; } } } } @ldap_close($ldap); if ($result === false) { $message = BB_Translate("Invalid username or password. %s.", $extra); } else { $origusername = $username; if ($sso_settings["sso_ldap"]["remove_domain"]) { $username = str_replace("\\", "/", $username); $pos = strrpos("/", $username); if ($pos !== false) { $username = substr($username, $pos + 1); } } $mapinfo = array(); $lines = explode("\n", str_replace("\r", "\n", $sso_settings["sso_ldap"]["map_custom"])); foreach ($lines as $line) { $line = trim($line); $pos = strpos($line, "="); if ($pos !== false) { $srcfield = substr($line, 0, $pos); $destfield = substr($line, $pos + 1); if (isset($userinfo[$srcfield]) && SSO_IsField($destfield)) { $mapinfo[$destfield] = $userinfo[$srcfield]; } } } $mapinfo[$sso_settings["sso_ldap"]["map_username"]] = $username; if ($sso_settings["sso_ldap"]["debug"]) { echo "Mapped fields:<br />"; echo "<table>"; foreach ($mapinfo as $key => $val) { echo "<tr><td style=\"padding-right: 15px;\"><b>" . htmlspecialchars($key) . "</b></td><td>" . htmlspecialchars($val) . "</td></tr>"; } echo "</table>"; exit; } SSO_ActivateUser($dn, serialize($sso_settings["sso_ldap"]), $mapinfo); // Only falls through on account lockout or a fatal error. $message = BB_Translate("User activation failed."); } } } } echo $sso_header; SSO_OutputHeartbeat(); ?> <script type="text/javascript"> SSO_Vars = { 'showpassword' : '<?php echo htmlspecialchars(BB_JSSafe(BB_Translate("Show password"))); ?> ' }; </script> <script type="text/javascript" src="<?php echo htmlspecialchars(SSO_ROOT_URL . "/" . SSO_PROVIDER_PATH . "/sso_ldap/sso_ldap.js"); ?> "></script> <div class="sso_main_wrap sso_ldap"> <div class="sso_main_wrap_inner"> <?php if ($message != "") { ?> <div class="sso_main_messages_wrap"> <div class="sso_main_messages"> <div class="sso_main_messageerror"><?php echo htmlspecialchars($message); ?> </div> </div> </div> <?php } ?> <div class="sso_main_form_wrap sso_ldap_signin_form"> <div class="sso_main_form_header"><?php echo htmlspecialchars(BB_Translate("Sign in")); ?> </div> <form class="sso_main_form" name="sso_ldap_form" method="post" accept-charset="UTF-8" enctype="multipart/form-data" action="<?php echo htmlspecialchars($sso_target_url); ?> "> <div class="sso_main_formitem"> <div class="sso_main_formtitle"><?php echo htmlspecialchars(BB_Translate("Username")); ?> </div> <div class="sso_main_formdata"><input class="sso_main_text" type="text" name="<?php echo SSO_FrontendField("username"); ?> " /></div> </div> <script type="text/javascript"> jQuery('input.sso_main_text:first').focus(); </script> <div class="sso_main_formitem"> <div class="sso_main_formtitle"><?php echo htmlspecialchars(BB_Translate("Password")); ?> </div> <div class="sso_main_formdata"><input class="sso_main_text" type="password" name="<?php echo SSO_FrontendField("password"); ?> " /></div> </div> <div class="sso_main_formsubmit"> <input type="submit" name="<?php echo SSO_FrontendField("submit"); ?> " value="<?php echo htmlspecialchars(BB_Translate("Sign in")); ?> " /> </div> </form> </div> <?php ?> </div> </div> <?php echo $sso_footer; }
public function CustomFrontend() { global $g_sso_login_modules, $sso_settings, $sso_header, $sso_footer, $sso_target_url, $sso_db, $sso_session_info, $sso_rng; $messages = array("errors" => array(), "warnings" => array(), "success" => ""); $info = $this->GetInfo(); if ($info["cookiekey"] != "" && $info["cookieiv"] != "" && $info["cookiekey2"] != "" && $info["cookieiv2"] != "") { // Initialize active modules. $this->activemodules = array(); foreach ($g_sso_login_modules as $key => $info2) { if ($sso_settings["sso_login"]["modules"][$key]["_a"]) { $module = "sso_login_module_" . $key; $this->activemodules[$key] = new $module(); } } $sso_db_sso_login_users = SSO_DB_PREFIX . "p_sso_login_users"; if (isset($_REQUEST["id"]) && isset($_COOKIE["sso_l_rme"])) { // Decrypt data. $info2 = @base64_decode($_COOKIE["sso_l_rme"]); if ($info2 !== false) { $info2 = Blowfish::ExtractDataPacket($info2, pack("H*", $info["cookiekey"]), array("mode" => "CBC", "iv" => pack("H*", $info["cookieiv"]), "key2" => pack("H*", $info["cookiekey2"]), "iv2" => pack("H*", $info["cookieiv2"]), "lightweight" => true)); } if ($info2 !== false) { $info2 = @unserialize($info2); } if ($info2 !== false) { $id = (int) $_REQUEST["id"]; if (isset($info2[$id]) && is_array($info2[$id]) && count($info2[$id]) == 2) { // Load database information and verify the sign in. $userrow = $sso_db->GetRow("SELECT", array("*", "FROM" => "?", "WHERE" => "id = ?"), $sso_db_sso_login_users, $id); if ($userrow && (!isset($userrow->verified) || $userrow->verified)) { $userinfo = SSO_DecryptDBData($userrow->info); if ($userinfo !== false && isset($userinfo["sso_remember_me"]) && isset($userinfo["sso_remember_me"][$info2[$userrow->id][0]])) { $info3 = $userinfo["sso_remember_me"][$info2[$userrow->id][0]]; $ts = CSDB::ConvertFromDBTime($info3["expires"]); if ($ts > time()) { $data = $info3["salt"] . ":" . $info2[$userrow->id][1]; if (sso_login::VerifyPasswordInfo($data, $info3["hash"], $info3["rounds"])) { // Sign in is now verified to be valid. if (!$info3["bypass"] && ($sso_settings["sso_login"]["require_two_factor"] || isset($userinfo["two_factor_method"]) && $userinfo["two_factor_method"] != "")) { // Go to two-factor authentication page. $methods = array(); foreach ($this->activemodules as $key => &$instance) { $name = $instance->GetTwoFactorName(false); if ($name !== false) { $methods[$key] = true; } } if ($sso_settings["sso_login"]["require_two_factor"] && (!isset($userinfo["two_factor_method"]) || !isset($methods[$userinfo["two_factor_method"]]))) { $messages["errors"][] = BB_Translate("A valid two-factor authentication method for this account is not available. Use account recovery to restore access to the account."); } else { $sso_session_info["sso_login_two_factor"] = array("id" => $userrow->id, "v" => $sso_rng->GenerateString(), "expires" => CSDB::ConvertToDBTime(time() + 5 * 60)); if (!SSO_SaveSessionInfo()) { $messages["errors"][] = BB_Translate("Login exists but a fatal error occurred. Fatal error: Unable to save session information."); } else { $this->activemodules[$userinfo["two_factor_method"]]->SendTwoFactorCode($messages, $userrow, $userinfo); if (!count($messages["errors"])) { header("Location: " . BB_GetRequestHost() . $sso_target_url . "&sso_login_action=two_factor&sso_v=" . urlencode($sso_session_info["sso_login_two_factor"]["v"])); exit; } } } } else { // Login succeeded. Activate the user. $mapinfo = array(); if ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "email") { $mapinfo[$sso_settings["sso_login"]["map_email"]] = $userrow->email; } if ($sso_settings["sso_login"]["install_type"] == "email_username" || $sso_settings["sso_login"]["install_type"] == "username") { $mapinfo[$sso_settings["sso_login"]["map_username"]] = $userrow->username; } $origuserinfo = $userinfo; foreach ($this->activemodules as &$instance) { $instance->LoginAddMap($mapinfo, $userrow, $userinfo, false); } // If a module updated $userinfo, then update the database. if (serialize($userinfo) !== serialize($origuserinfo)) { $userinfo2 = SSO_EncryptDBData($userinfo); try { $sso_db->Query("UPDATE", array($sso_db_sso_login_users, array("info" => $userinfo2), "WHERE" => "id = ?"), $userrow->id); } catch (Exception $e) { $messages["errors"][] = BB_Translate("Database query error."); } } if (!count($messages["errors"])) { SSO_ActivateUser($userrow->id, $userinfo["extra"], $mapinfo, CSDB::ConvertFromDBTime($userrow->created)); // Only falls through on account lockout or a fatal error. $messages["errors"][] = BB_Translate("User activation failed."); } } } } } } } } } echo $sso_header; SSO_OutputHeartbeat(); ?> <div class="sso_main_wrap sso_login"> <div class="sso_main_wrap_inner"> <div class="sso_main_messages_wrap"> <div class="sso_main_messages"> <?php if (count($messages["errors"])) { ?> <div class="sso_main_messageerror"><?php echo htmlspecialchars($messages["errors"][0]); ?> </div> <?php } ?> <div class="sso_main_messageerror"><?php echo htmlspecialchars(BB_Translate("An error occurred while processing the remembered sign in. You will have to sign in normally.")); ?> </div> </div> </div> <div class="sso_login_signin"><a href="<?php echo htmlspecialchars($sso_target_url); ?> "><?php echo htmlspecialchars(BB_Translate("Sign in")); ?> </a></div> </div> </div> <?php echo $sso_footer; } }