summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2016-06-28 15:43:08 -0400
committerRay Strode <rstrode@redhat.com>2016-06-30 10:17:58 -0400
commit98f428709e94e5a6aece070c74a8603dee7e58e2 (patch)
tree7ae9aaed03b4ca60402748a3af312e5173d5efa6
parentc85b41d3f82a01ec8bea48b67e1220e81116f456 (diff)
daemon: get local users from /etc/shadow not /etc/passwd
For some sites, it's common practice to rsync around large /etc/passwd files containing the password entries for remote users. That means accountsservices' "assume /etc/passwd is local users" heuristic falls over. This commit changes it to only treat users in /etc/shadow as local. https://bugs.freedesktop.org/show_bug.cgi?id=48177
-rw-r--r--src/daemon.c59
1 files changed, 53 insertions, 6 deletions
diff --git a/src/daemon.c b/src/daemon.c
index e62e124..1b2bacd 100644
--- a/src/daemon.c
+++ b/src/daemon.c
@@ -29,6 +29,9 @@
#include <fcntl.h>
#include <sys/wait.h>
#include <pwd.h>
+#ifdef HAVE_SHADOW_H
+#include <shadow.h>
+#endif
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
@@ -137,27 +140,71 @@ entry_generator_fgetpwent (GHashTable *users,
gpointer *state)
{
struct passwd *pwent;
- FILE *fp;
+ struct {
+ FILE *fp;
+ GHashTable *users;
+ } *generator_state;
/* First iteration */
if (*state == NULL) {
- *state = fp = fopen (PATH_PASSWD, "r");
+ GHashTable *shadow_users = NULL;
+ FILE *fp;
+#ifdef HAVE_SHADOW_H
+ struct spwd *shadow_entry;
+
+ fp = fopen (PATH_SHADOW, "r");
+ if (fp == NULL) {
+ g_warning ("Unable to open %s: %s", PATH_SHADOW, g_strerror (errno));
+ return NULL;
+ }
+
+ shadow_users = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ do {
+ shadow_entry = fgetspent (fp);
+ if (shadow_entry != NULL) {
+ g_hash_table_add (shadow_users, g_strdup (shadow_entry->sp_namp));
+ } else if (errno != EINTR) {
+ break;
+ }
+ } while (shadow_entry != NULL);
+
+ fclose (fp);
+
+ if (g_hash_table_size (shadow_users) == 0) {
+ g_clear_pointer (&shadow_users, g_hash_table_unref);
+ return NULL;
+ }
+#endif
+
+ fp = fopen (PATH_PASSWD, "r");
if (fp == NULL) {
+ g_clear_pointer (&shadow_users, g_hash_table_unref);
g_warning ("Unable to open %s: %s", PATH_PASSWD, g_strerror (errno));
return NULL;
}
+
+ generator_state = g_malloc0 (sizeof (generator_state));
+ generator_state->fp = fp;
+ generator_state->users = shadow_users;
+
+ *state = generator_state;
}
/* Every iteration */
- fp = *state;
- pwent = fgetpwent (fp);
+ generator_state = *state;
+ pwent = fgetpwent (generator_state->fp);
if (pwent != NULL) {
- return pwent;
+ if (!generator_state->users || g_hash_table_lookup (generator_state->users, pwent->pw_name))
+ return pwent;
}
/* Last iteration */
- fclose (fp);
+ fclose (generator_state->fp);
+ g_hash_table_unref (generator_state->users);
+ g_free (generator_state);
*state = NULL;
+
return NULL;
}