summaryrefslogtreecommitdiff
path: root/gdbus
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2010-08-29 00:18:47 +0200
committerMarcel Holtmann <marcel@holtmann.org>2010-09-09 18:27:17 +0200
commit5cbc959b6f4261a5504d64f27feec15329af3424 (patch)
tree02326c7a1dc2011051bd330bd91c9d7440b680c8 /gdbus
parent45b7028d9e42a5f236d6ae22c68626f3e5e7ca6f (diff)
downloadconnman-5cbc959b6f4261a5504d64f27feec15329af3424.tar.gz
connman-5cbc959b6f4261a5504d64f27feec15329af3424.tar.bz2
connman-5cbc959b6f4261a5504d64f27feec15329af3424.zip
Add support for GDBus security handlers
Diffstat (limited to 'gdbus')
-rw-r--r--gdbus/gdbus.h19
-rw-r--r--gdbus/object.c159
2 files changed, 156 insertions, 22 deletions
diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
index c3e72528..42d4f739 100644
--- a/gdbus/gdbus.h
+++ b/gdbus/gdbus.h
@@ -55,6 +55,11 @@ typedef void (* GDBusDestroyFunction) (void *user_data);
typedef DBusMessage * (* GDBusMethodFunction) (DBusConnection *connection,
DBusMessage *message, void *user_data);
+typedef guint32 GDBusPendingReply;
+
+typedef void (* GDBusSecurityFunction) (DBusConnection *connection,
+ DBusMessage *message, GDBusPendingReply pending);
+
typedef enum {
G_DBUS_METHOD_FLAG_DEPRECATED = (1 << 0),
G_DBUS_METHOD_FLAG_NOREPLY = (1 << 1),
@@ -75,6 +80,7 @@ typedef struct {
const char *reply;
GDBusMethodFunction function;
GDBusMethodFlags flags;
+ unsigned int privilege;
} GDBusMethodTable;
typedef struct {
@@ -89,6 +95,11 @@ typedef struct {
GDBusPropertyFlags flags;
} GDBusPropertyTable;
+typedef struct {
+ unsigned int privilege;
+ GDBusSecurityFunction function;
+} GDBusSecurityTable;
+
gboolean g_dbus_register_interface(DBusConnection *connection,
const char *path, const char *name,
const GDBusMethodTable *methods,
@@ -99,6 +110,14 @@ gboolean g_dbus_register_interface(DBusConnection *connection,
gboolean g_dbus_unregister_interface(DBusConnection *connection,
const char *path, const char *name);
+gboolean g_dbus_register_security(const GDBusSecurityTable *security);
+gboolean g_dbus_unregister_security(const GDBusSecurityTable *security);
+
+void g_dbus_pending_success(DBusConnection *connection,
+ GDBusPendingReply pending);
+void g_dbus_pending_error(DBusConnection *connection,
+ GDBusPendingReply pending, DBusMessage *error);
+
DBusMessage *g_dbus_create_error(DBusMessage *message, const char *name,
const char *format, ...)
__attribute__((format(printf, 3, 4)));
diff --git a/gdbus/object.c b/gdbus/object.c
index ff696414..a367f938 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -52,6 +52,13 @@ struct interface_data {
GDBusDestroyFunction destroy;
};
+struct security_data {
+ GDBusPendingReply pending;
+ DBusMessage *message;
+ const GDBusMethodTable *method;
+ void *iface_user_data;
+};
+
static void print_arguments(GString *gstr, const char *sig,
const char *direction)
{
@@ -208,6 +215,114 @@ static DBusMessage *introspect(DBusConnection *connection,
return reply;
}
+static DBusHandlerResult process_message(DBusConnection *connection,
+ DBusMessage *message, const GDBusMethodTable *method,
+ void *iface_user_data)
+{
+ DBusMessage *reply;
+
+ reply = method->function(connection, message, iface_user_data);
+
+ if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY) {
+ if (reply != NULL)
+ dbus_message_unref(reply);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ if (method->flags & G_DBUS_METHOD_FLAG_ASYNC) {
+ if (reply == NULL)
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ if (reply == NULL)
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ dbus_connection_send(connection, reply, NULL);
+ dbus_message_unref(reply);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static GDBusPendingReply next_pending = 1;
+static GSList *pending_security = NULL;
+
+static const GDBusSecurityTable *security_table = NULL;
+
+void g_dbus_pending_success(DBusConnection *connection,
+ GDBusPendingReply pending)
+{
+ GSList *list;
+
+ for (list = pending_security; list; list = list->next) {
+ struct security_data *secdata = list->data;
+ DBusHandlerResult result;
+
+ if (secdata->pending != pending)
+ continue;
+
+ pending_security = g_slist_remove(pending_security, secdata);
+
+ result = process_message(connection, secdata->message,
+ secdata->method, secdata->iface_user_data);
+
+ dbus_message_unref(secdata->message);
+ g_free(secdata);
+ return;
+ }
+}
+
+void g_dbus_pending_error(DBusConnection *connection,
+ GDBusPendingReply pending, DBusMessage *error)
+{
+ GSList *list;
+
+ for (list = pending_security; list; list = list->next) {
+ struct security_data *secdata = list->data;
+
+ if (secdata->pending != pending)
+ continue;
+
+ pending_security = g_slist_remove(pending_security, secdata);
+
+ if (error != NULL) {
+ dbus_connection_send(connection, error, NULL);
+ dbus_message_unref(error);
+ }
+
+ dbus_message_unref(secdata->message);
+ g_free(secdata);
+ return;
+ }
+}
+
+static gboolean check_privilege(DBusConnection *conn, DBusMessage *msg,
+ const GDBusMethodTable *method, void *iface_user_data)
+{
+ const GDBusSecurityTable *security;
+
+ for (security = security_table; security && security->function &&
+ security->privilege; security++) {
+ struct security_data *secdata;
+
+ if (security->privilege != method->privilege)
+ continue;
+
+ secdata = g_new(struct security_data, 1);
+ secdata->pending = next_pending++;
+ secdata->message = dbus_message_ref(msg);
+ secdata->method = method;
+ secdata->iface_user_data = iface_user_data;
+
+ pending_security = g_slist_prepend(pending_security, secdata);
+
+ security->function(conn, secdata->message, secdata->pending);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static void generic_unregister(DBusConnection *connection, void *user_data)
{
struct generic_data *data = user_data;
@@ -249,8 +364,6 @@ static DBusHandlerResult generic_message(DBusConnection *connection,
for (method = iface->methods; method &&
method->name && method->function; method++) {
- DBusMessage *reply;
-
if (dbus_message_is_method_call(message, iface->name,
method->name) == FALSE)
continue;
@@ -259,26 +372,12 @@ static DBusHandlerResult generic_message(DBusConnection *connection,
method->signature) == FALSE)
continue;
- reply = method->function(connection, message, iface->user_data);
-
- if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY) {
- if (reply != NULL)
- dbus_message_unref(reply);
+ if (check_privilege(connection, message, method,
+ iface->user_data) == TRUE)
return DBUS_HANDLER_RESULT_HANDLED;
- }
-
- if (method->flags & G_DBUS_METHOD_FLAG_ASYNC) {
- if (reply == NULL)
- return DBUS_HANDLER_RESULT_HANDLED;
- }
- if (reply == NULL)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- dbus_connection_send(connection, reply, NULL);
- dbus_message_unref(reply);
-
- return DBUS_HANDLER_RESULT_HANDLED;
+ return process_message(connection, message, method,
+ iface->user_data);
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@@ -362,11 +461,10 @@ static struct generic_data *object_path_ref(DBusConnection *connection,
}
data = g_new0(struct generic_data, 1);
+ data->refcount = 1;
data->introspect = g_strdup(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE "<node></node>");
- data->refcount = 1;
-
if (!dbus_connection_register_object_path(connection, path,
&generic_table, data)) {
g_free(data->introspect);
@@ -556,6 +654,23 @@ gboolean g_dbus_unregister_interface(DBusConnection *connection,
return TRUE;
}
+gboolean g_dbus_register_security(const GDBusSecurityTable *security)
+{
+ if (security_table != NULL)
+ return FALSE;
+
+ security_table = security;
+
+ return TRUE;
+}
+
+gboolean g_dbus_unregister_security(const GDBusSecurityTable *security)
+{
+ security_table = NULL;
+
+ return TRUE;
+}
+
DBusMessage *g_dbus_create_error_valist(DBusMessage *message, const char *name,
const char *format, va_list args)
{