From 96988286b4c594c535cf06691159868daf4ca7d2 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 9 Sep 2013 19:19:27 +0100 Subject: [PATCH 6/8] Remove old "D-Bus ACL" plugin API It was last used in Maemo 6. Mainstream Linux doesn't treat the session bus as a security boundary, and if it did, we could do this a lot better (with GAsyncResult, for a start). Also, McpRequestPolicy does this in a much less speculatively-general way. --- mission-control-plugins/Makefile.am | 2 - mission-control-plugins/dbus-acl.c | 431 --------------------- mission-control-plugins/dbus-acl.h | 134 ------- mission-control-plugins/debug.c | 3 +- mission-control-plugins/debug.h | 3 +- mission-control-plugins/mission-control-plugins.h | 1 - plugins/mcp-dbus-aegis-acl.c | 441 ---------------------- src/mcd-connection.c | 1 + src/mcd-dispatcher.c | 204 ++-------- src/mcd-storage.c | 1 + tests/twisted/Makefile.am | 4 - tests/twisted/mcp-dbus-caller-permission.c | 264 ------------- tests/twisted/mcp-plugin.c | 1 - 13 files changed, 37 insertions(+), 1453 deletions(-) delete mode 100644 mission-control-plugins/dbus-acl.c delete mode 100644 mission-control-plugins/dbus-acl.h delete mode 100644 plugins/mcp-dbus-aegis-acl.c delete mode 100644 tests/twisted/mcp-dbus-caller-permission.c diff --git a/mission-control-plugins/Makefile.am b/mission-control-plugins/Makefile.am index 1c6abf1..0e38dd4 100644 --- a/mission-control-plugins/Makefile.am +++ b/mission-control-plugins/Makefile.am @@ -21,7 +21,6 @@ plugins_include_HEADERS = \ mission-control-plugins.h \ account.h \ account-storage.h \ - dbus-acl.h \ debug.h \ dispatch-operation.h \ dispatch-operation-policy.h \ @@ -54,7 +53,6 @@ libmission_control_plugins_la_SOURCES = \ debug.c \ account.c \ account-storage.c \ - dbus-acl.c \ dispatch-operation.c \ dispatch-operation-policy.c \ implementation.h \ diff --git a/mission-control-plugins/dbus-acl.c b/mission-control-plugins/dbus-acl.c deleted file mode 100644 index 82ef0a2..0000000 --- a/mission-control-plugins/dbus-acl.c +++ /dev/null @@ -1,431 +0,0 @@ -/* Mission Control plugin API - DBus Caller ID. - * - * Copyright © 2010 Nokia Corporation - * Copyright © 2010 Collabora Ltd. - * - * This library 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * SECTION:dbus-acl - * @title: McpDBusAcl - * @short_description: DBus ACLs, implemented by plugins - * @see_also: - * @include: mission-control-plugins/mission-control-plugins.h - * - * Plugins may implement #McpDBusAcl in order to provide checks on whether - * a DBus method call or property get/set operation should be allowed. - * - * To do so, the plugin must implement a #GObject subclass that implements - * #McpDBusAcl, then return an instance of that subclass from - * mcp_plugin_ref_nth_object(). - * - * An implementation of this interface might look like this: - * - * - * G_DEFINE_TYPE_WITH_CODE (APlugin, a_plugin, - * G_TYPE_OBJECT, - * G_IMPLEMENT_INTERFACE (...); - * G_IMPLEMENT_INTERFACE (MCP_TYPE_DBUS_ACL, dbus_acl_iface_init); - * G_IMPLEMENT_INTERFACE (...)) - * /* ... */ - * static void - * dbus_acl_iface_init (McpDBusAclIface *iface, - * gpointer unused G_GNUC_UNUSED) - * { - * iface->name = "APlugin"; - * iface->desc = "A plugin that checks some conditions"; - * iface->authorised = _authorised; - * iface->authorised_async = _authorised_async; - * } - * - * - * A single object can implement more than one interface. - */ - -#include "config.h" - -#include -#include -#include -#include -#include - -#define MCP_DEBUG_TYPE MCP_DEBUG_DBUS_ACL -#define ACL_DEBUG(_p, _format, ...) \ - DEBUG("%s: " _format, \ - (_p != NULL) ? mcp_dbus_acl_name (_p) : "-", ##__VA_ARGS__) - -/** - * McpDBusAclIface: - * @parent: the parent type - * @name: the name of the plugin, or %NULL to use the GObject class name - * @desc: the description of the plugin, or %NULL - * @authorised: an implementation of part of mcp_dbus_acl_authorised() - * @authorised_async: an implementation of part of - * mcp_dbus_acl_authorised_async() - */ - -GType -mcp_dbus_acl_get_type (void) -{ - static gsize once = 0; - static GType type = 0; - - if (g_once_init_enter (&once)) - { - static const GTypeInfo info = - { - sizeof (McpDBusAclIface), - NULL, /* base_init */ - NULL, /* base_finalize */ - NULL, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - 0, /* instance_size */ - 0, /* n_preallocs */ - NULL, /* instance_init */ - NULL /* value_table */ - }; - - type = g_type_register_static (G_TYPE_INTERFACE, - "McpDBusAcl", &info, 0); - g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); - - g_once_init_leave (&once, 1); - } - - return type; -} - -static GList * -cached_acls (void) -{ - static gboolean acl_plugins_cached = FALSE; - static GList *dbus_acls = NULL; - - const GList *p; - - if (acl_plugins_cached) - return dbus_acls; - - /* insert the default storage plugin into the sorted plugin list */ - for (p = mcp_list_objects(); p != NULL; p = g_list_next (p)) - { - if (MCP_IS_DBUS_ACL (p->data)) - { - dbus_acls = g_list_prepend (dbus_acls, g_object_ref (p->data)); - } - } - - acl_plugins_cached = TRUE; - - return dbus_acls; -} - - -static DBusAclAuthData * -auth_data_new (TpDBusDaemon *dbus, const gchar *name, GHashTable *params) -{ - DBusAclAuthData *data = g_slice_new0 (DBusAclAuthData); - - data->dbus = g_object_ref (dbus); - data->params = (params != NULL) ? g_hash_table_ref (params) : NULL; - data->name = g_strdup (name); - - return data; -} - -static void -auth_data_free (DBusAclAuthData *data) -{ - data->cleanup (data->data); /* free the callback data */ - - tp_clear_pointer (&data->params, g_hash_table_unref); - tp_clear_object (&data->dbus); - g_free (data->name); - - g_slice_free (DBusAclAuthData, data); -} -/** - * mcp_dbus_acl_iface_set_name: - * @iface: an instance implementing McpDBusAclIface - * @name: the plugin's name (used in debugging and some return values) - * - * Sets the name of the plugin. Intended for use by the plugin implementor. - * - * This is no longer necessary: just use "iface->name = name". - **/ -void -mcp_dbus_acl_iface_set_name (McpDBusAclIface *iface, - const gchar *name) -{ - iface->name = name; -} - -/** - * mcp_dbus_acl_iface_set_desc: - * @iface: an instance implementing McpDBusAclIface - * @desc: the plugin's description - * - * Sets the plugin's description. Intended for use by the plugin implementor. - * - * This is no longer necessary: just use "iface->desc = desc". - **/ -void -mcp_dbus_acl_iface_set_desc (McpDBusAclIface *iface, - const gchar *desc) -{ - iface->desc = desc; -} - -/** - * mcp_dbus_acl_iface_implement_authorised: - * @iface: an instance implementing McpDBusAclIface - * @method: the plugin's description - * - * Implements this plugin's part of the mcp_dbus_acl_authorised() method. - * - * This is no longer necessary: just use "iface->authorised = method". - **/ -void -mcp_dbus_acl_iface_implement_authorised (McpDBusAclIface *iface, - DBusAclAuthoriser method) -{ - iface->authorised = method; -} - -/** - * mcp_dbus_acl_iface_implement_authorised_async: - * @iface: an instance implementing McpDBusAclIface - * @method: the plugin's description - * - * Implements this plugin's part of the mcp_dbus_acl_authorised_async() method. - * - * This is no longer necessary: just use "iface->authorised_async = method". - **/ -void -mcp_dbus_acl_iface_implement_authorised_async (McpDBusAclIface *iface, - DBusAclAsyncAuthoriser method) -{ - iface->authorised_async = method; -} - -/* FIXME: when we break ABI, this should move to src/ under a different name, - * and mcp_dbus_acl_authorised() should be a trivial wrapper around - * iface->authorised() */ -/** - * mcp_dbus_acl_authorised: - * @dbus: a #TpDBusDaemon instance - * @context: a #DBusGMethodInvocation corresponding to the DBus call - * @type: a #DBusAclType value (method call, get or set property) - * @name: the name of the method or property in question - * @params: A #GHashTable of #gchar * / #GValue parameters relating to the - * call which are deemed to be "of interest" for ACL plugins, or %NULL - * - * This method calls each #DBusAcl plugin's authorised method, set by - * mcp_dbus_acl_iface_implement_authorised() - * - * How a plugin deals with @params is entirely plugin dependent. - * - * If any plugin returns %FALSE, the call is considered to be forbidden. - * - * Returns: a #gboolean - %TRUE for permitted, %FALSE for forbidden. - **/ -gboolean -mcp_dbus_acl_authorised (const TpDBusDaemon *dbus, - DBusGMethodInvocation *context, - DBusAclType type, - const gchar *name, - const GHashTable *params) -{ - GList *p; - GList *acls = cached_acls (); - gboolean permitted = TRUE; - - for (p = acls; permitted && p != NULL; p = g_list_next (p)) - { - McpDBusAcl *plugin = MCP_DBUS_ACL (p->data); - McpDBusAclIface *iface = MCP_DBUS_ACL_GET_IFACE (p->data); - - ACL_DEBUG (plugin, "checking ACL for %s", name); - - if (iface->authorised != NULL) - permitted = iface->authorised (plugin, dbus, context, type, name, params); - - if (!permitted) - break; - } - - if (!permitted) - { - GError *denied = NULL; - const gchar *denier = mcp_dbus_acl_name (p->data); - - denied = g_error_new (DBUS_GERROR, DBUS_GERROR_ACCESS_DENIED, - "permission denied by DBus ACL plugin '%s'", denier); - - dbus_g_method_return_error (context, denied); - - g_error_free (denied); - } - - return permitted; -} - -/** - * mcp_dbus_acl_authorised_async_step: - * @ad: a #DBusAclAuthData pointer - * @permitted: whether the last plugin permitted the call being inspected - * - * This call is intended for use in the authorised_async mehod of a - * #DBusAcl plugin - it allows the plugin to hand control back to the - * overall ACL infrastructure, informing it of its decision as it does. - **/ -void -mcp_dbus_acl_authorised_async_step (DBusAclAuthData *ad, - gboolean permitted) -{ - if (permitted) - { - while (ad->next_acl != NULL && ad->next_acl->data != NULL) - { - McpDBusAcl *plugin = MCP_DBUS_ACL (ad->next_acl->data); - McpDBusAclIface *iface = MCP_DBUS_ACL_GET_IFACE (plugin); - - if (ad->acl != NULL) - ACL_DEBUG (ad->acl, "passed ACL for %s", ad->name); - - /* take the next plugin off the next_acl list */ - ad->next_acl = g_list_next (ad->next_acl); - ad->acl = plugin; - - if (iface->authorised_async != NULL) - { - /* kick off the next async authoriser in the chain */ - iface->authorised_async (plugin, ad); - - /* don't clean up, the next async acl will call us when it's - * done: */ - return; - } - } - - if (ad->acl != NULL) - ACL_DEBUG (ad->acl, "passed final ACL for %s", ad->name); - - ad->handler (ad->context, ad->data); - } - else - { - const gchar *who = (ad->acl != NULL) ? mcp_dbus_acl_name (ad->acl) : NULL; - GError *denied = g_error_new (DBUS_GERROR, DBUS_GERROR_ACCESS_DENIED, - "%s permission denied by DBus ACL plugin '%s'", - ad->name, - (who != NULL) ? who : "*unknown*"); - - dbus_g_method_return_error (ad->context, denied); - - g_error_free (denied); - } - - auth_data_free (ad); /* done with internal bookkeeping */ -} - -/* FIXME: when we break ABI, this should move to src/ under a different name, - * and mcp_dbus_acl_authorised_async() should be a trivial wrapper around - * iface->authorised_async(); it should also use GIO-style asynchronicity */ -/** - * mcp_dbus_acl_authorised_async: - * @dbus: a #TpDBusDaemon instance - * @context: a #DBusGMethodInvocation corresponding to the DBus call - * @type: a #DBusAclType value (method call, get or set property) - * @name: the name of the method or property in question - * @params: A #GHashTable of #gchar * / #GValue parameters relating to the - * call which are deemed to be "of interest" for ACL plugins, or %NULL - * @handler: callback to call if the ACL decides the call is permitted - * @data: a #gpointer to pass to the @handler - * @cleanup: a #GDestroyNotify to use to deallocate @data - * - * This method calls each #DBusAcl plugin's authorised_async method, set by - * mcp_dbus_acl_iface_implement_authorised_async() - * - * How a plugin deals with @parameters is entirely plugin dependent. - * - * The plugin should implement an async (or at least non-blocking) - * check, which should signal that it has finished by calling - * mcp_dbus_acl_authorised_async_step() - * - * If all the plugins permit this call, then @handler will be invoked - * with @context and @data as its arguments. - * - * @cleanup wll be called if the call is forbidden, or after @handler is - * invoked. If the call is forbidden, a DBus error will be returned to the - * caller automatically. - * - **/ -void -mcp_dbus_acl_authorised_async (TpDBusDaemon *dbus, - DBusGMethodInvocation *context, - DBusAclType type, - const gchar *name, - GHashTable *params, - DBusAclAuthorised handler, - gpointer data, - GDestroyNotify cleanup) -{ - GList *acls = cached_acls (); - DBusAclAuthData *ad = auth_data_new (dbus, name, params); - - ad->acl = NULL; /* first step, there's no current ACL yet */ - ad->type = type; - ad->data = data; - ad->cleanup = cleanup; - ad->context = context; - ad->handler = handler; - ad->next_acl = acls; - - ACL_DEBUG (NULL, "DBus access ACL verification: %u rules for %s", - g_list_length (acls), - name); - mcp_dbus_acl_authorised_async_step (ad, TRUE); -} - -/* plugin meta-data */ -const gchar * -mcp_dbus_acl_name (const McpDBusAcl *self) -{ - McpDBusAclIface *iface = MCP_DBUS_ACL_GET_IFACE (self); - - g_return_val_if_fail (iface != NULL, FALSE); - - if (iface->name == NULL) - return G_OBJECT_TYPE_NAME (self); - - return iface->name; -} - -const gchar * -mcp_dbus_acl_description (const McpDBusAcl *self) -{ - McpDBusAclIface *iface = MCP_DBUS_ACL_GET_IFACE (self); - - g_return_val_if_fail (iface != NULL, FALSE); - - if (iface->desc == NULL) - return "(no description)"; - - return iface->desc; -} diff --git a/mission-control-plugins/dbus-acl.h b/mission-control-plugins/dbus-acl.h deleted file mode 100644 index deba7b7..0000000 --- a/mission-control-plugins/dbus-acl.h +++ /dev/null @@ -1,134 +0,0 @@ -/* Mission Control plugin API - DBus Caller ID. - * - * Copyright © 2010 Nokia Corporation - * Copyright © 2010 Collabora Ltd. - * - * This library 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef MCP_DBUS_ACL_H -#define MCP_DBUS_ACL_H - -#ifndef _MCP_IN_MISSION_CONTROL_PLUGINS_H -#error Use instead -#endif - -#include -#include - -G_BEGIN_DECLS - -/* API for plugins to implement */ -typedef struct _McpDBusAcl McpDBusAcl; -typedef struct _McpDBusAclIface McpDBusAclIface; - -#define MCP_TYPE_DBUS_ACL (mcp_dbus_acl_get_type ()) - -#define MCP_DBUS_ACL(o) \ - (G_TYPE_CHECK_INSTANCE_CAST ((o), MCP_TYPE_DBUS_ACL, McpDBusAcl)) - -#define MCP_IS_DBUS_ACL(o) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((o), MCP_TYPE_DBUS_ACL)) - -#define MCP_DBUS_ACL_GET_IFACE(o) \ - (G_TYPE_INSTANCE_GET_INTERFACE ((o), MCP_TYPE_DBUS_ACL, \ - McpDBusAclIface)) - -GType mcp_dbus_acl_get_type (void) G_GNUC_CONST; - -/* FIXME: when we break API, rename all types to start with Mcp */ - -typedef void (*DBusAclAuthorised) (DBusGMethodInvocation *call, gpointer data); - -typedef enum { - DBUS_ACL_TYPE_UNKNOWN = 0, - DBUS_ACL_TYPE_METHOD, - DBUS_ACL_TYPE_GET_PROPERTY, - DBUS_ACL_TYPE_SET_PROPERTY, -} DBusAclType; - -typedef struct { - McpDBusAcl *acl; - const GList *next_acl; - DBusGMethodInvocation *context; - DBusAclType type; - gchar *name; - GHashTable *params; - TpDBusDaemon *dbus; - DBusAclAuthorised handler; - gpointer data; - GDestroyNotify cleanup; -} DBusAclAuthData; - -typedef gboolean (*DBusAclAuthoriser) (const McpDBusAcl *, - const TpDBusDaemon *, - const DBusGMethodInvocation *, - DBusAclType type, - const gchar *name, - const GHashTable *); - -typedef void (*DBusAclAsyncAuthoriser) (const McpDBusAcl *, - DBusAclAuthData *); - -/* real functions that handle multi-plugin acl logic */ -void mcp_dbus_acl_authorised_async_step (DBusAclAuthData *ad, - gboolean permitted); - -void mcp_dbus_acl_authorised_async (TpDBusDaemon *dbus, - DBusGMethodInvocation *context, - DBusAclType type, - const gchar *name, - GHashTable *params, - DBusAclAuthorised handler, - gpointer data, - GDestroyNotify cleanup); - -gboolean mcp_dbus_acl_authorised (const TpDBusDaemon *dbus, - DBusGMethodInvocation *context, - DBusAclType type, - const gchar *name, - const GHashTable *params); - -/* virtual methods */ -void mcp_dbus_acl_iface_set_name (McpDBusAclIface *iface, - const gchar *name); - -void mcp_dbus_acl_iface_set_desc (McpDBusAclIface *iface, - const gchar *desc); - -void mcp_dbus_acl_iface_implement_authorised (McpDBusAclIface *iface, - DBusAclAuthoriser method); - -void mcp_dbus_acl_iface_implement_authorised_async (McpDBusAclIface *iface, - DBusAclAsyncAuthoriser method); - -const gchar *mcp_dbus_acl_name (const McpDBusAcl *acl); - -const gchar *mcp_dbus_acl_description (const McpDBusAcl *acl); - -struct _McpDBusAclIface -{ - GTypeInterface parent; - - const gchar *name; - const gchar *desc; - - DBusAclAuthoriser authorised; - DBusAclAsyncAuthoriser authorised_async; -}; - -G_END_DECLS - -#endif diff --git a/mission-control-plugins/debug.c b/mission-control-plugins/debug.c index af0f1df..177e1d6 100644 --- a/mission-control-plugins/debug.c +++ b/mission-control-plugins/debug.c @@ -26,12 +26,11 @@ static McpDebugFlags debug_flags; static GDebugKey const keys[] = { { "account", MCP_DEBUG_ACCOUNT }, { "account-storage", MCP_DEBUG_ACCOUNT_STORAGE }, - { "dbus-acl", MCP_DEBUG_DBUS_ACL }, + { "request-policy", MCP_DEBUG_REQUEST_POLICY }, { "dispatch-operation", MCP_DEBUG_DISPATCH_OPERATION }, { "dispatch-operation-policy", MCP_DEBUG_DISPATCH_OPERATION_POLICY }, { "loader", MCP_DEBUG_LOADER }, { "request", MCP_DEBUG_REQUEST }, - { "request-policy", MCP_DEBUG_REQUEST_POLICY }, { NULL, 0 } }; diff --git a/mission-control-plugins/debug.h b/mission-control-plugins/debug.h index 909631c..a5c61c0 100644 --- a/mission-control-plugins/debug.h +++ b/mission-control-plugins/debug.h @@ -35,12 +35,11 @@ typedef enum { MCP_DEBUG_NONE = 0, MCP_DEBUG_ACCOUNT = 1 << 0, MCP_DEBUG_ACCOUNT_STORAGE = 1 << 1, - MCP_DEBUG_DBUS_ACL = 1 << 2, + MCP_DEBUG_REQUEST_POLICY = 1 << 2, MCP_DEBUG_DISPATCH_OPERATION = 1 << 3, MCP_DEBUG_DISPATCH_OPERATION_POLICY = 1 << 4, MCP_DEBUG_LOADER = 1 << 5, MCP_DEBUG_REQUEST = 1 << 6, - MCP_DEBUG_REQUEST_POLICY = 1 << 7, } McpDebugFlags; gboolean mcp_is_debugging (McpDebugFlags type); diff --git a/mission-control-plugins/mission-control-plugins.h b/mission-control-plugins/mission-control-plugins.h index d875199..13d87e6 100644 --- a/mission-control-plugins/mission-control-plugins.h +++ b/mission-control-plugins/mission-control-plugins.h @@ -37,7 +37,6 @@ typedef enum { #define _MCP_IN_MISSION_CONTROL_PLUGINS_H #include #include -#include #include #include #include diff --git a/plugins/mcp-dbus-aegis-acl.c b/plugins/mcp-dbus-aegis-acl.c deleted file mode 100644 index 1eda98e..0000000 --- a/plugins/mcp-dbus-aegis-acl.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * A pseudo-plugin that checks the caller's Aegis permission tokens - * - * Copyright © 2010-2011 Nokia Corporation - * Copyright © 2010-2011 Collabora Ltd. - * - * This library 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#ifdef G_LOG_DOMAIN -#undef G_LOG_DOMAIN -#endif -#define G_LOG_DOMAIN "mission-control-DBus-Access-ACL" - -#define DEBUG(_f, ...) MCP_DEBUG (MCP_DEBUG_DBUS_ACL, _f, ##__VA_ARGS__) - -#include - -#include -#include - -#include - -#include -#include - -typedef struct _AegisAcl AegisAcl; -typedef struct _AegisAclClass AegisAclClass; - -struct _AegisAcl { - GObject parent; -}; - -struct _AegisAclClass { - GObjectClass parent_class; -}; - -#define CREATE_CHANNEL TP_IFACE_CONNECTION_INTERFACE_REQUESTS ".CreateChannel" -#define ENSURE_CHANNEL TP_IFACE_CONNECTION_INTERFACE_REQUESTS ".EnsureChannel" -#define SEND_MESSAGE \ - TP_IFACE_CHANNEL_DISPATCHER ".Interface.Messages.DRAFT.SendMessage" - -#define AEGIS_CALL_TOKEN "Cellular" - -/* implemented by the Aegis-patched dbus-daemon */ -#define AEGIS_INTERFACE "com.meego.DBus.Creds" - -#define PLUGIN_NAME "dbus-aegis-acl" -#define PLUGIN_DESCRIPTION \ - "This plugin uses libcreds to check the aegis security tokens " \ - "associated with the calling process ID and determine whether " \ - "the DBus call or property access should be allowed" - -static creds_value_t aegis_token = CREDS_BAD; -static creds_type_t aegis_type = CREDS_BAD; - -static void aegis_acl_iface_init (McpDBusAclIface *, - gpointer); -static void aegis_cdo_policy_iface_init (McpDispatchOperationPolicyIface *, - gpointer); - -static GType aegis_acl_get_type (void); - -G_DEFINE_TYPE_WITH_CODE (AegisAcl, aegis_acl, - G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (MCP_TYPE_DBUS_ACL, aegis_acl_iface_init); - G_IMPLEMENT_INTERFACE (MCP_TYPE_DISPATCH_OPERATION_POLICY, - aegis_cdo_policy_iface_init)) - -static void -aegis_acl_init (AegisAcl *self) -{ -} - -static void -aegis_acl_class_init (AegisAclClass *cls) -{ - if (aegis_type != CREDS_BAD) - return; - - aegis_type = creds_str2creds (AEGIS_CALL_TOKEN, &aegis_token); -} - -static gchar *restricted_methods[] = - { - CREATE_CHANNEL, - ENSURE_CHANNEL, - SEND_MESSAGE, - NULL - }; - -static gboolean -method_is_filtered (const gchar *method) -{ - guint i; - - for (i = 0; restricted_methods[i] != NULL; i++) - { - if (!tp_strdiff (method, restricted_methods[i])) - return TRUE; - } - - return FALSE; -} - -static gboolean -is_filtered (DBusAclType type, - const gchar *name, - const GHashTable *params) -{ - const GValue *account = NULL; - const gchar *path = NULL; - - /* only bothered with method calls */ - if (type != DBUS_ACL_TYPE_METHOD) - return FALSE; - - /* only create/ensure channel concern us (and send message, now): */ - if (!method_is_filtered (name)) - return FALSE; - - /* must have at least the account-path to check */ - if (params == NULL) - return FALSE; - - account = g_hash_table_lookup ((GHashTable *) params, "account-path"); - - if (account == NULL) - return FALSE; - - path = g_value_get_string (account); - - DEBUG ("should we check account %s?", path); - /* account must belong to the ring or MMS connection manager: */ - if (g_str_has_prefix (path, TP_ACCOUNT_OBJECT_PATH_BASE "ring/") || - g_str_has_prefix (path, TP_ACCOUNT_OBJECT_PATH_BASE "mmscm/")) - return TRUE; - - return FALSE; -} - -/* For simplicity we don't implement non-trivial conversion between - * dbus-glib's arrays of guint, and libcreds' arrays of uint32_t. - * If this assertion fails on your platform, you'll need to implement it. */ -G_STATIC_ASSERT (sizeof (guint) == sizeof (uint32_t)); - -static gboolean -caller_creds_are_enough (const gchar *name, - const GArray *au) -{ - creds_t caller_creds = creds_import ((const uint32_t *) au->data, au->len); - gboolean ok = creds_have_p (caller_creds, aegis_type, aegis_token); - -#ifdef ENABLE_DEBUG - if (ok) - { - DEBUG ("Caller %s is appropriately privileged", name); - } - else - { - char buf[1024]; - creds_type_t debug_type; - creds_value_t debug_value; - int i = 0; - - DEBUG ("Caller %s has these credentials:", name); - - while ((debug_type = creds_list (caller_creds, i++, &debug_value)) - != CREDS_BAD) - { - creds_creds2str (debug_type, debug_value, buf, sizeof (buf)); - DEBUG ("- %s", buf); - } - - DEBUG ("but they are insufficient"); - } -#endif - - creds_free (caller_creds); - return ok; -} - -static gboolean -check_peer_creds_sync (DBusGConnection *dgc, - const gchar *bus_name, - gboolean activate) -{ - DBusGProxy *proxy = dbus_g_proxy_new_for_name (dgc, - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - AEGIS_INTERFACE); - GArray *au = NULL; - GError *error = NULL; - gboolean ok = FALSE; - - if (dbus_g_proxy_call (proxy, "GetConnectionCredentials", &error, - G_TYPE_STRING, bus_name, - G_TYPE_INVALID, - DBUS_TYPE_G_UINT_ARRAY, &au, - G_TYPE_INVALID)) - { - ok = caller_creds_are_enough (bus_name, au); - g_array_unref (au); - } - else if (activate && error->code == DBUS_GERROR_NAME_HAS_NO_OWNER) - { - guint status; - GError *start_error = NULL; - DBusGProxy *dbus = dbus_g_proxy_new_for_name (dgc, - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS); - - DEBUG ("Trying to activate %s for aegis credentials check", bus_name); - if (dbus_g_proxy_call (dbus, "StartServiceByName", &start_error, - G_TYPE_STRING, bus_name, - G_TYPE_UINT, 0, - G_TYPE_INVALID, - G_TYPE_UINT, &status, - G_TYPE_INVALID)) - { - ok = check_peer_creds_sync (dgc, bus_name, FALSE); - } - else - { - DEBUG ("GetConnectionCredentials failed: %s", start_error->message); - g_clear_error (&start_error); - } - - g_object_unref (dbus); - g_clear_error (&error); - } - else - { - DEBUG ("GetConnectionCredentials failed: %s", error->message); - g_clear_error (&error); - ok = FALSE; - } - - g_object_unref (proxy); - return ok; -} - -static gboolean -caller_authorised (const McpDBusAcl *self, - const TpDBusDaemon *dbus, - const DBusGMethodInvocation *call, - DBusAclType type, - const gchar *name, - const GHashTable *params) -{ - DBusGConnection *dgc = tp_proxy_get_dbus_connection ((TpDBusDaemon *)dbus); - gboolean ok = TRUE; - - if (is_filtered (type, name, params)) - { - gchar *caller = dbus_g_method_get_sender ((DBusGMethodInvocation *) call); - - ok = check_peer_creds_sync (dgc, caller, FALSE); - - g_free (caller); - } - - DEBUG ("sync Aegis ACL check [%s]", ok ? "Allowed" : "Forbidden"); - - return ok; -} - -static void -async_authorised_cb (DBusGProxy *proxy, - DBusGProxyCall *call, - gpointer data) -{ - GError *error = NULL; - DBusAclAuthData *ad = data; - GArray *au = NULL; - const McpDBusAcl *self = ad->acl; - gboolean permitted = FALSE; - - /* if this returns FALSE, there are no credentials, which means something - * untrustworthy is going on, which in turn means we must deny: can't - * authorise without first authenticating */ - permitted = dbus_g_proxy_end_call (proxy, call, &error, - DBUS_TYPE_G_UINT_ARRAY, &au, - G_TYPE_INVALID); - - if (permitted) - { - permitted = caller_creds_are_enough (ad->name, au); - g_array_unref (au); - } - else - { - DEBUG ("GetConnectionCredentials failed: %s", error->message); - g_clear_error (&error); - } - - DEBUG ("finished async Aegis ACL check [%s]", - permitted ? "Allowed" : "Forbidden"); - - mcp_dbus_acl_authorised_async_step (ad, permitted); - - g_object_unref (proxy); -} - -static void -caller_async_authorised (const McpDBusAcl *self, - DBusAclAuthData *data) -{ - DEBUG ("starting async caller-permission ACL check"); - - if (is_filtered (data->type, data->name, data->params)) - { - DBusGConnection *dgc; - DBusGProxy *proxy; - gchar *caller = dbus_g_method_get_sender (data->context); - - dgc = tp_proxy_get_dbus_connection (data->dbus); - proxy = dbus_g_proxy_new_for_name (dgc, - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - AEGIS_INTERFACE); - - dbus_g_proxy_begin_call (proxy, "GetConnectionCredentials", - async_authorised_cb, - data, - NULL, - G_TYPE_STRING, caller, - G_TYPE_INVALID); - - g_free (caller); - } - else - { - mcp_dbus_acl_authorised_async_step (data, TRUE); - } -} - - -static void -aegis_acl_iface_init (McpDBusAclIface *iface, - gpointer unused G_GNUC_UNUSED) -{ - mcp_dbus_acl_iface_set_name (iface, PLUGIN_NAME); - mcp_dbus_acl_iface_set_desc (iface, PLUGIN_DESCRIPTION); - - mcp_dbus_acl_iface_implement_authorised (iface, caller_authorised); - mcp_dbus_acl_iface_implement_authorised_async (iface, caller_async_authorised); -} - -static gchar *restricted_cms[] = { "ring", "mmscm", NULL }; - -static inline gboolean -cm_is_restricted (const gchar *cm_name) -{ - guint i; - - for (i = 0; restricted_cms[i] != NULL; i++) - { - if (!tp_strdiff (restricted_cms[i], cm_name)) - return TRUE; - } - - return FALSE; -} - -static void -handler_is_suitable_async (McpDispatchOperationPolicy *self, - TpClient *recipient, - const gchar *unique_name, - McpDispatchOperation *dispatch_op, - GAsyncReadyCallback callback, - gpointer user_data) -{ - const gchar *manager = mcp_dispatch_operation_get_cm_name (dispatch_op); - GSimpleAsyncResult *simple = g_simple_async_result_new ((GObject *) self, - callback, user_data, handler_is_suitable_async); - gboolean ok = TRUE; - - if (cm_is_restricted (manager)) - { - TpDBusDaemon *dbus = tp_dbus_daemon_dup (NULL); - - /* if MC started successfully, we ought to have one */ - g_assert (dbus != NULL); - - if (!tp_str_empty (unique_name)) - { - ok = check_peer_creds_sync (tp_proxy_get_dbus_connection (dbus), - unique_name, TRUE); - } - else - { - g_assert (recipient != NULL); - - ok = check_peer_creds_sync (tp_proxy_get_dbus_connection (dbus), - tp_proxy_get_bus_name (recipient), TRUE); - } - - if (!ok) - { - g_simple_async_result_set_error (simple, TP_ERROR, - TP_ERROR_PERMISSION_DENIED, "insufficient Aegis credentials"); - } - - g_object_unref (dbus); - } - - DEBUG ("sync Aegis CDO policy check [%s]", ok ? "Allowed" : "Forbidden"); - - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); -} - -static void -aegis_cdo_policy_iface_init (McpDispatchOperationPolicyIface *iface, - gpointer unused G_GNUC_UNUSED) -{ - iface->handler_is_suitable_async = handler_is_suitable_async; - /* the default finish function accepts our GSimpleAsyncResult */ -} - -GObject * -aegis_acl_new (void) -{ - return g_object_new (aegis_acl_get_type (), NULL); -} diff --git a/src/mcd-connection.c b/src/mcd-connection.c index 1e5955a..f0184c9 100644 --- a/src/mcd-connection.c +++ b/src/mcd-connection.c @@ -50,6 +50,7 @@ #include #include +#include #include #include diff --git a/src/mcd-dispatcher.c b/src/mcd-dispatcher.c index caa7007..f3ca1ef 100644 --- a/src/mcd-dispatcher.c +++ b/src/mcd-dispatcher.c @@ -1317,92 +1317,6 @@ finally: } static void -dispatcher_channel_request_acl_cleanup (gpointer data) -{ - McdChannelRequestACL *crd = data; - - DEBUG ("cleanup acl (%p)", data); - - g_free (crd->account_path); - g_free (crd->preferred_handler); - g_hash_table_unref (crd->properties); - g_object_unref (crd->dispatcher); - tp_clear_pointer (&crd->request_metadata, g_hash_table_unref); - - g_slice_free (McdChannelRequestACL, crd); -} - -static void -dispatcher_channel_request_acl_success (DBusGMethodInvocation *context, - gpointer data) -{ - McdChannelRequestACL *crd = data; - - DEBUG ("complete acl (%p)", crd); - - dispatcher_request_channel (MCD_DISPATCHER (crd->dispatcher), - crd->account_path, - crd->properties, - crd->user_action_time, - crd->preferred_handler, - crd->request_metadata, - context, - crd->ensure); -} - -static void -free_gvalue (gpointer gvalue) -{ - GValue *gv = gvalue; - - g_value_unset (gv); - g_slice_free (GValue, gv); -} - -static void -dispatcher_channel_request_acl_start (McdDispatcher *dispatcher, - const gchar *method, - const gchar *account_path, - GHashTable *requested_properties, - gint64 user_action_time, - const gchar *preferred_handler, - GHashTable *request_metadata, - DBusGMethodInvocation *context, - gboolean ensure) -{ - McdChannelRequestACL *crd = g_slice_new0 (McdChannelRequestACL); - GValue *account = g_slice_new0 (GValue); - GHashTable *params = - g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_gvalue); - - g_value_init (account, G_TYPE_STRING); - g_value_set_string (account, account_path); - g_hash_table_insert (params, "account-path", account); - - crd->dispatcher = g_object_ref (dispatcher); - crd->account_path = g_strdup (account_path); - crd->preferred_handler = g_strdup (preferred_handler); - crd->properties = g_hash_table_ref (requested_properties); - crd->user_action_time = user_action_time; - crd->ensure = ensure; - crd->request_metadata = request_metadata != NULL ? - g_hash_table_ref (request_metadata) : NULL; - - DEBUG ("start %s.%s acl (%p)", account_path, method, crd); - - mcp_dbus_acl_authorised_async (dispatcher->priv->dbus_daemon, - context, - DBUS_ACL_TYPE_METHOD, - method, - params, - dispatcher_channel_request_acl_success, - crd, - dispatcher_channel_request_acl_cleanup); - - g_hash_table_unref (params); -} - -static void dispatcher_create_channel (TpSvcChannelDispatcher *iface, const gchar *account_path, GHashTable *requested_properties, @@ -1410,15 +1324,14 @@ dispatcher_create_channel (TpSvcChannelDispatcher *iface, const gchar *preferred_handler, DBusGMethodInvocation *context) { - dispatcher_channel_request_acl_start (MCD_DISPATCHER (iface), - CREATE_CHANNEL, - account_path, - requested_properties, - user_action_time, - preferred_handler, - NULL, - context, - FALSE); + dispatcher_request_channel (MCD_DISPATCHER (iface), + account_path, + requested_properties, + user_action_time, + preferred_handler, + NULL, + context, + FALSE); } static void @@ -1429,15 +1342,14 @@ dispatcher_ensure_channel (TpSvcChannelDispatcher *iface, const gchar *preferred_handler, DBusGMethodInvocation *context) { - dispatcher_channel_request_acl_start (MCD_DISPATCHER (iface), - ENSURE_CHANNEL, - account_path, - requested_properties, - user_action_time, - preferred_handler, - NULL, - context, - TRUE); + dispatcher_request_channel (MCD_DISPATCHER (iface), + account_path, + requested_properties, + user_action_time, + preferred_handler, + NULL, + context, + TRUE); } static void @@ -1449,15 +1361,14 @@ dispatcher_create_channel_with_hints (TpSvcChannelDispatcher *iface, GHashTable *hints, DBusGMethodInvocation *context) { - dispatcher_channel_request_acl_start (MCD_DISPATCHER (iface), - CREATE_CHANNEL, - account_path, - requested_properties, - user_action_time, - preferred_handler, - hints, - context, - FALSE); + dispatcher_request_channel (MCD_DISPATCHER (iface), + account_path, + requested_properties, + user_action_time, + preferred_handler, + hints, + context, + FALSE); } static void @@ -1469,15 +1380,14 @@ dispatcher_ensure_channel_with_hints (TpSvcChannelDispatcher *iface, GHashTable *hints, DBusGMethodInvocation *context) { - dispatcher_channel_request_acl_start (MCD_DISPATCHER (iface), - ENSURE_CHANNEL, - account_path, - requested_properties, - user_action_time, - preferred_handler, - hints, - context, - TRUE); + dispatcher_request_channel (MCD_DISPATCHER (iface), + account_path, + requested_properties, + user_action_time, + preferred_handler, + hints, + context, + TRUE); } @@ -1552,17 +1462,6 @@ typedef struct } MessageContext; static MessageContext * -message_context_steal (MessageContext *from) -{ - MessageContext *stolen = g_slice_new0 (MessageContext); - - g_memmove (stolen, from, sizeof (MessageContext)); - memset (from, 0, sizeof (MessageContext)); - - return stolen; -} - -static MessageContext * message_context_new (McdDispatcher *dispatcher, const gchar *account_path, const gchar *target_id, @@ -1717,16 +1616,6 @@ send_message_got_channel (McdRequest *request, } static void -messages_send_message_acl_success (DBusGMethodInvocation *dbus_context, - gpointer data) -{ - /* steal the contents of the message context from the ACL framework: * - * this avoids a nasty double-free (and means we don't have to dup * - * the message payload memory twice) */ - messages_send_message_start (dbus_context, message_context_steal (data)); -} - -static void messages_send_message_start (DBusGMethodInvocation *dbus_context, MessageContext *message) { @@ -1820,17 +1709,6 @@ finished: } static void -messages_send_message_acl_cleanup (gpointer data) -{ - MessageContext *message = data; - - /* At this point either the messages framework or the ACL framework * - * is expected to have handled the DBus return, so we must not try to */ - message_context_set_return_context (message, NULL); - message_context_free (message); -} - -static void messages_send_message (McSvcChannelDispatcherInterfaceMessagesDraft *iface, const gchar *account_path, const gchar *target_id, @@ -1842,23 +1720,7 @@ messages_send_message (McSvcChannelDispatcherInterfaceMessagesDraft *iface, MessageContext *message = message_context_new (self, account_path, target_id, payload, flags); - /* these are for the ACL itself */ - GValue *account = g_slice_new0 (GValue); - GHashTable *params = - g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_gvalue); - - g_value_init (account, G_TYPE_STRING); - g_value_set_string (account, account_path); - g_hash_table_insert (params, "account-path", account); - - mcp_dbus_acl_authorised_async (self->priv->dbus_daemon, - context, - DBUS_ACL_TYPE_METHOD, - SEND_MESSAGE, - params, - messages_send_message_acl_success, - message, - messages_send_message_acl_cleanup); + messages_send_message_start (context, message); } static void diff --git a/src/mcd-storage.c b/src/mcd-storage.c index 1a0ebbf..6522e7b 100644 --- a/src/mcd-storage.c +++ b/src/mcd-storage.c @@ -32,6 +32,7 @@ #include #include +#include #include #include diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am index f1c454e..45605fd 100644 --- a/tests/twisted/Makefile.am +++ b/tests/twisted/Makefile.am @@ -164,7 +164,6 @@ AM_CFLAGS = $(ERROR_CFLAGS) plugins_list = \ mcp-plugin.la \ mcp-account-diversion.la \ - mcp-dbus-caller-permission.la \ libgiofakenetworkmonitor.la \ $(NULL) @@ -202,9 +201,6 @@ libgiofakenetworkmonitor_la_LDFLAGS = $(mcp_plugin_la_LDFLAGS) mcp_account_diversion_la_SOURCES = mcp-account-diversion.c mcp_account_diversion_la_LDFLAGS = $(mcp_plugin_la_LDFLAGS) -mcp_dbus_caller_permission_la_SOURCES = mcp-dbus-caller-permission.c -mcp_dbus_caller_permission_la_LDFLAGS = $(mcp_plugin_la_LDFLAGS) - # A debug version of the normal MC executable, which exits cleanly on # disconnection from D-Bus (so gcov info gets written out) noinst_PROGRAMS = mc-debug-server diff --git a/tests/twisted/mcp-dbus-caller-permission.c b/tests/twisted/mcp-dbus-caller-permission.c deleted file mode 100644 index 96162ba..0000000 --- a/tests/twisted/mcp-dbus-caller-permission.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * A demonstration plugin that checks a DBus caller's md5sum - * - * Copyright © 2010 Nokia Corporation - * Copyright © 2010 Collabora Ltd. - * - * This library 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include - -#define CONFFILE "mcp-dbus-caller-permissions.conf" - -#define DEBUG g_debug - -#define PLUGIN_NAME "dbus-caller-permission-checker" -#define PLUGIN_DESCRIPTION \ - "Test plugin that checks the md5 checksum of a DBus caller. " \ - "gkeyfile g_get_user_cache_dir()/" CONFFILE " holds the [paths " \ - "to] the binaries, and the permission tokens associated with each." - -/* Example conf file: -[/usr/local/bin/mc-tool] -org.freedesktop.Telepathy.AccountManager=1 -*=1 -*/ - -static void dbus_acl_iface_init (McpDBusAclIface *, - gpointer); - -typedef struct { - GObject parent; - GKeyFile *permits; - gboolean loaded; -} DBusCallerPermission; - -typedef struct { - GObjectClass parent_class; -} DBusCallerPermissionClass; - -GType dbus_caller_permission_get_type (void) G_GNUC_CONST; - -#define DBUS_CALLER_PERMISSION(o) \ - (G_TYPE_CHECK_INSTANCE_CAST ((o), dbus_caller_permission_get_type (), \ - DBusCallerPermission)) - -G_DEFINE_TYPE_WITH_CODE (DBusCallerPermission, dbus_caller_permission, - G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (MCP_TYPE_DBUS_ACL, dbus_acl_iface_init)); - -static void -dbus_caller_permission_init (DBusCallerPermission *self) -{ - const gchar *dir; - gchar *file = NULL; - - self->permits = g_key_file_new (); - - dir = g_get_user_cache_dir (); - file = g_build_path (G_DIR_SEPARATOR_S, dir, CONFFILE, NULL); - - if (!g_file_test (file, G_FILE_TEST_EXISTS)) - { - g_mkdir_with_parents (dir, 0700); - g_file_set_contents (file, "# MC DBus permissions\n", -1, NULL); - } - - DEBUG ("conf file %s", file); - g_key_file_load_from_file (self->permits, file, G_KEY_FILE_NONE, NULL); - - g_free (file); -} - -static void -dbus_caller_permission_class_init (DBusCallerPermissionClass *cls) -{ -} - -static gboolean is_filtered (const McpDBusAcl *self, - DBusAclType type, - const gchar *name) -{ - DBusCallerPermission *plugin = DBUS_CALLER_PERMISSION (self); - GKeyFile *permits = plugin->permits; - - switch (type) - { - case DBUS_ACL_TYPE_METHOD: - return g_key_file_get_boolean (permits, "methods", name, NULL); - case DBUS_ACL_TYPE_GET_PROPERTY: - return g_key_file_get_boolean (permits, "get-property", name, NULL); - case DBUS_ACL_TYPE_SET_PROPERTY: - return g_key_file_get_boolean (permits, "set-property", name, NULL); - default: - return FALSE; - } -} - -static gboolean -pid_is_permitted (const McpDBusAcl *self, const gchar *name, pid_t pid) -{ - gboolean ok = FALSE; - - if (pid != 0) - { - gchar *path = g_strdup_printf ("/proc/%d/exe", pid); - gchar *executable = g_file_read_link (path, NULL); - - if (executable != NULL) - { - DBusCallerPermission *plugin = DBUS_CALLER_PERMISSION (self); - GKeyFile *permits = plugin->permits; - - DEBUG ("executable to check for permission is %s", executable); - ok = g_key_file_get_boolean (permits, executable, name, NULL); - DEBUG ("%s:%s = %s", executable, name, ok ? "TRUE" : "FALSE"); - - g_free (executable); - } - - g_free (path); - } - - return ok; -} - -static gboolean -caller_authorised (const McpDBusAcl *self, - const TpDBusDaemon *dbus, - const DBusGMethodInvocation *call, - DBusAclType type, - const gchar *name, - const GHashTable *params) -{ - DBusGConnection *dgc = tp_proxy_get_dbus_connection ((TpDBusDaemon *)dbus); - gboolean ok = TRUE; - - if (is_filtered (self, type, name)) - { - pid_t pid = 0; - GError *error = NULL; - gchar *caller = dbus_g_method_get_sender ((DBusGMethodInvocation *) call); - DBusGProxy *proxy = dbus_g_proxy_new_for_name (dgc, - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS); - - dbus_g_proxy_call (proxy, "GetConnectionUnixProcessID", &error, - G_TYPE_STRING, caller, - G_TYPE_INVALID, - G_TYPE_UINT, &pid, - G_TYPE_INVALID); - - ok = pid_is_permitted (self, name, pid); - - g_free (caller); - g_object_unref (proxy); - } - - DEBUG ("sync caller-permission ACL check [%s]", ok ? "Allowed" : "Forbidden"); - - return ok; -} - -static void -async_authorised_cb (DBusGProxy *proxy, - DBusGProxyCall *call, - gpointer data) -{ - GError *error = NULL; - DBusAclAuthData *ad = data; - pid_t pid = 0; - const McpDBusAcl *self = ad->acl; - gboolean permitted = FALSE; - - /* if this returns FALSE, there's no PID, which means something bizarre * - * and untrustowrthy is going on, which in turn means we must deny: can't * - * authorise without first authenticating */ - permitted = dbus_g_proxy_end_call (proxy, call, &error, - G_TYPE_UINT, &pid, - G_TYPE_INVALID); - - if (permitted) - permitted = pid_is_permitted (self, ad->name, pid); - else - g_error_free (error); - - DEBUG ("finished async caller-permission ACL check [%u -> %s]", - pid, permitted ? "Allowed" : "Forbidden"); - - mcp_dbus_acl_authorised_async_step (ad, permitted); -} - -static void -caller_async_authorised (const McpDBusAcl *self, - DBusAclAuthData *data) -{ - DBusGConnection *dgc = tp_proxy_get_dbus_connection (data->dbus); - DBusGProxy *proxy = dbus_g_proxy_new_for_name (dgc, - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS); - - DEBUG ("starting async caller-permission ACL check"); - - if (is_filtered (self, data->type, data->name)) - { - gchar *caller = dbus_g_method_get_sender (data->context); - - dbus_g_proxy_begin_call (proxy, "GetConnectionUnixProcessID", - async_authorised_cb, - data, - NULL, - G_TYPE_STRING, caller, - G_TYPE_INVALID); - - g_free (caller); - } - else /* not filtered, so the call is allowed: */ - { - mcp_dbus_acl_authorised_async_step (data, TRUE); - } -} - - -static void -dbus_acl_iface_init (McpDBusAclIface *iface, - gpointer unused G_GNUC_UNUSED) -{ - mcp_dbus_acl_iface_set_name (iface, PLUGIN_NAME); - mcp_dbus_acl_iface_set_desc (iface, PLUGIN_DESCRIPTION); - - mcp_dbus_acl_iface_implement_authorised (iface, caller_authorised); - mcp_dbus_acl_iface_implement_authorised_async (iface, caller_async_authorised); -} - -GObject * -mcp_plugin_ref_nth_object (guint n) -{ - DEBUG ("Initializing mcp-dbus-caller-id plugin (n=%u)", n); - - switch (n) - { - case 0: - return g_object_new (dbus_caller_permission_get_type (), NULL); - - default: - return NULL; - } -} - diff --git a/tests/twisted/mcp-plugin.c b/tests/twisted/mcp-plugin.c index 34079c8..de74134 100644 --- a/tests/twisted/mcp-plugin.c +++ b/tests/twisted/mcp-plugin.c @@ -49,7 +49,6 @@ GType test_no_op_plugin_get_type (void) G_GNUC_CONST; G_DEFINE_TYPE_WITH_CODE (TestNoOpPlugin, test_no_op_plugin, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (MCP_TYPE_DBUS_ACL, NULL); G_IMPLEMENT_INTERFACE (MCP_TYPE_REQUEST_POLICY, NULL); G_IMPLEMENT_INTERFACE (MCP_TYPE_DISPATCH_OPERATION_POLICY, NULL)) -- 1.8.4.rc3