summaryrefslogtreecommitdiffstats
path: root/src/webview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/webview.cpp')
-rw-r--r--src/webview.cpp121
1 files changed, 86 insertions, 35 deletions
diff --git a/src/webview.cpp b/src/webview.cpp
index 1e4a3a4..c4995bd 100644
--- a/src/webview.cpp
+++ b/src/webview.cpp
@@ -2,7 +2,6 @@
#include "global.h"
-#include <QAction>
#include <QMessageBox>
#include <QTimer>
#include <QUrlQuery>
@@ -22,6 +21,9 @@
#include <QWebEngineUrlRequestInterceptor>
#include <QWebEngineScriptCollection>
+#include "global.h"
+#include "settings.h"
+
// Add: custom page to catch console messages from JS
class ActivityPage : public QWebEnginePage
{
@@ -273,38 +275,51 @@ static QRegularExpression urlListToRegExp(const QStringList &list)
void WebView::installJsInjectionScript()
{
- // If we should filter the list of allowed IdPs, inject the list into
- // the page as JavaScript
- QString str = Global::getCombinedIdpWhitelist().replace(
- QRegularExpression("[^\\w. /:-]", QRegularExpression::UseUnicodePropertiesOption),
- QString());
- QWebEngineScript script;
- script.setName(QStringLiteral("slxIdpFilterInjector"));
- script.setInjectionPoint(QWebEngineScript::DocumentCreation);
- script.setWorldId(QWebEngineScript::MainWorld);
- script.setRunsOnSubFrames(true);
- script.setSourceCode(QStringLiteral("var slxIdpFilter ='") + str + QStringLiteral("';"));
- page()->scripts().insert(script);
-
- // Inject activity listeners to signal user interaction back to C++
- QWebEngineScript activityScript;
- activityScript.setName(QStringLiteral("slxUserActivity"));
- activityScript.setInjectionPoint(QWebEngineScript::DocumentCreation);
- activityScript.setWorldId(QWebEngineScript::MainWorld);
- activityScript.setRunsOnSubFrames(true);
- activityScript.setSourceCode(QStringLiteral(
- "(function(){\n"
- " var last=0; function ping(){\n"
- " var now=Date.now(); if(now-last<2000) return; last=now;\n"
- " try{console.debug('LOG_USER_ACTIVITY');}catch(e){}\n"
- " }\n"
- " var evts=['mousedown','mouseup','click','keydown','keyup','wheel','touchstart','touchend','scroll'];\n"
- " evts.forEach(function(ev){\n"
- " window.addEventListener(ev, ping, {passive:true, capture:true});\n"
- " });\n"
- "})();\n"
- ));
- page()->scripts().insert(activityScript);
+ QString idpSpaceList;
+ {
+ // If we should filter the list of allowed IdPs, inject the list into
+ // the page as JavaScript
+ static QRegularExpression REGEX("[^\\w./:@-]", QRegularExpression::UseUnicodePropertiesOption);
+ const auto& map = Global::getCombinedIdpWhitelist();
+ QSet<QString> idpList;
+ for (auto it = map.constBegin(); it != map.constEnd(); ++it) {
+ for (QString s : it.value().toStringList()) {
+ idpList.insert(s.replace(REGEX, QString()));
+ }
+ }
+ idpSpaceList = idpList.values().join(' ');
+ }
+ {
+ QWebEngineScript script;
+ script.setName(QStringLiteral("slxIdpFilterInjector"));
+ script.setInjectionPoint(QWebEngineScript::DocumentCreation);
+ script.setWorldId(QWebEngineScript::MainWorld);
+ script.setRunsOnSubFrames(true);
+ script.setSourceCode(QStringLiteral("var slxIdpFilter = '")
+ + idpSpaceList + QStringLiteral("';"));
+ page()->scripts().insert(script);
+ }
+ {
+ // Inject activity listeners to signal user interaction back to C++
+ QWebEngineScript activityScript;
+ activityScript.setName(QStringLiteral("slxUserActivity"));
+ activityScript.setInjectionPoint(QWebEngineScript::DocumentCreation);
+ activityScript.setWorldId(QWebEngineScript::MainWorld);
+ activityScript.setRunsOnSubFrames(true);
+ activityScript.setSourceCode(QStringLiteral(
+ "(function(){\n"
+ " var last=0; function ping(){\n"
+ " var now=Date.now(); if(now-last<2000) return; last=now;\n"
+ " try{console.debug('LOG_USER_ACTIVITY');}catch(e){}\n"
+ " }\n"
+ " var evts=['mousedown','mouseup','click','keydown','keyup','wheel','touchstart','touchend','scroll'];\n"
+ " evts.forEach(function(ev){\n"
+ " window.addEventListener(ev, ping, {passive:true, capture:true});\n"
+ " });\n"
+ "})();\n"
+ ));
+ page()->scripts().insert(activityScript);
+ }
}
void WebView::contextMenuEvent(QContextMenuEvent* ev)
@@ -315,7 +330,7 @@ void WebView::contextMenuEvent(QContextMenuEvent* ev)
// Find and remove/hide the "View source" action
QAction* viewSource = page()->action(QWebEnginePage::ViewSource);
if (viewSource) {
- viewSource->setVisible(false); // or: menu->removeAction(viewSource);
+ viewSource->setVisible(false);
viewSource->setEnabled(false);
}
@@ -337,7 +352,9 @@ void WebView::evaluateAuthDom()
" pass: t('#bwlp-password'),"
" err: t('#bwlp-error'),"
" hash: t('#bwlp-hash'),"
- " adminToken: t('#bwlp-cow-token')"
+ " adminToken: t('#bwlp-cow-token'),"
+ " idp: t('#bwlp-idp'),"
+ " entitlement: t('#bwlp-entitlement')"
" };"
"})();"
);
@@ -349,6 +366,8 @@ void WebView::evaluateAuthDom()
const QString err = map.value(QStringLiteral("err")).toString();
const QString hash = map.value(QStringLiteral("hash")).toString();
const QString adminToken = map.value(QStringLiteral("adminToken")).toString();
+ const QString idp = map.value(QStringLiteral("idp")).toString();
+ const QStringList userEntitlements = map.value(QStringLiteral("entitlement")).toString().split(';');
if (!user.isEmpty() && !pass.isEmpty() && !hash.isEmpty()) {
if (hash != QCryptographicHash::hash(_token.toLatin1(), QCryptographicHash::Md5).toHex()) {
@@ -356,6 +375,38 @@ void WebView::evaluateAuthDom()
emit triggerReset(QStringLiteral("Invalid Hash"));
return;
}
+ const auto &idpMap = Global::getCombinedIdpWhitelist();
+ if (!idpMap.isEmpty()) {
+ bool ok = false;
+ for (auto it = idpMap.constBegin(); it != idpMap.constEnd(); ++it) {
+ if (it.key().isEmpty()) {
+ // An "anything goes" list, no restrictions
+ if (it.value().toStringList().contains(idp)) {
+ ok = true;
+ break;
+ }
+ } else if (it.value().toStringList().contains(idp)) {
+ // IdP in list, so if the entitlements match up, allow
+ ok = true;
+ // Break up key into individual entitlements, make sure the user has them all
+ QStringList requiredEntitlements = it.key().split(';');
+ for (const QString &n : requiredEntitlements) {
+ if (!userEntitlements.contains(n)) {
+ ok = false;
+ break;
+ }
+ }
+ if (ok)
+ break;
+ }
+ }
+ // Disallow if entitlement requirements are not met
+ if (!ok) {
+ QMessageBox::warning(this, QStringLiteral("Invalid entitlements"), Settings::shibEntitlementMissingText());
+ emit triggerReset(QStringLiteral("Invalid entitlements"));
+ return;
+ }
+ }
if (Global::isValidShibCreds(user, pass)) {
if (!adminToken.isEmpty()) {
Global::writeCowToken(user, adminToken);