remote-modify: Implement --update-metadata as a system-helper method

We download the summary and send it to the system helper, it verifies
the checksum and applies the changes, with the same polkit permissions
required as for an app update (i.e. typically none).

This allows us to update metadata automatically, without permission
requests.
tingping/wmclass
Alexander Larsson 2017-05-08 15:22:54 +02:00
parent b25987255e
commit 9896005ad0
5 changed files with 205 additions and 7 deletions

View File

@ -7609,11 +7609,13 @@ flatpak_dir_list_remote_refs (FlatpakDir *self,
static GVariant *
fetch_remote_summary_file (FlatpakDir *self,
const char *remote,
GBytes **summary_sig_bytes_out,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GError) my_error = NULL;
g_autoptr(GBytes) summary_bytes = NULL;
g_autoptr(GBytes) summary_sig_bytes = NULL;
if (error == NULL)
error = &my_error;
@ -7622,10 +7624,13 @@ fetch_remote_summary_file (FlatpakDir *self,
return NULL;
if (!flatpak_dir_remote_fetch_summary (self, remote,
&summary_bytes, NULL,
&summary_bytes, &summary_sig_bytes,
cancellable, error))
return NULL;
if (summary_sig_bytes_out != NULL)
*summary_sig_bytes_out = g_steal_pointer (&summary_sig_bytes);
return g_variant_ref_sink (g_variant_new_from_bytes (OSTREE_SUMMARY_GVARIANT_FORMAT,
summary_bytes, FALSE));
}
@ -7641,7 +7646,7 @@ flatpak_dir_fetch_remote_title (FlatpakDir *self,
g_autoptr(GVariant) extensions = NULL;
g_autofree char *title = NULL;
summary = fetch_remote_summary_file (self, remote, cancellable, error);
summary = fetch_remote_summary_file (self, remote, NULL, cancellable, error);
if (summary == NULL)
return NULL;
@ -7669,7 +7674,7 @@ flatpak_dir_fetch_remote_default_branch (FlatpakDir *self,
g_autoptr(GVariant) extensions = NULL;
g_autofree char *default_branch = NULL;
summary = fetch_remote_summary_file (self, remote, cancellable, error);
summary = fetch_remote_summary_file (self, remote, NULL, cancellable, error);
if (summary == NULL)
return NULL;
@ -7692,13 +7697,15 @@ flatpak_dir_fetch_remote_summary (FlatpakDir *self,
GCancellable *cancellable,
GError **error)
{
return fetch_remote_summary_file (self, remote, cancellable, error);
return fetch_remote_summary_file (self, remote, NULL, cancellable, error);
}
gboolean
flatpak_dir_update_remote_configuration_for_summary (FlatpakDir *self,
const char *remote,
GVariant *summary,
gboolean dry_run,
gboolean *has_changed_out,
GCancellable *cancellable,
GError **error)
{
@ -7778,7 +7785,10 @@ flatpak_dir_update_remote_configuration_for_summary (FlatpakDir *self,
i += 2;
}
if (!has_changed)
if (has_changed_out)
*has_changed_out = has_changed;
if (dry_run || !has_changed)
return TRUE;
if (flatpak_dir_use_system_helper (self, NULL))
@ -7820,12 +7830,64 @@ flatpak_dir_update_remote_configuration (FlatpakDir *self,
GError **error)
{
g_autoptr(GVariant) summary = NULL;
g_autoptr(GBytes) summary_sig_bytes = NULL;
summary = fetch_remote_summary_file (self, remote, cancellable, error);
summary = fetch_remote_summary_file (self, remote, &summary_sig_bytes, cancellable, error);
if (summary == NULL)
return FALSE;
return flatpak_dir_update_remote_configuration_for_summary (self, remote, summary, cancellable, error);
if (flatpak_dir_use_system_helper (self, NULL))
{
gboolean has_changed = FALSE;
if (!flatpak_dir_update_remote_configuration_for_summary (self, remote, summary, TRUE, &has_changed, cancellable, error))
return FALSE;
if (summary_sig_bytes == NULL)
return flatpak_fail (error, _("Can't update remote configuration as user, no GPG signature exist"));
if (has_changed)
{
g_autoptr(GBytes) bytes = g_variant_get_data_as_bytes (summary);
glnx_fd_close int summary_fd = -1;
g_autofree char *summary_path = NULL;
glnx_fd_close int summary_sig_fd = -1;
g_autofree char *summary_sig_path = NULL;
FlatpakSystemHelper *system_helper;
const char *installation;
system_helper = flatpak_dir_get_system_helper (self);
g_assert (system_helper != NULL);
summary_fd = g_file_open_tmp ("remote-summary.XXXXXX", &summary_path, error);
if (summary_fd == -1)
return FALSE;
if (glnx_loop_write (summary_fd, g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes)) < 0)
return glnx_throw_errno (error);
summary_sig_fd = g_file_open_tmp ("remote-summary-sig.XXXXXX", &summary_sig_path, error);
if (summary_sig_fd == -1)
return FALSE;
if (glnx_loop_write (summary_sig_fd, g_bytes_get_data (summary_sig_bytes, NULL), g_bytes_get_size (summary_sig_bytes)) < 0)
return glnx_throw_errno (error);
installation = flatpak_dir_get_id (self);
g_debug ("Calling system helper: UpdateRemote");
if (!flatpak_system_helper_call_update_remote_sync (system_helper, 0, remote,
installation ? installation : "",
summary_path, summary_sig_path,
cancellable, error))
return FALSE;
unlink (summary_path);
unlink (summary_sig_path);
}
return TRUE;
}
return flatpak_dir_update_remote_configuration_for_summary (self, remote, summary, FALSE, NULL, cancellable, error);
}
static gboolean

View File

@ -94,6 +94,12 @@ typedef enum {
#define FLATPAK_HELPER_CONFIGURE_REMOTE_FLAGS_ALL (FLATPAK_HELPER_CONFIGURE_REMOTE_FLAGS_FORCE_REMOVE)
typedef enum {
FLATPAK_HELPER_UPDATE_REMOTE_FLAGS_NONE = 0,
} FlatpakHelperUpdateRemoteFlags;
#define FLATPAK_HELPER_UPDATE_REMOTE_FLAGS_ALL (0)
typedef enum {
FLATPAK_PULL_FLAGS_NONE = 0,
FLATPAK_PULL_FLAGS_DOWNLOAD_EXTRA_DATA = 1 << 0,
@ -528,6 +534,8 @@ gboolean flatpak_dir_update_remote_configuration (FlatpakDir *self,
gboolean flatpak_dir_update_remote_configuration_for_summary (FlatpakDir *self,
const char *remote,
GVariant *summary,
gboolean dry_run,
gboolean *has_changed_out,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_fetch_ref_cache (FlatpakDir *self,

View File

@ -99,6 +99,14 @@
<arg type='s' name='installation' direction='in'/>
</method>
<method name="UpdateRemote">
<arg type='u' name='flags' direction='in'/>
<arg type='s' name='remote' direction='in'/>
<arg type='s' name='installation' direction='in'/>
<arg type='ay' name='summary_path' direction='in'/>
<arg type='ay' name='summary_sig_path' direction='in'/>
</method>
</interface>
</node>

View File

@ -677,6 +677,100 @@ handle_configure_remote (FlatpakSystemHelper *object,
return TRUE;
}
static gboolean
handle_update_remote (FlatpakSystemHelper *object,
GDBusMethodInvocation *invocation,
guint arg_flags,
const gchar *arg_remote,
const gchar *arg_installation,
const gchar *arg_summary_path,
const gchar *arg_summary_sig_path)
{
g_autoptr(FlatpakDir) system = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GKeyFile) config = g_key_file_new ();
g_autofree char *group = g_strdup_printf ("remote \"%s\"", arg_remote);
g_autoptr(GBytes) gpg_data = NULL;
gboolean force_remove;
char *summary_data = NULL;
gsize summary_size;
g_autoptr(GBytes) summary_bytes = NULL;
g_autoptr(GVariant) summary = NULL;
char *summary_sig_data = NULL;
gsize summary_sig_size;
g_autoptr(GBytes) summary_sig_bytes = NULL;
g_autoptr(OstreeGpgVerifyResult) gpg_result = NULL;
g_debug ("UpdateRemote %u %s %s %s %s", arg_flags, arg_remote, arg_installation, arg_summary_path, arg_summary_sig_path);
system = dir_get_system (arg_installation, &error);
if (system == NULL)
{
g_dbus_method_invocation_return_gerror (invocation, error);
return TRUE;
}
if (*arg_remote == 0 || strchr (arg_remote, '/') != NULL)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
"Invalid remote name: %s", arg_remote);
return TRUE;
}
if ((arg_flags & ~FLATPAK_HELPER_UPDATE_REMOTE_FLAGS_ALL) != 0)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
"Unsupported flags enabled: 0x%x", (arg_flags & ~FLATPAK_HELPER_UPDATE_REMOTE_FLAGS_ALL));
return TRUE;
}
if (!flatpak_dir_ensure_repo (system, NULL, &error))
{
g_dbus_method_invocation_return_gerror (invocation, error);
return TRUE;
}
if (!g_file_get_contents (arg_summary_path, &summary_data, &summary_size, &error))
{
g_dbus_method_invocation_return_gerror (invocation, error);
return TRUE;
}
summary_bytes = g_bytes_new_take (summary_data, summary_size);
if (!g_file_get_contents (arg_summary_sig_path, &summary_sig_data, &summary_sig_size, &error))
{
g_dbus_method_invocation_return_gerror (invocation, error);
return TRUE;
}
summary_sig_bytes = g_bytes_new_take (summary_sig_data, summary_sig_size);
gpg_result = ostree_repo_verify_summary (flatpak_dir_get_repo (system),
arg_remote,
summary_bytes,
summary_sig_bytes,
NULL, &error);
if (gpg_result == NULL ||
!ostree_gpg_verify_result_require_valid_signature (gpg_result, &error))
{
g_dbus_method_invocation_return_gerror (invocation, error);
return TRUE;
}
summary = g_variant_ref_sink (g_variant_new_from_bytes (OSTREE_SUMMARY_GVARIANT_FORMAT,
summary_bytes, FALSE));
if (!flatpak_dir_update_remote_configuration_for_summary (system, arg_remote, summary,
FALSE, NULL, NULL, &error))
{
g_dbus_method_invocation_return_gerror (invocation, error);
return TRUE;
}
flatpak_system_helper_complete_update_remote (object, invocation);
return TRUE;
}
static gboolean
flatpak_authorize_method_handler (GDBusInterfaceSkeleton *interface,
GDBusMethodInvocation *invocation,
@ -778,6 +872,16 @@ flatpak_authorize_method_handler (GDBusInterfaceSkeleton *interface,
action = "org.freedesktop.Flatpak.configure-remote";
polkit_details_insert (details, "remote", remote);
}
else if (g_strcmp0 (method_name, "UpdateRemote") == 0)
{
const char *remote;
g_variant_get_child (parameters, 1, "&s", &remote);
action = "org.freedesktop.Flatpak.update-remote";
polkit_details_insert (details, "remote", remote);
}
@ -832,6 +936,7 @@ on_bus_acquired (GDBusConnection *connection,
g_signal_connect (helper, "handle-uninstall", G_CALLBACK (handle_uninstall), NULL);
g_signal_connect (helper, "handle-install-bundle", G_CALLBACK (handle_install_bundle), NULL);
g_signal_connect (helper, "handle-configure-remote", G_CALLBACK (handle_configure_remote), NULL);
g_signal_connect (helper, "handle-update-remote", G_CALLBACK (handle_update_remote), NULL);
g_signal_connect (helper, "g-authorize-method",
G_CALLBACK (flatpak_authorize_method_handler),

View File

@ -83,6 +83,21 @@
</defaults>
</action>
<action id="org.freedesktop.Flatpak.update-remote">
<!-- SECURITY:
- Normal users do not need authentication to update metadata
from signed repositories.
-->
<description>Update remote metadata</description>
<message>Authentication is required to update remote info</message>
<icon_name>package-x-generic</icon_name>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="org.freedesktop.Flatpak.install-bundle">
<description>Install bundle</description>
<message>Authentication is required to install software</message>