File indexing completed on 2024-10-27 04:58:05

0001 // SPDX-FileCopyrightText: 2016 Sandro Knauß <knauss@kolabsystems.com>
0002 // SPDX-License-Identifier: LGPL-2.0-or-later
0003 
0004 #include <objecttreeparser.h>
0005 
0006 #include <gpgme.h>
0007 
0008 #include <QDebug>
0009 #include <QDir>
0010 #include <QProcess>
0011 #include <QTest>
0012 #include <QtGlobal>
0013 #include <qobjectdefs.h>
0014 
0015 QByteArray readMailFromFile(const QString &mailFile)
0016 {
0017     QFile file(QLatin1String(MAIL_DATA_DIR) + QLatin1Char('/') + mailFile);
0018     file.open(QIODevice::ReadOnly);
0019     Q_ASSERT(file.isOpen());
0020     return file.readAll();
0021 }
0022 
0023 void killAgent(const QString &dir)
0024 {
0025     QProcess proc;
0026     proc.setProgram(QStringLiteral("gpg-connect-agent"));
0027     QStringList arguments;
0028     arguments << QStringLiteral("-S ") << dir + QStringLiteral("/S.gpg-agent");
0029     proc.start();
0030     proc.waitForStarted();
0031     proc.write("KILLAGENT\n");
0032     proc.write("BYE\n");
0033     proc.closeWriteChannel();
0034     proc.waitForFinished();
0035 }
0036 
0037 class GpgErrorTest : public QObject
0038 {
0039     Q_OBJECT
0040 
0041 private Q_SLOTS:
0042 
0043     void testGpgConfiguredCorrectly()
0044     {
0045         setEnv("GNUPGHOME", GNUPGHOME);
0046 
0047         MimeTreeParser::ObjectTreeParser otp;
0048         otp.parseObjectTree(readMailFromFile(QStringLiteral("openpgp-inline-charset-encrypted.mbox")));
0049         otp.print();
0050         otp.decryptParts();
0051         otp.print();
0052         auto partList = otp.collectContentParts();
0053         QCOMPARE(partList.size(), 1);
0054         auto part = partList[0];
0055         QVERIFY(bool(part));
0056 
0057         QVERIFY(part->text().startsWith(QStringLiteral("asdasd")));
0058         QCOMPARE(part->encryptions().size(), 1);
0059         auto enc = part->encryptions()[0];
0060         QCOMPARE(enc->error(), MimeTreeParser::MessagePart::NoError);
0061         // QCOMPARE((int) enc->recipients().size(), 2);
0062     }
0063 
0064     void testNoGPGInstalled_data()
0065     {
0066         QTest::addColumn<QString>("mailFileName");
0067 
0068         QTest::newRow("openpgp-inline-charset-encrypted") << "openpgp-inline-charset-encrypted.mbox";
0069         QTest::newRow("openpgp-encrypted-attachment-and-non-encrypted-attachment") << "openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox";
0070         QTest::newRow("smime-encrypted") << "smime-encrypted.mbox";
0071     }
0072 
0073     void testNoGPGInstalled()
0074     {
0075         QFETCH(QString, mailFileName);
0076 
0077         setEnv("PATH", "/nonexististing");
0078         setGpgMEfname("/nonexisting/gpg", "");
0079 
0080         MimeTreeParser::ObjectTreeParser otp;
0081         otp.parseObjectTree(readMailFromFile(mailFileName));
0082         otp.print();
0083         otp.decryptParts();
0084         otp.print();
0085         auto partList = otp.collectContentParts();
0086         QCOMPARE(partList.size(), 1);
0087         auto part = partList[0].dynamicCast<MimeTreeParser::MessagePart>();
0088         QVERIFY(bool(part));
0089 
0090         QCOMPARE(part->encryptions().size(), 1);
0091         QVERIFY(part->text().isEmpty());
0092         auto enc = part->encryptions()[0];
0093         QCOMPARE(enc->error(), MimeTreeParser::MessagePart::NoKeyError);
0094     }
0095 
0096     void testGpgIncorrectGPGHOME_data()
0097     {
0098         QTest::addColumn<QString>("mailFileName");
0099 
0100         QTest::newRow("openpgp-inline-charset-encrypted") << "openpgp-inline-charset-encrypted.mbox";
0101         QTest::newRow("openpgp-encrypted-attachment-and-non-encrypted-attachment") << "openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox";
0102         QTest::newRow("smime-encrypted") << "smime-encrypted.mbox";
0103     }
0104 
0105     void testGpgIncorrectGPGHOME()
0106     {
0107         QFETCH(QString, mailFileName);
0108         setEnv("GNUPGHOME", QByteArray(GNUPGHOME) + QByteArray("noexist"));
0109 
0110         MimeTreeParser::ObjectTreeParser otp;
0111         otp.parseObjectTree(readMailFromFile(mailFileName));
0112         otp.print();
0113         otp.decryptParts();
0114         otp.print();
0115         auto partList = otp.collectContentParts();
0116         QCOMPARE(partList.size(), 1);
0117         auto part = partList[0].dynamicCast<MimeTreeParser::MessagePart>();
0118         QVERIFY(bool(part));
0119 
0120         QCOMPARE(part->encryptions().size(), 1);
0121         QCOMPARE(part->signatures().size(), 0);
0122         QVERIFY(part->text().isEmpty());
0123         auto enc = part->encryptions()[0];
0124         QCOMPARE(enc->error(), MimeTreeParser::MessagePart::NoKeyError);
0125         // QCOMPARE((int) enc->recipients().size(), 2);
0126     }
0127 
0128 public Q_SLOTS:
0129     void init()
0130     {
0131         mResetGpgmeEngine = false;
0132         mModifiedEnv.clear();
0133         {
0134             gpgme_check_version(nullptr);
0135             gpgme_ctx_t ctx = nullptr;
0136             gpgme_new(&ctx);
0137             gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP);
0138             gpgme_engine_info_t info = gpgme_ctx_get_engine_info(ctx);
0139             mGpgmeEngine_fname = info->file_name;
0140             gpgme_release(ctx);
0141         }
0142         mEnv = QProcessEnvironment::systemEnvironment();
0143         unsetEnv("GNUPGHOME");
0144     }
0145 
0146     void cleanup()
0147     {
0148         QCoreApplication::sendPostedEvents();
0149 
0150         const QString &gnupghome = QString::fromUtf8(qgetenv("GNUPGHOME"));
0151         if (!gnupghome.isEmpty()) {
0152             killAgent(gnupghome);
0153         }
0154 
0155         resetGpgMfname();
0156         resetEnv();
0157     }
0158 
0159 private:
0160     void unsetEnv(const QByteArray &name)
0161     {
0162         mModifiedEnv << name;
0163         qunsetenv(name.data());
0164     }
0165 
0166     void setEnv(const QByteArray &name, const QByteArray &value)
0167     {
0168         mModifiedEnv << name;
0169         qputenv(name.data(), value);
0170     }
0171 
0172     void resetEnv()
0173     {
0174         for (const auto &i : std::as_const(mModifiedEnv)) {
0175             const auto env = i.data();
0176             if (mEnv.contains(QString::fromUtf8(i))) {
0177                 qputenv(env, mEnv.value(QString::fromUtf8(i)).toUtf8());
0178             } else {
0179                 qunsetenv(env);
0180             }
0181         }
0182     }
0183 
0184     void resetGpgMfname()
0185     {
0186         if (mResetGpgmeEngine) {
0187             gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP, mGpgmeEngine_fname.data(), nullptr);
0188         }
0189     }
0190 
0191     void setGpgMEfname(const QByteArray &fname, const QByteArray &homedir)
0192     {
0193         mResetGpgmeEngine = true;
0194         gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP, fname.data(), homedir.data());
0195     }
0196 
0197     QSet<QByteArray> mModifiedEnv;
0198     QProcessEnvironment mEnv;
0199     bool mResetGpgmeEngine;
0200     QByteArray mGpgmeEngine_fname;
0201 };
0202 
0203 QTEST_GUILESS_MAIN(GpgErrorTest)
0204 #include "gpgerrortest.moc"