File indexing completed on 2024-06-23 05:20:27

0001 /*
0002     Copyright (c) 2016 Sandro Knauß <knauss@kolabsystems.com>
0003 
0004     This library is free software; you can redistribute it and/or modify it
0005     under the terms of the GNU Library General Public License as published by
0006     the Free Software Foundation; either version 2 of the License, or (at your
0007     option) any later version.
0008 
0009     This library is distributed in the hope that it will be useful, but WITHOUT
0010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
0012     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 the
0016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0017     02110-1301, USA.
0018 */
0019 
0020 #include <objecttreeparser.h>
0021 
0022 #include <gpgme.h>
0023 
0024 #include <QDebug>
0025 #include <QDir>
0026 #include <QProcess>
0027 #include <QTest>
0028 #include <QtGlobal>
0029 
0030 QByteArray readMailFromFile(const QString &mailFile)
0031 {
0032     QFile file(QLatin1String(MAIL_DATA_DIR) + QLatin1Char('/') + mailFile);
0033     file.open(QIODevice::ReadOnly);
0034     Q_ASSERT(file.isOpen());
0035     return file.readAll();
0036 }
0037 
0038 void killAgent(const QString& dir)
0039 {
0040     QProcess proc;
0041     proc.setProgram(QStringLiteral("gpg-connect-agent"));
0042     QStringList arguments;
0043     arguments << "-S " << dir + "/S.gpg-agent";
0044     proc.start();
0045     proc.waitForStarted();
0046     proc.write("KILLAGENT\n");
0047     proc.write("BYE\n");
0048     proc.closeWriteChannel();
0049     proc.waitForFinished();
0050 }
0051 
0052 class GpgErrorTest : public QObject
0053 {
0054     Q_OBJECT
0055 
0056 private slots:
0057 
0058     void testGpgConfiguredCorrectly()
0059     {
0060         setEnv("GNUPGHOME", GNUPGHOME);
0061 
0062         MimeTreeParser::ObjectTreeParser otp;
0063         otp.parseObjectTree(readMailFromFile("openpgp-inline-charset-encrypted.mbox"));
0064         otp.print();
0065         otp.decryptParts();
0066         otp.print();
0067         auto partList = otp.collectContentParts();
0068         QCOMPARE(partList.size(), 1);
0069         auto part = partList[0];
0070         QVERIFY(bool(part));
0071 
0072         QVERIFY(part->text().startsWith("asdasd"));
0073         QCOMPARE(part->encryptions().size(), 1);
0074         auto enc = part->encryptions()[0];
0075         QCOMPARE(enc->error(),  MimeTreeParser::MessagePart::NoError);
0076         // QCOMPARE((int) enc->recipients().size(), 2);
0077     }
0078 
0079     void testNoGPGInstalled_data()
0080     {
0081         QTest::addColumn<QString>("mailFileName");
0082 
0083         QTest::newRow("openpgp-inline-charset-encrypted") << "openpgp-inline-charset-encrypted.mbox";
0084         QTest::newRow("openpgp-encrypted-attachment-and-non-encrypted-attachment") << "openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox";
0085         QTest::newRow("smime-encrypted") << "smime-encrypted.mbox";
0086     }
0087 
0088     void testNoGPGInstalled()
0089     {
0090         QFETCH(QString, mailFileName);
0091 
0092         setEnv("PATH", "/nonexististing");
0093         setGpgMEfname("/nonexisting/gpg", "");
0094 
0095         MimeTreeParser::ObjectTreeParser otp;
0096         otp.parseObjectTree(readMailFromFile(mailFileName));
0097         otp.print();
0098         otp.decryptParts();
0099         otp.print();
0100         auto partList = otp.collectContentParts();
0101         QCOMPARE(partList.size(), 1);
0102         auto part = partList[0].dynamicCast<MimeTreeParser::MessagePart>();
0103         QVERIFY(bool(part));
0104 
0105         QCOMPARE(part->encryptions().size(), 1);
0106         QVERIFY(part->text().isEmpty());
0107         auto enc = part->encryptions()[0];
0108         QCOMPARE(enc->error(), MimeTreeParser::MessagePart::NoKeyError);
0109     }
0110 
0111     void testGpgIncorrectGPGHOME_data()
0112     {
0113         QTest::addColumn<QString>("mailFileName");
0114 
0115         QTest::newRow("openpgp-inline-charset-encrypted") << "openpgp-inline-charset-encrypted.mbox";
0116         QTest::newRow("openpgp-encrypted-attachment-and-non-encrypted-attachment") << "openpgp-encrypted-attachment-and-non-encrypted-attachment.mbox";
0117         QTest::newRow("smime-encrypted") << "smime-encrypted.mbox";
0118     }
0119 
0120     void testGpgIncorrectGPGHOME()
0121     {
0122         QFETCH(QString, mailFileName);
0123         setEnv("GNUPGHOME", QByteArray(GNUPGHOME) + QByteArray("noexist"));
0124 
0125         MimeTreeParser::ObjectTreeParser otp;
0126         otp.parseObjectTree(readMailFromFile(mailFileName));
0127         otp.print();
0128         otp.decryptParts();
0129         otp.print();
0130         auto partList = otp.collectContentParts();
0131         QCOMPARE(partList.size(), 1);
0132         auto part = partList[0].dynamicCast<MimeTreeParser::MessagePart>();
0133         QVERIFY(bool(part));
0134 
0135         QCOMPARE(part->encryptions().size(), 1);
0136         QCOMPARE(part->signatures().size(), 0);
0137         QVERIFY(part->text().isEmpty());
0138         auto enc = part->encryptions()[0];
0139         QCOMPARE(enc->error(), MimeTreeParser::MessagePart::NoKeyError);
0140         // QCOMPARE((int) enc->recipients().size(), 2);
0141     }
0142 
0143 public Q_SLOTS:
0144     void init()
0145     {
0146         mResetGpgmeEngine = false;
0147         mModifiedEnv.clear();
0148         {
0149 
0150             gpgme_check_version(0);
0151             gpgme_ctx_t ctx = 0;
0152             gpgme_new(&ctx);
0153             gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP);
0154             gpgme_engine_info_t info = gpgme_ctx_get_engine_info(ctx);
0155             mGpgmeEngine_fname = info->file_name;
0156             gpgme_release(ctx);
0157         }
0158         mEnv = QProcessEnvironment::systemEnvironment();
0159         unsetEnv("GNUPGHOME");
0160     }
0161 
0162     void cleanup()
0163     {
0164         QCoreApplication::sendPostedEvents();
0165 
0166         const QString &gnupghome = qgetenv("GNUPGHOME");
0167         if (!gnupghome.isEmpty()) {
0168             killAgent(gnupghome);
0169         }
0170 
0171         resetGpgMfname();
0172         resetEnv();
0173     }
0174 private:
0175     void unsetEnv(const QByteArray &name)
0176     {
0177         mModifiedEnv << name;
0178         qunsetenv(name);
0179     }
0180 
0181     void setEnv(const QByteArray &name, const QByteArray &value)
0182     {
0183         mModifiedEnv << name;
0184         qputenv(name, value);
0185     }
0186 
0187     void resetEnv()
0188     {
0189         foreach(const auto &i, mModifiedEnv) {
0190             if (mEnv.contains(i)) {
0191                 qputenv(i, mEnv.value(i).toUtf8());
0192             } else {
0193                 qunsetenv(i);
0194             }
0195         }
0196     }
0197 
0198     void resetGpgMfname()
0199     {
0200         if (mResetGpgmeEngine) {
0201             gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP, mGpgmeEngine_fname, NULL);
0202         }
0203     }
0204 
0205     void setGpgMEfname(const QByteArray &fname, const QByteArray &homedir)
0206     {
0207         mResetGpgmeEngine = true;
0208         gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP, fname, homedir);
0209     }
0210 
0211     QSet<QByteArray> mModifiedEnv;
0212     QProcessEnvironment mEnv;
0213     bool mResetGpgmeEngine;
0214     QByteArray mGpgmeEngine_fname;
0215 };
0216 
0217 QTEST_GUILESS_MAIN(GpgErrorTest)
0218 #include "gpgerrortest.moc"