Package: accountsservice
Version: 0.6.5-2
Severity: important

AccountsService makes many assumptions on the underlying system, basically it
considers it's a Fedora / Red Hat system, minimum uid set at 500, admin group
set as desktop_admin_r, presence of a desktop_user_r group, etc.

Here is a serie of patches:

0001-take-minimal_uid-value-from-login.defs.patch
 - read /etc/login.defs and look for the definition of UID_MAX

0002-create-and-manage-groups-like-on-a-debian-system.patch
 - do not consider desktop_admin_r and desktop_user_r, add desktop users to a
   serie of groups typical of Debian systems (audio, cdrom...), add admin user
   to an "admin" group (this may not exist but it appears to be working for
   the default sudo configuration on Ubuntu at least).

0003-do-not-consider-system-users-returned-from-consoleki.patch
 - accountsservice would add users found in consolekit history without
   attention to their uid, making it possible for system users to be listed.



-- System Information:
Debian Release: wheezy/sid
  APT prefers unstable
  APT policy: (500, 'unstable'), (500, 'testing'), (101, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.37-2-amd64 (SMP w/2 CPU cores)
Locale: LANG=fr_BE.UTF-8, LC_CTYPE=fr_BE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages accountsservice depends on:
ii  dbus                          1.4.6-1    simple interprocess messaging syst
ii  libaccountsservice0           0.6.5-2    query and manipulate user account 
ii  libc6                         2.11.2-13  Embedded GNU C Library: Shared lib
ii  libdbus-1-3                   1.4.6-1    simple interprocess messaging syst
ii  libdbus-glib-1-2              0.92-1     simple interprocess messaging syst
ii  libglib2.0-0                  2.28.2-1   The GLib library of C routines
ii  libpolkit-gobject-1-0         0.101-1    PolicyKit Authorization API

accountsservice recommends no packages.

Versions of packages accountsservice suggests:
ii  gnome-control-center         1:2.91.91-3 utilities to configure the GNOME d

-- no debconf information
>From 676555253b0fa14c53a6e2a37b67abdc2352e5d6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpet...@0d.be>
Date: Fri, 18 Mar 2011 00:18:23 +0100
Subject: [PATCH 1/3] take minimal_uid value from login.defs

---
 src/daemon.c |   38 +++++++++++++++++++++++++++++++++++---
 1 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/src/daemon.c b/src/daemon.c
index 4e0b935..0b95c14 100644
--- a/src/daemon.c
+++ b/src/daemon.c
@@ -46,7 +46,6 @@
 
 #define PATH_PASSWD "/etc/passwd"
 #define PATH_SHADOW "/etc/shadow"
-#define MINIMAL_UID 500
 
 #define USERDIR LOCALSTATEDIR "/lib/AccountsService/users"
 
@@ -104,6 +103,7 @@ struct DaemonPrivate {
         guint autologin_id;
 
         PolkitAuthority *authority;
+        guint minimal_uid;
 };
 
 static void daemon_finalize   (GObject     *object);
@@ -216,7 +216,7 @@ daemon_class_init (DaemonClass *klass)
 static gboolean
 user_is_excluded (Daemon *daemon, const gchar *username, uid_t uid)
 {
-        if (uid < MINIMAL_UID) {
+        if (uid < daemon->priv->minimal_uid) {
                 return TRUE;
         }
         if (g_hash_table_lookup (daemon->priv->exclusions, username)) {
@@ -338,7 +338,7 @@ process_ck_history_line (Daemon      *daemon,
         }
 
         /* pass MINIMAL_UID to just check the name here */
-        if (user_is_excluded (daemon, username, MINIMAL_UID)) {
+        if (user_is_excluded (daemon, username, daemon->priv->minimal_uid)) {
                 g_debug ("excluding user '%s'", username);
                 g_free (username);
                 return;
@@ -454,6 +454,37 @@ reload_ck_history (Daemon *daemon)
         g_free (command);
 }
 
+static void
+reload_adduser_conf (Daemon *daemon)
+{
+        GFile *file;
+        gboolean result;
+        char *contents;
+        guint first_uid = 0;
+
+        file = g_file_new_for_path ("/etc/login.defs");
+        result = g_file_load_contents (file, NULL, &contents, NULL, NULL, NULL);
+        if (result == TRUE) {
+                GRegex *regex;
+                GMatchInfo *match_info;
+
+                regex = g_regex_new ("^UID_MIN\\s+([0-9]+)\\s*$", G_REGEX_MULTILINE, 0, NULL);
+                g_regex_match (regex, contents, 0, &match_info);
+                while (g_match_info_matches (match_info)) {
+                        gchar *word = g_match_info_fetch (match_info, 1);
+                        first_uid = atoi(word);
+                        g_free (word);
+                        g_match_info_next (match_info, NULL);
+                        break;
+                }
+                g_match_info_free (match_info);
+                g_regex_unref (regex);
+
+                g_free (contents);
+        }
+        daemon->priv->minimal_uid = first_uid ? first_uid : 1000; /* default value */
+}
+
 static gint
 compare_user_name (gconstpointer a, gconstpointer b)
 {
@@ -572,6 +603,7 @@ static void
 reload_users (Daemon *daemon)
 {
         reload_ck_history (daemon);
+        reload_adduser_conf (daemon);
         reload_passwd (daemon);
         reload_data (daemon);
 }
-- 
1.7.4.1

>From 5bb23b0bd2abfe590159c8a9a6ab33c6e53673ab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpet...@0d.be>
Date: Fri, 18 Mar 2011 11:18:00 +0100
Subject: [PATCH 2/3] create and manage groups like on a debian system

---
 src/daemon.c |   29 ++++++++---------
 src/user.c   |   98 ++++++++++++++++------------------------------------------
 src/util.c   |   43 +++++++++++++++++++++++++
 src/util.h   |    8 +++++
 4 files changed, 91 insertions(+), 87 deletions(-)

diff --git a/src/daemon.c b/src/daemon.c
index 0b95c14..933a1fc 100644
--- a/src/daemon.c
+++ b/src/daemon.c
@@ -1076,22 +1076,8 @@ daemon_create_user_authorized_cb (Daemon                *daemon,
         argv[1] = "-m";
         argv[2] = "-c";
         argv[3] = cd->real_name;
-        if (cd->account_type == ACCOUNT_TYPE_ADMINISTRATOR) {
-                argv[4] = "-G";
-                argv[5] = "desktop_admin_r";
-                argv[6] = cd->user_name;
-                argv[7] = NULL;
-        }
-        else if (cd->account_type == ACCOUNT_TYPE_STANDARD) {
-                argv[4] = "-G";
-                argv[5] = "desktop_user_r";
-                argv[6] = cd->user_name;
-                argv[7] = NULL;
-        }
-        else {
-                argv[4] = cd->user_name;
-                argv[5] = NULL;
-        }
+        argv[4] = cd->user_name;
+        argv[5] = NULL;
 
         error = NULL;
         if (!spawn_with_login_uid (context, argv, &error)) {
@@ -1100,6 +1086,17 @@ daemon_create_user_authorized_cb (Daemon                *daemon,
                 return;
         }
 
+        if (cd->account_type == ACCOUNT_TYPE_ADMINISTRATOR) {
+                add_user_to_group (context, cd->user_name, "admin");
+        }
+        if (cd->account_type == ACCOUNT_TYPE_ADMINISTRATOR ||
+            cd->account_type == ACCOUNT_TYPE_STANDARD) {
+                add_user_to_group (context, cd->user_name, "audio");
+                add_user_to_group (context, cd->user_name, "cdrom");
+                add_user_to_group (context, cd->user_name, "dialout");
+                add_user_to_group (context, cd->user_name, "plugdev");
+        }
+
         user = daemon_local_find_user_by_name (daemon, cd->user_name);
 
         dbus_g_method_return (context, user_local_get_object_path (user));
diff --git a/src/user.c b/src/user.c
index b7acb6c..c5b64ae 100644
--- a/src/user.c
+++ b/src/user.c
@@ -412,38 +412,31 @@ static gint
 account_type_from_groups (struct passwd *pwent)
 {
         struct group *grp;
-        gid_t desktop_user_r;
-        gid_t desktop_admin_r;
+        gid_t admin;
         gid_t *groups;
         gint ngroups;
         gint i;
+        gint account_type = ACCOUNT_TYPE_STANDARD;
 
-        grp = getgrnam ("desktop_user_r");
+        grp = getgrnam ("admin");
         if (grp == NULL) {
-                g_warning ("desktop_user_r group not found");
+                g_warning ("admin group not found");
                 return ACCOUNT_TYPE_STANDARD;
         }
-        desktop_user_r = grp->gr_gid;
-
-        grp = getgrnam ("desktop_admin_r");
-        if (grp == NULL) {
-                g_warning ("desktop_admin_r group not found");
-                return ACCOUNT_TYPE_STANDARD;
-        }
-        desktop_admin_r = grp->gr_gid;
+        admin = grp->gr_gid;
 
         ngroups = get_user_groups (pwent->pw_name, pwent->pw_gid, &groups);
 
         for (i = 0; i < ngroups; i++) {
-                if (groups[i] == desktop_user_r)
-                        return ACCOUNT_TYPE_STANDARD;
-                if (groups[i] == desktop_admin_r)
-                        return ACCOUNT_TYPE_ADMINISTRATOR;
+                if (groups[i] == admin) {
+                        account_type = ACCOUNT_TYPE_ADMINISTRATOR;
+                        break;
+                }
         }
 
         g_free (groups);
 
-        return ACCOUNT_TYPE_SUPERVISED;
+        return account_type;
 }
 
 void
@@ -1560,70 +1553,33 @@ user_change_account_type_authorized_cb (Daemon                *daemon,
 
 {
         gint account_type = GPOINTER_TO_INT (data);
-        GError *error;
-        gid_t *groups;
-        gint ngroups;
-        GString *str;
-        gid_t desktop_user_r;
-        gid_t desktop_admin_r;
-        struct group *grp;
-        gint i;
-        gchar *argv[5];
 
         if (user->account_type != account_type) {
                 sys_log (context,
                          "change account type of user '%s' (%d) to %d",
                          user->user_name, user->uid, account_type);
 
-                grp = getgrnam ("desktop_user_r");
-                if (grp == NULL) {
-                        throw_error (context, ERROR_FAILED, "failed to set account type: desktop_user_r group not found");
-                        return;
+                /* removing extraneous groups */
+                if (account_type == ACCOUNT_TYPE_SUPERVISED) {
+                        remove_user_from_group (context, user->user_name, "audio");
+                        remove_user_from_group (context, user->user_name, "cdrom");
+                        remove_user_from_group (context, user->user_name, "dialout");
+                        remove_user_from_group (context, user->user_name, "plugdev");
                 }
-                desktop_user_r = grp->gr_gid;
-
-                grp = getgrnam ("desktop_admin_r");
-                if (grp == NULL) {
-                        throw_error (context, ERROR_FAILED, "failed to set account type: desktop_admin_r group not found");
-                        return;
+                else if (account_type == ACCOUNT_TYPE_STANDARD) {
+                        remove_user_from_group (context, user->user_name, "admin");
                 }
-                desktop_admin_r = grp->gr_gid;
-
-                ngroups = get_user_groups (user->user_name, user->gid, &groups);
 
-                str = g_string_new ("");
-                for (i = 0; i < ngroups; i++) {
-                        if (groups[i] == desktop_user_r || groups[i] == desktop_admin_r)
-                                continue;
-                        g_string_append_printf (str, "%d,", groups[i]);
+                /* adding new groups */
+                if (account_type == ACCOUNT_TYPE_STANDARD ||
+                    account_type == ACCOUNT_TYPE_ADMINISTRATOR) {
+                        add_user_to_group (context, user->user_name, "audio");
+                        add_user_to_group (context, user->user_name, "cdrom");
+                        add_user_to_group (context, user->user_name, "dialout");
+                        add_user_to_group (context, user->user_name, "plugdev");
                 }
-                switch (account_type) {
-                case ACCOUNT_TYPE_STANDARD:
-                        g_string_append_printf (str, "%d", desktop_user_r);
-                        break;
-                case ACCOUNT_TYPE_ADMINISTRATOR:
-                        g_string_append_printf (str, "%d", desktop_admin_r);
-                        break;
-                default:
-                        /* remove excess comma */
-                        g_string_truncate (str, str->len - 1);
-                }
-
-                g_free (groups);
-
-                argv[0] = "/usr/sbin/usermod";
-                argv[1] = "-G";
-                argv[2] = str->str;
-                argv[3] = user->user_name;
-                argv[4] = NULL;
-
-                g_string_free (str, FALSE);
-
-                error = NULL;
-                if (!spawn_with_login_uid (context, argv, &error)) {
-                        throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
-                        g_error_free (error);
-                        return;
+                if (account_type == ACCOUNT_TYPE_ADMINISTRATOR) {
+                        add_user_to_group (context, user->user_name, "admin");
                 }
 
                 user->account_type = account_type;
diff --git a/src/util.c b/src/util.c
index d748afd..0756d26 100644
--- a/src/util.c
+++ b/src/util.c
@@ -282,3 +282,46 @@ get_caller_uid (DBusGMethodInvocation *context, gint *uid)
 
         return TRUE;
 }
+
+void
+add_user_to_group (DBusGMethodInvocation *context,
+                  const char *user_name,
+                  const char *group_name)
+{
+        GError *error;
+        gchar *argv[4];
+
+        argv[0] = (gchar*) "/usr/sbin/adduser";
+        argv[1] = (gchar*) user_name;
+        argv[2] = (gchar*) group_name;
+        argv[3] = NULL;
+
+        error = NULL;
+        if (!spawn_with_login_uid (context, argv, &error)) {
+                g_warning ("failed to add user %s to group %s", user_name, group_name);
+                g_error_free (error);
+                return;
+        }
+}
+
+void
+remove_user_from_group (DBusGMethodInvocation *context,
+                        const char *user_name,
+                        const char *group_name)
+{
+        GError *error;
+        gchar *argv[4];
+
+        argv[0] = (gchar*) "/usr/sbin/deluser";
+        argv[1] = (gchar*) user_name;
+        argv[2] = (gchar*) group_name;
+        argv[3] = NULL;
+
+        error = NULL;
+        if (!spawn_with_login_uid (context, argv, &error)) {
+                g_warning ("failed to remove user %s from group %s", user_name, group_name);
+                g_error_free (error);
+                return;
+        }
+}
+
diff --git a/src/util.h b/src/util.h
index bfdf780..9cfd85f 100644
--- a/src/util.h
+++ b/src/util.h
@@ -41,6 +41,14 @@ gint get_user_groups (const gchar  *username,
                       gid_t         group,
                       gid_t       **groups);
 
+void add_user_to_group (DBusGMethodInvocation *context,
+                        const char *user_name,
+                        const char *group_name);
+
+void remove_user_from_group (DBusGMethodInvocation *context,
+                             const char *user_name,
+                             const char *group_name);
+
 G_END_DECLS
 
 #endif /* __UTIL_H__ */
-- 
1.7.4.1

>From ad6631970b5f77b669f4c67e6617a2fbd35d8fef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpet...@0d.be>
Date: Fri, 18 Mar 2011 11:29:49 +0100
Subject: [PATCH 3/3] do not consider system users returned from consolekit history

---
 src/daemon.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/daemon.c b/src/daemon.c
index 933a1fc..4940d08 100644
--- a/src/daemon.c
+++ b/src/daemon.c
@@ -329,6 +329,7 @@ process_ck_history_line (Daemon      *daemon,
         gchar *username;
         gulong frequency;
         User *user;
+        struct passwd *pw;
 
         frequency = 0;
         username = NULL;
@@ -337,8 +338,9 @@ process_ck_history_line (Daemon      *daemon,
                 return;
         }
 
-        /* pass MINIMAL_UID to just check the name here */
-        if (user_is_excluded (daemon, username, daemon->priv->minimal_uid)) {
+        pw = getpwnam (username);
+
+        if (user_is_excluded (daemon, username, pw->pw_uid)) {
                 g_debug ("excluding user '%s'", username);
                 g_free (username);
                 return;
-- 
1.7.4.1

Reply via email to