From 2e36c409124a1f22f66fe546ad5f96ab59ed6d5b Mon Sep 17 00:00:00 2001 From: Kasen IO Date: Sat, 7 Dec 2019 18:20:46 -0500 Subject: [PATCH 1/3] added QML + C++ system for whitelists --- .../security/EntityScriptWhitelist.qml | 110 ++++++++++++++++++ interface/src/Menu.cpp | 14 +++ interface/src/Menu.h | 1 + libraries/script-engine/src/ScriptEngine.cpp | 29 ++++- 4 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 interface/resources/qml/hifi/dialogs/security/EntityScriptWhitelist.qml diff --git a/interface/resources/qml/hifi/dialogs/security/EntityScriptWhitelist.qml b/interface/resources/qml/hifi/dialogs/security/EntityScriptWhitelist.qml new file mode 100644 index 0000000000..45a8368ce4 --- /dev/null +++ b/interface/resources/qml/hifi/dialogs/security/EntityScriptWhitelist.qml @@ -0,0 +1,110 @@ +// +// ScriptWhitelist.qml +// interface/resources/qml/hifi/dialogs/security +// +// Created by Kasen IO on 2019.12.05 | realities.dev | kasenvr@gmail.com +// Copyright 2019 Kasen IO +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +// Security Settings for the Entity Script Whitelist + +import Hifi 1.0 as Hifi +import QtQuick 2.8 +import QtQuick.Controls 2.3 +import QtQuick.Layouts 1.12 +import stylesUit 1.0 as HifiStylesUit +import controlsUit 1.0 as HiFiControls +import PerformanceEnums 1.0 +import "../../../windows" + + +Rectangle { + + function getWhitelistAsText() { + var whitelist = Settings.getValue("private/settingsSafeURLS"); + // var arrayWhitelist = whitelist.split(/\s*,\s*/); + // var whitelistText = arrayWhitelist.join("\n"); + return whitelist; + } + + function setWhiteListAsText(whitelistText) { + console.info('SETTINGCURRENTVALUE: ', Settings.getValue('private/settingsSafeURLS'), whitelistText.text) + Settings.setValue("private/settingsSafeURLS", whitelistText.text); + console.info('SETVALUE: ', Settings.getValue('private/settingsSafeURLS'), whitelistText.text) + } + + anchors.fill: parent + width: parent.width; + height: 120; + color: "#80010203"; + + HifiStylesUit.RalewayRegular { + id: titleText; + text: "Entity Script Whitelist" + // Text size + size: 24; + // Style + color: "white"; + elide: Text.ElideRight; + // Anchors + anchors.top: parent.top; + anchors.left: parent.left; + anchors.leftMargin: 20; + anchors.right: parent.right; + anchors.rightMargin: 20; + height: 60; + } + + Rectangle { + id: textAreaRectangle; + color: "black"; + width: parent.width; + height: 250; + anchors.top: titleText.bottom; + + ScrollView { + id: textAreaScrollView + anchors.fill: parent; + width: parent.width + height: parent.height + contentWidth: parent.width + contentHeight: parent.height + clip: false; + + TextArea { + id: whitelistTextArea + text: getWhitelistAsText(); + width: parent.width; + height: parent.height; + font.family: "Ubuntu"; + font.pointSize: 12; + color: "white"; + } + } + + Button { + id: saveChanges + // anchors.top: whitelistTextArea.bottom; + anchors.topMargin: 5; + anchors.leftMargin: 20; + // anchors.right: whitelistTextArea.right; + anchors.rightMargin: 20; + x: textAreaRectangle.x + textAreaRectangle.width - width - 5; + y: textAreaRectangle.y + textAreaRectangle.height - height; + contentItem: Text { + text: saveChanges.text + font.family: "Ubuntu"; + font.pointSize: 12; + opacity: enabled ? 1.0 : 0.3 + color: "black" + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + text: "Save Changes" + onClicked: setWhiteListAsText(whitelistTextArea) + } + } +} \ No newline at end of file diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 508c44fbd1..9bc1dae56e 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -286,6 +286,20 @@ Menu::Menu() { hmd->toggleShouldShowTablet(); } }); + + // Settings > Entity Script Whitelist + action = addActionToQMenuAndActionHash(settingsMenu, "Entity Script Whitelist"); + connect(action, &QAction::triggered, [] { + auto tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); + auto hmd = DependencyManager::get(); + + DependencyManager::get()->clearCache(); + tablet->pushOntoStack("hifi/dialogs/security/EntityScriptWhitelist.qml"); + + if (!hmd->getShouldShowTablet()) { + hmd->toggleShouldShowTablet(); + } + }); // Settings > Developer Menu addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus())); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index ea118ec5dd..37b3f971fc 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -181,6 +181,7 @@ namespace MenuOption { const QString RunningScripts = "Running Scripts..."; const QString RunTimingTests = "Run Timing Tests"; const QString ScriptedMotorControl = "Enable Scripted Motor Control"; + const QString EntityScriptWhitelist = "Entity Script Whitelist"; const QString ShowTrackedObjects = "Show Tracked Objects"; const QString SelfieCamera = "Selfie"; const QString SendWrongDSConnectVersion = "Send wrong DS connect version"; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index f205b016d1..78b483e3b3 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -84,6 +84,11 @@ #include "../../midi/src/Midi.h" // FIXME why won't a simpler include work? #include "MIDIEvent.h" +#include "SettingHandle.h" +// #include "SettingManager.h" +// #include "SettingInterface.h" +// #include "SettingHelpers.h" + const QString ScriptEngine::_SETTINGS_ENABLE_EXTENDED_EXCEPTIONS { "com.highfidelity.experimental.enableExtendedJSExceptions" }; @@ -2362,10 +2367,30 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co QList safeURLS = { "https://FAKEURL.t43wt4g4g44FAKE" }; safeURLS += qEnvironmentVariable("EXTRA_WHITELIST").split(QRegExp("\\s*,\\s*"), QString::SkipEmptyParts); + // PULL SAFEURLS FROM INTERFACE.JSON Settings + + QVariant raw = Setting::Handle("private/settingsSafeURLS").get(); + // qDebug() << "raw value" << raw; + // qDebug() << "raw value as list" << raw.toList(); + QStringList settingsSafeURLS = raw.toString().split(QRegExp("[\r\n]+")); + safeURLS += settingsSafeURLS; + + // QVariantList settingsSafeURLS = Setting::Handle("private/settingsSafeURLS").get(); + // qCDebug(scriptengine) << "ESWsafeURLS" << safeURLS; + + // for (QVariantList::iterator surl = settingsSafeURLS.begin(); surl != settingsSafeURLS.end(); surl++) + // { + // safeURLS += (*surl).toString(); + // } + + // for (const auto& s : settingsSafeURLS) safeURLS << s.toString(); + + // END PULL SAFEURLS FROM INTERFACE.JSON Settings + bool isInWhitelist = false; // assume unsafe for (const auto& str : safeURLS) { // qDebug() << "CHECKING" << entityID.toString() << scriptOrURL << "AGAINST" << str; - qDebug() << "SCRIPTOURL STARTSWITH" << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN" + qCDebug(scriptengine) << "SCRIPT URL STARTSWITH" << scriptOrURL << "TESTING AGAINST" << str << "RESULTS IN" << scriptOrURL.startsWith(str); if (scriptOrURL.startsWith(str)) { isInWhitelist = true; @@ -2373,7 +2398,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co } } if (!isInWhitelist) { - qDebug() << "(disabled entity script)" << entityID.toString() << scriptOrURL; + qCDebug(scriptengine) << "(disabled entity script)" << entityID.toString() << scriptOrURL; exception = makeError("UNSAFE_ENTITY_SCRIPTS == 0"); } else { QTimer timeout; From bc17febb3f986fe9f897907b1abbd26b3dffe822 Mon Sep 17 00:00:00 2001 From: Kasen IO Date: Sun, 8 Dec 2019 21:05:16 -0500 Subject: [PATCH 2/3] updated Readme.MD for new whitelist instructiosn --- README.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a4d04b8254..d111667007 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ ### [Download (Windows 64-bit, .zip)](https://realities.dev/cdn/hifi-community/v0860-kasen-VS-release+freshstart/Packaged_Release.zip) -#### Changes for **v0.86.0 K1** consist of: +#### Changes for **v0.86.0** consist of: + +#### Added in K1 (12/3/19) * Audio Buffer choppy audio bugfix by increasing the buffer size. * User Activity Logger disabled, option in code to log the reports to console. @@ -11,13 +13,21 @@ * Entity Script Whitelist, no scripts are whitelisted by default. * Background CMD outputs full log, instant close of application on closing of the CMD-line. +#### Added in K2 (12/8/19) + +* QML Interface to access and save whitelist live to interface.json +* Add "VideoDecodeStats" to .gitignore +* Fix VCPKG SDL2 to port files from 2.0.8 to 2.0.10 to fix CMake build issues. + This build has been tested on Windows 10 Pro 64-bit w/ Nvidia graphics drivers. ### Whitelist Instructions The whitelist checks every entity-script attempting to run on your client against a list of domains, their subfolders, or the specific script URL entirely. -The **Start** batch file launches and sets the whitelist environment variable for you (you have to edit in your whitelisted domains), however if you launch interface.exe directly then you must set the Windows environment variable "**EXTRA_WHITELIST**" with your whitelisted domains comma separated like so: "**https://kasen.io/,http://kasen.io/,https://exampledomain.com/scriptFolder/**" +The Interface has the whitelist settings under "**Settings -> Entity Script Whitelist**" for you to configure live. The whitelist checks against the domains literally, so you have to be precise to ensure security and functionality. For example, the difference between "http://" and "https://" matters as those will be seen as two different domains in the eyes of the whitelist. + +You can also set the Windows environment variable "**EXTRA_WHITELIST**" with your whitelisted domains comma separated like so: "**https://kasen.io/,http://kasen.io/,https://exampledomain.com/scriptFolder/**" Alternatively you can make a batch file placed in the same folder as interface.exe that sets the whitelist environment variable temporarily: @@ -26,10 +36,6 @@ set "EXTRA_WHITELIST=http://mpassets.highfidelity.com/,https://raw.githubusercon interface.exe ``` -By default, we are whitelisting High Fidelity's current known CDN domains so we can see their own/hosted entity-script related content. - -The whitelist checks against the domains literally, so you have to be precise to ensure security and functionality. For example, the difference between "http://" and "https://" matters as those will be seen as two different domains in the eyes of the whitelist. - ### Boot to Metaverse: The Goal Too many of us have our own personal combinations of High Fidelity from C++ modifications to different default scripts, all of which are lost to time as their fullest potential is never truly shared and propagated through the system. From f49e64b99f8829221caa83cfe7324b87d7487e6f Mon Sep 17 00:00:00 2001 From: Kasen IO Date: Sun, 8 Dec 2019 21:12:20 -0500 Subject: [PATCH 3/3] Cleaned out extra commented code. --- .../hifi/dialogs/security/EntityScriptWhitelist.qml | 4 ---- libraries/script-engine/src/ScriptEngine.cpp | 12 ------------ 2 files changed, 16 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/security/EntityScriptWhitelist.qml b/interface/resources/qml/hifi/dialogs/security/EntityScriptWhitelist.qml index 45a8368ce4..ba3f27788d 100644 --- a/interface/resources/qml/hifi/dialogs/security/EntityScriptWhitelist.qml +++ b/interface/resources/qml/hifi/dialogs/security/EntityScriptWhitelist.qml @@ -24,8 +24,6 @@ Rectangle { function getWhitelistAsText() { var whitelist = Settings.getValue("private/settingsSafeURLS"); - // var arrayWhitelist = whitelist.split(/\s*,\s*/); - // var whitelistText = arrayWhitelist.join("\n"); return whitelist; } @@ -86,10 +84,8 @@ Rectangle { Button { id: saveChanges - // anchors.top: whitelistTextArea.bottom; anchors.topMargin: 5; anchors.leftMargin: 20; - // anchors.right: whitelistTextArea.right; anchors.rightMargin: 20; x: textAreaRectangle.x + textAreaRectangle.width - width - 5; y: textAreaRectangle.y + textAreaRectangle.height - height; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 78b483e3b3..d8d593df32 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -2370,21 +2370,9 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co // PULL SAFEURLS FROM INTERFACE.JSON Settings QVariant raw = Setting::Handle("private/settingsSafeURLS").get(); - // qDebug() << "raw value" << raw; - // qDebug() << "raw value as list" << raw.toList(); QStringList settingsSafeURLS = raw.toString().split(QRegExp("[\r\n]+")); safeURLS += settingsSafeURLS; - // QVariantList settingsSafeURLS = Setting::Handle("private/settingsSafeURLS").get(); - // qCDebug(scriptengine) << "ESWsafeURLS" << safeURLS; - - // for (QVariantList::iterator surl = settingsSafeURLS.begin(); surl != settingsSafeURLS.end(); surl++) - // { - // safeURLS += (*surl).toString(); - // } - - // for (const auto& s : settingsSafeURLS) safeURLS << s.toString(); - // END PULL SAFEURLS FROM INTERFACE.JSON Settings bool isInWhitelist = false; // assume unsafe