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
This commit is contained in:
parent
1672e2eee0
commit
9f8f351cd4
|
|
@ -40,6 +40,7 @@ struct OstreeGpgVerifier {
|
||||||
GObject parent;
|
GObject parent;
|
||||||
|
|
||||||
GList *keyrings;
|
GList *keyrings;
|
||||||
|
GPtrArray *keyring_data;
|
||||||
GPtrArray *key_ascii_files;
|
GPtrArray *key_ascii_files;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -53,6 +54,7 @@ ostree_gpg_verifier_finalize (GObject *object)
|
||||||
g_list_free_full (self->keyrings, g_object_unref);
|
g_list_free_full (self->keyrings, g_object_unref);
|
||||||
if (self->key_ascii_files)
|
if (self->key_ascii_files)
|
||||||
g_ptr_array_unref (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);
|
G_OBJECT_CLASS (_ostree_gpg_verifier_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
@ -71,6 +73,7 @@ _ostree_gpg_verifier_class_init (OstreeGpgVerifierClass *klass)
|
||||||
static void
|
static void
|
||||||
_ostree_gpg_verifier_init (OstreeGpgVerifier *self)
|
_ostree_gpg_verifier_init (OstreeGpgVerifier *self)
|
||||||
{
|
{
|
||||||
|
self->keyring_data = g_ptr_array_new_with_free_func ((GDestroyNotify)g_bytes_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -151,6 +154,17 @@ _ostree_gpg_verifier_check_signature (OstreeGpgVerifier *self,
|
||||||
goto out;
|
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))
|
if (!g_output_stream_close (target_stream, cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
@ -253,15 +267,28 @@ out:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Given @path which should contain a GPG keyring file, add it
|
||||||
|
* to the list of trusted keys.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
_ostree_gpg_verifier_add_keyring (OstreeGpgVerifier *self,
|
_ostree_gpg_verifier_add_keyring_file (OstreeGpgVerifier *self,
|
||||||
GFile *path)
|
GFile *path)
|
||||||
{
|
{
|
||||||
g_return_if_fail (G_IS_FILE (path));
|
g_return_if_fail (G_IS_FILE (path));
|
||||||
|
|
||||||
self->keyrings = g_list_append (self->keyrings, g_object_ref (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
|
void
|
||||||
_ostree_gpg_verifier_add_key_ascii_file (OstreeGpgVerifier *self,
|
_ostree_gpg_verifier_add_key_ascii_file (OstreeGpgVerifier *self,
|
||||||
const char *path)
|
const char *path)
|
||||||
|
|
@ -276,32 +303,39 @@ _ostree_gpg_verifier_add_keyring_dir (OstreeGpgVerifier *self,
|
||||||
GFile *path,
|
GFile *path,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
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,
|
return _ostree_gpg_verifier_add_keyring_dir_at (self, AT_FDCWD,
|
||||||
cancellable, error);
|
gs_file_get_path_cached (path),
|
||||||
if (!enumerator)
|
cancellable, error);
|
||||||
goto out;
|
}
|
||||||
|
|
||||||
|
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)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
GFileInfo *file_info;
|
struct dirent *dent;
|
||||||
GFile *path;
|
|
||||||
const char *name;
|
|
||||||
|
|
||||||
if (!g_file_enumerator_iterate (enumerator, &file_info, &path,
|
if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error))
|
||||||
cancellable, error))
|
return FALSE;
|
||||||
goto out;
|
if (dent == NULL)
|
||||||
if (file_info == NULL)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_REGULAR)
|
if (dent->d_type != DT_REG)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
name = g_file_info_get_name (file_info);
|
const char *name = dent->d_name;
|
||||||
|
|
||||||
/* Files with a .gpg suffix are typically keyrings except
|
/* Files with a .gpg suffix are typically keyrings except
|
||||||
* for trustdb.gpg, which is the GPG trust database. */
|
* 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"))
|
if (g_str_equal (name, "secring.gpg"))
|
||||||
continue;
|
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;
|
return TRUE;
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
|
|
||||||
|
|
@ -55,12 +55,20 @@ gboolean _ostree_gpg_verifier_add_keyring_dir (OstreeGpgVerifier *self,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error);
|
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,
|
gboolean _ostree_gpg_verifier_add_global_keyring_dir (OstreeGpgVerifier *self,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
void _ostree_gpg_verifier_add_keyring (OstreeGpgVerifier *self,
|
void _ostree_gpg_verifier_add_keyring_data (OstreeGpgVerifier *self,
|
||||||
GFile *path);
|
GBytes *data);
|
||||||
|
void _ostree_gpg_verifier_add_keyring_file (OstreeGpgVerifier *self,
|
||||||
|
GFile *path);
|
||||||
|
|
||||||
void _ostree_gpg_verifier_add_key_ascii_file (OstreeGpgVerifier *self,
|
void _ostree_gpg_verifier_add_key_ascii_file (OstreeGpgVerifier *self,
|
||||||
const char *path);
|
const char *path);
|
||||||
|
|
|
||||||
|
|
@ -4202,31 +4202,52 @@ ostree_repo_add_gpg_signature_summary (OstreeRepo *self,
|
||||||
/* Special remote for _ostree_repo_gpg_verify_with_metadata() */
|
/* Special remote for _ostree_repo_gpg_verify_with_metadata() */
|
||||||
static const char *OSTREE_ALL_REMOTES = "__OSTREE_ALL_REMOTES__";
|
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,
|
find_keyring (OstreeRepo *self,
|
||||||
OstreeRemote *remote,
|
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);
|
g_autoptr(GFile) remotes_d = get_remotes_d_dir (self, NULL);
|
||||||
if (remotes_d)
|
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))
|
if (!ot_openat_ignore_enoent (AT_FDCWD, gs_file_get_path_cached (child), &fd, error))
|
||||||
return g_steal_pointer (&file2);
|
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)
|
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 *
|
static OstreeGpgVerifyResult *
|
||||||
|
|
@ -4248,8 +4269,8 @@ _ostree_repo_gpg_verify_data_internal (OstreeRepo *self,
|
||||||
{
|
{
|
||||||
/* Add all available remote keyring files. */
|
/* Add all available remote keyring files. */
|
||||||
|
|
||||||
if (!_ostree_gpg_verifier_add_keyring_dir (verifier, self->repodir,
|
if (!_ostree_gpg_verifier_add_keyring_dir_at (verifier, self->repo_dir_fd, ".",
|
||||||
cancellable, error))
|
cancellable, error))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (remote_name != 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. */
|
/* Add the remote's keyring file if it exists. */
|
||||||
|
|
||||||
OstreeRemote *remote;
|
OstreeRemote *remote;
|
||||||
g_autoptr(GFile) file = NULL;
|
|
||||||
|
|
||||||
remote = _ostree_repo_get_remote_inherited (self, remote_name, error);
|
remote = _ostree_repo_get_remote_inherited (self, remote_name, error);
|
||||||
if (remote == NULL)
|
if (remote == NULL)
|
||||||
return 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;
|
add_global_keyring_dir = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4297,7 +4319,7 @@ _ostree_repo_gpg_verify_data_internal (OstreeRepo *self,
|
||||||
}
|
}
|
||||||
if (extra_keyring != NULL)
|
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,
|
return _ostree_gpg_verifier_check_signature (verifier,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue