File indexing completed on 2024-04-14 14:23:58

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2005 Till Adam <adam@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "kacltest.h"
0009 
0010 #include <QTest>
0011 #include <config-kiocore.h>
0012 
0013 #if HAVE_POSIX_ACL
0014 #include <grp.h> // getgrnam()
0015 #include <sys/types.h>
0016 #endif
0017 
0018 // The code comes partly from kdebase/kioslave/trash/testtrash.cpp
0019 
0020 QTEST_MAIN(KACLTest)
0021 
0022 KACLTest::KACLTest()
0023 {
0024 }
0025 
0026 void KACLTest::initTestCase()
0027 {
0028 #if !HAVE_POSIX_ACL
0029     QSKIP("ACL support not compiled");
0030 #endif
0031 #ifdef Q_OS_FREEBSD
0032     QSKIP("The test is not adapted for FreeBSD yet");
0033 #endif
0034 
0035     m_testACL = QStringLiteral(
0036         "user::rw-\n"
0037         "user:bin:rwx\n"
0038         "group::rw-\n"
0039         "mask::rwx\n"
0040         "other::r--\n");
0041 
0042     m_acl = KACL(m_testACL);
0043 
0044     // setACL call acl_from_text(), which seems to order the groups in the resulting ACL
0045     // according to group numeric Id, in ascending order. Find which group comes first
0046     // so that the tests pass regardless of which distro they're run on.
0047     auto *grpStruct = getgrnam("audio");
0048     m_audioGid = static_cast<int>(grpStruct->gr_gid);
0049 
0050     grpStruct = getgrnam("users");
0051     m_usersGid = static_cast<int>(grpStruct->gr_gid);
0052 
0053     QLatin1String orderedGroups;
0054     if (m_audioGid < m_usersGid) {
0055         orderedGroups = QLatin1String{
0056             "group:audio:--x\n"
0057             "group:users:r--\n"};
0058     } else {
0059         orderedGroups = QLatin1String{
0060             "group:users:r--\n"
0061             "group:audio:--x\n"};
0062     }
0063 
0064     m_testACL2 =
0065         QLatin1String{
0066             "user::rwx\n"
0067             "user:bin:rwx\n"
0068             "group::rw-\n"}
0069         + orderedGroups
0070         + QLatin1String{
0071             "mask::r-x\n"
0072             "other::r--\n"};
0073 
0074     m_testACLEffective =
0075         QLatin1String{
0076             "user::rwx\n"
0077             "user:bin:rwx    #effective:r-x\n"
0078             "group::rw-      #effective:r--\n"}
0079         + orderedGroups
0080         + QLatin1String{
0081             "mask::r-x\n"
0082             "other::r--\n"};
0083 
0084     QVERIFY(m_acl2.setACL(m_testACL2));
0085 }
0086 
0087 void KACLTest::testAsString()
0088 {
0089     QCOMPARE(m_acl.asString(), m_testACL);
0090 }
0091 
0092 void KACLTest::testSetACL()
0093 {
0094     QCOMPARE(m_acl2.asString().simplified(), m_testACLEffective.simplified());
0095 }
0096 
0097 void KACLTest::testGetOwnerPermissions()
0098 {
0099     QCOMPARE(int(m_acl.ownerPermissions()), 6);
0100 }
0101 
0102 void KACLTest::testGetOwningGroupPermissions()
0103 {
0104     QCOMPARE(int(m_acl.owningGroupPermissions()), 6);
0105 }
0106 
0107 void KACLTest::testGetOthersPermissions()
0108 {
0109     QCOMPARE(int(m_acl.othersPermissions()), 4);
0110 }
0111 
0112 void KACLTest::testGetMaskPermissions()
0113 {
0114     bool exists = false;
0115     int mask = m_acl.maskPermissions(exists);
0116     QVERIFY(exists);
0117     QCOMPARE(mask, 7);
0118 }
0119 
0120 void KACLTest::testGetAllUserPermissions()
0121 {
0122     ACLUserPermissionsList list = m_acl.allUserPermissions();
0123     ACLUserPermissionsConstIterator it = list.constBegin();
0124     QString name;
0125     int permissions = 0;
0126     int count = 0;
0127     while (it != list.constEnd()) {
0128         name = (*it).first;
0129         permissions = (*it).second;
0130         ++it;
0131         ++count;
0132     }
0133     QCOMPARE(count, 1);
0134     QCOMPARE(name, QStringLiteral("bin"));
0135     QCOMPARE(permissions, 7);
0136 }
0137 
0138 void KACLTest::testGetAllGroupsPermissions()
0139 {
0140     const ACLGroupPermissionsList list = m_acl2.allGroupPermissions();
0141     QCOMPARE(list.size(), 2);
0142 
0143     const bool isAudioFirst = m_audioGid < m_usersGid;
0144 
0145     QString name;
0146     int permissions;
0147 
0148     const auto acl1 = list.at(0);
0149     name = acl1.first;
0150     permissions = acl1.second;
0151     if (isAudioFirst) {
0152         QCOMPARE(name, QStringLiteral("audio"));
0153         QCOMPARE(permissions, 1);
0154     } else {
0155         QCOMPARE(name, QStringLiteral("users"));
0156         QCOMPARE(permissions, 4);
0157     }
0158 
0159     const auto acl2 = list.at(1);
0160     name = acl2.first;
0161     permissions = acl2.second;
0162     if (isAudioFirst) {
0163         QCOMPARE(name, QStringLiteral("users"));
0164         QCOMPARE(permissions, 4);
0165     } else {
0166         QCOMPARE(name, QStringLiteral("audio"));
0167         QCOMPARE(permissions, 1);
0168     }
0169 }
0170 
0171 void KACLTest::testIsExtended()
0172 {
0173     KACL dukeOfMonmoth(m_testACL);
0174     QVERIFY(dukeOfMonmoth.isExtended());
0175     KACL earlOfUpnor(QStringLiteral("user::r--\ngroup::r--\nother::r--\n"));
0176     QVERIFY(!earlOfUpnor.isExtended());
0177 }
0178 
0179 void KACLTest::testOperators()
0180 {
0181     KACL dukeOfMonmoth(m_testACL);
0182     KACL JamesScott(m_testACL);
0183     KACL earlOfUpnor(m_testACL2);
0184     QVERIFY(!(dukeOfMonmoth == earlOfUpnor));
0185     QVERIFY(dukeOfMonmoth != earlOfUpnor);
0186     QVERIFY(dukeOfMonmoth != earlOfUpnor);
0187     QVERIFY(!(dukeOfMonmoth != JamesScott));
0188 }
0189 
0190 void KACLTest::testSettingBasic()
0191 {
0192     KACL CharlesII(m_testACL);
0193     CharlesII.setOwnerPermissions(7); // clearly
0194     CharlesII.setOwningGroupPermissions(0);
0195     CharlesII.setOthersPermissions(0);
0196     QCOMPARE(int(CharlesII.ownerPermissions()), 7);
0197     QCOMPARE(int(CharlesII.owningGroupPermissions()), 0);
0198     QCOMPARE(int(CharlesII.othersPermissions()), 0);
0199 }
0200 
0201 void KACLTest::testSettingExtended()
0202 {
0203     KACL CharlesII(m_testACL);
0204     CharlesII.setMaskPermissions(7); // clearly
0205     bool dummy = false;
0206     QCOMPARE(int(CharlesII.maskPermissions(dummy)), 7);
0207 
0208     const QString expected(QStringLiteral("user::rw-\nuser:root:rwx\nuser:bin:r--\ngroup::rw-\nmask::rwx\nother::r--\n"));
0209 
0210     ACLUserPermissionsList users;
0211     ACLUserPermissions user = qMakePair(QStringLiteral("root"), (unsigned short)7);
0212     users.append(user);
0213     user = qMakePair(QStringLiteral("bin"), (unsigned short)4);
0214     users.append(user);
0215     CharlesII.setAllUserPermissions(users);
0216     QCOMPARE(CharlesII.asString(), expected);
0217 
0218     CharlesII.setACL(m_testACL); // reset
0219     // it already has an entry for bin, let's change it
0220     CharlesII.setNamedUserPermissions(QStringLiteral("bin"), 4);
0221     CharlesII.setNamedUserPermissions(QStringLiteral("root"), 7);
0222     QCOMPARE(CharlesII.asString(), expected);
0223 
0224     // groups, all and named
0225 
0226     QLatin1String orderedGroups;
0227     if (m_audioGid < m_usersGid) {
0228         orderedGroups = QLatin1String{
0229             "group:audio:-wx\n"
0230             "group:users:r--\n"};
0231     } else {
0232         orderedGroups = QLatin1String{
0233             "group:users:r--\n"
0234             "group:audio:-wx\n"};
0235     }
0236 
0237     const QString expected2 =
0238         QLatin1String{
0239             "user::rw-\n"
0240             "user:bin:rwx\n"
0241             "group::rw-\n"}
0242         + orderedGroups
0243         + QLatin1String{
0244             "mask::rwx\n"
0245             "other::r--\n"};
0246 
0247     CharlesII.setACL(m_testACL); // reset
0248     ACLGroupPermissionsList groups;
0249     ACLGroupPermissions group = qMakePair(QStringLiteral("audio"), (unsigned short)3);
0250     groups.append(group);
0251     group = qMakePair(QStringLiteral("users"), (unsigned short)4);
0252     groups.append(group);
0253     CharlesII.setAllGroupPermissions(groups);
0254     QCOMPARE(CharlesII.asString(), expected2);
0255 
0256     CharlesII.setACL(m_testACL); // reset
0257     CharlesII.setNamedGroupPermissions(QStringLiteral("audio"), 3);
0258     CharlesII.setNamedGroupPermissions(QStringLiteral("users"), 4);
0259     QCOMPARE(CharlesII.asString(), expected2);
0260 }
0261 
0262 void KACLTest::testSettingErrorHandling()
0263 {
0264     KACL foo(m_testACL);
0265     bool v = foo.setNamedGroupPermissions(QStringLiteral("audio"), 7); // existing group
0266     QVERIFY(v);
0267     v = foo.setNamedGroupPermissions(QStringLiteral("jongel"), 7); // non-existing group
0268     QVERIFY(!v);
0269 
0270     v = foo.setNamedUserPermissions(QStringLiteral("bin"), 7); // existing user
0271     QVERIFY(v);
0272     v = foo.setNamedUserPermissions(QStringLiteral("jongel"), 7); // non-existing user
0273     QVERIFY(!v);
0274 }
0275 
0276 void KACLTest::testNewMask()
0277 {
0278     KACL CharlesII(QStringLiteral("user::rw-\ngroup::rw-\nother::rw\n"));
0279     bool dummy = false;
0280     CharlesII.maskPermissions(dummy);
0281     QVERIFY(!dummy);
0282 
0283     CharlesII.setMaskPermissions(6);
0284     QCOMPARE(int(CharlesII.maskPermissions(dummy)), 6);
0285     QVERIFY(dummy); // mask exists now
0286 }
0287 
0288 #include "moc_kacltest.cpp"