[gdm] Add support for include, exclude, and include_all configuration options in



commit 7c29be20c07c7200f2bff89883f9d5436fc0dadc
Author: Brian Cameron <Brian Cameron sun com>
Date:   Wed Sep 9 20:11:28 2009 -0500

    Add support for include, exclude, and include_all configuration options in
    the login GUI.  Fixes bug #557553.

 docs/C/gdm.xml                                   |   56 ++++
 gui/simple-greeter/gdm-simple-greeter.schemas.in |   35 +++
 gui/simple-greeter/gdm-user-manager.c            |  310 ++++++++++++++--------
 3 files changed, 285 insertions(+), 116 deletions(-)
---
diff --git a/docs/C/gdm.xml b/docs/C/gdm.xml
index 60ae5cf..17ce2a8 100644
--- a/docs/C/gdm.xml
+++ b/docs/C/gdm.xml
@@ -1569,6 +1569,62 @@ gdm:.my.domain
           </varlistentry>
 
           <varlistentry>
+            <term>/apps/gdm/simple-greeter/include</term>
+            <listitem>
+              <synopsis>[] (string list)</synopsis>
+              <para>
+               Set to a list of users to always include in the Face Browser.
+              </para>
+            </listitem>
+          </varlistentry>
+
+          <varlistentry>
+            <term>/apps/gdm/simple-greeter/include_all</term>
+            <listitem>
+              <synopsis>true (boolean)</synopsis>
+              <para>
+                If true, then the face browser will show all users on the
+                local machine.  If false, the face browser will only show
+                users who have recently logged in.
+              </para>
+              <para>
+               To provide more detail on how this option works. When this key
+               is true, GDM will call fgetpwent() to get a list of local users
+               on the system.  The Face Browser also will display any users
+               that have previously logged in on the system (for example
+               NIS/LDAP users).  It gets this list via calling the ck-history
+               ConsoleKit interface.  It will also filter out any users which
+               do not have a valid shell (valid shells are any shell that
+               getusershell() returns.  <filename>/sbin/nologin</filename> or
+               <filename>/bin/false</filename> are considered invalid shells
+               even if getusershell() returns them).
+              </para>
+
+              <para>
+               If false, then GDM more simply only displays users that have 
+               previously logged in on the system (local or NIS/LDAP users) by
+               calling the ck-history ConsoleKit interface.
+              </para>
+
+              <para>
+               In both cases, GDM filters out any users with a UID less than
+               500 (or 100 if running on Solaris).  Such users are considered
+               system users.
+              </para>
+            </listitem>
+          </varlistentry>
+
+          <varlistentry>
+            <term>/apps/gdm/simple-greeter/exclude</term>
+            <listitem>
+              <synopsis>[] (string list)</synopsis>
+              <para>
+                Set to a list of users to always exclude in the Face Browser.
+              </para>
+            </listitem>
+          </varlistentry>
+
+          <varlistentry>
             <term>/apps/gdm/simple-greeter/logo_icon_name</term>
             <listitem>
               <synopsis>computer (string)</synopsis>
diff --git a/gui/simple-greeter/gdm-simple-greeter.schemas.in b/gui/simple-greeter/gdm-simple-greeter.schemas.in
index f6e9a6b..e9507e8 100644
--- a/gui/simple-greeter/gdm-simple-greeter.schemas.in
+++ b/gui/simple-greeter/gdm-simple-greeter.schemas.in
@@ -281,6 +281,41 @@
         <long></long>
       </locale>
     </schema>
+    <schema>
+      <key>/schemas/apps/gdm/simple-greeter/include_all</key>
+      <applyto>/apps/gdm/simple-greeter/include_all</applyto>
+      <owner>gdm-simple-greeter</owner>
+      <type>bool</type>
+      <default>TRUE</default>
+      <locale name="C">
+        <short>Include local users in Face Browser</short>
+        <long>Set to true to include system local users in Face Browser</long>
+      </locale>
+    </schema>
+    <schema>
+      <key>/schemas/apps/gdm/simple-greeter/include</key>
+      <applyto>/apps/gdm/simple-greeter/include</applyto>
+      <owner>gdm-simple-greeter</owner>
+      <type>list</type>
+      <list_type>string</list_type>
+      <default>[]</default>
+      <locale name="C">
+        <short>Users to include in the Face Browser</short>
+        <long>Set to a list of users to be shown by default in the Face Browser.</long>
+      </locale>
+    </schema>
+    <schema>
+      <key>/schemas/apps/gdm/simple-greeter/exclude</key>
+      <applyto>/apps/gdm/simple-greeter/exclude</applyto>
+      <owner>gdm-simple-greeter</owner>
+      <type>list</type>
+      <list_type>string</list_type>
+      <default>[bin,root,daemon,adm,lp,sync,shutdown,halt,mail,news,uucp,operator,nobody,nobody4,noaccess,postgres,pvm,rpm,nfsnobody,pcap]</default>
+      <locale name="C">
+        <short>Users to exclude in the Face Browser</short>
+        <long>Set to a list of users not to be shown in the Face Browser.</long>
+      </locale>
+    </schema>
 
   </schemalist>
 </gconfschemafile>
diff --git a/gui/simple-greeter/gdm-user-manager.c b/gui/simple-greeter/gdm-user-manager.c
index 6c91b3b..bf93cac 100644
--- a/gui/simple-greeter/gdm-user-manager.c
+++ b/gui/simple-greeter/gdm-user-manager.c
@@ -40,6 +40,8 @@
 #include <glib-object.h>
 #include <gio/gio.h>
 
+#include <gconf/gconf-client.h>
+
 #include <dbus/dbus.h>
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-lowlevel.h>
@@ -76,34 +78,14 @@
 
 #define DEFAULT_GLOBAL_FACE_DIR DATADIR "/faces"
 #define DEFAULT_USER_ICON       "stock_person"
-#define DEFAULT_EXCLUDE         { "bin",        \
-                                  "root",       \
-                                  "daemon",     \
-                                  "adm",        \
-                                  "lp",         \
-                                  "sync",       \
-                                  "shutdown",   \
-                                  "halt",       \
-                                  "mail",       \
-                                  "news",       \
-                                  "uucp",       \
-                                  "operator",   \
-                                  "nobody",     \
-                                  "nobody4",    \
-                                  "noaccess",   \
-                                  GDM_USERNAME, \
-                                  "postgres",   \
-                                  "pvm",        \
-                                  "rpm",        \
-                                  "nfsnobody",  \
-                                  "pcap",       \
-                                  NULL }
+#define KEY_INCLUDE_ALL "/apps/gdm/simple-greeter/include_all"
+#define KEY_INCLUDE     "/apps/gdm/simple-greeter/include"
+#define KEY_EXCLUDE     "/apps/gdm/simple-greeter/exclude"
 
 struct GdmUserManagerPrivate
 {
         GHashTable            *users;
         GHashTable            *sessions;
-        GHashTable            *exclusions;
         GHashTable            *shells;
         DBusGConnection       *connection;
         DBusGProxy            *seat_proxy;
@@ -112,6 +94,10 @@ struct GdmUserManagerPrivate
         GFileMonitor          *passwd_monitor;
         GFileMonitor          *shells_monitor;
 
+        GSList                *exclude;
+        GSList                *include;
+        gboolean               include_all;
+
         guint                  reload_id;
         guint                  ck_history_id;
 
@@ -599,6 +585,39 @@ get_x11_display_for_session (DBusGConnection *connection,
         return x11_display;
 }
 
+static gint
+match_name_cmpfunc (gconstpointer a,
+                    gconstpointer b)
+{
+        if (a == NULL || b == NULL)
+                return -1;
+
+        return g_strcmp0 ((char *) a,
+                          (char *) b);
+}
+
+static gboolean
+check_excludes (GdmUserManager *manager, const char *user)
+{
+        GSList   *found;
+        gboolean  ret = FALSE;
+
+        g_debug ("checking exclude list");
+
+        /* always exclude the "gdm" user. */
+        if (user == NULL || (strcmp (user, GDM_USERNAME) == 0))
+                return TRUE;
+
+        if (manager->priv->exclude != NULL) {
+                found = g_slist_find_custom (manager->priv->exclude,
+                                             user,
+                                             match_name_cmpfunc);
+                if (found != NULL)
+                        ret = TRUE;
+        }
+        return ret;
+}
+
 static gboolean
 maybe_add_session_for_user (GdmUserManager *manager,
                             GdmUser        *user,
@@ -628,7 +647,7 @@ maybe_add_session_for_user (GdmUserManager *manager,
                 goto out;
         }
 
-        if (g_hash_table_lookup (manager->priv->exclusions, gdm_user_get_user_name (user))) {
+        if (check_excludes (manager, gdm_user_get_user_name (user))) {
                 g_debug ("GdmUserManager: excluding user '%s'", gdm_user_get_user_name (user));
                 goto out;
         }
@@ -906,7 +925,7 @@ seat_session_added (DBusGProxy     *seat_proxy,
         }
 
         /* check exclusions up front */
-        if (g_hash_table_lookup (manager->priv->exclusions, pwent->pw_name)) {
+        if (check_excludes (manager, pwent->pw_name)) {
                 g_debug ("GdmUserManager: excluding user '%s'", pwent->pw_name);
                 return;
         }
@@ -1222,7 +1241,7 @@ process_ck_history_line (GdmUserManager *manager,
                 return;
         }
 
-        if (g_hash_table_lookup (manager->priv->exclusions, username)) {
+        if (check_excludes (manager, username)) {
                 g_debug ("GdmUserManager: excluding user '%s'", username);
                 g_free (username);
                 return;
@@ -1359,6 +1378,20 @@ reload_ck_history (GdmUserManager *manager)
 }
 
 static void
+add_included_user (char *username, GdmUserManager *manager)
+{
+        GdmUser     *user;
+
+        g_debug ("Adding included user %s", username);
+        user = gdm_user_manager_get_user (manager, username);
+        if (user == NULL) {
+                g_debug ("GdmUserManager: unable to lookup user '%s'", username);
+                g_free (username);
+                return;
+        }
+}
+
+static void
 reload_passwd (GdmUserManager *manager)
 {
         struct passwd *pwent;
@@ -1390,48 +1423,58 @@ reload_passwd (GdmUserManager *manager)
                 }
         }
 
-        for (pwent = fgetpwent (fp); pwent != NULL; pwent = fgetpwent (fp)) {
-                GdmUser *user;
+        if (manager->priv->include_all != TRUE) {
+                g_debug ("GdmUserManager: include_all is FALSE");
+        } else {
+                g_debug ("GdmUserManager: include_all is TRUE");
 
-                user = NULL;
+                for (pwent = fgetpwent (fp);
+                     pwent != NULL;
+                     pwent = fgetpwent (fp)) {
+                        GdmUser *user;
 
-                /* Skip users below MinimalUID... */
-                if (pwent->pw_uid < DEFAULT_MINIMAL_UID) {
-                        continue;
-                }
+                        user = NULL;
 
-                /* ...And users w/ invalid shells... */
-                if (pwent->pw_shell == NULL ||
-                    !g_hash_table_lookup (manager->priv->shells, pwent->pw_shell)) {
-                        g_debug ("GdmUserManager: skipping user with bad shell: %s", pwent->pw_name);
-                        continue;
-                }
+                        /* Skip users below MinimalUID... */
+                        if (pwent->pw_uid < DEFAULT_MINIMAL_UID) {
+                                continue;
+                        }
 
-                /* ...And explicitly excluded users */
-                if (g_hash_table_lookup (manager->priv->exclusions, pwent->pw_name)) {
-                        g_debug ("GdmUserManager: explicitly skipping user: %s", pwent->pw_name);
-                        continue;
-                }
+                        /* ...And users w/ invalid shells... */
+                        if (pwent->pw_shell == NULL ||
+                            !g_hash_table_lookup (manager->priv->shells,
+                                                  pwent->pw_shell)) {
+                                g_debug ("GdmUserManager: skipping user with bad shell: %s", pwent->pw_name);
+                                continue;
+                        }
 
-                user = g_hash_table_lookup (manager->priv->users, pwent->pw_name);
+                        /* ...And explicitly excluded users */
+                        if (check_excludes (manager, pwent->pw_name)) {
+                                g_debug ("GdmUserManager: explicitly skipping user: %s", pwent->pw_name);
+                                continue;
+                        }
 
-                /* Update users already in the *new* list */
-                if (g_slist_find (new_users, user)) {
-                        _gdm_user_update (user, pwent);
-                        continue;
-                }
+                        user = g_hash_table_lookup (manager->priv->users,
+                                                    pwent->pw_name);
 
-                if (user == NULL) {
-                        user = create_user (manager);
-                } else {
-                        g_object_ref (user);
-                }
+                        /* Update users already in the *new* list */
+                        if (g_slist_find (new_users, user)) {
+                                _gdm_user_update (user, pwent);
+                                continue;
+                        }
 
-                /* Freeze & update users not already in the new list */
-                g_object_freeze_notify (G_OBJECT (user));
-                _gdm_user_update (user, pwent);
+                        if (user == NULL) {
+                                user = create_user (manager);
+                        } else {
+                                g_object_ref (user);
+                        }
+
+                        /* Freeze & update users not already in the new list */
+                        g_object_freeze_notify (G_OBJECT (user));
+                        _gdm_user_update (user, pwent);
 
-                new_users = g_slist_prepend (new_users, user);
+                        new_users = g_slist_prepend (new_users, user);
+                }
         }
 
         /* Go through and handle removed users */
@@ -1458,6 +1501,13 @@ reload_passwd (GdmUserManager *manager)
                 }
         }
 
+        /* Add users who are specifically included */
+        if (manager->priv->include != NULL) {
+                g_slist_foreach (manager->priv->include,
+                                 (GFunc)add_included_user,
+                                 (gpointer)manager);
+        }
+
  out:
         /* Cleanup */
 
@@ -1618,79 +1668,99 @@ gdm_user_manager_init (GdmUserManager *manager)
         int            i;
         GFile         *file;
         GError        *error;
-        const char    *exclude_default[] = DEFAULT_EXCLUDE;
+        GConfClient   *client;
 
         manager->priv = GDM_USER_MANAGER_GET_PRIVATE (manager);
 
-        /* sessions */
-        manager->priv->sessions = g_hash_table_new_full (g_str_hash,
-                                                         g_str_equal,
-                                                         g_free,
-                                                         g_free);
+        /* exclude/include */
+        error = NULL;
+        client = gconf_client_get_default ();
+        manager->priv->exclude = gconf_client_get_list (client, KEY_EXCLUDE, GCONF_VALUE_STRING, &error);
+        if (error != NULL) {
+                g_debug ("GdmUserManager: unable to get exclude configuration: %s", error->message);
+                g_error_free (error);
+                manager->priv->exclude = NULL;
+        }
 
-        /* exclusions */
-        manager->priv->exclusions = g_hash_table_new_full (g_str_hash,
-                                                           g_str_equal,
-                                                           g_free,
-                                                           NULL);
-        for (i = 0; exclude_default[i] != NULL; i++) {
-                g_hash_table_insert (manager->priv->exclusions,
-                                     g_strdup (exclude_default [i]),
-                                     GUINT_TO_POINTER (TRUE));
+        error = NULL;
+        manager->priv->include = gconf_client_get_list (client, KEY_INCLUDE, GCONF_VALUE_STRING, &error);
+        if (error != NULL) {
+                g_debug ("GdmUserManager: unable to get include configuration: %s", error->message);
+                g_error_free (error);
+                manager->priv->include = NULL;
         }
 
-        /* /etc/shells */
-        manager->priv->shells = g_hash_table_new_full (g_str_hash,
-                                                       g_str_equal,
-                                                       g_free,
-                                                       NULL);
-        reload_shells (manager);
-        file = g_file_new_for_path (_PATH_SHELLS);
         error = NULL;
-        manager->priv->shells_monitor = g_file_monitor_file (file,
-                                                             G_FILE_MONITOR_NONE,
-                                                             NULL,
-                                                             &error);
-        if (manager->priv->shells_monitor != NULL) {
-                g_signal_connect (manager->priv->shells_monitor,
-                                  "changed",
-                                  G_CALLBACK (on_shells_monitor_changed),
-                                  manager);
-        } else {
-                if (error != NULL) {
-                        g_warning ("Unable to monitor %s: %s", _PATH_SHELLS, error->message);
-                        g_error_free (error);
-                } else {
-                        g_warning ("Unable to monitor %s", _PATH_SHELLS);
-                }
+        manager->priv->include_all = gconf_client_get_bool (client, KEY_INCLUDE_ALL, &error);
+
+        if (error != NULL) {
+                g_debug ("GdmUserManager: unable to get include_all configuration: %s", error->message);
+                g_error_free (error);
+                manager->priv->include_all = TRUE;
         }
-        g_object_unref (file);
+        g_object_unref (client);
 
-        /* /etc/passwd */
+        /* sessions */
+        manager->priv->sessions = g_hash_table_new_full (g_str_hash,
+                                                         g_str_equal,
+                                                         g_free,
+                                                         g_free);
+
+        /* users */
         manager->priv->users = g_hash_table_new_full (g_str_hash,
                                                       g_str_equal,
                                                       g_free,
                                                       (GDestroyNotify) g_object_run_dispose);
-        file = g_file_new_for_path (PATH_PASSWD);
-        manager->priv->passwd_monitor = g_file_monitor_file (file,
-                                                             G_FILE_MONITOR_NONE,
-                                                             NULL,
-                                                             &error);
-        if (manager->priv->passwd_monitor != NULL) {
-                g_signal_connect (manager->priv->passwd_monitor,
-                                  "changed",
-                                  G_CALLBACK (on_passwd_monitor_changed),
-                                  manager);
-        } else {
-                if (error != NULL) {
-                        g_warning ("Unable to monitor %s: %s", PATH_PASSWD, error->message);
-                        g_error_free (error);
+
+        if (manager->priv->include_all == TRUE) {
+                /* /etc/shells */
+                manager->priv->shells = g_hash_table_new_full (g_str_hash,
+                                                               g_str_equal,
+                                                               g_free,
+                                                               NULL);
+                reload_shells (manager);
+                file = g_file_new_for_path (_PATH_SHELLS);
+                error = NULL;
+                manager->priv->shells_monitor = g_file_monitor_file (file,
+                                                                     G_FILE_MONITOR_NONE,
+                                                                     NULL,
+                                                                     &error);
+                if (manager->priv->shells_monitor != NULL) {
+                        g_signal_connect (manager->priv->shells_monitor,
+                                          "changed",
+                                          G_CALLBACK (on_shells_monitor_changed),
+                                          manager);
+                } else {
+                        if (error != NULL) {
+	        		g_warning ("Unable to monitor %s: %s", _PATH_SHELLS, error->message);
+                     		g_error_free (error);
+        		} else {
+                                g_warning ("Unable to monitor %s", _PATH_SHELLS);
+	        	}
+                }
+                g_object_unref (file);
+
+                /* /etc/passwd */
+                file = g_file_new_for_path (PATH_PASSWD);
+                manager->priv->passwd_monitor = g_file_monitor_file (file,
+                                                                     G_FILE_MONITOR_NONE,
+                                                                     NULL,
+                                                                     &error);
+                if (manager->priv->passwd_monitor != NULL) {
+                        g_signal_connect (manager->priv->passwd_monitor,
+                                          "changed",
+                                          G_CALLBACK (on_passwd_monitor_changed),
+                                          manager);
                 } else {
-                        g_warning ("Unable to monitor %s", PATH_PASSWD);
+                        if (error != NULL) {
+                                g_warning ("Unable to monitor %s: %s", PATH_PASSWD, error->message);
+                                g_error_free (error);
+        		} else {
+                                g_warning ("Unable to monitor %s", PATH_PASSWD);
+	        	}
                 }
+                g_object_unref (file);
         }
-        g_object_unref (file);
-
 
         get_seat_proxy (manager);
 
@@ -1711,6 +1781,14 @@ gdm_user_manager_finalize (GObject *object)
 
         g_return_if_fail (manager->priv != NULL);
 
+        if (manager->priv->exclude != NULL) {
+                g_slist_free (manager->priv->exclude);
+        }
+
+        if (manager->priv->include != NULL) {
+                g_slist_free (manager->priv->include);
+        }
+
         if (manager->priv->seat_proxy != NULL) {
                 g_object_unref (manager->priv->seat_proxy);
         }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]