summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorRobert Ancell <robert.ancell@canonical.com>2012-03-20 16:11:28 +1100
committerRobert Ancell <robert.ancell@canonical.com>2012-03-20 16:11:28 +1100
commit89a42458fad356f36742b09e04be686092e698dd (patch)
tree5d05625c6ae79784ce51bab9b2d553ef599e0c60 /tests
parentf8841d64f28da418060092a8e181e0693906b23e (diff)
downloadlightdm-89a42458fad356f36742b09e04be686092e698dd.tar.gz
Call initgroups before pam_setcred - this allows pam_setcred to change group membership correctly
Diffstat (limited to 'tests')
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/scripts/group-membership.conf34
-rw-r--r--tests/src/X.c11
-rw-r--r--tests/src/guest-account.c18
-rw-r--r--tests/src/libsystem.c183
-rw-r--r--tests/src/test-runner.c28
-rw-r--r--tests/src/test-session.c29
-rwxr-xr-xtests/test-group-membership2
8 files changed, 281 insertions, 26 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 1912ff68..a26996e8 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -22,6 +22,7 @@ TESTS = \
test-autologin-guest \
test-autologin-guest-fail-setup-script \
test-autologin-guest-logout \
+ test-group-membership \
test-session-stdout \
test-session-stderr \
test-xauthority \
@@ -158,6 +159,7 @@ EXTRA_DIST = \
scripts/greeter-fail-start.conf \
scripts/greeter-not-installed.conf \
scripts/greeter-xserver-crash.conf \
+ scripts/group-membership.conf \
scripts/headless.conf \
scripts/home-dir-on-authenticate.conf \
scripts/keyboard-layout.conf \
diff --git a/tests/scripts/group-membership.conf b/tests/scripts/group-membership.conf
new file mode 100644
index 00000000..70f5afd3
--- /dev/null
+++ b/tests/scripts/group-membership.conf
@@ -0,0 +1,34 @@
+#
+# Check group membership is correctly set up
+#
+
+[LightDM]
+minimum-display-number=50
+
+[SeatDefaults]
+autologin-user=group-member
+
+#?RUNNER DAEMON-START
+
+# X server starts
+#?XSERVER :50 START
+#?XSERVER :50 INDICATE-READY
+
+# LightDM connects to X server
+#?XSERVER :50 ACCEPT-CONNECT
+
+# Session starts
+#?SESSION :50 START USER=group-member
+#?XSERVER :50 ACCEPT-CONNECT
+#?SESSION :50 CONNECT-XSERVER
+
+# Check we belong to the group for our user and the special group set by PAM
+#?*SESSION :50 LIST-GROUPS
+#?SESSION :50 LIST-GROUPS GROUPS=group-member,test-group
+
+# Cleanup
+#?*STOP-DAEMON
+# Don't know what order they will terminate
+#?(SESSION :50 TERMINATE SIGNAL=15|XSERVER :50 TERMINATE SIGNAL=15)
+#?(SESSION :50 TERMINATE SIGNAL=15|XSERVER :50 TERMINATE SIGNAL=15)
+#?RUNNER DAEMON-EXIT STATUS=0
diff --git a/tests/src/X.c b/tests/src/X.c
index b11ea977..a6d846d6 100644
--- a/tests/src/X.c
+++ b/tests/src/X.c
@@ -348,21 +348,12 @@ main (int argc, char **argv)
if (g_getenv ("LIGHTDM_TEST_CONFIG"))
g_key_file_load_from_file (config, g_getenv ("LIGHTDM_TEST_CONFIG"), G_KEY_FILE_NONE, NULL);
- return_lock = g_build_filename (g_getenv ("LIGHTDM_TEST_HOME_DIR"), ".xserver-returned", NULL);
- f = fopen (return_lock, "r");
- if (f == NULL && g_key_file_has_key (config, "test-xserver-config", "return-value", NULL))
+ if (g_key_file_has_key (config, "test-xserver-config", "return-value", NULL))
{
int return_value = g_key_file_get_integer (config, "test-xserver-config", "return-value", NULL);
status_notify ("XSERVER :%d EXIT CODE=%d", display_number, return_value);
-
- /* Write lock to stop repeatedly exiting */
- f = fopen (return_lock, "w");
- fclose (f);
-
return return_value;
}
- if (f != NULL)
- fclose (f);
lock_path = g_strdup_printf ("/tmp/.X%d-lock", display_number);
lock_file = open (lock_path, O_CREAT | O_EXCL | O_WRONLY, 0444);
diff --git a/tests/src/guest-account.c b/tests/src/guest-account.c
index b736943c..9b851c31 100644
--- a/tests/src/guest-account.c
+++ b/tests/src/guest-account.c
@@ -17,6 +17,8 @@ request_cb (const gchar *message)
int
main (int argc, char **argv)
{
+ gchar *passwd_path;
+
g_type_init ();
status_connect (request_cb);
@@ -25,6 +27,8 @@ main (int argc, char **argv)
if (g_getenv ("LIGHTDM_TEST_CONFIG"))
g_key_file_load_from_file (config, g_getenv ("LIGHTDM_TEST_CONFIG"), G_KEY_FILE_NONE, NULL);
+ passwd_path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "passwd", NULL);
+
if (argc == 2 && strcmp (argv[1], "add") == 0)
{
gchar *home_dir, *username, line[1024];
@@ -32,7 +36,7 @@ main (int argc, char **argv)
FILE *passwd;
/* Create a unique name */
- home_dir = g_strdup_printf ("%s/guest-XXXXXX", g_getenv ("LIGHTDM_TEST_HOME_DIR"));
+ home_dir = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "home", "guest-XXXXXX", NULL);
if (!mkdtemp (home_dir))
{
g_printerr ("Failed to create home directory %s: %s\n", home_dir, strerror (errno));
@@ -41,7 +45,7 @@ main (int argc, char **argv)
username = strrchr (home_dir, '/') + 1;
/* Get the largest UID */
- passwd = fopen (g_getenv ("LIGHTDM_TEST_PASSWD_FILE"), "r");
+ passwd = fopen (passwd_path, "r");
if (passwd)
{
while (fgets (line, 1024, passwd))
@@ -59,7 +63,7 @@ main (int argc, char **argv)
}
/* Add a new account to the passwd file */
- passwd = fopen (g_getenv ("LIGHTDM_TEST_PASSWD_FILE"), "a");
+ passwd = fopen (passwd_path, "a");
fprintf (passwd, "%s::%d:%d:Guest Account:%s:/bin/sh\n", username, max_uid+1, max_uid+1, home_dir);
fclose (passwd);
@@ -80,8 +84,8 @@ main (int argc, char **argv)
status_notify ("GUEST-ACCOUNT REMOVE USERNAME=%s", username);
/* Open a new file for writing */
- passwd = fopen (g_getenv ("LIGHTDM_TEST_PASSWD_FILE"), "r");
- path = g_strdup_printf ("%s~", g_getenv ("LIGHTDM_TEST_PASSWD_FILE"));
+ passwd = fopen (passwd_path, "r");
+ path = g_strdup_printf ("%s~", passwd_path);
new_passwd = fopen (path, "w");
/* Copy the old file, omitting our entry */
@@ -95,10 +99,10 @@ main (int argc, char **argv)
fclose (new_passwd);
/* Move the new file on the old one */
- rename (path, g_getenv ("LIGHTDM_TEST_PASSWD_FILE"));
+ rename (path, passwd_path);
/* Delete home directory */
- gchar *command = g_strdup_printf ("rm -r %s/%s", g_getenv ("LIGHTDM_TEST_HOME_DIR"), username);
+ gchar *command = g_strdup_printf ("rm -r %s/home/%s", g_getenv ("LIGHTDM_TEST_ROOT"), username);
if (system (command))
perror ("Failed to delete temp directory");
diff --git a/tests/src/libsystem.c b/tests/src/libsystem.c
index ca3cd66d..184f8a66 100644
--- a/tests/src/libsystem.c
+++ b/tests/src/libsystem.c
@@ -1,7 +1,9 @@
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include <sys/types.h>
#include <pwd.h>
+#include <grp.h>
#include <security/pam_appl.h>
#include <unistd.h>
#include <fcntl.h>
@@ -19,6 +21,8 @@ static int console_fd = -1;
static GList *user_entries = NULL;
static GList *getpwent_link = NULL;
+static GList *group_entries = NULL;
+
struct pam_handle
{
char *service_name;
@@ -43,6 +47,61 @@ geteuid (void)
int
initgroups (const char *user, gid_t group)
{
+ gid_t g[1];
+
+ g[0] = group;
+ setgroups (1, g);
+
+ return 0;
+}
+
+int
+getgroups (int size, gid_t list[])
+{
+ const gchar *group_list;
+ gchar **groups;
+ gint groups_length;
+
+ /* Get groups we are a member of */
+ group_list = g_getenv ("LIGHTDM_TEST_GROUPS");
+ if (!group_list)
+ group_list = "";
+ groups = g_strsplit (group_list, ",", -1);
+ groups_length = g_strv_length (groups);
+
+ if (size != 0)
+ {
+ int i;
+
+ if (groups_length > size)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ for (i = 0; groups[i]; i++)
+ list[i] = atoi (groups[i]);
+ }
+ g_free (groups);
+
+ return groups_length;
+}
+
+int
+setgroups (size_t size, const gid_t *list)
+{
+ size_t i;
+ GString *group_list;
+
+ group_list = g_string_new ("");
+ for (i = 0; i < size; i++)
+ {
+ if (i != 0)
+ g_string_append (group_list, ",");
+ g_string_append_printf (group_list, "%d", list[i]);
+ }
+ g_setenv ("LIGHTDM_TEST_GROUPS", group_list->str, TRUE);
+ g_string_free (group_list, TRUE);
+
return 0;
}
@@ -73,7 +132,7 @@ open (const char *pathname, int flags, ...)
va_end (ap);
}
- _open = (int (*)(const char * pathname, int flags, mode_t mode)) dlsym (RTLD_NEXT, "open");
+ _open = (int (*)(const char * pathname, int flags, mode_t mode)) dlsym (RTLD_NEXT, "open");
if (strcmp (pathname, "/dev/console") == 0)
{
if (console_fd < 0)
@@ -141,7 +200,7 @@ free_user (gpointer data)
static void
load_passwd_file ()
{
- gchar *data = NULL, **lines;
+ gchar *path, *data = NULL, **lines;
gint i;
GError *error = NULL;
@@ -149,7 +208,9 @@ load_passwd_file ()
user_entries = NULL;
getpwent_link = NULL;
- g_file_get_contents (g_getenv ("LIGHTDM_TEST_PASSWD_FILE"), &data, NULL, &error);
+ path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "passwd", NULL);
+ g_file_get_contents (path, &data, NULL, &error);
+ g_free (path);
if (error)
g_warning ("Error loading passwd file: %s", error->message);
g_clear_error (&error);
@@ -257,6 +318,99 @@ getpwuid (uid_t uid)
return link->data;
}
+static void
+free_group (gpointer data)
+{
+ struct group *entry = data;
+
+ g_free (entry->gr_name);
+ g_free (entry->gr_passwd);
+ g_strfreev (entry->gr_mem);
+ g_free (entry);
+}
+
+static void
+load_group_file ()
+{
+ gchar *path, *data = NULL, **lines;
+ gint i;
+ GError *error = NULL;
+
+ g_list_free_full (group_entries, free_group);
+ group_entries = NULL;
+
+ path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "group", NULL);
+ g_file_get_contents (path, &data, NULL, &error);
+ g_free (path);
+ if (error)
+ g_warning ("Error loading group file: %s", error->message);
+ g_clear_error (&error);
+
+ if (!data)
+ return;
+
+ lines = g_strsplit (data, "\n", -1);
+ g_free (data);
+
+ for (i = 0; lines[i]; i++)
+ {
+ gchar *line, **fields;
+
+ line = g_strstrip (lines[i]);
+ fields = g_strsplit (line, ":", -1);
+ if (g_strv_length (fields) == 4)
+ {
+ struct group *entry = malloc (sizeof (struct group));
+
+ entry->gr_name = g_strdup (fields[0]);
+ entry->gr_passwd = g_strdup (fields[1]);
+ entry->gr_gid = atoi (fields[2]);
+ entry->gr_mem = g_strsplit (fields[3], ",", -1);
+ group_entries = g_list_append (group_entries, entry);
+ }
+ g_strfreev (fields);
+ }
+ g_strfreev (lines);
+}
+
+struct group *
+getgrnam (const char *name)
+{
+ GList *link;
+
+ load_group_file ();
+
+ for (link = group_entries; link; link = link->next)
+ {
+ struct group *entry = link->data;
+ if (strcmp (entry->gr_name, name) == 0)
+ break;
+ }
+ if (!link)
+ return NULL;
+
+ return link->data;
+}
+
+struct group *
+getgrgid (gid_t gid)
+{
+ GList *link;
+
+ load_group_file ();
+
+ for (link = group_entries; link; link = link->next)
+ {
+ struct group *entry = link->data;
+ if (entry->gr_gid == gid)
+ break;
+ }
+ if (!link)
+ return NULL;
+
+ return link->data;
+}
+
int
pam_start (const char *service_name, const char *user, const struct pam_conv *conversation, pam_handle_t **pamh)
{
@@ -645,6 +799,29 @@ pam_setcred (pam_handle_t *pamh, int flags)
pam_putenv (pamh, e);
g_free (e);
+ /* Join special groups if requested */
+ if (strcmp (pamh->user, "group-member") == 0 && flags & PAM_ESTABLISH_CRED)
+ {
+ struct group *group;
+ gid_t *groups;
+ int groups_length;
+
+ group = getgrnam ("test-group");
+ if (group)
+ {
+ groups_length = getgroups (0, NULL);
+ groups = malloc (sizeof (gid_t) * (groups_length + 1));
+ groups_length = getgroups (groups_length, groups);
+ groups[groups_length] = group->gr_gid;
+ groups_length++;
+ setgroups (groups_length, groups);
+ free (groups);
+ }
+
+ /* We need to pass our group overrides down the child process - the environment via PAM seems the only way to do it easily */
+ pam_putenv (pamh, g_strdup_printf ("LIGHTDM_TEST_GROUPS=%s", g_getenv ("LIGHTDM_TEST_GROUPS")));
+ }
+
return PAM_SUCCESS;
}
diff --git a/tests/src/test-runner.c b/tests/src/test-runner.c
index 36473349..ee2495bd 100644
--- a/tests/src/test-runner.c
+++ b/tests/src/test-runner.c
@@ -838,10 +838,12 @@ start_console_kit_daemon ()
static void
load_passwd_file ()
{
- gchar *data, **lines;
+ gchar *path, *data, **lines;
int i;
- g_file_get_contents (g_getenv ("LIGHTDM_TEST_PASSWD_FILE"), &data, NULL, NULL);
+ path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "passwd", NULL);
+ g_file_get_contents (path, &data, NULL, NULL);
+ g_free (path);
lines = g_strsplit (data, "\n", -1);
g_free (data);
@@ -1179,7 +1181,7 @@ main (int argc, char **argv)
{
GMainLoop *loop;
gchar *greeter = NULL, *script_name, *config_file, *path, *path1, *path2, *ld_preload, *ld_library_path, *home_dir;
- GString *passwd_data;
+ GString *passwd_data, *group_data;
GSource *status_source;
gchar cwd[1024];
GError *error = NULL;
@@ -1288,6 +1290,7 @@ main (int argc, char **argv)
quit (EXIT_FAILURE);
}
g_chmod (temp_dir, 0755);
+ g_setenv ("LIGHTDM_TEST_ROOT", temp_dir, TRUE);
/* Set up a skeleton file system */
g_mkdir_with_parents (g_strdup_printf ("%s/etc", temp_dir), 0755);
@@ -1311,7 +1314,6 @@ main (int argc, char **argv)
g_free (greeter);
home_dir = g_build_filename (temp_dir, "home", NULL);
- g_setenv ("LIGHTDM_TEST_HOME_DIR", home_dir, TRUE);
/* Make fake users */
struct
@@ -1372,9 +1374,12 @@ main (int argc, char **argv)
{"multi-info-prompt","password", TRUE, "Multi Info Prompt", NULL, NULL, NULL, NULL, 1022},
/* This account uses two factor authentication */
{"two-factor", "password", TRUE, "Two Factor", NULL, NULL, NULL, NULL, 1023},
+ /* This account has a special group */
+ {"group-member", "password", TRUE, "Group Member", NULL, NULL, NULL, NULL, 1024},
{NULL, NULL, FALSE, NULL, NULL, NULL, NULL, NULL, 0}
};
passwd_data = g_string_new ("");
+ group_data = g_string_new ("");
int i;
for (i = 0; users[i].user_name; i++)
{
@@ -1425,14 +1430,25 @@ main (int argc, char **argv)
g_key_file_free (dmrc_file);
+ /* Add passwd file entry */
g_string_append_printf (passwd_data, "%s:%s:%d:%d:%s:%s/home/%s:/bin/sh\n", users[i].user_name, users[i].password, users[i].uid, users[i].uid, users[i].real_name, temp_dir, users[i].user_name);
+
+ /* Add group file entry */
+ g_string_append_printf (group_data, "%s:x:%d:%s\n", users[i].user_name, users[i].uid, users[i].user_name);
}
- path = g_build_filename (temp_dir, "passwd", NULL);
- g_setenv ("LIGHTDM_TEST_PASSWD_FILE", path, TRUE);
+ path = g_build_filename (temp_dir, "etc", "passwd", NULL);
g_file_set_contents (path, passwd_data->str, -1, NULL);
g_free (path);
g_string_free (passwd_data, TRUE);
+ /* Add an extra test group */
+ g_string_append_printf (group_data, "test-group:x:111:\n");
+
+ path = g_build_filename (temp_dir, "etc", "group", NULL);
+ g_file_set_contents (path, group_data->str, -1, NULL);
+ g_free (path);
+ g_string_free (group_data, TRUE);
+
/* Start D-Bus services */
if (!g_key_file_get_boolean (config, "test-runner-config", "disable-console-kit", NULL))
start_console_kit_daemon ();
diff --git a/tests/src/test-session.c b/tests/src/test-session.c
index 8df53d45..fb42b1e4 100644
--- a/tests/src/test-session.c
+++ b/tests/src/test-session.c
@@ -5,6 +5,7 @@
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
+#include <grp.h>
#include <xcb/xcb.h>
#include <glib.h>
#include <glib-object.h>
@@ -76,6 +77,34 @@ request_cb (const gchar *request)
}
g_free (r);
+ r = g_strdup_printf ("SESSION %s LIST-GROUPS", getenv ("DISPLAY"));
+ if (strcmp (request, r) == 0)
+ {
+ int n_groups, i;
+ gid_t *groups;
+ GString *group_list;
+
+ n_groups = getgroups (0, NULL);
+ groups = malloc (sizeof (gid_t) * n_groups);
+ n_groups = getgroups (n_groups, groups);
+ group_list = g_string_new ("");
+ for (i = 0; i < n_groups; i++)
+ {
+ struct group *group;
+
+ if (i != 0)
+ g_string_append (group_list, ",");
+ group = getgrgid (groups[i]);
+ if (group)
+ g_string_append (group_list, group->gr_name);
+ else
+ g_string_append_printf (group_list, "%d", groups[i]);
+ }
+ status_notify ("SESSION %s LIST-GROUPS GROUPS=%s", getenv ("DISPLAY"), group_list->str);
+ g_string_free (group_list, TRUE);
+ free (groups);
+ }
+
r = g_strdup_printf ("SESSION %s READ-ENV NAME=", getenv ("DISPLAY"));
if (g_str_has_prefix (request, r))
{
diff --git a/tests/test-group-membership b/tests/test-group-membership
new file mode 100755
index 00000000..a18c48ec
--- /dev/null
+++ b/tests/test-group-membership
@@ -0,0 +1,2 @@
+#!/bin/sh
+./src/dbus-env ./src/test-runner group-membership test-gobject-greeter