diff options
Diffstat (limited to 'src/gpg/gpg_context/GpgContext.cpp')
-rw-r--r-- | src/gpg/gpg_context/GpgContext.cpp | 410 |
1 files changed, 0 insertions, 410 deletions
diff --git a/src/gpg/gpg_context/GpgContext.cpp b/src/gpg/gpg_context/GpgContext.cpp deleted file mode 100644 index 14b54b32..00000000 --- a/src/gpg/gpg_context/GpgContext.cpp +++ /dev/null @@ -1,410 +0,0 @@ -/** - * This file is part of GPGFrontend. - * - * GPGFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Foobar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from gpg4usb-team. - * Their source code version also complies with GNU General Public License. - * - * The source code version of this software was modified and released - * by Saturneric<[email protected]> starting on May 12, 2021. - * - */ - -#include "gpg/GpgContext.h" -#include "ui/WaitingDialog.h" - -#include <functional> -#include <unistd.h> /* contains read/write */ - -#ifdef _WIN32 - -#include <windows.h> - -#endif - -#define INT2VOIDP(i) (void*)(uintptr_t)(i) - -namespace GpgME { - - /** Constructor - * Set up gpgme-context, set paths to app-run path - */ - GpgContext::GpgContext() { - - /** The function `gpgme_check_version' must be called before any other - * function in the library, because it initializes the thread support - * subsystem in GPGME. (from the info page) */ - gpgme_check_version(nullptr); - - // the locale set here is used for the other setlocale calls which have nullptr - // -> nullptr means use default, which is configured here - setlocale(LC_ALL, settings.value("int/lang").toLocale().name().toUtf8().constData()); - - /** set locale, because tests do also */ - gpgme_set_locale(nullptr, LC_CTYPE, setlocale(LC_CTYPE, nullptr)); - //qDebug() << "Locale set to" << LC_CTYPE << " - " << setlocale(LC_CTYPE, nullptr); -#ifndef _WIN32 - gpgme_set_locale(nullptr, LC_MESSAGES, setlocale(LC_MESSAGES, nullptr)); -#endif - - err = gpgme_new(&mCtx); - checkErr(err); - - gpgme_engine_info_t engineInfo; - engineInfo = gpgme_ctx_get_engine_info(mCtx); - -// Check ENV before running - bool check_pass = false, find_openpgp = false, find_gpgconf = false, find_assuan = false, find_cms = false; - while (engineInfo != nullptr) { - qDebug() << gpgme_get_protocol_name(engineInfo->protocol) << engineInfo->file_name << engineInfo->protocol - << engineInfo->home_dir << engineInfo->version; - if (engineInfo->protocol == GPGME_PROTOCOL_GPGCONF && strcmp(engineInfo->version, "1.0.0") != 0) - find_gpgconf = true; - if (engineInfo->protocol == GPGME_PROTOCOL_OpenPGP && strcmp(engineInfo->version, "1.0.0") != 0) - find_openpgp = true, info.appPath = engineInfo->file_name; - if (engineInfo->protocol == GPGME_PROTOCOL_CMS && strcmp(engineInfo->version, "1.0.0") != 0) - find_cms = true; - if (engineInfo->protocol == GPGME_PROTOCOL_ASSUAN) - find_assuan = true; - - engineInfo = engineInfo->next; - } - - if (find_gpgconf && find_openpgp && find_cms && find_assuan) - check_pass = true; - - if (!check_pass) { - good = false; - return; - } else good = true; - - -/** Setting the output type must be done at the beginning */ -/** think this means ascii-armor --> ? */ - gpgme_set_armor(mCtx, 1); -/** passphrase-callback */ - gpgme_set_passphrase_cb(mCtx, passphraseCb, this); - -/** check if app is called with -d from command line */ - if (qApp->arguments().contains("-d")) { - qDebug() << "gpgme_data_t debug on"; - debug = true; - } else { - debug = false; - } - - connect(this, SIGNAL(signalKeyDBChanged()), - this, SLOT(slotRefreshKeyList()), Qt::DirectConnection); - connect(this, SIGNAL(signalKeyUpdated(QString)), - this, SLOT(slotUpdateKeyList(QString)), Qt::DirectConnection); - slotRefreshKeyList(); - } - - /** Destructor - * Release gpgme-context - */ - GpgContext::~GpgContext() { - if (mCtx) gpgme_release(mCtx); - mCtx = nullptr; - } - - bool GpgContext::isGood() const { - return good; - } - - /** Read gpgme-Data to QByteArray - * mainly from http://basket.kde.org/ (kgpgme.cpp) - */ -#define BUF_SIZE (32 * 1024) - - gpgme_error_t GpgContext::readToBuffer(gpgme_data_t dataIn, QByteArray *outBuffer) { - gpgme_off_t ret; - gpgme_error_t gpgErrNoError = GPG_ERR_NO_ERROR; - - ret = gpgme_data_seek(dataIn, 0, SEEK_SET); - if (ret) { - gpgErrNoError = gpgme_err_code_from_errno(errno); - checkErr(gpgErrNoError, "failed dataseek dataIn readToBuffer"); - } else { - char buf[BUF_SIZE + 2]; - - while ((ret = gpgme_data_read(dataIn, buf, BUF_SIZE)) > 0) { - const size_t size = outBuffer->size(); - outBuffer->resize(static_cast<int>(size + ret)); - memcpy(outBuffer->data() + size, buf, ret); - } - if (ret < 0) { - gpgErrNoError = gpgme_err_code_from_errno(errno); - checkErr(gpgErrNoError, "failed data_read dataIn readToBuffer"); - } - } - return gpgErrNoError; - } - - /** - * The Passphrase window, if not provided by env-Var GPG_AGENT_INFO - * originally copied from http://basket.kde.org/ (kgpgme.cpp), but modified - */ - gpgme_error_t GpgContext::passphraseCb(void *hook, const char *uid_hint, - const char *passphrase_info, - int last_was_bad, int fd) { - auto *gpg = static_cast<GpgContext *>(hook); - return gpg->passphrase(uid_hint, passphrase_info, last_was_bad, fd); - } - - gpgme_error_t GpgContext::passphrase(const char *uid_hint, - const char * /*passphrase_info*/, - int last_was_bad, int fd) { - - gpgme_error_t returnValue = GPG_ERR_CANCELED; - QString passwordDialogMessage; - QString gpgHint = QString::fromUtf8(uid_hint); - bool result; - -#ifdef _WIN32 - DWORD written; - auto hd = INT2VOIDP(fd); -#endif - - if (last_was_bad) { - passwordDialogMessage += "<i>" + tr("Wrong password") + ".</i><br><br>\n\n"; - clearPasswordCache(); - } - - /** if uid provided */ - if (!gpgHint.isEmpty()) { - // remove UID, leave only username & email - gpgHint.remove(0, gpgHint.indexOf(" ")); - passwordDialogMessage += "<b>" + tr("Enter Password for") + "</b><br>" + gpgHint + "<br>"; - } - - if (mPasswordCache.isEmpty()) { - QString password = QInputDialog::getText(QApplication::activeWindow(), tr("Enter Password"), - passwordDialogMessage, QLineEdit::Password, - "", &result); - - if (result) mPasswordCache = password.toUtf8(); - } else result = true; - - if (result) { - -#ifndef _WIN32 - if (write(fd, mPasswordCache.data(), mPasswordCache.length()) == -1) qDebug() << "something is terribly broken"; -#else - WriteFile(hd, mPasswordCache.data(), mPasswordCache.length(), &written, 0); -#endif - returnValue = GPG_ERR_NO_ERROR; - } - -#ifndef _WIN32 - if (write(fd, "\n", 1) == -1) qDebug() << "something is terribly broken"; -#else - WriteFile(hd, "\n", 1, &written, 0); - - /* program will hang on cancel if hd not closed */ - if (!result) CloseHandle(hd); -#endif - - return returnValue; - } - - /** also from kgpgme.cpp, seems to clear password from mem */ - void GpgContext::clearPasswordCache() { - if (mPasswordCache.size() > 0) { - mPasswordCache.fill('\0'); - mPasswordCache.truncate(0); - } - } - - // error-handling - void GpgContext::checkErr(gpgme_error_t gpgmeError, const QString &comment) { - //if (gpgmeError != GPG_ERR_NO_ERROR && gpgmeError != GPG_ERR_CANCELED) { - if (gpgmeError != GPG_ERR_NO_ERROR) { - qDebug() << "[Error " << gpg_err_code(gpgmeError) - << "] Source: " << gpgme_strsource(gpgmeError) << " Description: " << gpgErrString(gpgmeError); - } - } - - void GpgContext::checkErr(gpgme_error_t gpgmeError) { - //if (gpgmeError != GPG_ERR_NO_ERROR && gpgmeError != GPG_ERR_CANCELED) { - if (gpg_err_code(gpgmeError) != GPG_ERR_NO_ERROR) { - qDebug() << "[Error " << gpg_err_code(gpgmeError) - << "] Source: " << gpgme_strsource(gpgmeError) << " Description: " << gpgErrString(gpgmeError); - } - } - - QString GpgContext::gpgErrString(gpgme_error_t err) { - return QString::fromUtf8(gpgme_strerror(err)); - } - - /** return type should be gpgme_error_t*/ - void - GpgContext::executeGpgCommand(const QStringList &arguments, const std::function<void(QProcess *)> &interactFunc) { - QEventLoop looper; - auto dialog = new WaitingDialog(tr("Processing"), nullptr); - dialog->show(); - auto *gpgProcess = new QProcess(&looper); - gpgProcess->setProcessChannelMode(QProcess::MergedChannels); - connect(gpgProcess, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), &looper, &QEventLoop::quit); - connect(gpgProcess, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), dialog, - &WaitingDialog::deleteLater); - connect(gpgProcess, &QProcess::errorOccurred, []() -> void { qDebug("Error in Process"); }); - connect(gpgProcess, &QProcess::errorOccurred, &looper, &QEventLoop::quit); - connect(gpgProcess, &QProcess::started, []() -> void { qDebug() << "Gpg Process Started Success"; }); - connect(gpgProcess, &QProcess::readyReadStandardOutput, [interactFunc, gpgProcess]() { - qDebug() << "Function Called"; - interactFunc(gpgProcess); - }); - gpgProcess->setProgram(info.appPath); - gpgProcess->setArguments(arguments); - gpgProcess->start(); - looper.exec(); - dialog->close(); - - } - - - /* - * if there is no '\n' before the PGP-Begin-Block, but for example a whitespace, - * GPGME doesn't recognise the Message as encrypted. This function adds '\n' - * before the PGP-Begin-Block, if missing. - */ - void GpgContext::preventNoDataErr(QByteArray *in) { - int block_start = in->indexOf(GpgConstants::PGP_CRYPT_BEGIN); - if (block_start > 0 && in->at(block_start - 1) != '\n') { - in->insert(block_start, '\n'); - } - block_start = in->indexOf(GpgConstants::PGP_SIGNED_BEGIN); - if (block_start > 0 && in->at(block_start - 1) != '\n') { - in->insert(block_start, '\n'); - } - } - - /* - * isSigned returns: - * - 0, if text isn't signed at all - * - 1, if text is partially signed - * - 2, if text is completly signed - */ - int GpgContext::textIsSigned(const QByteArray &text) { - if (text.trimmed().startsWith(GpgConstants::PGP_SIGNED_BEGIN) && - text.trimmed().endsWith(GpgConstants::PGP_SIGNED_END)) - return 2; - else if (text.contains(GpgConstants::PGP_SIGNED_BEGIN) && text.contains(GpgConstants::PGP_SIGNED_END)) - return 1; - - else return 0; - } - - QString GpgContext::beautifyFingerprint(QString fingerprint) { - uint len = fingerprint.length(); - if ((len > 0) && (len % 4 == 0)) - for (uint n = 0; 4 * (n + 1) < len; ++n) fingerprint.insert(static_cast<int>(5u * n + 4u), ' '); - return fingerprint; - } - - void GpgContext::slotRefreshKeyList() { - qDebug() << "Refreshing Keys"; - this->fetch_keys(); - emit signalKeyInfoChanged(); - } - - QString GpgContext::getGpgmeVersion() { - return {gpgme_check_version(nullptr)}; - } - - const GpgKeyList &GpgContext::getKeys() const { - return mKeyList; - } - - void GpgContext::getSigners(QVector<GpgKey> &signer, gpgme_ctx_t ctx) { - auto count = gpgme_signers_count(ctx); - signer.clear(); - for (auto i = 0; i < count; i++) { - auto key = gpgme_signers_enum(ctx, i); - auto it = mKeyMap.find(key->subkeys->keyid); - if (it == mKeyMap.end()) { - qDebug() << "Inconsistent state"; - signer.push_back(GpgKey(key)); - } else { - signer.push_back(*it.value()); - } - } - } - - void GpgContext::setSigners(const QVector<GpgKey> &keys, gpgme_ctx_t ctx) { - gpgme_signers_clear(ctx); - for (const auto &key : keys) { - if (checkIfKeyCanSign(key)) { - auto gpgmeError = gpgme_signers_add(ctx, key.key_refer); - checkErr(gpgmeError); - } - } - if (keys.length() != gpgme_signers_count(ctx)) { - qDebug() << "No All Keys Added"; - } - } - - void GpgContext::slotUpdateKeyList(const QString &key_id) { - auto it = mKeyMap.find(key_id); - if (it != mKeyMap.end()) { - gpgme_key_t new_key_refer; - auto gpgmeErr = gpgme_get_key(mCtx, key_id.toUtf8().constData(), &new_key_refer, 0); - - if (gpgme_err_code(gpgmeErr) == GPG_ERR_EOF) { - gpgmeErr = gpgme_get_key(mCtx, key_id.toUtf8().constData(), &new_key_refer, 1); - - if (gpgme_err_code(gpgmeErr) == GPG_ERR_EOF) { - throw std::runtime_error("key_id not found in key database"); - } - - } - - if (new_key_refer != nullptr) { - it.value()->swapKeyRefer(new_key_refer); - emit signalKeyInfoChanged(); - } - - } - } - - bool GpgContext::revSign(const GpgKey &key, const GpgKeySignature &signature) { - - auto signing_key = getKeyById(signature.keyid); - - auto gpgmeError = gpgme_op_revsig(mCtx, key.key_refer, - signing_key.key_refer, - signature.uid.toUtf8().constData(), 0); - if (gpg_err_code(gpgmeError) == GPG_ERR_NO_ERROR) { - emit signalKeyUpdated(key.id); - return true; - } else { - checkErr(gpgmeError); - return false; - } - } - - gpgme_ctx_t GpgME::GpgContext::create_ctx() { - gpgme_ctx_t ctx; - err = gpgme_new(&ctx); - checkErr(err); - - gpgme_set_armor(ctx, 1); - gpgme_set_passphrase_cb(ctx, passphraseCb, this); - return ctx; - } - - -} |