|
|
7d8bc5 |
From b2ded5a4da58940159f5d337e9e29c5de5cc0f7a Mon Sep 17 00:00:00 2001
|
|
|
7d8bc5 |
From: Colin Walters <walters@verbum.org>
|
|
|
7d8bc5 |
Date: Thu, 2 Feb 2017 10:00:06 -0500
|
|
|
7d8bc5 |
Subject: [PATCH 1/2] repo: Enable GPG by default
|
|
|
7d8bc5 |
|
|
|
7d8bc5 |
This increases compatibility with dnf/yum. It was very surprising to me that we
|
|
|
7d8bc5 |
didn't do this. Most repos do seem to use `gpgcheck=1`, but I'm fairly certain
|
|
|
7d8bc5 |
I've seen repo configs in the wild that actually depend on it, though after
|
|
|
7d8bc5 |
looking at a few (ceph, postgres), I can't find one yet.
|
|
|
7d8bc5 |
|
|
|
7d8bc5 |
Still, I think it's worth making this change. I suspect very few people will
|
|
|
7d8bc5 |
edit `/etc/yum/yum.conf` to globally disable GPG checking, versus disabling it
|
|
|
7d8bc5 |
per repository.
|
|
|
7d8bc5 |
---
|
|
|
7d8bc5 |
libdnf/dnf-repo.c | 11 ++++++++++-
|
|
|
7d8bc5 |
1 file changed, 10 insertions(+), 1 deletion(-)
|
|
|
7d8bc5 |
|
|
|
7d8bc5 |
diff --git a/libdnf/dnf-repo.c b/libdnf/dnf-repo.c
|
|
|
7d8bc5 |
index 08e0d8b..017c82d 100644
|
|
|
7d8bc5 |
--- a/libdnf/libdnf/dnf-repo.c
|
|
|
7d8bc5 |
+++ b/libdnf/libdnf/dnf-repo.c
|
|
|
7d8bc5 |
@@ -858,7 +858,16 @@ dnf_repo_set_keyfile_data(DnfRepo *repo, GError **error)
|
|
|
7d8bc5 |
/* gpgkey is optional for gpgcheck=1, but required for repo_gpgcheck=1 */
|
|
|
7d8bc5 |
g_free(priv->gpgkey);
|
|
|
7d8bc5 |
priv->gpgkey = g_key_file_get_string(priv->keyfile, priv->id, "gpgkey", NULL);
|
|
|
7d8bc5 |
- priv->gpgcheck_pkgs = dnf_repo_get_boolean(priv->keyfile, priv->id, "gpgcheck", NULL);
|
|
|
7d8bc5 |
+ /* Currently, we don't have a global configuration file. The way this worked in yum
|
|
|
7d8bc5 |
+ * is that the yum package enabled gpgcheck=1 by default in /etc/yum.conf. Basically,
|
|
|
7d8bc5 |
+ * I don't think many people changed that. It's just saner to disable it in the individual
|
|
|
7d8bc5 |
+ * repo files as required. To claim compatibility with yum repository files, I think
|
|
|
7d8bc5 |
+ * we need to basically hard code the yum.conf defaults here.
|
|
|
7d8bc5 |
+ */
|
|
|
7d8bc5 |
+ if (!g_key_file_has_key (priv->keyfile, priv->id, "gpgcheck", NULL))
|
|
|
7d8bc5 |
+ priv->gpgcheck_pkgs = TRUE;
|
|
|
7d8bc5 |
+ else
|
|
|
7d8bc5 |
+ priv->gpgcheck_pkgs = dnf_repo_get_boolean(priv->keyfile, priv->id, "gpgcheck", NULL);
|
|
|
7d8bc5 |
priv->gpgcheck_md = dnf_repo_get_boolean(priv->keyfile, priv->id, "repo_gpgcheck", NULL);
|
|
|
7d8bc5 |
if (priv->gpgcheck_md && priv->gpgkey == NULL) {
|
|
|
7d8bc5 |
g_set_error_literal(error,
|
|
|
7d8bc5 |
--
|
|
|
7d8bc5 |
2.9.3
|
|
|
7d8bc5 |
|
|
|
7d8bc5 |
|
|
|
7d8bc5 |
From 0d68ebac7d39a9278ebb5259c4912efa55c080da Mon Sep 17 00:00:00 2001
|
|
|
7d8bc5 |
From: Colin Walters <walters@verbum.org>
|
|
|
7d8bc5 |
Date: Tue, 31 Jan 2017 17:14:37 -0500
|
|
|
7d8bc5 |
Subject: [PATCH 2/2] transaction: Export parts of the GPG functionality
|
|
|
7d8bc5 |
|
|
|
7d8bc5 |
rpm-ostree doesn't use `dnf_transaction_commit()`, because it uses libostree to
|
|
|
7d8bc5 |
store the RPMs, and bubblewrap to run `%post`s. However, we do need the GPG
|
|
|
7d8bc5 |
functionality.
|
|
|
7d8bc5 |
---
|
|
|
7d8bc5 |
libdnf/libdnf/dnf-transaction.c | 193 ++++++++++++++++++++++++++++-------------------
|
|
|
7d8bc5 |
libdnf/libdnf/dnf-transaction.h | 11 +++
|
|
|
7d8bc5 |
2 files changed, 127 insertions(+), 77 deletions(-)
|
|
|
7d8bc5 |
|
|
|
7d8bc5 |
diff --git a/libdnf/libdnf/dnf-transaction.c b/libdnf/libdnf/dnf-transaction.c
|
|
|
7d8bc5 |
index 62fcc51..dd73245 100644
|
|
|
7d8bc5 |
--- a/libdnf/libdnf/dnf-transaction.c
|
|
|
7d8bc5 |
+++ b/libdnf/libdnf/dnf-transaction.c
|
|
|
7d8bc5 |
@@ -328,17 +328,88 @@ dnf_transaction_ensure_repo_list(DnfTransaction *transaction,
|
|
|
7d8bc5 |
return TRUE;
|
|
|
7d8bc5 |
}
|
|
|
7d8bc5 |
|
|
|
7d8bc5 |
+gboolean
|
|
|
7d8bc5 |
+dnf_transaction_gpgcheck_package (DnfTransaction *transaction,
|
|
|
7d8bc5 |
+ DnfPackage *pkg,
|
|
|
7d8bc5 |
+ GError **error)
|
|
|
7d8bc5 |
+{
|
|
|
7d8bc5 |
+ DnfTransactionPrivate *priv = GET_PRIVATE(transaction);
|
|
|
7d8bc5 |
+ GError *error_local = NULL;
|
|
|
7d8bc5 |
+ DnfRepo *repo;
|
|
|
7d8bc5 |
+ const gchar *fn;
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
+ /* ensure the filename is set */
|
|
|
7d8bc5 |
+ if (!dnf_transaction_ensure_repo(transaction, pkg, error)) {
|
|
|
7d8bc5 |
+ g_prefix_error(error, "Failed to check untrusted: ");
|
|
|
7d8bc5 |
+ return FALSE;
|
|
|
7d8bc5 |
+ }
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
+ /* find the location of the local file */
|
|
|
7d8bc5 |
+ fn = dnf_package_get_filename(pkg);
|
|
|
7d8bc5 |
+ if (fn == NULL) {
|
|
|
7d8bc5 |
+ g_set_error(error,
|
|
|
7d8bc5 |
+ DNF_ERROR,
|
|
|
7d8bc5 |
+ DNF_ERROR_FILE_NOT_FOUND,
|
|
|
7d8bc5 |
+ "Downloaded file for %s not found",
|
|
|
7d8bc5 |
+ dnf_package_get_name(pkg));
|
|
|
7d8bc5 |
+ return FALSE;
|
|
|
7d8bc5 |
+ }
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
+ /* check file */
|
|
|
7d8bc5 |
+ if (!dnf_keyring_check_untrusted_file(priv->keyring, fn, &error_local)) {
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
+ /* probably an i/o error */
|
|
|
7d8bc5 |
+ if (!g_error_matches(error_local,
|
|
|
7d8bc5 |
+ DNF_ERROR,
|
|
|
7d8bc5 |
+ DNF_ERROR_GPG_SIGNATURE_INVALID)) {
|
|
|
7d8bc5 |
+ g_propagate_error(error, error_local);
|
|
|
7d8bc5 |
+ return FALSE;
|
|
|
7d8bc5 |
+ }
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
+ /* if the repo is signed this is ALWAYS an error */
|
|
|
7d8bc5 |
+ repo = dnf_package_get_repo(pkg);
|
|
|
7d8bc5 |
+ if (repo != NULL && dnf_repo_get_gpgcheck(repo)) {
|
|
|
7d8bc5 |
+ g_set_error(error,
|
|
|
7d8bc5 |
+ DNF_ERROR,
|
|
|
7d8bc5 |
+ DNF_ERROR_FILE_INVALID,
|
|
|
7d8bc5 |
+ "package %s cannot be verified "
|
|
|
7d8bc5 |
+ "and repo %s is GPG enabled: %s",
|
|
|
7d8bc5 |
+ dnf_package_get_nevra(pkg),
|
|
|
7d8bc5 |
+ dnf_repo_get_id(repo),
|
|
|
7d8bc5 |
+ error_local->message);
|
|
|
7d8bc5 |
+ g_error_free(error_local);
|
|
|
7d8bc5 |
+ return FALSE;
|
|
|
7d8bc5 |
+ }
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
+ /* we can only install signed packages in this mode */
|
|
|
7d8bc5 |
+ if ((priv->flags & DNF_TRANSACTION_FLAG_ONLY_TRUSTED) > 0) {
|
|
|
7d8bc5 |
+ g_propagate_error(error, error_local);
|
|
|
7d8bc5 |
+ return FALSE;
|
|
|
7d8bc5 |
+ }
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
+ /* we can install unsigned packages */
|
|
|
7d8bc5 |
+ g_warning("ignoring as allow-untrusted: %s",
|
|
|
7d8bc5 |
+ error_local->message);
|
|
|
7d8bc5 |
+ g_clear_error(&error_local);
|
|
|
7d8bc5 |
+ }
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
+ return TRUE;
|
|
|
7d8bc5 |
+}
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
/**
|
|
|
7d8bc5 |
* dnf_transaction_check_untrusted:
|
|
|
7d8bc5 |
+ * @transaction: Transaction
|
|
|
7d8bc5 |
+ * @goal: Target goal
|
|
|
7d8bc5 |
+ * @error: Error
|
|
|
7d8bc5 |
+ *
|
|
|
7d8bc5 |
+ * Verify GPG signatures for all pending packages to be changed as part
|
|
|
7d8bc5 |
+ * of @goal.
|
|
|
7d8bc5 |
*/
|
|
|
7d8bc5 |
-static gboolean
|
|
|
7d8bc5 |
+gboolean
|
|
|
7d8bc5 |
dnf_transaction_check_untrusted(DnfTransaction *transaction,
|
|
|
7d8bc5 |
HyGoal goal,
|
|
|
7d8bc5 |
GError **error)
|
|
|
7d8bc5 |
{
|
|
|
7d8bc5 |
- DnfTransactionPrivate *priv = GET_PRIVATE(transaction);
|
|
|
7d8bc5 |
- DnfPackage *pkg;
|
|
|
7d8bc5 |
- const gchar *fn;
|
|
|
7d8bc5 |
guint i;
|
|
|
7d8bc5 |
g_autoptr(GPtrArray) install = NULL;
|
|
|
7d8bc5 |
|
|
|
7d8bc5 |
@@ -354,64 +425,10 @@ dnf_transaction_check_untrusted(DnfTransaction *transaction,
|
|
|
7d8bc5 |
|
|
|
7d8bc5 |
/* find any packages in untrusted repos */
|
|
|
7d8bc5 |
for (i = 0; i < install->len; i++) {
|
|
|
7d8bc5 |
- GError *error_local = NULL;
|
|
|
7d8bc5 |
- DnfRepo *repo;
|
|
|
7d8bc5 |
- pkg = g_ptr_array_index(install, i);
|
|
|
7d8bc5 |
+ DnfPackage *pkg = g_ptr_array_index(install, i);
|
|
|
7d8bc5 |
|
|
|
7d8bc5 |
- /* ensure the filename is set */
|
|
|
7d8bc5 |
- if (!dnf_transaction_ensure_repo(transaction, pkg, error)) {
|
|
|
7d8bc5 |
- g_prefix_error(error, "Failed to check untrusted: ");
|
|
|
7d8bc5 |
+ if (!dnf_transaction_gpgcheck_package (transaction, pkg, error))
|
|
|
7d8bc5 |
return FALSE;
|
|
|
7d8bc5 |
- }
|
|
|
7d8bc5 |
-
|
|
|
7d8bc5 |
- /* find the location of the local file */
|
|
|
7d8bc5 |
- fn = dnf_package_get_filename(pkg);
|
|
|
7d8bc5 |
- if (fn == NULL) {
|
|
|
7d8bc5 |
- g_set_error(error,
|
|
|
7d8bc5 |
- DNF_ERROR,
|
|
|
7d8bc5 |
- DNF_ERROR_FILE_NOT_FOUND,
|
|
|
7d8bc5 |
- "Downloaded file for %s not found",
|
|
|
7d8bc5 |
- dnf_package_get_name(pkg));
|
|
|
7d8bc5 |
- return FALSE;
|
|
|
7d8bc5 |
- }
|
|
|
7d8bc5 |
-
|
|
|
7d8bc5 |
- /* check file */
|
|
|
7d8bc5 |
- if (!dnf_keyring_check_untrusted_file(priv->keyring, fn, &error_local)) {
|
|
|
7d8bc5 |
-
|
|
|
7d8bc5 |
- /* probably an i/o error */
|
|
|
7d8bc5 |
- if (!g_error_matches(error_local,
|
|
|
7d8bc5 |
- DNF_ERROR,
|
|
|
7d8bc5 |
- DNF_ERROR_GPG_SIGNATURE_INVALID)) {
|
|
|
7d8bc5 |
- g_propagate_error(error, error_local);
|
|
|
7d8bc5 |
- return FALSE;
|
|
|
7d8bc5 |
- }
|
|
|
7d8bc5 |
-
|
|
|
7d8bc5 |
- /* if the repo is signed this is ALWAYS an error */
|
|
|
7d8bc5 |
- repo = dnf_package_get_repo(pkg);
|
|
|
7d8bc5 |
- if (repo != NULL && dnf_repo_get_gpgcheck(repo)) {
|
|
|
7d8bc5 |
- g_set_error(error,
|
|
|
7d8bc5 |
- DNF_ERROR,
|
|
|
7d8bc5 |
- DNF_ERROR_FILE_INVALID,
|
|
|
7d8bc5 |
- "package %s cannot be verified "
|
|
|
7d8bc5 |
- "and repo %s is GPG enabled: %s",
|
|
|
7d8bc5 |
- dnf_package_get_nevra(pkg),
|
|
|
7d8bc5 |
- dnf_repo_get_id(repo),
|
|
|
7d8bc5 |
- error_local->message);
|
|
|
7d8bc5 |
- g_error_free(error_local);
|
|
|
7d8bc5 |
- return FALSE;
|
|
|
7d8bc5 |
- }
|
|
|
7d8bc5 |
-
|
|
|
7d8bc5 |
- /* we can only install signed packages in this mode */
|
|
|
7d8bc5 |
- if ((priv->flags & DNF_TRANSACTION_FLAG_ONLY_TRUSTED) > 0) {
|
|
|
7d8bc5 |
- g_propagate_error(error, error_local);
|
|
|
7d8bc5 |
- return FALSE;
|
|
|
7d8bc5 |
- }
|
|
|
7d8bc5 |
-
|
|
|
7d8bc5 |
- /* we can install unsigned packages */
|
|
|
7d8bc5 |
- g_debug("ignoring as allow-untrusted: %s",
|
|
|
7d8bc5 |
- error_local->message);
|
|
|
7d8bc5 |
- g_clear_error(&error_local);
|
|
|
7d8bc5 |
- }
|
|
|
7d8bc5 |
}
|
|
|
7d8bc5 |
return TRUE;
|
|
|
7d8bc5 |
}
|
|
|
7d8bc5 |
@@ -1167,6 +1184,44 @@ dnf_transaction_reset(DnfTransaction *transaction)
|
|
|
7d8bc5 |
}
|
|
|
7d8bc5 |
|
|
|
7d8bc5 |
/**
|
|
|
7d8bc5 |
+ * dnf_transaction_import_keys:
|
|
|
7d8bc5 |
+ * @transaction: a #DnfTransaction instance.
|
|
|
7d8bc5 |
+ * @error: A #GError or %NULL
|
|
|
7d8bc5 |
+ *
|
|
|
7d8bc5 |
+ * Imports all keys from /etc/pki/rpm-gpg as well as any
|
|
|
7d8bc5 |
+ * downloaded per-repo keys. Note this is called automatically
|
|
|
7d8bc5 |
+ * by dnf_transaction_commit().
|
|
|
7d8bc5 |
+ **/
|
|
|
7d8bc5 |
+gboolean
|
|
|
7d8bc5 |
+dnf_transaction_import_keys(DnfTransaction *transaction,
|
|
|
7d8bc5 |
+ GError **error)
|
|
|
7d8bc5 |
+{
|
|
|
7d8bc5 |
+ guint i;
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
+ DnfTransactionPrivate *priv = GET_PRIVATE(transaction);
|
|
|
7d8bc5 |
+ /* import all system wide GPG keys */
|
|
|
7d8bc5 |
+ if (!dnf_keyring_add_public_keys(priv->keyring, error))
|
|
|
7d8bc5 |
+ return FALSE;
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
+ /* import downloaded repo GPG keys */
|
|
|
7d8bc5 |
+ for (i = 0; i < priv->repos->len; i++) {
|
|
|
7d8bc5 |
+ DnfRepo *repo = g_ptr_array_index(priv->repos, i);
|
|
|
7d8bc5 |
+ const gchar *pubkey;
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
+ /* does this file actually exist */
|
|
|
7d8bc5 |
+ pubkey = dnf_repo_get_public_key(repo);
|
|
|
7d8bc5 |
+ if (g_file_test(pubkey, G_FILE_TEST_EXISTS)) {
|
|
|
7d8bc5 |
+ /* import */
|
|
|
7d8bc5 |
+ if (!dnf_keyring_add_public_key(priv->keyring, pubkey, error))
|
|
|
7d8bc5 |
+ return FALSE;
|
|
|
7d8bc5 |
+ }
|
|
|
7d8bc5 |
+ }
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
+ return TRUE;
|
|
|
7d8bc5 |
+}
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
+/**
|
|
|
7d8bc5 |
* dnf_transaction_commit:
|
|
|
7d8bc5 |
* @transaction: a #DnfTransaction instance.
|
|
|
7d8bc5 |
* @goal: A #HyGoal
|
|
|
7d8bc5 |
@@ -1237,26 +1292,10 @@ dnf_transaction_commit(DnfTransaction *transaction,
|
|
|
7d8bc5 |
if (!ret)
|
|
|
7d8bc5 |
goto out;
|
|
|
7d8bc5 |
|
|
|
7d8bc5 |
- /* import all system wide GPG keys */
|
|
|
7d8bc5 |
- ret = dnf_keyring_add_public_keys(priv->keyring, error);
|
|
|
7d8bc5 |
+ ret = dnf_transaction_import_keys(transaction, error);
|
|
|
7d8bc5 |
if (!ret)
|
|
|
7d8bc5 |
goto out;
|
|
|
7d8bc5 |
|
|
|
7d8bc5 |
- /* import downloaded repo GPG keys */
|
|
|
7d8bc5 |
- for (i = 0; i < priv->repos->len; i++) {
|
|
|
7d8bc5 |
- DnfRepo *repo = g_ptr_array_index(priv->repos, i);
|
|
|
7d8bc5 |
- const gchar *pubkey;
|
|
|
7d8bc5 |
-
|
|
|
7d8bc5 |
- /* does this file actually exist */
|
|
|
7d8bc5 |
- pubkey = dnf_repo_get_public_key(repo);
|
|
|
7d8bc5 |
- if (g_file_test(pubkey, G_FILE_TEST_EXISTS)) {
|
|
|
7d8bc5 |
- /* import */
|
|
|
7d8bc5 |
- ret = dnf_keyring_add_public_key(priv->keyring, pubkey, error);
|
|
|
7d8bc5 |
- if (!ret)
|
|
|
7d8bc5 |
- goto out;
|
|
|
7d8bc5 |
- }
|
|
|
7d8bc5 |
- }
|
|
|
7d8bc5 |
-
|
|
|
7d8bc5 |
/* find any packages without valid GPG signatures */
|
|
|
7d8bc5 |
ret = dnf_transaction_check_untrusted(transaction, goal, error);
|
|
|
7d8bc5 |
if (!ret)
|
|
|
7d8bc5 |
diff --git a/libdnf/libdnf/dnf-transaction.h b/libdnf/libdnf/dnf-transaction.h
|
|
|
7d8bc5 |
index 6131374..84d1365 100644
|
|
|
7d8bc5 |
--- a/libdnf/libdnf/dnf-transaction.h
|
|
|
7d8bc5 |
+++ b/libdnf/libdnf/dnf-transaction.h
|
|
|
7d8bc5 |
@@ -95,6 +95,17 @@ gboolean dnf_transaction_depsolve (DnfTransaction *transac
|
|
|
7d8bc5 |
gboolean dnf_transaction_download (DnfTransaction *transaction,
|
|
|
7d8bc5 |
DnfState *state,
|
|
|
7d8bc5 |
GError **error);
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
+gboolean dnf_transaction_import_keys (DnfTransaction *transaction,
|
|
|
7d8bc5 |
+ GError **error);
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
+gboolean dnf_transaction_gpgcheck_package (DnfTransaction *transaction,
|
|
|
7d8bc5 |
+ DnfPackage *pkg,
|
|
|
7d8bc5 |
+ GError **error);
|
|
|
7d8bc5 |
+gboolean dnf_transaction_check_untrusted (DnfTransaction *transaction,
|
|
|
7d8bc5 |
+ HyGoal goal,
|
|
|
7d8bc5 |
+ GError **error);
|
|
|
7d8bc5 |
+
|
|
|
7d8bc5 |
gboolean dnf_transaction_commit (DnfTransaction *transaction,
|
|
|
7d8bc5 |
HyGoal goal,
|
|
|
7d8bc5 |
DnfState *state,
|
|
|
7d8bc5 |
--
|
|
|
7d8bc5 |
2.9.3
|
|
|
7d8bc5 |
|