File indexing completed on 2024-05-05 04:45:04

0001 /*
0002  * Copyright (C) 2003-2005  Justin Karneges <justin@affinix.com>
0003  *
0004  * This library is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU Lesser General Public
0006  * License as published by the Free Software Foundation; either
0007  * version 2.1 of the License, or (at your option) any later version.
0008  *
0009  * This library is distributed in the hope that it will be useful,
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012  * Lesser General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU Lesser General Public
0015  * License along with this library; if not, write to the Free Software
0016  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
0017  *
0018  */
0019 
0020 #include "gpgop.h"
0021 #include "gpgaction.h"
0022 #include "gpgop_p.h"
0023 
0024 namespace gpgQCAPlugin {
0025 
0026 //----------------------------------------------------------------------------
0027 // GpgOp
0028 //----------------------------------------------------------------------------
0029 GpgOp::Private::Private(GpgOp *_q)
0030     : QObject(_q)
0031     , sync(_q)
0032     , q(_q)
0033     , act(nullptr)
0034     , waiting(false)
0035 {
0036     reset(ResetAll);
0037 }
0038 
0039 GpgOp::Private::~Private()
0040 {
0041     reset(ResetAll);
0042 }
0043 
0044 void GpgOp::Private::reset(ResetMode mode)
0045 {
0046     if (act) {
0047         act->disconnect(this);
0048         act->setParent(nullptr);
0049         act->deleteLater();
0050 
0051         act = nullptr;
0052     }
0053 
0054     if (mode >= ResetSessionAndData) {
0055         output = GpgAction::Output();
0056         result.clear();
0057         diagnosticText = QString();
0058         eventList.clear();
0059     }
0060 
0061     if (mode >= ResetAll) {
0062         opt_ascii       = false;
0063         opt_noagent     = false;
0064         opt_alwaystrust = false;
0065         opt_pubfile     = QString();
0066         opt_secfile     = QString();
0067     }
0068 }
0069 
0070 void GpgOp::Private::make_act(GpgOp::Type _op)
0071 {
0072     reset(ResetSessionAndData);
0073 
0074     op = _op;
0075 
0076     act = new GpgAction(this);
0077 
0078     connect(act, &GpgAction::readyRead, this, &GpgOp::Private::act_readyRead);
0079     connect(act, &GpgAction::bytesWritten, this, &GpgOp::Private::act_bytesWritten);
0080     connect(act, &GpgAction::needPassphrase, this, &GpgOp::Private::act_needPassphrase);
0081     connect(act, &GpgAction::needCard, this, &GpgOp::Private::act_needCard);
0082     connect(act, &GpgAction::finished, this, &GpgOp::Private::act_finished);
0083     connect(act, &GpgAction::readyReadDiagnosticText, this, &GpgOp::Private::act_readyReadDiagnosticText);
0084 
0085     act->input.bin             = bin;
0086     act->input.op              = op;
0087     act->input.opt_ascii       = opt_ascii;
0088     act->input.opt_noagent     = opt_noagent;
0089     act->input.opt_alwaystrust = opt_alwaystrust;
0090     act->input.opt_pubfile     = opt_pubfile;
0091     act->input.opt_secfile     = opt_secfile;
0092 }
0093 
0094 void GpgOp::Private::eventReady(const GpgOp::Event &e)
0095 {
0096     eventList += e;
0097     sync.conditionMet();
0098 }
0099 
0100 void GpgOp::Private::eventReady(GpgOp::Event::Type type)
0101 {
0102     GpgOp::Event e;
0103     e.type = type;
0104     eventReady(e);
0105 }
0106 
0107 void GpgOp::Private::eventReady(GpgOp::Event::Type type, int written)
0108 {
0109     GpgOp::Event e;
0110     e.type    = type;
0111     e.written = written;
0112     eventReady(e);
0113 }
0114 
0115 void GpgOp::Private::eventReady(GpgOp::Event::Type type, const QString &keyId)
0116 {
0117     GpgOp::Event e;
0118     e.type  = type;
0119     e.keyId = keyId;
0120     eventReady(e);
0121 }
0122 
0123 void GpgOp::Private::act_readyRead()
0124 {
0125     if (waiting)
0126         eventReady(GpgOp::Event::ReadyRead);
0127     else
0128         emit q->readyRead();
0129 }
0130 
0131 void GpgOp::Private::act_bytesWritten(int bytes)
0132 {
0133     if (waiting)
0134         eventReady(GpgOp::Event::BytesWritten, bytes);
0135     else
0136         emit q->bytesWritten(bytes);
0137 }
0138 
0139 void GpgOp::Private::act_needPassphrase(const QString &keyId)
0140 {
0141     if (waiting)
0142         eventReady(GpgOp::Event::NeedPassphrase, keyId);
0143     else
0144         emit q->needPassphrase(keyId);
0145 }
0146 
0147 void GpgOp::Private::act_needCard()
0148 {
0149     if (waiting)
0150         eventReady(GpgOp::Event::NeedCard);
0151     else
0152         emit q->needCard();
0153 }
0154 
0155 void GpgOp::Private::act_readyReadDiagnosticText()
0156 {
0157     const QString s = act->readDiagnosticText();
0158     // printf("dtext ready: [%s]\n", qPrintable(s));
0159     diagnosticText += s;
0160 
0161     if (waiting)
0162         eventReady(GpgOp::Event::ReadyReadDiagnosticText);
0163     else
0164         emit q->readyReadDiagnosticText();
0165 }
0166 
0167 void GpgOp::Private::act_finished()
0168 {
0169 #ifdef GPG_PROFILE
0170     if (op == GpgOp::Encrypt)
0171         printf("<< doEncrypt: %d >>\n", timer.elapsed());
0172 #endif
0173 
0174     result = act->read();
0175     diagnosticText += act->readDiagnosticText();
0176     output = act->output;
0177 
0178     QMap<int, QString> errmap;
0179     errmap[GpgOp::ErrorProcess]          = QStringLiteral("ErrorProcess");
0180     errmap[GpgOp::ErrorPassphrase]       = QStringLiteral("ErrorPassphrase");
0181     errmap[GpgOp::ErrorFormat]           = QStringLiteral("ErrorFormat");
0182     errmap[GpgOp::ErrorSignerExpired]    = QStringLiteral("ErrorSignerExpired");
0183     errmap[GpgOp::ErrorEncryptExpired]   = QStringLiteral("ErrorEncryptExpired");
0184     errmap[GpgOp::ErrorEncryptUntrusted] = QStringLiteral("ErrorEncryptUntrusted");
0185     errmap[GpgOp::ErrorEncryptInvalid]   = QStringLiteral("ErrorEncryptInvalid");
0186     errmap[GpgOp::ErrorDecryptNoKey]     = QStringLiteral("ErrorDecryptNoKey");
0187     errmap[GpgOp::ErrorUnknown]          = QStringLiteral("ErrorUnknown");
0188     if (output.success)
0189         diagnosticText += QStringLiteral("GpgAction success\n");
0190     else
0191         diagnosticText += QStringLiteral("GpgAction error: %1\n").arg(errmap[output.errorCode]);
0192 
0193     if (output.wasSigned) {
0194         QString s;
0195         if (output.verifyResult == GpgOp::VerifyGood)
0196             s = QStringLiteral("VerifyGood");
0197         else if (output.verifyResult == GpgOp::VerifyBad)
0198             s = QStringLiteral("VerifyBad");
0199         else
0200             s = QStringLiteral("VerifyNoKey");
0201         diagnosticText += QStringLiteral("wasSigned: verifyResult: %1\n").arg(s);
0202     }
0203 
0204     // printf("diagnosticText:\n%s", qPrintable(diagnosticText));
0205 
0206     reset(ResetSession);
0207 
0208     if (waiting)
0209         eventReady(GpgOp::Event::Finished);
0210     else
0211         emit q->finished();
0212 }
0213 
0214 GpgOp::GpgOp(const QString &bin, QObject *parent)
0215     : QObject(parent)
0216 {
0217     d      = new Private(this);
0218     d->bin = bin;
0219 }
0220 
0221 GpgOp::~GpgOp()
0222 {
0223     delete d;
0224 }
0225 
0226 void GpgOp::reset()
0227 {
0228     d->reset(ResetAll);
0229 }
0230 
0231 bool GpgOp::isActive() const
0232 {
0233     return (d->act ? true : false);
0234 }
0235 
0236 GpgOp::Type GpgOp::op() const
0237 {
0238     return d->op;
0239 }
0240 
0241 void GpgOp::setAsciiFormat(bool b)
0242 {
0243     d->opt_ascii = b;
0244 }
0245 
0246 void GpgOp::setDisableAgent(bool b)
0247 {
0248     d->opt_noagent = b;
0249 }
0250 
0251 void GpgOp::setAlwaysTrust(bool b)
0252 {
0253     d->opt_alwaystrust = b;
0254 }
0255 
0256 void GpgOp::setKeyrings(const QString &pubfile, const QString &secfile)
0257 {
0258     d->opt_pubfile = pubfile;
0259     d->opt_secfile = secfile;
0260 }
0261 
0262 void GpgOp::doCheck()
0263 {
0264     d->make_act(Check);
0265     d->act->start();
0266 }
0267 
0268 void GpgOp::doSecretKeyringFile()
0269 {
0270     d->make_act(SecretKeyringFile);
0271     d->act->start();
0272 }
0273 
0274 void GpgOp::doPublicKeyringFile()
0275 {
0276     d->make_act(PublicKeyringFile);
0277     d->act->start();
0278 }
0279 
0280 void GpgOp::doSecretKeys()
0281 {
0282     d->make_act(SecretKeys);
0283     d->act->start();
0284 }
0285 
0286 void GpgOp::doPublicKeys()
0287 {
0288     d->make_act(PublicKeys);
0289     d->act->start();
0290 }
0291 
0292 void GpgOp::doEncrypt(const QStringList &recip_ids)
0293 {
0294 #ifdef GPG_PROFILE
0295     d->timer.start();
0296     printf("<< doEncrypt >>\n");
0297 #endif
0298 
0299     d->make_act(Encrypt);
0300     d->act->input.recip_ids = recip_ids;
0301     d->act->start();
0302 }
0303 
0304 void GpgOp::doDecrypt()
0305 {
0306     d->make_act(Decrypt);
0307     d->act->start();
0308 }
0309 
0310 void GpgOp::doSign(const QString &signer_id)
0311 {
0312     d->make_act(Sign);
0313     d->act->input.signer_id = signer_id;
0314     d->act->start();
0315 }
0316 
0317 void GpgOp::doSignAndEncrypt(const QString &signer_id, const QStringList &recip_ids)
0318 {
0319     d->make_act(SignAndEncrypt);
0320     d->act->input.signer_id = signer_id;
0321     d->act->input.recip_ids = recip_ids;
0322     d->act->start();
0323 }
0324 
0325 void GpgOp::doSignClearsign(const QString &signer_id)
0326 {
0327     d->make_act(SignClearsign);
0328     d->act->input.signer_id = signer_id;
0329     d->act->start();
0330 }
0331 
0332 void GpgOp::doSignDetached(const QString &signer_id)
0333 {
0334     d->make_act(SignDetached);
0335     d->act->input.signer_id = signer_id;
0336     d->act->start();
0337 }
0338 
0339 void GpgOp::doVerify()
0340 {
0341     d->make_act(Verify);
0342     d->act->start();
0343 }
0344 
0345 void GpgOp::doVerifyDetached(const QByteArray &sig)
0346 {
0347     d->make_act(VerifyDetached);
0348     d->act->input.sig = sig;
0349     d->act->start();
0350 }
0351 
0352 void GpgOp::doImport(const QByteArray &in)
0353 {
0354     d->make_act(Import);
0355     d->act->input.inkey = in;
0356     d->act->start();
0357 }
0358 
0359 void GpgOp::doExport(const QString &key_id)
0360 {
0361     d->make_act(Export);
0362     d->act->input.export_key_id = key_id;
0363     d->act->start();
0364 }
0365 
0366 void GpgOp::doDeleteKey(const QString &key_fingerprint)
0367 {
0368     d->make_act(DeleteKey);
0369     d->act->input.delete_key_fingerprint = key_fingerprint;
0370     d->act->start();
0371 }
0372 
0373 #ifdef QPIPE_SECURE
0374 void GpgOp::submitPassphrase(const QCA::SecureArray &a)
0375 #else
0376 void GpgOp::submitPassphrase(const QByteArray &a)
0377 #endif
0378 {
0379     d->act->submitPassphrase(a);
0380 }
0381 
0382 void GpgOp::cardOkay()
0383 {
0384     d->act->cardOkay();
0385 }
0386 
0387 QByteArray GpgOp::read()
0388 {
0389     if (d->act) {
0390         return d->act->read();
0391     } else {
0392         const QByteArray a = d->result;
0393         d->result.clear();
0394         return a;
0395     }
0396 }
0397 
0398 void GpgOp::write(const QByteArray &in)
0399 {
0400     d->act->write(in);
0401 }
0402 
0403 void GpgOp::endWrite()
0404 {
0405     d->act->endWrite();
0406 }
0407 
0408 QString GpgOp::readDiagnosticText()
0409 {
0410     QString s         = d->diagnosticText;
0411     d->diagnosticText = QString();
0412     return s;
0413 }
0414 
0415 GpgOp::Event GpgOp::waitForEvent(int msecs)
0416 {
0417     if (!d->eventList.isEmpty())
0418         return d->eventList.takeFirst();
0419 
0420     if (!d->act)
0421         return GpgOp::Event();
0422 
0423     d->waiting = true;
0424     d->sync.waitForCondition(msecs);
0425     d->waiting = false;
0426     if (!d->eventList.isEmpty())
0427         return d->eventList.takeFirst();
0428     else
0429         return GpgOp::Event();
0430 }
0431 
0432 bool GpgOp::success() const
0433 {
0434     return d->output.success;
0435 }
0436 
0437 GpgOp::Error GpgOp::errorCode() const
0438 {
0439     return d->output.errorCode;
0440 }
0441 
0442 GpgOp::KeyList GpgOp::keys() const
0443 {
0444     return d->output.keys;
0445 }
0446 
0447 QString GpgOp::keyringFile() const
0448 {
0449     return d->output.keyringFile;
0450 }
0451 
0452 QString GpgOp::homeDir() const
0453 {
0454     return d->output.homeDir;
0455 }
0456 
0457 QString GpgOp::encryptedToId() const
0458 {
0459     return d->output.encryptedToId;
0460 }
0461 
0462 bool GpgOp::wasSigned() const
0463 {
0464     return d->output.wasSigned;
0465 }
0466 
0467 QString GpgOp::signerId() const
0468 {
0469     return d->output.signerId;
0470 }
0471 
0472 QDateTime GpgOp::timestamp() const
0473 {
0474     return d->output.timestamp;
0475 }
0476 
0477 GpgOp::VerifyResult GpgOp::verifyResult() const
0478 {
0479     return d->output.verifyResult;
0480 }
0481 
0482 }