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;
40 struct pam_conv conversation;
56 initgroups (const char *user, gid_t group)
67 getgroups (int size, gid_t list[])
69 const gchar *group_list;
73 /* Get groups we are a member of */
74 group_list = g_getenv ("LIGHTDM_TEST_GROUPS");
77 groups = g_strsplit (group_list, ",", -1);
78 groups_length = g_strv_length (groups);
84 if (groups_length > size)
89 for (i = 0; groups[i]; i++)
90 list[i] = atoi (groups[i]);
98 setgroups (size_t size, const gid_t *list)
103 group_list = g_string_new ("");
104 for (i = 0; i < size; i++)
107 g_string_append (group_list, ",");
108 g_string_append_printf (group_list, "%d", list[i]);
110 g_setenv ("LIGHTDM_TEST_GROUPS", group_list->str, TRUE);
111 g_string_free (group_list, TRUE);
129 setresgid (gid_t rgid, gid_t ugid, gid_t sgid)
147 setresuid (uid_t ruid, uid_t uuid, uid_t suid)
153 redirect_path (const gchar *path)
158 // Don't redirect if inside the running directory
159 if (g_str_has_prefix (path, g_getenv ("LIGHTDM_TEST_ROOT")))
160 return g_strdup (path);
162 if (g_str_has_prefix (path, SYSCONFDIR))
163 return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", path + strlen (SYSCONFDIR), NULL);
165 if (g_str_has_prefix (path, LOCALSTATEDIR))
166 return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "var", path + strlen (LOCALSTATEDIR), NULL);
168 if (g_str_has_prefix (path, DATADIR))
169 return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "usr", "share", path + strlen (DATADIR), NULL);
171 // Don't redirect if inside the build directory
172 if (g_str_has_prefix (path, BUILDDIR))
173 return g_strdup (path);
175 if (g_str_has_prefix (path, "/tmp"))
176 return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "tmp", path + strlen ("tmp"), NULL);
178 return g_strdup (path);
183 open_wrapper (const char *func, const char *pathname, int flags, mode_t mode)
185 int (*_open) (const char *pathname, int flags, mode_t mode);
186 gchar *new_path = NULL;
189 _open = (int (*)(const char *pathname, int flags, mode_t mode)) dlsym (RTLD_NEXT, func);
191 if (strcmp (pathname, "/dev/console") == 0)
195 console_fd = _open ("/dev/null", flags, mode);
196 fcntl (console_fd, F_SETFD, FD_CLOEXEC);
201 new_path = redirect_path (pathname);
202 fd = _open (new_path, flags, mode);
209 open (const char *pathname, int flags, ...)
215 va_start (ap, flags);
216 mode = va_arg (ap, mode_t);
219 return open_wrapper ("open", pathname, flags, mode);
223 open64 (const char *pathname, int flags, ...)
229 va_start (ap, flags);
230 mode = va_arg (ap, mode_t);
233 return open_wrapper ("open64", pathname, flags, mode);
237 fopen (const char *path, const char *mode)
239 FILE *(*_fopen) (const char *pathname, const char *mode);
240 gchar *new_path = NULL;
243 _fopen = (FILE *(*)(const char *pathname, const char *mode)) dlsym (RTLD_NEXT, "fopen");
245 new_path = redirect_path (path);
246 result = _fopen (new_path, mode);
253 creat (const char *pathname, mode_t mode)
255 int (*_creat) (const char *pathname, mode_t mode);
256 gchar *new_path = NULL;
259 _creat = (int (*)(const char *pathname, mode_t mode)) dlsym (RTLD_NEXT, "creat");
261 new_path = redirect_path (pathname);
262 result = _creat (new_path, mode);
269 creat64 (const char *pathname, mode_t mode)
271 int (*_creat64) (const char *pathname, mode_t mode);
272 gchar *new_path = NULL;
275 _creat64 = (int (*)(const char *pathname, mode_t mode)) dlsym (RTLD_NEXT, "creat64");
277 new_path = redirect_path (pathname);
278 result = _creat64 (new_path, mode);
285 access (const char *pathname, int mode)
287 int (*_access) (const char *pathname, int mode);
288 gchar *new_path = NULL;
291 _access = (int (*)(const char *pathname, int mode)) dlsym (RTLD_NEXT, "access");
293 new_path = redirect_path (pathname);
294 ret = _access (new_path, mode);
301 stat (const char *path, struct stat *buf)
303 int (*_stat) (const char *path, struct stat *buf);
304 gchar *new_path = NULL;
307 _stat = (int (*)(const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "stat");
309 new_path = redirect_path (path);
310 ret = _stat (new_path, buf);
317 stat64 (const char *path, struct stat *buf)
319 int (*_stat64) (const char *path, struct stat *buf);
320 gchar *new_path = NULL;
323 _stat64 = (int (*)(const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "stat64");
325 new_path = redirect_path (path);
326 ret = _stat (new_path, buf);
333 __xstat (int version, const char *path, struct stat *buf)
335 int (*___xstat) (int version, const char *path, struct stat *buf);
336 gchar *new_path = NULL;
339 ___xstat = (int (*)(int version, const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "__xstat");
341 new_path = redirect_path (path);
342 ret = ___xstat (version, new_path, buf);
349 __xstat64 (int version, const char *path, struct stat *buf)
351 int (*___xstat64) (int version, const char *path, struct stat *buf);
352 gchar *new_path = NULL;
355 ___xstat64 = (int (*)(int version, const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "__xstat64");
357 new_path = redirect_path (path);
358 ret = ___xstat64 (version, new_path, buf);
365 opendir (const char *name)
367 DIR *(*_opendir) (const char *name);
368 gchar *new_path = NULL;
371 _opendir = (DIR *(*)(const char *name)) dlsym (RTLD_NEXT, "opendir");
373 new_path = redirect_path (name);
374 result = _opendir (new_path);
381 mkdir (const char *pathname, mode_t mode)
383 int (*_mkdir) (const char *pathname, mode_t mode);
384 gchar *new_path = NULL;
387 _mkdir = (int (*)(const char *pathname, mode_t mode)) dlsym (RTLD_NEXT, "mkdir");
389 new_path = redirect_path (pathname);
390 result = _mkdir (new_path, mode);
397 chown (const char *pathname, uid_t owner, gid_t group)
399 int (*_chown) (const char *pathname, uid_t owner, gid_t group);
400 gchar *new_path = NULL;
403 _chown = (int (*)(const char *pathname, uid_t owner, gid_t group)) dlsym (RTLD_NEXT, "chown");
405 new_path = redirect_path (pathname);
406 result = _chown (new_path, owner, group);
413 ioctl (int d, int request, void *data)
415 int (*_ioctl) (int d, int request, void *data);
417 _ioctl = (int (*)(int d, int request, void *data)) dlsym (RTLD_NEXT, "ioctl");
418 if (d > 0 && d == console_fd)
420 struct vt_stat *console_state;
426 console_state = data;
427 console_state->v_active = active_vt;
430 active_vt = GPOINTER_TO_INT (data);
438 return _ioctl (d, request, data);
444 int (*_close) (int fd);
446 if (fd > 0 && fd == console_fd)
449 _close = (int (*)(int fd)) dlsym (RTLD_NEXT, "close");
455 free_user (gpointer data)
457 struct passwd *entry = data;
459 g_free (entry->pw_name);
460 g_free (entry->pw_passwd);
461 g_free (entry->pw_gecos);
462 g_free (entry->pw_dir);
463 g_free (entry->pw_shell);
470 gchar *path, *data = NULL, **lines;
472 GError *error = NULL;
474 g_list_free_full (user_entries, free_user);
476 getpwent_link = NULL;
478 path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "passwd", NULL);
479 g_file_get_contents (path, &data, NULL, &error);
482 g_warning ("Error loading passwd file: %s", error->message);
483 g_clear_error (&error);
488 lines = g_strsplit (data, "\n", -1);
491 for (i = 0; lines[i]; i++)
493 gchar *line, **fields;
495 line = g_strstrip (lines[i]);
496 fields = g_strsplit (line, ":", -1);
497 if (g_strv_length (fields) == 7)
499 struct passwd *entry = malloc (sizeof (struct passwd));
501 entry->pw_name = g_strdup (fields[0]);
502 entry->pw_passwd = g_strdup (fields[1]);
503 entry->pw_uid = atoi (fields[2]);
504 entry->pw_gid = atoi (fields[3]);
505 entry->pw_gecos = g_strdup (fields[4]);
506 entry->pw_dir = g_strdup (fields[5]);
507 entry->pw_shell = g_strdup (fields[6]);
508 user_entries = g_list_append (user_entries, entry);
518 if (getpwent_link == NULL)
521 if (user_entries == NULL)
523 getpwent_link = user_entries;
527 if (getpwent_link->next == NULL)
529 getpwent_link = getpwent_link->next;
532 return getpwent_link->data;
538 getpwent_link = NULL;
544 getpwent_link = NULL;
548 getpwnam (const char *name)
557 for (link = user_entries; link; link = link->next)
559 struct passwd *entry = link->data;
560 if (strcmp (entry->pw_name, name) == 0)
576 for (link = user_entries; link; link = link->next)
578 struct passwd *entry = link->data;
579 if (entry->pw_uid == uid)
589 free_group (gpointer data)
591 struct group *entry = data;
593 g_free (entry->gr_name);
594 g_free (entry->gr_passwd);
595 g_strfreev (entry->gr_mem);
602 gchar *path, *data = NULL, **lines;
604 GError *error = NULL;
606 g_list_free_full (group_entries, free_group);
607 group_entries = NULL;
609 path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "group", NULL);
610 g_file_get_contents (path, &data, NULL, &error);
613 g_warning ("Error loading group file: %s", error->message);
614 g_clear_error (&error);
619 lines = g_strsplit (data, "\n", -1);
622 for (i = 0; lines[i]; i++)
624 gchar *line, **fields;
626 line = g_strstrip (lines[i]);
627 fields = g_strsplit (line, ":", -1);
628 if (g_strv_length (fields) == 4)
630 struct group *entry = malloc (sizeof (struct group));
632 entry->gr_name = g_strdup (fields[0]);
633 entry->gr_passwd = g_strdup (fields[1]);
634 entry->gr_gid = atoi (fields[2]);
635 entry->gr_mem = g_strsplit (fields[3], ",", -1);
636 group_entries = g_list_append (group_entries, entry);
644 getgrnam (const char *name)
650 for (link = group_entries; link; link = link->next)
652 struct group *entry = link->data;
653 if (strcmp (entry->gr_name, name) == 0)
669 for (link = group_entries; link; link = link->next)
671 struct group *entry = link->data;
672 if (entry->gr_gid == gid)
682 pam_start (const char *service_name, const char *user, const struct pam_conv *conversation, pam_handle_t **pamh)
684 pam_handle_t *handle;
686 if (service_name == NULL || conversation == NULL || pamh == NULL)
687 return PAM_SYSTEM_ERR;
689 handle = *pamh = malloc (sizeof (pam_handle_t));
693 handle->service_name = strdup (service_name);
694 handle->user = user ? strdup (user) : NULL;
695 handle->authtok = NULL;
696 handle->ruser = NULL;
698 handle->conversation.conv = conversation->conv;
699 handle->conversation.appdata_ptr = conversation->appdata_ptr;
700 handle->envlist = malloc (sizeof (char *) * 1);
701 handle->envlist[0] = NULL;
707 send_info (pam_handle_t *pamh, const char *message)
709 struct pam_message **msg;
710 struct pam_response *resp = NULL;
712 msg = calloc (1, sizeof (struct pam_message *));
713 msg[0] = malloc (sizeof (struct pam_message));
714 msg[0]->msg_style = PAM_TEXT_INFO;
715 msg[0]->msg = message;
716 pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
728 pam_authenticate (pam_handle_t *pamh, int flags)
730 struct passwd *entry;
731 gboolean password_matches = FALSE;
734 return PAM_SYSTEM_ERR;
736 if (strcmp (pamh->service_name, "test-remote") == 0)
739 struct pam_message **msg;
740 struct pam_response *resp = NULL;
742 msg = malloc (sizeof (struct pam_message *) * 1);
743 msg[0] = malloc (sizeof (struct pam_message));
744 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
745 msg[0]->msg = "remote-login:";
746 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
749 if (result != PAM_SUCCESS)
754 if (resp[0].resp == NULL)
762 pamh->ruser = strdup (resp[0].resp);
766 msg = malloc (sizeof (struct pam_message *) * 1);
767 msg[0] = malloc (sizeof (struct pam_message));
768 msg[0]->msg_style = PAM_PROMPT_ECHO_OFF;
769 msg[0]->msg = "remote-password:";
770 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
773 if (result != PAM_SUCCESS)
778 if (resp[0].resp == NULL)
785 free (pamh->authtok);
786 pamh->authtok = strdup (resp[0].resp);
790 password_matches = strcmp (pamh->ruser, "remote-user") == 0 && strcmp (pamh->authtok, "password") == 0;
792 if (password_matches)
798 /* Prompt for username */
799 if (pamh->user == NULL)
802 struct pam_message **msg;
803 struct pam_response *resp = NULL;
805 msg = malloc (sizeof (struct pam_message *) * 1);
806 msg[0] = malloc (sizeof (struct pam_message));
807 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
808 msg[0]->msg = LOGIN_PROMPT;
809 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
812 if (result != PAM_SUCCESS)
817 if (resp[0].resp == NULL)
823 pamh->user = strdup (resp[0].resp);
828 if (strcmp (pamh->user, "log-pam") == 0)
829 send_info (pamh, "pam_authenticate");
831 /* Crash on authenticate */
832 if (strcmp (pamh->user, "crash-authenticate") == 0)
833 kill (getpid (), SIGSEGV);
835 /* Look up password database */
836 entry = getpwnam (pamh->user);
838 /* Prompt for password if required */
839 if (entry && strcmp (pamh->user, "always-password") != 0 && (strcmp (pamh->service_name, "lightdm-autologin") == 0 || strcmp (entry->pw_passwd, "") == 0))
840 password_matches = TRUE;
843 int i, n_messages = 0, password_index, result;
844 struct pam_message **msg;
845 struct pam_response *resp = NULL;
847 msg = malloc (sizeof (struct pam_message *) * 5);
848 if (strcmp (pamh->user, "info-prompt") == 0)
850 msg[n_messages] = malloc (sizeof (struct pam_message));
851 msg[n_messages]->msg_style = PAM_TEXT_INFO;
852 msg[n_messages]->msg = "Welcome to LightDM";
855 if (strcmp (pamh->user, "multi-info-prompt") == 0)
857 msg[n_messages] = malloc (sizeof (struct pam_message));
858 msg[n_messages]->msg_style = PAM_TEXT_INFO;
859 msg[n_messages]->msg = "Welcome to LightDM";
861 msg[n_messages] = malloc (sizeof (struct pam_message));
862 msg[n_messages]->msg_style = PAM_ERROR_MSG;
863 msg[n_messages]->msg = "This is an error";
865 msg[n_messages] = malloc (sizeof (struct pam_message));
866 msg[n_messages]->msg_style = PAM_TEXT_INFO;
867 msg[n_messages]->msg = "You should have seen three messages";
870 if (strcmp (pamh->user, "multi-prompt") == 0)
872 msg[n_messages] = malloc (sizeof (struct pam_message));
873 msg[n_messages]->msg_style = PAM_PROMPT_ECHO_ON;
874 msg[n_messages]->msg = "Favorite Color:";
877 msg[n_messages] = malloc (sizeof (struct pam_message));
878 msg[n_messages]->msg_style = PAM_PROMPT_ECHO_OFF;
879 msg[n_messages]->msg = "Password:";
880 password_index = n_messages;
882 result = pamh->conversation.conv (n_messages, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
883 for (i = 0; i < n_messages; i++)
886 if (result != PAM_SUCCESS)
891 if (resp[password_index].resp == NULL)
898 password_matches = strcmp (entry->pw_passwd, resp[password_index].resp) == 0;
900 if (password_matches && strcmp (pamh->user, "multi-prompt") == 0)
901 password_matches = strcmp ("blue", resp[0].resp) == 0;
903 for (i = 0; i < n_messages; i++)
910 /* Do two factor authentication */
911 if (password_matches && strcmp (pamh->user, "two-factor") == 0)
913 msg = malloc (sizeof (struct pam_message *) * 1);
914 msg[0] = malloc (sizeof (struct pam_message));
915 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
916 msg[0]->msg = "OTP:";
918 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
924 if (resp[0].resp == NULL)
929 password_matches = strcmp (resp[0].resp, "otp") == 0;
935 /* Special user has home directory created on login */
936 if (password_matches && strcmp (pamh->user, "mount-home-dir") == 0)
937 g_mkdir_with_parents (entry->pw_dir, 0755);
939 /* Special user 'change-user1' changes user on authentication */
940 if (password_matches && strcmp (pamh->user, "change-user1") == 0)
943 pamh->user = g_strdup ("change-user2");
946 /* Special user 'change-user-invalid' changes to an invalid user on authentication */
947 if (password_matches && strcmp (pamh->user, "change-user-invalid") == 0)
950 pamh->user = g_strdup ("invalid-user");
953 if (password_matches)
960 get_env_value (const char *name_value, const char *name)
964 for (j = 0; name[j] && name_value[j] && name[j] == name_value[j]; j++);
965 if (name[j] == '\0' && name_value[j] == '=')
966 return &name_value[j + 1];
972 pam_putenv (pam_handle_t *pamh, const char *name_value)
977 if (pamh == NULL || name_value == NULL)
978 return PAM_SYSTEM_ERR;
980 name = strdup (name_value);
981 for (i = 0; name[i]; i++)
984 for (i = 0; pamh->envlist[i]; i++)
986 if (get_env_value (pamh->envlist[i], name))
991 if (pamh->envlist[i])
993 free (pamh->envlist[i]);
994 pamh->envlist[i] = strdup (name_value);
998 pamh->envlist = realloc (pamh->envlist, sizeof (char *) * (i + 2));
999 pamh->envlist[i] = strdup (name_value);
1000 pamh->envlist[i + 1] = NULL;
1007 pam_getenv (pam_handle_t *pamh, const char *name)
1011 if (pamh == NULL || name == NULL)
1014 for (i = 0; pamh->envlist[i]; i++)
1017 value = get_env_value (pamh->envlist[i], name);
1026 pam_getenvlist (pam_handle_t *pamh)
1031 return pamh->envlist;
1035 pam_set_item (pam_handle_t *pamh, int item_type, const void *item)
1037 if (pamh == NULL || item == NULL)
1038 return PAM_SYSTEM_ERR;
1045 pamh->tty = strdup ((const char *) item);
1049 return PAM_BAD_ITEM;
1054 pam_get_item (const pam_handle_t *pamh, int item_type, const void **item)
1056 if (pamh == NULL || item == NULL)
1057 return PAM_SYSTEM_ERR;
1062 *item = pamh->service_name;
1070 *item = pamh->authtok;
1074 *item = pamh->ruser;
1077 case PAM_USER_PROMPT:
1078 *item = LOGIN_PROMPT;
1086 *item = &pamh->conversation;
1090 return PAM_BAD_ITEM;
1095 pam_open_session (pam_handle_t *pamh, int flags)
1098 return PAM_SYSTEM_ERR;
1100 if (strcmp (pamh->user, "session-error") == 0)
1101 return PAM_SESSION_ERR;
1103 if (strcmp (pamh->user, "log-pam") == 0)
1104 send_info (pamh, "pam_open_session");
1106 if (strcmp (pamh->user, "make-home-dir") == 0)
1108 struct passwd *entry;
1109 entry = getpwnam (pamh->user);
1110 g_mkdir_with_parents (entry->pw_dir, 0755);
1117 pam_close_session (pam_handle_t *pamh, int flags)
1120 return PAM_SYSTEM_ERR;
1122 if (strcmp (pamh->user, "log-pam") == 0)
1123 send_info (pamh, "pam_close_session");
1129 pam_acct_mgmt (pam_handle_t *pamh, int flags)
1132 return PAM_SYSTEM_ERR;
1135 return PAM_USER_UNKNOWN;
1137 if (strcmp (pamh->user, "log-pam") == 0)
1138 send_info (pamh, "pam_acct_mgmt");
1140 if (strcmp (pamh->user, "denied") == 0)
1141 return PAM_PERM_DENIED;
1142 if (strcmp (pamh->user, "expired") == 0)
1143 return PAM_ACCT_EXPIRED;
1144 if (strcmp (pamh->user, "new-authtok") == 0)
1145 return PAM_NEW_AUTHTOK_REQD;
1151 pam_chauthtok (pam_handle_t *pamh, int flags)
1153 struct passwd *entry;
1155 struct pam_message **msg;
1156 struct pam_response *resp = NULL;
1159 return PAM_SYSTEM_ERR;
1161 if (strcmp (pamh->user, "log-pam") == 0)
1162 send_info (pamh, "pam_chauthtok");
1164 msg = malloc (sizeof (struct pam_message *) * 1);
1165 msg[0] = malloc (sizeof (struct pam_message));
1166 msg[0]->msg_style = PAM_PROMPT_ECHO_OFF;
1167 msg[0]->msg = "Enter new password:";
1168 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
1171 if (result != PAM_SUCCESS)
1175 return PAM_CONV_ERR;
1176 if (resp[0].resp == NULL)
1179 return PAM_CONV_ERR;
1182 /* Update password database */
1183 entry = getpwnam (pamh->user);
1184 free (entry->pw_passwd);
1185 entry->pw_passwd = resp[0].resp;
1192 pam_setcred (pam_handle_t *pamh, int flags)
1197 return PAM_SYSTEM_ERR;
1199 if (strcmp (pamh->user, "log-pam") == 0)
1200 send_info (pamh, "pam_setcred");
1202 /* Put the test directories into the path */
1203 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"));
1204 pam_putenv (pamh, e);
1207 if (strcmp (pamh->user, "cred-error") == 0)
1208 return PAM_CRED_ERR;
1209 if (strcmp (pamh->user, "cred-expired") == 0)
1210 return PAM_CRED_EXPIRED;
1211 if (strcmp (pamh->user, "cred-unavail") == 0)
1212 return PAM_CRED_UNAVAIL;
1214 /* Join special groups if requested */
1215 if (strcmp (pamh->user, "group-member") == 0 && flags & PAM_ESTABLISH_CRED)
1217 struct group *group;
1221 group = getgrnam ("test-group");
1224 groups_length = getgroups (0, NULL);
1225 groups = malloc (sizeof (gid_t) * (groups_length + 1));
1226 groups_length = getgroups (groups_length, groups);
1227 groups[groups_length] = group->gr_gid;
1229 setgroups (groups_length, groups);
1233 /* We need to pass our group overrides down the child process - the environment via PAM seems the only way to do it easily */
1234 pam_putenv (pamh, g_strdup_printf ("LIGHTDM_TEST_GROUPS=%s", g_getenv ("LIGHTDM_TEST_GROUPS")));
1241 pam_end (pam_handle_t *pamh, int pam_status)
1244 return PAM_SYSTEM_ERR;
1246 free (pamh->service_name);
1250 free (pamh->authtok);
1261 pam_strerror (pam_handle_t *pamh, int errnum)
1271 return "Critical error - immediate abort";
1273 return "Failed to load module";
1274 case PAM_SYMBOL_ERR:
1275 return "Symbol not found";
1276 case PAM_SERVICE_ERR:
1277 return "Error in service module";
1278 case PAM_SYSTEM_ERR:
1279 return "System error";
1281 return "Memory buffer error";
1282 case PAM_PERM_DENIED:
1283 return "Permission denied";
1285 return "Authentication failure";
1286 case PAM_CRED_INSUFFICIENT:
1287 return "Insufficient credentials to access authentication data";
1288 case PAM_AUTHINFO_UNAVAIL:
1289 return "Authentication service cannot retrieve authentication info";
1290 case PAM_USER_UNKNOWN:
1291 return "User not known to the underlying authentication module";
1293 return "Have exhausted maximum number of retries for service";
1294 case PAM_NEW_AUTHTOK_REQD:
1295 return "Authentication token is no longer valid; new one required";
1296 case PAM_ACCT_EXPIRED:
1297 return "User account has expired";
1298 case PAM_SESSION_ERR:
1299 return "Cannot make/remove an entry for the specified session";
1300 case PAM_CRED_UNAVAIL:
1301 return "Authentication service cannot retrieve user credentials";
1302 case PAM_CRED_EXPIRED:
1303 return "User credentials expired";
1305 return "Failure setting user credentials";
1306 case PAM_NO_MODULE_DATA:
1307 return "No module specific data is present";
1309 return "Bad item passed to pam_*_item()";
1311 return "Conversation error";
1312 case PAM_AUTHTOK_ERR:
1313 return "Authentication token manipulation error";
1314 case PAM_AUTHTOK_RECOVERY_ERR:
1315 return "Authentication information cannot be recovered";
1316 case PAM_AUTHTOK_LOCK_BUSY:
1317 return "Authentication token lock busy";
1318 case PAM_AUTHTOK_DISABLE_AGING:
1319 return "Authentication token aging disabled";
1321 return "Failed preliminary check by password service";
1323 return "The return value should be ignored by PAM dispatch";
1324 case PAM_MODULE_UNKNOWN:
1325 return "Module is unknown";
1326 case PAM_AUTHTOK_EXPIRED:
1327 return "Authentication token expired";
1328 case PAM_CONV_AGAIN:
1329 return "Conversation is waiting for event";
1330 case PAM_INCOMPLETE:
1331 return "Application needs to call libpam again";
1333 return "Unknown PAM error";
1343 pututxline (struct utmp *ut)
1353 struct xcb_connection_t
1361 xcb_connect_to_display_with_auth_info (const char *display, xcb_auth_info_t *auth, int *screen)
1363 xcb_connection_t *c;
1365 GSocketAddress *address;
1366 GError *error = NULL;
1368 c = malloc (sizeof (xcb_connection_t));
1369 c->display = g_strdup (display);
1372 if (display == NULL)
1373 display = getenv ("DISPLAY");
1374 if (display == NULL)
1375 c->error = XCB_CONN_CLOSED_PARSE_ERR;
1379 c->socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &error);
1381 g_printerr ("%s\n", error->message);
1382 g_clear_error (&error);
1383 if (c->socket == NULL)
1384 c->error = XCB_CONN_ERROR;
1391 /* Skip the hostname, we'll assume it's localhost */
1392 d = g_strdup_printf (".x%s", strchr (display, ':'));
1394 socket_path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), d, NULL);
1396 address = g_unix_socket_address_new (socket_path);
1397 if (!g_socket_connect (c->socket, address, NULL, &error))
1398 c->error = XCB_CONN_ERROR;
1400 g_printerr ("Failed to connect to X socket %s: %s\n", socket_path, error->message);
1401 g_free (socket_path);
1402 g_clear_error (&error);
1405 // FIXME: Send auth info
1410 g_object_unref (address);
1416 xcb_connect (const char *displayname, int *screenp)
1418 return xcb_connect_to_display_with_auth_info(displayname, NULL, screenp);
1422 xcb_connection_has_error (xcb_connection_t *c)
1428 xcb_disconnect (xcb_connection_t *c)
1432 g_object_unref (c->socket);