lib/repo: Factor out GPG verifier key imports
authorDan Nicholson <nicholson@endlessm.com>
Fri, 26 Jul 2019 15:38:23 +0000 (09:38 -0600)
committerDan Nicholson <dbn@endlessos.org>
Thu, 15 Jul 2021 21:50:04 +0000 (15:50 -0600)
Currently the verifier only imports all the GPG keys when verifying
data, but it would also be useful for inspecting the trusted keys.

src/libostree/ostree-gpg-verifier.c

index 95ed36eed6b8d5596efad92baa5193341f50b587..88850d467eb8d07b2f353fa2c9755c7f6c07d68d 100644 (file)
@@ -91,43 +91,16 @@ verify_result_finalized_cb (gpointer data,
   (void) glnx_shutil_rm_rf_at (AT_FDCWD, tmp_dir, NULL, NULL);
 }
 
-OstreeGpgVerifyResult *
-_ostree_gpg_verifier_check_signature (OstreeGpgVerifier  *self,
-                                      GBytes             *signed_data,
-                                      GBytes             *signatures,
-                                      GCancellable       *cancellable,
-                                      GError            **error)
+static gboolean
+_ostree_gpg_verifier_import_keys (OstreeGpgVerifier  *self,
+                                  gpgme_ctx_t         gpgme_ctx,
+                                  GOutputStream      *pubring_stream,
+                                  GCancellable       *cancellable,
+                                  GError            **error)
 {
   GLNX_AUTO_PREFIX_ERROR("GPG", error);
-  gpgme_error_t gpg_error = 0;
-  g_auto(gpgme_data_t) data_buffer = NULL;
-  g_auto(gpgme_data_t) signature_buffer = NULL;
-  g_autofree char *tmp_dir = NULL;
-  g_autoptr(GOutputStream) target_stream = NULL;
-  OstreeGpgVerifyResult *result = NULL;
-  gboolean success = FALSE;
-  GList *link;
-  int armor;
-
-  /* GPGME has no API for using multiple keyrings (aka, gpg --keyring),
-   * so we concatenate all the keyring files into one pubring.gpg in a
-   * temporary directory, then tell GPGME to use that directory as the
-   * home directory. */
-
-  if (g_cancellable_set_error_if_cancelled (cancellable, error))
-    goto out;
-
-  result = g_initable_new (OSTREE_TYPE_GPG_VERIFY_RESULT,
-                           cancellable, error, NULL);
-  if (result == NULL)
-    goto out;
 
-  if (!ot_gpgme_ctx_tmp_home_dir (result->context,
-                                  &tmp_dir, &target_stream,
-                                  cancellable, error))
-    goto out;
-
-  for (link = self->keyrings; link != NULL; link = link->next)
+  for (GList *link = self->keyrings; link != NULL; link = link->next)
     {
       g_autoptr(GFileInputStream) source_stream = NULL;
       GFile *keyring_file = link->data;
@@ -145,15 +118,15 @@ _ostree_gpg_verifier_check_signature (OstreeGpgVerifier  *self,
       else if (local_error != NULL)
         {
           g_propagate_error (error, local_error);
-          goto out;
+          return FALSE;
         }
 
-      bytes_written = g_output_stream_splice (target_stream,
+      bytes_written = g_output_stream_splice (pubring_stream,
                                               G_INPUT_STREAM (source_stream),
                                               G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
                                               cancellable, error);
       if (bytes_written < 0)
-        goto out;
+        return FALSE;
     }
 
   for (guint i = 0; i < self->keyring_data->len; i++)
@@ -162,23 +135,25 @@ _ostree_gpg_verifier_check_signature (OstreeGpgVerifier  *self,
       gsize len;
       gsize bytes_written;
       const guint8 *buf = g_bytes_get_data (keyringd, &len);
-      if (!g_output_stream_write_all (target_stream, buf, len, &bytes_written,
+      if (!g_output_stream_write_all (pubring_stream, buf, len, &bytes_written,
                                       cancellable, error))
-        goto out;
+        return FALSE;
     }
 
-  if (!g_output_stream_close (target_stream, cancellable, error))
-    goto out;
+  if (!g_output_stream_close (pubring_stream, cancellable, error))
+    return FALSE;
 
   /* Save the previous armor value - we need it on for importing ASCII keys */
-  armor = gpgme_get_armor (result->context);
-  gpgme_set_armor (result->context, 1);
+  gboolean ret = FALSE;
+  int armor = gpgme_get_armor (gpgme_ctx);
+  gpgme_set_armor (gpgme_ctx, 1);
 
   /* Now, use the API to import ASCII-armored keys */
   if (self->key_ascii_files)
     {
       for (guint i = 0; i < self->key_ascii_files->len; i++)
         {
+          gpgme_error_t gpg_error;
           const char *path = self->key_ascii_files->pdata[i];
           glnx_autofd int fd = -1;
           g_auto(gpgme_data_t) kdata = NULL;
@@ -193,7 +168,7 @@ _ostree_gpg_verifier_check_signature (OstreeGpgVerifier  *self,
               goto out;
             }
 
-          gpg_error = gpgme_op_import (result->context, kdata);
+          gpg_error = gpgme_op_import (gpgme_ctx, kdata);
           if (gpg_error != GPG_ERR_NO_ERROR)
             {
               ot_gpgme_throw (gpg_error, error, "Failed to import key");
@@ -202,7 +177,51 @@ _ostree_gpg_verifier_check_signature (OstreeGpgVerifier  *self,
         }
     }
 
-  gpgme_set_armor (result->context, armor);
+  ret = TRUE;
+
+ out:
+  gpgme_set_armor (gpgme_ctx, armor);
+
+  return ret;
+}
+
+OstreeGpgVerifyResult *
+_ostree_gpg_verifier_check_signature (OstreeGpgVerifier  *self,
+                                      GBytes             *signed_data,
+                                      GBytes             *signatures,
+                                      GCancellable       *cancellable,
+                                      GError            **error)
+{
+  GLNX_AUTO_PREFIX_ERROR("GPG", error);
+  gpgme_error_t gpg_error = 0;
+  g_auto(gpgme_data_t) data_buffer = NULL;
+  g_auto(gpgme_data_t) signature_buffer = NULL;
+  g_autofree char *tmp_dir = NULL;
+  g_autoptr(GOutputStream) target_stream = NULL;
+  OstreeGpgVerifyResult *result = NULL;
+  gboolean success = FALSE;
+
+  /* GPGME has no API for using multiple keyrings (aka, gpg --keyring),
+   * so we concatenate all the keyring files into one pubring.gpg in a
+   * temporary directory, then tell GPGME to use that directory as the
+   * home directory. */
+
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    goto out;
+
+  result = g_initable_new (OSTREE_TYPE_GPG_VERIFY_RESULT,
+                           cancellable, error, NULL);
+  if (result == NULL)
+    goto out;
+
+  if (!ot_gpgme_ctx_tmp_home_dir (result->context,
+                                  &tmp_dir, &target_stream,
+                                  cancellable, error))
+    goto out;
+
+  if (!_ostree_gpg_verifier_import_keys (self, result->context, target_stream,
+                                         cancellable, error))
+    goto out;
 
   /* Both the signed data and signature GBytes instances will outlive the
    * gpgme_data_t structs, so we can safely reuse the GBytes memory buffer