diff -Nur -x '*.orig' -x '*~' gdm-2.29.1/daemon/gdm-session-worker.c gdm-2.29.1.new/daemon/gdm-session-worker.c --- gdm-2.29.1/daemon/gdm-session-worker.c 2009-11-16 22:37:43.000000000 +0000 +++ gdm-2.29.1.new/daemon/gdm-session-worker.c 2010-01-02 10:52:47.959529940 +0000 @@ -91,6 +91,35 @@ #define MAX_FILE_SIZE 65536 +#ifdef __sun +#define DEFAULT_MINIMAL_UID 100 +#else +#define DEFAULT_MINIMAL_UID 1000 +#endif + +#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 } + enum { GDM_SESSION_WORKER_STATE_NONE = 0, GDM_SESSION_WORKER_STATE_SETUP_COMPLETE, @@ -129,6 +158,9 @@ int cred_flags; + GHashTable *exclusions; + guint minimal_uid; + char **arguments; GHashTable *environment; guint32 cancelled : 1; @@ -1670,6 +1702,45 @@ goto out; } + /* Skip users below MinimalUID... */ + if (uid < worker->priv->minimal_uid) { + error_code = PAM_AUTH_ERR; + g_set_error (error, + GDM_SESSION_WORKER_ERROR, + GDM_SESSION_WORKER_ERROR_GIVING_CREDENTIALS, + uid == 0 ? _("The system administrator is not allowed to login from this screen") + : _("%s: User not allowed to log in"), worker->priv->username); + goto out; + } + + /* ...And users w/ invalid shells... */ + if (shell == NULL + || strcmp (shell, "/sbin/nologin") == 0 + || strcmp (shell, "/bin/false") == 0) { + g_debug ("GdmSessionWorker: skipping user with bad shell: %s", worker->priv->username); + + error_code = PAM_AUTH_ERR; + g_set_error (error, + GDM_SESSION_WORKER_ERROR, + GDM_SESSION_WORKER_ERROR_GIVING_CREDENTIALS, + uid == 0 ? _("The system administrator is not allowed to login from this screen") + : _("%s: User not allowed to log in"), worker->priv->username); + goto out; + } + + /* ...And explicitly excluded users */ + if (g_hash_table_lookup (worker->priv->exclusions, worker->priv->username)) { + g_debug ("GdmSessionWorker: explicitly skipping user: %s", worker->priv->username); + + error_code = PAM_AUTH_ERR; + g_set_error (error, + GDM_SESSION_WORKER_ERROR, + GDM_SESSION_WORKER_ERROR_GIVING_CREDENTIALS, + uid == 0 ? _("The system administrator is not allowed to login from this screen") + : _("%s: User not allowed to log in"), worker->priv->username); + goto out; + } + gdm_session_worker_update_environment_from_passwd_info (worker, uid, gid, @@ -2909,15 +2980,64 @@ G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); } + +static guint +system_minimal_uid (void) +{ + guint uid = DEFAULT_MINIMAL_UID; +#ifndef __sun + char *defspath = "/etc/login.defs"; + FILE *fp; + char line[128]; + + errno = 0; + fp = fopen (defspath, "r"); + if (fp == NULL) { + g_warning ("Unable to open %s: %s", defspath, g_strerror (errno)); + goto out; + } + while (fgets (line, sizeof(line), fp)) { + if (strncmp (line, "UID_MIN", 7) == 0) { + char *ptr = line + 7; + int value; + while (*ptr && isblank (*ptr)) { ptr++; } + value = atoi (ptr); + if (value) uid = value; + break; + } + } + fclose (fp); +#endif +out: + return uid; +} + + static void gdm_session_worker_init (GdmSessionWorker *worker) { + const char *exclude_default[] = DEFAULT_EXCLUDE; + int i; worker->priv = GDM_SESSION_WORKER_GET_PRIVATE (worker); worker->priv->environment = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, (GDestroyNotify) g_free); + + worker->priv->minimal_uid = system_minimal_uid (); + + /* exclusions */ + worker->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 (worker->priv->exclusions, + g_strdup (exclude_default [i]), + GUINT_TO_POINTER (TRUE)); + } + } static void