File indexing completed on 2024-05-05 17:56:55

0001 /*
0002     SPDX-FileCopyrightText: 2000 Shie Erlich <krusader@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2000 Rafi Yanai <krusader@users.sourceforge.net>
0004     SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #include "krpermhandler.h"
0010 
0011 // QtCore
0012 #include <QLocale>
0013 
0014 #include <grp.h>
0015 #include <pwd.h>
0016 #include <sys/stat.h>
0017 
0018 QSet<int> KrPermHandler::currentGroups;
0019 QHash<int, QString> KrPermHandler::uidCache;
0020 QHash<int, QString> KrPermHandler::gidCache;
0021 
0022 QString KrPermHandler::mode2QString(mode_t m)
0023 {
0024     char perm[11];
0025     for (int i = 0; i != 10; i++)
0026         perm[i] = '-';
0027     perm[10] = 0;
0028 
0029     if (S_ISLNK(m))
0030         perm[0] = 'l'; // check for symLink
0031     if (S_ISDIR(m))
0032         perm[0] = 'd'; // check for directory
0033 
0034     // ReadUser = 0400, WriteUser = 0200, ExeUser = 0100, Suid = 04000
0035     if (m & 0400)
0036         perm[1] = 'r';
0037     if (m & 0200)
0038         perm[2] = 'w';
0039     if (m & 0100)
0040         perm[3] = 'x';
0041     if (m & 04000)
0042         perm[3] = 's';
0043     // ReadGroup = 0040, WriteGroup = 0020, ExeGroup = 0010, Gid = 02000
0044     if (m & 0040)
0045         perm[4] = 'r';
0046     if (m & 0020)
0047         perm[5] = 'w';
0048     if (m & 0010)
0049         perm[6] = 'x';
0050     if (m & 02000)
0051         perm[6] = 's';
0052     // ReadOther = 0004, WriteOther = 0002, ExeOther = 0001, Sticky = 01000
0053     if (m & 0004)
0054         perm[7] = 'r';
0055     if (m & 0002)
0056         perm[8] = 'w';
0057     if (m & 0001)
0058         perm[9] = 'x';
0059     if (m & 01000)
0060         perm[9] = 't';
0061 
0062     return QString(perm);
0063 }
0064 
0065 void KrPermHandler::init()
0066 {
0067     // set the umask to 022
0068     // umask( 022 );
0069 
0070     // 200 groups should be enough
0071     gid_t groupList[200];
0072     int groupNo = getgroups(200, groupList);
0073 
0074 // In kdewin32 implementation as of 4.1.2, getpwent always returns the same struct
0075 #ifndef Q_OS_WIN
0076     // fill the UID cache
0077     struct passwd *pass;
0078     while ((pass = getpwent()) != nullptr) {
0079         uidCache.insert(pass->pw_uid, pass->pw_name);
0080     }
0081     delete pass;
0082     endpwent();
0083 
0084     // fill the GID cache
0085     struct group *gr;
0086     while ((gr = getgrent()) != nullptr) {
0087         gidCache.insert(gr->gr_gid, QString(gr->gr_name));
0088     }
0089     delete gr;
0090     endgrent();
0091 #endif
0092 
0093     // fill the groups for the current user
0094     for (int i = 0; i < groupNo; ++i) {
0095         currentGroups.insert(groupList[i]);
0096     }
0097     // just to be sure add the effective gid...
0098     currentGroups.insert(getegid());
0099 }
0100 
0101 char KrPermHandler::readable(const QString &perm, gid_t gid, uid_t uid)
0102 {
0103     return getLocalPermission(perm, gid, uid, 0);
0104 }
0105 
0106 char KrPermHandler::writeable(const QString &perm, gid_t gid, uid_t uid)
0107 {
0108     return getLocalPermission(perm, gid, uid, 1);
0109 }
0110 
0111 char KrPermHandler::executable(const QString &perm, gid_t gid, uid_t uid)
0112 {
0113     return getLocalPermission(perm, gid, uid, 2, true);
0114 }
0115 
0116 char KrPermHandler::getLocalPermission(const QString &perm, gid_t gid, uid_t uid, int permOffset, bool ignoreRoot)
0117 {
0118     // root override
0119     if (!ignoreRoot && getuid() == 0)
0120         return ALLOWED_PERM;
0121     // first check other permissions.
0122     if (perm[7 + permOffset] != '-')
0123         return ALLOWED_PERM;
0124     // now check group permission
0125     if ((perm[4 + permOffset] != '-') && currentGroups.contains(gid))
0126         return ALLOWED_PERM;
0127     // the last chance - user permissions
0128     if ((perm[1 + permOffset] != '-') && (uid == getuid()))
0129         return ALLOWED_PERM;
0130     // sorry !
0131     return NO_PERM;
0132 }
0133 
0134 char KrPermHandler::ftpReadable(const QString &fileOwner, const QString &userName, const QString &perm)
0135 {
0136     return getFtpPermission(fileOwner, userName, perm, 0);
0137 }
0138 
0139 char KrPermHandler::ftpWriteable(const QString &fileOwner, const QString &userName, const QString &perm)
0140 {
0141     return getFtpPermission(fileOwner, userName, perm, 1);
0142 }
0143 
0144 char KrPermHandler::ftpExecutable(const QString &fileOwner, const QString &userName, const QString &perm)
0145 {
0146     return getFtpPermission(fileOwner, userName, perm, 2);
0147 }
0148 
0149 char KrPermHandler::getFtpPermission(const QString &fileOwner, const QString &userName, const QString &perm, int permOffset)
0150 {
0151     // first check other permissions.
0152     if (perm[7 + permOffset] != '-')
0153         return ALLOWED_PERM;
0154     // can't check group permission !
0155     // so check the user permissions
0156     if ((perm[1 + permOffset] != '-') && (fileOwner == userName))
0157         return ALLOWED_PERM;
0158     if ((perm[1 + permOffset] != '-') && (userName.isEmpty()))
0159         return UNKNOWN_PERM;
0160     if (perm[4 + permOffset] != '-')
0161         return UNKNOWN_PERM;
0162     return NO_PERM;
0163 }
0164 
0165 QString KrPermHandler::parseSize(KIO::filesize_t val)
0166 {
0167     return QLocale().toString(val);
0168 }
0169 
0170 QString KrPermHandler::gid2group(gid_t groupId)
0171 {
0172     return gidCache.value(groupId, QStringLiteral("???"));
0173 }
0174 
0175 QString KrPermHandler::uid2user(uid_t userId)
0176 {
0177     return uidCache.value(userId, QStringLiteral("???"));
0178 }