=== modified file 'data/org.freedesktop.Accounts.xml' --- data/org.freedesktop.Accounts.xml 2011-03-18 10:28:02 +0000 +++ data/org.freedesktop.Accounts.xml 2012-08-21 06:12:00 +0000 @@ -173,5 +173,17 @@ + + + + + True when user listing is trimmed to set limit. + + + + + + + === modified file 'src/daemon.c' --- src/daemon.c 2011-11-25 08:28:18 +0000 +++ src/daemon.c 2012-08-21 05:49:22 +0000 @@ -58,6 +58,11 @@ #define FALLBACK_MINIMAL_UID 500 #endif +#ifndef FALLBACK_MAXIMUM_UID +#define FALLBACK_MAXIMUM_UID 500 /* does not make sense to manage more than these many users on a desktop system me */ +#endif + + #define USERDIR LOCALSTATEDIR "/lib/AccountsService/users" static const char *default_excludes[] = { @@ -86,7 +91,8 @@ enum { PROP_0, - PROP_DAEMON_VERSION + PROP_DAEMON_VERSION, + PROP_USER_LIMIT }; enum { @@ -104,6 +110,8 @@ GHashTable *users; GHashTable *exclusions; uid_t minimal_uid; + uid_t maximum_uid; /* maximum no of users that are to be listed */ + gboolean user_limit; /* did we cross the user limit, if so we did bail out on listing all users */ User *autologin; @@ -165,17 +173,22 @@ GValue *value, GParamSpec *pspec) { + Daemon *daemon = DAEMON (object); + switch (prop_id) { case PROP_DAEMON_VERSION: g_value_set_string (value, VERSION); break; - + case PROP_USER_LIMIT: + g_value_set_boolean (value, daemon->priv->user_limit); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } + static void daemon_class_init (DaemonClass *klass) { @@ -222,6 +235,14 @@ "Daemon version", NULL, G_PARAM_READABLE)); + g_object_class_install_property (object_class, + PROP_USER_LIMIT, + g_param_spec_boolean ("user-limit", + "User limit", + "User limit exceeded", + FALSE, + G_PARAM_READABLE)); + } gboolean @@ -356,6 +377,9 @@ g_hash_table_foreach (daemon->priv->users, listify_hash_values_hfunc, &old_users); g_slist_foreach (old_users, (GFunc) g_object_ref, NULL); + int i = 0; + daemon->priv->user_limit = FALSE; + #ifdef HAVE_FGETPWENT while ((pwent = fgetpwent (fp)) != NULL) { #else @@ -379,6 +403,11 @@ g_object_ref (user); } + if ( i++ > daemon->priv->maximum_uid ) { + daemon->priv->user_limit = TRUE; + break; + } + /* freeze & update users not already in the new list */ g_object_freeze_notify (G_OBJECT (user)); user_local_update_from_pwent (user, pwent); @@ -576,18 +605,18 @@ } static uid_t -get_minimal_uid (void) +get_value_from_login (gchar *key, uid_t *value) { GError *error; char *contents; - gboolean contents_loaded; - const char *uid_min_string, *start_of_uid_string; + gboolean contents_loaded, ret; + const char *key_value, *start_of_key_value; char *end; - uid_t uid = FALLBACK_MINIMAL_UID; - gint64 uid_as_number; + gint64 key_as_number; error = NULL; contents = NULL; + ret = FALSE; contents_loaded = g_file_get_contents (PATH_LOGIN_DEFS, &contents, NULL, &error); if (!contents_loaded) { g_debug ("unable to read " PATH_LOGIN_DEFS ": %s", error->message); @@ -595,36 +624,66 @@ goto out; } - uid_min_string = strstr (contents, "UID_MIN"); - - if (uid_min_string == NULL || - (uid_min_string != contents && uid_min_string[-1] != '\n')) { - g_debug (PATH_LOGIN_DEFS " does not have a UID_MIN field"); - goto out; - } - - start_of_uid_string = uid_min_string + strlen ("UID_MIN"); - - if (start_of_uid_string == '\0') { - g_debug (PATH_LOGIN_DEFS " contains UID_MIN key with no value"); - goto out; - } - - - uid_as_number = g_ascii_strtoll (start_of_uid_string, &end, 10); + if ( key == NULL ) { + g_debug ("undefined key to search for"); + goto out; + } + + key_value = strstr (contents, key); + + if (key_value == NULL || + (key_value != contents && key_value[-1] != '\n')) { + g_debug (PATH_LOGIN_DEFS " does not have a %s field", key); + goto out; + } + + start_of_key_value = key_value + strlen (key); + + if (start_of_key_value == '\0') { + g_debug (PATH_LOGIN_DEFS " contains %s key with no value", key); + goto out; + } + + + key_as_number = g_ascii_strtoll (start_of_key_value, &end, 10); if (!g_ascii_isspace (*end) && *end != '\0') { - g_debug (PATH_LOGIN_DEFS " contains non-numerical value for UID_MIN"); - goto out; - } - - if (uid_as_number < 0 || ((uid_t) uid_as_number) != uid_as_number) { - g_debug (PATH_LOGIN_DEFS " contains out-of-range value for UID_MIN"); - goto out; - } - - uid = (uid_t) uid_as_number; + g_debug (PATH_LOGIN_DEFS " contains non-numerical value for %s", key); + goto out; + } + + if (key_as_number < 0 || ((uid_t) key_as_number) != key_as_number) { + g_debug (PATH_LOGIN_DEFS " contains out-of-range value for %s", key); + goto out; + } + + *value = (uid_t) key_as_number; + ret = TRUE; out: g_free (contents); + return ret; +} + +static uid_t +get_minimal_uid (void) +{ + uid_t uid; + gboolean ret = get_value_from_login ("UID_MIN", &uid); + if (!ret) { + return FALLBACK_MINIMAL_UID; + } + + return uid; +} + +static uid_t +get_maximum_uid (void) +{ + uid_t uid; + gboolean ret = get_value_from_login ("UID_MAX", &uid); + if (!ret) { + return FALLBACK_MAXIMUM_UID; + } + return uid; } @@ -638,6 +697,8 @@ daemon->priv = DAEMON_GET_PRIVATE (daemon); daemon->priv->minimal_uid = get_minimal_uid (); + daemon->priv->maximum_uid = get_maximum_uid(); + daemon->priv->user_limit = FALSE; /* assume we have not yet hit the user limit */ daemon->priv->exclusions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,