summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2011-05-05 18:44:39 +0100
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2011-05-05 18:44:39 +0100
commitd2f40c4995911d3583794297f6a76b4570453c44 (patch)
treea702f25f8ba4476ba8e6eb74b53ebd839c513ddd /plugins
parentebef3a3d1fedf07edd75cf8cdf924df6e8958444 (diff)
Use GetConnectionCredentials() when checking credentials synchronously
This avoids a time of check / time of use vulnerability. Also, don't crash if the D-Bus call fails.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/mcp-dbus-aegis-acl.c113
1 files changed, 80 insertions, 33 deletions
diff --git a/plugins/mcp-dbus-aegis-acl.c b/plugins/mcp-dbus-aegis-acl.c
index b0dda6ce..9bfcdf58 100644
--- a/plugins/mcp-dbus-aegis-acl.c
+++ b/plugins/mcp-dbus-aegis-acl.c
@@ -32,6 +32,7 @@
#define DEBUG(_f, ...) do {} while (0)
#endif
+#include <dbus/dbus-glib.h>
#include <telepathy-glib/interfaces.h>
#include <telepathy-glib/util.h>
#include <telepathy-glib/defs.h>
@@ -59,6 +60,9 @@ struct _AegisAclClass {
#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 " \
@@ -153,6 +157,79 @@ is_filtered (DBusAclType type,
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)
+{
+ 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;
+
+ 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
+ {
+ DEBUG ("GetConnectionCredentials failed: %s", error->message);
+ g_clear_error (&error);
+ ok = FALSE;
+ }
+
+ g_object_unref (proxy);
+ return ok;
+}
+
static gboolean
pid_is_permitted (pid_t pid)
{
@@ -186,24 +263,11 @@ caller_authorised (const McpDBusAcl *self,
if (is_filtered (type, name, params))
{
- 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 (pid);
+ ok = check_peer_creds_sync (dgc, caller);
g_free (caller);
- g_object_unref (proxy);
}
DEBUG ("sync Aegis ACL check [%s]", ok ? "Allowed" : "Forbidden");
@@ -313,25 +377,8 @@ handler_is_suitable (McpDispatchOperationPolicy *self,
if (cm_is_restricted (manager))
{
- pid_t pid = 0;
- GError *error = NULL;
- const gchar *name = tp_proxy_get_bus_name (recipient);
- DBusGConnection *dgc = tp_proxy_get_dbus_connection (recipient);
-
- 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, name,
- G_TYPE_INVALID,
- G_TYPE_UINT, &pid,
- G_TYPE_INVALID);
-
- ok = pid_is_permitted (pid);
-
- g_object_unref (proxy);
+ ok = check_peer_creds_sync (tp_proxy_get_dbus_connection (recipient),
+ tp_proxy_get_bus_name (recipient));
}
DEBUG ("sync Aegis CDO policy check [%s]", ok ? "Allowed" : "Forbidden");