summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Lortie <desrt@desrt.ca>2014-03-13 18:51:18 -0400
committerRay Strode <rstrode@redhat.com>2014-03-14 23:25:56 -0400
commitcdee3f55a5821cc76ad270b8c709a7bb1e3ae1b2 (patch)
tree6f86f6207690bdb70daba3081bd8e474fe512183
parent3863f54e5efe8c3f929dc93ea026a17d5855a786 (diff)
downloadaccountsservice-cdee3f55a5821cc76ad270b8c709a7bb1e3ae1b2.tar.gz
daemon: emulate fgetpwent() if we don't have it
We use fgetpwent directly on /etc/passwd in order to ensure we only get a list of local users (and not ones from the network directory service). Unfortunately, this function is not commonly found on non-GNU systems. Provide our own implementation of fgetpwent if the operating system does not provide it. https://bugs.freedesktop.org/show_bug.cgi?id=41747
-rw-r--r--configure.ac2
-rw-r--r--src/Makefile.am4
-rw-r--r--src/daemon.c4
-rw-r--r--src/fgetpwent.c108
4 files changed, 118 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 39c5b92..ee9dbcb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -187,6 +187,8 @@ AC_SUBST(WARN_CFLAGS)
AC_CHECK_HEADERS([shadow.h utmpx.h])
+AC_CHECK_FUNCS([fgetpwent])
+
dnl ---------------------------------------------------------------------------
dnl - gtk-doc Documentation
dnl ---------------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 6940f2d..30e5c8a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -47,6 +47,10 @@ accounts_daemon_LDADD = \
libaccounts-generated.la \
$(POLKIT_LIBS)
+EXTRA_DIST = \
+ fgetpwent.c \
+ $(NULL)
+
CLEANFILES = \
$(BUILT_SOURCES) \
*.gcda \
diff --git a/src/daemon.c b/src/daemon.c
index cb36f01..233f374 100644
--- a/src/daemon.c
+++ b/src/daemon.c
@@ -162,6 +162,10 @@ user_previous_login_free (UserPreviousLogin *previous_login)
g_free (previous_login);
}
+#ifndef HAVE_FGETPWENT
+#include "fgetpwent.c"
+#endif
+
static struct passwd *
entry_generator_wtmp (GHashTable *users,
gpointer *state)
diff --git a/src/fgetpwent.c b/src/fgetpwent.c
new file mode 100644
index 0000000..3a2d77c
--- /dev/null
+++ b/src/fgetpwent.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2013 Canonical Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the licence, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Ryan Lortie <desrt@desrt.ca>
+ */
+
+static gchar *
+fgetpwent_getline (FILE *fp)
+{
+ static GString str;
+
+ /* We could be "more clever" here and avoid the strlen() but this is a
+ * clear case of dumb is better.
+ */
+ str.len = 0;
+ while (!str.len || str.str[str.len - 1] != '\n')
+ {
+ if (str.allocated_len < str.len + 32)
+ {
+ str.allocated_len = str.len + 32;
+ str.str = g_realloc (str.str, str.allocated_len);
+ }
+
+ if (fgets (str.str + str.len, str.allocated_len - str.len, fp) == NULL)
+ return NULL;
+
+ str.len = strlen (str.str + str.len) + str.len;
+ }
+
+ /* chomp the '\n' */
+ str.str[str.len - 1] = '\0';
+
+ return str.str;
+}
+
+static struct passwd *
+fgetpwent (FILE *fp)
+{
+ static struct passwd pw;
+ guint64 intval;
+ gchar *line;
+
+ /* In case of failure, we ignore the line and start again */
+again:
+ line = fgetpwent_getline (fp);
+ if (!line)
+ return NULL;
+
+ while (g_ascii_isspace (*line))
+ line++;
+
+ /* comments, empty lines */
+ if (line[0] == '#' || line[0] == '\0')
+ goto again;
+
+ /* username */
+ pw.pw_name = line;
+ if (!(line = strchr (line, ':')))
+ goto again;
+ *line++ = '\0';
+
+ /* password */
+ pw.pw_passwd = line;
+ if (!(line = strchr (line, ':')))
+ goto again;
+ *line++ = '\0';
+
+ /* uid */
+ pw.pw_uid = intval = g_ascii_strtoull (line, &line, 10);
+ if (pw.pw_uid != intval || *line++ != ':')
+ goto again;
+
+ /* gid */
+ pw.pw_gid = intval = g_ascii_strtoull (line, &line, 10);
+ if (pw.pw_gid != intval || *line++ != ':')
+ goto again;
+
+ /* gecos */
+ pw.pw_gecos = line;
+ if (!(line = strchr (line, ':')))
+ goto again;
+ *line++ = '\0';
+
+ /* home directory */
+ pw.pw_dir = line;
+ if (!(line = strchr (line, ':')))
+ goto again;
+ *line++ = '\0';
+
+ /* shell */
+ pw.pw_shell = line;
+
+ return &pw;
+}