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

0001 #include "mypgpkeycontext.h"
0002 #include "gpgop.h"
0003 #include "utils.h"
0004 #include <QDir>
0005 #include <QTemporaryFile>
0006 
0007 using namespace QCA;
0008 
0009 namespace gpgQCAPlugin {
0010 
0011 MyPGPKeyContext::MyPGPKeyContext(Provider *p)
0012     : PGPKeyContext(p)
0013 {
0014     // zero out the props
0015     _props.isSecret  = false;
0016     _props.inKeyring = true;
0017     _props.isTrusted = false;
0018 }
0019 
0020 Provider::Context *MyPGPKeyContext::clone() const
0021 {
0022     return new MyPGPKeyContext(*this);
0023 }
0024 
0025 const PGPKeyContextProps *MyPGPKeyContext::props() const
0026 {
0027     return &_props;
0028 }
0029 
0030 QByteArray MyPGPKeyContext::toBinary() const
0031 {
0032     if (_props.inKeyring) {
0033         GpgOp gpg(find_bin());
0034         gpg.setAsciiFormat(false);
0035         gpg.doExport(_props.keyId);
0036         gpg_waitForFinished(&gpg);
0037         gpg_keyStoreLog(gpg.readDiagnosticText());
0038         if (!gpg.success())
0039             return QByteArray();
0040         return gpg.read();
0041     } else
0042         return cacheExportBinary;
0043 }
0044 
0045 ConvertResult MyPGPKeyContext::fromBinary(const QByteArray &a)
0046 {
0047     GpgOp::Key key;
0048     bool       sec = false;
0049 
0050     // temporary keyrings
0051     QString pubname, secname;
0052 
0053     QTemporaryFile pubtmp(QDir::tempPath() + QLatin1String("/qca_gnupg_tmp.XXXXXX.gpg"));
0054     if (!pubtmp.open())
0055         return ErrorDecode;
0056 
0057     QTemporaryFile sectmp(QDir::tempPath() + QLatin1String("/qca_gnupg_tmp.XXXXXX.gpg"));
0058     if (!sectmp.open())
0059         return ErrorDecode;
0060 
0061     pubname = pubtmp.fileName();
0062     secname = sectmp.fileName();
0063 
0064     // we turn off autoRemove so that we can close the files
0065     //   without them getting deleted
0066     pubtmp.setAutoRemove(false);
0067     sectmp.setAutoRemove(false);
0068     pubtmp.close();
0069     sectmp.close();
0070 
0071     // import key into temporary keyring
0072     GpgOp gpg(find_bin());
0073     gpg.setKeyrings(pubname, secname);
0074     gpg.doImport(a);
0075     gpg_waitForFinished(&gpg);
0076     gpg_keyStoreLog(gpg.readDiagnosticText());
0077     // comment this out.  apparently gpg will report failure for
0078     //   an import if there are trust issues, even though the
0079     //   key actually did get imported
0080     /*if(!gpg.success())
0081       {
0082       cleanup_temp_keyring(pubname);
0083       cleanup_temp_keyring(secname);
0084       return ErrorDecode;
0085       }*/
0086 
0087     // now extract the key from gpg like normal
0088 
0089     // is it a public key?
0090     gpg.doPublicKeys();
0091     gpg_waitForFinished(&gpg);
0092     gpg_keyStoreLog(gpg.readDiagnosticText());
0093     if (!gpg.success()) {
0094         cleanup_temp_keyring(pubname);
0095         cleanup_temp_keyring(secname);
0096         return ErrorDecode;
0097     }
0098 
0099     const GpgOp::KeyList pubkeys = gpg.keys();
0100     if (!pubkeys.isEmpty()) {
0101         key = pubkeys.first();
0102     } else {
0103         // is it a secret key?
0104         gpg.doSecretKeys();
0105         gpg_waitForFinished(&gpg);
0106         gpg_keyStoreLog(gpg.readDiagnosticText());
0107         if (!gpg.success()) {
0108             cleanup_temp_keyring(pubname);
0109             cleanup_temp_keyring(secname);
0110             return ErrorDecode;
0111         }
0112 
0113         const GpgOp::KeyList seckeys = gpg.keys();
0114         if (!seckeys.isEmpty()) {
0115             key = seckeys.first();
0116             sec = true;
0117         } else {
0118             // no keys found
0119             cleanup_temp_keyring(pubname);
0120             cleanup_temp_keyring(secname);
0121             return ErrorDecode;
0122         }
0123     }
0124 
0125     // export binary/ascii and cache
0126 
0127     gpg.setAsciiFormat(false);
0128     gpg.doExport(key.keyItems.first().id);
0129     gpg_waitForFinished(&gpg);
0130     gpg_keyStoreLog(gpg.readDiagnosticText());
0131     if (!gpg.success()) {
0132         cleanup_temp_keyring(pubname);
0133         cleanup_temp_keyring(secname);
0134         return ErrorDecode;
0135     }
0136     cacheExportBinary = gpg.read();
0137 
0138     gpg.setAsciiFormat(true);
0139     gpg.doExport(key.keyItems.first().id);
0140     gpg_waitForFinished(&gpg);
0141     gpg_keyStoreLog(gpg.readDiagnosticText());
0142     if (!gpg.success()) {
0143         cleanup_temp_keyring(pubname);
0144         cleanup_temp_keyring(secname);
0145         return ErrorDecode;
0146     }
0147     cacheExportAscii = QString::fromLocal8Bit(gpg.read());
0148 
0149     // all done
0150 
0151     cleanup_temp_keyring(pubname);
0152     cleanup_temp_keyring(secname);
0153 
0154     set(key, sec, false, false);
0155     return ConvertGood;
0156 }
0157 
0158 QString MyPGPKeyContext::toAscii() const
0159 {
0160     if (_props.inKeyring) {
0161         GpgOp gpg(find_bin());
0162         gpg.setAsciiFormat(true);
0163         gpg.doExport(_props.keyId);
0164         gpg_waitForFinished(&gpg);
0165         gpg_keyStoreLog(gpg.readDiagnosticText());
0166         if (!gpg.success())
0167             return QString();
0168         return QString::fromLocal8Bit(gpg.read());
0169     } else {
0170         return cacheExportAscii;
0171     }
0172 }
0173 
0174 ConvertResult MyPGPKeyContext::fromAscii(const QString &s)
0175 {
0176     // GnuPG does ascii/binary detection for imports, so for
0177     //   simplicity we consider an ascii import to just be a
0178     //   binary import that happens to be comprised of ascii
0179     return fromBinary(s.toLocal8Bit());
0180 }
0181 
0182 void MyPGPKeyContext::set(const GpgOp::Key &i, bool isSecret, bool inKeyring, bool isTrusted)
0183 {
0184     const GpgOp::KeyItem &ki = i.keyItems.first();
0185 
0186     _props.keyId          = ki.id;
0187     _props.userIds        = i.userIds;
0188     _props.isSecret       = isSecret;
0189     _props.creationDate   = ki.creationDate;
0190     _props.expirationDate = ki.expirationDate;
0191     _props.fingerprint    = ki.fingerprint.toLower();
0192     _props.inKeyring      = inKeyring;
0193     _props.isTrusted      = isTrusted;
0194 }
0195 
0196 void MyPGPKeyContext::cleanup_temp_keyring(const QString &name)
0197 {
0198     QFile::remove(name);
0199     QFile::remove(name + QLatin1Char('~')); // remove possible backup file
0200 }
0201 
0202 } // end namespace gpgQCAPlugin