diff options
author | Martin Reddy <lynx@lindenlab.com> | 2009-09-14 17:09:45 +0000 |
---|---|---|
committer | Martin Reddy <lynx@lindenlab.com> | 2009-09-14 17:09:45 +0000 |
commit | cb926640b72afc5f4cad3919222acaefdd090c92 (patch) | |
tree | 18e9a3dbf2cde4b310513bf4c970eeb8cf2fa5ea /indra/newview | |
parent | 5f4764c785becf7344f48b02afd764a37b820d4c (diff) |
DEV-15182 VWR-5474 SEC-20: re-enabled support for clicking on the
following SLAPP URL types in an untrusted browser:
secondlife:///app/agent/...
secondlife:///app/group/...
secondlife:///app/parcel/...
In order to find a compromise between supporting these commands and
security concerns over potential griefing vectors, we use a throttling
solution when these commands are issued by untrusted web browsers.
That is, we only process one command per 15 seconds.
This applies to external browsers, like Firefox, as well as the
internal SL browser.
Notably, we continue to block secondlife:///app/teleport URLs.
Reviewed by james.
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/llchatbar.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llcommandhandler.cpp | 51 | ||||
-rw-r--r-- | indra/newview/llcommandhandler.h | 11 | ||||
-rw-r--r-- | indra/newview/llfloaterhandler.h | 2 | ||||
-rw-r--r-- | indra/newview/llfloaterparcel.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llgroupactions.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llloginhandler.h | 2 | ||||
-rw-r--r-- | indra/newview/llmediactrl.cpp | 9 | ||||
-rw-r--r-- | indra/newview/llnearbychatbar.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llpanelclassified.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llpanellogin.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llpanelprofile.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llstatusbar.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llurldispatcher.cpp | 2 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/notifications.xml | 8 |
15 files changed, 60 insertions, 41 deletions
diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index 3ee2c93961..96c707b08f 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -674,7 +674,7 @@ class LLChatHandler : public LLCommandHandler { public: // not allowed from outside the app - LLChatHandler() : LLCommandHandler("chat", true) { } + LLChatHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } // Your code here bool handle(const LLSD& tokens, const LLSD& query_map, diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp index a04182a910..af6488388a 100644 --- a/indra/newview/llcommandhandler.cpp +++ b/indra/newview/llcommandhandler.cpp @@ -38,12 +38,14 @@ // system includes #include <boost/tokenizer.hpp> +#define THROTTLE_PERIOD 15 // required secs between throttled commands + //--------------------------------------------------------------------------- // Underlying registry for command handlers, not directly accessible. //--------------------------------------------------------------------------- struct LLCommandHandlerInfo { - bool mRequireTrustedBrowser; + LLCommandHandler::EUntrustedAccess mUntrustedBrowserAccess; LLCommandHandler* mHandler; // safe, all of these are static objects }; @@ -51,7 +53,9 @@ class LLCommandHandlerRegistry { public: static LLCommandHandlerRegistry& instance(); - void add(const char* cmd, bool require_trusted_browser, LLCommandHandler* handler); + void add(const char* cmd, + LLCommandHandler::EUntrustedAccess untrusted_access, + LLCommandHandler* handler); bool dispatch(const std::string& cmd, const LLSD& params, const LLSD& query_map, @@ -72,10 +76,12 @@ LLCommandHandlerRegistry& LLCommandHandlerRegistry::instance() return instance; } -void LLCommandHandlerRegistry::add(const char* cmd, bool require_trusted_browser, LLCommandHandler* handler) +void LLCommandHandlerRegistry::add(const char* cmd, + LLCommandHandler::EUntrustedAccess untrusted_access, + LLCommandHandler* handler) { LLCommandHandlerInfo info; - info.mRequireTrustedBrowser = require_trusted_browser; + info.mUntrustedBrowserAccess = untrusted_access; info.mHandler = handler; mMap[cmd] = info; @@ -87,15 +93,37 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd, LLMediaCtrl* web, bool trusted_browser) { + static F64 last_throttle_time = 0.0; + F64 cur_time = 0.0; std::map<std::string, LLCommandHandlerInfo>::iterator it = mMap.find(cmd); if (it == mMap.end()) return false; const LLCommandHandlerInfo& info = it->second; - if (!trusted_browser && info.mRequireTrustedBrowser) + if (!trusted_browser) { - // block request from external browser, but report as - // "handled" because it was well formatted. - LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL; - return true; + switch (info.mUntrustedBrowserAccess) + { + case LLCommandHandler::UNTRUSTED_ALLOW: + // fall through and let the command be handled + break; + + case LLCommandHandler::UNTRUSTED_BLOCK: + // block request from external browser, but report as + // "handled" because it was well formatted. + LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL; + return true; + + case LLCommandHandler::UNTRUSTED_THROTTLE: + cur_time = LLTimer::getElapsedSeconds(); + if (cur_time < last_throttle_time + THROTTLE_PERIOD) + { + // block request from external browser if it happened + // within THROTTLE_PERIOD secs of the last command + LL_WARNS_ONCE("SLURL") << "Throttled SLURL command from untrusted browser" << LL_ENDL; + return true; + } + last_throttle_time = cur_time; + break; + } } if (!info.mHandler) return false; return info.mHandler->handle(params, query_map, web); @@ -106,10 +134,9 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd, //--------------------------------------------------------------------------- LLCommandHandler::LLCommandHandler(const char* cmd, - bool require_trusted_browser) + EUntrustedAccess untrusted_access) { - LLCommandHandlerRegistry::instance().add( - cmd, require_trusted_browser, this); + LLCommandHandlerRegistry::instance().add(cmd, untrusted_access, this); } LLCommandHandler::~LLCommandHandler() diff --git a/indra/newview/llcommandhandler.h b/indra/newview/llcommandhandler.h index 5cb3ee73d4..1bae6d9414 100644 --- a/indra/newview/llcommandhandler.h +++ b/indra/newview/llcommandhandler.h @@ -43,7 +43,7 @@ public: // Inform the system you handle commands starting // with "foo" and they are only allowed from // "trusted" (pointed at Linden content) browsers - LLFooHandler() : LLCommandHandler("foo", true) { } + LLFooHandler() : LLCommandHandler("foo", UNTRUSTED_BLOCK) { } // Your code here bool handle(const LLSD& tokens, const LLSD& query_map, @@ -65,7 +65,14 @@ class LLMediaCtrl; class LLCommandHandler { public: - LLCommandHandler(const char* command, bool allow_from_untrusted_browser); + enum EUntrustedAccess + { + UNTRUSTED_ALLOW, // allow commands from untrusted browsers + UNTRUSTED_BLOCK, // ignore commands from untrusted browsers + UNTRUSTED_THROTTLE // allow untrusted, but only a few per min. + }; + + LLCommandHandler(const char* command, EUntrustedAccess untrusted_access); // Automatically registers object to get called when // command is executed. All commands can be processed // in links from LLMediaCtrl, but some (like teleport) diff --git a/indra/newview/llfloaterhandler.h b/indra/newview/llfloaterhandler.h index 31ea80c12c..cd9d8b5377 100644 --- a/indra/newview/llfloaterhandler.h +++ b/indra/newview/llfloaterhandler.h @@ -38,7 +38,7 @@ class LLFloaterHandler : public LLCommandHandler { public: - LLFloaterHandler() : LLCommandHandler("floater", true) { } + LLFloaterHandler() : LLCommandHandler("floater", UNTRUSTED_BLOCK) { } bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web); }; diff --git a/indra/newview/llfloaterparcel.cpp b/indra/newview/llfloaterparcel.cpp index 44270683a0..88a39a495f 100644 --- a/indra/newview/llfloaterparcel.cpp +++ b/indra/newview/llfloaterparcel.cpp @@ -53,7 +53,7 @@ class LLParcelHandler : public LLCommandHandler { public: // requires trusted browser to trigger - LLParcelHandler() : LLCommandHandler("parcel", true) { } + LLParcelHandler() : LLCommandHandler("parcel", UNTRUSTED_THROTTLE) { } bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) { diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index 10a17476d9..d1cbe96906 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -51,7 +51,7 @@ class LLGroupHandler : public LLCommandHandler { public: // requires trusted browser to trigger - LLGroupHandler() : LLCommandHandler("group", true) { } + LLGroupHandler() : LLCommandHandler("group", UNTRUSTED_THROTTLE) { } bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) { diff --git a/indra/newview/llloginhandler.h b/indra/newview/llloginhandler.h index 0844b80c7c..d36ceaf3cc 100644 --- a/indra/newview/llloginhandler.h +++ b/indra/newview/llloginhandler.h @@ -39,7 +39,7 @@ class LLLoginHandler : public LLCommandHandler { public: // allow from external browsers - LLLoginHandler() : LLCommandHandler("login", false) { } + LLLoginHandler() : LLCommandHandler("login", UNTRUSTED_ALLOW) { } /*virtual*/ bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web); // Fill in our internal fields from a SLURL like diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 62b38f2b4a..09a7edaa43 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -916,15 +916,8 @@ void LLMediaCtrl::onClickLinkHref( LLPluginClassMedia* self ) // void LLMediaCtrl::onClickLinkNoFollow( LLPluginClassMedia* self ) { + // let the dispatcher handle blocking/throttling of SLURLs std::string url = self->getClickURL(); - if (LLSLURL::isSLURLCommand(url) - && !mTrusted) - { - // block handling of this secondlife:///app/ URL - LLNotifications::instance().add("UnableToOpenCommandURL"); - return; - } - LLURLDispatcher::dispatch(url, this, mTrusted); } diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 764e093bcc..e348189ea9 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -616,7 +616,7 @@ class LLChatHandler : public LLCommandHandler { public: // not allowed from outside the app - LLChatHandler() : LLCommandHandler("chat", true) { } + LLChatHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } // Your code here bool handle(const LLSD& tokens, const LLSD& query_map, diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index c77d089af7..ee5d265220 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -119,7 +119,7 @@ class LLClassifiedTeleportHandler : public LLCommandHandler { public: // don't allow from external browsers because it moves you immediately - LLClassifiedTeleportHandler() : LLCommandHandler("classifiedteleport", true) { } + LLClassifiedTeleportHandler() : LLCommandHandler("classifiedteleport", UNTRUSTED_BLOCK) { } bool handle(const LLSD& tokens, const LLSD& queryMap) { diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index ef830d5f03..9caa751854 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -87,7 +87,7 @@ class LLLoginRefreshHandler : public LLCommandHandler { public: // don't allow from external browsers - LLLoginRefreshHandler() : LLCommandHandler("login_refresh", true) { } + LLLoginRefreshHandler() : LLCommandHandler("login_refresh", UNTRUSTED_BLOCK) { } bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) { if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP) diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 6d3d307526..ce01568e99 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -46,7 +46,7 @@ class LLAgentHandler : public LLCommandHandler { public: // requires trusted browser to trigger - LLAgentHandler() : LLCommandHandler("agent", true) { } + LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { } bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index c724fb5315..40b8445dcf 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -623,7 +623,7 @@ class LLBalanceHandler : public LLCommandHandler { public: // Requires "trusted" browser/URL source - LLBalanceHandler() : LLCommandHandler("balance", true) { } + LLBalanceHandler() : LLCommandHandler("balance", UNTRUSTED_BLOCK) { } bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) { if (tokens.size() == 1 diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp index 4cdeca7707..901d0594f1 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -331,7 +331,7 @@ public: // Teleport requests *must* come from a trusted browser // inside the app, otherwise a malicious web page could // cause a constant teleport loop. JC - LLTeleportHandler() : LLCommandHandler("teleport", true) { } + LLTeleportHandler() : LLCommandHandler("teleport", UNTRUSTED_BLOCK) { } bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 1f0578f819..ea1c0dd99b 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6495,14 +6495,6 @@ Click Accept to join the chat or Decline to decline the invitation. Click Block <notification icon="notifytip.tga" - name="UnableToOpenCommandURL" - priority="high" - type="notifytip"> - The link you clicked cannot be opened from this web browser. - </notification> - - <notification - icon="notifytip.tga" name="UnsupportedCommandSLURL" priority="high" type="notifytip"> |