Blob Blame History Raw
From b2ded5a4da58940159f5d337e9e29c5de5cc0f7a Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@verbum.org>
Date: Thu, 2 Feb 2017 10:00:06 -0500
Subject: [PATCH 1/2] repo: Enable GPG by default

This increases compatibility with dnf/yum. It was very surprising to me that we
didn't do this. Most repos do seem to use `gpgcheck=1`, but I'm fairly certain
I've seen repo configs in the wild that actually depend on it, though after
looking at a few (ceph, postgres), I can't find one yet.

Still, I think it's worth making this change. I suspect very few people will
edit `/etc/yum/yum.conf` to globally disable GPG checking, versus disabling it
per repository.
---
 libdnf/dnf-repo.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/libdnf/dnf-repo.c b/libdnf/dnf-repo.c
index 08e0d8b..017c82d 100644
--- a/libdnf/libdnf/dnf-repo.c
+++ b/libdnf/libdnf/dnf-repo.c
@@ -858,7 +858,16 @@ dnf_repo_set_keyfile_data(DnfRepo *repo, GError **error)
     /* gpgkey is optional for gpgcheck=1, but required for repo_gpgcheck=1 */
     g_free(priv->gpgkey);
     priv->gpgkey = g_key_file_get_string(priv->keyfile, priv->id, "gpgkey", NULL);
-    priv->gpgcheck_pkgs = dnf_repo_get_boolean(priv->keyfile, priv->id, "gpgcheck", NULL);
+    /* Currently, we don't have a global configuration file.  The way this worked in yum
+     * is that the yum package enabled gpgcheck=1 by default in /etc/yum.conf.  Basically,
+     * I don't think many people changed that.  It's just saner to disable it in the individual
+     * repo files as required.  To claim compatibility with yum repository files, I think
+     * we need to basically hard code the yum.conf defaults here.
+     */
+    if (!g_key_file_has_key (priv->keyfile, priv->id, "gpgcheck", NULL))
+        priv->gpgcheck_pkgs = TRUE;
+    else
+        priv->gpgcheck_pkgs = dnf_repo_get_boolean(priv->keyfile, priv->id, "gpgcheck", NULL);
     priv->gpgcheck_md = dnf_repo_get_boolean(priv->keyfile, priv->id, "repo_gpgcheck", NULL);
     if (priv->gpgcheck_md && priv->gpgkey == NULL) {
         g_set_error_literal(error,
-- 
2.9.3


From 0d68ebac7d39a9278ebb5259c4912efa55c080da Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@verbum.org>
Date: Tue, 31 Jan 2017 17:14:37 -0500
Subject: [PATCH 2/2] transaction: Export parts of the GPG functionality

rpm-ostree doesn't use `dnf_transaction_commit()`, because it uses libostree to
store the RPMs, and bubblewrap to run `%post`s. However, we do need the GPG
functionality.
---
 libdnf/libdnf/dnf-transaction.c | 193 ++++++++++++++++++++++++++++-------------------
 libdnf/libdnf/dnf-transaction.h |  11 +++
 2 files changed, 127 insertions(+), 77 deletions(-)

diff --git a/libdnf/libdnf/dnf-transaction.c b/libdnf/libdnf/dnf-transaction.c
index 62fcc51..dd73245 100644
--- a/libdnf/libdnf/dnf-transaction.c
+++ b/libdnf/libdnf/dnf-transaction.c
@@ -328,17 +328,88 @@ dnf_transaction_ensure_repo_list(DnfTransaction *transaction,
     return TRUE;
 }
 
+gboolean
+dnf_transaction_gpgcheck_package (DnfTransaction *transaction,
+                                  DnfPackage     *pkg,
+                                  GError        **error)
+{
+    DnfTransactionPrivate *priv = GET_PRIVATE(transaction);
+    GError *error_local = NULL;
+    DnfRepo *repo;
+    const gchar *fn;
+
+    /* ensure the filename is set */
+    if (!dnf_transaction_ensure_repo(transaction, pkg, error)) {
+        g_prefix_error(error, "Failed to check untrusted: ");
+        return FALSE;
+    }
+
+    /* find the location of the local file */
+    fn = dnf_package_get_filename(pkg);
+    if (fn == NULL) {
+        g_set_error(error,
+                    DNF_ERROR,
+                    DNF_ERROR_FILE_NOT_FOUND,
+                    "Downloaded file for %s not found",
+                    dnf_package_get_name(pkg));
+        return FALSE;
+    }
+
+    /* check file */
+    if (!dnf_keyring_check_untrusted_file(priv->keyring, fn, &error_local)) {
+
+        /* probably an i/o error */
+        if (!g_error_matches(error_local,
+                             DNF_ERROR,
+                             DNF_ERROR_GPG_SIGNATURE_INVALID)) {
+            g_propagate_error(error, error_local);
+            return FALSE;
+        }
+
+        /* if the repo is signed this is ALWAYS an error */
+        repo = dnf_package_get_repo(pkg);
+        if (repo != NULL && dnf_repo_get_gpgcheck(repo)) {
+            g_set_error(error,
+                        DNF_ERROR,
+                        DNF_ERROR_FILE_INVALID,
+                        "package %s cannot be verified "
+                        "and repo %s is GPG enabled: %s",
+                        dnf_package_get_nevra(pkg),
+                        dnf_repo_get_id(repo),
+                        error_local->message);
+            g_error_free(error_local);
+            return FALSE;
+        }
+
+        /* we can only install signed packages in this mode */
+        if ((priv->flags & DNF_TRANSACTION_FLAG_ONLY_TRUSTED) > 0) {
+            g_propagate_error(error, error_local);
+            return FALSE;
+        }
+
+        /* we can install unsigned packages */
+        g_warning("ignoring as allow-untrusted: %s",
+                error_local->message);
+        g_clear_error(&error_local);
+    }
+
+    return TRUE;
+}
+
 /**
  * dnf_transaction_check_untrusted:
+ * @transaction: Transaction
+ * @goal: Target goal
+ * @error: Error
+ *
+ * Verify GPG signatures for all pending packages to be changed as part
+ * of @goal.
  */
-static gboolean
+gboolean
 dnf_transaction_check_untrusted(DnfTransaction *transaction,
                                 HyGoal goal,
                                 GError **error)
 {
-    DnfTransactionPrivate *priv = GET_PRIVATE(transaction);
-    DnfPackage *pkg;
-    const gchar *fn;
     guint i;
     g_autoptr(GPtrArray) install = NULL;
 
@@ -354,64 +425,10 @@ dnf_transaction_check_untrusted(DnfTransaction *transaction,
 
     /* find any packages in untrusted repos */
     for (i = 0; i < install->len; i++) {
-        GError *error_local = NULL;
-        DnfRepo *repo;
-        pkg = g_ptr_array_index(install, i);
+        DnfPackage *pkg = g_ptr_array_index(install, i);
 
-        /* ensure the filename is set */
-        if (!dnf_transaction_ensure_repo(transaction, pkg, error)) {
-            g_prefix_error(error, "Failed to check untrusted: ");
+        if (!dnf_transaction_gpgcheck_package (transaction, pkg, error))
             return FALSE;
-        }
-
-        /* find the location of the local file */
-        fn = dnf_package_get_filename(pkg);
-        if (fn == NULL) {
-            g_set_error(error,
-                        DNF_ERROR,
-                        DNF_ERROR_FILE_NOT_FOUND,
-                        "Downloaded file for %s not found",
-                        dnf_package_get_name(pkg));
-            return FALSE;
-        }
-
-        /* check file */
-        if (!dnf_keyring_check_untrusted_file(priv->keyring, fn, &error_local)) {
-
-            /* probably an i/o error */
-            if (!g_error_matches(error_local,
-                                 DNF_ERROR,
-                                 DNF_ERROR_GPG_SIGNATURE_INVALID)) {
-                g_propagate_error(error, error_local);
-                return FALSE;
-            }
-
-            /* if the repo is signed this is ALWAYS an error */
-            repo = dnf_package_get_repo(pkg);
-            if (repo != NULL && dnf_repo_get_gpgcheck(repo)) {
-                g_set_error(error,
-                            DNF_ERROR,
-                            DNF_ERROR_FILE_INVALID,
-                            "package %s cannot be verified "
-                            "and repo %s is GPG enabled: %s",
-                            dnf_package_get_nevra(pkg),
-                            dnf_repo_get_id(repo),
-                            error_local->message);
-                g_error_free(error_local);
-                return FALSE;
-            }
-
-            /* we can only install signed packages in this mode */
-            if ((priv->flags & DNF_TRANSACTION_FLAG_ONLY_TRUSTED) > 0) {
-                g_propagate_error(error, error_local);
-                return FALSE;
-            }
-
-            /* we can install unsigned packages */
-            g_debug("ignoring as allow-untrusted: %s",
-                 error_local->message);
-            g_clear_error(&error_local);
-        }
     }
     return TRUE;
 }
@@ -1167,6 +1184,44 @@ dnf_transaction_reset(DnfTransaction *transaction)
 }
 
 /**
+ * dnf_transaction_import_keys:
+ * @transaction: a #DnfTransaction instance.
+ * @error: A #GError or %NULL
+ *
+ * Imports all keys from /etc/pki/rpm-gpg as well as any
+ * downloaded per-repo keys.  Note this is called automatically
+ * by dnf_transaction_commit().
+ **/
+gboolean
+dnf_transaction_import_keys(DnfTransaction *transaction,
+                            GError **error)
+{
+    guint i;
+
+    DnfTransactionPrivate *priv = GET_PRIVATE(transaction);
+    /* import all system wide GPG keys */
+    if (!dnf_keyring_add_public_keys(priv->keyring, error))
+        return FALSE;
+
+    /* import downloaded repo GPG keys */
+    for (i = 0; i < priv->repos->len; i++) {
+        DnfRepo *repo = g_ptr_array_index(priv->repos, i);
+        const gchar *pubkey;
+
+        /* does this file actually exist */
+        pubkey = dnf_repo_get_public_key(repo);
+        if (g_file_test(pubkey, G_FILE_TEST_EXISTS)) {
+            /* import */
+            if (!dnf_keyring_add_public_key(priv->keyring, pubkey, error))
+                return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+
+/**
  * dnf_transaction_commit:
  * @transaction: a #DnfTransaction instance.
  * @goal: A #HyGoal
@@ -1237,26 +1292,10 @@ dnf_transaction_commit(DnfTransaction *transaction,
     if (!ret)
         goto out;
 
-    /* import all system wide GPG keys */
-    ret = dnf_keyring_add_public_keys(priv->keyring, error);
+    ret = dnf_transaction_import_keys(transaction, error);
     if (!ret)
         goto out;
 
-    /* import downloaded repo GPG keys */
-    for (i = 0; i < priv->repos->len; i++) {
-        DnfRepo *repo = g_ptr_array_index(priv->repos, i);
-        const gchar *pubkey;
-
-        /* does this file actually exist */
-        pubkey = dnf_repo_get_public_key(repo);
-        if (g_file_test(pubkey, G_FILE_TEST_EXISTS)) {
-            /* import */
-            ret = dnf_keyring_add_public_key(priv->keyring, pubkey, error);
-            if (!ret)
-                goto out;
-        }
-    }
-
     /* find any packages without valid GPG signatures */
     ret = dnf_transaction_check_untrusted(transaction, goal, error);
     if (!ret)
diff --git a/libdnf/libdnf/dnf-transaction.h b/libdnf/libdnf/dnf-transaction.h
index 6131374..84d1365 100644
--- a/libdnf/libdnf/dnf-transaction.h
+++ b/libdnf/libdnf/dnf-transaction.h
@@ -95,6 +95,17 @@ gboolean         dnf_transaction_depsolve               (DnfTransaction *transac
 gboolean         dnf_transaction_download               (DnfTransaction *transaction,
                                                          DnfState       *state,
                                                          GError         **error);
+
+gboolean         dnf_transaction_import_keys            (DnfTransaction *transaction,
+                                                         GError **error);
+
+gboolean         dnf_transaction_gpgcheck_package        (DnfTransaction *transaction,
+                                                          DnfPackage     *pkg,
+                                                          GError        **error);
+gboolean         dnf_transaction_check_untrusted        (DnfTransaction *transaction,
+                                                         HyGoal          goal,
+                                                         GError        **error);
+
 gboolean         dnf_transaction_commit                 (DnfTransaction *transaction,
                                                          HyGoal          goal,
                                                          DnfState       *state,
-- 
2.9.3