aboutsummaryrefslogtreecommitdiff
path: root/src/core/kauthorized.cpp
diff options
context:
space:
mode:
authorJenkins CI <null@kde.org>2013-12-18 00:45:18 +0000
committerJenkins CI <null@kde.org>2013-12-18 00:45:18 +0000
commit867e7a50e6396338ab4fe9aa22ad141e4cd344d2 (patch)
tree1d6f8d6c912fa04dc268b5580bcfe696fa538743 /src/core/kauthorized.cpp
parentc38b88497a833e482e6892b72c8f52adec6de857 (diff)
downloadkconfig-867e7a50e6396338ab4fe9aa22ad141e4cd344d2.tar.gz
kconfig-867e7a50e6396338ab4fe9aa22ad141e4cd344d2.tar.bz2
Move kconfig code to the root directory.
Diffstat (limited to 'src/core/kauthorized.cpp')
-rw-r--r--src/core/kauthorized.cpp393
1 files changed, 393 insertions, 0 deletions
diff --git a/src/core/kauthorized.cpp b/src/core/kauthorized.cpp
new file mode 100644
index 00000000..abf479ca
--- /dev/null
+++ b/src/core/kauthorized.cpp
@@ -0,0 +1,393 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
+ Copyright (C) 1998, 1999, 2000 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kauthorized.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QRegExp>
+#include <QList>
+#include <QUrl>
+
+#include <QCoreApplication>
+#include <ksharedconfig.h>
+#include <stdlib.h> // srand(), rand()
+#ifndef Q_OS_WIN
+#include <unistd.h>
+#include <netdb.h>
+#endif
+
+#include <kconfiggroup.h>
+
+#include <QMutex>
+#include <QMutexLocker>
+
+extern bool kde_kiosk_exception;
+
+
+class URLActionRule
+{
+ public:
+#define checkExactMatch(s, b) \
+ if (s.isEmpty()) b = true; \
+ else if (s[s.length()-1] == QLatin1Char('!')) \
+ { b = false; s.truncate(s.length()-1); } \
+ else b = true;
+#define checkStartWildCard(s, b) \
+ if (s.isEmpty()) b = true; \
+ else if (s[0] == QLatin1Char('*')) \
+ { b = true; s = s.mid(1); } \
+ else b = false;
+#define checkEqual(s, b) \
+ b = (s == QString::fromLatin1("="));
+
+ URLActionRule(const QByteArray &act,
+ const QString &bProt, const QString &bHost, const QString &bPath,
+ const QString &dProt, const QString &dHost, const QString &dPath,
+ bool perm)
+ : action(act),
+ baseProt(bProt), baseHost(bHost), basePath(bPath),
+ destProt(dProt), destHost(dHost), destPath(dPath),
+ permission(perm)
+ {
+ checkExactMatch(baseProt, baseProtWildCard);
+ checkStartWildCard(baseHost, baseHostWildCard);
+ checkExactMatch(basePath, basePathWildCard);
+ checkExactMatch(destProt, destProtWildCard);
+ checkStartWildCard(destHost, destHostWildCard);
+ checkExactMatch(destPath, destPathWildCard);
+ checkEqual(destProt, destProtEqual);
+ checkEqual(destHost, destHostEqual);
+ }
+
+ bool baseMatch(const QUrl &url, const QString &protClass) const
+ {
+ if (baseProtWildCard)
+ {
+ if ( !baseProt.isEmpty() && !url.scheme().startsWith(baseProt) &&
+ (protClass.isEmpty() || (protClass != baseProt)) )
+ return false;
+ }
+ else
+ {
+ if ( (url.scheme() != baseProt) &&
+ (protClass.isEmpty() || (protClass != baseProt)) )
+ return false;
+ }
+ if (baseHostWildCard)
+ {
+ if (!baseHost.isEmpty() && !url.host().endsWith(baseHost))
+ return false;
+ }
+ else
+ {
+ if (url.host() != baseHost)
+ return false;
+ }
+ if (basePathWildCard)
+ {
+ if (!basePath.isEmpty() && !url.path().startsWith(basePath))
+ return false;
+ }
+ else
+ {
+ if (url.path() != basePath)
+ return false;
+ }
+ return true;
+ }
+
+ bool destMatch(const QUrl &url, const QString &protClass, const QUrl &base, const QString &baseClass) const
+ {
+ if (destProtEqual)
+ {
+ if ( (url.scheme() != base.scheme()) &&
+ (protClass.isEmpty() || baseClass.isEmpty() || protClass != baseClass) )
+ return false;
+ }
+ else if (destProtWildCard)
+ {
+ if ( !destProt.isEmpty() && !url.scheme().startsWith(destProt) &&
+ (protClass.isEmpty() || (protClass != destProt)) )
+ return false;
+ }
+ else
+ {
+ if ( (url.scheme() != destProt) &&
+ (protClass.isEmpty() || (protClass != destProt)) )
+ return false;
+ }
+ if (destHostWildCard)
+ {
+ if (!destHost.isEmpty() && !url.host().endsWith(destHost))
+ return false;
+ }
+ else if (destHostEqual)
+ {
+ if (url.host() != base.host())
+ return false;
+ }
+ else
+ {
+ if (url.host() != destHost)
+ return false;
+ }
+ if (destPathWildCard)
+ {
+ if (!destPath.isEmpty() && !url.path().startsWith(destPath))
+ return false;
+ }
+ else
+ {
+ if (url.path() != destPath)
+ return false;
+ }
+ return true;
+ }
+
+ QByteArray action;
+ QString baseProt;
+ QString baseHost;
+ QString basePath;
+ QString destProt;
+ QString destHost;
+ QString destPath;
+ bool baseProtWildCard : 1;
+ bool baseHostWildCard : 1;
+ bool basePathWildCard : 1;
+ bool destProtWildCard : 1;
+ bool destHostWildCard : 1;
+ bool destPathWildCard : 1;
+ bool destProtEqual : 1;
+ bool destHostEqual : 1;
+ bool permission;
+};
+
+class KAuthorizedPrivate {
+public:
+ KAuthorizedPrivate()
+ : actionRestrictions( false ), blockEverything(false),mutex(QMutex::Recursive)
+ {
+ Q_ASSERT_X(QCoreApplication::instance(),"KAuthorizedPrivate()","There has to be an existing QCoreApplication::instance() pointer");
+
+ KSharedConfig::Ptr config = KSharedConfig::openConfig();
+
+ Q_ASSERT_X(config,"KAuthorizedPrivate()","There has to be an existing KSharedConfig::openConfig() pointer");
+ if (!config) {
+ blockEverything=true;
+ return;
+ }
+ actionRestrictions = config->hasGroup("KDE Action Restrictions" ) && !kde_kiosk_exception;
+ }
+
+ ~KAuthorizedPrivate()
+ {
+ }
+
+ bool actionRestrictions : 1;
+ bool blockEverything : 1;
+ QList<URLActionRule> urlActionRestrictions;
+ QMutex mutex;
+};
+
+Q_GLOBAL_STATIC(KAuthorizedPrivate,authPrivate)
+#define MY_D KAuthorizedPrivate *d=authPrivate();
+
+
+bool KAuthorized::authorize(const QString &genericAction)
+{
+ MY_D
+ if (d->blockEverything) return false;
+
+ if (!d->actionRestrictions)
+ return true;
+
+ KConfigGroup cg(KSharedConfig::openConfig(), "KDE Action Restrictions");
+ return cg.readEntry(genericAction, true);
+}
+
+bool KAuthorized::authorizeKAction(const QString& action)
+{
+ MY_D
+ if (d->blockEverything) return false;
+ if (!d->actionRestrictions || action.isEmpty())
+ return true;
+
+ return authorize(QLatin1String("action/") + action);
+}
+
+bool KAuthorized::authorizeControlModule(const QString &menuId)
+{
+ if (menuId.isEmpty() || kde_kiosk_exception)
+ return true;
+ KConfigGroup cg(KSharedConfig::openConfig(), "KDE Control Module Restrictions");
+ return cg.readEntry(menuId, true);
+}
+
+QStringList KAuthorized::authorizeControlModules(const QStringList &menuIds)
+{
+ KConfigGroup cg(KSharedConfig::openConfig(), "KDE Control Module Restrictions");
+ QStringList result;
+ for(QStringList::ConstIterator it = menuIds.begin();
+ it != menuIds.end(); ++it)
+ {
+ if (cg.readEntry(*it, true))
+ result.append(*it);
+ }
+ return result;
+}
+
+static void initUrlActionRestrictions()
+{
+ MY_D
+ const QString Any;
+
+ d->urlActionRestrictions.clear();
+ d->urlActionRestrictions.append(
+ URLActionRule("open", Any, Any, Any, Any, Any, Any, true));
+ d->urlActionRestrictions.append(
+ URLActionRule("list", Any, Any, Any, Any, Any, Any, true));
+// TEST:
+// d->urlActionRestrictions.append(
+// URLActionRule("list", Any, Any, Any, Any, Any, Any, false));
+// d->urlActionRestrictions.append(
+// URLActionRule("list", Any, Any, Any, "file", Any, QDir::homePath(), true));
+ d->urlActionRestrictions.append(
+ URLActionRule("link", Any, Any, Any, QLatin1String(":internet"), Any, Any, true));
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", Any, Any, Any, QLatin1String(":internet"), Any, Any, true));
+
+ // We allow redirections to file: but not from internet protocols, redirecting to file:
+ // is very popular among io-slaves and we don't want to break them
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", Any, Any, Any, QLatin1String("file"), Any, Any, true));
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", QLatin1String(":internet"), Any, Any, QLatin1String("file"), Any, Any, false));
+
+ // local protocols may redirect everywhere
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", QLatin1String(":local"), Any, Any, Any, Any, Any, true));
+
+ // Anyone may redirect to about:
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", Any, Any, Any, QLatin1String("about"), Any, Any, true));
+
+ // Anyone may redirect to mailto:
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", Any, Any, Any, QLatin1String("mailto"), Any, Any, true));
+
+ // Anyone may redirect to itself, cq. within it's own group
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", Any, Any, Any, QLatin1String("="), Any, Any, true));
+
+ d->urlActionRestrictions.append(
+ URLActionRule("redirect", QLatin1String("about"), Any, Any, Any, Any, Any, true));
+
+
+ KConfigGroup cg(KSharedConfig::openConfig(), "KDE URL Restrictions");
+ int count = cg.readEntry("rule_count", 0);
+ QString keyFormat = QString::fromLatin1("rule_%1");
+ for(int i = 1; i <= count; i++)
+ {
+ QString key = keyFormat.arg(i);
+ const QStringList rule = cg.readEntry(key, QStringList());
+ if (rule.count() != 8)
+ continue;
+ const QByteArray action = rule[0].toLatin1();
+ QString refProt = rule[1];
+ QString refHost = rule[2];
+ QString refPath = rule[3];
+ QString urlProt = rule[4];
+ QString urlHost = rule[5];
+ QString urlPath = rule[6];
+ bool bEnabled = (rule[7].toLower() == QLatin1String("true"));
+
+ if (refPath.startsWith(QLatin1String("$HOME")))
+ refPath.replace(0, 5, QDir::homePath());
+ else if (refPath.startsWith(QLatin1Char('~')))
+ refPath.replace(0, 1, QDir::homePath());
+ if (urlPath.startsWith(QLatin1String("$HOME")))
+ urlPath.replace(0, 5, QDir::homePath());
+ else if (urlPath.startsWith(QLatin1Char('~')))
+ urlPath.replace(0, 1, QDir::homePath());
+
+ if (refPath.startsWith(QLatin1String("$TMP")))
+ refPath.replace(0, 4, QDir::tempPath());
+ if (urlPath.startsWith(QLatin1String("$TMP")))
+ urlPath.replace(0, 4, QDir::tempPath());
+
+ d->urlActionRestrictions.append(
+ URLActionRule( action, refProt, refHost, refPath, urlProt, urlHost, urlPath, bEnabled));
+ }
+}
+
+namespace KAuthorized
+{
+// Called by KAuthorized::allowUrlAction in KIO
+KCONFIGCORE_EXPORT void allowUrlActionInternal(const QString &action, const QUrl &_baseURL, const QUrl &_destURL)
+{
+ MY_D
+ QMutexLocker locker((&d->mutex));
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0)
+ const QString basePath = _baseURL.adjusted(QUrl::StripTrailingSlash).path();
+ const QString destPath = _destURL.adjusted(QUrl::StripTrailingSlash).path();
+#else
+ const QString basePath = QUrl(_baseURL.toString(QUrl::StripTrailingSlash)).path();
+ const QString destPath = QUrl(_destURL.toString(QUrl::StripTrailingSlash)).path();
+#endif
+
+ d->urlActionRestrictions.append( URLActionRule
+ ( action.toLatin1(), _baseURL.scheme(), _baseURL.host(), basePath,
+ _destURL.scheme(), _destURL.host(), destPath, true));
+}
+
+// Called by KAuthorized::authorizeUrlAction in KIO
+KCONFIGCORE_EXPORT bool authorizeUrlActionInternal(const QString& action, const QUrl &_baseURL, const QUrl &_destURL, const QString& baseClass, const QString& destClass)
+{
+ MY_D
+ QMutexLocker locker(&(d->mutex));
+ if (d->blockEverything) return false;
+
+ if (_destURL.isEmpty())
+ return true;
+
+ bool result = false;
+ if (d->urlActionRestrictions.isEmpty())
+ initUrlActionRestrictions();
+
+ QUrl baseURL(_baseURL);
+ baseURL.setPath(QDir::cleanPath(baseURL.path()));
+
+ QUrl destURL(_destURL);
+ destURL.setPath(QDir::cleanPath(destURL.path()));
+
+ Q_FOREACH(const URLActionRule &rule, d->urlActionRestrictions) {
+ if ((result != rule.permission) && // No need to check if it doesn't make a difference
+ (action == QLatin1String(rule.action.constData())) &&
+ rule.baseMatch(baseURL, baseClass) &&
+ rule.destMatch(destURL, destClass, baseURL, baseClass))
+ {
+ result = rule.permission;
+ }
+ }
+ return result;
+}
+
+} // namespace