Provide a way for clients to add new firmware metadata to the system cache

This is only possible if the metadata has been signed by a key that we trust.
This commit is contained in:
Richard Hughes 2015-06-24 16:18:29 +01:00
parent 595f59c8e5
commit ae0efdc5a7
9 changed files with 457 additions and 0 deletions

View File

@ -79,6 +79,7 @@ find %{buildroot} -name '*.la' -exec rm -f {} ';'
%{_libexecdir}/fwupd
%{_bindir}/fwupdmgr
%{_sysconfdir}/pki/fwupd
%{_sysconfdir}/pki/fwupd-metadata
%{_sysconfdir}/dbus-1/system.d/org.freedesktop.fwupd.conf
%{_datadir}/dbus-1/interfaces/org.freedesktop.fwupd.xml
%{_datadir}/polkit-1/actions/org.freedesktop.fwupd.policy
@ -90,6 +91,9 @@ find %{buildroot} -name '*.la' -exec rm -f {} ';'
%dir %{_localstatedir}/lib/fwupd
%{_libdir}/lib*.so.*
%{_libdir}/girepository-1.0/*.typelib
%dir %{_localstatedir}/cache/app-info
%dir %{_localstatedir}/cache/app-info/icons
%dir %{_localstatedir}/cache/app-info/xmls
%files devel
%{_includedir}/fwupd-1

View File

@ -0,0 +1,110 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
mQENBEgu03ABCAC+4WHuoCNAN0G1jHRSF2DAphtTIuZkhKbd3C1BMzvU40O5cwhW
LWILM1IYa4YwYI77tJsLi1Hax9D59NNAKdESqsKGuN/QbeXuAD3qpKA6B51lZD9k
jPizCl+s3q+NxaJb8Rk92yocYyuolNii5qrkD1YazcbFCkuBX2wg7q1hqU8YaGNx
Q3SuKf4Rkkg9T/6mCz6hEE8z4sVLncFY7pqt6ch+ycGz4MWGo9Eh51HvYi2QmSf3
6OjNrKHp1LwPF1V/LYI9dHPXfeWE3tgco8hhDsgYaG2W3yhk8Pn5BhnNGgmiCXQs
Allf7a3U/leXgOMTVJNvx+8yNrHRuI2YZMRhABEBAAG0JFJpY2hhcmQgSHVnaGVz
IDxyaWNoYXJkQGh1Z2hzaWUuY29tPokBNgQTAQIAIAUCSC7TcAIbLwYLCQgHAwIE
FQIIAwQWAgMBAh4BAheAAAoJEBesuo36lw4XBVIH/RKjtx2Xk1782CGX9PZnwLaC
krfPTDlcusAFwqtV9AiECenXGLS3A3Kcq6BOJ9wCh1FF80mRJMwRn2ONvHEkg1Dh
8amv4YD9y4r6mjA6tyk7MOPNCSc8ZYZHUl/RacHAOePnKjMWSsU7n6v+RTpjOWR5
JjyMlIHv7K9h6KEx5VCLaDXLxluQvPc8uYBZJlMBa3K/pGS18RJKKrw0l5/8p5tY
uWPxL4Zay7SWdGiiy3EPcq3GJXu85I1x+LbMbq69BjwQt28B/5iMD0RCbYF0mHG2
6iQNU1Gr8+BX2+CFXLSbo1rPExsrOO3Maz7OjX4VathnqS0h9I+Q3dFlnks6Ic/R
zxnPFwEQAAEBAAAAAAAAAAAAAAAA/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgG
BgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx
NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIy
MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCACQAH0DASIA
AhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgED
AwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2Jy
ggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1
dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJ
ytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAA
AAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJB
UQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNE
RUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJma
oqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP0
9fb3+Pn6/9oADAMBAAIRAxEAPwDtVhmb0FSLaOfvNV4LS4rmJKq2a9yakFrGO1WA
Kpapq1lo1o11fTrFGo6nv7CgLFkQoozgACud1nxx4d0HetzfRtMv/LGL5m/SvLvG
HxR1HVGe10gm1tPus4Hzv757CvOJS8h8yR9xPU55NUo3K5e57VL8bbBXYQaVM4/h
LSAZ/Sn23xptHb9/pMyJ6pICf6V4aGyflFWYmJGGxVOBSSPoTTvit4cvZFSVprVj
xmVOPzGa7OzvbW/gWe0uI5o25DRsCK+T9o525I/lVvTPEOqaBdiawupIWB5A6N9R
0NTyvoJxPq7FGK868G/FSw1xI7XVGjtb8naMcI59vSvRlIZQykEHoRUkNCVn6r/q
R9a0qztUH7taBDtLGLXPvV2q2nDFoPrVrFAFelxSCgnAJpDMXxH4kttAtCzkGZlJ
Re3414vrfiX+3b5pLr992CEkKPoBS/EPWJrzxDMjsQinaoBB4rQ8DeF47krf3ceR
1jVv51nNpLmkdlCF3ZbmRNoS3tiZbezaJ8epxXMzaTOrnzFOFznjpivpGLSoHi2G
NcemKyrvwZZzb1EQG7g4rGniGmdlTC3R4Pb6cDyFzxnmrtvpMk7BY0JbOMAV6W3w
9mguv3Kh4zkD1Ga7jwz4EtdPtxLdKHlJzjHSrdZyehl7FQV5Hitr4IvrxisULZAz
nHWs3VPBmq2BYS2zADvjg19Sx6fa23+qiVfwqC8s4LqMpLGrA+oqfaziPkpzPkGS
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
vEI5YQ==
=/V/G
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -1,4 +1,7 @@
pkidir = $(sysconfdir)/pki/fwupd
dist_pki_DATA = GPG-KEY-Hughski-Limited
pkimetadatadir = $(sysconfdir)/pki/fwupd-metadata
dist_pkimetadata_DATA = GPG-KEY-Linux-Vendor-Firmware-Service
-include $(top_srcdir)/git.mk

View File

@ -166,6 +166,8 @@ install-data-hook:
if test -w $(DESTDIR)$(prefix)/; then \
mkdir -p $(DESTDIR)$(localstatedir)/lib/fwupd; \
chmod 0755 $(DESTDIR)$(localstatedir)/lib/fwupd; \
mkdir -p $(DESTDIR)$(localstatedir)/cache/app-info/xmls; \
mkdir -p $(DESTDIR)$(localstatedir)/cache/app-info/icons; \
fi
TESTS = fu-self-test

View File

@ -321,6 +321,94 @@ out:
return ret;
}
/**
* fu_keyring_verify_data:
**/
gboolean
fu_keyring_verify_data (FuKeyring *keyring,
GBytes *payload,
GBytes *payload_signature,
GError **error)
{
gboolean ret = TRUE;
gpgme_data_t data = NULL;
gpgme_data_t sig = NULL;
gpgme_error_t rc;
gpgme_signature_t s;
gpgme_verify_result_t result;
g_return_val_if_fail (FU_IS_KEYRING (keyring), FALSE);
g_return_val_if_fail (payload != NULL, FALSE);
g_return_val_if_fail (payload_signature != NULL, FALSE);
/* setup context */
if (!fu_keyring_setup (keyring, error))
return FALSE;
/* load file data */
rc = gpgme_data_new_from_mem (&data,
g_bytes_get_data (payload, NULL),
g_bytes_get_size (payload), 0);
if (rc != GPG_ERR_NO_ERROR) {
ret = FALSE;
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"failed to load data: %s",
gpgme_strerror (rc));
goto out;
}
rc = gpgme_data_new_from_mem (&sig,
g_bytes_get_data (payload_signature, NULL),
g_bytes_get_size (payload_signature), 0);
if (rc != GPG_ERR_NO_ERROR) {
ret = FALSE;
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"failed to load signature: %s",
gpgme_strerror (rc));
goto out;
}
/* verify */
rc = gpgme_op_verify (keyring->priv->ctx, sig, data, NULL);
if (rc != GPG_ERR_NO_ERROR) {
ret = FALSE;
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"failed to verify data: %s",
gpgme_strerror (rc));
goto out;
}
/* verify the result */
result = gpgme_op_verify_result (keyring->priv->ctx);
if (result == NULL) {
ret = FALSE;
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"no result record from libgpgme");
goto out;
}
/* look at each signature */
for (s = result->signatures; s != NULL ; s = s->next ) {
ret = fu_keyring_check_signature (s, error);
if (!ret)
goto out;
}
out:
if (data != NULL)
gpgme_data_release (data);
if (sig != NULL)
gpgme_data_release (sig);
return ret;
}
/**
* fu_keyring_class_init:
**/

View File

@ -63,6 +63,10 @@ gboolean fu_keyring_verify_file (FuKeyring *keyring,
const gchar *filename,
const gchar *signature,
GError **error);
gboolean fu_keyring_verify_data (FuKeyring *keyring,
GBytes *payload,
GBytes *payload_signature,
GError **error);
G_END_DECLS

View File

@ -26,6 +26,7 @@
#include <glib/gstdio.h>
#include <gio/gio.h>
#include <gio/gunixfdlist.h>
#include <gio/gunixinputstream.h>
#include <glib/gi18n.h>
#include <locale.h>
#include <polkit/polkit.h>
@ -36,6 +37,7 @@
#include "fu-cleanup.h"
#include "fu-debug.h"
#include "fu-device.h"
#include "fu-keyring.h"
#include "fu-pending.h"
#include "fu-provider.h"
#include "fu-provider-usb.h"
@ -566,6 +568,101 @@ fu_main_get_action_id_for_device (FuMainAuthHelper *helper)
return "org.freedesktop.fwupd.update-internal";
}
/**
* fu_main_daemon_update_metadata:
*
* Supports optionally GZipped AppStream files up to 1MiB in size.
**/
static gboolean
fu_main_daemon_update_metadata (gint fd, gint fd_sig, GError **error)
{
guint8 magic[2];
_cleanup_bytes_unref_ GBytes *bytes = NULL;
_cleanup_bytes_unref_ GBytes *bytes_raw = NULL;
_cleanup_bytes_unref_ GBytes *bytes_sig = NULL;
_cleanup_object_unref_ AsStore *store = NULL;
_cleanup_object_unref_ FuKeyring *kr = NULL;
_cleanup_object_unref_ GConverter *converter = NULL;
_cleanup_object_unref_ GFile *file = NULL;
_cleanup_object_unref_ GInputStream *stream_buf = NULL;
_cleanup_object_unref_ GInputStream *stream_fd = NULL;
_cleanup_object_unref_ GInputStream *stream = NULL;
_cleanup_object_unref_ GInputStream *stream_sig = NULL;
/* open existing file if it exists */
store = as_store_new ();
file = g_file_new_for_path ("/var/cache/app-info/xmls/fwupd.xml");
if (g_file_query_exists (file, NULL)) {
if (!as_store_from_file (store, file, NULL, NULL, error))
return FALSE;
}
/* read the entire file into memory */
stream_fd = g_unix_input_stream_new (fd, TRUE);
bytes_raw = g_input_stream_read_bytes (stream_fd, 0x100000, NULL, error);
if (bytes_raw == NULL)
return FALSE;
stream_buf = g_memory_input_stream_new ();
g_memory_input_stream_add_bytes (G_MEMORY_INPUT_STREAM (stream_buf), bytes_raw);
/* peek the file type and get data */
if (g_input_stream_read (stream_buf, magic, 2, NULL, error) == -1)
return FALSE;
if (magic[0] == 0x1f && magic[1] == 0x8b) {
g_debug ("using GZip decompressor for data");
if (!g_seekable_seek (G_SEEKABLE (stream_buf), 0, G_SEEK_SET, NULL, error))
return FALSE;
converter = G_CONVERTER (g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP));
stream = g_converter_input_stream_new (stream_buf, converter);
bytes = g_input_stream_read_bytes (stream, 0x100000, NULL, error);
if (bytes == NULL)
return FALSE;
} else if (magic[0] == '<' && magic[1] == '?') {
g_debug ("using no decompressor for data");
bytes = g_bytes_ref (bytes_raw);
} else {
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE,
"file type '0x%02x,0x%02x' not supported",
magic[0], magic[1]);
return FALSE;
}
/* read signature */
stream_sig = g_unix_input_stream_new (fd_sig, TRUE);
bytes_sig = g_input_stream_read_bytes (stream_sig, 0x800, NULL, error);
if (bytes_sig == NULL)
return FALSE;
/* verify file */
kr = fu_keyring_new ();
if (!fu_keyring_add_public_keys (kr, "/etc/pki/fwupd-metadata", error))
return FALSE;
if (!fu_keyring_verify_data (kr, bytes_raw, bytes_sig, error))
return FALSE;
/* merge in the new contents */
g_debug ("Store was %i size", as_store_get_size (store));
if (!as_store_from_xml (store,
g_bytes_get_data (bytes, NULL), -1,
NULL, error))
return FALSE;
g_debug ("Store now %i size", as_store_get_size (store));
/* save the new file */
as_store_set_api_version (store, 0.9);
if (!as_store_to_file (store, file,
AS_NODE_TO_XML_FLAG_ADD_HEADER |
AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE |
AS_NODE_TO_XML_FLAG_FORMAT_INDENT,
NULL, error)) {
return FALSE;
}
return TRUE;
}
/**
* fu_main_daemon_method_call:
**/
@ -648,6 +745,42 @@ fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender,
return;
}
/* return '' */
if (g_strcmp0 (method_name, "UpdateMetadata") == 0) {
GDBusMessage *message;
GUnixFDList *fd_list;
gint fd_data;
gint fd_sig;
_cleanup_error_free_ GError *error = NULL;
message = g_dbus_method_invocation_get_message (invocation);
fd_list = g_dbus_message_get_unix_fd_list (message);
if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 2) {
g_dbus_method_invocation_return_error (invocation,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"invalid handle");
return;
}
fd_data = g_unix_fd_list_get (fd_list, 0, &error);
if (fd_data < 0) {
g_dbus_method_invocation_return_gerror (invocation, error);
return;
}
fd_sig = g_unix_fd_list_get (fd_list, 1, &error);
if (fd_sig < 0) {
g_dbus_method_invocation_return_gerror (invocation, error);
return;
}
if (!fu_main_daemon_update_metadata (fd_data, fd_sig, &error)) {
g_prefix_error (&error, "failed to update metadata: ");
g_dbus_method_invocation_return_gerror (invocation, error);
return;
}
g_dbus_method_invocation_return_value (invocation, NULL);
return;
}
/* return '' */
if (g_strcmp0 (method_name, "Update") == 0) {
FuDeviceItem *item = NULL;

View File

@ -776,6 +776,84 @@ fu_util_clear_results (FuUtilPrivate *priv, gchar **values, GError **error)
return TRUE;
}
/**
* fu_util_update_metadata:
**/
static gboolean
fu_util_update_metadata (FuUtilPrivate *priv, gchar **values, GError **error)
{
GVariant *body;
gint fd;
gint fd_sig;
_cleanup_object_unref_ GDBusMessage *request = NULL;
_cleanup_object_unref_ GUnixFDList *fd_list = NULL;
if (g_strv_length (values) != 2) {
g_set_error_literal (error,
FWUPD_ERROR,
FWUPD_ERROR_INTERNAL,
"Invalid arguments: expected 'filename.xml' 'filename.xml.asc'");
return FALSE;
}
/* open file */
fd = open (values[0], O_RDONLY);
if (fd < 0) {
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE,
"failed to open %s",
values[0]);
return FALSE;
}
fd_sig = open (values[1], O_RDONLY);
if (fd_sig < 0) {
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_INVALID_FILE,
"failed to open %s",
values[1]);
return FALSE;
}
/* set out of band file descriptor */
fd_list = g_unix_fd_list_new ();
g_unix_fd_list_append (fd_list, fd, NULL);
g_unix_fd_list_append (fd_list, fd_sig, NULL);
request = g_dbus_message_new_method_call (FWUPD_DBUS_SERVICE,
FWUPD_DBUS_PATH,
FWUPD_DBUS_INTERFACE,
"UpdateMetadata");
g_dbus_message_set_unix_fd_list (request, fd_list);
/* g_unix_fd_list_append did a dup() already */
close (fd);
close (fd_sig);
/* send message */
body = g_variant_new ("(hh)", fd, fd_sig);
g_dbus_message_set_body (request, body);
g_dbus_connection_send_message_with_reply (priv->conn,
request,
G_DBUS_SEND_MESSAGE_FLAGS_NONE,
-1,
NULL,
NULL,
fu_util_update_cb,
priv);
g_main_loop_run (priv->loop);
if (priv->message == NULL) {
g_dbus_error_strip_remote_error (priv->error);
g_propagate_error (error, priv->error);
return FALSE;
}
if (g_dbus_message_to_gerror (priv->message, error)) {
g_dbus_error_strip_remote_error (*error);
return FALSE;
}
return TRUE;
}
/**
* fu_util_get_results:
**/
@ -1061,6 +1139,12 @@ main (int argc, char *argv[])
/* TRANSLATORS: command description */
_("Gets the results from the last update"),
fu_util_get_results);
fu_util_add (priv->cmd_array,
"update-metadata",
NULL,
/* TRANSLATORS: command description */
_("Updates metadata"),
fu_util_update_metadata);
/* sort by command name */
g_ptr_array_sort (priv->cmd_array,

View File

@ -169,6 +169,35 @@
</arg>
</method>
<!--***********************************************************-->
<method name='UpdateMetadata'>
<doc:doc>
<doc:description>
<doc:para>
Adds AppStream resource information from a session client.
</doc:para>
</doc:description>
</doc:doc>
<arg type='h' name='data' direction='in'>
<doc:doc>
<doc:summary>
<doc:para>
File handle to AppStream metadata.
</doc:para>
</doc:summary>
</doc:doc>
</arg>
<arg type='h' name='signature' direction='in'>
<doc:doc>
<doc:summary>
<doc:para>
File handle to AppStream metadata GPG signature.
</doc:para>
</doc:summary>
</doc:doc>
</arg>
</method>
<!--***********************************************************-->
<signal name='Changed'>
<doc:doc>