00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kauthorized.h"
00022
00023 #include <QtCore/QDir>
00024 #include <QtCore/QRegExp>
00025 #include <QList>
00026
00027
00028 #include <QCoreApplication>
00029 #include <kglobal.h>
00030 #include <ksharedconfig.h>
00031 #include <kprotocolinfo.h>
00032 #include <kstandarddirs.h>
00033 #include <stdlib.h>
00034 #include <unistd.h>
00035 #include <netdb.h>
00036 #include <kurl.h>
00037 #include <kconfiggroup.h>
00038
00039 #include <QMutex>
00040 #include <QMutexLocker>
00041 #include <QtCore/QBool>
00042
00043 #ifdef __GNUC__
00044 #warning used non public api for now
00045 #endif
00046 extern bool kde_kiosk_exception;
00047
00048
00049 class URLActionRule
00050 {
00051 public:
00052 #define checkExactMatch(s, b) \
00053 if (s.isEmpty()) b = true; \
00054 else if (s[s.length()-1] == '!') \
00055 { b = false; s.truncate(s.length()-1); } \
00056 else b = true;
00057 #define checkStartWildCard(s, b) \
00058 if (s.isEmpty()) b = true; \
00059 else if (s[0] == '*') \
00060 { b = true; s = s.mid(1); } \
00061 else b = false;
00062 #define checkEqual(s, b) \
00063 b = (s == "=");
00064
00065 URLActionRule(const QString &act,
00066 const QString &bProt, const QString &bHost, const QString &bPath,
00067 const QString &dProt, const QString &dHost, const QString &dPath,
00068 bool perm)
00069 : action(act),
00070 baseProt(bProt), baseHost(bHost), basePath(bPath),
00071 destProt(dProt), destHost(dHost), destPath(dPath),
00072 permission(perm)
00073 {
00074 checkExactMatch(baseProt, baseProtWildCard);
00075 checkStartWildCard(baseHost, baseHostWildCard);
00076 checkExactMatch(basePath, basePathWildCard);
00077 checkExactMatch(destProt, destProtWildCard);
00078 checkStartWildCard(destHost, destHostWildCard);
00079 checkExactMatch(destPath, destPathWildCard);
00080 checkEqual(destProt, destProtEqual);
00081 checkEqual(destHost, destHostEqual);
00082 }
00083
00084 bool baseMatch(const KUrl &url, const QString &protClass) const
00085 {
00086 if (baseProtWildCard)
00087 {
00088 if ( !baseProt.isEmpty() && !url.protocol().startsWith(baseProt) &&
00089 (protClass.isEmpty() || (protClass != baseProt)) )
00090 return false;
00091 }
00092 else
00093 {
00094 if ( (url.protocol() != baseProt) &&
00095 (protClass.isEmpty() || (protClass != baseProt)) )
00096 return false;
00097 }
00098 if (baseHostWildCard)
00099 {
00100 if (!baseHost.isEmpty() && !url.host().endsWith(baseHost))
00101 return false;
00102 }
00103 else
00104 {
00105 if (url.host() != baseHost)
00106 return false;
00107 }
00108 if (basePathWildCard)
00109 {
00110 if (!basePath.isEmpty() && !url.path().startsWith(basePath))
00111 return false;
00112 }
00113 else
00114 {
00115 if (url.path() != basePath)
00116 return false;
00117 }
00118 return true;
00119 }
00120
00121 bool destMatch(const KUrl &url, const QString &protClass, const KUrl &base, const QString &baseClass) const
00122 {
00123 if (destProtEqual)
00124 {
00125 if ( (url.protocol() != base.protocol()) &&
00126 (protClass.isEmpty() || baseClass.isEmpty() || protClass != baseClass) )
00127 return false;
00128 }
00129 else if (destProtWildCard)
00130 {
00131 if ( !destProt.isEmpty() && !url.protocol().startsWith(destProt) &&
00132 (protClass.isEmpty() || (protClass != destProt)) )
00133 return false;
00134 }
00135 else
00136 {
00137 if ( (url.protocol() != destProt) &&
00138 (protClass.isEmpty() || (protClass != destProt)) )
00139 return false;
00140 }
00141 if (destHostWildCard)
00142 {
00143 if (!destHost.isEmpty() && !url.host().endsWith(destHost))
00144 return false;
00145 }
00146 else if (destHostEqual)
00147 {
00148 if (url.host() != base.host())
00149 return false;
00150 }
00151 else
00152 {
00153 if (url.host() != destHost)
00154 return false;
00155 }
00156 if (destPathWildCard)
00157 {
00158 if (!destPath.isEmpty() && !url.path().startsWith(destPath))
00159 return false;
00160 }
00161 else
00162 {
00163 if (url.path() != destPath)
00164 return false;
00165 }
00166 return true;
00167 }
00168
00169 QString action;
00170 QString baseProt;
00171 QString baseHost;
00172 QString basePath;
00173 QString destProt;
00174 QString destHost;
00175 QString destPath;
00176 bool baseProtWildCard : 1;
00177 bool baseHostWildCard : 1;
00178 bool basePathWildCard : 1;
00179 bool destProtWildCard : 1;
00180 bool destHostWildCard : 1;
00181 bool destPathWildCard : 1;
00182 bool destProtEqual : 1;
00183 bool destHostEqual : 1;
00184 bool permission;
00185 };
00186
00187 class KAuthorizedPrivate {
00188 public:
00189 KAuthorizedPrivate()
00190 : actionRestrictions( false ), blockEverything(false),mutex(QMutex::Recursive)
00191 {
00192 Q_ASSERT_X(QCoreApplication::instance(),"KAuthorizedPrivate()","There has to be an existing QCoreApplication::instance() pointer");
00193
00194 KSharedConfig::Ptr config = KGlobal::config();
00195
00196 Q_ASSERT_X(config,"KAuthorizedPrivate()","There has to be an existing KGlobal::config() pointer");
00197 if (!config) {
00198 blockEverything=true;
00199 return;
00200 }
00201 actionRestrictions = config->hasGroup("KDE Action Restrictions" ) && !kde_kiosk_exception;
00202 }
00203
00204 ~KAuthorizedPrivate()
00205 {
00206 }
00207
00208 bool actionRestrictions : 1;
00209 bool blockEverything : 1;
00210 QList<URLActionRule> urlActionRestrictions;
00211 QMutex mutex;
00212 };
00213
00214 Q_GLOBAL_STATIC(KAuthorizedPrivate,authPrivate)
00215 #define MY_D KAuthorizedPrivate *d=authPrivate();
00216
00217
00218 bool KAuthorized::authorize(const QString &genericAction)
00219 {
00220 MY_D
00221 if (d->blockEverything) return false;
00222
00223 if (!d->actionRestrictions)
00224 return true;
00225
00226 KConfigGroup cg(KGlobal::config(), "KDE Action Restrictions");
00227 return cg.readEntry(genericAction, true);
00228 }
00229
00230 bool KAuthorized::authorizeKAction(const QString& action)
00231 {
00232 MY_D
00233 if (d->blockEverything) return false;
00234 if (!d->actionRestrictions || action.isEmpty())
00235 return true;
00236
00237 return authorize(QLatin1String("action/") + action);
00238 }
00239
00240 bool KAuthorized::authorizeControlModule(const QString &menuId)
00241 {
00242 if (menuId.isEmpty() || kde_kiosk_exception)
00243 return true;
00244 KConfigGroup cg(KGlobal::config(), "KDE Control Module Restrictions");
00245 return cg.readEntry(menuId, true);
00246 }
00247
00248 QStringList KAuthorized::authorizeControlModules(const QStringList &menuIds)
00249 {
00250 KConfigGroup cg(KGlobal::config(), "KDE Control Module Restrictions");
00251 QStringList result;
00252 for(QStringList::ConstIterator it = menuIds.begin();
00253 it != menuIds.end(); ++it)
00254 {
00255 if (cg.readEntry(*it, true))
00256 result.append(*it);
00257 }
00258 return result;
00259 }
00260
00261 static void initUrlActionRestrictions()
00262 {
00263 MY_D
00264 const QString Any;
00265
00266 d->urlActionRestrictions.clear();
00267 d->urlActionRestrictions.append(
00268 URLActionRule("open", Any, Any, Any, Any, Any, Any, true));
00269 d->urlActionRestrictions.append(
00270 URLActionRule("list", Any, Any, Any, Any, Any, Any, true));
00271
00272
00273
00274
00275
00276 d->urlActionRestrictions.append(
00277 URLActionRule("link", Any, Any, Any, ":internet", Any, Any, true));
00278 d->urlActionRestrictions.append(
00279 URLActionRule("redirect", Any, Any, Any, ":internet", Any, Any, true));
00280
00281
00282
00283 d->urlActionRestrictions.append(
00284 URLActionRule("redirect", Any, Any, Any, "file", Any, Any, true));
00285 d->urlActionRestrictions.append(
00286 URLActionRule("redirect", ":internet", Any, Any, "file", Any, Any, false));
00287
00288
00289 d->urlActionRestrictions.append(
00290 URLActionRule("redirect", ":local", Any, Any, Any, Any, Any, true));
00291
00292
00293 d->urlActionRestrictions.append(
00294 URLActionRule("redirect", Any, Any, Any, "about", Any, Any, true));
00295
00296
00297 d->urlActionRestrictions.append(
00298 URLActionRule("redirect", Any, Any, Any, "=", Any, Any, true));
00299
00300 d->urlActionRestrictions.append(
00301 URLActionRule("redirect", "about", Any, Any, Any, Any, Any, true));
00302
00303
00304 KConfigGroup cg(KGlobal::config(), "KDE URL Restrictions");
00305 int count = cg.readEntry("rule_count", 0);
00306 QString keyFormat = QString("rule_%1");
00307 for(int i = 1; i <= count; i++)
00308 {
00309 QString key = keyFormat.arg(i);
00310 const QStringList rule = cg.readEntry(key, QStringList());
00311 if (rule.count() != 8)
00312 continue;
00313 QString action = rule[0];
00314 QString refProt = rule[1];
00315 QString refHost = rule[2];
00316 QString refPath = rule[3];
00317 QString urlProt = rule[4];
00318 QString urlHost = rule[5];
00319 QString urlPath = rule[6];
00320 bool bEnabled = (rule[7].toLower() == "true");
00321
00322 if (refPath.startsWith("$HOME"))
00323 refPath.replace(0, 5, QDir::homePath());
00324 else if (refPath.startsWith('~'))
00325 refPath.replace(0, 1, QDir::homePath());
00326 if (urlPath.startsWith("$HOME"))
00327 urlPath.replace(0, 5, QDir::homePath());
00328 else if (urlPath.startsWith('~'))
00329 urlPath.replace(0, 1, QDir::homePath());
00330
00331 if (refPath.startsWith("$TMP"))
00332 refPath.replace(0, 4, KGlobal::dirs()->saveLocation("tmp"));
00333 if (urlPath.startsWith("$TMP"))
00334 urlPath.replace(0, 4, KGlobal::dirs()->saveLocation("tmp"));
00335
00336 d->urlActionRestrictions.append(
00337 URLActionRule( action, refProt, refHost, refPath, urlProt, urlHost, urlPath, bEnabled));
00338 }
00339 }
00340
00341 void KAuthorized::allowUrlAction(const QString &action, const KUrl &_baseURL, const KUrl &_destURL)
00342 {
00343 MY_D
00344 QMutexLocker locker((&d->mutex));
00345 if (authorizeUrlAction(action, _baseURL, _destURL))
00346 return;
00347
00348 d->urlActionRestrictions.append( URLActionRule
00349 ( action, _baseURL.protocol(), _baseURL.host(), _baseURL.path(KUrl::RemoveTrailingSlash),
00350 _destURL.protocol(), _destURL.host(), _destURL.path(KUrl::RemoveTrailingSlash), true));
00351 }
00352
00353 bool KAuthorized::authorizeUrlAction(const QString &action, const KUrl &_baseURL, const KUrl &_destURL)
00354 {
00355 MY_D
00356 QMutexLocker locker(&(d->mutex));
00357 if (d->blockEverything) return false;
00358
00359 if (_destURL.isEmpty())
00360 return true;
00361
00362 bool result = false;
00363 if (d->urlActionRestrictions.isEmpty())
00364 initUrlActionRestrictions();
00365
00366 KUrl baseURL(_baseURL);
00367 baseURL.setPath(QDir::cleanPath(baseURL.path()));
00368 QString baseClass = KProtocolInfo::protocolClass(baseURL.protocol());
00369 KUrl destURL(_destURL);
00370 destURL.setPath(QDir::cleanPath(destURL.path()));
00371 QString destClass = KProtocolInfo::protocolClass(destURL.protocol());
00372
00373 foreach(const URLActionRule &rule, d->urlActionRestrictions) {
00374 if ((result != rule.permission) &&
00375 (action == rule.action) &&
00376 rule.baseMatch(baseURL, baseClass) &&
00377 rule.destMatch(destURL, destClass, baseURL, baseClass))
00378 {
00379 result = rule.permission;
00380 }
00381 }
00382 return result;
00383 }