From a1fb89ebb6e6cc89ed301b10305c145da3be295f Mon Sep 17 00:00:00 2001 From: Brad Kittenbrink Date: Tue, 23 Nov 2021 17:44:06 -0800 Subject: SL-16365 Viewer adds empty mfa token to login params --- indra/newview/lllogininstance.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index e81d2cc082..25182593ce 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -225,6 +225,7 @@ void LLLoginInstance::constructAuthParams(LLPointer user_credentia request_params["id0"] = mSerialNumber; request_params["host_id"] = gSavedSettings.getString("HostID"); request_params["extended_errors"] = true; // request message_id and message_args + request_params["token"] = ""; // log request_params _before_ adding the credentials LL_DEBUGS("LLLogin") << "Login parameters: " << LLSDOStreamer(request_params) << LL_ENDL; -- cgit v1.2.3 From d307843dd431de86e6d4c4f3e6fe8eaf946354d4 Mon Sep 17 00:00:00 2001 From: Brad Kittenbrink Date: Tue, 23 Nov 2021 17:39:37 -0800 Subject: SL-16388 Viewer MFA Implementation We now present MFA errors to the user during login and prompt them for an authentication token. --- indra/newview/CMakeLists.txt | 2 + indra/newview/llfloatermfa.cpp | 104 +++++++++++++++++++++ indra/newview/llfloatermfa.h | 50 ++++++++++ indra/newview/lllogininstance.cpp | 40 ++++++++ indra/newview/lllogininstance.h | 1 + indra/newview/llstartup.cpp | 6 +- indra/newview/llviewerfloaterreg.cpp | 2 + indra/newview/skins/default/xui/en/floater_mfa.xml | 50 ++++++++++ 8 files changed, 252 insertions(+), 3 deletions(-) create mode 100644 indra/newview/llfloatermfa.cpp create mode 100644 indra/newview/llfloatermfa.h create mode 100644 indra/newview/skins/default/xui/en/floater_mfa.xml diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 1969c498f0..9e6cd48f21 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -271,6 +271,7 @@ set(viewer_SOURCE_FILES llfloatermap.cpp llfloatermediasettings.cpp llfloatermemleak.cpp + llfloatermfa.cpp llfloatermodelpreview.cpp llfloatermodeluploadbase.cpp llfloatermyscripts.cpp @@ -913,6 +914,7 @@ set(viewer_HEADER_FILES llfloatermarketplacelistings.h llfloatermediasettings.h llfloatermemleak.h + llfloatermfa.h llfloatermodelpreview.h llfloatermodeluploadbase.h llfloatermyscripts.h diff --git a/indra/newview/llfloatermfa.cpp b/indra/newview/llfloatermfa.cpp new file mode 100644 index 0000000000..9fb6788923 --- /dev/null +++ b/indra/newview/llfloatermfa.cpp @@ -0,0 +1,104 @@ +/** + * @file llfloatermfa.cpp + * @brief Multi-Factor Auth token submission dialog + * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatermfa.h" + +// viewer includes +#include "llevents.h" + + +LLFloaterMFA::LLFloaterMFA(const LLSD& data) +: LLModalDialog("mfa_challenge"), + mMessage(data["message"].asStringRef()), + mReplyPumpName(data["reply_pump"].asStringRef()) +{ + +} + +LLFloaterMFA::~LLFloaterMFA() +{ +} + +BOOL LLFloaterMFA::postBuild() +{ + childSetAction("Continue", onContinue, this); + childSetAction("Cancel", onCancel, this); + + if (hasChild("token_prompt")) + { + // this displays the prompt message + LLUICtrl *token_prompt = getChild("token_prompt"); + token_prompt->setEnabled( FALSE ); + token_prompt->setFocus(TRUE); + token_prompt->setValue(LLSD(mMessage)); + + return TRUE; + } + + return TRUE; +} + +// static +void LLFloaterMFA::onContinue( void* userdata ) +{ + LLFloaterMFA* self = (LLFloaterMFA*) userdata; + LL_INFOS("MFA") << "User submits MFA token for challenge." << LL_ENDL; + + std::string token{"8675309"}; + + if (self->hasChild("token")) + { + // this displays the prompt message + LLUICtrl *token_ctrl = self->getChild("token"); + + token = token_ctrl->getValue().asStringRef(); + } + + if(self->mReplyPumpName != "") + { + LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD(token)); + } + + self->closeFloater(); // destroys this object +} + +// static +void LLFloaterMFA::onCancel( void* userdata ) +{ + LLFloaterMFA* self = (LLFloaterMFA*) userdata; + LL_INFOS("MFA") << "User cancels MFA challenge attempt." << LL_ENDL; + + if(self->mReplyPumpName != "") + { + LL_DEBUGS("MFA") << self->mReplyPumpName << LL_ENDL; + LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD()); + } + + // destroys this object + self->closeFloater(); +} diff --git a/indra/newview/llfloatermfa.h b/indra/newview/llfloatermfa.h new file mode 100644 index 0000000000..c6c79439b8 --- /dev/null +++ b/indra/newview/llfloatermfa.h @@ -0,0 +1,50 @@ +/** + * @file llfloatermfa.h + * @brief Multi-Factor Auth token submission dialog + * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERMFA_H +#define LL_LLFLOATERMFA_H + +#include "llmodaldialog.h" + + +class LLFloaterMFA : + public LLModalDialog +{ +public: + LLFloaterMFA(const LLSD& data); + virtual ~LLFloaterMFA(); + + BOOL postBuild(); + + static void onContinue(void* userdata); + static void onCancel(void* userdata); + +private: + std::string mMessage; + std::string mReplyPumpName; +}; + +#endif // LL_FLOATERMFA_H diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 25182593ce..e380e5a3f4 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -75,6 +75,8 @@ public: static const char * const TOS_REPLY_PUMP = "lllogininstance_tos_callback"; static const char * const TOS_LISTENER_NAME = "lllogininstance_tos"; +static const char * const MFA_REPLY_PUMP = "lllogininstance_mfa_callback"; +static const char * const MFA_LISTENER_NAME = "lllogininstance_mfa"; std::string construct_start_string(); @@ -408,6 +410,23 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event) boost::bind(&LLLoginInstance::syncWithUpdater, this, resp, _1, _2)); } } + else if(reason_response == "mfa_challenge") + { + LL_DEBUGS("LLLogin") << " MFA challenge" << LL_ENDL; + + LLSD data(LLSD::emptyMap()); + data["message"] = message_response; + data["reply_pump"] = MFA_REPLY_PUMP; + if (gViewerWindow) + { + gViewerWindow->setShowProgress(FALSE); + } + LLFloaterReg::showInstance("message_mfa", data); + LLEventPumps::instance().obtain(MFA_REPLY_PUMP) + .listen(MFA_LISTENER_NAME, [=](const LLSD& token) { + return this->handleMFAResponse(token, "token"); + }); + } else if( reason_response == "key" || reason_response == "presence" || reason_response == "connect" @@ -502,6 +521,27 @@ bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) return true; } +bool LLLoginInstance::handleMFAResponse(const std::string& token, const std::string& key) +{ + if(!token.empty()) + { + LL_INFOS("LLLogin") << "LLLoginInstance::handleMFAResponse: token submitted" << LL_ENDL; + + // Set the request data to true and retry login. + mRequestData["params"][key] = token; + reconnect(); + } + else + { + LL_INFOS("LLLogin") << "LLLoginInstance::handleMFAResponse: no token, attemptComplete" << LL_ENDL; + + attemptComplete(); + } + + LLEventPumps::instance().obtain(MFA_REPLY_PUMP).stopListening(MFA_LISTENER_NAME); + return true; +} + std::string construct_start_string() { std::string start; diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index b759b43474..ce64e9e3be 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -84,6 +84,7 @@ private: void syncWithUpdater(ResponsePtr resp, const LLSD& notification, const LLSD& response); bool handleTOSResponse(bool v, const std::string& key); + bool handleMFAResponse(const std::string& v, const std::string& key); void attemptComplete() { mAttemptComplete = true; } // In the future an event? diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index f22be6481a..228d64c17b 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1117,10 +1117,10 @@ bool idle_startup() } else { - if (reason_response != "tos") + if (reason_response != "tos" && reason_response != "mfa_challenge") { - // Don't pop up a notification in the TOS case because - // LLFloaterTOS::onCancel() already scolded the user. + // Don't pop up a notification in the TOS or MFA cases because + // the specialized floater has already scolded the user. std::string error_code; if(response.has("errorcode")) { diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 5a05f89758..603cc00062 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -91,6 +91,7 @@ #include "llfloatermarketplacelistings.h" #include "llfloatermediasettings.h" #include "llfloatermemleak.h" +#include "llfloatermfa.h" #include "llfloatermodelpreview.h" #include "llfloatermyscripts.h" #include "llfloatermyenvironment.h" @@ -286,6 +287,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("marketplace_validation", "floater_marketplace_validation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("message_critical", "floater_critical.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("message_tos", "floater_tos.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("message_mfa", "floater_mfa.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("mute_object_by_name", "floater_mute_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/skins/default/xui/en/floater_mfa.xml b/indra/newview/skins/default/xui/en/floater_mfa.xml new file mode 100644 index 0000000000..acdfbc82c0 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_mfa.xml @@ -0,0 +1,50 @@ + + + + token prompt + + +