KDECore
kauthorized.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org) 00003 Copyright (C) 1998, 1999, 2000 Waldo Bastian <bastian@kde.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 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> // srand(), rand() 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 extern bool kde_kiosk_exception; 00044 00045 00046 class URLActionRule 00047 { 00048 public: 00049 #define checkExactMatch(s, b) \ 00050 if (s.isEmpty()) b = true; \ 00051 else if (s[s.length()-1] == QLatin1Char('!')) \ 00052 { b = false; s.truncate(s.length()-1); } \ 00053 else b = true; 00054 #define checkStartWildCard(s, b) \ 00055 if (s.isEmpty()) b = true; \ 00056 else if (s[0] == QLatin1Char('*')) \ 00057 { b = true; s = s.mid(1); } \ 00058 else b = false; 00059 #define checkEqual(s, b) \ 00060 b = (s == QString::fromLatin1("=")); 00061 00062 URLActionRule(const QByteArray &act, 00063 const QString &bProt, const QString &bHost, const QString &bPath, 00064 const QString &dProt, const QString &dHost, const QString &dPath, 00065 bool perm) 00066 : action(act), 00067 baseProt(bProt), baseHost(bHost), basePath(bPath), 00068 destProt(dProt), destHost(dHost), destPath(dPath), 00069 permission(perm) 00070 { 00071 checkExactMatch(baseProt, baseProtWildCard); 00072 checkStartWildCard(baseHost, baseHostWildCard); 00073 checkExactMatch(basePath, basePathWildCard); 00074 checkExactMatch(destProt, destProtWildCard); 00075 checkStartWildCard(destHost, destHostWildCard); 00076 checkExactMatch(destPath, destPathWildCard); 00077 checkEqual(destProt, destProtEqual); 00078 checkEqual(destHost, destHostEqual); 00079 } 00080 00081 bool baseMatch(const KUrl &url, const QString &protClass) const 00082 { 00083 if (baseProtWildCard) 00084 { 00085 if ( !baseProt.isEmpty() && !url.protocol().startsWith(baseProt) && 00086 (protClass.isEmpty() || (protClass != baseProt)) ) 00087 return false; 00088 } 00089 else 00090 { 00091 if ( (url.protocol() != baseProt) && 00092 (protClass.isEmpty() || (protClass != baseProt)) ) 00093 return false; 00094 } 00095 if (baseHostWildCard) 00096 { 00097 if (!baseHost.isEmpty() && !url.host().endsWith(baseHost)) 00098 return false; 00099 } 00100 else 00101 { 00102 if (url.host() != baseHost) 00103 return false; 00104 } 00105 if (basePathWildCard) 00106 { 00107 if (!basePath.isEmpty() && !url.path().startsWith(basePath)) 00108 return false; 00109 } 00110 else 00111 { 00112 if (url.path() != basePath) 00113 return false; 00114 } 00115 return true; 00116 } 00117 00118 bool destMatch(const KUrl &url, const QString &protClass, const KUrl &base, const QString &baseClass) const 00119 { 00120 if (destProtEqual) 00121 { 00122 if ( (url.protocol() != base.protocol()) && 00123 (protClass.isEmpty() || baseClass.isEmpty() || protClass != baseClass) ) 00124 return false; 00125 } 00126 else if (destProtWildCard) 00127 { 00128 if ( !destProt.isEmpty() && !url.protocol().startsWith(destProt) && 00129 (protClass.isEmpty() || (protClass != destProt)) ) 00130 return false; 00131 } 00132 else 00133 { 00134 if ( (url.protocol() != destProt) && 00135 (protClass.isEmpty() || (protClass != destProt)) ) 00136 return false; 00137 } 00138 if (destHostWildCard) 00139 { 00140 if (!destHost.isEmpty() && !url.host().endsWith(destHost)) 00141 return false; 00142 } 00143 else if (destHostEqual) 00144 { 00145 if (url.host() != base.host()) 00146 return false; 00147 } 00148 else 00149 { 00150 if (url.host() != destHost) 00151 return false; 00152 } 00153 if (destPathWildCard) 00154 { 00155 if (!destPath.isEmpty() && !url.path().startsWith(destPath)) 00156 return false; 00157 } 00158 else 00159 { 00160 if (url.path() != destPath) 00161 return false; 00162 } 00163 return true; 00164 } 00165 00166 QByteArray action; 00167 QString baseProt; 00168 QString baseHost; 00169 QString basePath; 00170 QString destProt; 00171 QString destHost; 00172 QString destPath; 00173 bool baseProtWildCard : 1; 00174 bool baseHostWildCard : 1; 00175 bool basePathWildCard : 1; 00176 bool destProtWildCard : 1; 00177 bool destHostWildCard : 1; 00178 bool destPathWildCard : 1; 00179 bool destProtEqual : 1; 00180 bool destHostEqual : 1; 00181 bool permission; 00182 }; 00183 00184 class KAuthorizedPrivate { 00185 public: 00186 KAuthorizedPrivate() 00187 : actionRestrictions( false ), blockEverything(false),mutex(QMutex::Recursive) 00188 { 00189 Q_ASSERT_X(QCoreApplication::instance(),"KAuthorizedPrivate()","There has to be an existing QCoreApplication::instance() pointer"); 00190 00191 KSharedConfig::Ptr config = KGlobal::config(); 00192 00193 Q_ASSERT_X(config,"KAuthorizedPrivate()","There has to be an existing KGlobal::config() pointer"); 00194 if (!config) { 00195 blockEverything=true; 00196 return; 00197 } 00198 actionRestrictions = config->hasGroup("KDE Action Restrictions" ) && !kde_kiosk_exception; 00199 } 00200 00201 ~KAuthorizedPrivate() 00202 { 00203 } 00204 00205 bool actionRestrictions : 1; 00206 bool blockEverything : 1; 00207 QList<URLActionRule> urlActionRestrictions; 00208 QMutex mutex; 00209 }; 00210 00211 Q_GLOBAL_STATIC(KAuthorizedPrivate,authPrivate) 00212 #define MY_D KAuthorizedPrivate *d=authPrivate(); 00213 00214 00215 bool KAuthorized::authorize(const QString &genericAction) 00216 { 00217 MY_D 00218 if (d->blockEverything) return false; 00219 00220 if (!d->actionRestrictions) 00221 return true; 00222 00223 KConfigGroup cg(KGlobal::config(), "KDE Action Restrictions"); 00224 return cg.readEntry(genericAction, true); 00225 } 00226 00227 bool KAuthorized::authorizeKAction(const QString& action) 00228 { 00229 MY_D 00230 if (d->blockEverything) return false; 00231 if (!d->actionRestrictions || action.isEmpty()) 00232 return true; 00233 00234 return authorize(QLatin1String("action/") + action); 00235 } 00236 00237 bool KAuthorized::authorizeControlModule(const QString &menuId) 00238 { 00239 if (menuId.isEmpty() || kde_kiosk_exception) 00240 return true; 00241 KConfigGroup cg(KGlobal::config(), "KDE Control Module Restrictions"); 00242 return cg.readEntry(menuId, true); 00243 } 00244 00245 QStringList KAuthorized::authorizeControlModules(const QStringList &menuIds) 00246 { 00247 KConfigGroup cg(KGlobal::config(), "KDE Control Module Restrictions"); 00248 QStringList result; 00249 for(QStringList::ConstIterator it = menuIds.begin(); 00250 it != menuIds.end(); ++it) 00251 { 00252 if (cg.readEntry(*it, true)) 00253 result.append(*it); 00254 } 00255 return result; 00256 } 00257 00258 static void initUrlActionRestrictions() 00259 { 00260 MY_D 00261 const QString Any; 00262 00263 d->urlActionRestrictions.clear(); 00264 d->urlActionRestrictions.append( 00265 URLActionRule("open", Any, Any, Any, Any, Any, Any, true)); 00266 d->urlActionRestrictions.append( 00267 URLActionRule("list", Any, Any, Any, Any, Any, Any, true)); 00268 // TEST: 00269 // d->urlActionRestrictions.append( 00270 // URLActionRule("list", Any, Any, Any, Any, Any, Any, false)); 00271 // d->urlActionRestrictions.append( 00272 // URLActionRule("list", Any, Any, Any, "file", Any, QDir::homePath(), true)); 00273 d->urlActionRestrictions.append( 00274 URLActionRule("link", Any, Any, Any, QLatin1String(":internet"), Any, Any, true)); 00275 d->urlActionRestrictions.append( 00276 URLActionRule("redirect", Any, Any, Any, QLatin1String(":internet"), Any, Any, true)); 00277 00278 // We allow redirections to file: but not from internet protocols, redirecting to file: 00279 // is very popular among io-slaves and we don't want to break them 00280 d->urlActionRestrictions.append( 00281 URLActionRule("redirect", Any, Any, Any, QLatin1String("file"), Any, Any, true)); 00282 d->urlActionRestrictions.append( 00283 URLActionRule("redirect", QLatin1String(":internet"), Any, Any, QLatin1String("file"), Any, Any, false)); 00284 00285 // local protocols may redirect everywhere 00286 d->urlActionRestrictions.append( 00287 URLActionRule("redirect", QLatin1String(":local"), Any, Any, Any, Any, Any, true)); 00288 00289 // Anyone may redirect to about: 00290 d->urlActionRestrictions.append( 00291 URLActionRule("redirect", Any, Any, Any, QLatin1String("about"), Any, Any, true)); 00292 00293 // Anyone may redirect to itself, cq. within it's own group 00294 d->urlActionRestrictions.append( 00295 URLActionRule("redirect", Any, Any, Any, QLatin1String("="), Any, Any, true)); 00296 00297 d->urlActionRestrictions.append( 00298 URLActionRule("redirect", QLatin1String("about"), Any, Any, Any, Any, Any, true)); 00299 00300 00301 KConfigGroup cg(KGlobal::config(), "KDE URL Restrictions"); 00302 int count = cg.readEntry("rule_count", 0); 00303 QString keyFormat = QString::fromLatin1("rule_%1"); 00304 for(int i = 1; i <= count; i++) 00305 { 00306 QString key = keyFormat.arg(i); 00307 const QStringList rule = cg.readEntry(key, QStringList()); 00308 if (rule.count() != 8) 00309 continue; 00310 const QByteArray action = rule[0].toLatin1(); 00311 QString refProt = rule[1]; 00312 QString refHost = rule[2]; 00313 QString refPath = rule[3]; 00314 QString urlProt = rule[4]; 00315 QString urlHost = rule[5]; 00316 QString urlPath = rule[6]; 00317 bool bEnabled = (rule[7].toLower() == QLatin1String("true")); 00318 00319 if (refPath.startsWith(QLatin1String("$HOME"))) 00320 refPath.replace(0, 5, QDir::homePath()); 00321 else if (refPath.startsWith(QLatin1Char('~'))) 00322 refPath.replace(0, 1, QDir::homePath()); 00323 if (urlPath.startsWith(QLatin1String("$HOME"))) 00324 urlPath.replace(0, 5, QDir::homePath()); 00325 else if (urlPath.startsWith(QLatin1Char('~'))) 00326 urlPath.replace(0, 1, QDir::homePath()); 00327 00328 if (refPath.startsWith(QLatin1String("$TMP"))) 00329 refPath.replace(0, 4, KGlobal::dirs()->saveLocation("tmp")); 00330 if (urlPath.startsWith(QLatin1String("$TMP"))) 00331 urlPath.replace(0, 4, KGlobal::dirs()->saveLocation("tmp")); 00332 00333 d->urlActionRestrictions.append( 00334 URLActionRule( action, refProt, refHost, refPath, urlProt, urlHost, urlPath, bEnabled)); 00335 } 00336 } 00337 00338 void KAuthorized::allowUrlAction(const QString &action, const KUrl &_baseURL, const KUrl &_destURL) 00339 { 00340 MY_D 00341 QMutexLocker locker((&d->mutex)); 00342 if (authorizeUrlAction(action, _baseURL, _destURL)) 00343 return; 00344 00345 d->urlActionRestrictions.append( URLActionRule 00346 ( action.toLatin1(), _baseURL.protocol(), _baseURL.host(), _baseURL.path(KUrl::RemoveTrailingSlash), 00347 _destURL.protocol(), _destURL.host(), _destURL.path(KUrl::RemoveTrailingSlash), true)); 00348 } 00349 00350 bool KAuthorized::authorizeUrlAction(const QString &action, const KUrl &_baseURL, const KUrl &_destURL) 00351 { 00352 MY_D 00353 QMutexLocker locker(&(d->mutex)); 00354 if (d->blockEverything) return false; 00355 00356 if (_destURL.isEmpty()) 00357 return true; 00358 00359 bool result = false; 00360 if (d->urlActionRestrictions.isEmpty()) 00361 initUrlActionRestrictions(); 00362 00363 KUrl baseURL(_baseURL); 00364 baseURL.setPath(QDir::cleanPath(baseURL.path())); 00365 QString baseClass = KProtocolInfo::protocolClass(baseURL.protocol()); 00366 KUrl destURL(_destURL); 00367 destURL.setPath(QDir::cleanPath(destURL.path())); 00368 QString destClass = KProtocolInfo::protocolClass(destURL.protocol()); 00369 00370 foreach(const URLActionRule &rule, d->urlActionRestrictions) { 00371 if ((result != rule.permission) && // No need to check if it doesn't make a difference 00372 (action == QLatin1String(rule.action)) && 00373 rule.baseMatch(baseURL, baseClass) && 00374 rule.destMatch(destURL, destClass, baseURL, baseClass)) 00375 { 00376 result = rule.permission; 00377 } 00378 } 00379 return result; 00380 }
KDE 4.6 API Reference