From 5fbecb9533a5584d20a2b76f5816e58c2ffbb6f6 Mon Sep 17 00:00:00 2001 From: Jaroslav Rohel Date: Wed, 2 Feb 2022 08:45:36 +0100 Subject: [PATCH 1/2] Use `rpmdbCookie` from librpm, remove `hawkey.Sack._rpmdb_version` `dnf_sack_get_rpmdb_version` function that computed the hash of installed packages was removed. `rpmdbCookie` function from librpm is used in context part of libdnf instead. The private Python function `hawkey.Sack._rpmdb_version()` was removed too. It was used by DNF. The new version of DNF uses `rpm.TransactionSet.dbCookie()` function from librpm, which wraps the `rpmdbCookie` function. So the same librpm function will be used in context part of libdnf (e.g. by microdnf) and in the DNF. `rpmdbCookie` funkcion is safer. It also detect reinstalation of package as a change. That will be needed in the future to determining if the libsolv cache is still valid. It also solves the libdnf problem with SHA1 in FIPS mode. = changelog = msg: Use `rpmdbCookie` from librpm, remove `hawkey.Sack._rpmdb_version` type: bugfix related: https://bugzilla.redhat.com/show_bug.cgi?id=2043476 --- libdnf/dnf-sack-private.hpp | 15 ------------ libdnf/dnf-sack.cpp | 40 ------------------------------- libdnf/dnf-transaction.cpp | 48 +++++++++++++++++++++---------------- python/hawkey/sack-py.cpp | 8 ------- 4 files changed, 27 insertions(+), 84 deletions(-) diff --git a/libdnf/dnf-sack-private.hpp b/libdnf/dnf-sack-private.hpp index 89873534..2db96320 100644 --- a/libdnf/dnf-sack-private.hpp +++ b/libdnf/dnf-sack-private.hpp @@ -81,19 +81,4 @@ std::pair>, libdnf::ModulePackageContainer: std::vector requiresModuleEnablement(DnfSack * sack, const libdnf::PackageSet * installSet); -/** - * @brief Return fingerprint of installed RPMs. - * The format is :. - * is a count of installed RPMs. - * is a sha1 hash of sorted sha1hdr hashes of installed RPMs. - * - * The count can be computed from the command line by running: - * rpm -qa --qf='%{name}\n' | grep -v '^gpg-pubkey$' | wc -l - * - * The hash can be computed from the command line by running: - * rpm -qa --qf='%{name} %{sha1header}\n' | grep -v '^gpg-pubkey ' \ - * | cut -d ' ' -f 2 | LC_ALL=C sort | tr -d '\n' | sha1sum - */ -std::string dnf_sack_get_rpmdb_version(DnfSack *sack); - #endif // HY_SACK_INTERNAL_H diff --git a/libdnf/dnf-sack.cpp b/libdnf/dnf-sack.cpp index a88e8a1c..13977730 100644 --- a/libdnf/dnf-sack.cpp +++ b/libdnf/dnf-sack.cpp @@ -80,7 +80,6 @@ extern "C" { #include "module/ModulePackage.hpp" #include "repo/Repo-private.hpp" #include "repo/solvable/DependencyContainer.hpp" -#include "utils/crypto/sha1.hpp" #include "utils/File.hpp" #include "utils/utils.hpp" #include "log.hpp" @@ -2535,42 +2534,3 @@ std::pair>, libdnf::ModulePackageContainer: setModuleExcludes(sack, hotfixRepos, *moduleContainer); return ret; } - -std::string dnf_sack_get_rpmdb_version(DnfSack *sack) { - // collect all sha1hdr checksums - // they are sufficiently unique IDs that represent installed RPMs - std::vector checksums; - - // iterate all @System repo RPMs (rpmdb records) - libdnf::Query query{sack, libdnf::Query::ExcludeFlags::IGNORE_EXCLUDES}; - query.installed(); - - auto pset = query.getResultPset(); - Id id = -1; - while(true) { - id = pset->next(id); - if (id == -1) { - break; - } - DnfPackage *pkg = dnf_package_new(sack, id); - // store pkgid (equals to sha1hdr) - checksums.push_back(libdnf::string::fromCstring(dnf_package_get_pkgid(pkg))); - g_object_unref(pkg); - } - - // sort checksums to compute the output checksum always the same - std::sort(checksums.begin(), checksums.end()); - - SHA1Hash h; - for (auto & checksum : checksums) { - h.update(checksum.c_str()); - } - - // build : output - std::ostringstream result; - result << checksums.size(); - result << ":"; - result << h.hexdigest(); - - return result.str(); -} diff --git a/libdnf/dnf-transaction.cpp b/libdnf/dnf-transaction.cpp index e0966582..d93c5ec6 100644 --- a/libdnf/dnf-transaction.cpp +++ b/libdnf/dnf-transaction.cpp @@ -28,6 +28,7 @@ * This object represents an RPM transaction. */ +#include #include #include #include @@ -53,6 +54,7 @@ #include "transaction/Swdb.hpp" #include "transaction/Transformer.hpp" #include "utils/bgettext/bgettext-lib.h" +#include "utils/utils.hpp" typedef enum { DNF_TRANSACTION_STEP_STARTED, @@ -1136,9 +1138,8 @@ dnf_transaction_commit(DnfTransaction *transaction, HyGoal goal, DnfState *state libdnf::Swdb *swdb = priv->swdb; PluginHookContextTransactionData data{PLUGIN_HOOK_ID_CONTEXT_PRE_TRANSACTION, transaction, goal, state}; DnfSack * sack = hy_goal_get_sack(goal); - DnfSack * rpmdb_version_sack = NULL; - std::string rpmdb_begin; - std::string rpmdb_end; + std::unique_ptr rpmdb_cookie_uptr{nullptr, free}; + std::string rpmdb_cookie; /* take lock */ ret = dnf_state_take_lock(state, DNF_LOCK_TYPE_RPMDB, DNF_LOCK_MODE_PROCESS, error); @@ -1431,17 +1432,24 @@ dnf_transaction_commit(DnfTransaction *transaction, HyGoal goal, DnfState *state if (!dnf_context_plugin_hook(priv->context, PLUGIN_HOOK_ID_CONTEXT_PRE_TRANSACTION, &data, nullptr)) goto out; - // FIXME get commandline - if (sack) { - rpmdb_begin = dnf_sack_get_rpmdb_version(sack); - } else { - // if sack is not available, create a custom instance - rpmdb_version_sack = dnf_sack_new(); - dnf_sack_load_system_repo(rpmdb_version_sack, nullptr, DNF_SACK_LOAD_FLAG_NONE, nullptr); - rpmdb_begin = dnf_sack_get_rpmdb_version(rpmdb_version_sack); - g_object_unref(rpmdb_version_sack); + // Open rpm database if it is not already open + if (!rpmtsGetRdb(priv->ts)) { + rc = rpmtsOpenDB(priv->ts, rpmtsGetDBMode(priv->ts)); + if (rc != 0) { + ret = FALSE; + g_set_error( + error, DNF_ERROR, DNF_ERROR_INTERNAL_ERROR, _("Error %i opening rpm database"), rc); + goto out; + } } - swdb->beginTransaction(_get_current_time(), rpmdb_begin, "", priv->uid); + + rpmdb_cookie_uptr.reset(rpmdbCookie(rpmtsGetRdb(priv->ts))); + rpmdb_cookie = libdnf::string::fromCstring(rpmdb_cookie_uptr.get()); + if (rpmdb_cookie.empty()) { + g_critical(_("The rpmdbCookie() function did not return cookie of rpm database.")); + } + // FIXME get commandline + swdb->beginTransaction(_get_current_time(), rpmdb_cookie, "", priv->uid); /* run the transaction */ priv->state = dnf_state_get_child(state); @@ -1481,14 +1489,12 @@ dnf_transaction_commit(DnfTransaction *transaction, HyGoal goal, DnfState *state if (!ret) goto out; - // finalize swdb transaction - // always load a new sack with rpmdb state after the transaction - rpmdb_version_sack = dnf_sack_new(); - dnf_sack_load_system_repo(rpmdb_version_sack, nullptr, DNF_SACK_LOAD_FLAG_NONE, nullptr); - rpmdb_end = dnf_sack_get_rpmdb_version(rpmdb_version_sack); - g_object_unref(rpmdb_version_sack); - - swdb->endTransaction(_get_current_time(), rpmdb_end.c_str(), libdnf::TransactionState::DONE); + rpmdb_cookie_uptr.reset(rpmdbCookie(rpmtsGetRdb(priv->ts))); + rpmdb_cookie = libdnf::string::fromCstring(rpmdb_cookie_uptr.get()); + if (rpmdb_cookie.empty()) { + g_critical(_("The rpmdbCookie() function did not return cookie of rpm database.")); + } + swdb->endTransaction(_get_current_time(), rpmdb_cookie, libdnf::TransactionState::DONE); swdb->closeTransaction(); data.hookId = PLUGIN_HOOK_ID_CONTEXT_TRANSACTION; diff --git a/python/hawkey/sack-py.cpp b/python/hawkey/sack-py.cpp index 4de499cb..fcb5cd61 100644 --- a/python/hawkey/sack-py.cpp +++ b/python/hawkey/sack-py.cpp @@ -783,13 +783,6 @@ load_repo(_SackObject *self, PyObject *args, PyObject *kwds) try Py_RETURN_NONE; } CATCH_TO_PYTHON -static PyObject * -rpmdb_version(_SackObject *self, PyObject *unused) try -{ - auto result = dnf_sack_get_rpmdb_version(self->sack); - return PyString_FromString(result.c_str()); -} CATCH_TO_PYTHON - static Py_ssize_t len(_SackObject *self) try { @@ -858,7 +851,6 @@ PyMethodDef sack_methods[] = { METH_VARARGS | METH_KEYWORDS, NULL}, {"load_repo", (PyCFunction)load_repo, METH_VARARGS | METH_KEYWORDS, NULL}, - {"_rpmdb_version", (PyCFunction)rpmdb_version, METH_VARARGS | METH_KEYWORDS, NULL}, {NULL} /* sentinel */ }; -- 2.34.1 From 3dae1fd8754ec9521e16e2e11a7c4bf2c81bbb02 Mon Sep 17 00:00:00 2001 From: Jaroslav Rohel Date: Wed, 2 Feb 2022 18:00:39 +0100 Subject: [PATCH 2/2] Remove class `SHA1Hash`, which is no longer used, remove OpenSSL require The class was used by the `dnf_sack_get_rpmdb_version` function, which was removed. The `rpmdbCookie` function from librpm is used instead. --- CMakeLists.txt | 1 - libdnf.spec | 1 - libdnf/CMakeLists.txt | 1 - libdnf/utils/CMakeLists.txt | 1 - libdnf/utils/crypto/CMakeLists.txt | 5 ----- libdnf/utils/crypto/sha1.cpp | 36 ------------------------------ libdnf/utils/crypto/sha1.hpp | 25 --------------------- 7 files changed, 70 deletions(-) delete mode 100644 libdnf/utils/crypto/CMakeLists.txt delete mode 100644 libdnf/utils/crypto/sha1.cpp delete mode 100644 libdnf/utils/crypto/sha1.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 60cf1b8c..7149b9e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,7 +52,6 @@ endif() # build dependencies find_package(Gpgme REQUIRED) find_package(LibSolv 0.6.30 REQUIRED COMPONENTS ext) -find_package(OpenSSL REQUIRED) # build dependencies via pkg-config diff --git a/libdnf.spec b/libdnf.spec index 697911f0..89d2fb40 100644 --- a/libdnf.spec +++ b/libdnf.spec @@ -83,7 +83,6 @@ BuildRequires: pkgconfig(zck) >= 0.9.11 BuildRequires: pkgconfig(sqlite3) BuildRequires: pkgconfig(json-c) BuildRequires: pkgconfig(cppunit) -BuildRequires: pkgconfig(libcrypto) BuildRequires: pkgconfig(modulemd-2.0) >= %{libmodulemd_version} BuildRequires: pkgconfig(smartcols) BuildRequires: gettext diff --git a/libdnf/CMakeLists.txt b/libdnf/CMakeLists.txt index 998a6f94..9e71d139 100644 --- a/libdnf/CMakeLists.txt +++ b/libdnf/CMakeLists.txt @@ -75,7 +75,6 @@ target_link_libraries(libdnf ${GLIB_GIO_UNIX_LIBRARIES} ${LIBSOLV_LIBRARY} ${LIBSOLV_EXT_LIBRARY} - ${OPENSSL_CRYPTO_LIBRARY} ${RPM_LIBRARIES} ${SCOLS_LIBRARIES} ${SQLite3_LIBRARIES} diff --git a/libdnf/utils/CMakeLists.txt b/libdnf/utils/CMakeLists.txt index 71a1042c..4ec456ef 100644 --- a/libdnf/utils/CMakeLists.txt +++ b/libdnf/utils/CMakeLists.txt @@ -1,5 +1,4 @@ add_subdirectory(bgettext) -add_subdirectory(crypto) add_subdirectory(iniparser) add_subdirectory(regex) add_subdirectory(sqlite3) diff --git a/libdnf/utils/crypto/CMakeLists.txt b/libdnf/utils/crypto/CMakeLists.txt deleted file mode 100644 index 149d100c..00000000 --- a/libdnf/utils/crypto/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -set(UTILS_SOURCES - ${UTILS_SOURCES} - ${CMAKE_CURRENT_SOURCE_DIR}/sha1.cpp - PARENT_SCOPE -) diff --git a/libdnf/utils/crypto/sha1.cpp b/libdnf/utils/crypto/sha1.cpp deleted file mode 100644 index 1533ee6b..00000000 --- a/libdnf/utils/crypto/sha1.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include - -#include -#include - -#include "sha1.hpp" - - -SHA1Hash::SHA1Hash() -{ - md_ctx = EVP_MD_CTX_new(); - EVP_DigestInit_ex(md_ctx, EVP_sha1(), NULL); -} - - -void -SHA1Hash::update(const char * data) -{ - EVP_DigestUpdate(md_ctx, data, strlen(data)); -} - - -std::string -SHA1Hash::hexdigest() -{ - unsigned char md[digestLength]; - EVP_DigestFinal_ex(md_ctx, md, NULL); - - std::stringstream ss; - for(int i=0; i(md[i]); - } - - EVP_MD_CTX_free(md_ctx); - return ss.str(); -} diff --git a/libdnf/utils/crypto/sha1.hpp b/libdnf/utils/crypto/sha1.hpp deleted file mode 100644 index 9f1dfdeb..00000000 --- a/libdnf/utils/crypto/sha1.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include -#include - - -/* -USAGE: - -SHA1Hash h; -h.update("foo"); -h.update("bar"); -std::cout << h.hexdigest() << std::endl; -*/ - - -class SHA1Hash { -public: - SHA1Hash(); - void update(const char *data); - std::string hexdigest(); - static constexpr int digestLength = SHA_DIGEST_LENGTH; - -private: - EVP_MD_CTX *md_ctx; -}; -- 2.34.1