From: Daniel Wagner <daniel.wag...@bmw-carit.de>

When the session core ask to create a configuration, then we
first ask the D-Bus server which UID the session belongs to.
If possible we also ask for the SELinux context. Then we try
to figure out which file containts the configuration for
UID/SElinux identification.

The SELinux identification has higher priority than UID. It is
possible to run a mixed configuration but not really recommended.
There might be dragons.
---
 plugins/session_policy_local.c | 93 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 85 insertions(+), 8 deletions(-)

diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c
index c28b856..aeb4bbf 100644
--- a/plugins/session_policy_local.c
+++ b/plugins/session_policy_local.c
@@ -27,6 +27,8 @@
 #include <string.h>
 #include <sys/inotify.h>
 #include <sys/stat.h>
+#include <sys/types.h>
+#include <pwd.h>
 
 #include <glib.h>
 
@@ -52,12 +54,18 @@ static GSList *policy_list;
 
 struct create_data {
        struct connman_session *session;
+       char *user;
+       uid_t uid;
+       gid_t gid;
 };
 
 struct policy_data {
        int refcount;
        char *filename;
        char *lsm_ctx; /* The Linux Security Module Context */
+       char *user;
+       uid_t uid;
+       gid_t gid;
 
        struct connman_session *session;
        struct connman_session_config *config;
@@ -72,6 +80,7 @@ static void free_policy(gpointer user_data)
 
        g_free(policy->filename);
        g_free(policy->lsm_ctx);
+       g_free(policy->user);
        g_free(policy->config);
        g_free(policy);
 }
@@ -152,7 +161,8 @@ static struct policy_data *find_policy_by_file(const char 
*filename)
        for (list = policy_list; list != NULL; list = list->next) {
                policy = list->data;
 
-               if (g_strcmp0(policy->lsm_ctx, filename) != 0)
+               if (g_strcmp0(policy->lsm_ctx, filename) != 0 &&
+                               g_strcmp0(policy->user, filename) != 0)
                        continue;
 
                return policy;
@@ -161,7 +171,8 @@ static struct policy_data *find_policy_by_file(const char 
*filename)
        return NULL;
 }
 
-static struct policy_data *find_policy_by_session(const char *lsm_ctx)
+static struct policy_data *find_policy_by_session(const char *lsm_ctx,
+                                                       const char *user)
 {
        GSList *list;
        struct policy_data *policy;
@@ -169,7 +180,8 @@ static struct policy_data *find_policy_by_session(const 
char *lsm_ctx)
        for (list = policy_list; list != NULL; list = list->next) {
                policy = list->data;
 
-               if (g_strcmp0(policy->filename, lsm_ctx) != 0)
+               if (g_strcmp0(policy->filename, lsm_ctx) != 0 &&
+                               g_strcmp0(policy->filename, user) != 0)
                        continue;
 
                return policy;
@@ -203,13 +215,16 @@ static void selinux_context_reply(int error,
                goto done;
        }
 
-       policy = find_policy_by_session(ident);
+       policy = find_policy_by_session(ident, data->user);
        if (policy == NULL)
                policy = create_policy();
        else
                policy_ref(policy);
 
        policy->lsm_ctx = g_strdup(ident);
+       policy->user = data->user;
+       policy->uid = data->uid;
+       policy->gid = data->gid;
        policy->session = data->session;
 
        g_hash_table_replace(session_hash, data->session, policy);
@@ -224,6 +239,69 @@ done:
        g_free(ctx);
 }
 
+static void get_uid_reply(int error, unsigned int uid, void *user_data)
+{
+       struct cb_data *cbd = user_data;
+       connman_session_config_cb_t cb = cbd->cb;
+       struct create_data *data = cbd->data;
+       struct policy_data *policy;
+       const char *owner;
+       struct passwd *pwd;
+       struct connman_session_config *config = NULL;
+
+       DBG("session %p uid %d", data->session, uid);
+
+       if (error < 0)
+               goto done;
+
+       errno = 0;
+       pwd = getpwuid((uid_t)uid);
+       if (pwd == NULL) {
+               if (errno != 0)
+                       error = -errno;
+               else
+                       error = -EINVAL;
+               goto done;
+       }
+
+       data->user = g_strdup(pwd->pw_name);
+       data->uid = pwd->pw_uid;
+       data->gid = pwd->pw_gid;
+
+       owner = connman_session_get_owner(data->session);
+
+       error = connman_dbus_get_selinux_context(connection, owner,
+                                               selinux_context_reply, cbd);
+       if (error == 0) {
+               /*
+                * We are able to ask for a SELinux context. Let's defer the
+                * creation of the session config until we get the answer
+                * from D-Bus.
+                */
+               return;
+       }
+
+       policy = find_policy_by_session(NULL, data->user);
+       if (policy == NULL)
+               policy = create_policy();
+       else
+               policy_ref(policy);
+
+       policy->user = data->user;
+       policy->uid = data->uid;
+       policy->gid = data->gid;
+       policy->session = data->session;
+
+       g_hash_table_replace(session_hash, data->session, policy);
+
+       config = policy->config;
+done:
+       (*cb)(error, data->session, config, cbd->user_data);
+
+       g_free(data);
+       g_free(cbd);
+}
+
 static int policy_local_create(struct connman_session *session,
                                connman_session_config_cb_t cb,
                                void *user_data)
@@ -242,11 +320,10 @@ static int policy_local_create(struct connman_session 
*session,
 
        owner = connman_session_get_owner(session);
 
-       err = connman_dbus_get_selinux_context(connection, owner,
-                                       selinux_context_reply,
-                                       cbd);
+       err = connman_dbus_get_connection_unix_user(connection, owner,
+                                               get_uid_reply, cbd);
        if (err < 0) {
-               connman_error("Could not get SELinux context");
+               connman_error("Could not get UID");
                g_free(data);
                g_free(cbd);
                return err;
-- 
1.8.1.3.566.gaa39828

_______________________________________________
connman mailing list
connman@connman.net
http://lists.connman.net/listinfo/connman

Reply via email to