diff options
author | Colin Walters <walters@verbum.org> | 2017-07-24 16:39:01 -0400 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2017-08-08 15:50:25 +0000 |
commit | 9f8f351cd45e5dd0219c3177558b497ab10c58e9 (patch) | |
tree | 9b5f15183f9e8b09ac6e228f9a38f4f5cc9bb6db | |
parent | 1672e2eee058d0fe41ed102ca310a9634d36572f (diff) | |
download | ostree-9f8f351cd45e5dd0219c3177558b497ab10c58e9.tar.gz |
lib: Port gpg verification for remotes to fd-relative
This was the last use of `repo->repodir` internally, and will help finally add
`ostree_repo_open_at()`.
Closes: #1034
Approved by: jlebon
-rw-r--r-- | src/libostree/ostree-gpg-verifier.c | 86 | ||||
-rw-r--r-- | src/libostree/ostree-gpg-verifier.h | 12 | ||||
-rw-r--r-- | src/libostree/ostree-repo.c | 56 |
3 files changed, 112 insertions, 42 deletions
diff --git a/src/libostree/ostree-gpg-verifier.c b/src/libostree/ostree-gpg-verifier.c index 680c410b..99756e2b 100644 --- a/src/libostree/ostree-gpg-verifier.c +++ b/src/libostree/ostree-gpg-verifier.c @@ -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 diff --git a/src/libostree/ostree-gpg-verifier.h b/src/libostree/ostree-gpg-verifier.h index 4156d1bd..7d5a7594 100644 --- a/src/libostree/ostree-gpg-verifier.h +++ b/src/libostree/ostree-gpg-verifier.h @@ -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); diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 5d5d871b..7b787760 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -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, |