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 _access = (int (*)(const char *pathname, int mode)) dlsym (RTLD_NEXT, "access");
295 new_path = redirect_path (pathname);
296 ret = _access (new_path, mode);
303 stat (const char *path, struct stat *buf)
305 int (*_stat) (const char *path, struct stat *buf);
306 gchar *new_path = NULL;
309 _stat = (int (*)(const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "stat");
311 new_path = redirect_path (path);
312 ret = _stat (new_path, buf);
319 stat64 (const char *path, struct stat *buf)
321 int (*_stat64) (const char *path, struct stat *buf);
322 gchar *new_path = NULL;
325 _stat64 = (int (*)(const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "stat64");
327 new_path = redirect_path (path);
328 ret = _stat (new_path, buf);
335 __xstat (int version, const char *path, struct stat *buf)
337 int (*___xstat) (int version, const char *path, struct stat *buf);
338 gchar *new_path = NULL;
341 ___xstat = (int (*)(int version, const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "__xstat");
343 new_path = redirect_path (path);
344 ret = ___xstat (version, new_path, buf);
351 __xstat64 (int version, const char *path, struct stat *buf)
353 int (*___xstat64) (int version, const char *path, struct stat *buf);
354 gchar *new_path = NULL;
357 ___xstat64 = (int (*)(int version, const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "__xstat64");
359 new_path = redirect_path (path);
360 ret = ___xstat64 (version, new_path, buf);
367 opendir (const char *name)
369 DIR *(*_opendir) (const char *name);
370 gchar *new_path = NULL;
373 _opendir = (DIR *(*)(const char *name)) dlsym (RTLD_NEXT, "opendir");
375 new_path = redirect_path (name);
376 result = _opendir (new_path);
383 mkdir (const char *pathname, mode_t mode)
385 int (*_mkdir) (const char *pathname, mode_t mode);
386 gchar *new_path = NULL;
389 _mkdir = (int (*)(const char *pathname, mode_t mode)) dlsym (RTLD_NEXT, "mkdir");
391 new_path = redirect_path (pathname);
392 result = _mkdir (new_path, mode);
399 chown (const char *pathname, uid_t owner, gid_t group)
401 int (*_chown) (const char *pathname, uid_t owner, gid_t group);
402 gchar *new_path = NULL;
405 _chown = (int (*)(const char *pathname, uid_t owner, gid_t group)) dlsym (RTLD_NEXT, "chown");
407 new_path = redirect_path (pathname);
408 result = _chown (new_path, owner, group);
415 ioctl (int d, int request, void *data)
417 int (*_ioctl) (int d, int request, void *data);
419 _ioctl = (int (*)(int d, int request, void *data)) dlsym (RTLD_NEXT, "ioctl");
420 if (d > 0 && d == console_fd)
422 struct vt_stat *console_state;
429 console_state = data;
430 console_state->v_active = active_vt;
433 vt = GPOINTER_TO_INT (data);
437 if (!status_connected)
438 status_connected = status_connect (NULL);
439 status_notify ("VT ACTIVATE VT=%d", active_vt);
448 return _ioctl (d, request, data);
454 int (*_close) (int fd);
456 if (fd > 0 && fd == console_fd)
459 _close = (int (*)(int fd)) dlsym (RTLD_NEXT, "close");
465 free_user (gpointer data)
467 struct passwd *entry = data;
469 g_free (entry->pw_name);
470 g_free (entry->pw_passwd);
471 g_free (entry->pw_gecos);
472 g_free (entry->pw_dir);
473 g_free (entry->pw_shell);
480 gchar *path, *data = NULL, **lines;
482 GError *error = NULL;
484 g_list_free_full (user_entries, free_user);
486 getpwent_link = NULL;
488 path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "passwd", NULL);
489 g_file_get_contents (path, &data, NULL, &error);
492 g_warning ("Error loading passwd file: %s", error->message);
493 g_clear_error (&error);
498 lines = g_strsplit (data, "\n", -1);
501 for (i = 0; lines[i]; i++)
503 gchar *line, **fields;
505 line = g_strstrip (lines[i]);
506 fields = g_strsplit (line, ":", -1);
507 if (g_strv_length (fields) == 7)
509 struct passwd *entry = malloc (sizeof (struct passwd));
511 entry->pw_name = g_strdup (fields[0]);
512 entry->pw_passwd = g_strdup (fields[1]);
513 entry->pw_uid = atoi (fields[2]);
514 entry->pw_gid = atoi (fields[3]);
515 entry->pw_gecos = g_strdup (fields[4]);
516 entry->pw_dir = g_strdup (fields[5]);
517 entry->pw_shell = g_strdup (fields[6]);
518 user_entries = g_list_append (user_entries, entry);
528 if (getpwent_link == NULL)
531 if (user_entries == NULL)
533 getpwent_link = user_entries;
537 if (getpwent_link->next == NULL)
539 getpwent_link = getpwent_link->next;
542 return getpwent_link->data;
548 getpwent_link = NULL;
554 getpwent_link = NULL;
558 getpwnam (const char *name)
567 for (link = user_entries; link; link = link->next)
569 struct passwd *entry = link->data;
570 if (strcmp (entry->pw_name, name) == 0)
586 for (link = user_entries; link; link = link->next)
588 struct passwd *entry = link->data;
589 if (entry->pw_uid == uid)
599 free_group (gpointer data)
601 struct group *entry = data;
603 g_free (entry->gr_name);
604 g_free (entry->gr_passwd);
605 g_strfreev (entry->gr_mem);
612 gchar *path, *data = NULL, **lines;
614 GError *error = NULL;
616 g_list_free_full (group_entries, free_group);
617 group_entries = NULL;
619 path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "group", NULL);
620 g_file_get_contents (path, &data, NULL, &error);
623 g_warning ("Error loading group file: %s", error->message);
624 g_clear_error (&error);
629 lines = g_strsplit (data, "\n", -1);
632 for (i = 0; lines[i]; i++)
634 gchar *line, **fields;
636 line = g_strstrip (lines[i]);
637 fields = g_strsplit (line, ":", -1);
638 if (g_strv_length (fields) == 4)
640 struct group *entry = malloc (sizeof (struct group));
642 entry->gr_name = g_strdup (fields[0]);
643 entry->gr_passwd = g_strdup (fields[1]);
644 entry->gr_gid = atoi (fields[2]);
645 entry->gr_mem = g_strsplit (fields[3], ",", -1);
646 group_entries = g_list_append (group_entries, entry);
654 getgrnam (const char *name)
660 for (link = group_entries; link; link = link->next)
662 struct group *entry = link->data;
663 if (strcmp (entry->gr_name, name) == 0)
679 for (link = group_entries; link; link = link->next)
681 struct group *entry = link->data;
682 if (entry->gr_gid == gid)
692 pam_start (const char *service_name, const char *user, const struct pam_conv *conversation, pam_handle_t **pamh)
694 pam_handle_t *handle;
696 if (service_name == NULL || conversation == NULL || pamh == NULL)
697 return PAM_SYSTEM_ERR;
699 handle = *pamh = malloc (sizeof (pam_handle_t));
703 handle->service_name = strdup (service_name);
704 handle->user = user ? strdup (user) : NULL;
705 handle->authtok = NULL;
706 handle->ruser = NULL;
708 handle->conversation.conv = conversation->conv;
709 handle->conversation.appdata_ptr = conversation->appdata_ptr;
710 handle->envlist = malloc (sizeof (char *) * 1);
711 handle->envlist[0] = NULL;
717 send_info (pam_handle_t *pamh, const char *message)
719 struct pam_message **msg;
720 struct pam_response *resp = NULL;
722 msg = calloc (1, sizeof (struct pam_message *));
723 msg[0] = malloc (sizeof (struct pam_message));
724 msg[0]->msg_style = PAM_TEXT_INFO;
725 msg[0]->msg = message;
726 pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
738 pam_authenticate (pam_handle_t *pamh, int flags)
740 struct passwd *entry;
741 gboolean password_matches = FALSE;
744 return PAM_SYSTEM_ERR;
746 if (strcmp (pamh->service_name, "test-remote") == 0)
749 struct pam_message **msg;
750 struct pam_response *resp = NULL;
752 msg = malloc (sizeof (struct pam_message *) * 1);
753 msg[0] = malloc (sizeof (struct pam_message));
754 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
755 msg[0]->msg = "remote-login:";
756 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
759 if (result != PAM_SUCCESS)
764 if (resp[0].resp == NULL)
772 pamh->ruser = strdup (resp[0].resp);
776 msg = malloc (sizeof (struct pam_message *) * 1);
777 msg[0] = malloc (sizeof (struct pam_message));
778 msg[0]->msg_style = PAM_PROMPT_ECHO_OFF;
779 msg[0]->msg = "remote-password:";
780 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
783 if (result != PAM_SUCCESS)
788 if (resp[0].resp == NULL)
795 free (pamh->authtok);
796 pamh->authtok = strdup (resp[0].resp);
800 password_matches = strcmp (pamh->ruser, "remote-user") == 0 && strcmp (pamh->authtok, "password") == 0;
802 if (password_matches)
808 /* Prompt for username */
809 if (pamh->user == NULL)
812 struct pam_message **msg;
813 struct pam_response *resp = NULL;
815 msg = malloc (sizeof (struct pam_message *) * 1);
816 msg[0] = malloc (sizeof (struct pam_message));
817 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
818 msg[0]->msg = LOGIN_PROMPT;
819 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
822 if (result != PAM_SUCCESS)
827 if (resp[0].resp == NULL)
833 pamh->user = strdup (resp[0].resp);
838 if (strcmp (pamh->user, "log-pam") == 0)
839 send_info (pamh, "pam_authenticate");
841 /* Crash on authenticate */
842 if (strcmp (pamh->user, "crash-authenticate") == 0)
843 kill (getpid (), SIGSEGV);
845 /* Look up password database */
846 entry = getpwnam (pamh->user);
848 /* Prompt for password if required */
849 if (entry && strcmp (pamh->user, "always-password") != 0 && (strcmp (pamh->service_name, "lightdm-autologin") == 0 || strcmp (entry->pw_passwd, "") == 0))
850 password_matches = TRUE;
853 int i, n_messages = 0, password_index, result;
854 struct pam_message **msg;
855 struct pam_response *resp = NULL;
857 msg = malloc (sizeof (struct pam_message *) * 5);
858 if (strcmp (pamh->user, "info-prompt") == 0)
860 msg[n_messages] = malloc (sizeof (struct pam_message));
861 msg[n_messages]->msg_style = PAM_TEXT_INFO;
862 msg[n_messages]->msg = "Welcome to LightDM";
865 if (strcmp (pamh->user, "multi-info-prompt") == 0)
867 msg[n_messages] = malloc (sizeof (struct pam_message));
868 msg[n_messages]->msg_style = PAM_TEXT_INFO;
869 msg[n_messages]->msg = "Welcome to LightDM";
871 msg[n_messages] = malloc (sizeof (struct pam_message));
872 msg[n_messages]->msg_style = PAM_ERROR_MSG;
873 msg[n_messages]->msg = "This is an error";
875 msg[n_messages] = malloc (sizeof (struct pam_message));
876 msg[n_messages]->msg_style = PAM_TEXT_INFO;
877 msg[n_messages]->msg = "You should have seen three messages";
880 if (strcmp (pamh->user, "multi-prompt") == 0)
882 msg[n_messages] = malloc (sizeof (struct pam_message));
883 msg[n_messages]->msg_style = PAM_PROMPT_ECHO_ON;
884 msg[n_messages]->msg = "Favorite Color:";
887 msg[n_messages] = malloc (sizeof (struct pam_message));
888 msg[n_messages]->msg_style = PAM_PROMPT_ECHO_OFF;
889 msg[n_messages]->msg = "Password:";
890 password_index = n_messages;
892 result = pamh->conversation.conv (n_messages, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
893 for (i = 0; i < n_messages; i++)
896 if (result != PAM_SUCCESS)
901 if (resp[password_index].resp == NULL)
908 password_matches = strcmp (entry->pw_passwd, resp[password_index].resp) == 0;
910 if (password_matches && strcmp (pamh->user, "multi-prompt") == 0)
911 password_matches = strcmp ("blue", resp[0].resp) == 0;
913 for (i = 0; i < n_messages; i++)
920 /* Do two factor authentication */
921 if (password_matches && strcmp (pamh->user, "two-factor") == 0)
923 msg = malloc (sizeof (struct pam_message *) * 1);
924 msg[0] = malloc (sizeof (struct pam_message));
925 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
926 msg[0]->msg = "OTP:";
928 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
934 if (resp[0].resp == NULL)
939 password_matches = strcmp (resp[0].resp, "otp") == 0;
945 /* Special user has home directory created on login */
946 if (password_matches && strcmp (pamh->user, "mount-home-dir") == 0)
947 g_mkdir_with_parents (entry->pw_dir, 0755);
949 /* Special user 'change-user1' changes user on authentication */
950 if (password_matches && strcmp (pamh->user, "change-user1") == 0)
953 pamh->user = g_strdup ("change-user2");
956 /* Special user 'change-user-invalid' changes to an invalid user on authentication */
957 if (password_matches && strcmp (pamh->user, "change-user-invalid") == 0)
960 pamh->user = g_strdup ("invalid-user");
963 if (password_matches)
970 get_env_value (const char *name_value, const char *name)
974 for (j = 0; name[j] && name_value[j] && name[j] == name_value[j]; j++);
975 if (name[j] == '\0' && name_value[j] == '=')
976 return &name_value[j + 1];
982 pam_putenv (pam_handle_t *pamh, const char *name_value)
987 if (pamh == NULL || name_value == NULL)
988 return PAM_SYSTEM_ERR;
990 name = strdup (name_value);
991 for (i = 0; name[i]; i++)
994 for (i = 0; pamh->envlist[i]; i++)
996 if (get_env_value (pamh->envlist[i], name))
1001 if (pamh->envlist[i])
1003 free (pamh->envlist[i]);
1004 pamh->envlist[i] = strdup (name_value);
1008 pamh->envlist = realloc (pamh->envlist, sizeof (char *) * (i + 2));
1009 pamh->envlist[i] = strdup (name_value);
1010 pamh->envlist[i + 1] = NULL;
1017 pam_getenv (pam_handle_t *pamh, const char *name)
1021 if (pamh == NULL || name == NULL)
1024 for (i = 0; pamh->envlist[i]; i++)
1027 value = get_env_value (pamh->envlist[i], name);
1036 pam_getenvlist (pam_handle_t *pamh)
1041 return pamh->envlist;
1045 pam_set_item (pam_handle_t *pamh, int item_type, const void *item)
1047 if (pamh == NULL || item == NULL)
1048 return PAM_SYSTEM_ERR;
1055 pamh->tty = strdup ((const char *) item);
1059 return PAM_BAD_ITEM;
1064 pam_get_item (const pam_handle_t *pamh, int item_type, const void **item)
1066 if (pamh == NULL || item == NULL)
1067 return PAM_SYSTEM_ERR;
1072 *item = pamh->service_name;
1080 *item = pamh->authtok;
1084 *item = pamh->ruser;
1087 case PAM_USER_PROMPT:
1088 *item = LOGIN_PROMPT;
1096 *item = &pamh->conversation;
1100 return PAM_BAD_ITEM;
1105 pam_open_session (pam_handle_t *pamh, int flags)
1108 return PAM_SYSTEM_ERR;
1110 if (strcmp (pamh->user, "session-error") == 0)
1111 return PAM_SESSION_ERR;
1113 if (strcmp (pamh->user, "log-pam") == 0)
1114 send_info (pamh, "pam_open_session");
1116 if (strcmp (pamh->user, "make-home-dir") == 0)
1118 struct passwd *entry;
1119 entry = getpwnam (pamh->user);
1120 g_mkdir_with_parents (entry->pw_dir, 0755);
1127 pam_close_session (pam_handle_t *pamh, int flags)
1130 return PAM_SYSTEM_ERR;
1132 if (strcmp (pamh->user, "log-pam") == 0)
1133 send_info (pamh, "pam_close_session");
1139 pam_acct_mgmt (pam_handle_t *pamh, int flags)
1142 return PAM_SYSTEM_ERR;
1145 return PAM_USER_UNKNOWN;
1147 if (strcmp (pamh->user, "log-pam") == 0)
1148 send_info (pamh, "pam_acct_mgmt");
1150 if (strcmp (pamh->user, "denied") == 0)
1151 return PAM_PERM_DENIED;
1152 if (strcmp (pamh->user, "expired") == 0)
1153 return PAM_ACCT_EXPIRED;
1154 if (strcmp (pamh->user, "new-authtok") == 0)
1155 return PAM_NEW_AUTHTOK_REQD;
1161 pam_chauthtok (pam_handle_t *pamh, int flags)
1163 struct passwd *entry;
1165 struct pam_message **msg;
1166 struct pam_response *resp = NULL;
1169 return PAM_SYSTEM_ERR;
1171 if (strcmp (pamh->user, "log-pam") == 0)
1172 send_info (pamh, "pam_chauthtok");
1174 msg = malloc (sizeof (struct pam_message *) * 1);
1175 msg[0] = malloc (sizeof (struct pam_message));
1176 msg[0]->msg_style = PAM_PROMPT_ECHO_OFF;
1177 msg[0]->msg = "Enter new password:";
1178 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
1181 if (result != PAM_SUCCESS)
1185 return PAM_CONV_ERR;
1186 if (resp[0].resp == NULL)
1189 return PAM_CONV_ERR;
1192 /* Update password database */
1193 entry = getpwnam (pamh->user);
1194 free (entry->pw_passwd);
1195 entry->pw_passwd = resp[0].resp;
1202 pam_setcred (pam_handle_t *pamh, int flags)
1207 return PAM_SYSTEM_ERR;
1209 if (strcmp (pamh->user, "log-pam") == 0)
1210 send_info (pamh, "pam_setcred");
1212 /* Put the test directories into the path */
1213 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"));
1214 pam_putenv (pamh, e);
1217 if (strcmp (pamh->user, "cred-error") == 0)
1218 return PAM_CRED_ERR;
1219 if (strcmp (pamh->user, "cred-expired") == 0)
1220 return PAM_CRED_EXPIRED;
1221 if (strcmp (pamh->user, "cred-unavail") == 0)
1222 return PAM_CRED_UNAVAIL;
1224 /* Join special groups if requested */
1225 if (strcmp (pamh->user, "group-member") == 0 && flags & PAM_ESTABLISH_CRED)
1227 struct group *group;
1231 group = getgrnam ("test-group");
1234 groups_length = getgroups (0, NULL);
1235 groups = malloc (sizeof (gid_t) * (groups_length + 1));
1236 groups_length = getgroups (groups_length, groups);
1237 groups[groups_length] = group->gr_gid;
1239 setgroups (groups_length, groups);
1243 /* We need to pass our group overrides down the child process - the environment via PAM seems the only way to do it easily */
1244 pam_putenv (pamh, g_strdup_printf ("LIGHTDM_TEST_GROUPS=%s", g_getenv ("LIGHTDM_TEST_GROUPS")));
1251 pam_end (pam_handle_t *pamh, int pam_status)
1254 return PAM_SYSTEM_ERR;
1256 free (pamh->service_name);
1260 free (pamh->authtok);
1271 pam_strerror (pam_handle_t *pamh, int errnum)
1281 return "Critical error - immediate abort";
1283 return "Failed to load module";
1284 case PAM_SYMBOL_ERR:
1285 return "Symbol not found";
1286 case PAM_SERVICE_ERR:
1287 return "Error in service module";
1288 case PAM_SYSTEM_ERR:
1289 return "System error";
1291 return "Memory buffer error";
1292 case PAM_PERM_DENIED:
1293 return "Permission denied";
1295 return "Authentication failure";
1296 case PAM_CRED_INSUFFICIENT:
1297 return "Insufficient credentials to access authentication data";
1298 case PAM_AUTHINFO_UNAVAIL:
1299 return "Authentication service cannot retrieve authentication info";
1300 case PAM_USER_UNKNOWN:
1301 return "User not known to the underlying authentication module";
1303 return "Have exhausted maximum number of retries for service";
1304 case PAM_NEW_AUTHTOK_REQD:
1305 return "Authentication token is no longer valid; new one required";
1306 case PAM_ACCT_EXPIRED:
1307 return "User account has expired";
1308 case PAM_SESSION_ERR:
1309 return "Cannot make/remove an entry for the specified session";
1310 case PAM_CRED_UNAVAIL:
1311 return "Authentication service cannot retrieve user credentials";
1312 case PAM_CRED_EXPIRED:
1313 return "User credentials expired";
1315 return "Failure setting user credentials";
1316 case PAM_NO_MODULE_DATA:
1317 return "No module specific data is present";
1319 return "Bad item passed to pam_*_item()";
1321 return "Conversation error";
1322 case PAM_AUTHTOK_ERR:
1323 return "Authentication token manipulation error";
1324 case PAM_AUTHTOK_RECOVERY_ERR:
1325 return "Authentication information cannot be recovered";
1326 case PAM_AUTHTOK_LOCK_BUSY:
1327 return "Authentication token lock busy";
1328 case PAM_AUTHTOK_DISABLE_AGING:
1329 return "Authentication token aging disabled";
1331 return "Failed preliminary check by password service";
1333 return "The return value should be ignored by PAM dispatch";
1334 case PAM_MODULE_UNKNOWN:
1335 return "Module is unknown";
1336 case PAM_AUTHTOK_EXPIRED:
1337 return "Authentication token expired";
1338 case PAM_CONV_AGAIN:
1339 return "Conversation is waiting for event";
1340 case PAM_INCOMPLETE:
1341 return "Application needs to call libpam again";
1343 return "Unknown PAM error";
1353 pututxline (struct utmp *ut)
1363 struct xcb_connection_t
1371 xcb_connect_to_display_with_auth_info (const char *display, xcb_auth_info_t *auth, int *screen)
1373 xcb_connection_t *c;
1375 GSocketAddress *address;
1376 GError *error = NULL;
1378 c = malloc (sizeof (xcb_connection_t));
1379 c->display = g_strdup (display);
1382 if (display == NULL)
1383 display = getenv ("DISPLAY");
1384 if (display == NULL)
1385 c->error = XCB_CONN_CLOSED_PARSE_ERR;
1389 c->socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &error);
1391 g_printerr ("%s\n", error->message);
1392 g_clear_error (&error);
1393 if (c->socket == NULL)
1394 c->error = XCB_CONN_ERROR;
1401 /* Skip the hostname, we'll assume it's localhost */
1402 d = g_strdup_printf (".x%s", strchr (display, ':'));
1404 socket_path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), d, NULL);
1406 address = g_unix_socket_address_new (socket_path);
1407 if (!g_socket_connect (c->socket, address, NULL, &error))
1408 c->error = XCB_CONN_ERROR;
1410 g_printerr ("Failed to connect to X socket %s: %s\n", socket_path, error->message);
1411 g_free (socket_path);
1412 g_clear_error (&error);
1415 // FIXME: Send auth info
1420 g_object_unref (address);
1426 xcb_connect (const char *displayname, int *screenp)
1428 return xcb_connect_to_display_with_auth_info(displayname, NULL, screenp);
1432 xcb_connection_has_error (xcb_connection_t *c)
1438 xcb_disconnect (xcb_connection_t *c)
1442 g_object_unref (c->socket);