From 5fbecb9533a5584d20a2b76f5816e58c2ffbb6f6 Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
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<std::vector<std::vector<std::string>>, libdnf::ModulePackageContainer:
std::vector<libdnf::ModulePackage *> requiresModuleEnablement(DnfSack * sack, const libdnf::PackageSet * installSet);
-/**
- * @brief Return fingerprint of installed RPMs.
- * The format is <count>:<hash>.
- * <count> is a count of installed RPMs.
- * <hash> 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<std::vector<std::vector<std::string>>, 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<std::string> 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 <count>:<hash> 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 <rpm/rpmdb.h>
#include <rpm/rpmlib.h>
#include <rpm/rpmlog.h>
#include <rpm/rpmts.h>
@@ -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<char, decltype(free)*> 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 <jrohel@redhat.com>
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 <cstring>
-
-#include <iomanip>
-#include <sstream>
-
-#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<digestLength; i++) {
- ss << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(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 <string>
-#include <openssl/sha.h>
-#include <openssl/evp.h>
-
-
-/*
-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