diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/GpgContext.cpp | 134 | ||||
-rw-r--r-- | src/core/GpgContext.h | 2 | ||||
-rw-r--r-- | src/core/GpgCoreInit.cpp | 89 | ||||
-rw-r--r-- | src/core/function/ArchiveFileOperator.cpp | 15 | ||||
-rw-r--r-- | src/core/function/CharsetOperator.cpp | 6 | ||||
-rw-r--r-- | src/core/function/aes/aes_ssl_cbc.cpp | 4 | ||||
-rw-r--r-- | src/core/model/GpgData.cpp | 3 | ||||
-rw-r--r-- | src/core/thread/Task.cpp | 2 |
8 files changed, 187 insertions, 68 deletions
diff --git a/src/core/GpgContext.cpp b/src/core/GpgContext.cpp index a5213134..f8dbebc6 100644 --- a/src/core/GpgContext.cpp +++ b/src/core/GpgContext.cpp @@ -40,8 +40,10 @@ #include "core/GpgModel.h" #include "core/common/CoreCommonUtil.h" #include "core/function/CoreSignalStation.h" +#include "core/function/GlobalSettingStation.h" #include "core/function/gpg/GpgCommandExecutor.h" #include "core/thread/TaskRunnerGetter.h" +#include "spdlog/spdlog.h" #include "thread/Task.h" #ifdef _WIN32 @@ -58,20 +60,12 @@ GpgContext::GpgContext(int channel) * Set up gpgme-context, set paths to app-run path */ GpgContext::GpgContext(const GpgContextInitArgs &args) : args_(args) { - static bool _first = true; - - if (_first) { - /* Initialize the locale environment. */ - SPDLOG_DEBUG("locale: {}", setlocale(LC_CTYPE, nullptr)); - info_.GpgMEVersion = gpgme_check_version(nullptr); - gpgme_set_locale(nullptr, LC_CTYPE, setlocale(LC_CTYPE, nullptr)); -#ifdef LC_MESSAGES - gpgme_set_locale(nullptr, LC_MESSAGES, setlocale(LC_MESSAGES, nullptr)); -#endif - _first = false; - } - gpgme_ctx_t _p_ctx; + + // get gpgme library version + info_.GpgMEVersion = gpgme_check_version(nullptr); + + // create a new context check_gpg_error(gpgme_new(&_p_ctx)); _ctx_ref = CtxRefHandler(_p_ctx); @@ -83,6 +77,17 @@ GpgContext::GpgContext(const GpgContextInitArgs &args) : args_(args) { assert(check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR); } + // set context offline mode + SPDLOG_DEBUG("gpg context offline mode: {}", args_.offline_mode); + gpgme_set_offline(_ctx_ref.get(), args_.offline_mode ? 1 : 0); + + // set option auto import missing key + // invalid at offline mode + SPDLOG_DEBUG("gpg context auto import missing key: {}", args_.offline_mode); + if (!args.offline_mode && args.auto_import_missing_key) + check_gpg_error(gpgme_set_ctx_flag(_ctx_ref.get(), "auto-key-import", "1")); + + // get engine info auto engine_info = gpgme_ctx_get_engine_info(*this); // Check ENV before running bool check_passed = false, find_openpgp = false, find_gpgconf = false, @@ -219,8 +224,22 @@ void GpgContext::post_init_ctx() { // preload info auto &info = GetInfo(); - // listen passphrase input event - SetPassphraseCb(custom_passphrase_cb); + auto &settings = GlobalSettingStation::GetInstance().GetUISettings(); + + bool use_pinentry_as_password_input_dialog = false; + try { + use_pinentry_as_password_input_dialog = + settings.lookup("general.use_pinentry_as_password_input_dialog"); + } catch (...) { + SPDLOG_ERROR( + "setting operation error: use_pinentry_as_password_input_dialog"); + } + + // use custom qt dialog to replace pinentry + if (!use_pinentry_as_password_input_dialog) { + SetPassphraseCb(custom_passphrase_cb); + } + connect(this, &GpgContext::SignalNeedUserInputPassphrase, CoreSignalStation::GetInstance(), &CoreSignalStation::SignalNeedUserInputPassphrase); @@ -372,6 +391,16 @@ const GpgInfo &GpgContext::GetInfo(bool refresh) { auto component_name = info_split_list[0]; auto component_desc = info_split_list[1]; auto component_path = info_split_list[2]; + + boost::algorithm::trim(component_name); + boost::algorithm::trim(component_desc); + boost::algorithm::trim(component_path); + +#ifdef WINDOWS + // replace some special substrings on windows platform + boost::replace_all(component_path, "%3a", ":"); +#endif + auto binary_checksum = check_binary_chacksum(component_path); SPDLOG_DEBUG( @@ -386,13 +415,13 @@ const GpgInfo &GpgContext::GetInfo(bool refresh) { version = info_.GnupgVersion; } if (component_name == "gpg-agent") { - info_.GpgAgentPath = info_split_list[2]; + info_.GpgAgentPath = component_path; } if (component_name == "dirmngr") { - info_.DirmngrPath = info_split_list[2]; + info_.DirmngrPath = component_path; } if (component_name == "keyboxd") { - info_.KeyboxdPath = info_split_list[2]; + info_.KeyboxdPath = component_path; } { @@ -436,16 +465,25 @@ const GpgInfo &GpgContext::GetInfo(bool refresh) { if (info_split_list.size() != 2) continue; + auto configuration_name = info_split_list[0]; + auto configuration_value = info_split_list[1]; + boost::algorithm::trim(configuration_name); + boost::algorithm::trim(configuration_value); + +#ifdef WINDOWS + // replace some special substrings on windows platform + boost::replace_all(configuration_value, "%3a", ":"); +#endif + // record gnupg home path - if (info_split_list[0] == "homedir") { + if (configuration_name == "homedir") { info_.GnuPGHomePath = info_split_list[1]; } - auto configuration_name = info_split_list[0]; { // try lock std::unique_lock lock(info_.Lock); - configurations_info[configuration_name] = {info_split_list[1]}; + configurations_info[configuration_name] = {configuration_value}; } } }); @@ -489,12 +527,19 @@ const GpgInfo &GpgContext::GetInfo(bool refresh) { if (info_split_list.size() != 6) continue; auto configuration_name = info_split_list[0]; + boost::algorithm::trim(configuration_name); { // try lock std::unique_lock lock(info_.Lock); options_info[configuration_name] = { info_split_list[1], info_split_list[2], info_split_list[3], info_split_list[4], info_split_list[5]}; + + boost::algorithm::trim(options_info[configuration_name][0]); + boost::algorithm::trim(options_info[configuration_name][1]); + boost::algorithm::trim(options_info[configuration_name][2]); + boost::algorithm::trim(options_info[configuration_name][3]); + boost::algorithm::trim(options_info[configuration_name][4]); } } }); @@ -540,6 +585,7 @@ const GpgInfo &GpgContext::GetInfo(bool refresh) { if (info_split_list.size() != 10) continue; auto configuration_name = info_split_list[0]; + boost::algorithm::trim(configuration_name); { // try lock std::unique_lock lock(info_.Lock); @@ -547,6 +593,25 @@ const GpgInfo &GpgContext::GetInfo(bool refresh) { info_split_list[1], info_split_list[2], info_split_list[3], info_split_list[4], info_split_list[5], info_split_list[6], info_split_list[7], info_split_list[8], info_split_list[9]}; + + boost::algorithm::trim( + available_options_info[configuration_name][0]); + boost::algorithm::trim( + available_options_info[configuration_name][1]); + boost::algorithm::trim( + available_options_info[configuration_name][2]); + boost::algorithm::trim( + available_options_info[configuration_name][3]); + boost::algorithm::trim( + available_options_info[configuration_name][4]); + boost::algorithm::trim( + available_options_info[configuration_name][5]); + boost::algorithm::trim( + available_options_info[configuration_name][6]); + boost::algorithm::trim( + available_options_info[configuration_name][7]); + boost::algorithm::trim( + available_options_info[configuration_name][8]); } } }); @@ -561,20 +626,33 @@ const GpgInfo &GpgContext::GetInfo(bool refresh) { std::optional<std::string> GpgContext::check_binary_chacksum( std::filesystem::path path) { - QFile f(QString::fromStdString(path.u8string())); - if (!f.open(QFile::ReadOnly)) return {}; + // check file info and access rights + QFileInfo info(QString::fromStdString(path.u8string())); + if (!info.exists() || !info.isFile() || !info.isReadable()) { + SPDLOG_ERROR("get info for file {} error, exists: {}", + info.filePath().toStdString(), info.exists()); + return {}; + } + + // open and read file + QFile f(info.filePath()); + if (!f.open(QIODevice::ReadOnly)) { + SPDLOG_ERROR("open {} to calculate check sum error: {}", path.u8string(), + f.errorString().toStdString()); + return {}; + } // read all data from file auto buffer = f.readAll(); f.close(); - auto hash_md5 = QCryptographicHash(QCryptographicHash::Md5); + auto hash_sha = QCryptographicHash(QCryptographicHash::Sha256); // md5 - hash_md5.addData(buffer); - auto md5 = hash_md5.result().toHex().toStdString(); - SPDLOG_DEBUG("md5 {}", md5); + hash_sha.addData(buffer); + auto sha = hash_sha.result().toHex().toStdString(); + SPDLOG_DEBUG("checksum for file {} is {}", path.u8string(), sha); - return md5.substr(0, 6); + return sha.substr(0, 6); } void GpgContext::_ctx_ref_deleter::operator()(gpgme_ctx_t _ctx) { diff --git a/src/core/GpgContext.h b/src/core/GpgContext.h index 384271a6..2ff87e6b 100644 --- a/src/core/GpgContext.h +++ b/src/core/GpgContext.h @@ -51,6 +51,8 @@ struct GpgContextInitArgs { std::string gpg_path = {}; bool test_mode = false; bool ascii = true; + bool offline_mode = false; + bool auto_import_missing_key = false; GpgContextInitArgs() = default; }; diff --git a/src/core/GpgCoreInit.cpp b/src/core/GpgCoreInit.cpp index 840b2b87..9395bac7 100644 --- a/src/core/GpgCoreInit.cpp +++ b/src/core/GpgCoreInit.cpp @@ -36,6 +36,10 @@ #include "core/GpgContext.h" #include "core/function/GlobalSettingStation.h" #include "function/gpg/GpgAdvancedOperator.h" +#include "spdlog/spdlog.h" +#include "thread/Task.h" +#include "thread/TaskRunner.h" +#include "thread/TaskRunnerGetter.h" namespace GpgFrontend { @@ -93,12 +97,38 @@ void ShutdownCoreLoggingSystem() { void ResetGpgFrontendCore() { reset_gpgfrontend_core(); } void init_gpgfrontend_core() { - // read from settings file + /* Initialize the locale environment. */ + SPDLOG_DEBUG("locale: {}", setlocale(LC_CTYPE, nullptr)); + // init gpgme subsystem + gpgme_check_version(nullptr); + gpgme_set_locale(nullptr, LC_CTYPE, setlocale(LC_CTYPE, nullptr)); +#ifdef LC_MESSAGES + gpgme_set_locale(nullptr, LC_MESSAGES, setlocale(LC_MESSAGES, nullptr)); +#endif + + // get settings + auto& settings = GlobalSettingStation::GetInstance().GetUISettings(); + + // read settings + bool forbid_all_gnupg_connection = false; + try { + forbid_all_gnupg_connection = + settings.lookup("network.forbid_all_gnupg_connection"); + } catch (...) { + SPDLOG_ERROR("setting operation error: forbid_all_gnupg_connection"); + } + + bool auto_import_missing_key = false; + try { + auto_import_missing_key = + settings.lookup("network.auto_import_missing_key"); + } catch (...) { + SPDLOG_ERROR("setting operation error: auto_import_missing_key"); + } + // read from settings file bool use_custom_key_database_path = false; try { - auto& settings = - GpgFrontend::GlobalSettingStation::GetInstance().GetUISettings(); use_custom_key_database_path = settings.lookup("general.use_custom_key_database_path"); } catch (...) { @@ -110,8 +140,6 @@ void init_gpgfrontend_core() { std::string custom_key_database_path; try { - auto& settings = - GpgFrontend::GlobalSettingStation::GetInstance().GetUISettings(); custom_key_database_path = static_cast<std::string>( settings.lookup("general.custom_key_database_path")); @@ -123,7 +151,7 @@ void init_gpgfrontend_core() { custom_key_database_path); // init default channel - GpgFrontend::GpgContext::CreateInstance( + auto& default_ctx = GpgFrontend::GpgContext::CreateInstance( GPGFRONTEND_DEFAULT_CHANNEL, [=]() -> std::unique_ptr<ChannelObject> { GpgFrontend::GpgContextInitArgs args; @@ -132,23 +160,46 @@ void init_gpgfrontend_core() { args.db_path = custom_key_database_path; } - return std::unique_ptr<ChannelObject>(new GpgContext(args)); - }); - - // init non-ascii channel - GpgFrontend::GpgContext::CreateInstance( - GPGFRONTEND_NON_ASCII_CHANNEL, [=]() -> std::unique_ptr<ChannelObject> { - GpgFrontend::GpgContextInitArgs args; - args.ascii = false; - - // set key database path - if (use_custom_key_database_path && !custom_key_database_path.empty()) { - args.db_path = custom_key_database_path; - } + args.offline_mode = forbid_all_gnupg_connection; + args.auto_import_missing_key = auto_import_missing_key; return std::unique_ptr<ChannelObject>(new GpgContext(args)); }); + // exit if failed + if (!default_ctx.good()) { + SPDLOG_ERROR("default gpgme context init error, exit."); + QCoreApplication::exit(); + }; + + // async init no-ascii channel + Thread::TaskRunnerGetter::GetInstance() + .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_GPG) + ->PostTask( + new Thread::Task([=](Thread::Task::DataObjectPtr data_obj) -> int { + // init non-ascii channel + auto& ctx = GpgFrontend::GpgContext::CreateInstance( + GPGFRONTEND_NON_ASCII_CHANNEL, + [=]() -> std::unique_ptr<ChannelObject> { + GpgFrontend::GpgContextInitArgs args; + args.ascii = false; + + // set key database path + if (use_custom_key_database_path && + !custom_key_database_path.empty()) { + args.db_path = custom_key_database_path; + } + + args.offline_mode = forbid_all_gnupg_connection; + args.auto_import_missing_key = auto_import_missing_key; + + return std::unique_ptr<ChannelObject>(new GpgContext(args)); + }); + if (!ctx.good()) SPDLOG_ERROR("no-ascii channel init error"); + + return ctx.good() ? 0 : -1; + })); + // try to restart all components GpgFrontend::GpgAdvancedOperator::GetInstance().RestartGpgComponents(); } diff --git a/src/core/function/ArchiveFileOperator.cpp b/src/core/function/ArchiveFileOperator.cpp index 04c9326f..8aad0500 100644 --- a/src/core/function/ArchiveFileOperator.cpp +++ b/src/core/function/ArchiveFileOperator.cpp @@ -136,8 +136,6 @@ void GpgFrontend::ArchiveFileOperator::CreateArchive( } for (;;) { - bool needcr = false; - entry = archive_entry_new(); r = archive_read_next_header2(disk, entry); @@ -149,15 +147,6 @@ void GpgFrontend::ArchiveFileOperator::CreateArchive( } archive_read_disk_descend(disk); -#ifdef WINDOWS - auto entry_path = - QString::fromStdWString(std::wstring(archive_entry_pathname_w(entry))) - .toUtf8() - .toStdString(); -#else - auto entry_path = std::string(archive_entry_pathname_utf8(entry)); -#endif - SPDLOG_DEBUG("Adding: {} size: {} bytes: {} file type: {}", archive_entry_pathname_utf8(entry), archive_entry_size(entry), archive_entry_filetype(entry)); @@ -201,7 +190,6 @@ void GpgFrontend::ArchiveFileOperator::ExtractArchive( struct archive *a; struct archive *ext; struct archive_entry *entry; - int r; a = archive_read_new(); ext = archive_write_disk_new(); @@ -241,8 +229,9 @@ void GpgFrontend::ArchiveFileOperator::ExtractArchive( archive_error_string(a)); throw std::runtime_error("archive_read_open_filename() failed"); } + for (;;) { - r = archive_read_next_header(a, &entry); + int r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) break; if (r != ARCHIVE_OK) { SPDLOG_ERROR("archive_read_next_header() failed: {}", diff --git a/src/core/function/CharsetOperator.cpp b/src/core/function/CharsetOperator.cpp index 0e40e317..72c5e72b 100644 --- a/src/core/function/CharsetOperator.cpp +++ b/src/core/function/CharsetOperator.cpp @@ -117,12 +117,10 @@ bool GpgFrontend::CharsetOperator::Convert2Utf8(const std::string &buffer, if (status == U_BUFFER_OVERFLOW_ERROR) { status = U_ZERO_ERROR; - target_limit = target_capacity + 1; out_buffer.clear(); out_buffer.resize(target_capacity); - target_capacity = - ucnv_convert(from_encode.c_str(), to_encode.c_str(), out_buffer.data(), - out_buffer.size(), buffer.data(), buffer.size(), &status); + ucnv_convert(from_encode.c_str(), to_encode.c_str(), out_buffer.data(), + out_buffer.size(), buffer.data(), buffer.size(), &status); } if (U_FAILURE(status)) { diff --git a/src/core/function/aes/aes_ssl_cbc.cpp b/src/core/function/aes/aes_ssl_cbc.cpp index 88a54baa..3aa80ef5 100644 --- a/src/core/function/aes/aes_ssl_cbc.cpp +++ b/src/core/function/aes/aes_ssl_cbc.cpp @@ -59,7 +59,7 @@ uint8_t *aes_256_cbc_encrypt(EVP_CIPHER_CTX *e, uint8_t *plaintext, int *len) { /* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE -1 * bytes */ int c_len = *len + AES_BLOCK_SIZE, f_len = 0; - auto *ciphertext = (uint8_t *)malloc(c_len); + auto *ciphertext = static_cast<uint8_t *>(malloc(c_len)); /* allows reusing of 'e' for multiple encryption cycles */ EVP_EncryptInit_ex(e, nullptr, nullptr, nullptr, nullptr); @@ -86,7 +86,7 @@ uint8_t *aes_256_cbc_encrypt(EVP_CIPHER_CTX *e, uint8_t *plaintext, int *len) { uint8_t *aes_256_cbc_decrypt(EVP_CIPHER_CTX *e, uint8_t *ciphertext, int *len) { /* plaintext will always be equal to or lesser than length of ciphertext*/ int p_len = *len, f_len = 0; - auto *plaintext = (uint8_t *)malloc(p_len); + auto *plaintext = static_cast<uint8_t *>(malloc(p_len)); EVP_DecryptInit_ex(e, nullptr, nullptr, nullptr, nullptr); EVP_DecryptUpdate(e, plaintext, &p_len, ciphertext, *len); diff --git a/src/core/model/GpgData.cpp b/src/core/model/GpgData.cpp index 5aa95dc6..05f61a46 100644 --- a/src/core/model/GpgData.cpp +++ b/src/core/model/GpgData.cpp @@ -40,7 +40,8 @@ GpgFrontend::GpgData::GpgData() { GpgFrontend::GpgData::GpgData(void* buffer, size_t size, bool copy) { gpgme_data_t data; - auto err = gpgme_data_new_from_mem(&data, (const char*)buffer, size, copy); + auto err = gpgme_data_new_from_mem(&data, static_cast<const char*>(buffer), + size, copy); assert(gpgme_err_code(err) == GPG_ERR_NO_ERROR); data_ref_ = std::unique_ptr<struct gpgme_data, _data_ref_deleter>(data); diff --git a/src/core/thread/Task.cpp b/src/core/thread/Task.cpp index f3c6ae86..7173b69e 100644 --- a/src/core/thread/Task.cpp +++ b/src/core/thread/Task.cpp @@ -218,7 +218,7 @@ void GpgFrontend::Thread::Task::DataObject::free_heap_ptr(Destructor *ptr) { if (ptr->destroy != nullptr) { ptr->destroy(ptr->p_obj); } - free((void *)ptr->p_obj); + free(const_cast<void *>(ptr->p_obj)); delete ptr; } |