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 = _stat64 (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 chmod (const char *path, mode_t mode)
421 int (*_chmod) (const char *path, mode_t mode);
422 gchar *new_path = NULL;
425 _chmod = (int (*)(const char *path, mode_t mode)) dlsym (RTLD_NEXT, "chmod");
427 new_path = redirect_path (path);
428 result = _chmod (new_path, mode);
435 ioctl (int d, int request, void *data)
437 int (*_ioctl) (int d, int request, void *data);
439 _ioctl = (int (*)(int d, int request, void *data)) dlsym (RTLD_NEXT, "ioctl");
440 if (d > 0 && d == console_fd)
442 struct vt_stat *console_state;
449 console_state = data;
450 console_state->v_active = active_vt;
453 vt = GPOINTER_TO_INT (data);
457 if (!status_connected)
458 status_connected = status_connect (NULL);
459 status_notify ("VT ACTIVATE VT=%d", active_vt);
468 return _ioctl (d, request, data);
474 int (*_close) (int fd);
476 if (fd > 0 && fd == console_fd)
479 _close = (int (*)(int fd)) dlsym (RTLD_NEXT, "close");
485 free_user (gpointer data)
487 struct passwd *entry = data;
489 g_free (entry->pw_name);
490 g_free (entry->pw_passwd);
491 g_free (entry->pw_gecos);
492 g_free (entry->pw_dir);
493 g_free (entry->pw_shell);
500 gchar *path, *data = NULL, **lines;
502 GError *error = NULL;
504 g_list_free_full (user_entries, free_user);
506 getpwent_link = NULL;
508 path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "passwd", NULL);
509 g_file_get_contents (path, &data, NULL, &error);
512 g_warning ("Error loading passwd file: %s", error->message);
513 g_clear_error (&error);
518 lines = g_strsplit (data, "\n", -1);
521 for (i = 0; lines[i]; i++)
523 gchar *line, **fields;
525 line = g_strstrip (lines[i]);
526 fields = g_strsplit (line, ":", -1);
527 if (g_strv_length (fields) == 7)
529 struct passwd *entry = malloc (sizeof (struct passwd));
531 entry->pw_name = g_strdup (fields[0]);
532 entry->pw_passwd = g_strdup (fields[1]);
533 entry->pw_uid = atoi (fields[2]);
534 entry->pw_gid = atoi (fields[3]);
535 entry->pw_gecos = g_strdup (fields[4]);
536 entry->pw_dir = g_strdup (fields[5]);
537 entry->pw_shell = g_strdup (fields[6]);
538 user_entries = g_list_append (user_entries, entry);
548 if (getpwent_link == NULL)
551 if (user_entries == NULL)
553 getpwent_link = user_entries;
557 if (getpwent_link->next == NULL)
559 getpwent_link = getpwent_link->next;
562 return getpwent_link->data;
568 getpwent_link = NULL;
574 getpwent_link = NULL;
578 getpwnam (const char *name)
587 for (link = user_entries; link; link = link->next)
589 struct passwd *entry = link->data;
590 if (strcmp (entry->pw_name, name) == 0)
606 for (link = user_entries; link; link = link->next)
608 struct passwd *entry = link->data;
609 if (entry->pw_uid == uid)
619 free_group (gpointer data)
621 struct group *entry = data;
623 g_free (entry->gr_name);
624 g_free (entry->gr_passwd);
625 g_strfreev (entry->gr_mem);
632 gchar *path, *data = NULL, **lines;
634 GError *error = NULL;
636 g_list_free_full (group_entries, free_group);
637 group_entries = NULL;
639 path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "group", NULL);
640 g_file_get_contents (path, &data, NULL, &error);
643 g_warning ("Error loading group file: %s", error->message);
644 g_clear_error (&error);
649 lines = g_strsplit (data, "\n", -1);
652 for (i = 0; lines[i]; i++)
654 gchar *line, **fields;
656 line = g_strstrip (lines[i]);
657 fields = g_strsplit (line, ":", -1);
658 if (g_strv_length (fields) == 4)
660 struct group *entry = malloc (sizeof (struct group));
662 entry->gr_name = g_strdup (fields[0]);
663 entry->gr_passwd = g_strdup (fields[1]);
664 entry->gr_gid = atoi (fields[2]);
665 entry->gr_mem = g_strsplit (fields[3], ",", -1);
666 group_entries = g_list_append (group_entries, entry);
674 getgrnam (const char *name)
680 for (link = group_entries; link; link = link->next)
682 struct group *entry = link->data;
683 if (strcmp (entry->gr_name, name) == 0)
699 for (link = group_entries; link; link = link->next)
701 struct group *entry = link->data;
702 if (entry->gr_gid == gid)
712 pam_start (const char *service_name, const char *user, const struct pam_conv *conversation, pam_handle_t **pamh)
714 pam_handle_t *handle;
716 if (service_name == NULL || conversation == NULL || pamh == NULL)
717 return PAM_SYSTEM_ERR;
719 handle = *pamh = malloc (sizeof (pam_handle_t));
723 handle->service_name = strdup (service_name);
724 handle->user = user ? strdup (user) : NULL;
725 handle->authtok = NULL;
726 handle->ruser = NULL;
728 handle->conversation.conv = conversation->conv;
729 handle->conversation.appdata_ptr = conversation->appdata_ptr;
730 handle->envlist = malloc (sizeof (char *) * 1);
731 handle->envlist[0] = NULL;
737 send_info (pam_handle_t *pamh, const char *message)
739 struct pam_message **msg;
740 struct pam_response *resp = NULL;
742 msg = calloc (1, sizeof (struct pam_message *));
743 msg[0] = malloc (sizeof (struct pam_message));
744 msg[0]->msg_style = PAM_TEXT_INFO;
745 msg[0]->msg = message;
746 pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
758 pam_authenticate (pam_handle_t *pamh, int flags)
760 struct passwd *entry;
761 gboolean password_matches = FALSE;
764 return PAM_SYSTEM_ERR;
766 if (strcmp (pamh->service_name, "test-remote") == 0)
769 struct pam_message **msg;
770 struct pam_response *resp = NULL;
772 msg = malloc (sizeof (struct pam_message *) * 1);
773 msg[0] = malloc (sizeof (struct pam_message));
774 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
775 msg[0]->msg = "remote-login:";
776 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
779 if (result != PAM_SUCCESS)
784 if (resp[0].resp == NULL)
792 pamh->ruser = strdup (resp[0].resp);
796 msg = malloc (sizeof (struct pam_message *) * 1);
797 msg[0] = malloc (sizeof (struct pam_message));
798 msg[0]->msg_style = PAM_PROMPT_ECHO_OFF;
799 msg[0]->msg = "remote-password:";
800 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
803 if (result != PAM_SUCCESS)
808 if (resp[0].resp == NULL)
815 free (pamh->authtok);
816 pamh->authtok = strdup (resp[0].resp);
820 password_matches = strcmp (pamh->ruser, "remote-user") == 0 && strcmp (pamh->authtok, "password") == 0;
822 if (password_matches)
828 /* Prompt for username */
829 if (pamh->user == NULL)
832 struct pam_message **msg;
833 struct pam_response *resp = NULL;
835 msg = malloc (sizeof (struct pam_message *) * 1);
836 msg[0] = malloc (sizeof (struct pam_message));
837 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
838 msg[0]->msg = LOGIN_PROMPT;
839 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
842 if (result != PAM_SUCCESS)
847 if (resp[0].resp == NULL)
853 pamh->user = strdup (resp[0].resp);
858 if (strcmp (pamh->user, "log-pam") == 0)
859 send_info (pamh, "pam_authenticate");
861 /* Crash on authenticate */
862 if (strcmp (pamh->user, "crash-authenticate") == 0)
863 kill (getpid (), SIGSEGV);
865 /* Look up password database */
866 entry = getpwnam (pamh->user);
868 /* Prompt for password if required */
869 if (entry && strcmp (pamh->user, "always-password") != 0 && (strcmp (pamh->service_name, "lightdm-autologin") == 0 || strcmp (entry->pw_passwd, "") == 0))
870 password_matches = TRUE;
873 int i, n_messages = 0, password_index, result;
874 struct pam_message **msg;
875 struct pam_response *resp = NULL;
877 msg = malloc (sizeof (struct pam_message *) * 5);
878 if (strcmp (pamh->user, "info-prompt") == 0)
880 msg[n_messages] = malloc (sizeof (struct pam_message));
881 msg[n_messages]->msg_style = PAM_TEXT_INFO;
882 msg[n_messages]->msg = "Welcome to LightDM";
885 if (strcmp (pamh->user, "multi-info-prompt") == 0)
887 msg[n_messages] = malloc (sizeof (struct pam_message));
888 msg[n_messages]->msg_style = PAM_TEXT_INFO;
889 msg[n_messages]->msg = "Welcome to LightDM";
891 msg[n_messages] = malloc (sizeof (struct pam_message));
892 msg[n_messages]->msg_style = PAM_ERROR_MSG;
893 msg[n_messages]->msg = "This is an error";
895 msg[n_messages] = malloc (sizeof (struct pam_message));
896 msg[n_messages]->msg_style = PAM_TEXT_INFO;
897 msg[n_messages]->msg = "You should have seen three messages";
900 if (strcmp (pamh->user, "multi-prompt") == 0)
902 msg[n_messages] = malloc (sizeof (struct pam_message));
903 msg[n_messages]->msg_style = PAM_PROMPT_ECHO_ON;
904 msg[n_messages]->msg = "Favorite Color:";
907 msg[n_messages] = malloc (sizeof (struct pam_message));
908 msg[n_messages]->msg_style = PAM_PROMPT_ECHO_OFF;
909 msg[n_messages]->msg = "Password:";
910 password_index = n_messages;
912 result = pamh->conversation.conv (n_messages, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
913 for (i = 0; i < n_messages; i++)
916 if (result != PAM_SUCCESS)
921 if (resp[password_index].resp == NULL)
928 password_matches = strcmp (entry->pw_passwd, resp[password_index].resp) == 0;
930 if (password_matches && strcmp (pamh->user, "multi-prompt") == 0)
931 password_matches = strcmp ("blue", resp[0].resp) == 0;
933 for (i = 0; i < n_messages; i++)
940 /* Do two factor authentication */
941 if (password_matches && strcmp (pamh->user, "two-factor") == 0)
943 msg = malloc (sizeof (struct pam_message *) * 1);
944 msg[0] = malloc (sizeof (struct pam_message));
945 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
946 msg[0]->msg = "OTP:";
948 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
954 if (resp[0].resp == NULL)
959 password_matches = strcmp (resp[0].resp, "otp") == 0;
965 /* Special user has home directory created on login */
966 if (password_matches && strcmp (pamh->user, "mount-home-dir") == 0)
967 g_mkdir_with_parents (entry->pw_dir, 0755);
969 /* Special user 'change-user1' changes user on authentication */
970 if (password_matches && strcmp (pamh->user, "change-user1") == 0)
973 pamh->user = g_strdup ("change-user2");
976 /* Special user 'change-user-invalid' changes to an invalid user on authentication */
977 if (password_matches && strcmp (pamh->user, "change-user-invalid") == 0)
980 pamh->user = g_strdup ("invalid-user");
983 if (password_matches)
990 get_env_value (const char *name_value, const char *name)
994 for (j = 0; name[j] && name_value[j] && name[j] == name_value[j]; j++);
995 if (name[j] == '\0' && name_value[j] == '=')
996 return &name_value[j + 1];
1002 pam_putenv (pam_handle_t *pamh, const char *name_value)
1007 if (pamh == NULL || name_value == NULL)
1008 return PAM_SYSTEM_ERR;
1010 name = strdup (name_value);
1011 for (i = 0; name[i]; i++)
1014 for (i = 0; pamh->envlist[i]; i++)
1016 if (get_env_value (pamh->envlist[i], name))
1021 if (pamh->envlist[i])
1023 free (pamh->envlist[i]);
1024 pamh->envlist[i] = strdup (name_value);
1028 pamh->envlist = realloc (pamh->envlist, sizeof (char *) * (i + 2));
1029 pamh->envlist[i] = strdup (name_value);
1030 pamh->envlist[i + 1] = NULL;
1037 pam_getenv (pam_handle_t *pamh, const char *name)
1041 if (pamh == NULL || name == NULL)
1044 for (i = 0; pamh->envlist[i]; i++)
1047 value = get_env_value (pamh->envlist[i], name);
1056 pam_getenvlist (pam_handle_t *pamh)
1061 return pamh->envlist;
1065 pam_set_item (pam_handle_t *pamh, int item_type, const void *item)
1067 if (pamh == NULL || item == NULL)
1068 return PAM_SYSTEM_ERR;
1075 pamh->tty = strdup ((const char *) item);
1079 return PAM_BAD_ITEM;
1084 pam_get_item (const pam_handle_t *pamh, int item_type, const void **item)
1086 if (pamh == NULL || item == NULL)
1087 return PAM_SYSTEM_ERR;
1092 *item = pamh->service_name;
1100 *item = pamh->authtok;
1104 *item = pamh->ruser;
1107 case PAM_USER_PROMPT:
1108 *item = LOGIN_PROMPT;
1116 *item = &pamh->conversation;
1120 return PAM_BAD_ITEM;
1125 pam_open_session (pam_handle_t *pamh, int flags)
1128 return PAM_SYSTEM_ERR;
1130 if (strcmp (pamh->user, "session-error") == 0)
1131 return PAM_SESSION_ERR;
1133 if (strcmp (pamh->user, "log-pam") == 0)
1134 send_info (pamh, "pam_open_session");
1136 if (strcmp (pamh->user, "make-home-dir") == 0)
1138 struct passwd *entry;
1139 entry = getpwnam (pamh->user);
1140 g_mkdir_with_parents (entry->pw_dir, 0755);
1147 pam_close_session (pam_handle_t *pamh, int flags)
1150 return PAM_SYSTEM_ERR;
1152 if (strcmp (pamh->user, "log-pam") == 0)
1153 send_info (pamh, "pam_close_session");
1159 pam_acct_mgmt (pam_handle_t *pamh, int flags)
1162 return PAM_SYSTEM_ERR;
1165 return PAM_USER_UNKNOWN;
1167 if (strcmp (pamh->user, "log-pam") == 0)
1168 send_info (pamh, "pam_acct_mgmt");
1170 if (strcmp (pamh->user, "denied") == 0)
1171 return PAM_PERM_DENIED;
1172 if (strcmp (pamh->user, "expired") == 0)
1173 return PAM_ACCT_EXPIRED;
1174 if (strcmp (pamh->user, "new-authtok") == 0)
1175 return PAM_NEW_AUTHTOK_REQD;
1181 pam_chauthtok (pam_handle_t *pamh, int flags)
1183 struct passwd *entry;
1185 struct pam_message **msg;
1186 struct pam_response *resp = NULL;
1189 return PAM_SYSTEM_ERR;
1191 if (strcmp (pamh->user, "log-pam") == 0)
1192 send_info (pamh, "pam_chauthtok");
1194 msg = malloc (sizeof (struct pam_message *) * 1);
1195 msg[0] = malloc (sizeof (struct pam_message));
1196 msg[0]->msg_style = PAM_PROMPT_ECHO_OFF;
1197 msg[0]->msg = "Enter new password:";
1198 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
1201 if (result != PAM_SUCCESS)
1205 return PAM_CONV_ERR;
1206 if (resp[0].resp == NULL)
1209 return PAM_CONV_ERR;
1212 /* Update password database */
1213 entry = getpwnam (pamh->user);
1214 free (entry->pw_passwd);
1215 entry->pw_passwd = resp[0].resp;
1222 pam_setcred (pam_handle_t *pamh, int flags)
1227 return PAM_SYSTEM_ERR;
1229 if (strcmp (pamh->user, "log-pam") == 0)
1230 send_info (pamh, "pam_setcred");
1232 /* Put the test directories into the path */
1233 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"));
1234 pam_putenv (pamh, e);
1237 if (strcmp (pamh->user, "cred-error") == 0)
1238 return PAM_CRED_ERR;
1239 if (strcmp (pamh->user, "cred-expired") == 0)
1240 return PAM_CRED_EXPIRED;
1241 if (strcmp (pamh->user, "cred-unavail") == 0)
1242 return PAM_CRED_UNAVAIL;
1244 /* Join special groups if requested */
1245 if (strcmp (pamh->user, "group-member") == 0 && flags & PAM_ESTABLISH_CRED)
1247 struct group *group;
1251 group = getgrnam ("test-group");
1254 groups_length = getgroups (0, NULL);
1255 if (groups_length < 0)
1256 return PAM_SYSTEM_ERR;
1257 groups = malloc (sizeof (gid_t) * (groups_length + 1));
1258 groups_length = getgroups (groups_length, groups);
1259 if (groups_length < 0)
1260 return PAM_SYSTEM_ERR;
1261 groups[groups_length] = group->gr_gid;
1263 setgroups (groups_length, groups);
1267 /* We need to pass our group overrides down the child process - the environment via PAM seems the only way to do it easily */
1268 pam_putenv (pamh, g_strdup_printf ("LIGHTDM_TEST_GROUPS=%s", g_getenv ("LIGHTDM_TEST_GROUPS")));
1275 pam_end (pam_handle_t *pamh, int pam_status)
1278 return PAM_SYSTEM_ERR;
1280 free (pamh->service_name);
1284 free (pamh->authtok);
1295 pam_strerror (pam_handle_t *pamh, int errnum)
1305 return "Critical error - immediate abort";
1307 return "Failed to load module";
1308 case PAM_SYMBOL_ERR:
1309 return "Symbol not found";
1310 case PAM_SERVICE_ERR:
1311 return "Error in service module";
1312 case PAM_SYSTEM_ERR:
1313 return "System error";
1315 return "Memory buffer error";
1316 case PAM_PERM_DENIED:
1317 return "Permission denied";
1319 return "Authentication failure";
1320 case PAM_CRED_INSUFFICIENT:
1321 return "Insufficient credentials to access authentication data";
1322 case PAM_AUTHINFO_UNAVAIL:
1323 return "Authentication service cannot retrieve authentication info";
1324 case PAM_USER_UNKNOWN:
1325 return "User not known to the underlying authentication module";
1327 return "Have exhausted maximum number of retries for service";
1328 case PAM_NEW_AUTHTOK_REQD:
1329 return "Authentication token is no longer valid; new one required";
1330 case PAM_ACCT_EXPIRED:
1331 return "User account has expired";
1332 case PAM_SESSION_ERR:
1333 return "Cannot make/remove an entry for the specified session";
1334 case PAM_CRED_UNAVAIL:
1335 return "Authentication service cannot retrieve user credentials";
1336 case PAM_CRED_EXPIRED:
1337 return "User credentials expired";
1339 return "Failure setting user credentials";
1340 case PAM_NO_MODULE_DATA:
1341 return "No module specific data is present";
1343 return "Bad item passed to pam_*_item()";
1345 return "Conversation error";
1346 case PAM_AUTHTOK_ERR:
1347 return "Authentication token manipulation error";
1348 case PAM_AUTHTOK_RECOVERY_ERR:
1349 return "Authentication information cannot be recovered";
1350 case PAM_AUTHTOK_LOCK_BUSY:
1351 return "Authentication token lock busy";
1352 case PAM_AUTHTOK_DISABLE_AGING:
1353 return "Authentication token aging disabled";
1355 return "Failed preliminary check by password service";
1357 return "The return value should be ignored by PAM dispatch";
1358 case PAM_MODULE_UNKNOWN:
1359 return "Module is unknown";
1360 case PAM_AUTHTOK_EXPIRED:
1361 return "Authentication token expired";
1362 case PAM_CONV_AGAIN:
1363 return "Conversation is waiting for event";
1364 case PAM_INCOMPLETE:
1365 return "Application needs to call libpam again";
1367 return "Unknown PAM error";
1377 pututxline (struct utmp *ut)
1387 struct xcb_connection_t
1395 xcb_connect_to_display_with_auth_info (const char *display, xcb_auth_info_t *auth, int *screen)
1397 xcb_connection_t *c;
1399 GError *error = NULL;
1401 c = malloc (sizeof (xcb_connection_t));
1402 c->display = g_strdup (display);
1405 if (display == NULL)
1406 display = getenv ("DISPLAY");
1407 if (display == NULL)
1408 c->error = XCB_CONN_CLOSED_PARSE_ERR;
1412 c->socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &error);
1414 g_printerr ("%s\n", error->message);
1415 g_clear_error (&error);
1416 if (c->socket == NULL)
1417 c->error = XCB_CONN_ERROR;
1423 GSocketAddress *address;
1425 /* Skip the hostname, we'll assume it's localhost */
1426 d = g_strdup_printf (".x%s", strchr (display, ':'));
1428 socket_path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), d, NULL);
1430 address = g_unix_socket_address_new (socket_path);
1431 if (!g_socket_connect (c->socket, address, NULL, &error))
1432 c->error = XCB_CONN_ERROR;
1433 g_object_unref (address);
1435 g_printerr ("Failed to connect to X socket %s: %s\n", socket_path, error->message);
1436 g_free (socket_path);
1437 g_clear_error (&error);
1440 // FIXME: Send auth info
1449 xcb_connect (const char *displayname, int *screenp)
1451 return xcb_connect_to_display_with_auth_info(displayname, NULL, screenp);
1455 xcb_connection_has_error (xcb_connection_t *c)
1461 xcb_disconnect (xcb_connection_t *c)
1465 g_object_unref (c->socket);