summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/dbus.h8
-rw-r--r--src/dbus.c135
2 files changed, 143 insertions, 0 deletions
diff --git a/include/dbus.h b/include/dbus.h
index bf5f8c14..c00488e2 100644
--- a/include/dbus.h
+++ b/include/dbus.h
@@ -171,6 +171,14 @@ static inline void connman_dbus_dict_append_fixed_array(DBusMessageIter *dict,
dbus_bool_t connman_dbus_validate_ident(const char *ident);
char *connman_dbus_encode_string(const char *value);
+typedef void (* connman_dbus_get_context_cb_t) (const unsigned char *context,
+ void *user_data, int err);
+
+int connman_dbus_get_selinux_context(DBusConnection *connection,
+ const char *service,
+ connman_dbus_get_context_cb_t func,
+ void *user_data);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/dbus.c b/src/dbus.c
index 9d19f946..70af6173 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -24,6 +24,7 @@
#endif
#include <string.h>
+#include <errno.h>
#include <gdbus.h>
#include "connman.h"
@@ -405,6 +406,140 @@ dbus_bool_t __connman_dbus_append_objpath_dict_array(DBusMessage *msg,
return TRUE;
}
+struct selinux_data {
+ connman_dbus_get_context_cb_t func;
+ void *user_data;
+};
+
+static unsigned char *parse_context(DBusMessage *msg)
+{
+ DBusMessageIter iter, array;
+ unsigned char *ctx, *p;
+ int size = 0;
+
+ dbus_message_iter_init(msg, &iter);
+ dbus_message_iter_recurse(&iter, &array);
+ while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_BYTE) {
+ size++;
+
+ dbus_message_iter_next(&array);
+ }
+
+ if (size == 0)
+ return NULL;
+
+ ctx = g_try_malloc0(size + 1);
+ if (ctx == NULL)
+ return NULL;
+
+ p = ctx;
+
+ dbus_message_iter_init(msg, &iter);
+ dbus_message_iter_recurse(&iter, &array);
+ while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_BYTE) {
+ dbus_message_iter_get_basic(&array, p);
+
+ p++;
+ dbus_message_iter_next(&array);
+ }
+
+ return ctx;
+}
+
+static void selinux_get_context_reply(DBusPendingCall *call, void *user_data)
+{
+ struct selinux_data *data = user_data;
+ DBusMessage *reply;
+ unsigned char *context = NULL;
+ int err = 0;
+
+ reply = dbus_pending_call_steal_reply(call);
+
+ if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
+ DBG("Failed to retrieve SELinux context");
+ err = -EIO;
+ goto done;
+ }
+
+ if (dbus_message_has_signature(reply, "ay") == FALSE) {
+ DBG("Message signature is wrong");
+ err = -EINVAL;
+ goto done;
+ }
+
+ context = parse_context(reply);
+
+done:
+ (*data->func)(context, data->user_data, err);
+
+ g_free(context);
+
+ dbus_message_unref(reply);
+
+ dbus_pending_call_unref(call);
+}
+
+int connman_dbus_get_selinux_context(DBusConnection *connection,
+ const char *service,
+ connman_dbus_get_context_cb_t func,
+ void *user_data)
+{
+ struct selinux_data *data;
+ DBusPendingCall *call;
+ DBusMessage *msg = NULL;
+ int err;
+
+ if (func == NULL)
+ return -EINVAL;
+
+ data = g_try_new0(struct selinux_data, 1);
+ if (data == NULL) {
+ DBG("Can't allocate data structure");
+ return -ENOMEM;
+ }
+
+ msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "GetConnectionSELinuxSecurityContext");
+ if (msg == NULL) {
+ DBG("Can't allocate new message");
+ err = -ENOMEM;
+ goto err;
+ }
+
+ dbus_message_append_args(msg, DBUS_TYPE_STRING, &service,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_connection_send_with_reply(connection, msg,
+ &call, -1) == FALSE) {
+ DBG("Failed to execute method call");
+ err = -EINVAL;
+ goto err;
+ }
+
+ if (call == NULL) {
+ DBG("D-Bus connection not available");
+ err = -EINVAL;
+ goto err;
+ }
+
+ data->func = func;
+ data->user_data = user_data;
+
+ dbus_pending_call_set_notify(call, selinux_get_context_reply,
+ data, g_free);
+
+ dbus_message_unref(msg);
+
+ return 0;
+
+err:
+ dbus_message_unref(msg);
+ g_free(data);
+
+ return err;
+}
+
DBusConnection *connman_dbus_get_connection(void)
{
if (connection == NULL)