summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules4
-rw-r--r--Makefile.am13
m---------dbus-proxy0
-rw-r--r--dbus-proxy/Makefile.am.inc12
-rw-r--r--dbus-proxy/dbus-proxy.c322
-rw-r--r--dbus-proxy/flatpak-proxy.c2852
-rw-r--r--dbus-proxy/flatpak-proxy.h68
7 files changed, 15 insertions, 3256 deletions
diff --git a/.gitmodules b/.gitmodules
index 7b8cda87..c025d05b 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -5,3 +5,7 @@
path = bubblewrap
url = https://github.com/projectatomic/bubblewrap.git
ignore = dirty
+[submodule "dbus-proxy"]
+ path = dbus-proxy
+ url = https://github.com/flatpak/xdg-dbus-proxy.git
+ branch = master
diff --git a/Makefile.am b/Makefile.am
index 6516cc2b..1b0af08a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -96,10 +96,19 @@ include app/Makefile.am.inc
include session-helper/Makefile.am.inc
include portal/Makefile.am.inc
include system-helper/Makefile.am.inc
+include tests/Makefile.am.inc
+
if !WITH_SYSTEM_DBUS_PROXY
-include dbus-proxy/Makefile.am.inc
+libexec_PROGRAMS+=flatpak-dbus-proxy
+flatpak_dbus_proxy_SOURCES = \
+ dbus-proxy/flatpak-proxy.c \
+ dbus-proxy/flatpak-proxy.h \
+ dbus-proxy/dbus-proxy.c \
+ dbus-proxy/backport-autoptr.h \
+ $(NULL)
+flatpak_dbus_proxy_LDADD = $(AM_LDADD) $(BASE_LIBS)
+flatpak_dbus_proxy_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS)
endif
-include tests/Makefile.am.inc
if !WITH_SYSTEM_BWRAP
diff --git a/dbus-proxy b/dbus-proxy
new file mode 160000
+Subproject ef4d1d05efe1b3498152b86b18df64a4622d15e
diff --git a/dbus-proxy/Makefile.am.inc b/dbus-proxy/Makefile.am.inc
deleted file mode 100644
index c25d7af3..00000000
--- a/dbus-proxy/Makefile.am.inc
+++ /dev/null
@@ -1,12 +0,0 @@
-libexec_PROGRAMS += \
- flatpak-dbus-proxy \
- $(NULL)
-
-flatpak_dbus_proxy_SOURCES = \
- dbus-proxy/flatpak-proxy.c \
- dbus-proxy/flatpak-proxy.h \
- dbus-proxy/dbus-proxy.c \
- $(NULL)
-
-flatpak_dbus_proxy_LDADD = $(AM_LDADD) $(BASE_LIBS) libglnx.la
-flatpak_dbus_proxy_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS) -I$(srcdir)/dbus-proxy
diff --git a/dbus-proxy/dbus-proxy.c b/dbus-proxy/dbus-proxy.c
deleted file mode 100644
index d0be7c4f..00000000
--- a/dbus-proxy/dbus-proxy.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright © 2015 Red Hat, Inc
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Alexander Larsson <alexl@redhat.com>
- */
-
-#include "config.h"
-
-#include <string.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include "libglnx/libglnx.h"
-
-#include "flatpak-proxy.h"
-
-static GList *proxies;
-static int sync_fd = -1;
-
-static void
-add_args (GBytes *bytes,
- GPtrArray *args,
- int pos)
-{
- gsize data_len, remainder_len;
- const guchar *data = g_bytes_get_data (bytes, &data_len);
- guchar *s;
- const guchar *remainder;
-
- remainder = data;
- remainder_len = data_len;
- s = memchr (remainder, 0, remainder_len);
- while (s)
- {
- gsize len = s - remainder;
- char *arg = g_strndup ((char *) remainder, len);
- g_ptr_array_insert (args, pos++, arg);
- remainder = s + 1;
- remainder_len -= len + 1;
- s = memchr (remainder, 0, remainder_len);
- }
-
- if (remainder_len)
- {
- char *arg = g_strndup ((char *) remainder, remainder_len);
- g_ptr_array_insert (args, pos++, arg);
- }
-}
-
-
-static gboolean
-parse_generic_args (GPtrArray *args, int *args_i)
-{
- const char *arg = g_ptr_array_index (args, *args_i);
-
- if (g_str_has_prefix (arg, "--fd="))
- {
- const char *fd_s = arg + strlen ("--fd=");
- char *endptr;
- int fd;
-
- fd = strtol (fd_s, &endptr, 10);
- if (fd < 0 || endptr == fd_s || *endptr != 0)
- {
- g_printerr ("Invalid fd %s\n", fd_s);
- return FALSE;
- }
- sync_fd = fd;
-
- *args_i += 1;
-
- return TRUE;
- }
- else if (g_str_has_prefix (arg, "--args="))
- {
- const char *fd_s = arg + strlen ("--args=");
- char *endptr;
- int fd;
- g_autoptr(GBytes) data = NULL;
- g_autoptr(GError) error = NULL;
-
- fd = strtol (fd_s, &endptr, 10);
- if (fd < 0 || endptr == fd_s || *endptr != 0)
- {
- g_printerr ("Invalid --args fd %s\n", fd_s);
- return FALSE;
- }
-
- data = glnx_fd_readall_bytes (fd, NULL, &error);
-
- if (data == NULL)
- {
- g_printerr ("Failed to load --args: %s\n", error->message);
- return FALSE;
- }
-
- *args_i += 1;
-
- add_args (data, args, *args_i);
-
- return TRUE;
- }
- else
- {
- g_printerr ("Unknown argument %s\n", arg);
- return FALSE;
- }
-}
-
-static gboolean
-start_proxy (GPtrArray *args, int *args_i)
-{
- g_autoptr(FlatpakProxy) proxy = NULL;
- g_autoptr(GError) error = NULL;
- const char *bus_address, *socket_path;
- const char *arg;
-
- if (*args_i >= args->len || ((char *) g_ptr_array_index (args, *args_i))[0] == '-')
- {
- g_printerr ("No bus address given\n");
- return FALSE;
- }
-
- bus_address = g_ptr_array_index (args, *args_i);
- *args_i += 1;
-
- if (*args_i >= args->len || ((char *) g_ptr_array_index (args, *args_i))[0] == '-')
- {
- g_printerr ("No socket path given\n");
- return FALSE;
- }
-
- socket_path = g_ptr_array_index (args, *args_i);
- *args_i += 1;
-
- proxy = flatpak_proxy_new (bus_address, socket_path);
-
- while (*args_i < args->len)
- {
- arg = g_ptr_array_index (args, *args_i);
-
- if (arg[0] != '-')
- break;
-
- if (g_str_has_prefix (arg, "--see=") ||
- g_str_has_prefix (arg, "--talk=") ||
- g_str_has_prefix (arg, "--own="))
- {
- FlatpakPolicy policy = FLATPAK_POLICY_SEE;
- g_autofree char *name = g_strdup (strchr (arg, '=') + 1);
- gboolean wildcard = FALSE;
-
- if (arg[2] == 't')
- policy = FLATPAK_POLICY_TALK;
- else if (arg[2] == 'o')
- policy = FLATPAK_POLICY_OWN;
-
- if (g_str_has_suffix (name, ".*"))
- {
- name[strlen (name) - 2] = 0;
- wildcard = TRUE;
- }
-
- if (name[0] == ':' || !g_dbus_is_name (name))
- {
- g_printerr ("'%s' is not a valid dbus name\n", name);
- return FALSE;
- }
-
- flatpak_proxy_add_policy (proxy, name, wildcard, policy);
-
- *args_i += 1;
- }
- else if (g_str_has_prefix (arg, "--call=") ||
- g_str_has_prefix (arg, "--broadcast="))
- {
- g_autofree char *rest = g_strdup (strchr (arg, '=') + 1);
- char *name = rest;
- char *rule;
- char *name_end = strchr (rest, '=');
- gboolean wildcard = FALSE;
-
- if (name_end == NULL)
- {
- g_printerr ("'%s' is not a valid name + rule\n", rest);
- return FALSE;
- }
-
- *name_end = 0;
- rule = name_end + 1;
-
- if (g_str_has_suffix (name, ".*"))
- {
- name[strlen (name) - 2] = 0;
- wildcard = TRUE;
- }
-
- if (g_str_has_prefix (arg, "--call="))
- flatpak_proxy_add_call_rule (proxy, name, wildcard, rule);
- else
- flatpak_proxy_add_broadcast_rule (proxy, name, wildcard, rule);
-
- *args_i += 1;
- }
- else if (g_str_equal (arg, "--log"))
- {
- flatpak_proxy_set_log_messages (proxy, TRUE);
- *args_i += 1;
- }
- else if (g_str_equal (arg, "--filter"))
- {
- flatpak_proxy_set_filter (proxy, TRUE);
- *args_i += 1;
- }
- else if (g_str_equal (arg, "--sloppy-names"))
- {
- /* This means we're reporing the name changes for all unique names,
- which is needed for the a11y bus */
- flatpak_proxy_set_sloppy_names (proxy, TRUE);
- *args_i += 1;
- }
- else
- {
- if (!parse_generic_args (args, args_i))
- return FALSE;
- }
- }
-
- if (!flatpak_proxy_start (proxy, &error))
- {
- g_printerr ("Failed to start proxy for %s: %s\n", bus_address, error->message);
- return FALSE;
- }
-
- proxies = g_list_prepend (proxies, g_object_ref (proxy));
-
- return TRUE;
-}
-
-static gboolean
-sync_closed_cb (GIOChannel *source,
- GIOCondition condition,
- gpointer data)
-{
- GList *l;
-
- for (l = proxies; l != NULL; l = l->next)
- flatpak_proxy_stop (FLATPAK_PROXY (l->data));
-
- exit (0);
- return TRUE;
-}
-
-int
-main (int argc, const char *argv[])
-{
- GMainLoop *service_loop;
- int i, args_i;
-
- g_autoptr(GPtrArray) args = g_ptr_array_new_with_free_func (g_free);
-
- for (i = 1; i < argc; i++)
- g_ptr_array_add (args, g_strdup ((char *) argv[i]));
-
- args_i = 0;
- while (args_i < args->len)
- {
- const char *arg = g_ptr_array_index (args, args_i);
- if (arg[0] == '-')
- {
- if (!parse_generic_args (args, &args_i))
- return 1;
- }
- else
- {
- if (!start_proxy (args, &args_i))
- return 1;
- }
- }
-
- if (proxies == NULL)
- {
- g_printerr ("No proxies specified\n");
- return 1;
- }
-
- if (sync_fd >= 0)
- {
- ssize_t written;
- GIOChannel *sync_channel;
- written = write (sync_fd, "x", 1);
- if (written != 1)
- g_warning ("Can't write to sync socket");
-
- sync_channel = g_io_channel_unix_new (sync_fd);
- g_io_add_watch (sync_channel, G_IO_ERR | G_IO_HUP,
- sync_closed_cb, NULL);
- }
-
- service_loop = g_main_loop_new (NULL, FALSE);
- g_main_loop_run (service_loop);
-
- g_main_loop_unref (service_loop);
-
- return 0;
-}
diff --git a/dbus-proxy/flatpak-proxy.c b/dbus-proxy/flatpak-proxy.c
deleted file mode 100644
index fff7686c..00000000
--- a/dbus-proxy/flatpak-proxy.c
+++ /dev/null
@@ -1,2852 +0,0 @@
-/*
- * Copyright © 2015 Red Hat, Inc
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Alexander Larsson <alexl@redhat.com>
- */
-
-#include "config.h"
-
-#include <unistd.h>
-#include <string.h>
-
-#include "flatpak-proxy.h"
-
-#include <gio/gunixsocketaddress.h>
-#include <gio/gunixconnection.h>
-#include <gio/gunixfdmessage.h>
-
-/**
- * The proxy listens to a unix domain socket, and for each new
- * connection it opens up a new connection to a specified dbus bus
- * address (typically the session bus) and forwards data between the
- * two. During the authentication phase all data is forwarded as
- * received, and additionally for the first 1 byte zero we also send
- * the proxy credentials to the bus.
- *
- * Once the connection is authenticated there are two modes, filtered
- * and unfiltered. In the unfiltered mode we just send all messages on
- * as we receive, but in the in the filtering mode we apply a policy,
- * which is similar to the policy supported by kdbus.
- *
- * The policy for the filtering consists of a mapping from well-known
- * names to a policy that is either SEE, TALK or OWN. The default
- * initial policy is that the the user is only allowed to TALK to the
- * bus itself (org.freedesktop.DBus, or no destination specified), and
- * TALK to its own unique id. All other clients are invisible. The
- * well-known names can be specified exactly, or as a arg0namespace
- * wildcards like "org.foo.*" which matches "org.foo", "org.foo.bar",
- * and "org.foo.bar.gazonk", but not "org.foobar".
- *
- * Polices are specified for well-known names, but they also affect
- * the owner of that name, so that the policy for a unique id is the
- * superset of the polices for all the names it owns. Due to technical
- * reasons the policy for a unique name is "sticky", in that we keep
- * the highest policy granted by a once-owned name even when the client
- * releases that name. This is impossible to avoid in a race-free way
- * in a proxy. But this is rarely a problem in practice, as clients
- * rarely release names and stay on the bus.
- *
- * Here is a description of the policy levels:
- * (all policy levels also imply the ones before it)
- *
- * SEE:
- * The name/id is visible in the ListNames reply
- * The name/id is visible in the ListActivatableNames reply
- * You can call GetNameOwner on the name
- * You can call NameHasOwner on the name
- * You see NameOwnerChanged signals on the name
- * You see NameOwnerChanged signals on the id when the client disconnects
- * You can call the GetXXX methods on the name/id to get e.g. the peer pid
- * You get AccessDenied rather than NameHasNoOwner when sending messages to the name/id
- *
- * TALK:
- * You can send any method calls and signals to the name/id
- * You will receive broadcast signals from the name/id (if you have a match rule for them)
- * You can call StartServiceByName on the name
- *
- * OWN:
- * You are allowed to call RequestName/ReleaseName/ListQueuedOwners on the name.
- *
- * Additionally, there can be more detailed filters installed that
- * limits what messages you can send to and receive broadcasts from.
- * However, if you can *ever* call or recieve broadcasts from a name (even if
- * filtered to some subset of paths/interfaces) its visibility is considered
- * to be as TALK.
- *
- * The policy applies only to outgoing signals and method calls and
- * incoming broadcast. All replies (errors or method returns) are
- * allowed once for an outstanding method call, and never
- * otherwise.
- *
- * Every peer on the bus is considered priviledged, and we thus trust
- * it and don't apply any filtering (except broadcasts). So we rely on
- * similar proxies to be running for all untrusted clients. Any such
- * priviledged peer is allowed to send method call or unicast signal
- * messages to the proxied client. Once another peer
- * sends you a message the unique id of that peer is now made visible
- * (policy SEE) to the proxied client, allowing the client to track
- * caller lifetimes via NameOwnerChanged signals.
- *
- * Differences to kdbus custom endpoint policies:
- *
- * * The proxy will return the credentials (like pid) of the proxy,
- * not the real client.
- *
- * * Policy is not dropped when a peer releases a name.
- *
- * * Peers that call you become visible (SEE) (and get signals for
- * NameOwnerChange disconnect) In kdbus currently custom endpoints
- * never get NameOwnerChange signals for unique ids, but this is
- * problematic as it disallows a services to track lifetimes of its
- * clients.
- *
- * Mode of operation
- *
- * Once authenticated we receive incoming messages one at a time,
- * and then we demarshal the message headers to make routing decisions.
- * This means we trust the bus to do message format validation, etc.
- * (because we don't parse the body). Also we assume that the bus verifies
- * reply_serials, i.e. that a reply can only be sent once and by the real
- * recipient of an previously sent method call.
- *
- * We don't however trust the serials from the client. We verify that
- * they are strictly increasing to make sure the code is not confused
- * by serials being reused.
- *
- * In order to track the ownership of the allowed names we hijack the
- * connection after the initial Hello message, sending AddMatch,
- * ListNames and GetNameOwner messages to get a proper view of who
- * owns the names atm. Then we listen to NameOwnerChanged events for
- * further updates. This causes a slight offset between serials in the
- * client and serials as seen by the bus.
- *
- * After that the filter is strictly passive, in that we never
- * construct our own requests. For each message received from the
- * client we look up the type and the destination policy and make a
- * decision to either pass it on as is, rewrite it before passing on
- * (for instance ListName replies), drop it completely, or return a
- * made-up reply/error to the sender.
- *
- * When returning a made-up reply we replace the actual message with a
- * Ping request to the bus with the same serial and replace the resulting
- * reply with the made up reply (with the serial from the Ping reply).
- * This means we keep the strict message ordering and serial numbers of
- * the bus.
- *
- * Policy is applied to unique ids in the following cases:
- * * During startup we call AddWatch for signals on all policy names
- * and wildcards (using arg0namespace) so that we get NameOwnerChanged
- * events which we use to update the unique id policies.
- * * During startup we create synthetic GetNameOwner requests for all
- * normal policy names, and if there are wildcarded names we create a
- * synthetic ListNames request and use the results of that to do further
- * GetNameOwner for the existing names matching the wildcards. When we get
- * replies for the GetNameOwner requests the unique id policy is updated.
- * * When we get a method call from a unique id, it gets SEE
- * * When we get a reply to the initial Hello request we give
- * our own assigned unique id policy TALK.
- *
- * There is also a mode called "sloppy-names" where you automatically get
- * SEE access to all the unique names on the bus. This is used only for
- * the a11y bus.
- *
- * All messages sent to the bus itself are fully demarshalled
- * and handled on a per-method basis:
- *
- * Hello, AddMatch, RemoveMatch, GetId: Always allowed
- * ListNames, ListActivatableNames: Always allowed, but response filtered
- * UpdateActivationEnvironment, BecomeMonitor: Always denied
- * RequestName, ReleaseName, ListQueuedOwners: Only allowed if arg0 is a name with policy OWN
- * NameHasOwner, GetNameOwner: Only pass on if arg0 is a name with policy SEE, otherwise return synthetic reply
- * StartServiceByName: Only allowed if policy TALK on arg0
- * GetConnectionUnixProcessID, GetConnectionCredentials,
- * GetAdtAuditSessionData, GetConnectionSELinuxSecurityContext,
- * GetConnectionUnixUser: Allowed if policy SEE on arg0
- *
- * For unknown methods, we return a synthetic error.
- */
-
-typedef struct FlatpakProxyClient FlatpakProxyClient;
-
-#define FIND_AUTH_END_CONTINUE -1
-#define FIND_AUTH_END_ABORT -2
-
-#define AUTH_LINE_SENTINEL "\r\n"
-#define AUTH_BEGIN "BEGIN"
-
-typedef enum {
- EXPECTED_REPLY_NONE,
- EXPECTED_REPLY_NORMAL,
- EXPECTED_REPLY_HELLO,
- EXPECTED_REPLY_FILTER,
- EXPECTED_REPLY_FAKE_GET_NAME_OWNER,
- EXPECTED_REPLY_FAKE_LIST_NAMES,
- EXPECTED_REPLY_LIST_NAMES,
- EXPECTED_REPLY_REWRITE,
-} ExpectedReplyType;
-
-typedef struct
-{
- gsize size;
- gsize pos;
- int refcount;
- gboolean send_credentials;
- GList *control_messages;
-
- guchar data[16];
- /* data continues here */
-} Buffer;
-
-typedef struct
-{
- Buffer *buffer;
- gboolean big_endian;
- guchar type;
- guchar flags;
- guint32 length;
- guint32 serial;
- const char *path;
- const char *interface;
- const char *member;
- const char *error_name;
- const char *destination;
- const char *sender;
- const char *signature;
- gboolean has_reply_serial;
- guint32 reply_serial;
- guint32 unix_fds;
-} Header;
-
-typedef enum {
- FILTER_TYPE_CALL = 1 << 0,
- FILTER_TYPE_BROADCAST = 1 << 1,
-} FilterTypeMask;
-
-#define FILTER_TYPE_ALL (FILTER_TYPE_CALL | FILTER_TYPE_BROADCAST)
-
-typedef struct
-{
- char *name;
- gboolean name_is_subtree;
- FlatpakPolicy policy;
-
- /* More detailed filter */
- FilterTypeMask types;
- char *path;
- gboolean path_is_subtree;
- char *interface;
- char *member;
-} Filter;
-
-static void header_free (Header *header);
-G_DEFINE_AUTOPTR_CLEANUP_FUNC (Header, header_free)
-
-typedef struct
-{
- gboolean got_first_byte; /* always true on bus side */
- gboolean closed; /* always true on bus side */
-
- FlatpakProxyClient *client;
- GSocketConnection *connection;
- GSource *in_source;
- GSource *out_source;
-
- GBytes *extra_input_data;
- Buffer *current_read_buffer;
- Buffer header_buffer;
-
- GList *buffers; /* to be sent */
- GList *control_messages;
-
- GHashTable *expected_replies;
-} ProxySide;
-
-struct FlatpakProxyClient
-{
- GObject parent;
-
- FlatpakProxy *proxy;
-
- gboolean authenticated;
- GByteArray *auth_buffer;
-
- ProxySide client_side;
- ProxySide bus_side;
-
- /* Filtering data: */
- guint32 serial_offset;
- guint32 hello_serial;
- guint32 last_serial;
- GHashTable *rewrite_reply;
- GHashTable *get_owner_reply;
-
- GHashTable *unique_id_policy;
- GHashTable *unique_id_owned_names;
-};
-
-typedef struct
-{
- GObjectClass parent_class;
-} FlatpakProxyClientClass;
-
-struct FlatpakProxy
-{
- GSocketService parent;
-
- gboolean log_messages;
-
- GList *clients;
- char *socket_path;
- char *dbus_address;
-
- gboolean filter;
- gboolean sloppy_names;
-
- GHashTable *filters;
-};
-
-typedef struct
-{
- GSocketServiceClass parent_class;
-} FlatpakProxyClass;
-
-
-enum {
- PROP_0,
-
- PROP_DBUS_ADDRESS,
- PROP_SOCKET_PATH
-};
-
-#define FLATPAK_TYPE_PROXY flatpak_proxy_get_type ()
-#define FLATPAK_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_PROXY, FlatpakProxy))
-#define FLATPAK_IS_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_PROXY))
-
-
-#define FLATPAK_TYPE_PROXY_CLIENT flatpak_proxy_client_get_type ()
-#define FLATPAK_PROXY_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_PROXY_CLIENT, FlatpakProxyClient))
-#define FLATPAK_IS_PROXY_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_PROXY_CLIENT))
-
-GType flatpak_proxy_client_get_type (void);
-
-G_DEFINE_TYPE (FlatpakProxy, flatpak_proxy, G_TYPE_SOCKET_SERVICE)
-G_DEFINE_TYPE (FlatpakProxyClient, flatpak_proxy_client, G_TYPE_OBJECT)
-
-static void start_reading (ProxySide *side);
-static void stop_reading (ProxySide *side);
-
-static void
-string_list_free (GList *filters)
-{
- g_list_free_full (filters, (GDestroyNotify) g_free);
-}
-
-static void
-buffer_unref (Buffer *buffer)
-{
- g_assert (buffer->refcount > 0);
- buffer->refcount--;
-
- if (buffer->refcount == 0)
- {
- g_list_free_full (buffer->control_messages, g_object_unref);
- g_free (buffer);
- }
-}
-
-static Buffer *
-buffer_ref (Buffer *buffer)
-{
- g_assert (buffer->refcount > 0);
- buffer->refcount++;
- return buffer;
-}
-
-static void
-free_side (ProxySide *side)
-{
- g_clear_object (&side->connection);
- g_clear_pointer (&side->extra_input_data, g_bytes_unref);
-
- g_list_free_full (side->buffers, (GDestroyNotify) buffer_unref);
- g_list_free_full (side->control_messages, (GDestroyNotify) g_object_unref);
-
- if (side->in_source)
- g_source_destroy (side->in_source);
- if (side->out_source)
- g_source_destroy (side->out_source);
-
- g_hash_table_destroy (side->expected_replies);
-}
-
-static void
-flatpak_proxy_client_finalize (GObject *object)
-{
- FlatpakProxyClient *client = FLATPAK_PROXY_CLIENT (object);
-
- client->proxy->clients = g_list_remove (client->proxy->clients, client);
- g_clear_object (&client->proxy);
-
- g_byte_array_free (client->auth_buffer, TRUE);
- g_hash_table_destroy (client->rewrite_reply);
- g_hash_table_destroy (client->get_owner_reply);
- g_hash_table_destroy (client->unique_id_policy);
- g_hash_table_destroy (client->unique_id_owned_names);
-
- free_side (&client->client_side);
- free_side (&client->bus_side);
-
- G_OBJECT_CLASS (flatpak_proxy_client_parent_class)->finalize (object);
-}
-
-static void
-flatpak_proxy_client_class_init (FlatpakProxyClientClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = flatpak_proxy_client_finalize;
-}
-
-static void
-init_side (FlatpakProxyClient *client, ProxySide *side)
-{
- side->got_first_byte = (side == &client->bus_side);
- side->client = client;
- side->header_buffer.size = 16;
- side->header_buffer.pos = 0;
- side->current_read_buffer = &side->header_buffer;
- side->expected_replies = g_hash_table_new (g_direct_hash, g_direct_equal);
-}
-
-static void
-flatpak_proxy_client_init (FlatpakProxyClient *client)
-{
- init_side (client, &client->client_side);
- init_side (client, &client->bus_side);
-
- client->auth_buffer = g_byte_array_new ();
- client->rewrite_reply = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
- client->get_owner_reply = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
- client->unique_id_policy = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- client->unique_id_owned_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) string_list_free);
-}
-
-static FlatpakProxyClient *
-flatpak_proxy_client_new (FlatpakProxy *proxy, GSocketConnection *connection)
-{
- FlatpakProxyClient *client;
-
- g_socket_set_blocking (g_socket_connection_get_socket (connection), FALSE);
-
- client = g_object_new (FLATPAK_TYPE_PROXY_CLIENT, NULL);
- client->proxy = g_object_ref (proxy);
- client->client_side.connection = g_object_ref (connection);
-
- proxy->clients = g_list_prepend (proxy->clients, client);
-
- return client;
-}
-
-void
-flatpak_proxy_set_filter (FlatpakProxy *proxy,
- gboolean filter)
-{
- proxy->filter = filter;
-}
-
-void
-flatpak_proxy_set_sloppy_names (FlatpakProxy *proxy,
- gboolean sloppy_names)
-{
- proxy->sloppy_names = sloppy_names;
-}
-
-void
-flatpak_proxy_set_log_messages (FlatpakProxy *proxy,
- gboolean log)
-{
- proxy->log_messages = log;
-}
-
-static void
-filter_free (Filter *filter)
-{
- g_free (filter->name);
- g_free (filter->path);
- g_free (filter->interface);
- g_free (filter->member);
- g_free (filter);
-}
-
-static void
-filter_list_free (GList *filters)
-{
- g_list_free_full (filters, (GDestroyNotify) filter_free);
-}
-
-
-static Filter *
-filter_new (const char *name,
- gboolean name_is_subtree,
- FlatpakPolicy policy)
-{
- Filter *filter = g_new0 (Filter, 1);
-
- filter->name = g_strdup (name);
- filter->name_is_subtree = name_is_subtree;
- filter->policy = policy;
- filter->types = FILTER_TYPE_ALL;
-
- return filter;
-}
-
-// rules are of the form [*|org.the.interface.[method|*]]|[@/obj/path[/*]]
-static Filter *
-filter_new_from_rule (const char *name,
- gboolean name_is_subtree,
- FilterTypeMask types,
- const char *rule)
-{
- Filter *filter;
- const char *obj_path_start = NULL;
- const char *method_end = NULL;
-
- filter = filter_new (name, name_is_subtree, FLATPAK_POLICY_TALK);
- filter->types = types;
-
- obj_path_start = strchr (rule, '@');
- if (obj_path_start && obj_path_start[1] != 0)
- {
- filter->path = g_strdup (obj_path_start + 1);
-
- if (g_str_has_suffix (filter->path, "/*"))
- {
- filter->path_is_subtree = TRUE;
- filter->path[strlen (filter->path) - 2] = 0;
- }
- }
-
- if (obj_path_start != NULL)
- method_end = obj_path_start;
- else
- method_end = rule + strlen (rule);
-
- if (method_end != rule)
- {
- if (rule[0] == '*')
- {
- /* Both interface and method wildcarded */
- }
- else
- {
- filter->interface = g_strndup (rule, method_end - rule);
- char *dot = strrchr (filter->interface, '.');
- if (dot != NULL)
- {
- *dot = 0;
- if (strcmp (dot + 1, "*") != 0)
- filter->member = g_strdup (dot + 1);
- }
- }
- }
-
- return filter;
-}
-
-static gboolean
-filter_matches (Filter *filter,
- FilterTypeMask type,
- const char *path,
- const char *interface,
- const char *member)
-{
- if (filter->policy < FLATPAK_POLICY_TALK ||
- (filter->types & type) == 0)
- return FALSE;
-
- if (filter->path)
- {
- if (path == NULL)
- return FALSE;
-
- if (filter->path_is_subtree)
- {
- gsize filter_path_len = strlen (filter->path);
- if (strncmp (path, filter->path, filter_path_len) != 0 ||
- (path[filter_path_len] != 0 && path[filter_path_len] != '/'))
- return FALSE;
- }
- else if (strcmp (filter->path, path) != 0)
- return FALSE;
- }
-
- if (filter->interface && g_strcmp0 (filter->interface, interface) != 0)
- return FALSE;
-
- if (filter->member && g_strcmp0 (filter->member, member) != 0)
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-any_filter_matches (GList *filters,
- FilterTypeMask type,
- const char *path,
- const char *interface,
- const char *member)
-{
- GList *l;
-
- for (l = filters; l != NULL; l = l->next)
- {
- Filter *filter = l->data;
- if (filter_matches (filter, type, path, interface, member))
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-static void
-flatpak_proxy_add_filter (FlatpakProxy *proxy,
- Filter *filter)
-{
- GList *filters, *new_filters;
-
- if (g_hash_table_lookup_extended (proxy->filters,
- filter->name,
- NULL, (void **) &filters))
- {
- new_filters = g_list_append (filters, filter);
- g_assert (new_filters == filters);
- }
- else
- {
- filters = g_list_append (NULL, filter);
- g_hash_table_insert (proxy->filters, g_strdup (filter->name), filters);
- }
-}
-
-void
-flatpak_proxy_add_policy (FlatpakProxy *proxy,
- const char *name,
- gboolean name_is_subtree,
- FlatpakPolicy policy)
-{
- Filter *filter = filter_new (name, name_is_subtree, policy);
-
- flatpak_proxy_add_filter (proxy, filter);
-}
-
-void
-flatpak_proxy_add_call_rule (FlatpakProxy *proxy,
- const char *name,
- gboolean name_is_subtree,
- const char *rule)
-{
- Filter *filter = filter_new_from_rule (name, name_is_subtree, FILTER_TYPE_CALL, rule);
-
- flatpak_proxy_add_filter (proxy, filter);
-}
-
-void
-flatpak_proxy_add_broadcast_rule (FlatpakProxy *proxy,
- const char *name,
- gboolean name_is_subtree,
- const char *rule)
-{
- Filter *filter = filter_new_from_rule (name, name_is_subtree, FILTER_TYPE_BROADCAST, rule);
-
- flatpak_proxy_add_filter (proxy, filter);
-}
-
-static void
-flatpak_proxy_finalize (GObject *object)
-{
- FlatpakProxy *proxy = FLATPAK_PROXY (object);
-
- if (g_socket_service_is_active (G_SOCKET_SERVICE (proxy)))
- unlink (proxy->socket_path);
-
- g_assert (proxy->clients == NULL);
-
- g_hash_table_destroy (proxy->filters);
-
- g_free (proxy->socket_path);
- g_free (proxy->dbus_address);
-
- G_OBJECT_CLASS (flatpak_proxy_parent_class)->finalize (object);
-}
-
-static void
-flatpak_proxy_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- FlatpakProxy *proxy = FLATPAK_PROXY (object);
-
- switch (prop_id)
- {
- case PROP_DBUS_ADDRESS:
- proxy->dbus_address = g_value_dup_string (value);
- break;
-
- case PROP_SOCKET_PATH:
- proxy->socket_path = g_value_dup_string (value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-flatpak_proxy_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- FlatpakProxy *proxy = FLATPAK_PROXY (object);
-
- switch (prop_id)
- {
- case PROP_DBUS_ADDRESS:
- g_value_set_string (value, proxy->dbus_address);
- break;
-
- case PROP_SOCKET_PATH:
- g_value_set_string (value, proxy->socket_path);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static Buffer *
-buffer_new (gsize size, Buffer *old)
-{
- Buffer *buffer = g_malloc0 (sizeof (Buffer) + size - 16);
-
- buffer->control_messages = NULL;
- buffer->size = size;
- buffer->refcount = 1;
-
- if (old)
- {
- buffer->pos = old->pos;
- /* Takes ownership of any old control messages */
- buffer->control_messages = old->control_messages;
- old->control_messages = NULL;
-
- g_assert (size >= old->size);
- memcpy (buffer->data, old->data, old->size);
- }
-
- return buffer;
-}
-
-static ProxySide *
-get_other_side (ProxySide *side)
-{
- FlatpakProxyClient *client = side->client;
-
- if (side == &client->client_side)
- return &client->bus_side;
-
- return &client->client_side;
-}
-
-static void
-side_closed (ProxySide *side)
-{
- GSocket *socket, *other_socket;
- ProxySide *other_side = get_other_side (side);
-
- if (side->closed)
- return;
-
- socket = g_socket_connection_get_socket (side->connection);
- g_socket_close (socket, NULL);
- side->closed = TRUE;
-
- other_socket = g_socket_connection_get_socket (other_side->connection);
- if (!other_side->closed && other_side->buffers == NULL)
- {
- g_socket_close (other_socket, NULL);
- other_side->closed = TRUE;
- }
-
- if (other_side->closed)
- {
- g_object_unref (side->client);
- }
- else
- {
- GError *error = NULL;
-
- if (!g_socket_shutdown (other_socket, TRUE, FALSE, &error))
- {
- g_warning ("Unable to shutdown read side: %s", error->message);
- g_error_free (error);
- }
- }
-}
-
-static gboolean
-buffer_read (ProxySide *side,
- Buffer *buffer,
- GSocket *socket)
-{
- gssize res;
- GInputVector v;
- GError *error = NULL;
- GSocketControlMessage **messages;
- int num_messages, i;
-
- if (side->extra_input_data)
- {
- gsize extra_size;
- const guchar *extra_bytes = g_bytes_get_data (side->extra_input_data, &extra_size);
-
- res = MIN (extra_size, buffer->size - buffer->pos);
- memcpy (&buffer->data[buffer->pos], extra_bytes, res);
-
- if (res < extra_size)
- {
- side->extra_input_data =
- g_bytes_new_with_free_func (extra_bytes + res,
- extra_size - res,
- (GDestroyNotify) g_bytes_unref,
- side->extra_input_data);
- }
- else
- {
- g_clear_pointer (&side->extra_input_data, g_bytes_unref);
- }
- }
- else
- {
- int flags = 0;
- v.buffer = &buffer->data[buffer->pos];
- v.size = buffer->size - buffer->pos;
-
- res = g_socket_receive_message (socket, NULL, &v, 1,
- &messages,
- &num_messages,
- &flags, NULL, &error);
- if (res < 0 && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
- {
- g_error_free (error);
- return FALSE;
- }
-
- if (res <= 0)
- {
- if (res != 0)
- {
- g_debug ("Error reading from socket: %s", error->message);
- g_error_free (error);
- }
-
- side_closed (side);
- return FALSE;
- }
-
- for (i = 0; i < num_messages; i++)
- buffer->control_messages = g_list_append (buffer->control_messages, messages[i]);
-
- g_free (messages);
- }
-
- buffer->pos += res;
- return TRUE;
-}
-
-static gboolean
-buffer_write (ProxySide *side,
- Buffer *buffer,
- GSocket *socket)
-{
- gssize res;
- GOutputVector v;
- GError *error = NULL;
- GSocketControlMessage **messages = NULL;
- int i, n_messages;
- GList *l;
-
- if (buffer->send_credentials &&
- G_IS_UNIX_CONNECTION (side->connection))
- {
- g_assert (buffer->size == 1);
-
- if (!g_unix_connection_send_credentials (G_UNIX_CONNECTION (side->connection),
- NULL,
- &error))
- {
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
- {
- g_error_free (error);
- return FALSE;
- }
-
- g_warning ("Error writing credentials to socket: %s", error->message);
- g_error_free (error);
-
- side_closed (side);
- return FALSE;
- }
-
- buffer->pos = 1;
- return TRUE;
- }
-
- n_messages = g_list_length (buffer->control_messages);
- messages = g_new (GSocketControlMessage *, n_messages);
- for (l = buffer->control_messages, i = 0; l != NULL; l = l->next, i++)
- messages[i] = l->data;
-
- v.buffer = &buffer->data[buffer->pos];
- v.size = buffer->size - buffer->pos;
-
- res = g_socket_send_message (socket, NULL, &v, 1,
- messages, n_messages,
- G_SOCKET_MSG_NONE, NULL, &error);
- g_free (messages);
- if (res < 0 && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
- {
- g_error_free (error);
- return FALSE;
- }
-
- if (res <= 0)
- {
- if (res < 0)
- {
- g_warning ("Error writing credentials to socket: %s", error->message);
- g_error_free (error);
- }
-
- side_closed (side);
- return FALSE;
- }
-
- g_list_free_full (buffer->control_messages, g_object_unref);
- buffer->control_messages = NULL;
-
- buffer->pos += res;
- return TRUE;
-}
-
-static gboolean
-side_out_cb (GSocket *socket, GIOCondition condition, gpointer user_data)
-{
- ProxySide *side = user_data;
- FlatpakProxyClient *client = side->client;
- gboolean retval = G_SOURCE_CONTINUE;
-
- g_object_ref (client);
-
- while (side->buffers)
- {
- Buffer *buffer = side->buffers->data;
-
- if (buffer_write (side, buffer, socket))
- {
- if (buffer->pos == buffer->size)
- {
- side->buffers = g_list_delete_link (side->buffers, side->buffers);
- buffer_unref (buffer);
- }
- }
- else
- {
- break;
- }
- }
-
- if (side->buffers == NULL)
- {
- ProxySide *other_side = get_other_side (side);
-
- side->out_source = NULL;
- retval = G_SOURCE_REMOVE;
-
- if (other_side->closed)
- side_closed (side);
- }
-
- g_object_unref (client);
-
- return retval;
-}
-
-static void
-queue_expected_reply (ProxySide *side, guint32 serial, ExpectedReplyType type)
-{
- g_hash_table_replace (side->expected_replies,
- GUINT_TO_POINTER (serial),
- GUINT_TO_POINTER (type));
-}
-
-static ExpectedReplyType
-steal_expected_reply (ProxySide *side, guint32 serial)
-{
- ExpectedReplyType type;
-
- type = GPOINTER_TO_UINT (g_hash_table_lookup (side->expected_replies,
- GUINT_TO_POINTER (serial)));
- if (type)
- g_hash_table_remove (side->expected_replies,
- GUINT_TO_POINTER (serial));
- return type;
-}
-
-
-static void
-queue_outgoing_buffer (ProxySide *side, Buffer *buffer)
-{
- if (side->out_source == NULL)
- {
- GSocket *socket;
-
- socket = g_socket_connection_get_socket (side->connection);
- side->out_source = g_socket_create_source (socket, G_IO_OUT, NULL);
- g_source_set_callback (side->out_source, (GSourceFunc) side_out_cb, side, NULL);
- g_source_attach (side->out_source, NULL);
- g_source_unref (side->out_source);
- }
-
- buffer->pos = 0;
- side->buffers = g_list_append (side->buffers, buffer);
-}
-
-static guint32
-read_uint32 (Header *header, guint8 *ptr)
-{
- if (header->big_endian)
- return GUINT32_FROM_BE (*(guint32 *) ptr);
- else
- return GUINT32_FROM_LE (*(guint32 *) ptr);
-}
-
-static void
-write_uint32 (Header *header, guint8 *ptr, guint32 val)
-{
- if (header->big_endian)
- *(guint32 *) ptr = GUINT32_TO_BE (val);
- else
- *(guint32 *) ptr = GUINT32_TO_LE (val);
-}
-
-static inline guint32
-align_by_8 (guint32 offset)
-{
- return (offset + 8 - 1) & ~(8 - 1);
-}
-
-static inline guint32
-align_by_4 (guint32 offset)
-{
- return (offset + 4 - 1) & ~(4 - 1);
-}
-
-static const char *
-get_signature (Buffer *buffer, guint32 *offset, guint32 end_offset)
-{
- guint8 len;
- char *str;
-
- if (*offset >= end_offset)
- return FALSE;
-
- len = buffer->data[*offset];
- (*offset)++;
-
- if ((*offset) + len + 1 > end_offset)
- return FALSE;
-
- if (buffer->data[(*offset) + len] != 0)
- return FALSE;
-
- str = (char *) &buffer->data[(*offset)];
- *offset += len + 1;
-
- return str;
-}
-
-static const char *
-get_string (Buffer *buffer, Header *header, guint32 *offset, guint32 end_offset)
-{
- guint8 len;
- char *str;
-
- *offset = align_by_4 (*offset);
- if (*offset + 4 >= end_offset)
- return FALSE;
-
- len = read_uint32 (header, &buffer->data[*offset]);
- *offset += 4;
-
- if ((*offset) + len + 1 > end_offset)
- return FALSE;
-
- if (buffer->data[(*offset) + len] != 0)
- return FALSE;
-
- str = (char *) &buffer->data[(*offset)];
- *offset += len + 1;
-
- return str;
-}
-
-static void
-header_free (Header *header)
-{
- if (header->buffer)
- buffer_unref (header->buffer);
- g_free (header);
-}
-
-static Header *
-parse_header (Buffer *buffer, guint32 serial_offset, guint32 reply_serial_offset, guint32 hello_serial)
-{
- guint32 array_len, header_len;
- guint32 offset, end_offset;
- guint8 header_type;
- guint32 reply_serial_pos = 0;
- const char *signature;
-
- g_autoptr(Header) header = g_new0 (Header, 1);
-
- header->buffer = buffer_ref (buffer);
-
- if (buffer->size < 16)
- return NULL;
-
- if (buffer->data[3] != 1) /* Protocol version */
- return NULL;
-
- if (buffer->data[0] == 'B')
- header->big_endian = TRUE;
- else if (buffer->data[0] == 'l')
- header->big_endian = FALSE;
- else
- return NULL;
-
- header->type = buffer->data[1];
- header->flags = buffer->data[2];
-
- header->length = read_uint32 (header, &buffer->data[4]);
- header->serial = read_uint32 (header, &buffer->data[8]);
-
- if (header->serial == 0)
- return NULL;
-
- array_len = read_uint32 (header, &buffer->data[12]);
-
- header_len = align_by_8 (12 + 4 + array_len);
- g_assert (buffer->size >= header_len); /* We should have verified this when reading in the message */
- if (header_len > buffer->size)
- return NULL;
-
- offset = 12 + 4;
- end_offset = offset + array_len;
-
- while (offset < end_offset)
- {
- offset = align_by_8 (offset); /* Structs must be 8 byte aligned */
- if (offset >= end_offset)
- return NULL;
-
- header_type = buffer->data[offset++];
- if (offset >= end_offset)
- return NULL;
-
- signature = get_signature (buffer, &offset, end_offset);
- if (signature == NULL)
- return NULL;
-
- switch (header_type)
- {
- case G_DBUS_MESSAGE_HEADER_FIELD_INVALID:
- return NULL;
-
- case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
- if (strcmp (signature, "o") != 0)
- return NULL;
- header->path = get_string (buffer, header, &offset, end_offset);
- if (header->path == NULL)
- return NULL;
- break;
-
- case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE:
- if (strcmp (signature, "s") != 0)
- return NULL;
- header->interface = get_string (buffer, header, &offset, end_offset);
- if (header->interface == NULL)
- return NULL;
- break;
-
- case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER:
- if (strcmp (signature, "s") != 0)
- return NULL;
- header->member = get_string (buffer, header, &offset, end_offset);
- if (header->member == NULL)
- return NULL;
- break;
-
- case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME:
- if (strcmp (signature, "s") != 0)
- return NULL;
- header->error_name = get_string (buffer, header, &offset, end_offset);
- if (header->error_name == NULL)
- return NULL;
- break;
-
- case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
- if (offset + 4 > end_offset)
- return NULL;
-
- header->has_reply_serial = TRUE;
- reply_serial_pos = offset;
- header->reply_serial = read_uint32 (header, &buffer->data[offset]);
- offset += 4;
- break;
-
- case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION:
- if (strcmp (signature, "s") != 0)
- return NULL;
- header->destination = get_string (buffer, header, &offset, end_offset);
- if (header->destination == NULL)
- return NULL;
- break;
-
- case G_DBUS_MESSAGE_HEADER_FIELD_SENDER:
- if (strcmp (signature, "s") != 0)
- return NULL;
- header->sender = get_string (buffer, header, &offset, end_offset);
- if (header->sender == NULL)
- return NULL;
- break;
-
- case G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE:
- if (strcmp (signature, "g") != 0)
- return NULL;
- header->signature = get_signature (buffer, &offset, end_offset);
- if (header->signature == NULL)
- return NULL;
- break;
-
- case G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS:
- if (offset + 4 > end_offset)
- return NULL;
-
- header->unix_fds = read_uint32 (header, &buffer->data[offset]);
- offset += 4;
- break;
-
- default:
- /* Unknown header field, for safety, fail parse */
- return NULL;
- }
- }
-
- switch (header->type)
- {
- case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
- if (header->path == NULL || header->member == NULL)
- return NULL;
- break;
-
- case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
- if (!header->has_reply_serial)
- return NULL;
- break;
-
- case G_DBUS_MESSAGE_TYPE_ERROR:
- if (header->error_name == NULL || !header->has_reply_serial)
- return NULL;
- break;
-
- case G_DBUS_MESSAGE_TYPE_SIGNAL:
- if (header->path == NULL ||
- header->interface == NULL ||
- header->member == NULL)
- return NULL;
- if (strcmp (header->path, "/org/freedesktop/DBus/Local") == 0 ||
- strcmp (header->interface, "org.freedesktop.DBus.Local") == 0)
- return NULL;
- break;
-
- default:
- /* Unknown message type, for safety, fail parse */
- return NULL;
- }
-
- if (serial_offset > 0)
- {
- header->serial += serial_offset;
- write_uint32 (header, &buffer->data[8], header->serial);
- }
-
- if (reply_serial_offset > 0 &&
- header->has_reply_serial &&
- header->reply_serial > hello_serial + reply_serial_offset)
- write_uint32 (header, &buffer->data[reply_serial_pos], header->reply_serial - reply_serial_offset);
-
- return g_steal_pointer (&header);
-}
-
-static void
-print_outgoing_header (Header *header)
-{
- switch (header->type)
- {
- case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
- g_print ("C%d: -> %s call %s.%s at %s\n",
- header->serial,
- header->destination ? header->destination : "(no dest)",
- header->interface ? header->interface : "",
- header->member ? header->member : "",
- header->path ? header->path : "");
- break;
-
- case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
- g_print ("C%d: -> %s return from B%d\n",
- header->serial,
- header->destination ? header->destination : "(no dest)",
- header->reply_serial);
- break;
-
- case G_DBUS_MESSAGE_TYPE_ERROR:
- g_print ("C%d: -> %s return error %s from B%d\n",
- header->serial,
- header->destination ? header->destination : "(no dest)",
- header->error_name ? header->error_name : "(no error)",
- header->reply_serial);
- break;
-
- case G_DBUS_MESSAGE_TYPE_SIGNAL:
- g_print ("C%d: -> %s signal %s.%s at %s\n",
- header->serial,
- header->destination ? header->destination : "all",
- header->interface ? header->interface : "",
- header->member ? header->member : "",
- header->path ? header->path : "");
- break;
-
- default:
- g_print ("unknown message type\n");
- }
-}
-
-static void
-print_incoming_header (Header *header)
-{
- switch (header->type)
- {
- case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
- g_print ("B%d: <- %s call %s.%s at %s\n",
- header->serial,
- header->sender ? header->sender : "(no sender)",
- header->interface ? header->interface : "",
- header->member ? header->member : "",
- header->path ? header->path : "");
- break;
-
- case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
- g_print ("B%d: <- %s return from C%d\n",
- header->serial,
- header->sender ? header->sender : "(no sender)",
- header->reply_serial);
- break;
-
- case G_DBUS_MESSAGE_TYPE_ERROR:
- g_print ("B%d: <- %s return error %s from C%d\n",
- header->serial,
- header->sender ? header->sender : "(no sender)",
- header->error_name ? header->error_name : "(no error)",
- header->reply_serial);
- break;
-
- case G_DBUS_MESSAGE_TYPE_SIGNAL:
- g_print ("B%d: <- %s signal %s.%s at %s\n",
- header->serial,
- header->sender ? header->sender : "(no sender)",
- header->interface ? header->interface : "",
- header->member ? header->member : "",
- header->path ? header->path : "");
- break;
-
- default:
- g_print ("unknown message type\n");
- }
-}
-
-
-static Filter *match_all[FLATPAK_POLICY_OWN + 1] = { NULL };
-
-
-static FlatpakPolicy
-flatpak_proxy_client_get_max_policy_and_matched (FlatpakProxyClient *client,
- const char *source,
- GList **matched_filters)
-{
- GList *names, *filters, *l;
- FlatpakPolicy max_policy = FLATPAK_POLICY_NONE;
- g_autofree char *name = NULL;
- gboolean exact_name_match;
- char *dot;
-
- if (match_all[FLATPAK_POLICY_SEE] == NULL)
- {
- match_all[FLATPAK_POLICY_SEE] = filter_new ("", FALSE, FLATPAK_POLICY_SEE);
- match_all[FLATPAK_POLICY_TALK] = filter_new ("", FALSE, FLATPAK_POLICY_TALK);
- match_all[FLATPAK_POLICY_OWN] = filter_new ("", FALSE, FLATPAK_POLICY_OWN);
- }
-
- if (source == NULL)
- {
- if (matched_filters)
- *matched_filters = g_list_append (*matched_filters, match_all[FLATPAK_POLICY_TALK]);
-
- return FLATPAK_POLICY_TALK; /* All clients can talk to the bus itself */
- }
-
- if (source[0] == ':')
- {
- /* Default to the unique id policy, i.e. TALK for self, and SEE for trusted peers */
- max_policy = GPOINTER_TO_UINT (g_hash_table_lookup (client->unique_id_policy, source));
- if (max_policy > FLATPAK_POLICY_NONE && matched_filters)
- *matched_filters = g_list_append (*matched_filters, match_all[max_policy]);
-
- /* Treat this as the merged list of filters for all the names the unique id ever owned */
- names = g_hash_table_lookup (client->unique_id_owned_names, source);
- for (l = names; l != NULL; l = l->next)
- {
- const char *owned_name = l->data;
- max_policy = MAX (max_policy, flatpak_proxy_client_get_max_policy_and_matched (client, owned_name, matched_filters));
- }
-
-
- return max_policy;
- }
-
- name = g_strdup (source);
- exact_name_match = TRUE;
- do
- {
- filters = g_hash_table_lookup (client->proxy->filters, name);
-
- for (l = filters; l != NULL; l = l->next)
- {
- Filter *filter = l->data;
-
- if (exact_name_match || filter->name_is_subtree)
- {
- max_policy = MAX (max_policy, filter->policy);
- if (matched_filters)
- *matched_filters = g_list_append (*matched_filters, filter);
- }
- }
-
- exact_name_match = FALSE;
- dot = strrchr (name, '.');
- if (dot != NULL)
- *dot = 0;
- }
- while (dot != NULL);
-
- return max_policy;
-}
-
-static FlatpakPolicy
-flatpak_proxy_client_get_max_policy (FlatpakProxyClient *client,
- const char *source)
-{
- return flatpak_proxy_client_get_max_policy_and_matched (client, source, NULL);
-}
-
-static void
-flatpak_proxy_client_update_unique_id_policy (FlatpakProxyClient *client,
- const char *unique_id,
- FlatpakPolicy policy)
-{
- if (policy > FLATPAK_POLICY_NONE)
- {
- FlatpakPolicy old_policy;
- old_policy = GPOINTER_TO_UINT (g_hash_table_lookup (client->unique_id_policy, unique_id));
- if (policy > old_policy)
- g_hash_table_replace (client->unique_id_policy, g_strdup (unique_id), GINT_TO_POINTER (policy));
- }
-}
-
-
-static void
-flatpak_proxy_client_add_unique_id_owned_name (FlatpakProxyClient *client,
- const char *unique_id,
- const char *owned_name)
-{
- GList *names;
- gboolean already_added;
-
- names = NULL;
- already_added = g_hash_table_lookup_extended (client->unique_id_owned_names,
- unique_id,
- NULL, (void **) &names);
- names = g_list_append (names, g_strdup (owned_name));
-
- if (!already_added)
- g_hash_table_insert (client->unique_id_owned_names, g_strdup (unique_id), names);
-}
-
-
-static gboolean
-client_message_generates_reply (Header *header)
-{
- switch (header->type)
- {
- case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
- return (header->flags & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED) == 0;
-
- case G_DBUS_MESSAGE_TYPE_SIGNAL:
- case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
- case G_DBUS_MESSAGE_TYPE_ERROR:
- default:
- return FALSE;
- }
-}
-
-static Buffer *
-message_to_buffer (GDBusMessage *message)
-{
- Buffer *buffer;
- guchar *blob;
- gsize blob_size;
-
- blob = g_dbus_message_to_blob (message, &blob_size, G_DBUS_CAPABILITY_FLAGS_NONE, NULL);
- buffer = buffer_new (blob_size, NULL);
- memcpy (buffer->data, blob, blob_size);
- g_free (blob);
-
- return buffer;
-}
-
-static GDBusMessage *
-get_error_for_header (FlatpakProxyClient *client, Header *header, const char *error)
-{
- GDBusMessage *reply;
-
- reply = g_dbus_message_new ();
- g_dbus_message_set_message_type (reply, G_DBUS_MESSAGE_TYPE_ERROR);
- g_dbus_message_set_flags (reply, G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED);
- g_dbus_message_set_reply_serial (reply, header->serial - client->serial_offset);
- g_dbus_message_set_error_name (reply, error);
- g_dbus_message_set_body (reply, g_variant_new ("(s)", error));
-
- return reply;
-}
-
-static GDBusMessage *
-get_bool_reply_for_header (FlatpakProxyClient *client, Header *header, gboolean val)
-{
- GDBusMessage *reply;
-
- reply = g_dbus_message_new ();
- g_dbus_message_set_message_type (reply, G_DBUS_MESSAGE_TYPE_METHOD_RETURN);
- g_dbus_message_set_flags (reply, G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED);
- g_dbus_message_set_reply_serial (reply, header->serial - client->serial_offset);
- g_dbus_message_set_body (reply, g_variant_new ("(b)", val));
-
- return reply;
-}
-
-static Buffer *
-get_ping_buffer_for_header (Header *header)
-{
- Buffer *buffer;
- GDBusMessage *dummy;
-
- dummy = g_dbus_message_new_method_call (NULL, "/", "org.freedesktop.DBus.Peer", "Ping");
- g_dbus_message_set_serial (dummy, header->serial);
- g_dbus_message_set_flags (dummy, header->flags);
-
- buffer = message_to_buffer (dummy);
-
- g_object_unref (dummy);
-
- return buffer;
-}
-
-static Buffer *
-get_error_for_roundtrip (FlatpakProxyClient *client, Header *header, const char *error_name)
-{
- Buffer *ping_buffer = get_ping_buffer_for_header (header);
- GDBusMessage *reply;
-
- reply = get_error_for_header (client, header, error_name);
- g_hash_table_replace (client->rewrite_reply, GINT_TO_POINTER (header->serial), reply);
- return ping_buffer;
-}
-
-static Buffer *
-get_bool_reply_for_roundtrip (FlatpakProxyClient *client, Header *header, gboolean val)
-{
- Buffer *ping_buffer = get_ping_buffer_for_header (header);
- GDBusMessage *reply;
-
- reply = get_bool_reply_for_header (client, header, val);
- g_hash_table_replace (client->rewrite_reply, GINT_TO_POINTER (header->serial), reply);
-
- return ping_buffer;
-}
-
-typedef enum {
- HANDLE_PASS,
- HANDLE_DENY,
- HANDLE_HIDE,
- HANDLE_FILTER_NAME_LIST_REPLY,
- HANDLE_FILTER_HAS_OWNER_REPLY,
- HANDLE_FILTER_GET_OWNER_REPLY,
- HANDLE_VALIDATE_OWN,
- HANDLE_VALIDATE_SEE,
- HANDLE_VALIDATE_TALK,
- HANDLE_VALIDATE_MATCH,
-} BusHandler;
-
-static gboolean
-is_for_bus (Header *header)
-{
- return g_strcmp0 (header->destination, "org.freedesktop.DBus") == 0;
-}
-
-static gboolean
-is_dbus_method_call (Header *header)
-{
- return
- is_for_bus (header) &&
- header->type == G_DBUS_MESSAGE_TYPE_METHOD_CALL &&
- g_strcmp0 (header->interface, "org.freedesktop.DBus") == 0;
-}
-
-static gboolean
-is_introspection_call (Header *header)
-{
- return
- header->type == G_DBUS_MESSAGE_TYPE_METHOD_CALL &&
- g_strcmp0 (header->interface, "org.freedesktop.DBus.Introspectable") == 0;
-}
-
-static BusHandler
-get_dbus_method_handler (FlatpakProxyClient *client, Header *header)
-{
- FlatpakPolicy policy;
- const char *method;
-
- g_autoptr(GList) filters = NULL;
-
- if (header->has_reply_serial)
- {
- ExpectedReplyType expected_reply =
- steal_expected_reply (&client->bus_side,
- header->reply_serial);
- if (expected_reply == EXPECTED_REPLY_NONE)
- return HANDLE_DENY;
-
- return HANDLE_PASS;
- }
-
- policy = flatpak_proxy_client_get_max_policy_and_matched (client, header->destination, &filters);
- if (policy < FLATPAK_POLICY_SEE)
- return HANDLE_HIDE;
- if (policy < FLATPAK_POLICY_TALK)
- return HANDLE_DENY;
-
- if (!is_for_bus (header))
- {
- if (policy == FLATPAK_POLICY_OWN ||
- any_filter_matches (filters, FILTER_TYPE_CALL,
- header->path,
- header->interface,
- header->member))
- return HANDLE_PASS;
-
- return HANDLE_DENY;
- }
-
- /* Its a bus call */
-
- if (is_introspection_call (header))
- {
- return HANDLE_PASS;
- }
- else if (is_dbus_method_call (header))
- {
- method = header->member;
- if (method == NULL)
- return HANDLE_DENY;
-
- if (strcmp (method, "AddMatch") == 0)
- return HANDLE_VALIDATE_MATCH;
-
- if (strcmp (method, "Hello") == 0 ||
- strcmp (method, "RemoveMatch") == 0 ||
- strcmp (method, "GetId") == 0)
- return HANDLE_PASS;
-
- if (strcmp (method, "UpdateActivationEnvironment") == 0 ||
- strcmp (method, "BecomeMonitor") == 0)
- return HANDLE_DENY;
-
- if (strcmp (method, "RequestName") == 0 ||
- strcmp (method, "ReleaseName") == 0 ||
- strcmp (method, "ListQueuedOwners") == 0)
- return HANDLE_VALIDATE_OWN;
-
- if (strcmp (method, "NameHasOwner") == 0)
- return HANDLE_FILTER_HAS_OWNER_REPLY;
-
- if (strcmp (method, "GetNameOwner") == 0)
- return HANDLE_FILTER_GET_OWNER_REPLY;
-
- if (strcmp (method, "GetConnectionUnixProcessID") == 0 ||
- strcmp (method, "GetConnectionCredentials") == 0 ||
- strcmp (method, "GetAdtAuditSessionData") == 0 ||
- strcmp (method, "GetConnectionSELinuxSecurityContext") == 0 ||
- strcmp (method, "GetConnectionUnixUser") == 0)
- return HANDLE_VALIDATE_SEE;
-
- if (strcmp (method, "StartServiceByName") == 0)
- return HANDLE_VALIDATE_TALK;
-
- if (strcmp (method, "ListNames") == 0 ||
- strcmp (method, "ListActivatableNames") == 0)
- return HANDLE_FILTER_NAME_LIST_REPLY;
-
- g_warning ("Unknown bus method %s", method);
- return HANDLE_DENY;
- }
- else
- {
- return HANDLE_DENY;
- }
-}
-
-static FlatpakPolicy
-policy_from_handler (BusHandler handler)
-{
- switch (handler)
- {
- case HANDLE_VALIDATE_OWN:
- return FLATPAK_POLICY_OWN;
-
- case HANDLE_VALIDATE_TALK:
- return FLATPAK_POLICY_TALK;
-
- case HANDLE_VALIDATE_SEE:
- return FLATPAK_POLICY_SEE;
-
- default:
- return FLATPAK_POLICY_NONE;
- }
-}
-
-static char *
-get_arg0_string (Buffer *buffer)
-{
- GDBusMessage *message = g_dbus_message_new_from_blob (buffer->data, buffer->size, 0, NULL);
- GVariant *body;
-
- g_autoptr(GVariant) arg0 = NULL;
- char *name = NULL;
-
- if (message != NULL &&
- (body = g_dbus_message_get_body (message)) != NULL &&
- (arg0 = g_variant_get_child_value (body, 0)) != NULL &&
- g_variant_is_of_type (arg0, G_VARIANT_TYPE_STRING))
- name = g_variant_dup_string (arg0, NULL);
-
- g_object_unref (message);
-
- return name;
-}
-
-static gboolean
-validate_arg0_match (FlatpakProxyClient *client, Buffer *buffer)
-{
- GDBusMessage *message = g_dbus_message_new_from_blob (buffer->data, buffer->size, 0, NULL);
- GVariant *body, *arg0;
- const char *match;
- gboolean res = TRUE;
-
- if (message != NULL &&
- (body = g_dbus_message_get_body (message)) != NULL &&
- (arg0 = g_variant_get_child_value (body, 0)) != NULL &&
- g_variant_is_of_type (arg0, G_VARIANT_TYPE_STRING))
- {
- match = g_variant_get_string (arg0, NULL);
- if (strstr (match, "eavesdrop=") != NULL)
- res = FALSE;
- }
-
- g_object_unref (message);
- return res;
-}
-
-static gboolean
-validate_arg0_name (FlatpakProxyClient *client, Buffer *buffer, FlatpakPolicy required_policy, FlatpakPolicy *has_policy)
-{
- GDBusMessage *message = g_dbus_message_new_from_blob (buffer->data, buffer->size, 0, NULL);
- GVariant *body, *arg0;
- const char *name;
- FlatpakPolicy name_policy;
- gboolean res = FALSE;
-
- if (has_policy)
- *has_policy = FLATPAK_POLICY_NONE;
-
- if (message != NULL &&
- (body = g_dbus_message_get_body (message)) != NULL &&
- (arg0 = g_variant_get_child_value (body, 0)) != NULL &&
- g_variant_is_of_type (arg0, G_VARIANT_TYPE_STRING))
- {
- name = g_variant_get_string (arg0, NULL);
- name_policy = flatpak_proxy_client_get_max_policy (client, name);
-
- if (has_policy)
- *has_policy = name_policy;
-
- if (name_policy >= required_policy)
- res = TRUE;
- else if (client->proxy->log_messages)
- g_print ("Filtering message due to arg0 %s, policy: %d (required %d)\n", name, name_policy, required_policy);
- }
-
- g_object_unref (message);
- return res;
-}
-
-static Buffer *
-filter_names_list (FlatpakProxyClient *client, Buffer *buffer)
-{
- GDBusMessage *message = g_dbus_message_new_from_blob (buffer->data, buffer->size, 0, NULL);
- GVariant *body, *arg0, *new_names;
- const gchar **names;
- int i;
- GVariantBuilder builder;
- Buffer *filtered;
-
- if (message == NULL ||
- (body = g_dbus_message_get_body (message)) == NULL ||
- (arg0 = g_variant_get_child_value (body, 0)) == NULL ||
- !g_variant_is_of_type (arg0, G_VARIANT_TYPE_STRING_ARRAY))
- return NULL;
-
- names = g_variant_get_strv (arg0, NULL);
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE_STRING_ARRAY);
- for (i = 0; names[i] != NULL; i++)
- {
- if (flatpak_proxy_client_get_max_policy (client, names[i]) >= FLATPAK_POLICY_SEE)
- g_variant_builder_add (&builder, "s", names[i]);
- }
- g_free (names);
-
- new_names = g_variant_builder_end (&builder);
- g_dbus_message_set_body (message,
- g_variant_new_tuple (&new_names, 1));
-
- filtered = message_to_buffer (message);
- g_object_unref (message);
- return filtered;
-}
-
-static gboolean
-message_is_name_owner_changed (FlatpakProxyClient *client, Header *header)
-{
- if (header->type == G_DBUS_MESSAGE_TYPE_SIGNAL &&
- g_strcmp0 (header->sender, "org.freedesktop.DBus") == 0 &&
- g_strcmp0 (header->interface, "org.freedesktop.DBus") == 0 &&
- g_strcmp0 (header->member, "NameOwnerChanged") == 0)
- return TRUE;
- return FALSE;
-}
-
-static gboolean
-should_filter_name_owner_changed (FlatpakProxyClient *client, Buffer *buffer)
-{
- GDBusMessage *message = g_dbus_message_new_from_blob (buffer->data, buffer->size, 0, NULL);
- GVariant *body, *arg0, *arg1, *arg2;
- const gchar *name, *new;
- gboolean filter = TRUE;
-
- if (message == NULL ||
- (body = g_dbus_message_get_body (message)) == NULL ||
- (arg0 = g_variant_get_child_value (body, 0)) == NULL ||
- !g_variant_is_of_type (arg0, G_VARIANT_TYPE_STRING) ||
- (arg1 = g_variant_get_child_value (body, 1)) == NULL ||
- !g_variant_is_of_type (arg1, G_VARIANT_TYPE_STRING) ||
- (arg2 = g_variant_get_child_value (body, 2)) == NULL ||
- !g_variant_is_of_type (arg2, G_VARIANT_TYPE_STRING))
- return TRUE;
-
- name = g_variant_get_string (arg0, NULL);
- new = g_variant_get_string (arg2, NULL);
-
- if (flatpak_proxy_client_get_max_policy (client, name) >= FLATPAK_POLICY_SEE ||
- (client->proxy->sloppy_names && name[0] == ':'))
- {
- if (name[0] != ':')
- {
- if (new[0] != 0)
- flatpak_proxy_client_add_unique_id_owned_name (client, new, name);
- }
-
- filter = FALSE;
- }
-
- g_object_unref (message);
-
- return filter;
-}
-
-static GList *
-side_get_n_unix_fds (ProxySide *side, int n_fds)
-{
- GList *res = NULL;
-
- while (side->control_messages != NULL)
- {
- GSocketControlMessage *control_message = side->control_messages->data;
-
- if (G_IS_UNIX_FD_MESSAGE (control_message))
- {
- GUnixFDMessage *fd_message = G_UNIX_FD_MESSAGE (control_message);
- GUnixFDList *fd_list = g_unix_fd_message_get_fd_list (fd_message);
- int len = g_unix_fd_list_get_length (fd_list);
-
- /* I believe that socket control messages are never merged, and
- the sender side sends only one unix-fd-list per message, so
- at this point there should always be one full fd list
- per requested number of fds */
- if (len != n_fds)
- {
- g_warning ("Not right nr of fds in socket message");
- return NULL;
- }
-
- side->control_messages = g_list_delete_link (side->control_messages, side->control_messages);
-
- return g_list_append (NULL, control_message);
- }
-
- g_object_unref (control_message);
- side->control_messages = g_list_delete_link (side->control_messages, side->control_messages);
- }
-
- return res;
-}
-
-static gboolean
-update_socket_messages (ProxySide *side, Buffer *buffer, Header *header)
-{
- /* We may accidentally combine multiple control messages into one
- buffer when we receive (since we can do several recvs), so we
- keep a list of all we get and then only re-attach the amount
- specified in the header to the buffer. */
-
- side->control_messages = g_list_concat (side->control_messages, buffer->control_messages);
- buffer->control_messages = NULL;
- if (header->unix_fds > 0)
- {
- buffer->control_messages = side_get_n_unix_fds (side, header->unix_fds);
- if (buffer->control_messages == NULL)
- {
- g_warning ("Not enough fds for message");
- side_closed (side);
- buffer_unref (buffer);
- return FALSE;
- }
- }
- return TRUE;
-}
-
-static void
-queue_fake_message (FlatpakProxyClient *client, GDBusMessage *message, ExpectedReplyType reply_type)
-{
- Buffer *buffer;
-
- client->last_serial++;
- client->serial_offset++;
- g_dbus_message_set_serial (message, client->last_serial);
- buffer = message_to_buffer (message);
- g_object_unref (message);
-
- queue_outgoing_buffer (&client->bus_side, buffer);
- queue_expected_reply (&client->client_side, client->last_serial, reply_type);
-}
-
-/* After the first Hello message we need to synthesize a bunch of messages to synchronize the
- ownership state for the names in the policy */
-static void
-queue_initial_name_ops (FlatpakProxyClient *client)
-{
- GHashTableIter iter;
- gpointer key, value;
- gboolean has_wildcards = FALSE;
-
- g_hash_table_iter_init (&iter, client->proxy->filters);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- const char *name = key;
- GList *filters = value;
- gboolean name_needs_subtree = FALSE;
- GDBusMessage *message;
- GVariant *match;
- GList *l;
-
- for (l = filters; l != NULL; l = l->next)
- {
- Filter *filter = l->data;
- if (filter->name_is_subtree)
- {
- name_needs_subtree = TRUE;
- break;
- }
- }
-
- if (strcmp (name, "org.freedesktop.DBus") == 0)
- continue;
-
- /* AddMatch the name so we get told about ownership changes.
- Do it before the GetNameOwner to avoid races */
- message = g_dbus_message_new_method_call ("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "AddMatch");
- if (name_needs_subtree)
- match = g_variant_new_printf ("type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0namespace='%s'", name);
- else
- match = g_variant_new_printf ("type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0='%s'", name);
- g_dbus_message_set_body (message, g_variant_new_tuple (&match, 1));
- queue_fake_message (client, message, EXPECTED_REPLY_FILTER);
-
- if (client->proxy->log_messages)
- g_print ("C%d: -> org.freedesktop.DBus fake %sAddMatch for %s\n", client->last_serial, name_needs_subtree ? "wildcarded " : "", name);
-
- if (!name_needs_subtree)
- {
- /* Get the current owner of the name (if any) so we can apply policy to it */
- message = g_dbus_message_new_method_call ("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetNameOwner");
- g_dbus_message_set_body (message, g_variant_new ("(s)", name));
- queue_fake_message (client, message, EXPECTED_REPLY_FAKE_GET_NAME_OWNER);
- g_hash_table_replace (client->get_owner_reply, GINT_TO_POINTER (client->last_serial), g_strdup (name));
-
- if (client->proxy->log_messages)
- g_print ("C%d: -> org.freedesktop.DBus fake GetNameOwner for %s\n", client->last_serial, name);
- }
- else
- has_wildcards = TRUE; /* Send ListNames below */
- }
-
- /* For wildcarded rules we don't know the actual names to GetNameOwner for, so we have to list all current names */
- if (has_wildcards)
- {
- GDBusMessage *message;
-
- /* AddMatch the name so we get told about ownership changes.
- Do it before the GetNameOwner to avoid races */
- message = g_dbus_message_new_method_call ("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "ListNames");
- g_dbus_message_set_body (message, g_variant_new ("()"));
- queue_fake_message (client, message, EXPECTED_REPLY_FAKE_LIST_NAMES);
-
- if (client->proxy->log_messages)
- g_print ("C%d: -> org.freedesktop.DBus fake ListNames\n", client->last_serial);
-
- /* Stop reading from the client, to avoid incoming messages fighting with the ListNames roundtrip.
- We will start it again once we have handled the ListNames reply */
- stop_reading (&client->client_side);
-
- /* Once we get the reply to this queue_wildcard_initial_name_ops() will be called and we continue there */
- }
-}
-
-static void
-queue_wildcard_initial_name_ops (FlatpakProxyClient *client, Header *header, Buffer *buffer)
-{
- GDBusMessage *decoded_message = g_dbus_message_new_from_blob (buffer->data, buffer->size, 0, NULL);
- GVariant *body, *arg0;
-
- if (decoded_message != NULL &&
- header->type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN &&
- (body = g_dbus_message_get_body (decoded_message)) != NULL &&
- (arg0 = g_variant_get_child_value (body, 0)) != NULL &&
- g_variant_is_of_type (arg0, G_VARIANT_TYPE_STRING_ARRAY))
- {
- const gchar **names = g_variant_get_strv (arg0, NULL);
- int i;
-
- /* Loop over all current names and get the owner for all the ones that match our rules
- policies so that we can update the unique id policies for those */
- for (i = 0; names[i] != NULL; i++)
- {
- const char *name = names[i];
-
- if (name[0] != ':' &&
- flatpak_proxy_client_get_max_policy (client, name) != FLATPAK_POLICY_NONE)
- {
- /* Get the current owner of the name (if any) so we can apply policy to it */
- GDBusMessage *message = g_dbus_message_new_method_call ("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetNameOwner");
- g_dbus_message_set_body (message, g_variant_new ("(s)", name));
- queue_fake_message (client, message, EXPECTED_REPLY_FAKE_GET_NAME_OWNER);
- g_hash_table_replace (client->get_owner_reply, GINT_TO_POINTER (client->last_serial), g_strdup (name));
-
- if (client->proxy->log_messages)
- g_print ("C%d: -> org.freedesktop.DBus fake GetNameOwner for %s\n", client->last_serial, name);
- }
- }
- g_free (names);
- }
-
- g_object_unref (decoded_message);
-}
-
-
-static void
-got_buffer_from_client (FlatpakProxyClient *client, ProxySide *side, Buffer *buffer)
-{
- ExpectedReplyType expecting_reply = EXPECTED_REPLY_NONE;
-
- if (client->authenticated && client->proxy->filter)
- {
- g_autoptr(Header) header = NULL;
- ;
- BusHandler handler;
-
- /* Filter and rewrite outgoing messages as needed */
-
- header = parse_header (buffer, client->serial_offset, 0, 0);
- if (header == NULL)
- {
- g_warning ("Invalid message header format");
- side_closed (side);
- buffer_unref (buffer);
- return;
- }
-
- if (!update_socket_messages (side, buffer, header))
- return;
-
- /* Make sure the client is not playing games with the serials, as that
- could confuse us. */
- if (header->serial <= client->last_serial)
- {
- g_warning ("Invalid client serial");
- side_closed (side);
- buffer_unref (buffer);
- return;
- }
- client->last_serial = header->serial;
-
- if (client->proxy->log_messages)
- print_outgoing_header (header);
-
- /* Keep track of the initial Hello request so that we can read
- the reply which has our assigned unique id */
- if (is_dbus_method_call (header) &&
- g_strcmp0 (header->member, "Hello") == 0)
- {
- expecting_reply = EXPECTED_REPLY_HELLO;
- client->hello_serial = header->serial;
- }
-
- handler = get_dbus_method_handler (client, header);
-
- switch (handler)
- {
- case HANDLE_FILTER_HAS_OWNER_REPLY:
- case HANDLE_FILTER_GET_OWNER_REPLY:
- if (!validate_arg0_name (client, buffer, FLATPAK_POLICY_SEE, NULL))
- {
- g_clear_pointer (&buffer, buffer_unref);
- if (handler == HANDLE_FILTER_GET_OWNER_REPLY)
- buffer = get_error_for_roundtrip (client, header,
- "org.freedesktop.DBus.Error.NameHasNoOwner");
- else
- buffer = get_bool_reply_for_roundtrip (client, header, FALSE);
-
- expecting_reply = EXPECTED_REPLY_REWRITE;
- break;
- }
-
- goto handle_pass;
-
- case HANDLE_VALIDATE_MATCH:
- if (!validate_arg0_match (client, buffer))
- {
- if (client->proxy->log_messages)
- g_print ("*DENIED* (ping)\n");
- g_clear_pointer (&buffer, buffer_unref);
- buffer = get_error_for_roundtrip (client, header,
- "org.freedesktop.DBus.Error.AccessDenied");
- expecting_reply = EXPECTED_REPLY_REWRITE;
- break;
- }
-
- goto handle_pass;
-
- case HANDLE_VALIDATE_OWN:
- case HANDLE_VALIDATE_SEE:
- case HANDLE_VALIDATE_TALK:
- {
- FlatpakPolicy name_policy;
- if (validate_arg0_name (client, buffer, policy_from_handler (handler), &name_policy))
- goto handle_pass;
-
- if (name_policy < (int) FLATPAK_POLICY_SEE)
- goto handle_hide;
- else
- goto handle_deny;
- }
-
- case HANDLE_FILTER_NAME_LIST_REPLY:
- expecting_reply = EXPECTED_REPLY_LIST_NAMES;
- goto handle_pass;
-
- case HANDLE_PASS:
-handle_pass:
- if (client_message_generates_reply (header))
- {
- if (expecting_reply == EXPECTED_REPLY_NONE)
- expecting_reply = EXPECTED_REPLY_NORMAL;
- }
-
- break;
-
- case HANDLE_HIDE:
-handle_hide:
- g_clear_pointer (&buffer, buffer_unref);
-
- if (client_message_generates_reply (header))
- {
- const char *error;
-
- if (client->proxy->log_messages)
- g_print ("*HIDDEN* (ping)\n");
-
- if ((header->destination != NULL && header->destination[0] == ':') ||
- (header->flags & G_DBUS_MESSAGE_FLAGS_NO_AUTO_START) != 0)
- error = "org.freedesktop.DBus.Error.NameHasNoOwner";
- else
- error = "org.freedesktop.DBus.Error.ServiceUnknown";
-
- buffer = get_error_for_roundtrip (client, header, error);
- expecting_reply = EXPECTED_REPLY_REWRITE;
- }
- else
- {
- if (client->proxy->log_messages)
- g_print ("*HIDDEN*\n");
- }
- break;
-
- default:
- case HANDLE_DENY:
-handle_deny:
- g_clear_pointer (&buffer, buffer_unref);
-
- if (client_message_generates_reply (header))
- {
- if (client->proxy->log_messages)
- g_print ("*DENIED* (ping)\n");
-
- buffer = get_error_for_roundtrip (client, header,
- "org.freedesktop.DBus.Error.AccessDenied");
- expecting_reply = EXPECTED_REPLY_REWRITE;
- }
- else
- {
- if (client->proxy->log_messages)
- g_print ("*DENIED*\n");
- }
- break;
- }
-
- if (buffer != NULL && expecting_reply != EXPECTED_REPLY_NONE)
- queue_expected_reply (side, header->serial, expecting_reply);
- }
-
- if (buffer)
- queue_outgoing_buffer (&client->bus_side, buffer);
-
- if (buffer != NULL && expecting_reply == EXPECTED_REPLY_HELLO)
- queue_initial_name_ops (client);
-}
-
-static void
-got_buffer_from_bus (FlatpakProxyClient *client, ProxySide *side, Buffer *buffer)
-{
- if (client->authenticated && client->proxy->filter)
- {
- g_autoptr(Header) header = NULL;
- ;
- GDBusMessage *rewritten;
- FlatpakPolicy policy;
- ExpectedReplyType expected_reply;
-
- /* Filter and rewrite incoming messages as needed */
-
- header = parse_header (buffer, 0, client->serial_offset, client->hello_serial);
- if (header == NULL)
- {
- g_warning ("Invalid message header format");
- buffer_unref (buffer);
- side_closed (side);
- return;
- }
-
- if (!update_socket_messages (side, buffer, header))
- return;
-
- if (client->proxy->log_messages)
- print_incoming_header (header);
-
- if (header->has_reply_serial)
- {
- expected_reply = steal_expected_reply (get_other_side (side), header->reply_serial);
-
- /* We only allow replies we expect */
- if (expected_reply == EXPECTED_REPLY_NONE)
- {
- if (client->proxy->log_messages)
- g_print ("*Unexpected reply*\n");
- buffer_unref (buffer);
- return;
- }
-
- switch (expected_reply)
- {
- case EXPECTED_REPLY_HELLO:
- /* When we get the initial reply to Hello, allow all
- further communications to our own unique id. */
- if (header->type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN)
- {
- g_autofree char *my_id = get_arg0_string (buffer);
- flatpak_proxy_client_update_unique_id_policy (client, my_id, FLATPAK_POLICY_TALK);
- break;
- }
-
- case EXPECTED_REPLY_REWRITE:
- /* Replace a roundtrip ping with the rewritten message */
-
- rewritten = g_hash_table_lookup (client->rewrite_reply,
- GINT_TO_POINTER (header->reply_serial));
-
- if (client->proxy->log_messages)
- g_print ("*REWRITTEN*\n");
-
- g_dbus_message_set_serial (rewritten, header->serial);
- g_clear_pointer (&buffer, buffer_unref);
- buffer = message_to_buffer (rewritten);
-
- g_hash_table_remove (client->rewrite_reply,
- GINT_TO_POINTER (header->reply_serial));
- break;
-
- case EXPECTED_REPLY_FAKE_LIST_NAMES:
- /* This is a reply from the bus to a fake ListNames
- request, request ownership of any name matching a
- wildcard policy */
-
- queue_wildcard_initial_name_ops (client, header, buffer);
-
- /* Don't forward fake replies to the app */
- if (client->proxy->log_messages)
- g_print ("*SKIPPED*\n");
- g_clear_pointer (&buffer, buffer_unref);
-
- /* Start reading the clients requests now that we are done with the names */
- start_reading (&client->client_side);
- break;
-
- case EXPECTED_REPLY_FAKE_GET_NAME_OWNER:
- /* This is a reply from the bus to a fake GetNameOwner
- request, update the policy for this unique name based on
- the policy */
- {
- char *requested_name = g_hash_table_lookup (client->get_owner_reply, GINT_TO_POINTER (header->reply_serial));
-
- if (header->type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN)
- {
- g_autofree char *owner = get_arg0_string (buffer);
- flatpak_proxy_client_add_unique_id_owned_name (client, owner, requested_name);
- }
-
- g_hash_table_remove (client->get_owner_reply, GINT_TO_POINTER (header->reply_serial));
-
- /* Don't forward fake replies to the app */
- if (client->proxy->log_messages)
- g_print ("*SKIPPED*\n");
- g_clear_pointer (&buffer, buffer_unref);
- break;
- }
-
- case EXPECTED_REPLY_FILTER:
- if (client->proxy->log_messages)
- g_print ("*SKIPPED*\n");
- g_clear_pointer (&buffer, buffer_unref);
- break;
-
- case EXPECTED_REPLY_LIST_NAMES:
- /* This is a reply from the bus to a ListNames request, filter
- it according to the policy */
- if (header->type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN)
- {
- Buffer *filtered_buffer;
-
- filtered_buffer = filter_names_list (client, buffer);
- g_clear_pointer (&buffer, buffer_unref);
- buffer = filtered_buffer;
- }
-
- break;
-
- case EXPECTED_REPLY_NORMAL:
- break;
-
- default:
- g_warning ("Unexpected expected reply type %d", expected_reply);
- }
- }
- else /* Not reply */
- {
-
- /* Don't allow reply types with no reply_serial */
- if (header->type == G_DBUS_MESSAGE_TYPE_METHOD_RETURN ||
- header->type == G_DBUS_MESSAGE_TYPE_ERROR)
- {
- if (client->proxy->log_messages)
- g_print ("*Invalid reply*\n");
- g_clear_pointer (&buffer, buffer_unref);
- }
-
- /* We filter all NameOwnerChanged signal according to the policy */
- if (message_is_name_owner_changed (client, header))
- {
- if (should_filter_name_owner_changed (client, buffer))
- g_clear_pointer (&buffer, buffer_unref);
- }
- }
-
- /* All incoming broadcast signals are filtered according to policy */
- if (header->type == G_DBUS_MESSAGE_TYPE_SIGNAL && header->destination == NULL)
- {
- g_autoptr(GList) filters = NULL;
- gboolean filtered = TRUE;
-
- policy = flatpak_proxy_client_get_max_policy_and_matched (client, header->sender, &filters);
-
- if (policy == FLATPAK_POLICY_OWN ||
- (policy == FLATPAK_POLICY_TALK &&
- any_filter_matches (filters, FILTER_TYPE_BROADCAST,
- header->path,
- header->interface,
- header->member)))
- filtered = FALSE;
-
- if (filtered)
- {
- if (client->proxy->log_messages)
- g_print ("*FILTERED IN*\n");
- g_clear_pointer (&buffer, buffer_unref);
- }
- }
-
- /* We received and forwarded a message from a trusted peer. Make the policy for
- this unique id SEE so that the client can track its lifetime. */
- if (buffer && header->sender && header->sender[0] == ':')
- flatpak_proxy_client_update_unique_id_policy (client, header->sender, FLATPAK_POLICY_SEE);
-
- if (buffer && client_message_generates_reply (header))
- queue_expected_reply (side, header->serial, EXPECTED_REPLY_NORMAL);
- }
-
- if (buffer)
- queue_outgoing_buffer (&client->client_side, buffer);
-}
-
-static void
-got_buffer_from_side (ProxySide *side, Buffer *buffer)
-{
- FlatpakProxyClient *client = side->client;
-
- if (side == &client->client_side)
- got_buffer_from_client (client, side, buffer);
- else
- got_buffer_from_bus (client, side, buffer);
-}
-
-#define _DBUS_ISASCII(c) ((c) != '\0' && (((c) & ~0x7f) == 0))
-
-static gboolean
-auth_line_is_valid (guint8 *line, guint8 *line_end)
-{
- guint8 *p;
-
- for (p = line; p < line_end; p++)
- {
- if (!_DBUS_ISASCII (*p))
- return FALSE;
-
- /* Technically, the dbus spec allows all ASCII characters, but for robustness we also
- fail if we see any control characters. Such low values will appear in potential attacks,
- but will never happen in real sasl (where all binary data is hex encoded). */
- if (*p < ' ')
- return FALSE;
- }
-
- /* For robustness we require the first char of the line to be an upper case letter.
- This is not technically required by the dbus spec, but all commands are upper
- case, and there is no provisioning for whitespace before the command, so in practice
- this is true, and this means we're not confused by e.g. initial whitespace. */
- if (line[0] < 'A' || line[0] > 'Z')
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-auth_line_is_begin (guint8 *line)
-{
- guint8 next_char;
-
- if (!g_str_has_prefix ((char *) line, AUTH_BEGIN))
- return FALSE;
-
- /* dbus-daemon accepts either nothing, or a whitespace followed by anything as end of auth */
- next_char = line[strlen (AUTH_BEGIN)];
- return next_char == 0 ||
- next_char == ' ' ||
- next_char == '\t';
-}
-
-static gssize
-find_auth_end (FlatpakProxyClient *client, Buffer *buffer)
-{
- goffset offset = 0;
- gsize original_size = client->auth_buffer->len;
-
- /* Add the new data to the remaining data from last iteration */
- g_byte_array_append (client->auth_buffer, buffer->data, buffer->pos);
-
- while (TRUE)
- {
- guint8 *line_start = client->auth_buffer->data + offset;
- gsize remaining_data = client->auth_buffer->len - offset;
- guint8 *line_end;
-
- line_end = memmem (line_start, remaining_data,
- AUTH_LINE_SENTINEL, strlen (AUTH_LINE_SENTINEL));
- if (line_end) /* Found end of line */
- {
- offset = (line_end + strlen (AUTH_LINE_SENTINEL) - line_start);
-
- if (!auth_line_is_valid (line_start, line_end))
- return FIND_AUTH_END_ABORT;
-
- *line_end = 0;
- if (auth_line_is_begin (line_start))
- return offset - original_size;
-
- /* continue with next line */
- }
- else
- {
- /* No end-of-line in this buffer */
- g_byte_array_remove_range (client->auth_buffer, 0, offset);
-
- /* Abort if more than 16k before newline, similar to what dbus-daemon does */
- if (client->auth_buffer->len >= 16 * 1024)
- return FIND_AUTH_END_ABORT;
-
- return FIND_AUTH_END_CONTINUE;
- }
- }
-}
-
-static gboolean
-side_in_cb (GSocket *socket, GIOCondition condition, gpointer user_data)
-{
- ProxySide *side = user_data;
- FlatpakProxyClient *client = side->client;
- GError *error = NULL;
- Buffer *buffer;
- gboolean retval = G_SOURCE_CONTINUE;
-
- g_object_ref (client);
-
- while (!side->closed)
- {
- if (!side->got_first_byte)
- buffer = buffer_new (1, NULL);
- else if (!client->authenticated)
- buffer = buffer_new (64, NULL);
- else
- buffer = side->current_read_buffer;
-
- if (!buffer_read (side, buffer, socket))
- {
- if (buffer != side->current_read_buffer)
- buffer_unref (buffer);
- break;
- }
-
- if (!client->authenticated)
- {
- if (buffer->pos > 0)
- {
- gboolean found_auth_end = FALSE;
- gsize extra_data;
-
- buffer->size = buffer->pos;
- if (!side->got_first_byte)
- {
- buffer->send_credentials = TRUE;
- side->got_first_byte = TRUE;
- }
- /* Look for end of authentication mechanism */
- else if (side == &client->client_side)
- {
- gssize auth_end = find_auth_end (client, buffer);
-
- if (auth_end >= 0)
- {
- found_auth_end = TRUE;
- buffer->size = auth_end;
- extra_data = buffer->pos - buffer->size;
-
- /* We may have gotten some extra data which is not part of
- the auth handshake, keep it for the next iteration. */
- if (extra_data > 0)
- side->extra_input_data = g_bytes_new (buffer->data + buffer->size, extra_data);
- }
- else if (auth_end == FIND_AUTH_END_ABORT)
- {
- buffer_unref (buffer);
- if (client->proxy->log_messages)
- g_print ("Invalid AUTH line, aborting\n");
- side_closed (side);
- break;
- }
- }
-
- got_buffer_from_side (side, buffer);
-
- if (found_auth_end)
- client->authenticated = TRUE;
- }
- else
- {
- buffer_unref (buffer);
- }
- }
- else if (buffer->pos == buffer->size)
- {
- if (buffer == &side->header_buffer)
- {
- gssize required;
- required = g_dbus_message_bytes_needed (buffer->data, buffer->size, &error);
- if (required < 0)
- {
- g_warning ("Invalid message header read");
- side_closed (side);
- }
- else
- {
- side->current_read_buffer = buffer_new (required, buffer);
- }
- }
- else
- {
- got_buffer_from_side (side, buffer);
- side->header_buffer.pos = 0;
- side->current_read_buffer = &side->header_buffer;
- }
- }
- }
-
- if (side->closed)
- {
- side->in_source = NULL;
- retval = G_SOURCE_REMOVE;
- }
-
- g_object_unref (client);
-
- return retval;
-}
-
-static void
-start_reading (ProxySide *side)
-{
- GSocket *socket;
-
- socket = g_socket_connection_get_socket (side->connection);
- side->in_source = g_socket_create_source (socket, G_IO_IN, NULL);
- g_source_set_callback (side->in_source, (GSourceFunc) side_in_cb, side, NULL);
- g_source_attach (side->in_source, NULL);
- g_source_unref (side->in_source);
-}
-
-static void
-stop_reading (ProxySide *side)
-{
- if (side->in_source)
- {
- g_source_destroy (side->in_source);
- side->in_source = NULL;
- }
-}
-
-
-static void
-client_connected_to_dbus (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
-{
- FlatpakProxyClient *client = user_data;
- GSocketConnection *connection;
- GError *error = NULL;
- GIOStream *stream;
-
- stream = g_dbus_address_get_stream_finish (res, NULL, &error);
- if (stream == NULL)
- {
- g_warning ("Failed to connect to bus: %s", error->message);
- g_object_unref (client);
- return;
- }
-
- connection = G_SOCKET_CONNECTION (stream);
- g_socket_set_blocking (g_socket_connection_get_socket (connection), FALSE);
- client->bus_side.connection = connection;
-
- start_reading (&client->client_side);
- start_reading (&client->bus_side);
-}
-
-static gboolean
-flatpak_proxy_incoming (GSocketService *service,
- GSocketConnection *connection,
- GObject *source_object)
-{
- FlatpakProxy *proxy = FLATPAK_PROXY (service);
- FlatpakProxyClient *client;
-
- client = flatpak_proxy_client_new (proxy, connection);
-
- g_dbus_address_get_stream (proxy->dbus_address,
- NULL,
- client_connected_to_dbus,
- client);
- return TRUE;
-}
-
-static void
-flatpak_proxy_init (FlatpakProxy *proxy)
-{
- proxy->filters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) filter_list_free);
- flatpak_proxy_add_policy (proxy, "org.freedesktop.DBus", FALSE, FLATPAK_POLICY_TALK);
-}
-
-static void
-flatpak_proxy_class_init (FlatpakProxyClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GSocketServiceClass *socket_service_class = G_SOCKET_SERVICE_CLASS (klass);
-
- object_class->get_property = flatpak_proxy_get_property;
- object_class->set_property = flatpak_proxy_set_property;
- object_class->finalize = flatpak_proxy_finalize;
-
- socket_service_class->incoming = flatpak_proxy_incoming;
-
- g_object_class_install_property (object_class,
- PROP_DBUS_ADDRESS,
- g_param_spec_string ("dbus-address",
- "",
- "",
- NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
- g_object_class_install_property (object_class,
- PROP_SOCKET_PATH,
- g_param_spec_string ("socket-path",
- "",
- "",
- NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-}
-
-FlatpakProxy *
-flatpak_proxy_new (const char *dbus_address,
- const char *socket_path)
-{
- FlatpakProxy *proxy;
-
- proxy = g_object_new (FLATPAK_TYPE_PROXY, "dbus-address", dbus_address, "socket-path", socket_path, NULL);
- return proxy;
-}
-
-gboolean
-flatpak_proxy_start (FlatpakProxy *proxy, GError **error)
-{
- GSocketAddress *address;
- gboolean res;
-
- unlink (proxy->socket_path);
-
- address = g_unix_socket_address_new (proxy->socket_path);
-
- error = NULL;
- res = g_socket_listener_add_address (G_SOCKET_LISTENER (proxy),
- address,
- G_SOCKET_TYPE_STREAM,
- G_SOCKET_PROTOCOL_DEFAULT,
- NULL, /* source_object */
- NULL, /* effective_address */
- error);
- g_object_unref (address);
-
- if (!res)
- return FALSE;
-
-
- g_socket_service_start (G_SOCKET_SERVICE (proxy));
- return TRUE;
-}
-
-void
-flatpak_proxy_stop (FlatpakProxy *proxy)
-{
- unlink (proxy->socket_path);
-
- g_socket_service_stop (G_SOCKET_SERVICE (proxy));
-}
diff --git a/dbus-proxy/flatpak-proxy.h b/dbus-proxy/flatpak-proxy.h
deleted file mode 100644
index a42b507e..00000000
--- a/dbus-proxy/flatpak-proxy.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright © 2015 Red Hat, Inc
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Alexander Larsson <alexl@redhat.com>
- */
-
-#ifndef __FLATPAK_PROXY_H__
-#define __FLATPAK_PROXY_H__
-
-#include <gio/gio.h>
-#include "libglnx/libglnx.h"
-
-typedef enum {
- FLATPAK_POLICY_NONE,
- FLATPAK_POLICY_SEE,
- FLATPAK_POLICY_TALK,
- FLATPAK_POLICY_OWN
-} FlatpakPolicy;
-
-typedef struct FlatpakProxy FlatpakProxy;
-
-#define FLATPAK_TYPE_PROXY flatpak_proxy_get_type ()
-#define FLATPAK_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_PROXY, FlatpakProxy))
-#define FLATPAK_IS_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_PROXY))
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakProxy, g_object_unref)
-
-GType flatpak_proxy_get_type (void);
-
-FlatpakProxy *flatpak_proxy_new (const char *dbus_address,
- const char *socket_path);
-void flatpak_proxy_set_log_messages (FlatpakProxy *proxy,
- gboolean log);
-void flatpak_proxy_set_filter (FlatpakProxy *proxy,
- gboolean filter);
-void flatpak_proxy_set_sloppy_names (FlatpakProxy *proxy,
- gboolean sloppy_names);
-void flatpak_proxy_add_policy (FlatpakProxy *proxy,
- const char *name,
- gboolean name_is_subtree,
- FlatpakPolicy policy);
-void flatpak_proxy_add_call_rule (FlatpakProxy *proxy,
- const char *name,
- gboolean name_is_subtree,
- const char *rule);
-void flatpak_proxy_add_broadcast_rule (FlatpakProxy *proxy,
- const char *name,
- gboolean name_is_subtree,
- const char *rule);
-gboolean flatpak_proxy_start (FlatpakProxy *proxy,
- GError **error);
-void flatpak_proxy_stop (FlatpakProxy *proxy);
-
-#endif /* __FLATPAK_PROXY_H__ */