function SSO_OutputHeartbeat() { global $sso_db, $sso_db_temp_sessions, $sso_sessionrow, $sso_session_info, $sso_indexphp; if ($sso_session_info["initmsg"] != "" || $sso_session_info["files"]) { $sso_session_info["initmsg"] = ""; $sso_session_info["files"] = 0; SSO_SaveSessionInfo(); } if ($sso_sessionrow->heartbeat > 0) { $sso_db->Query("UPDATE", array($sso_db_temp_sessions, array("updated" => CSDB::ConvertToDBTime(time())), array("heartbeat" => "heartbeat - 1"), "WHERE" => "id = ? AND heartbeat > 0"), $sso_sessionrow->id); } ?> <script type="text/javascript"> if (typeof(window.jQuery) == 'undefined') { document.write('<' + 'script type="text/javascript" src="<?php echo htmlspecialchars(SSO_ROOT_URL . "/" . SSO_SUPPORT_PATH . "/jquery-1.11.0.min.js"); ?> " /' + '><' + '/script' + '>'); document.write('<' + 'script type="text/javascript"' + '>jQuery.noConflict();<' + '/script' + '>'); } </script> <script type="text/javascript"> function SSO_Heartbeat() { jQuery('#sso_heartbeat').load('<?php echo SSO_ROOT_URL . "/" . $sso_indexphp; ?> ', { 'sso_ajax' : 1, 'sso_id' : '<?php echo htmlspecialchars(BB_JSSafe($_REQUEST["sso_id"])); ?> ', 'sso_action' : 'sso_heartbeat' }); } jQuery(function() { setInterval(SSO_Heartbeat, 3300000); }); </script> <div id="sso_heartbeat" style="display: none;"></div> <?php }
private function ProcessVerification(&$result, $info) { global $sso_ipaddr, $sso_session_info; if ($info["publickey"] != "" && $info["privatekey"] != "" && (!$info["remember"] || !isset($sso_session_info["sso_recaptcha_passed"]) || !$sso_session_info["sso_recaptcha_passed"])) { if (!isset($_REQUEST["g-recaptcha-response"])) { $result["errors"][] = BB_Translate("Human Verification information is missing."); } else { require_once SSO_ROOT_PATH . "/" . SSO_SUPPORT_PATH . "/http.php"; require_once SSO_ROOT_PATH . "/" . SSO_SUPPORT_PATH . "/web_browser.php"; $url = "https://www.google.com/recaptcha/api/siteverify?secret=" . urlencode($info["privatekey"]) . "&response=" . urlencode($_REQUEST["g-recaptcha-response"]) . "&remoteip=" . urlencode($sso_ipaddr["ipv6"]); $web = new WebBrowser(); $result2 = $web->Process($url); if (!$result2["success"]) { $result["errors"][] = BB_Translate("Human Verification failed. Error retrieving response from remote service.", $result2["error"]); } else { if ($result2["response"]["code"] != 200) { $result["errors"][] = BB_Translate("Human Verification failed. The remote service responded with: %s", $result2["response"]["code"] . " " . $result2["response"]["meaning"]); } else { $data = @json_decode($result2["body"], true); if ($data === false) { $result["errors"][] = BB_Translate("Human Verification failed. Unable to decode the response from the remote service."); } else { if (!isset($data["success"])) { $result["errors"][] = BB_Translate("Incorrect Human Verification entered. Try again. (Code: %s)", BB_Translate($data["error"])); } else { if ($info["remember"]) { $sso_session_info["sso_recaptcha_passed"] = true; if (!SSO_SaveSessionInfo()) { $result["errors"][] = BB_Translate("Unable to save session information."); return; } } } } } } } } }
public function ProcessFrontend() { global $sso_rng, $sso_provider, $sso_settings, $sso_session_info; $redirect_uri = BB_GetRequestHost() . SSO_ROOT_URL . "/index.php?sso_provider=" . urlencode($sso_provider) . "&sso_google_action=signin"; if (isset($_REQUEST["sso_google_action"]) && $_REQUEST["sso_google_action"] == "signin") { // Recover the language settings. if (!isset($sso_session_info["sso_google_info"])) { $this->DisplayError(BB_Translate("Unable to authenticate the request.")); return; } $url = BB_GetRequestHost() . SSO_ROOT_URL . "/index.php?sso_provider=" . urlencode($sso_provider) . "&sso_google_action=signin2"; if (isset($_REQUEST["state"])) { $url .= "&state=" . urlencode($_REQUEST["state"]); } if (isset($_REQUEST["code"])) { $url .= "&code=" . urlencode($_REQUEST["code"]); } if (isset($_REQUEST["error"])) { $url .= "&error=" . urlencode($_REQUEST["error"]); } $url .= "&lang=" . urlencode($sso_session_info["sso_google_info"]["lang"]); header("Location: " . $url); } else { if (isset($_REQUEST["sso_google_action"]) && $_REQUEST["sso_google_action"] == "signin2") { // Validate the token. if (!isset($_REQUEST["state"]) || !isset($sso_session_info["sso_google_info"]) || $_REQUEST["state"] !== $sso_session_info["sso_google_info"]["token"]) { $this->DisplayError(BB_Translate("Unable to authenticate the request.")); return; } // Check for token expiration. if (CSDB::ConvertFromDBTime($sso_session_info["sso_google_info"]["expires"]) < time()) { $this->DisplayError(BB_Translate("Verification token has expired.")); return; } if (isset($_REQUEST["error"])) { if ($_REQUEST["error"] == "access_denied") { $message = BB_Translate("The request to sign in with Google was denied."); } else { $message = BB_Translate("The error message returned was '%s'.", $_REQUEST["error"]); } $this->DisplayError(BB_Translate("Sign in failed. %s", $message)); return; } if (!isset($_REQUEST["code"])) { $this->DisplayError(BB_Translate("Sign in failed. Authorization code missing.")); return; } // Get an access token from the authorization code. require_once SSO_ROOT_PATH . "/" . SSO_SUPPORT_PATH . "/http.php"; require_once SSO_ROOT_PATH . "/" . SSO_SUPPORT_PATH . "/web_browser.php"; $url = "https://accounts.google.com/o/oauth2/token"; $options = array("postvars" => array("code" => $_REQUEST["code"], "client_id" => $sso_settings["sso_google"]["client_id"], "client_secret" => $sso_settings["sso_google"]["client_secret"], "redirect_uri" => $redirect_uri, "grant_type" => "authorization_code")); $web = new WebBrowser(); $result = $web->Process($url, "auto", $options); if (!$result["success"]) { $this->DisplayError(BB_Translate("Sign in failed. Error retrieving URL for Google access token. %s", $result["error"])); } else { if ($result["response"]["code"] != 200) { $this->DisplayError(BB_Translate("Sign in failed. The Google access token server returned: %s", $result["response"]["code"] . " " . $result["response"]["meaning"])); } else { // Get the access token. $data = @json_decode($result["body"], true); if ($data === false || !isset($data["access_token"])) { $this->DisplayError(BB_Translate("Sign in failed. Error retrieving access token from Google.")); } else { // Get the user's profile information. $url = "https://www.googleapis.com/oauth2/v1/userinfo?access_token=" . urlencode($data["access_token"]); $result = $web->Process($url); if (!$result["success"]) { $this->DisplayError(BB_Translate("Sign in failed. Error retrieving URL for Google profile information. %s", $result["error"])); } else { if ($result["response"]["code"] != 200) { $this->DisplayError(BB_Translate("Sign in failed. The Google profile information server returned: %s", $result["response"]["code"] . " " . $result["response"]["meaning"])); } else { $profile = @json_decode($result["body"], true); if ($profile === false) { $this->DisplayError(BB_Translate("Sign in failed. Error retrieving profile information from Google.")); } $origprofile = $profile; // Remove unverified e-mail addresses. if (!isset($profile["verified_email"]) || !$profile["verified_email"]) { unset($profile["verified_email"]); unset($profile["email"]); } // 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; } $mapinfo = array(); foreach (self::$fieldmap as $key => $info) { $key2 = $sso_settings["sso_google"]["map_" . $key]; if ($key2 != "" && isset($profile[$key])) { $mapinfo[$key2] = $profile[$key]; } } SSO_ActivateUser($profile["id"], serialize($origprofile), $mapinfo); // Only falls through on account lockout or a fatal error. $this->DisplayError(BB_Translate("User activation failed.")); } } } } } } else { // Create internal data packet. $token = $sso_rng->GenerateString(); $sso_session_info["sso_google_info"] = array("lang" => isset($_REQUEST["lang"]) ? $_REQUEST["lang"] : "", "token" => $token, "expires" => CSDB::ConvertToDBTime(time() + 30 * 60)); if (!SSO_SaveSessionInfo()) { $this->DisplayError(BB_Translate("Unable to save session information.")); return; } // Calculate the required scope. $scope = array("https://www.googleapis.com/auth/userinfo.profile" => true); foreach (self::$fieldmap as $key => $info) { if ($info["extra"] != "" && $sso_settings["sso_google"]["map_" . $key] != "") { $scope[$info["extra"]] = true; } } // Get the login redirection URL. $options = array("response_type" => "code", "client_id" => $sso_settings["sso_google"]["client_id"], "redirect_uri" => $redirect_uri, "scope" => implode(" ", array_keys($scope)), "state" => $token); $options2 = array(); foreach ($options as $key => $val) { $options2[] = urlencode($key) . "=" . urlencode($val); } $url = "https://accounts.google.com/o/oauth2/auth?" . implode("&", $options2); SSO_ExternalRedirect($url); } } }
public function RecoveryCheck2(&$result, $userinfo) { global $sso_session_info, $sso_target_url; if ($userinfo !== false && $_REQUEST["sso_method"] == "sso_sms_recovery") { $field = SSO_FrontendFieldValue("sso_login_sms_recovery_phrase", ""); $field = strtolower(trim(preg_replace('/\\s+/', " ", $field))); if ($field == "" || $field != $sso_session_info["sso_login_recover"]["v"]) { $sso_session_info["sso_login_recover"]["attempts"]--; if ($sso_session_info["sso_login_recover"]["attempts"] < 1) { unset($sso_session_info["sso_login_recover"]); SSO_SaveSessionInfo(); header("Location: " . BB_GetRequestHost() . $sso_target_url . "&sso_login_action=recover&sso_msg=recovery_expired_invalid"); exit; } else { if (!SSO_SaveSessionInfo()) { $result["errors"][] = BB_Translate("Incorrect recovery phrase and a fatal error occurred. Fatal error: Unable to save session information."); } else { if ($sso_session_info["sso_login_recover"]["attempts"] == 1) { $result["errors"][] = BB_Translate("Incorrect recovery phrase. 1 attempt left."); } else { $result["errors"][] = BB_Translate("Incorrect recovery phrase. %d attempts left.", $sso_session_info["sso_login_recover"]["attempts"]); } } } } else { unset($sso_session_info["sso_login_recover"]); } } }
public function ProcessFrontend() { global $sso_settings, $sso_rng, $sso_provider, $sso_target_url, $sso_session_info, $sso_session_id, $sso_db; if (isset($sso_session_info["setlogin_result"]) && !isset($_REQUEST["tryagain"])) { // Check the secret. if (!isset($_REQUEST["sso_setlogin_secret"]) || !isset($sso_session_info["setlogin_info"]) || $_REQUEST["sso_setlogin_secret"] !== $sso_session_info["setlogin_info"]["secret"]) { $this->DisplayError(BB_Translate("Unable to authenticate the request.")); return; } // Should be nearly impossible to get here since browser redirects are executed almost immediately. if (CSDB::ConvertFromDBTime($sso_session_info["setlogin_info"]["expires"]) < time()) { $this->DisplayError(BB_Translate("Verification token has expired.")); return; } // The user is signed in. Activate the account. $sso_db_sso_remote_users = SSO_DB_PREFIX . "p_sso_remote_users"; try { $id = $sso_db->GetOne("SELECT", array("id", "FROM" => "?", "WHERE" => "remote_id = ? AND user_id = ?"), $sso_db_sso_remote_users, $this->info["row"]->id, $sso_session_info["setlogin_result"]["user_id"]); if ($id === false) { $sso_db->Query("INSERT", array($sso_db_sso_remote_users, array("remote_id" => $this->info["row"]->id, "user_id" => $sso_session_info["setlogin_result"]["user_id"], "created" => CSDB::ConvertToDBTime(time())), "AUTO INCREMENT" => "id")); $id = $sso_db->GetInsertID(); } $mapinfo = $sso_session_info["setlogin_result"]["protected_fields"]; $mapinfo[$sso_settings["sso_remote"]["map_remote_id"]] = $this->info["row"]->id; SSO_ActivateUser($id, serialize($sso_session_info["setlogin_info"]), $mapinfo, false, $this->info["row_info"]["automate"]); // Only falls through on account lockout or a fatal error. $this->DisplayError(BB_Translate("User activation failed.")); } catch (Exception $e) { $this->DisplayError("A database error has occurred. Most likely cause: Bad SQL query."); } } else { // Check the API key information. $info = unserialize($this->info["apirow"]->info); if ($info["type"] != "remote") { $this->DisplayError(BB_Translate("The target client API key is not a remote API key.")); return; } if ($info["url"] == "") { $this->DisplayError(BB_Translate("The target client API key URL is missing.")); return; } // Set up the session so that the endpoint works. unset($sso_session_info["setlogin_result"]); $token = $sso_rng->GenerateString(); $sso_session_info["setlogin_info"] = array("provider" => $sso_provider, "apikey_id" => $this->info["apirow"]->id, "redirect_url" => BB_GetRequestHost() . $sso_target_url, "token" => $token, "secret" => $sso_rng->GenerateString(), "expires" => CSDB::ConvertToDBTime(time() + 30 * 60)); if (!SSO_SaveSessionInfo()) { $this->DisplayError(BB_Translate("Unable to save session information.")); return; } // Redirect to the remote host. $url = $info["url"] . (strpos($info["url"], "?") === false ? "?" : "&") . "from_sso_server=1&sso_setlogin_id=" . urlencode($sso_session_id[1]) . "&sso_setlogin_token=" . urlencode($token) . (isset($_REQUEST["lang"]) ? "&sso_lang=" . urlencode($_REQUEST["lang"]) : ""); SSO_ExternalRedirect($url); } }
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; } } } } } } } } }
function SSO_ActivateUserSession($row, $automate) { global $sso_rng, $sso_db, $sso_db_user_sessions, $sso_sessionrow, $sso_session_info, $sso_apirow; try { // Create a user session. $sid = $sso_rng->GenerateString(); $sso_db->Query("INSERT", array($sso_db_user_sessions, array("user_id" => $row->id, "apikey_id" => $sso_sessionrow->apikey_id, "updated" => CSDB::ConvertToDBTime(time()), "created" => CSDB::ConvertToDBTime(time()), "session_id" => $sid, "info" => serialize(array("validated" => false, "automate" => $automate))), "AUTO INCREMENT" => "id")); $id = $sso_db->GetInsertID(); // Update the current session with the new information. $sso_session_info["new_id"] = $sid . "-" . $id; if (!SSO_SaveSessionInfo()) { return false; } // Set the second ID cookie. SetCookieFixDomain("sso_server_id2", $sso_session_info["new_id"], 0, "", "", SSO_IsSSLRequest(), true); // Redirect to validation. header("Location: " . BB_GetRequestHost() . SSO_ROOT_URL . "/index.php?sso_action=sso_validate" . (isset($_REQUEST["lang"]) ? "&lang=" . urlencode($_REQUEST["lang"]) : "")); exit; } catch (Exception $e) { // Don't do anything here. Just catch the database exception and let the code fall through. // It should be nearly impossible to get here in the first place. } return false; }
} // Calculate API key field mapping. $protectedfields = array(); $updateinfo = $sso_data["updateinfo"] != "" ? @json_decode($sso_data["updateinfo"], true) : false; if (!is_array($updateinfo)) { $updateinfo = false; } foreach ($sso_apikey_info["field_map"] as $key => $info) { if ($info["perms"] == "rw") { if ($updateinfo !== false && isset($updateinfo[$info["name"]])) { $protectedfields[$key] = $updateinfo[$info["name"]]; } } } $sso_session_info["setlogin_result"] = array("user_id" => $sso_data["user_id"], "protected_fields" => $protectedfields); if (!SSO_SaveSessionInfo()) { SSO_EndpointError("Unable to save session information."); } $url = $sso_session_info["setlogin_info"]["redirect_url"]; $url .= (strpos($url, "?") === false ? "?" : "&") . "sso_setlogin_secret=" . urlencode($sso_session_info["setlogin_info"]["secret"]); $result = array("success" => true, "url" => $url); SSO_EndpointOutput($result); } else { if ($sso_data["action"] == "getlogin") { if ($sso_apikey_info["type"] != "normal") { SSO_EndpointError("Invalid API key type."); } // Load the user account. if (!isset($sso_data["sso_id"])) { SSO_EndpointError("Session ID expected."); }
public function TwoFactorFailed(&$result, $userinfo) { global $sso_session_info, $sso_target_url; $info = $this->GetInfo(); if (!isset($sso_session_info["sso_login_two_factor"]["sso_ratelimit"])) { $sso_session_info["sso_login_two_factor"]["sso_ratelimit"] = 0; } $sso_session_info["sso_login_two_factor"]["sso_ratelimit"]++; if ($sso_session_info["sso_login_two_factor"]["sso_ratelimit"] < $info["two_factor_attempts"]) { SSO_SaveSessionInfo(); } else { unset($sso_session_info["sso_login_two_factor"]); SSO_SaveSessionInfo(); header("Location: " . BB_GetRequestHost() . $sso_target_url . "&sso_msg=two_factor_auth_expired"); exit; } }
protected function clearAllPersistentData() { global $sso_session_info; unset($sso_session_info["sso_facebook"]); SSO_SaveSessionInfo(); }
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; } }