File indexing completed on 2024-05-05 16:08:27

0001 /* This file is part of the KDE project
0002    Copyright (c) 2001 David Faure <faure@kde.org>
0003    Copyright (c) 2001 Laurent Montel <lmontel@mandrakesoft.com>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License version 2 as published by the Free Software Foundation.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017    Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include "kfileshare.h"
0021 #include "kfileshare_p.h"
0022 #include <QDir>
0023 #include <QFile>
0024 #include <QProcess>
0025 #include <QDebug>
0026 #include <klocalizedstring.h>
0027 #include <qstandardpaths.h>
0028 #include <kdirwatch.h>
0029 #include <stdio.h>
0030 #include <stdlib.h>
0031 #include <errno.h>
0032 #include <kconfig.h>
0033 #include <kconfiggroup.h>
0034 #include <kuser.h>
0035 
0036 static KFileShare::Authorization s_authorization = KFileShare::NotInitialized;
0037 Q_GLOBAL_STATIC(QStringList, s_shareList)
0038 static KFileShare::ShareMode s_shareMode;
0039 static bool s_sambaEnabled;
0040 static bool s_nfsEnabled;
0041 static bool s_restricted;
0042 static QString s_fileShareGroup;
0043 static bool s_sharingEnabled;
0044 
0045 #define FILESHARECONF "/etc/security/fileshare.conf"
0046 
0047 static QString findExe(const char *exeName)
0048 {
0049     // Normally fileshareset and filesharelist are installed in libexec/kf5;
0050     // allow distributions to move it somewhere else in the PATH or in /usr/sbin.
0051     QString exe = QStandardPaths::findExecutable(exeName);
0052     if (exe.isEmpty()) {
0053         exe = QStandardPaths::findExecutable(exeName, QStringList() << "/usr/sbin");
0054     }
0055     if (exe.isEmpty()) {
0056         qWarning() << exeName << "not found in PATH nor in /usr/sbin";
0057     }
0058     return exe;
0059 }
0060 
0061 KFileSharePrivate::KFileSharePrivate()
0062 {
0063     KDirWatch::self()->addFile(FILESHARECONF);
0064     connect(KDirWatch::self(), SIGNAL(dirty(QString)), this,
0065             SLOT(slotFileChange(QString)));
0066     connect(KDirWatch::self(), SIGNAL(created(QString)), this,
0067             SLOT(slotFileChange(QString)));
0068     connect(KDirWatch::self(), SIGNAL(deleted(QString)), this,
0069             SLOT(slotFileChange(QString)));
0070 }
0071 
0072 KFileSharePrivate::~KFileSharePrivate()
0073 {
0074     KDirWatch::self()->removeFile(FILESHARECONF);
0075 }
0076 
0077 Q_GLOBAL_STATIC(KFileSharePrivate, _self)
0078 
0079 KFileSharePrivate *KFileSharePrivate::self()
0080 {
0081     return _self();
0082 }
0083 
0084 void KFileSharePrivate::slotFileChange(const QString &file)
0085 {
0086     if (file == FILESHARECONF) {
0087         KFileShare::readConfig();
0088         KFileShare::readShareList();
0089     }
0090 }
0091 
0092 KFileShare::ShareMode readEntry(const KConfigGroup &cg, const char *key,
0093                                 const KFileShare::ShareMode &aDefault)
0094 {
0095     const QByteArray data = cg.readEntry(key, QByteArray());
0096 
0097     if (!data.isEmpty()) {
0098         if (data.toLower() == "simple") {
0099             return KFileShare::Simple;
0100         } else if (data.toLower() == "advanced") {
0101             return KFileShare::Advanced;
0102         }
0103     }
0104 
0105     return aDefault;
0106 }
0107 
0108 void KFileShare::readConfig() // static
0109 {
0110     // Create KFileSharePrivate instance
0111     KFileSharePrivate::self();
0112     KConfig config(QLatin1String(FILESHARECONF));
0113     KConfigGroup group(&config, QString());
0114 
0115     s_sharingEnabled = group.readEntry("FILESHARING", true);
0116     s_restricted = group.readEntry("RESTRICT", true);
0117     s_fileShareGroup = group.readEntry("FILESHAREGROUP", "fileshare");
0118 
0119     if (!s_sharingEnabled) {
0120         s_authorization = UserNotAllowed;
0121     } else if (!s_restricted) {
0122         s_authorization = Authorized;
0123     } else {
0124         // check if current user is in fileshare group
0125         KUserGroup shareGroup(s_fileShareGroup);
0126         if (shareGroup.users().contains(KUser())) {
0127             s_authorization = Authorized;
0128         } else {
0129             s_authorization = UserNotAllowed;
0130         }
0131     }
0132 
0133     s_shareMode = readEntry(group, "SHARINGMODE", Simple);
0134 
0135     s_sambaEnabled = group.readEntry("SAMBA", true);
0136     s_nfsEnabled = group.readEntry("NFS", true);
0137 }
0138 
0139 KFileShare::ShareMode KFileShare::shareMode()
0140 {
0141     if (s_authorization == NotInitialized) {
0142         readConfig();
0143     }
0144 
0145     return s_shareMode;
0146 }
0147 
0148 bool KFileShare::sharingEnabled()
0149 {
0150     if (s_authorization == NotInitialized) {
0151         readConfig();
0152     }
0153 
0154     return s_sharingEnabled;
0155 }
0156 
0157 bool KFileShare::isRestricted()
0158 {
0159     if (s_authorization == NotInitialized) {
0160         readConfig();
0161     }
0162 
0163     return s_restricted;
0164 }
0165 
0166 QString KFileShare::fileShareGroup()
0167 {
0168     if (s_authorization == NotInitialized) {
0169         readConfig();
0170     }
0171 
0172     return s_fileShareGroup;
0173 }
0174 
0175 bool KFileShare::sambaEnabled()
0176 {
0177     if (s_authorization == NotInitialized) {
0178         readConfig();
0179     }
0180 
0181     return s_sambaEnabled;
0182 }
0183 
0184 bool KFileShare::nfsEnabled()
0185 {
0186     if (s_authorization == NotInitialized) {
0187         readConfig();
0188     }
0189 
0190     return s_nfsEnabled;
0191 }
0192 
0193 void KFileShare::readShareList()
0194 {
0195     KFileSharePrivate::self();
0196     s_shareList()->clear();
0197 
0198     QString exe = ::findExe("filesharelist");
0199     if (exe.isEmpty()) {
0200         s_authorization = ErrorNotFound;
0201         return;
0202     }
0203     QProcess proc;
0204     proc.start(exe, QStringList());
0205     if (!proc.waitForFinished()) {
0206         qWarning() << "Can't run" << exe;
0207         s_authorization = ErrorNotFound;
0208         return;
0209     }
0210 
0211     // Reading code shamelessly stolen from khostname.cpp ;)
0212     while (!proc.atEnd()) {
0213         QString line = proc.readLine().trimmed();
0214         int length = line.length();
0215         if (length > 0) {
0216             if (line[length - 1] != '/') {
0217                 line += '/';
0218             }
0219             s_shareList()->append(line);
0220             //qDebug() << "Shared dir:" << line;
0221         }
0222     }
0223 }
0224 
0225 bool KFileShare::isDirectoryShared(const QString &_path)
0226 {
0227     if (! s_shareList.exists())
0228         readShareList();
0229 
0230     QString path(_path);
0231     if (path[path.length() - 1] != '/') {
0232         path += '/';
0233     }
0234     return s_shareList()->contains(path);
0235 }
0236 
0237 KFileShare::Authorization KFileShare::authorization()
0238 {
0239     // The app should do this on startup, but if it doesn't, let's do here.
0240     if (s_authorization == NotInitialized) {
0241         readConfig();
0242     }
0243     return s_authorization;
0244 }
0245 
0246 bool KFileShare::setShared(const QString &path, bool shared)
0247 {
0248     if (! KFileShare::sharingEnabled() ||
0249             KFileShare::shareMode() == Advanced) {
0250         return false;
0251     }
0252 
0253     //qDebug() << path << "," << shared;
0254     QString exe = ::findExe("fileshareset");
0255     if (exe.isEmpty()) {
0256         return false;
0257     }
0258 
0259     QStringList args;
0260     if (shared) {
0261         args << "--add";
0262     } else {
0263         args << "--remove";
0264     }
0265     args << path;
0266     int ec = QProcess::execute(exe, args);   // should be ok, the perl script terminates fast
0267     //qDebug() << "exitCode=" << ec;
0268     bool ok = !ec;
0269     switch (ec) {
0270     case 1:
0271         // User is not authorized
0272         break;
0273     case 3:
0274         // Called script with --add, but path was already shared before.
0275         // Result is nevertheless what the client wanted, so
0276         // this is alright.
0277         ok = true;
0278         break;
0279     case 4:
0280         // Invalid mount point
0281         break;
0282     case 5:
0283         // Called script with --remove, but path was not shared before.
0284         // Result is nevertheless what the client wanted, so
0285         // this is alright.
0286         ok = true;
0287         break;
0288     case 6:
0289         // There is no export method
0290         break;
0291     case 7:
0292         // file sharing is disabled
0293         break;
0294     case 8:
0295         // advanced sharing is enabled
0296         break;
0297     case 255:
0298         // Abitrary error
0299         break;
0300     }
0301 
0302     return ok;
0303 }
0304 
0305 #include "moc_kfileshare_p.cpp"
0306