|
|
889f5f |
From 691d11c09d40cf6e9745e0c61e3fc59f77865e04 Mon Sep 17 00:00:00 2001
|
|
|
889f5f |
From: Ray Strode <rstrode@redhat.com>
|
|
|
889f5f |
Date: Thu, 23 Mar 2017 16:59:11 -0400
|
|
|
889f5f |
Subject: [PATCH] daemon: make sure explicitly requested users aren't lost on
|
|
|
889f5f |
reloads
|
|
|
889f5f |
|
|
|
889f5f |
Right now, a user proxy can suddenly become defunct if the
|
|
|
889f5f |
/etc/passwd file is updated or some other reason leads to a reload.
|
|
|
889f5f |
|
|
|
889f5f |
This commit makes sure that the objects associated with proxies
|
|
|
889f5f |
stick around across reloads.
|
|
|
889f5f |
---
|
|
|
889f5f |
src/daemon.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------
|
|
|
889f5f |
1 file changed, 67 insertions(+), 7 deletions(-)
|
|
|
889f5f |
|
|
|
889f5f |
diff --git a/src/daemon.c b/src/daemon.c
|
|
|
889f5f |
index 815e2c9..4586eff 100644
|
|
|
889f5f |
--- a/src/daemon.c
|
|
|
889f5f |
+++ b/src/daemon.c
|
|
|
889f5f |
@@ -41,78 +41,79 @@
|
|
|
889f5f |
|
|
|
889f5f |
#include <glib.h>
|
|
|
889f5f |
#include <glib/gi18n.h>
|
|
|
889f5f |
#include <glib-object.h>
|
|
|
889f5f |
#include <glib/gstdio.h>
|
|
|
889f5f |
#include <gio/gio.h>
|
|
|
889f5f |
#include <polkit/polkit.h>
|
|
|
889f5f |
|
|
|
889f5f |
#include "user-classify.h"
|
|
|
889f5f |
#include "daemon.h"
|
|
|
889f5f |
#include "util.h"
|
|
|
889f5f |
|
|
|
889f5f |
#define PATH_PASSWD "/etc/passwd"
|
|
|
889f5f |
#define PATH_SHADOW "/etc/shadow"
|
|
|
889f5f |
#define PATH_GROUP "/etc/group"
|
|
|
889f5f |
#define PATH_GDM_CUSTOM "/etc/gdm/custom.conf"
|
|
|
889f5f |
#ifdef HAVE_UTMPX_H
|
|
|
889f5f |
#define PATH_WTMP _PATH_WTMPX
|
|
|
889f5f |
#endif
|
|
|
889f5f |
|
|
|
889f5f |
enum {
|
|
|
889f5f |
PROP_0,
|
|
|
889f5f |
PROP_DAEMON_VERSION
|
|
|
889f5f |
};
|
|
|
889f5f |
|
|
|
889f5f |
struct DaemonPrivate {
|
|
|
889f5f |
GDBusConnection *bus_connection;
|
|
|
889f5f |
GDBusProxy *bus_proxy;
|
|
|
889f5f |
|
|
|
889f5f |
GHashTable *users;
|
|
|
889f5f |
+ GList *explicitly_requested_users;
|
|
|
889f5f |
|
|
|
889f5f |
User *autologin;
|
|
|
889f5f |
|
|
|
889f5f |
GFileMonitor *passwd_monitor;
|
|
|
889f5f |
GFileMonitor *shadow_monitor;
|
|
|
889f5f |
GFileMonitor *group_monitor;
|
|
|
889f5f |
GFileMonitor *gdm_monitor;
|
|
|
889f5f |
#ifdef HAVE_UTMPX_H
|
|
|
889f5f |
GFileMonitor *wtmp_monitor;
|
|
|
889f5f |
#endif
|
|
|
889f5f |
|
|
|
889f5f |
guint reload_id;
|
|
|
889f5f |
guint autologin_id;
|
|
|
889f5f |
|
|
|
889f5f |
PolkitAuthority *authority;
|
|
|
889f5f |
};
|
|
|
889f5f |
|
|
|
889f5f |
-typedef struct passwd * (* EntryGeneratorFunc) (GHashTable *, gpointer *, struct spwd **shadow_entry);
|
|
|
889f5f |
+typedef struct passwd * (* EntryGeneratorFunc) (Daemon *, GHashTable *, gpointer *, struct spwd **shadow_entry);
|
|
|
889f5f |
|
|
|
889f5f |
static void daemon_accounts_accounts_iface_init (AccountsAccountsIface *iface);
|
|
|
889f5f |
|
|
|
889f5f |
G_DEFINE_TYPE_WITH_CODE (Daemon, daemon, ACCOUNTS_TYPE_ACCOUNTS_SKELETON, G_IMPLEMENT_INTERFACE (ACCOUNTS_TYPE_ACCOUNTS, daemon_accounts_accounts_iface_init));
|
|
|
889f5f |
|
|
|
889f5f |
#define DAEMON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_DAEMON, DaemonPrivate))
|
|
|
889f5f |
|
|
|
889f5f |
static const GDBusErrorEntry accounts_error_entries[] =
|
|
|
889f5f |
{
|
|
|
889f5f |
{ ERROR_FAILED, "org.freedesktop.Accounts.Error.Failed" },
|
|
|
889f5f |
{ ERROR_USER_EXISTS, "org.freedesktop.Accounts.Error.UserExists" },
|
|
|
889f5f |
{ ERROR_USER_DOES_NOT_EXIST, "org.freedesktop.Accounts.Error.UserDoesNotExist" },
|
|
|
889f5f |
{ ERROR_PERMISSION_DENIED, "org.freedesktop.Accounts.Error.PermissionDenied" },
|
|
|
889f5f |
{ ERROR_NOT_SUPPORTED, "org.freedesktop.Accounts.Error.NotSupported" }
|
|
|
889f5f |
};
|
|
|
889f5f |
|
|
|
889f5f |
GQuark
|
|
|
889f5f |
error_quark (void)
|
|
|
889f5f |
{
|
|
|
889f5f |
static volatile gsize quark_volatile = 0;
|
|
|
889f5f |
|
|
|
889f5f |
g_dbus_error_register_error_domain ("accounts_error",
|
|
|
889f5f |
&quark_volatile,
|
|
|
889f5f |
accounts_error_entries,
|
|
|
889f5f |
G_N_ELEMENTS (accounts_error_entries));
|
|
|
889f5f |
|
|
|
889f5f |
return (GQuark) quark_volatile;
|
|
|
889f5f |
}
|
|
|
889f5f |
#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
|
|
|
889f5f |
|
|
|
889f5f |
@@ -265,61 +266,62 @@ wtmp_update_login_frequencies (GHashTable *users)
|
|
|
889f5f |
|
|
|
889f5f |
g_object_set (user, "login-frequency", accounting->frequency, NULL);
|
|
|
889f5f |
g_object_set (user, "login-time", accounting->time, NULL);
|
|
|
889f5f |
|
|
|
889f5f |
builder = g_variant_builder_new (G_VARIANT_TYPE ("a(xxa{sv})"));
|
|
|
889f5f |
for (l = g_list_last (accounting->previous_logins); l != NULL; l = l->prev) {
|
|
|
889f5f |
previous_login = l->data;
|
|
|
889f5f |
|
|
|
889f5f |
builder2 = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
|
|
|
889f5f |
g_variant_builder_add (builder2, "{sv}", "type", g_variant_new_string (previous_login->id));
|
|
|
889f5f |
g_variant_builder_add (builder, "(xxa{sv})", previous_login->login_time, previous_login->logout_time, builder2);
|
|
|
889f5f |
g_variant_builder_unref (builder2);
|
|
|
889f5f |
}
|
|
|
889f5f |
g_object_set (user, "login-history", g_variant_new ("a(xxa{sv})", builder), NULL);
|
|
|
889f5f |
g_variant_builder_unref (builder);
|
|
|
889f5f |
g_list_free_full (accounting->previous_logins, (GDestroyNotify) user_previous_login_free);
|
|
|
889f5f |
|
|
|
889f5f |
user_changed (user);
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
g_hash_table_unref (login_hash);
|
|
|
889f5f |
g_hash_table_unref (logout_hash);
|
|
|
889f5f |
}
|
|
|
889f5f |
#endif /* HAVE_UTMPX_H */
|
|
|
889f5f |
|
|
|
889f5f |
#ifndef MAX_LOCAL_USERS
|
|
|
889f5f |
#define MAX_LOCAL_USERS 50
|
|
|
889f5f |
#endif
|
|
|
889f5f |
|
|
|
889f5f |
static struct passwd *
|
|
|
889f5f |
-entry_generator_fgetpwent (GHashTable *users,
|
|
|
889f5f |
+entry_generator_fgetpwent (Daemon *daemon,
|
|
|
889f5f |
+ GHashTable *users,
|
|
|
889f5f |
gpointer *state,
|
|
|
889f5f |
struct spwd **spent)
|
|
|
889f5f |
{
|
|
|
889f5f |
struct passwd *pwent;
|
|
|
889f5f |
|
|
|
889f5f |
struct {
|
|
|
889f5f |
struct spwd spbuf;
|
|
|
889f5f |
char buf[1024];
|
|
|
889f5f |
} *shadow_entry_buffers;
|
|
|
889f5f |
|
|
|
889f5f |
struct {
|
|
|
889f5f |
FILE *fp;
|
|
|
889f5f |
GHashTable *users;
|
|
|
889f5f |
} *generator_state;
|
|
|
889f5f |
|
|
|
889f5f |
/* First iteration */
|
|
|
889f5f |
if (*state == NULL) {
|
|
|
889f5f |
GHashTable *shadow_users = NULL;
|
|
|
889f5f |
FILE *fp;
|
|
|
889f5f |
struct spwd *shadow_entry;
|
|
|
889f5f |
|
|
|
889f5f |
fp = fopen (PATH_SHADOW, "r");
|
|
|
889f5f |
if (fp == NULL) {
|
|
|
889f5f |
g_warning ("Unable to open %s: %s", PATH_SHADOW, g_strerror (errno));
|
|
|
889f5f |
return NULL;
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
shadow_users = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
|
|
889f5f |
|
|
|
889f5f |
do {
|
|
|
889f5f |
@@ -358,61 +360,62 @@ entry_generator_fgetpwent (GHashTable *users,
|
|
|
889f5f |
generator_state->users = shadow_users;
|
|
|
889f5f |
|
|
|
889f5f |
*state = generator_state;
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
/* Every iteration */
|
|
|
889f5f |
generator_state = *state;
|
|
|
889f5f |
|
|
|
889f5f |
if (g_hash_table_size (users) < MAX_LOCAL_USERS) {
|
|
|
889f5f |
pwent = fgetpwent (generator_state->fp);
|
|
|
889f5f |
if (pwent != NULL) {
|
|
|
889f5f |
shadow_entry_buffers = g_hash_table_lookup (generator_state->users, pwent->pw_name);
|
|
|
889f5f |
|
|
|
889f5f |
if (shadow_entry_buffers != NULL) {
|
|
|
889f5f |
*spent = &shadow_entry_buffers->spbuf;
|
|
|
889f5f |
return pwent;
|
|
|
889f5f |
}
|
|
|
889f5f |
}
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
/* Last iteration */
|
|
|
889f5f |
fclose (generator_state->fp);
|
|
|
889f5f |
g_hash_table_unref (generator_state->users);
|
|
|
889f5f |
g_free (generator_state);
|
|
|
889f5f |
*state = NULL;
|
|
|
889f5f |
|
|
|
889f5f |
return NULL;
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
static struct passwd *
|
|
|
889f5f |
-entry_generator_cachedir (GHashTable *users,
|
|
|
889f5f |
+entry_generator_cachedir (Daemon *daemon,
|
|
|
889f5f |
+ GHashTable *users,
|
|
|
889f5f |
gpointer *state,
|
|
|
889f5f |
struct spwd **shadow_entry)
|
|
|
889f5f |
{
|
|
|
889f5f |
struct passwd *pwent;
|
|
|
889f5f |
const gchar *name;
|
|
|
889f5f |
GError *error = NULL;
|
|
|
889f5f |
gchar *filename;
|
|
|
889f5f |
gboolean regular;
|
|
|
889f5f |
GHashTableIter iter;
|
|
|
889f5f |
GKeyFile *key_file;
|
|
|
889f5f |
User *user;
|
|
|
889f5f |
GDir *dir;
|
|
|
889f5f |
|
|
|
889f5f |
/* First iteration */
|
|
|
889f5f |
if (*state == NULL) {
|
|
|
889f5f |
*state = g_dir_open (USERDIR, 0, &error);
|
|
|
889f5f |
if (error != NULL) {
|
|
|
889f5f |
if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
|
|
|
889f5f |
g_warning ("couldn't list user cache directory: %s", USERDIR);
|
|
|
889f5f |
g_error_free (error);
|
|
|
889f5f |
return NULL;
|
|
|
889f5f |
}
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
/* Every iteration */
|
|
|
889f5f |
|
|
|
889f5f |
/*
|
|
|
889f5f |
* Use names of files of regular type to lookup information
|
|
|
889f5f |
* about each user. Loop until we find something valid.
|
|
|
889f5f |
*/
|
|
|
889f5f |
@@ -430,145 +433,194 @@ entry_generator_cachedir (GHashTable *users,
|
|
|
889f5f |
if (regular) {
|
|
|
889f5f |
pwent = getpwnam (name);
|
|
|
889f5f |
if (pwent == NULL) {
|
|
|
889f5f |
g_debug ("user '%s' in cache dir but not present on system", name);
|
|
|
889f5f |
} else {
|
|
|
889f5f |
*shadow_entry = getspnam (pwent->pw_name);
|
|
|
889f5f |
|
|
|
889f5f |
return pwent;
|
|
|
889f5f |
}
|
|
|
889f5f |
}
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
/* Last iteration */
|
|
|
889f5f |
g_dir_close (dir);
|
|
|
889f5f |
|
|
|
889f5f |
/* Update all the users from the files in the cache dir */
|
|
|
889f5f |
g_hash_table_iter_init (&iter, users);
|
|
|
889f5f |
while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&user)) {
|
|
|
889f5f |
filename = g_build_filename (USERDIR, name, NULL);
|
|
|
889f5f |
key_file = g_key_file_new ();
|
|
|
889f5f |
if (g_key_file_load_from_file (key_file, filename, 0, NULL))
|
|
|
889f5f |
user_update_from_keyfile (user, key_file);
|
|
|
889f5f |
g_key_file_unref (key_file);
|
|
|
889f5f |
g_free (filename);
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
*state = NULL;
|
|
|
889f5f |
return NULL;
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
+static struct passwd *
|
|
|
889f5f |
+entry_generator_requested_users (Daemon *daemon,
|
|
|
889f5f |
+ GHashTable *users,
|
|
|
889f5f |
+ gpointer *state,
|
|
|
889f5f |
+ struct spwd **shadow_entry)
|
|
|
889f5f |
+{
|
|
|
889f5f |
+ struct passwd *pwent;
|
|
|
889f5f |
+ GList *node;
|
|
|
889f5f |
+
|
|
|
889f5f |
+ /* First iteration */
|
|
|
889f5f |
+ if (*state == NULL) {
|
|
|
889f5f |
+ *state = daemon->priv->explicitly_requested_users;
|
|
|
889f5f |
+ }
|
|
|
889f5f |
+
|
|
|
889f5f |
+ /* Every iteration */
|
|
|
889f5f |
+
|
|
|
889f5f |
+ if (g_hash_table_size (users) < MAX_LOCAL_USERS) {
|
|
|
889f5f |
+ node = *state;
|
|
|
889f5f |
+ while (node != NULL) {
|
|
|
889f5f |
+ const char *name;
|
|
|
889f5f |
+
|
|
|
889f5f |
+ name = node->data;
|
|
|
889f5f |
+ node = node->next;
|
|
|
889f5f |
+
|
|
|
889f5f |
+ *state = node;
|
|
|
889f5f |
+
|
|
|
889f5f |
+ if (!g_hash_table_lookup (users, name)) {
|
|
|
889f5f |
+ pwent = getpwnam (name);
|
|
|
889f5f |
+ if (pwent == NULL) {
|
|
|
889f5f |
+ g_debug ("user '%s' requested previously but not present on system", name);
|
|
|
889f5f |
+ } else {
|
|
|
889f5f |
+ *shadow_entry = getspnam (pwent->pw_name);
|
|
|
889f5f |
+
|
|
|
889f5f |
+ return pwent;
|
|
|
889f5f |
+ }
|
|
|
889f5f |
+ }
|
|
|
889f5f |
+ }
|
|
|
889f5f |
+ }
|
|
|
889f5f |
+
|
|
|
889f5f |
+ /* Last iteration */
|
|
|
889f5f |
+
|
|
|
889f5f |
+ *state = NULL;
|
|
|
889f5f |
+ return NULL;
|
|
|
889f5f |
+}
|
|
|
889f5f |
+
|
|
|
889f5f |
static void
|
|
|
889f5f |
load_entries (Daemon *daemon,
|
|
|
889f5f |
GHashTable *users,
|
|
|
889f5f |
+ gboolean allow_system_users,
|
|
|
889f5f |
EntryGeneratorFunc entry_generator)
|
|
|
889f5f |
{
|
|
|
889f5f |
gpointer generator_state = NULL;
|
|
|
889f5f |
struct passwd *pwent;
|
|
|
889f5f |
struct spwd *spent = NULL;
|
|
|
889f5f |
User *user = NULL;
|
|
|
889f5f |
|
|
|
889f5f |
g_assert (entry_generator != NULL);
|
|
|
889f5f |
|
|
|
889f5f |
for (;;) {
|
|
|
889f5f |
spent = NULL;
|
|
|
889f5f |
- pwent = entry_generator (users, &generator_state, &spent);
|
|
|
889f5f |
+ pwent = entry_generator (daemon, users, &generator_state, &spent);
|
|
|
889f5f |
if (pwent == NULL)
|
|
|
889f5f |
break;
|
|
|
889f5f |
|
|
|
889f5f |
/* Skip system users... */
|
|
|
889f5f |
- if (!user_classify_is_human (pwent->pw_uid, pwent->pw_name, pwent->pw_shell, spent? spent->sp_pwdp : NULL)) {
|
|
|
889f5f |
+ if (!allow_system_users && !user_classify_is_human (pwent->pw_uid, pwent->pw_name, pwent->pw_shell, spent? spent->sp_pwdp : NULL)) {
|
|
|
889f5f |
g_debug ("skipping user: %s", pwent->pw_name);
|
|
|
889f5f |
continue;
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
/* ignore duplicate entries */
|
|
|
889f5f |
if (g_hash_table_lookup (users, pwent->pw_name)) {
|
|
|
889f5f |
continue;
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
user = g_hash_table_lookup (daemon->priv->users, pwent->pw_name);
|
|
|
889f5f |
if (user == NULL) {
|
|
|
889f5f |
user = user_new (daemon, pwent->pw_uid);
|
|
|
889f5f |
} else {
|
|
|
889f5f |
g_object_ref (user);
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
/* freeze & update users not already in the new list */
|
|
|
889f5f |
g_object_freeze_notify (G_OBJECT (user));
|
|
|
889f5f |
user_update_from_pwent (user, pwent, spent);
|
|
|
889f5f |
|
|
|
889f5f |
g_hash_table_insert (users, g_strdup (user_get_user_name (user)), user);
|
|
|
889f5f |
g_debug ("loaded user: %s", user_get_user_name (user));
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
/* Generator should have cleaned up */
|
|
|
889f5f |
g_assert (generator_state == NULL);
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
static GHashTable *
|
|
|
889f5f |
create_users_hash_table (void)
|
|
|
889f5f |
{
|
|
|
889f5f |
return g_hash_table_new_full (g_str_hash,
|
|
|
889f5f |
g_str_equal,
|
|
|
889f5f |
g_free,
|
|
|
889f5f |
g_object_unref);
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
static void
|
|
|
889f5f |
reload_users (Daemon *daemon)
|
|
|
889f5f |
{
|
|
|
889f5f |
GHashTable *users;
|
|
|
889f5f |
GHashTable *old_users;
|
|
|
889f5f |
GHashTable *local;
|
|
|
889f5f |
GHashTableIter iter;
|
|
|
889f5f |
gpointer name;
|
|
|
889f5f |
User *user;
|
|
|
889f5f |
|
|
|
889f5f |
/* Track the users that we saw during our (re)load */
|
|
|
889f5f |
users = create_users_hash_table ();
|
|
|
889f5f |
|
|
|
889f5f |
/*
|
|
|
889f5f |
* NOTE: As we load data from all the sources, notifies are
|
|
|
889f5f |
* frozen in load_entries() and then thawed as we process
|
|
|
889f5f |
* them below.
|
|
|
889f5f |
*/
|
|
|
889f5f |
|
|
|
889f5f |
/* Load the local users into our hash table */
|
|
|
889f5f |
- load_entries (daemon, users, entry_generator_fgetpwent);
|
|
|
889f5f |
+ load_entries (daemon, users, FALSE, entry_generator_fgetpwent);
|
|
|
889f5f |
local = g_hash_table_new (g_str_hash, g_str_equal);
|
|
|
889f5f |
g_hash_table_iter_init (&iter, users);
|
|
|
889f5f |
while (g_hash_table_iter_next (&iter, &name, NULL))
|
|
|
889f5f |
g_hash_table_add (local, name);
|
|
|
889f5f |
|
|
|
889f5f |
+ /* and add users to hash table that were explicitly requested */
|
|
|
889f5f |
+ load_entries (daemon, users, TRUE, entry_generator_requested_users);
|
|
|
889f5f |
+
|
|
|
889f5f |
/* Now add/update users from other sources, possibly non-local */
|
|
|
889f5f |
- load_entries (daemon, users, entry_generator_cachedir);
|
|
|
889f5f |
+ load_entries (daemon, users, FALSE, entry_generator_cachedir);
|
|
|
889f5f |
|
|
|
889f5f |
#ifdef HAVE_UTMPX_H
|
|
|
889f5f |
wtmp_update_login_frequencies (users);
|
|
|
889f5f |
#endif
|
|
|
889f5f |
|
|
|
889f5f |
/* Mark which users are local, which are not */
|
|
|
889f5f |
g_hash_table_iter_init (&iter, users);
|
|
|
889f5f |
while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user))
|
|
|
889f5f |
user_update_local_account_property (user, g_hash_table_lookup (local, name) != NULL);
|
|
|
889f5f |
|
|
|
889f5f |
g_hash_table_destroy (local);
|
|
|
889f5f |
|
|
|
889f5f |
/* Swap out the users */
|
|
|
889f5f |
old_users = daemon->priv->users;
|
|
|
889f5f |
daemon->priv->users = users;
|
|
|
889f5f |
|
|
|
889f5f |
/* Remove all the old users */
|
|
|
889f5f |
g_hash_table_iter_init (&iter, old_users);
|
|
|
889f5f |
while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) {
|
|
|
889f5f |
if (!g_hash_table_lookup (users, name)) {
|
|
|
889f5f |
user_unregister (user);
|
|
|
889f5f |
accounts_accounts_emit_user_deleted (ACCOUNTS_ACCOUNTS (daemon),
|
|
|
889f5f |
user_get_object_path (user));
|
|
|
889f5f |
}
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
/* Register all the new users */
|
|
|
889f5f |
g_hash_table_iter_init (&iter, users);
|
|
|
889f5f |
while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) {
|
|
|
889f5f |
if (!g_hash_table_lookup (old_users, name)) {
|
|
|
889f5f |
@@ -757,60 +809,62 @@ daemon_init (Daemon *daemon)
|
|
|
889f5f |
|
|
|
889f5f |
#ifdef HAVE_UTMPX_H
|
|
|
889f5f |
daemon->priv->wtmp_monitor = setup_monitor (daemon,
|
|
|
889f5f |
PATH_WTMP,
|
|
|
889f5f |
on_users_monitor_changed);
|
|
|
889f5f |
#endif
|
|
|
889f5f |
|
|
|
889f5f |
daemon->priv->gdm_monitor = setup_monitor (daemon,
|
|
|
889f5f |
PATH_GDM_CUSTOM,
|
|
|
889f5f |
on_gdm_monitor_changed);
|
|
|
889f5f |
|
|
|
889f5f |
queue_reload_users (daemon);
|
|
|
889f5f |
queue_reload_autologin (daemon);
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
static void
|
|
|
889f5f |
daemon_finalize (GObject *object)
|
|
|
889f5f |
{
|
|
|
889f5f |
Daemon *daemon;
|
|
|
889f5f |
|
|
|
889f5f |
g_return_if_fail (IS_DAEMON (object));
|
|
|
889f5f |
|
|
|
889f5f |
daemon = DAEMON (object);
|
|
|
889f5f |
|
|
|
889f5f |
if (daemon->priv->bus_proxy != NULL)
|
|
|
889f5f |
g_object_unref (daemon->priv->bus_proxy);
|
|
|
889f5f |
|
|
|
889f5f |
if (daemon->priv->bus_connection != NULL)
|
|
|
889f5f |
g_object_unref (daemon->priv->bus_connection);
|
|
|
889f5f |
|
|
|
889f5f |
+ g_list_free_full (daemon->priv->explicitly_requested_users, g_free);
|
|
|
889f5f |
+
|
|
|
889f5f |
g_hash_table_destroy (daemon->priv->users);
|
|
|
889f5f |
|
|
|
889f5f |
G_OBJECT_CLASS (daemon_parent_class)->finalize (object);
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
static gboolean
|
|
|
889f5f |
register_accounts_daemon (Daemon *daemon)
|
|
|
889f5f |
{
|
|
|
889f5f |
GError *error = NULL;
|
|
|
889f5f |
|
|
|
889f5f |
daemon->priv->authority = polkit_authority_get_sync (NULL, &error);
|
|
|
889f5f |
|
|
|
889f5f |
if (daemon->priv->authority == NULL) {
|
|
|
889f5f |
if (error != NULL) {
|
|
|
889f5f |
g_critical ("error getting polkit authority: %s", error->message);
|
|
|
889f5f |
g_error_free (error);
|
|
|
889f5f |
}
|
|
|
889f5f |
goto error;
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
daemon->priv->bus_connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
|
|
889f5f |
if (daemon->priv->bus_connection == NULL) {
|
|
|
889f5f |
if (error != NULL) {
|
|
|
889f5f |
g_critical ("error getting system bus: %s", error->message);
|
|
|
889f5f |
g_error_free (error);
|
|
|
889f5f |
}
|
|
|
889f5f |
goto error;
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon),
|
|
|
889f5f |
@@ -878,84 +932,90 @@ add_new_user_for_pwent (Daemon *daemon,
|
|
|
889f5f |
user_register (user);
|
|
|
889f5f |
|
|
|
889f5f |
g_hash_table_insert (daemon->priv->users,
|
|
|
889f5f |
g_strdup (user_get_user_name (user)),
|
|
|
889f5f |
user);
|
|
|
889f5f |
|
|
|
889f5f |
accounts_accounts_emit_user_added (ACCOUNTS_ACCOUNTS (daemon), user_get_object_path (user));
|
|
|
889f5f |
|
|
|
889f5f |
return user;
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
User *
|
|
|
889f5f |
daemon_local_find_user_by_id (Daemon *daemon,
|
|
|
889f5f |
uid_t uid)
|
|
|
889f5f |
{
|
|
|
889f5f |
User *user;
|
|
|
889f5f |
struct passwd *pwent;
|
|
|
889f5f |
|
|
|
889f5f |
pwent = getpwuid (uid);
|
|
|
889f5f |
if (pwent == NULL) {
|
|
|
889f5f |
g_debug ("unable to lookup uid %d", (int)uid);
|
|
|
889f5f |
return NULL;
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
user = g_hash_table_lookup (daemon->priv->users, pwent->pw_name);
|
|
|
889f5f |
|
|
|
889f5f |
if (user == NULL) {
|
|
|
889f5f |
struct spwd *spent;
|
|
|
889f5f |
spent = getspnam (pwent->pw_name);
|
|
|
889f5f |
user = add_new_user_for_pwent (daemon, pwent, spent);
|
|
|
889f5f |
+
|
|
|
889f5f |
+ daemon->priv->explicitly_requested_users = g_list_append (daemon->priv->explicitly_requested_users,
|
|
|
889f5f |
+ g_strdup (pwent->pw_name));
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
return user;
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
User *
|
|
|
889f5f |
daemon_local_find_user_by_name (Daemon *daemon,
|
|
|
889f5f |
const gchar *name)
|
|
|
889f5f |
{
|
|
|
889f5f |
User *user;
|
|
|
889f5f |
struct passwd *pwent;
|
|
|
889f5f |
|
|
|
889f5f |
pwent = getpwnam (name);
|
|
|
889f5f |
if (pwent == NULL) {
|
|
|
889f5f |
g_debug ("unable to lookup name %s: %s", name, g_strerror (errno));
|
|
|
889f5f |
return NULL;
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
user = g_hash_table_lookup (daemon->priv->users, pwent->pw_name);
|
|
|
889f5f |
|
|
|
889f5f |
if (user == NULL) {
|
|
|
889f5f |
struct spwd *spent;
|
|
|
889f5f |
spent = getspnam (pwent->pw_name);
|
|
|
889f5f |
user = add_new_user_for_pwent (daemon, pwent, spent);
|
|
|
889f5f |
+
|
|
|
889f5f |
+ daemon->priv->explicitly_requested_users = g_list_append (daemon->priv->explicitly_requested_users,
|
|
|
889f5f |
+ g_strdup (pwent->pw_name));
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
return user;
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
User *
|
|
|
889f5f |
daemon_local_get_automatic_login_user (Daemon *daemon)
|
|
|
889f5f |
{
|
|
|
889f5f |
return daemon->priv->autologin;
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
static gboolean
|
|
|
889f5f |
daemon_find_user_by_id (AccountsAccounts *accounts,
|
|
|
889f5f |
GDBusMethodInvocation *context,
|
|
|
889f5f |
gint64 uid)
|
|
|
889f5f |
{
|
|
|
889f5f |
Daemon *daemon = (Daemon*)accounts;
|
|
|
889f5f |
User *user;
|
|
|
889f5f |
|
|
|
889f5f |
user = daemon_local_find_user_by_id (daemon, uid);
|
|
|
889f5f |
|
|
|
889f5f |
if (user) {
|
|
|
889f5f |
accounts_accounts_complete_find_user_by_id (NULL, context, user_get_object_path (user));
|
|
|
889f5f |
}
|
|
|
889f5f |
else {
|
|
|
889f5f |
throw_error (context, ERROR_FAILED, "Failed to look up user with uid %d.", (int)uid);
|
|
|
889f5f |
}
|
|
|
889f5f |
|
|
|
889f5f |
return TRUE;
|
|
|
889f5f |
}
|
|
|
889f5f |
--
|
|
|
889f5f |
2.12.0
|
|
|
889f5f |
|