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/GID 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
SElinux, UID or GID identification.

The order of matching preference is SELinux, UID and finally GID.
It is possible to run a mixed configuration but not really recommended.
There might be dragons.
---
 plugins/session_policy_local.c | 115 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 106 insertions(+), 9 deletions(-)

diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c
index bb81277..0279863 100644
--- a/plugins/session_policy_local.c
+++ b/plugins/session_policy_local.c
@@ -27,6 +27,9 @@
 #include <string.h>
 #include <sys/inotify.h>
 #include <sys/stat.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
 
 #include <glib.h>
 
@@ -52,12 +55,20 @@ static GSList *policy_list;
 
 struct create_data {
        struct connman_session *session;
+       char *user;
+       char *group;
+       uid_t uid;
+       gid_t gid;
 };
 
 struct policy_data {
        int refcount;
        char *filename;
        char *lsm_ctx; /* The Linux Security Module Context */
+       char *user;
+       char *group;
+       uid_t uid;
+       gid_t gid;
 
        struct connman_session *session;
        struct connman_session_config *config;
@@ -72,6 +83,8 @@ static void free_policy(gpointer user_data)
 
        g_free(policy->filename);
        g_free(policy->lsm_ctx);
+       g_free(policy->user);
+       g_free(policy->group);
        g_free(policy->config);
        g_free(policy);
 }
@@ -152,8 +165,10 @@ 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)
-                       continue;
+               if (g_strcmp0(policy->lsm_ctx, filename) != 0 &&
+                               g_strcmp0(policy->user, filename) != 0 &&
+                               g_strcmp0(policy->group, filename) != 0)
+               continue;
 
                return policy;
        }
@@ -161,7 +176,9 @@ 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,
+                                                       const char *group)
 {
        GSList *list;
        struct policy_data *policy;
@@ -169,7 +186,9 @@ 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 &&
+                               g_strcmp0(policy->filename, group) != 0)
                        continue;
 
                return policy;
@@ -203,13 +222,17 @@ static void selinux_context_reply(int error,
                goto done;
        }
 
-       policy = find_policy_by_session(ident);
+       policy = find_policy_by_session(ident, data->user, data->group);
        if (policy == NULL)
                policy = create_policy();
        else
                policy_ref(policy);
 
        policy->lsm_ctx = g_strdup(ident);
+       policy->user = data->user;
+       policy->group = data->group;
+       policy->uid = data->uid;
+       policy->gid = data->gid;
        policy->session = data->session;
 
        g_hash_table_replace(session_hash, data->session, policy);
@@ -224,6 +247,81 @@ 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 group *grp;
+       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;
+       }
+
+       grp = getgrgid(pwd->pw_gid);
+       if (grp == NULL) {
+               if (errno != 0)
+                       error = -errno;
+               else
+                       error = -EINVAL;
+               goto done;
+       }
+
+       data->user = g_strdup(pwd->pw_name);
+       data->group = g_strdup(grp->gr_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, data->group);
+       if (policy == NULL)
+               policy = create_policy();
+       else
+               policy_ref(policy);
+
+       policy->user = data->user;
+       policy->group = data->group;
+       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 +340,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