summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Kittenbrink <brad@lindenlab.com>2021-11-23 17:39:37 -0800
committerBrad Kittenbrink <brad@lindenlab.com>2021-11-23 17:45:22 -0800
commitd307843dd431de86e6d4c4f3e6fe8eaf946354d4 (patch)
treedae66c7682fa0addd24d1cb5cde89a4cb47b4f35
parenta1fb89ebb6e6cc89ed301b10305c145da3be295f (diff)
SL-16388 Viewer MFA Implementation
We now present MFA errors to the user during login and prompt them for an authentication token.
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/llfloatermfa.cpp104
-rw-r--r--indra/newview/llfloatermfa.h50
-rw-r--r--indra/newview/lllogininstance.cpp40
-rw-r--r--indra/newview/lllogininstance.h1
-rw-r--r--indra/newview/llstartup.cpp6
-rw-r--r--indra/newview/llviewerfloaterreg.cpp2
-rw-r--r--indra/newview/skins/default/xui/en/floater_mfa.xml50
8 files changed, 252 insertions, 3 deletions
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<LLUICtrl>("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<LLUICtrl>("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<LLFloaterMarketplaceValidation>);
LLFloaterReg::add("message_critical", "floater_critical.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>);
LLFloaterReg::add("message_tos", "floater_tos.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>);
+ LLFloaterReg::add("message_mfa", "floater_mfa.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMFA>);
LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMove>);
LLFloaterReg::add("mute_object_by_name", "floater_mute_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGetBlockedObjectName>);
LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMap>);
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 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ height="87"
+ layout="topleft"
+ name="mfa_challenge"
+ help_topic="mfa_challenge"
+ width="480">
+ <text
+ type="string"
+ length="1"
+ bottom="20"
+ follows="top|left"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="token_prompt"
+ top="20">
+ token prompt
+ </text>
+ <text_box
+ allow_text_entry="true"
+ follows="left|top|right"
+ height="19"
+ layout="topleft"
+ left_delta="70"
+ max_chars="16"
+ name="token_entry"
+ top_delta="-4"
+ width="16" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Continue"
+ layout="topleft"
+ left="10"
+ name="Continue"
+ top="50"
+ width="64" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Cancel"
+ layout="topleft"
+ left_pad="5"
+ name="Cancel"
+ top_delta="0"
+ width="64" />
+</floater>