10 #include <sys/ioctl.h>
15 #include <security/pam_appl.h>
24 #include <gio/gunixsocketaddress.h>
28 #define LOGIN_PROMPT "login:"
30 static int console_fd = -1;
32 static GList *user_entries = NULL;
33 static GList *getpwent_link = NULL;
35 static GList *group_entries = NULL;
37 static int active_vt = 7;
39 static gboolean status_connected = FALSE;
49 struct pam_conv conversation;
65 initgroups (const char *user, gid_t group)
76 getgroups (int size, gid_t list[])
78 const gchar *group_list;
82 /* Get groups we are a member of */
83 group_list = g_getenv ("LIGHTDM_TEST_GROUPS");
86 groups = g_strsplit (group_list, ",", -1);
87 groups_length = g_strv_length (groups);
93 if (groups_length > size)
98 for (i = 0; groups[i]; i++)
99 list[i] = atoi (groups[i]);
103 return groups_length;
107 setgroups (size_t size, const gid_t *list)
112 group_list = g_string_new ("");
113 for (i = 0; i < size; i++)
116 g_string_append (group_list, ",");
117 g_string_append_printf (group_list, "%d", list[i]);
119 g_setenv ("LIGHTDM_TEST_GROUPS", group_list->str, TRUE);
120 g_string_free (group_list, TRUE);
138 setresgid (gid_t rgid, gid_t ugid, gid_t sgid)
156 setresuid (uid_t ruid, uid_t uuid, uid_t suid)
162 redirect_path (const gchar *path)
164 // Don't redirect if inside the running directory
165 if (g_str_has_prefix (path, g_getenv ("LIGHTDM_TEST_ROOT")))
166 return g_strdup (path);
168 if (g_str_has_prefix (path, SYSCONFDIR))
169 return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", path + strlen (SYSCONFDIR), NULL);
171 if (g_str_has_prefix (path, LOCALSTATEDIR))
172 return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "var", path + strlen (LOCALSTATEDIR), NULL);
174 if (g_str_has_prefix (path, DATADIR))
175 return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "usr", "share", path + strlen (DATADIR), NULL);
177 // Don't redirect if inside the build directory
178 if (g_str_has_prefix (path, BUILDDIR))
179 return g_strdup (path);
181 if (g_str_has_prefix (path, "/tmp"))
182 return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "tmp", path + strlen ("/tmp"), NULL);
184 return g_strdup (path);
189 open_wrapper (const char *func, const char *pathname, int flags, mode_t mode)
191 int (*_open) (const char *pathname, int flags, mode_t mode);
192 gchar *new_path = NULL;
195 _open = (int (*)(const char *pathname, int flags, mode_t mode)) dlsym (RTLD_NEXT, func);
197 if (strcmp (pathname, "/dev/console") == 0)
201 console_fd = _open ("/dev/null", flags, mode);
202 fcntl (console_fd, F_SETFD, FD_CLOEXEC);
207 new_path = redirect_path (pathname);
208 fd = _open (new_path, flags, mode);
215 open (const char *pathname, int flags, ...)
221 va_start (ap, flags);
222 mode = va_arg (ap, mode_t);
225 return open_wrapper ("open", pathname, flags, mode);
229 open64 (const char *pathname, int flags, ...)
235 va_start (ap, flags);
236 mode = va_arg (ap, mode_t);
239 return open_wrapper ("open64", pathname, flags, mode);
243 fopen (const char *path, const char *mode)
245 FILE *(*_fopen) (const char *pathname, const char *mode);
246 gchar *new_path = NULL;
249 _fopen = (FILE *(*)(const char *pathname, const char *mode)) dlsym (RTLD_NEXT, "fopen");
251 new_path = redirect_path (path);
252 result = _fopen (new_path, mode);
259 unlinkat (int dirfd, const char *pathname, int flags)
261 int (*_unlinkat) (int dirfd, const char *pathname, int flags);
262 gchar *new_path = NULL;
265 _unlinkat = (int (*)(int dirfd, const char *pathname, int flags)) dlsym (RTLD_NEXT, "unlinkat");
267 new_path = redirect_path (pathname);
268 result = _unlinkat (dirfd, new_path, flags);
275 creat (const char *pathname, mode_t mode)
277 int (*_creat) (const char *pathname, mode_t mode);
278 gchar *new_path = NULL;
281 _creat = (int (*)(const char *pathname, mode_t mode)) dlsym (RTLD_NEXT, "creat");
283 new_path = redirect_path (pathname);
284 result = _creat (new_path, mode);
291 creat64 (const char *pathname, mode_t mode)
293 int (*_creat64) (const char *pathname, mode_t mode);
294 gchar *new_path = NULL;
297 _creat64 = (int (*)(const char *pathname, mode_t mode)) dlsym (RTLD_NEXT, "creat64");
299 new_path = redirect_path (pathname);
300 result = _creat64 (new_path, mode);
307 access (const char *pathname, int mode)
309 int (*_access) (const char *pathname, int mode);
310 gchar *new_path = NULL;
313 /* Look like systemd is always running */
314 if (strcmp (pathname, "/run/systemd/seats/") == 0)
317 _access = (int (*)(const char *pathname, int mode)) dlsym (RTLD_NEXT, "access");
319 new_path = redirect_path (pathname);
320 ret = _access (new_path, mode);
327 stat (const char *path, struct stat *buf)
329 int (*_stat) (const char *path, struct stat *buf);
330 gchar *new_path = NULL;
333 _stat = (int (*)(const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "stat");
335 new_path = redirect_path (path);
336 ret = _stat (new_path, buf);
343 stat64 (const char *path, struct stat64 *buf)
345 int (*_stat64) (const char *path, struct stat64 *buf);
346 gchar *new_path = NULL;
349 _stat64 = (int (*)(const char *path, struct stat64 *buf)) dlsym (RTLD_NEXT, "stat64");
351 new_path = redirect_path (path);
352 ret = _stat64 (new_path, buf);
359 __xstat (int version, const char *path, struct stat *buf)
361 int (*___xstat) (int version, const char *path, struct stat *buf);
362 gchar *new_path = NULL;
365 ___xstat = (int (*)(int version, const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "__xstat");
367 new_path = redirect_path (path);
368 ret = ___xstat (version, new_path, buf);
375 __xstat64 (int version, const char *path, struct stat64 *buf)
377 int (*___xstat64) (int version, const char *path, struct stat64 *buf);
378 gchar *new_path = NULL;
381 ___xstat64 = (int (*)(int version, const char *path, struct stat64 *buf)) dlsym (RTLD_NEXT, "__xstat64");
383 new_path = redirect_path (path);
384 ret = ___xstat64 (version, new_path, buf);
391 __fxstatat(int ver, int dirfd, const char *pathname, struct stat *buf, int flags)
393 int (*___fxstatat) (int ver, int dirfd, const char *pathname, struct stat *buf, int flags);
394 gchar *new_path = NULL;
397 ___fxstatat = (int (*)(int ver, int dirfd, const char *pathname, struct stat *buf, int flags)) dlsym (RTLD_NEXT, "__fxstatat");
399 new_path = redirect_path (pathname);
400 ret = ___fxstatat (ver, dirfd, new_path, buf, flags);
407 __fxstatat64(int ver, int dirfd, const char *pathname, struct stat64 *buf, int flags)
409 int (*___fxstatat64) (int ver, int dirfd, const char *pathname, struct stat64 *buf, int flags);
410 gchar *new_path = NULL;
413 ___fxstatat64 = (int (*)(int ver, int dirfd, const char *pathname, struct stat64 *buf, int flags)) dlsym (RTLD_NEXT, "__fxstatat64");
415 new_path = redirect_path (pathname);
416 ret = ___fxstatat64 (ver, dirfd, new_path, buf, flags);
423 opendir (const char *name)
425 DIR *(*_opendir) (const char *name);
426 gchar *new_path = NULL;
429 _opendir = (DIR *(*)(const char *name)) dlsym (RTLD_NEXT, "opendir");
431 new_path = redirect_path (name);
432 result = _opendir (new_path);
439 mkdir (const char *pathname, mode_t mode)
441 int (*_mkdir) (const char *pathname, mode_t mode);
442 gchar *new_path = NULL;
445 _mkdir = (int (*)(const char *pathname, mode_t mode)) dlsym (RTLD_NEXT, "mkdir");
447 new_path = redirect_path (pathname);
448 result = _mkdir (new_path, mode);
455 chown (const char *pathname, uid_t owner, gid_t group)
457 /* Just fake it - we're not root */
462 chmod (const char *path, mode_t mode)
464 int (*_chmod) (const char *path, mode_t mode);
465 gchar *new_path = NULL;
468 _chmod = (int (*)(const char *path, mode_t mode)) dlsym (RTLD_NEXT, "chmod");
470 new_path = redirect_path (path);
471 result = _chmod (new_path, mode);
478 ioctl (int d, unsigned long request, ...)
480 int (*_ioctl) (int d, int request, ...);
482 _ioctl = (int (*)(int d, int request, ...)) dlsym (RTLD_NEXT, "ioctl");
483 if (d > 0 && d == console_fd)
485 struct vt_stat *console_state;
492 va_start (ap, request);
493 console_state = va_arg (ap, struct vt_stat *);
495 console_state->v_active = active_vt;
498 va_start (ap, request);
499 vt = va_arg (ap, int);
504 if (!status_connected)
505 status_connected = status_connect (NULL, NULL);
506 status_notify ("VT ACTIVATE VT=%d", active_vt);
519 va_start (ap, request);
520 data = va_arg (ap, void *);
522 return _ioctl (d, request, data);
529 int (*_close) (int fd);
531 if (fd > 0 && fd == console_fd)
534 _close = (int (*)(int fd)) dlsym (RTLD_NEXT, "close");
540 free_user (gpointer data)
542 struct passwd *entry = data;
544 g_free (entry->pw_name);
545 g_free (entry->pw_passwd);
546 g_free (entry->pw_gecos);
547 g_free (entry->pw_dir);
548 g_free (entry->pw_shell);
553 load_passwd_file (void)
555 gchar *path, *data = NULL, **lines;
557 GError *error = NULL;
559 g_list_free_full (user_entries, free_user);
561 getpwent_link = NULL;
563 path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "passwd", NULL);
564 g_file_get_contents (path, &data, NULL, &error);
567 g_warning ("Error loading passwd file: %s", error->message);
568 g_clear_error (&error);
573 lines = g_strsplit (data, "\n", -1);
576 for (i = 0; lines[i]; i++)
578 gchar *line, **fields;
580 line = g_strstrip (lines[i]);
581 fields = g_strsplit (line, ":", -1);
582 if (g_strv_length (fields) == 7)
584 struct passwd *entry = malloc (sizeof (struct passwd));
586 entry->pw_name = g_strdup (fields[0]);
587 entry->pw_passwd = g_strdup (fields[1]);
588 entry->pw_uid = atoi (fields[2]);
589 entry->pw_gid = atoi (fields[3]);
590 entry->pw_gecos = g_strdup (fields[4]);
591 entry->pw_dir = g_strdup (fields[5]);
592 entry->pw_shell = g_strdup (fields[6]);
593 user_entries = g_list_append (user_entries, entry);
603 if (getpwent_link == NULL)
606 if (user_entries == NULL)
608 getpwent_link = user_entries;
612 if (getpwent_link->next == NULL)
614 getpwent_link = getpwent_link->next;
617 return getpwent_link->data;
623 getpwent_link = NULL;
629 getpwent_link = NULL;
633 getpwnam (const char *name)
642 for (link = user_entries; link; link = link->next)
644 struct passwd *entry = link->data;
645 if (strcmp (entry->pw_name, name) == 0)
661 for (link = user_entries; link; link = link->next)
663 struct passwd *entry = link->data;
664 if (entry->pw_uid == uid)
674 free_group (gpointer data)
676 struct group *entry = data;
678 g_free (entry->gr_name);
679 g_free (entry->gr_passwd);
680 g_strfreev (entry->gr_mem);
685 load_group_file (void)
687 gchar *path, *data = NULL, **lines;
689 GError *error = NULL;
691 g_list_free_full (group_entries, free_group);
692 group_entries = NULL;
694 path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "group", NULL);
695 g_file_get_contents (path, &data, NULL, &error);
698 g_warning ("Error loading group file: %s", error->message);
699 g_clear_error (&error);
704 lines = g_strsplit (data, "\n", -1);
707 for (i = 0; lines[i]; i++)
709 gchar *line, **fields;
711 line = g_strstrip (lines[i]);
712 fields = g_strsplit (line, ":", -1);
713 if (g_strv_length (fields) == 4)
715 struct group *entry = malloc (sizeof (struct group));
717 entry->gr_name = g_strdup (fields[0]);
718 entry->gr_passwd = g_strdup (fields[1]);
719 entry->gr_gid = atoi (fields[2]);
720 entry->gr_mem = g_strsplit (fields[3], ",", -1);
721 group_entries = g_list_append (group_entries, entry);
729 getgrnam (const char *name)
735 for (link = group_entries; link; link = link->next)
737 struct group *entry = link->data;
738 if (strcmp (entry->gr_name, name) == 0)
754 for (link = group_entries; link; link = link->next)
756 struct group *entry = link->data;
757 if (entry->gr_gid == gid)
767 pam_start (const char *service_name, const char *user, const struct pam_conv *conversation, pam_handle_t **pamh)
769 pam_handle_t *handle;
771 if (service_name == NULL || conversation == NULL || pamh == NULL)
772 return PAM_SYSTEM_ERR;
774 handle = *pamh = malloc (sizeof (pam_handle_t));
778 handle->service_name = strdup (service_name);
779 handle->user = user ? strdup (user) : NULL;
780 handle->authtok = NULL;
781 handle->ruser = NULL;
783 handle->conversation.conv = conversation->conv;
784 handle->conversation.appdata_ptr = conversation->appdata_ptr;
785 handle->envlist = malloc (sizeof (char *) * 1);
786 handle->envlist[0] = NULL;
792 send_info (pam_handle_t *pamh, const char *message)
794 struct pam_message **msg;
795 struct pam_response *resp = NULL;
797 msg = calloc (1, sizeof (struct pam_message *));
798 msg[0] = malloc (sizeof (struct pam_message));
799 msg[0]->msg_style = PAM_TEXT_INFO;
800 msg[0]->msg = message;
801 pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
813 pam_authenticate (pam_handle_t *pamh, int flags)
815 struct passwd *entry;
816 gboolean password_matches = FALSE;
819 return PAM_SYSTEM_ERR;
821 if (strcmp (pamh->service_name, "test-remote") == 0)
824 struct pam_message **msg;
825 struct pam_response *resp = NULL;
827 msg = malloc (sizeof (struct pam_message *) * 1);
828 msg[0] = malloc (sizeof (struct pam_message));
829 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
830 msg[0]->msg = "remote-login:";
831 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
834 if (result != PAM_SUCCESS)
839 if (resp[0].resp == NULL)
847 pamh->ruser = strdup (resp[0].resp);
851 msg = malloc (sizeof (struct pam_message *) * 1);
852 msg[0] = malloc (sizeof (struct pam_message));
853 msg[0]->msg_style = PAM_PROMPT_ECHO_OFF;
854 msg[0]->msg = "remote-password:";
855 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
858 if (result != PAM_SUCCESS)
863 if (resp[0].resp == NULL)
870 free (pamh->authtok);
871 pamh->authtok = strdup (resp[0].resp);
875 password_matches = strcmp (pamh->ruser, "remote-user") == 0 && strcmp (pamh->authtok, "password") == 0;
877 if (password_matches)
883 /* Prompt for username */
884 if (pamh->user == NULL)
887 struct pam_message **msg;
888 struct pam_response *resp = NULL;
890 msg = malloc (sizeof (struct pam_message *) * 1);
891 msg[0] = malloc (sizeof (struct pam_message));
892 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
893 msg[0]->msg = LOGIN_PROMPT;
894 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
897 if (result != PAM_SUCCESS)
902 if (resp[0].resp == NULL)
908 pamh->user = strdup (resp[0].resp);
913 if (strcmp (pamh->user, "log-pam") == 0)
914 send_info (pamh, "pam_authenticate");
916 /* Crash on authenticate */
917 if (strcmp (pamh->user, "crash-authenticate") == 0)
918 kill (getpid (), SIGSEGV);
920 /* Look up password database */
921 entry = getpwnam (pamh->user);
923 /* Prompt for password if required */
924 if (entry && strcmp (pamh->user, "always-password") != 0 && (strcmp (pamh->service_name, "lightdm-autologin") == 0 || strcmp (entry->pw_passwd, "") == 0))
925 password_matches = TRUE;
928 int i, n_messages = 0, password_index, result;
929 struct pam_message **msg;
930 struct pam_response *resp = NULL;
932 msg = malloc (sizeof (struct pam_message *) * 5);
933 if (strcmp (pamh->user, "info-prompt") == 0)
935 msg[n_messages] = malloc (sizeof (struct pam_message));
936 msg[n_messages]->msg_style = PAM_TEXT_INFO;
937 msg[n_messages]->msg = "Welcome to LightDM";
940 if (strcmp (pamh->user, "multi-info-prompt") == 0)
942 msg[n_messages] = malloc (sizeof (struct pam_message));
943 msg[n_messages]->msg_style = PAM_TEXT_INFO;
944 msg[n_messages]->msg = "Welcome to LightDM";
946 msg[n_messages] = malloc (sizeof (struct pam_message));
947 msg[n_messages]->msg_style = PAM_ERROR_MSG;
948 msg[n_messages]->msg = "This is an error";
950 msg[n_messages] = malloc (sizeof (struct pam_message));
951 msg[n_messages]->msg_style = PAM_TEXT_INFO;
952 msg[n_messages]->msg = "You should have seen three messages";
955 if (strcmp (pamh->user, "multi-prompt") == 0)
957 msg[n_messages] = malloc (sizeof (struct pam_message));
958 msg[n_messages]->msg_style = PAM_PROMPT_ECHO_ON;
959 msg[n_messages]->msg = "Favorite Color:";
962 msg[n_messages] = malloc (sizeof (struct pam_message));
963 msg[n_messages]->msg_style = PAM_PROMPT_ECHO_OFF;
964 msg[n_messages]->msg = "Password:";
965 password_index = n_messages;
967 result = pamh->conversation.conv (n_messages, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
968 for (i = 0; i < n_messages; i++)
971 if (result != PAM_SUCCESS)
976 if (resp[password_index].resp == NULL)
983 password_matches = strcmp (entry->pw_passwd, resp[password_index].resp) == 0;
985 if (password_matches && strcmp (pamh->user, "multi-prompt") == 0)
986 password_matches = strcmp ("blue", resp[0].resp) == 0;
988 for (i = 0; i < n_messages; i++)
995 /* Do two factor authentication */
996 if (password_matches && strcmp (pamh->user, "two-factor") == 0)
998 msg = malloc (sizeof (struct pam_message *) * 1);
999 msg[0] = malloc (sizeof (struct pam_message));
1000 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
1001 msg[0]->msg = "OTP:";
1003 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
1008 return PAM_CONV_ERR;
1009 if (resp[0].resp == NULL)
1012 return PAM_CONV_ERR;
1014 password_matches = strcmp (resp[0].resp, "otp") == 0;
1015 free (resp[0].resp);
1020 /* Special user has home directory created on login */
1021 if (password_matches && strcmp (pamh->user, "mount-home-dir") == 0)
1022 g_mkdir_with_parents (entry->pw_dir, 0755);
1024 /* Special user 'change-user1' changes user on authentication */
1025 if (password_matches && strcmp (pamh->user, "change-user1") == 0)
1027 g_free (pamh->user);
1028 pamh->user = g_strdup ("change-user2");
1031 /* Special user 'change-user-invalid' changes to an invalid user on authentication */
1032 if (password_matches && strcmp (pamh->user, "change-user-invalid") == 0)
1034 g_free (pamh->user);
1035 pamh->user = g_strdup ("invalid-user");
1038 if (password_matches)
1041 return PAM_AUTH_ERR;
1045 get_env_value (const char *name_value, const char *name)
1049 for (j = 0; name[j] && name_value[j] && name[j] == name_value[j]; j++);
1050 if (name[j] == '\0' && name_value[j] == '=')
1051 return &name_value[j + 1];
1057 pam_putenv (pam_handle_t *pamh, const char *name_value)
1062 if (pamh == NULL || name_value == NULL)
1063 return PAM_SYSTEM_ERR;
1065 name = strdup (name_value);
1066 for (i = 0; name[i]; i++)
1069 for (i = 0; pamh->envlist[i]; i++)
1071 if (get_env_value (pamh->envlist[i], name))
1076 if (pamh->envlist[i])
1078 free (pamh->envlist[i]);
1079 pamh->envlist[i] = strdup (name_value);
1083 pamh->envlist = realloc (pamh->envlist, sizeof (char *) * (i + 2));
1084 pamh->envlist[i] = strdup (name_value);
1085 pamh->envlist[i + 1] = NULL;
1092 pam_getenv (pam_handle_t *pamh, const char *name)
1096 if (pamh == NULL || name == NULL)
1099 for (i = 0; pamh->envlist[i]; i++)
1102 value = get_env_value (pamh->envlist[i], name);
1111 pam_getenvlist (pam_handle_t *pamh)
1116 return pamh->envlist;
1120 pam_set_item (pam_handle_t *pamh, int item_type, const void *item)
1122 if (pamh == NULL || item == NULL)
1123 return PAM_SYSTEM_ERR;
1130 pamh->tty = strdup ((const char *) item);
1134 return PAM_BAD_ITEM;
1139 pam_get_item (const pam_handle_t *pamh, int item_type, const void **item)
1141 if (pamh == NULL || item == NULL)
1142 return PAM_SYSTEM_ERR;
1147 *item = pamh->service_name;
1155 *item = pamh->authtok;
1159 *item = pamh->ruser;
1162 case PAM_USER_PROMPT:
1163 *item = LOGIN_PROMPT;
1171 *item = &pamh->conversation;
1175 return PAM_BAD_ITEM;
1180 pam_open_session (pam_handle_t *pamh, int flags)
1183 return PAM_SYSTEM_ERR;
1185 if (strcmp (pamh->user, "session-error") == 0)
1186 return PAM_SESSION_ERR;
1188 if (strcmp (pamh->user, "log-pam") == 0)
1189 send_info (pamh, "pam_open_session");
1191 if (strcmp (pamh->user, "make-home-dir") == 0)
1193 struct passwd *entry;
1194 entry = getpwnam (pamh->user);
1195 g_mkdir_with_parents (entry->pw_dir, 0755);
1202 pam_close_session (pam_handle_t *pamh, int flags)
1205 return PAM_SYSTEM_ERR;
1207 if (strcmp (pamh->user, "log-pam") == 0)
1208 send_info (pamh, "pam_close_session");
1214 pam_acct_mgmt (pam_handle_t *pamh, int flags)
1217 return PAM_SYSTEM_ERR;
1220 return PAM_USER_UNKNOWN;
1222 if (strcmp (pamh->user, "log-pam") == 0)
1223 send_info (pamh, "pam_acct_mgmt");
1225 if (strcmp (pamh->user, "denied") == 0)
1226 return PAM_PERM_DENIED;
1227 if (strcmp (pamh->user, "expired") == 0)
1228 return PAM_ACCT_EXPIRED;
1229 if (strcmp (pamh->user, "new-authtok") == 0)
1230 return PAM_NEW_AUTHTOK_REQD;
1236 pam_chauthtok (pam_handle_t *pamh, int flags)
1238 struct passwd *entry;
1240 struct pam_message **msg;
1241 struct pam_response *resp = NULL;
1244 return PAM_SYSTEM_ERR;
1246 if (strcmp (pamh->user, "log-pam") == 0)
1247 send_info (pamh, "pam_chauthtok");
1249 msg = malloc (sizeof (struct pam_message *) * 1);
1250 msg[0] = malloc (sizeof (struct pam_message));
1251 msg[0]->msg_style = PAM_PROMPT_ECHO_OFF;
1252 if ((flags & PAM_CHANGE_EXPIRED_AUTHTOK) != 0)
1253 msg[0]->msg = "Enter new password (expired):";
1255 msg[0]->msg = "Enter new password:";
1256 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
1259 if (result != PAM_SUCCESS)
1263 return PAM_CONV_ERR;
1264 if (resp[0].resp == NULL)
1267 return PAM_CONV_ERR;
1270 /* Update password database */
1271 entry = getpwnam (pamh->user);
1272 free (entry->pw_passwd);
1273 entry->pw_passwd = resp[0].resp;
1280 pam_setcred (pam_handle_t *pamh, int flags)
1285 return PAM_SYSTEM_ERR;
1287 if (strcmp (pamh->user, "log-pam") == 0)
1288 send_info (pamh, "pam_setcred");
1290 /* Put the test directories into the path */
1291 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"));
1292 pam_putenv (pamh, e);
1295 if (strcmp (pamh->user, "cred-error") == 0)
1296 return PAM_CRED_ERR;
1297 if (strcmp (pamh->user, "cred-expired") == 0)
1298 return PAM_CRED_EXPIRED;
1299 if (strcmp (pamh->user, "cred-unavail") == 0)
1300 return PAM_CRED_UNAVAIL;
1302 /* Join special groups if requested */
1303 if (strcmp (pamh->user, "group-member") == 0 && flags & PAM_ESTABLISH_CRED)
1305 struct group *group;
1309 group = getgrnam ("test-group");
1312 groups_length = getgroups (0, NULL);
1313 if (groups_length < 0)
1314 return PAM_SYSTEM_ERR;
1315 groups = malloc (sizeof (gid_t) * (groups_length + 1));
1316 groups_length = getgroups (groups_length, groups);
1317 if (groups_length < 0)
1318 return PAM_SYSTEM_ERR;
1319 groups[groups_length] = group->gr_gid;
1321 setgroups (groups_length, groups);
1325 /* We need to pass our group overrides down the child process - the environment via PAM seems the only way to do it easily */
1326 pam_putenv (pamh, g_strdup_printf ("LIGHTDM_TEST_GROUPS=%s", g_getenv ("LIGHTDM_TEST_GROUPS")));
1333 pam_end (pam_handle_t *pamh, int pam_status)
1336 return PAM_SYSTEM_ERR;
1338 free (pamh->service_name);
1342 free (pamh->authtok);
1353 pam_strerror (pam_handle_t *pamh, int errnum)
1363 return "Critical error - immediate abort";
1365 return "Failed to load module";
1366 case PAM_SYMBOL_ERR:
1367 return "Symbol not found";
1368 case PAM_SERVICE_ERR:
1369 return "Error in service module";
1370 case PAM_SYSTEM_ERR:
1371 return "System error";
1373 return "Memory buffer error";
1374 case PAM_PERM_DENIED:
1375 return "Permission denied";
1377 return "Authentication failure";
1378 case PAM_CRED_INSUFFICIENT:
1379 return "Insufficient credentials to access authentication data";
1380 case PAM_AUTHINFO_UNAVAIL:
1381 return "Authentication service cannot retrieve authentication info";
1382 case PAM_USER_UNKNOWN:
1383 return "User not known to the underlying authentication module";
1385 return "Have exhausted maximum number of retries for service";
1386 case PAM_NEW_AUTHTOK_REQD:
1387 return "Authentication token is no longer valid; new one required";
1388 case PAM_ACCT_EXPIRED:
1389 return "User account has expired";
1390 case PAM_SESSION_ERR:
1391 return "Cannot make/remove an entry for the specified session";
1392 case PAM_CRED_UNAVAIL:
1393 return "Authentication service cannot retrieve user credentials";
1394 case PAM_CRED_EXPIRED:
1395 return "User credentials expired";
1397 return "Failure setting user credentials";
1398 case PAM_NO_MODULE_DATA:
1399 return "No module specific data is present";
1401 return "Bad item passed to pam_*_item()";
1403 return "Conversation error";
1404 case PAM_AUTHTOK_ERR:
1405 return "Authentication token manipulation error";
1406 case PAM_AUTHTOK_RECOVERY_ERR:
1407 return "Authentication information cannot be recovered";
1408 case PAM_AUTHTOK_LOCK_BUSY:
1409 return "Authentication token lock busy";
1410 case PAM_AUTHTOK_DISABLE_AGING:
1411 return "Authentication token aging disabled";
1413 return "Failed preliminary check by password service";
1415 return "The return value should be ignored by PAM dispatch";
1416 case PAM_MODULE_UNKNOWN:
1417 return "Module is unknown";
1418 case PAM_AUTHTOK_EXPIRED:
1419 return "Authentication token expired";
1420 case PAM_CONV_AGAIN:
1421 return "Conversation is waiting for event";
1422 case PAM_INCOMPLETE:
1423 return "Application needs to call libpam again";
1425 return "Unknown PAM error";
1435 pututxline (const struct utmpx *ut)
1437 return (struct utmpx *)ut;
1445 struct xcb_connection_t
1453 xcb_connect_to_display_with_auth_info (const char *display, xcb_auth_info_t *auth, int *screen)
1455 xcb_connection_t *c;
1457 GError *error = NULL;
1459 c = malloc (sizeof (xcb_connection_t));
1460 c->display = g_strdup (display);
1463 if (display == NULL)
1464 display = getenv ("DISPLAY");
1465 if (display == NULL)
1466 c->error = XCB_CONN_CLOSED_PARSE_ERR;
1470 c->socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &error);
1472 g_printerr ("%s\n", error->message);
1473 g_clear_error (&error);
1474 if (c->socket == NULL)
1475 c->error = XCB_CONN_ERROR;
1481 GSocketAddress *address;
1483 /* Skip the hostname, we'll assume it's localhost */
1484 d = g_strdup_printf (".x%s", strchr (display, ':'));
1486 socket_path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), d, NULL);
1488 address = g_unix_socket_address_new (socket_path);
1489 if (!g_socket_connect (c->socket, address, NULL, &error))
1490 c->error = XCB_CONN_ERROR;
1491 g_object_unref (address);
1493 g_printerr ("Failed to connect to X socket %s: %s\n", socket_path, error->message);
1494 g_free (socket_path);
1495 g_clear_error (&error);
1498 // FIXME: Send auth info
1507 xcb_connect (const char *displayname, int *screenp)
1509 return xcb_connect_to_display_with_auth_info(displayname, NULL, screenp);
1513 xcb_connection_has_error (xcb_connection_t *c)
1519 xcb_disconnect (xcb_connection_t *c)
1523 g_object_unref (c->socket);