10 #include <security/pam_appl.h>
19 #include <gio/gunixsocketaddress.h>
21 #define LOGIN_PROMPT "login:"
23 static int console_fd = -1;
25 static GList *user_entries = NULL;
26 static GList *getpwent_link = NULL;
28 static GList *group_entries = NULL;
30 static int active_vt = 7;
32 static gboolean status_connected = FALSE;
42 struct pam_conv conversation;
58 initgroups (const char *user, gid_t group)
69 getgroups (int size, gid_t list[])
71 const gchar *group_list;
75 /* Get groups we are a member of */
76 group_list = g_getenv ("LIGHTDM_TEST_GROUPS");
79 groups = g_strsplit (group_list, ",", -1);
80 groups_length = g_strv_length (groups);
86 if (groups_length > size)
91 for (i = 0; groups[i]; i++)
92 list[i] = atoi (groups[i]);
100 setgroups (size_t size, const gid_t *list)
105 group_list = g_string_new ("");
106 for (i = 0; i < size; i++)
109 g_string_append (group_list, ",");
110 g_string_append_printf (group_list, "%d", list[i]);
112 g_setenv ("LIGHTDM_TEST_GROUPS", group_list->str, TRUE);
113 g_string_free (group_list, TRUE);
131 setresgid (gid_t rgid, gid_t ugid, gid_t sgid)
149 setresuid (uid_t ruid, uid_t uuid, uid_t suid)
155 redirect_path (const gchar *path)
160 // Don't redirect if inside the running directory
161 if (g_str_has_prefix (path, g_getenv ("LIGHTDM_TEST_ROOT")))
162 return g_strdup (path);
164 if (g_str_has_prefix (path, SYSCONFDIR))
165 return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", path + strlen (SYSCONFDIR), NULL);
167 if (g_str_has_prefix (path, LOCALSTATEDIR))
168 return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "var", path + strlen (LOCALSTATEDIR), NULL);
170 if (g_str_has_prefix (path, DATADIR))
171 return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "usr", "share", path + strlen (DATADIR), NULL);
173 // Don't redirect if inside the build directory
174 if (g_str_has_prefix (path, BUILDDIR))
175 return g_strdup (path);
177 if (g_str_has_prefix (path, "/tmp"))
178 return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "tmp", path + strlen ("tmp"), NULL);
180 return g_strdup (path);
185 open_wrapper (const char *func, const char *pathname, int flags, mode_t mode)
187 int (*_open) (const char *pathname, int flags, mode_t mode);
188 gchar *new_path = NULL;
191 _open = (int (*)(const char *pathname, int flags, mode_t mode)) dlsym (RTLD_NEXT, func);
193 if (strcmp (pathname, "/dev/console") == 0)
197 console_fd = _open ("/dev/null", flags, mode);
198 fcntl (console_fd, F_SETFD, FD_CLOEXEC);
203 new_path = redirect_path (pathname);
204 fd = _open (new_path, flags, mode);
211 open (const char *pathname, int flags, ...)
217 va_start (ap, flags);
218 mode = va_arg (ap, mode_t);
221 return open_wrapper ("open", pathname, flags, mode);
225 open64 (const char *pathname, int flags, ...)
231 va_start (ap, flags);
232 mode = va_arg (ap, mode_t);
235 return open_wrapper ("open64", pathname, flags, mode);
239 fopen (const char *path, const char *mode)
241 FILE *(*_fopen) (const char *pathname, const char *mode);
242 gchar *new_path = NULL;
245 _fopen = (FILE *(*)(const char *pathname, const char *mode)) dlsym (RTLD_NEXT, "fopen");
247 new_path = redirect_path (path);
248 result = _fopen (new_path, mode);
255 creat (const char *pathname, mode_t mode)
257 int (*_creat) (const char *pathname, mode_t mode);
258 gchar *new_path = NULL;
261 _creat = (int (*)(const char *pathname, mode_t mode)) dlsym (RTLD_NEXT, "creat");
263 new_path = redirect_path (pathname);
264 result = _creat (new_path, mode);
271 creat64 (const char *pathname, mode_t mode)
273 int (*_creat64) (const char *pathname, mode_t mode);
274 gchar *new_path = NULL;
277 _creat64 = (int (*)(const char *pathname, mode_t mode)) dlsym (RTLD_NEXT, "creat64");
279 new_path = redirect_path (pathname);
280 result = _creat64 (new_path, mode);
287 access (const char *pathname, int mode)
289 int (*_access) (const char *pathname, int mode);
290 gchar *new_path = NULL;
293 /* Look like systemd is always running */
294 if (strcmp (pathname, "/run/systemd/seats/") == 0)
297 _access = (int (*)(const char *pathname, int mode)) dlsym (RTLD_NEXT, "access");
299 new_path = redirect_path (pathname);
300 ret = _access (new_path, mode);
307 stat (const char *path, struct stat *buf)
309 int (*_stat) (const char *path, struct stat *buf);
310 gchar *new_path = NULL;
313 _stat = (int (*)(const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "stat");
315 new_path = redirect_path (path);
316 ret = _stat (new_path, buf);
323 stat64 (const char *path, struct stat *buf)
325 int (*_stat64) (const char *path, struct stat *buf);
326 gchar *new_path = NULL;
329 _stat64 = (int (*)(const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "stat64");
331 new_path = redirect_path (path);
332 ret = _stat (new_path, buf);
339 __xstat (int version, const char *path, struct stat *buf)
341 int (*___xstat) (int version, const char *path, struct stat *buf);
342 gchar *new_path = NULL;
345 ___xstat = (int (*)(int version, const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "__xstat");
347 new_path = redirect_path (path);
348 ret = ___xstat (version, new_path, buf);
355 __xstat64 (int version, const char *path, struct stat *buf)
357 int (*___xstat64) (int version, const char *path, struct stat *buf);
358 gchar *new_path = NULL;
361 ___xstat64 = (int (*)(int version, const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "__xstat64");
363 new_path = redirect_path (path);
364 ret = ___xstat64 (version, new_path, buf);
371 opendir (const char *name)
373 DIR *(*_opendir) (const char *name);
374 gchar *new_path = NULL;
377 _opendir = (DIR *(*)(const char *name)) dlsym (RTLD_NEXT, "opendir");
379 new_path = redirect_path (name);
380 result = _opendir (new_path);
387 mkdir (const char *pathname, mode_t mode)
389 int (*_mkdir) (const char *pathname, mode_t mode);
390 gchar *new_path = NULL;
393 _mkdir = (int (*)(const char *pathname, mode_t mode)) dlsym (RTLD_NEXT, "mkdir");
395 new_path = redirect_path (pathname);
396 result = _mkdir (new_path, mode);
403 chown (const char *pathname, uid_t owner, gid_t group)
405 int (*_chown) (const char *pathname, uid_t owner, gid_t group);
406 gchar *new_path = NULL;
409 _chown = (int (*)(const char *pathname, uid_t owner, gid_t group)) dlsym (RTLD_NEXT, "chown");
411 new_path = redirect_path (pathname);
412 result = _chown (new_path, owner, group);
419 ioctl (int d, int request, void *data)
421 int (*_ioctl) (int d, int request, void *data);
423 _ioctl = (int (*)(int d, int request, void *data)) dlsym (RTLD_NEXT, "ioctl");
424 if (d > 0 && d == console_fd)
426 struct vt_stat *console_state;
433 console_state = data;
434 console_state->v_active = active_vt;
437 vt = GPOINTER_TO_INT (data);
441 if (!status_connected)
442 status_connected = status_connect (NULL);
443 status_notify ("VT ACTIVATE VT=%d", active_vt);
452 return _ioctl (d, request, data);
458 int (*_close) (int fd);
460 if (fd > 0 && fd == console_fd)
463 _close = (int (*)(int fd)) dlsym (RTLD_NEXT, "close");
469 free_user (gpointer data)
471 struct passwd *entry = data;
473 g_free (entry->pw_name);
474 g_free (entry->pw_passwd);
475 g_free (entry->pw_gecos);
476 g_free (entry->pw_dir);
477 g_free (entry->pw_shell);
484 gchar *path, *data = NULL, **lines;
486 GError *error = NULL;
488 g_list_free_full (user_entries, free_user);
490 getpwent_link = NULL;
492 path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "passwd", NULL);
493 g_file_get_contents (path, &data, NULL, &error);
496 g_warning ("Error loading passwd file: %s", error->message);
497 g_clear_error (&error);
502 lines = g_strsplit (data, "\n", -1);
505 for (i = 0; lines[i]; i++)
507 gchar *line, **fields;
509 line = g_strstrip (lines[i]);
510 fields = g_strsplit (line, ":", -1);
511 if (g_strv_length (fields) == 7)
513 struct passwd *entry = malloc (sizeof (struct passwd));
515 entry->pw_name = g_strdup (fields[0]);
516 entry->pw_passwd = g_strdup (fields[1]);
517 entry->pw_uid = atoi (fields[2]);
518 entry->pw_gid = atoi (fields[3]);
519 entry->pw_gecos = g_strdup (fields[4]);
520 entry->pw_dir = g_strdup (fields[5]);
521 entry->pw_shell = g_strdup (fields[6]);
522 user_entries = g_list_append (user_entries, entry);
532 if (getpwent_link == NULL)
535 if (user_entries == NULL)
537 getpwent_link = user_entries;
541 if (getpwent_link->next == NULL)
543 getpwent_link = getpwent_link->next;
546 return getpwent_link->data;
552 getpwent_link = NULL;
558 getpwent_link = NULL;
562 getpwnam (const char *name)
571 for (link = user_entries; link; link = link->next)
573 struct passwd *entry = link->data;
574 if (strcmp (entry->pw_name, name) == 0)
590 for (link = user_entries; link; link = link->next)
592 struct passwd *entry = link->data;
593 if (entry->pw_uid == uid)
603 free_group (gpointer data)
605 struct group *entry = data;
607 g_free (entry->gr_name);
608 g_free (entry->gr_passwd);
609 g_strfreev (entry->gr_mem);
616 gchar *path, *data = NULL, **lines;
618 GError *error = NULL;
620 g_list_free_full (group_entries, free_group);
621 group_entries = NULL;
623 path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "group", NULL);
624 g_file_get_contents (path, &data, NULL, &error);
627 g_warning ("Error loading group file: %s", error->message);
628 g_clear_error (&error);
633 lines = g_strsplit (data, "\n", -1);
636 for (i = 0; lines[i]; i++)
638 gchar *line, **fields;
640 line = g_strstrip (lines[i]);
641 fields = g_strsplit (line, ":", -1);
642 if (g_strv_length (fields) == 4)
644 struct group *entry = malloc (sizeof (struct group));
646 entry->gr_name = g_strdup (fields[0]);
647 entry->gr_passwd = g_strdup (fields[1]);
648 entry->gr_gid = atoi (fields[2]);
649 entry->gr_mem = g_strsplit (fields[3], ",", -1);
650 group_entries = g_list_append (group_entries, entry);
658 getgrnam (const char *name)
664 for (link = group_entries; link; link = link->next)
666 struct group *entry = link->data;
667 if (strcmp (entry->gr_name, name) == 0)
683 for (link = group_entries; link; link = link->next)
685 struct group *entry = link->data;
686 if (entry->gr_gid == gid)
696 pam_start (const char *service_name, const char *user, const struct pam_conv *conversation, pam_handle_t **pamh)
698 pam_handle_t *handle;
700 if (service_name == NULL || conversation == NULL || pamh == NULL)
701 return PAM_SYSTEM_ERR;
703 handle = *pamh = malloc (sizeof (pam_handle_t));
707 handle->service_name = strdup (service_name);
708 handle->user = user ? strdup (user) : NULL;
709 handle->authtok = NULL;
710 handle->ruser = NULL;
712 handle->conversation.conv = conversation->conv;
713 handle->conversation.appdata_ptr = conversation->appdata_ptr;
714 handle->envlist = malloc (sizeof (char *) * 1);
715 handle->envlist[0] = NULL;
721 send_info (pam_handle_t *pamh, const char *message)
723 struct pam_message **msg;
724 struct pam_response *resp = NULL;
726 msg = calloc (1, sizeof (struct pam_message *));
727 msg[0] = malloc (sizeof (struct pam_message));
728 msg[0]->msg_style = PAM_TEXT_INFO;
729 msg[0]->msg = message;
730 pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
742 pam_authenticate (pam_handle_t *pamh, int flags)
744 struct passwd *entry;
745 gboolean password_matches = FALSE;
748 return PAM_SYSTEM_ERR;
750 if (strcmp (pamh->service_name, "test-remote") == 0)
753 struct pam_message **msg;
754 struct pam_response *resp = NULL;
756 msg = malloc (sizeof (struct pam_message *) * 1);
757 msg[0] = malloc (sizeof (struct pam_message));
758 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
759 msg[0]->msg = "remote-login:";
760 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
763 if (result != PAM_SUCCESS)
768 if (resp[0].resp == NULL)
776 pamh->ruser = strdup (resp[0].resp);
780 msg = malloc (sizeof (struct pam_message *) * 1);
781 msg[0] = malloc (sizeof (struct pam_message));
782 msg[0]->msg_style = PAM_PROMPT_ECHO_OFF;
783 msg[0]->msg = "remote-password:";
784 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
787 if (result != PAM_SUCCESS)
792 if (resp[0].resp == NULL)
799 free (pamh->authtok);
800 pamh->authtok = strdup (resp[0].resp);
804 password_matches = strcmp (pamh->ruser, "remote-user") == 0 && strcmp (pamh->authtok, "password") == 0;
806 if (password_matches)
812 /* Prompt for username */
813 if (pamh->user == NULL)
816 struct pam_message **msg;
817 struct pam_response *resp = NULL;
819 msg = malloc (sizeof (struct pam_message *) * 1);
820 msg[0] = malloc (sizeof (struct pam_message));
821 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
822 msg[0]->msg = LOGIN_PROMPT;
823 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
826 if (result != PAM_SUCCESS)
831 if (resp[0].resp == NULL)
837 pamh->user = strdup (resp[0].resp);
842 if (strcmp (pamh->user, "log-pam") == 0)
843 send_info (pamh, "pam_authenticate");
845 /* Crash on authenticate */
846 if (strcmp (pamh->user, "crash-authenticate") == 0)
847 kill (getpid (), SIGSEGV);
849 /* Look up password database */
850 entry = getpwnam (pamh->user);
852 /* Prompt for password if required */
853 if (entry && strcmp (pamh->user, "always-password") != 0 && (strcmp (pamh->service_name, "lightdm-autologin") == 0 || strcmp (entry->pw_passwd, "") == 0))
854 password_matches = TRUE;
857 int i, n_messages = 0, password_index, result;
858 struct pam_message **msg;
859 struct pam_response *resp = NULL;
861 msg = malloc (sizeof (struct pam_message *) * 5);
862 if (strcmp (pamh->user, "info-prompt") == 0)
864 msg[n_messages] = malloc (sizeof (struct pam_message));
865 msg[n_messages]->msg_style = PAM_TEXT_INFO;
866 msg[n_messages]->msg = "Welcome to LightDM";
869 if (strcmp (pamh->user, "multi-info-prompt") == 0)
871 msg[n_messages] = malloc (sizeof (struct pam_message));
872 msg[n_messages]->msg_style = PAM_TEXT_INFO;
873 msg[n_messages]->msg = "Welcome to LightDM";
875 msg[n_messages] = malloc (sizeof (struct pam_message));
876 msg[n_messages]->msg_style = PAM_ERROR_MSG;
877 msg[n_messages]->msg = "This is an error";
879 msg[n_messages] = malloc (sizeof (struct pam_message));
880 msg[n_messages]->msg_style = PAM_TEXT_INFO;
881 msg[n_messages]->msg = "You should have seen three messages";
884 if (strcmp (pamh->user, "multi-prompt") == 0)
886 msg[n_messages] = malloc (sizeof (struct pam_message));
887 msg[n_messages]->msg_style = PAM_PROMPT_ECHO_ON;
888 msg[n_messages]->msg = "Favorite Color:";
891 msg[n_messages] = malloc (sizeof (struct pam_message));
892 msg[n_messages]->msg_style = PAM_PROMPT_ECHO_OFF;
893 msg[n_messages]->msg = "Password:";
894 password_index = n_messages;
896 result = pamh->conversation.conv (n_messages, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
897 for (i = 0; i < n_messages; i++)
900 if (result != PAM_SUCCESS)
905 if (resp[password_index].resp == NULL)
912 password_matches = strcmp (entry->pw_passwd, resp[password_index].resp) == 0;
914 if (password_matches && strcmp (pamh->user, "multi-prompt") == 0)
915 password_matches = strcmp ("blue", resp[0].resp) == 0;
917 for (i = 0; i < n_messages; i++)
924 /* Do two factor authentication */
925 if (password_matches && strcmp (pamh->user, "two-factor") == 0)
927 msg = malloc (sizeof (struct pam_message *) * 1);
928 msg[0] = malloc (sizeof (struct pam_message));
929 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
930 msg[0]->msg = "OTP:";
932 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
938 if (resp[0].resp == NULL)
943 password_matches = strcmp (resp[0].resp, "otp") == 0;
949 /* Special user has home directory created on login */
950 if (password_matches && strcmp (pamh->user, "mount-home-dir") == 0)
951 g_mkdir_with_parents (entry->pw_dir, 0755);
953 /* Special user 'change-user1' changes user on authentication */
954 if (password_matches && strcmp (pamh->user, "change-user1") == 0)
957 pamh->user = g_strdup ("change-user2");
960 /* Special user 'change-user-invalid' changes to an invalid user on authentication */
961 if (password_matches && strcmp (pamh->user, "change-user-invalid") == 0)
964 pamh->user = g_strdup ("invalid-user");
967 if (password_matches)
974 get_env_value (const char *name_value, const char *name)
978 for (j = 0; name[j] && name_value[j] && name[j] == name_value[j]; j++);
979 if (name[j] == '\0' && name_value[j] == '=')
980 return &name_value[j + 1];
986 pam_putenv (pam_handle_t *pamh, const char *name_value)
991 if (pamh == NULL || name_value == NULL)
992 return PAM_SYSTEM_ERR;
994 name = strdup (name_value);
995 for (i = 0; name[i]; i++)
998 for (i = 0; pamh->envlist[i]; i++)
1000 if (get_env_value (pamh->envlist[i], name))
1005 if (pamh->envlist[i])
1007 free (pamh->envlist[i]);
1008 pamh->envlist[i] = strdup (name_value);
1012 pamh->envlist = realloc (pamh->envlist, sizeof (char *) * (i + 2));
1013 pamh->envlist[i] = strdup (name_value);
1014 pamh->envlist[i + 1] = NULL;
1021 pam_getenv (pam_handle_t *pamh, const char *name)
1025 if (pamh == NULL || name == NULL)
1028 for (i = 0; pamh->envlist[i]; i++)
1031 value = get_env_value (pamh->envlist[i], name);
1040 pam_getenvlist (pam_handle_t *pamh)
1045 return pamh->envlist;
1049 pam_set_item (pam_handle_t *pamh, int item_type, const void *item)
1051 if (pamh == NULL || item == NULL)
1052 return PAM_SYSTEM_ERR;
1059 pamh->tty = strdup ((const char *) item);
1063 return PAM_BAD_ITEM;
1068 pam_get_item (const pam_handle_t *pamh, int item_type, const void **item)
1070 if (pamh == NULL || item == NULL)
1071 return PAM_SYSTEM_ERR;
1076 *item = pamh->service_name;
1084 *item = pamh->authtok;
1088 *item = pamh->ruser;
1091 case PAM_USER_PROMPT:
1092 *item = LOGIN_PROMPT;
1100 *item = &pamh->conversation;
1104 return PAM_BAD_ITEM;
1109 pam_open_session (pam_handle_t *pamh, int flags)
1112 return PAM_SYSTEM_ERR;
1114 if (strcmp (pamh->user, "session-error") == 0)
1115 return PAM_SESSION_ERR;
1117 if (strcmp (pamh->user, "log-pam") == 0)
1118 send_info (pamh, "pam_open_session");
1120 if (strcmp (pamh->user, "make-home-dir") == 0)
1122 struct passwd *entry;
1123 entry = getpwnam (pamh->user);
1124 g_mkdir_with_parents (entry->pw_dir, 0755);
1131 pam_close_session (pam_handle_t *pamh, int flags)
1134 return PAM_SYSTEM_ERR;
1136 if (strcmp (pamh->user, "log-pam") == 0)
1137 send_info (pamh, "pam_close_session");
1143 pam_acct_mgmt (pam_handle_t *pamh, int flags)
1146 return PAM_SYSTEM_ERR;
1149 return PAM_USER_UNKNOWN;
1151 if (strcmp (pamh->user, "log-pam") == 0)
1152 send_info (pamh, "pam_acct_mgmt");
1154 if (strcmp (pamh->user, "denied") == 0)
1155 return PAM_PERM_DENIED;
1156 if (strcmp (pamh->user, "expired") == 0)
1157 return PAM_ACCT_EXPIRED;
1158 if (strcmp (pamh->user, "new-authtok") == 0)
1159 return PAM_NEW_AUTHTOK_REQD;
1165 pam_chauthtok (pam_handle_t *pamh, int flags)
1167 struct passwd *entry;
1169 struct pam_message **msg;
1170 struct pam_response *resp = NULL;
1173 return PAM_SYSTEM_ERR;
1175 if (strcmp (pamh->user, "log-pam") == 0)
1176 send_info (pamh, "pam_chauthtok");
1178 msg = malloc (sizeof (struct pam_message *) * 1);
1179 msg[0] = malloc (sizeof (struct pam_message));
1180 msg[0]->msg_style = PAM_PROMPT_ECHO_OFF;
1181 msg[0]->msg = "Enter new password:";
1182 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
1185 if (result != PAM_SUCCESS)
1189 return PAM_CONV_ERR;
1190 if (resp[0].resp == NULL)
1193 return PAM_CONV_ERR;
1196 /* Update password database */
1197 entry = getpwnam (pamh->user);
1198 free (entry->pw_passwd);
1199 entry->pw_passwd = resp[0].resp;
1206 pam_setcred (pam_handle_t *pamh, int flags)
1211 return PAM_SYSTEM_ERR;
1213 if (strcmp (pamh->user, "log-pam") == 0)
1214 send_info (pamh, "pam_setcred");
1216 /* Put the test directories into the path */
1217 e = g_strdup_printf ("PATH=%s/tests/src/.libs:%s/tests/src:%s/tests/src:%s/src:%s", BUILDDIR, BUILDDIR, SRCDIR, BUILDDIR, pam_getenv (pamh, "PATH"));
1218 pam_putenv (pamh, e);
1221 if (strcmp (pamh->user, "cred-error") == 0)
1222 return PAM_CRED_ERR;
1223 if (strcmp (pamh->user, "cred-expired") == 0)
1224 return PAM_CRED_EXPIRED;
1225 if (strcmp (pamh->user, "cred-unavail") == 0)
1226 return PAM_CRED_UNAVAIL;
1228 /* Join special groups if requested */
1229 if (strcmp (pamh->user, "group-member") == 0 && flags & PAM_ESTABLISH_CRED)
1231 struct group *group;
1235 group = getgrnam ("test-group");
1238 groups_length = getgroups (0, NULL);
1239 groups = malloc (sizeof (gid_t) * (groups_length + 1));
1240 groups_length = getgroups (groups_length, groups);
1241 groups[groups_length] = group->gr_gid;
1243 setgroups (groups_length, groups);
1247 /* We need to pass our group overrides down the child process - the environment via PAM seems the only way to do it easily */
1248 pam_putenv (pamh, g_strdup_printf ("LIGHTDM_TEST_GROUPS=%s", g_getenv ("LIGHTDM_TEST_GROUPS")));
1255 pam_end (pam_handle_t *pamh, int pam_status)
1258 return PAM_SYSTEM_ERR;
1260 free (pamh->service_name);
1264 free (pamh->authtok);
1275 pam_strerror (pam_handle_t *pamh, int errnum)
1285 return "Critical error - immediate abort";
1287 return "Failed to load module";
1288 case PAM_SYMBOL_ERR:
1289 return "Symbol not found";
1290 case PAM_SERVICE_ERR:
1291 return "Error in service module";
1292 case PAM_SYSTEM_ERR:
1293 return "System error";
1295 return "Memory buffer error";
1296 case PAM_PERM_DENIED:
1297 return "Permission denied";
1299 return "Authentication failure";
1300 case PAM_CRED_INSUFFICIENT:
1301 return "Insufficient credentials to access authentication data";
1302 case PAM_AUTHINFO_UNAVAIL:
1303 return "Authentication service cannot retrieve authentication info";
1304 case PAM_USER_UNKNOWN:
1305 return "User not known to the underlying authentication module";
1307 return "Have exhausted maximum number of retries for service";
1308 case PAM_NEW_AUTHTOK_REQD:
1309 return "Authentication token is no longer valid; new one required";
1310 case PAM_ACCT_EXPIRED:
1311 return "User account has expired";
1312 case PAM_SESSION_ERR:
1313 return "Cannot make/remove an entry for the specified session";
1314 case PAM_CRED_UNAVAIL:
1315 return "Authentication service cannot retrieve user credentials";
1316 case PAM_CRED_EXPIRED:
1317 return "User credentials expired";
1319 return "Failure setting user credentials";
1320 case PAM_NO_MODULE_DATA:
1321 return "No module specific data is present";
1323 return "Bad item passed to pam_*_item()";
1325 return "Conversation error";
1326 case PAM_AUTHTOK_ERR:
1327 return "Authentication token manipulation error";
1328 case PAM_AUTHTOK_RECOVERY_ERR:
1329 return "Authentication information cannot be recovered";
1330 case PAM_AUTHTOK_LOCK_BUSY:
1331 return "Authentication token lock busy";
1332 case PAM_AUTHTOK_DISABLE_AGING:
1333 return "Authentication token aging disabled";
1335 return "Failed preliminary check by password service";
1337 return "The return value should be ignored by PAM dispatch";
1338 case PAM_MODULE_UNKNOWN:
1339 return "Module is unknown";
1340 case PAM_AUTHTOK_EXPIRED:
1341 return "Authentication token expired";
1342 case PAM_CONV_AGAIN:
1343 return "Conversation is waiting for event";
1344 case PAM_INCOMPLETE:
1345 return "Application needs to call libpam again";
1347 return "Unknown PAM error";
1357 pututxline (struct utmp *ut)
1367 struct xcb_connection_t
1375 xcb_connect_to_display_with_auth_info (const char *display, xcb_auth_info_t *auth, int *screen)
1377 xcb_connection_t *c;
1379 GSocketAddress *address;
1380 GError *error = NULL;
1382 c = malloc (sizeof (xcb_connection_t));
1383 c->display = g_strdup (display);
1386 if (display == NULL)
1387 display = getenv ("DISPLAY");
1388 if (display == NULL)
1389 c->error = XCB_CONN_CLOSED_PARSE_ERR;
1393 c->socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &error);
1395 g_printerr ("%s\n", error->message);
1396 g_clear_error (&error);
1397 if (c->socket == NULL)
1398 c->error = XCB_CONN_ERROR;
1405 /* Skip the hostname, we'll assume it's localhost */
1406 d = g_strdup_printf (".x%s", strchr (display, ':'));
1408 socket_path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), d, NULL);
1410 address = g_unix_socket_address_new (socket_path);
1411 if (!g_socket_connect (c->socket, address, NULL, &error))
1412 c->error = XCB_CONN_ERROR;
1414 g_printerr ("Failed to connect to X socket %s: %s\n", socket_path, error->message);
1415 g_free (socket_path);
1416 g_clear_error (&error);
1419 // FIXME: Send auth info
1424 g_object_unref (address);
1430 xcb_connect (const char *displayname, int *screenp)
1432 return xcb_connect_to_display_with_auth_info(displayname, NULL, screenp);
1436 xcb_connection_has_error (xcb_connection_t *c)
1442 xcb_disconnect (xcb_connection_t *c)
1446 g_object_unref (c->socket);