1 /* t-various.cpp 2 3 This file is part of qgpgme, the Qt API binding for gpgme 4 Copyright (c) 2017 by Bundesamt für Sicherheit in der Informationstechnik 5 Software engineering by Intevation GmbH 6 7 QGpgME is free software; you can redistribute it and/or 8 modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the 10 License, or (at your option) any later version. 11 12 QGpgME is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 21 In addition, as a special exception, the copyright holders give 22 permission to link the code of this program with any edition of 23 the Qt library by Trolltech AS, Norway (or with modified versions 24 of Qt that use the same license as Qt), and distribute linked 25 combinations including the two. You must obey the GNU General 26 Public License in all respects for all of the code used other than 27 Qt. If you modify this file, you may extend this exception to 28 your version of the file, but you are not obligated to do so. If 29 you do not wish to do so, delete this exception statement from 30 your version. 31 */ 32 33 #ifdef HAVE_CONFIG_H 34 #include "config.h" 35 #endif 36 37 #include <QDebug> 38 #include <QTest> 39 #include <QSignalSpy> 40 #include <QTemporaryDir> 41 #include "keylistjob.h" 42 #include "protocol.h" 43 #include "keylistresult.h" 44 #include "context.h" 45 #include "engineinfo.h" 46 #include "dn.h" 47 #include "data.h" 48 #include "dataprovider.h" 49 50 #include "t-support.h" 51 52 using namespace QGpgME; 53 using namespace GpgME; 54 55 static const char aKey[] = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" 56 "\n" 57 "mDMEWG+w/hYJKwYBBAHaRw8BAQdAiq1oStvDYg8ZfFs5DgisYJo8dJxD+C/AA21O\n" 58 "K/aif0O0GXRvZnVfY29uZmxpY3RAZXhhbXBsZS5jb22IlgQTFggAPhYhBHoJBLaV\n" 59 "DamYAgoa1L5BwMOl/x88BQJYb7D+AhsDBQkDwmcABQsJCAcCBhUICQoLAgQWAgMB\n" 60 "Ah4BAheAAAoJEL5BwMOl/x88GvwA/0SxkbLyAcshGm2PRrPsFQsSVAfwaSYFVmS2\n" 61 "cMVIw1PfAQDclRH1Z4MpufK07ju4qI33o4s0UFpVRBuSxt7A4P2ZD7g4BFhvsP4S\n" 62 "CisGAQQBl1UBBQEBB0AmVrgaDNJ7K2BSalsRo2EkRJjHGqnp5bBB0tapnF81CQMB\n" 63 "CAeIeAQYFggAIBYhBHoJBLaVDamYAgoa1L5BwMOl/x88BQJYb7D+AhsMAAoJEL5B\n" 64 "wMOl/x88OR0BAMq4/vmJUORRTmzjHcv/DDrQB030DSq666rlckGIKTShAPoDXM9N\n" 65 "0gZK+YzvrinSKZXHmn0aSwmC1/hyPybJPEljBw==\n" 66 "=p2Oj\n" 67 "-----END PGP PUBLIC KEY BLOCK-----\n"; 68 69 class TestVarious: public QGpgMETest 70 { 71 Q_OBJECT 72 73 Q_SIGNALS: 74 void asyncDone(); 75 76 private Q_SLOTS: testDN()77 void testDN() 78 { 79 DN dn(QStringLiteral("CN=Before\\0DAfter,OU=Test,DC=North America,DC=Fabrikam,DC=COM")); 80 QVERIFY(dn.dn() == QStringLiteral("CN=Before\rAfter,OU=Test,DC=North America,DC=Fabrikam,DC=COM")); 81 QStringList attrOrder; 82 attrOrder << QStringLiteral("DC") << QStringLiteral("OU") << QStringLiteral("CN"); 83 dn.setAttributeOrder(attrOrder); 84 QVERIFY(dn.prettyDN() == QStringLiteral("DC=North America,DC=Fabrikam,DC=COM,OU=Test,CN=Before\rAfter")); 85 } 86 testKeyFromFile()87 void testKeyFromFile() 88 { 89 if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.14") { 90 return; 91 } 92 QGpgME::QByteArrayDataProvider dp(aKey); 93 Data data(&dp); 94 const auto keys = data.toKeys(); 95 QVERIFY(keys.size() == 1); 96 const auto key = keys[0]; 97 QVERIFY(!key.isNull()); 98 QVERIFY(key.primaryFingerprint() == QStringLiteral("7A0904B6950DA998020A1AD4BE41C0C3A5FF1F3C")); 99 } 100 testDataRewind()101 void testDataRewind() 102 { 103 if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.14") { 104 return; 105 } 106 QGpgME::QByteArrayDataProvider dp(aKey); 107 Data data(&dp); 108 char buf[20]; 109 data.read(buf, 20); 110 111 auto keys = data.toKeys(); 112 QVERIFY(keys.size() == 0); 113 114 data.rewind(); 115 116 keys = data.toKeys(); 117 QVERIFY(keys.size() == 1); 118 } 119 testQuickUid()120 void testQuickUid() 121 { 122 if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.13") { 123 return; 124 } 125 KeyListJob *job = openpgp()->keyListJob(false, true, true); 126 std::vector<GpgME::Key> keys; 127 GpgME::KeyListResult result = job->exec(QStringList() << QStringLiteral("alfa@example.net"), 128 false, keys); 129 delete job; 130 QVERIFY (!result.error()); 131 QVERIFY (keys.size() == 1); 132 Key key = keys.front(); 133 134 QVERIFY (key.numUserIDs() == 3); 135 const char uid[] = "Foo Bar (with comment) <foo@bar.baz>"; 136 137 auto ctx = Context::createForProtocol(key.protocol()); 138 QVERIFY (ctx); 139 TestPassphraseProvider provider; 140 ctx->setPassphraseProvider(&provider); 141 ctx->setPinentryMode(Context::PinentryLoopback); 142 143 QVERIFY(!ctx->addUid(key, uid)); 144 delete ctx; 145 key.update(); 146 147 QVERIFY (key.numUserIDs() == 4); 148 bool id_found = false;; 149 for (const auto &u: key.userIDs()) { 150 if (!strcmp (u.id(), uid)) { 151 QVERIFY (!u.isRevoked()); 152 id_found = true; 153 break; 154 } 155 } 156 QVERIFY (id_found); 157 158 ctx = Context::createForProtocol(key.protocol()); 159 QVERIFY (!ctx->revUid(key, uid)); 160 delete ctx; 161 key.update(); 162 163 bool id_revoked = false;; 164 for (const auto &u: key.userIDs()) { 165 if (!strcmp (u.id(), uid)) { 166 id_revoked = true; 167 break; 168 } 169 } 170 QVERIFY(id_revoked); 171 } 172 testSetExpire()173 void testSetExpire() 174 { 175 if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.22") { 176 return; 177 } 178 KeyListJob *job = openpgp()->keyListJob(false, true, true); 179 std::vector<GpgME::Key> keys; 180 GpgME::KeyListResult result = job->exec(QStringList() << QStringLiteral("alfa@example.net"), 181 false, keys); 182 delete job; 183 QVERIFY (!result.error()); 184 QVERIFY (keys.size() == 1); 185 Key key = keys.front(); 186 187 QVERIFY (key.subkey(0).expirationTime() == time_t(0)); 188 QVERIFY (key.subkey(1).expirationTime() == time_t(0)); 189 190 auto ctx = Context::createForProtocol(key.protocol()); 191 QVERIFY (ctx); 192 TestPassphraseProvider provider; 193 ctx->setPassphraseProvider(&provider); 194 ctx->setPinentryMode(Context::PinentryLoopback); 195 196 // change expiration of the main key 197 QVERIFY(!ctx->setExpire(key, 1000)); 198 delete ctx; 199 key.update(); 200 201 QVERIFY (key.subkey(0).expirationTime() != time_t(0)); 202 QVERIFY (key.subkey(1).expirationTime() == time_t(0)); 203 time_t keyExpiration = key.subkey(0).expirationTime(); 204 205 // change expiration of all subkeys 206 ctx = Context::createForProtocol(key.protocol()); 207 QVERIFY(!ctx->setExpire(key, 2000, std::vector<Subkey>(), Context::SetExpireAllSubkeys)); 208 delete ctx; 209 key.update(); 210 211 QVERIFY (key.subkey(0).expirationTime() == keyExpiration); 212 QVERIFY (key.subkey(1).expirationTime() != time_t(0)); 213 time_t subkeyExpiration = key.subkey(1).expirationTime(); 214 215 // change expiration of specific subkey(s) 216 ctx = Context::createForProtocol(key.protocol()); 217 std::vector<Subkey> specificSubkeys; 218 specificSubkeys.push_back(key.subkey(1)); 219 QVERIFY(!ctx->setExpire(key, 3000, specificSubkeys)); 220 delete ctx; 221 key.update(); 222 223 QVERIFY (key.subkey(0).expirationTime() == keyExpiration); 224 QVERIFY (key.subkey(1).expirationTime() != subkeyExpiration); 225 226 // test error handling: calling setExpire() with the primary key as 227 // subkey should fail with "subkey <primary key fpr> not found" 228 ctx = Context::createForProtocol(key.protocol()); 229 std::vector<Subkey> primaryKey; 230 primaryKey.push_back(key.subkey(0)); 231 const auto err = ctx->setExpire(key, 3000, primaryKey); 232 QCOMPARE(err.code(), GPG_ERR_NOT_FOUND); 233 delete ctx; 234 } 235 testVersion()236 void testVersion() 237 { 238 QVERIFY(EngineInfo::Version("2.1.0") < EngineInfo::Version("2.1.1")); 239 QVERIFY(EngineInfo::Version("2.1.10") < EngineInfo::Version("2.1.11")); 240 QVERIFY(EngineInfo::Version("2.2.0") > EngineInfo::Version("2.1.19")); 241 QVERIFY(EngineInfo::Version("1.0.0") < EngineInfo::Version("2.0.0")); 242 QVERIFY(EngineInfo::Version("0.1.0") < EngineInfo::Version("1.0.0")); 243 QVERIFY(!(EngineInfo::Version("2.0.0") < EngineInfo::Version("2.0.0"))); 244 QVERIFY(!(EngineInfo::Version("2.0.0") > EngineInfo::Version("2.0.0"))); 245 QVERIFY(EngineInfo::Version("3.0.0") > EngineInfo::Version("2.3.20")); 246 QVERIFY(EngineInfo::Version("3.0.1") > EngineInfo::Version("3.0.0")); 247 QVERIFY(EngineInfo::Version("3.1.0") > EngineInfo::Version("3.0.20")); 248 249 QVERIFY(EngineInfo::Version("1.1.1") <= "2.0.0"); 250 QVERIFY(EngineInfo::Version("1.1.1") <= "1.2.0"); 251 QVERIFY(EngineInfo::Version("1.1.1") <= "1.1.2"); 252 QVERIFY(EngineInfo::Version("1.1.1") <= "1.1.1"); 253 QVERIFY(!(EngineInfo::Version("1.1.1") <= "1.1.0")); 254 QVERIFY(!(EngineInfo::Version("1.1.1") <= "1.0.9")); 255 QVERIFY(!(EngineInfo::Version("1.1.1") <= "0.9.9")); 256 257 QVERIFY(!(EngineInfo::Version("1.1.1") == "2.0.0")); 258 QVERIFY(!(EngineInfo::Version("1.1.1") == "1.2.0")); 259 QVERIFY(!(EngineInfo::Version("1.1.1") == "1.1.2")); 260 QVERIFY(EngineInfo::Version("1.1.1") == "1.1.1"); 261 QVERIFY(!(EngineInfo::Version("1.1.1") == "1.1.0")); 262 QVERIFY(!(EngineInfo::Version("1.1.1") == "1.0.9")); 263 QVERIFY(!(EngineInfo::Version("1.1.1") == "0.9.9")); 264 265 QVERIFY(EngineInfo::Version("1.1.1") != "2.0.0"); 266 QVERIFY(EngineInfo::Version("1.1.1") != "1.2.0"); 267 QVERIFY(EngineInfo::Version("1.1.1") != "1.1.2"); 268 QVERIFY(!(EngineInfo::Version("1.1.1") != "1.1.1")); 269 QVERIFY(EngineInfo::Version("1.1.1") != "1.1.0"); 270 QVERIFY(EngineInfo::Version("1.1.1") != "1.0.9"); 271 QVERIFY(EngineInfo::Version("1.1.1") != "0.9.9"); 272 273 QVERIFY(!(EngineInfo::Version("1.1.1") >= "2.0.0")); 274 QVERIFY(!(EngineInfo::Version("1.1.1") >= "1.2.0")); 275 QVERIFY(!(EngineInfo::Version("1.1.1") >= "1.1.2")); 276 QVERIFY(EngineInfo::Version("1.1.1") >= "1.1.1"); 277 QVERIFY(EngineInfo::Version("1.1.1") >= "1.1.0"); 278 QVERIFY(EngineInfo::Version("1.1.1") >= "1.0.9"); 279 QVERIFY(EngineInfo::Version("1.1.1") >= "0.9.9"); 280 } 281 initTestCase()282 void initTestCase() 283 { 284 QGpgMETest::initTestCase(); 285 const QString gpgHome = qgetenv("GNUPGHOME"); 286 QVERIFY(copyKeyrings(gpgHome, mDir.path())); 287 qputenv("GNUPGHOME", mDir.path().toUtf8()); 288 } 289 290 private: 291 QTemporaryDir mDir; 292 }; 293 294 QTEST_MAIN(TestVarious) 295 296 #include "t-various.moc" 297