lib: Port gpg verification for remotes to fd-relative
authorColin Walters <walters@verbum.org>
Mon, 24 Jul 2017 20:39:01 +0000 (16:39 -0400)
committerAtomic Bot <atomic-devel@projectatomic.io>
Tue, 8 Aug 2017 15:50:25 +0000 (15:50 +0000)
This was the last use of `repo->repodir` internally, and will help finally add
`ostree_repo_open_at()`.

Closes: #1034
Approved by: jlebon

src/libostree/ostree-gpg-verifier.c
src/libostree/ostree-gpg-verifier.h
src/libostree/ostree-repo.c

index 680c410b8e38172f96ff4504297607138568e550..99756e2b807130d7cba5523905a3bb5b09b452ed 100644 (file)
@@ -40,6 +40,7 @@ struct OstreeGpgVerifier {
   GObject parent;
 
   GList *keyrings;
+  GPtrArray *keyring_data;
   GPtrArray *key_ascii_files;
 };
 
@@ -53,6 +54,7 @@ ostree_gpg_verifier_finalize (GObject *object)
   g_list_free_full (self->keyrings, g_object_unref);
   if (self->key_ascii_files)
     g_ptr_array_unref (self->key_ascii_files);
+  g_clear_pointer (&self->keyring_data, (GDestroyNotify)g_ptr_array_unref);
 
   G_OBJECT_CLASS (_ostree_gpg_verifier_parent_class)->finalize (object);
 }
@@ -71,6 +73,7 @@ _ostree_gpg_verifier_class_init (OstreeGpgVerifierClass *klass)
 static void
 _ostree_gpg_verifier_init (OstreeGpgVerifier *self)
 {
+  self->keyring_data = g_ptr_array_new_with_free_func ((GDestroyNotify)g_bytes_unref);
 }
 
 static void
@@ -151,6 +154,17 @@ _ostree_gpg_verifier_check_signature (OstreeGpgVerifier  *self,
         goto out;
     }
 
+  for (guint i = 0; i < self->keyring_data->len; i++)
+    {
+      GBytes *keyringd = self->keyring_data->pdata[i];
+      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,
+                                      cancellable, error))
+        goto out;
+    }
+
   if (!g_output_stream_close (target_stream, cancellable, error))
     goto out;
 
@@ -253,15 +267,28 @@ out:
   return result;
 }
 
+/* Given @path which should contain a GPG keyring file, add it
+ * to the list of trusted keys.
+ */
 void
-_ostree_gpg_verifier_add_keyring (OstreeGpgVerifier  *self,
-                                  GFile              *path)
+_ostree_gpg_verifier_add_keyring_file (OstreeGpgVerifier  *self,
+                                       GFile              *path)
 {
   g_return_if_fail (G_IS_FILE (path));
 
   self->keyrings = g_list_append (self->keyrings, g_object_ref (path));
 }
 
+/* Given @keyring which should be the contents of a GPG keyring file, add it to
+ * the list of trusted keys.
+ */
+void
+_ostree_gpg_verifier_add_keyring_data (OstreeGpgVerifier  *self,
+                                       GBytes             *keyring)
+{
+  g_ptr_array_add (self->keyring_data, g_bytes_ref (keyring));
+}
+
 void
 _ostree_gpg_verifier_add_key_ascii_file (OstreeGpgVerifier *self,
                                          const char        *path)
@@ -276,32 +303,39 @@ _ostree_gpg_verifier_add_keyring_dir (OstreeGpgVerifier   *self,
                                       GFile               *path,
                                       GCancellable        *cancellable,
                                       GError             **error)
+
 {
-  gboolean ret = FALSE;
-  g_autoptr(GFileEnumerator) enumerator = NULL;
-  
-  enumerator = g_file_enumerate_children (path, OSTREE_GIO_FAST_QUERYINFO,
-                                          G_FILE_QUERY_INFO_NONE,
-                                          cancellable, error);
-  if (!enumerator)
-    goto out;
+  return _ostree_gpg_verifier_add_keyring_dir_at (self, AT_FDCWD,
+                                                  gs_file_get_path_cached (path),
+                                                  cancellable, error);
+}
+
+gboolean
+_ostree_gpg_verifier_add_keyring_dir_at (OstreeGpgVerifier   *self,
+                                         int                  dfd,
+                                         const char          *path,
+                                         GCancellable        *cancellable,
+                                         GError             **error)
+
+{
+  g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
+  if (!glnx_dirfd_iterator_init_at (dfd, path, FALSE,
+                                    &dfd_iter, error))
+    return FALSE;
 
   while (TRUE)
     {
-      GFileInfo *file_info;
-      GFile *path;
-      const char *name;
+      struct dirent *dent;
 
-      if (!g_file_enumerator_iterate (enumerator, &file_info, &path,
-                                      cancellable, error))
-        goto out;
-      if (file_info == NULL)
+      if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error))
+        return FALSE;
+      if (dent == NULL)
         break;
 
-      if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_REGULAR)
+      if (dent->d_type != DT_REG)
         continue;
 
-      name = g_file_info_get_name (file_info);
+      const char *name = dent->d_name;
 
       /* Files with a .gpg suffix are typically keyrings except
        * for trustdb.gpg, which is the GPG trust database. */
@@ -315,12 +349,18 @@ _ostree_gpg_verifier_add_keyring_dir (OstreeGpgVerifier   *self,
       if (g_str_equal (name, "secring.gpg"))
         continue;
 
-      self->keyrings = g_list_append (self->keyrings, g_object_ref (path));
+      glnx_fd_close int fd = -1;
+      if (!glnx_openat_rdonly (dfd_iter.fd, dent->d_name, TRUE, &fd, error))
+        return FALSE;
+
+      g_autoptr(GBytes) data = glnx_fd_readall_bytes (fd, cancellable, error);
+      if (!data)
+        return FALSE;
+
+      g_ptr_array_add (self->keyring_data, g_steal_pointer (&data));
     }
 
-  ret = TRUE;
- out:
-  return ret;
+  return TRUE;
 }
 
 gboolean
index 4156d1bd43c4efc3f83067241390b90da8a9d50b..7d5a7594d5db3922eaded395719038bf7207156b 100644 (file)
@@ -55,12 +55,20 @@ gboolean      _ostree_gpg_verifier_add_keyring_dir (OstreeGpgVerifier   *self,
                                                     GCancellable        *cancellable,
                                                     GError             **error);
 
+gboolean      _ostree_gpg_verifier_add_keyring_dir_at (OstreeGpgVerifier   *self,
+                                                       int                  dfd,
+                                                       const char          *path,
+                                                       GCancellable        *cancellable,
+                                                       GError             **error);
+
 gboolean      _ostree_gpg_verifier_add_global_keyring_dir (OstreeGpgVerifier  *self,
                                                            GCancellable       *cancellable,
                                                            GError            **error);
 
-void _ostree_gpg_verifier_add_keyring (OstreeGpgVerifier *self,
-                                       GFile             *path);
+void _ostree_gpg_verifier_add_keyring_data (OstreeGpgVerifier *self,
+                                            GBytes            *data);
+void _ostree_gpg_verifier_add_keyring_file (OstreeGpgVerifier *self,
+                                            GFile             *path);
 
 void _ostree_gpg_verifier_add_key_ascii_file (OstreeGpgVerifier *self,
                                               const char        *path);
index 5d5d871b48172b2cb66a8fe6b233b19080b7596f..7b7877606f1e616793a9198d3f086c73ee2e271d 100644 (file)
@@ -4202,31 +4202,52 @@ ostree_repo_add_gpg_signature_summary (OstreeRepo     *self,
 /* Special remote for _ostree_repo_gpg_verify_with_metadata() */
 static const char *OSTREE_ALL_REMOTES = "__OSTREE_ALL_REMOTES__";
 
-static GFile *
+/* Look for a keyring for @remote in the repo itself, or in
+ * /etc/ostree/remotes.d.
+ */
+static gboolean
 find_keyring (OstreeRepo          *self,
               OstreeRemote        *remote,
-              GCancellable        *cancellable)
+              GBytes             **ret_bytes,
+              GCancellable        *cancellable,
+              GError             **error)
 {
-  g_autoptr(GFile) file = g_file_get_child (self->repodir, remote->keyring);
+  glnx_fd_close int fd = -1;
+  if (!ot_openat_ignore_enoent (self->repo_dir_fd, remote->keyring, &fd, error))
+    return FALSE;
 
-  if (g_file_query_exists (file, cancellable))
+  if (fd != -1)
     {
-      return g_steal_pointer (&file);
+      GBytes *ret = glnx_fd_readall_bytes (fd, cancellable, error);
+      if (!ret)
+        return FALSE;
+      *ret_bytes = ret;
+      return TRUE;
     }
 
   g_autoptr(GFile) remotes_d = get_remotes_d_dir (self, NULL);
   if (remotes_d)
     {
-      g_autoptr(GFile) file2 = g_file_get_child (remotes_d, remote->keyring);
+      g_autoptr(GFile) child = g_file_get_child (remotes_d, remote->keyring);
 
-      if (g_file_query_exists (file2, cancellable))
-        return g_steal_pointer (&file2);
+      if (!ot_openat_ignore_enoent (AT_FDCWD, gs_file_get_path_cached (child), &fd, error))
+        return FALSE;
+
+      if (fd != -1)
+        {
+          GBytes *ret = glnx_fd_readall_bytes (fd, cancellable, error);
+          if (!ret)
+            return FALSE;
+          *ret_bytes = ret;
+          return TRUE;
+        }
     }
 
   if (self->parent_repo)
-    return find_keyring (self->parent_repo, remote, cancellable);
+    return find_keyring (self->parent_repo, remote, ret_bytes, cancellable, error);
 
-  return NULL;
+  *ret_bytes = NULL;
+  return TRUE;
 }
 
 static OstreeGpgVerifyResult *
@@ -4248,8 +4269,8 @@ _ostree_repo_gpg_verify_data_internal (OstreeRepo    *self,
     {
       /* Add all available remote keyring files. */
 
-      if (!_ostree_gpg_verifier_add_keyring_dir (verifier, self->repodir,
-                                                 cancellable, error))
+      if (!_ostree_gpg_verifier_add_keyring_dir_at (verifier, self->repo_dir_fd, ".",
+                                                    cancellable, error))
         return NULL;
     }
   else if (remote_name != NULL)
@@ -4258,17 +4279,18 @@ _ostree_repo_gpg_verify_data_internal (OstreeRepo    *self,
       /* Add the remote's keyring file if it exists. */
 
       OstreeRemote *remote;
-      g_autoptr(GFile) file = NULL;
 
       remote = _ostree_repo_get_remote_inherited (self, remote_name, error);
       if (remote == NULL)
         return NULL;
 
-      file = find_keyring (self, remote, cancellable);
+      g_autoptr(GBytes) keyring_data = NULL;
+      if (!find_keyring (self, remote, &keyring_data, cancellable, error))
+        return NULL;
 
-      if (file != NULL)
+      if (keyring_data != NULL)
         {
-          _ostree_gpg_verifier_add_keyring (verifier, file);
+          _ostree_gpg_verifier_add_keyring_data (verifier, keyring_data);
           add_global_keyring_dir = FALSE;
         }
 
@@ -4297,7 +4319,7 @@ _ostree_repo_gpg_verify_data_internal (OstreeRepo    *self,
     }
   if (extra_keyring != NULL)
     {
-      _ostree_gpg_verifier_add_keyring (verifier, extra_keyring);
+      _ostree_gpg_verifier_add_keyring_file (verifier, extra_keyring);
     }
 
   return _ostree_gpg_verifier_check_signature (verifier,