10 #include <sys/ioctl.h>
15 #include <security/pam_appl.h>
25 #include <gio/gunixsocketaddress.h>
29 #define LOGIN_PROMPT "login:"
31 static int console_fd = -1;
33 static GList *user_entries = NULL;
34 static GList *getpwent_link = NULL;
36 static GList *group_entries = NULL;
38 static int active_vt = 7;
40 static gboolean status_connected = FALSE;
41 static GKeyFile *config;
43 static void connect_status (void)
47 status_connected = TRUE;
49 status_connect (NULL, NULL);
51 config = g_key_file_new ();
52 g_key_file_load_from_file (config, g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "script", NULL), G_KEY_FILE_NONE, NULL);
63 struct pam_conv conversation;
79 initgroups (const char *user, gid_t group)
90 getgroups (int size, gid_t list[])
92 const gchar *group_list;
96 /* Get groups we are a member of */
97 group_list = g_getenv ("LIGHTDM_TEST_GROUPS");
100 groups = g_strsplit (group_list, ",", -1);
101 groups_length = g_strv_length (groups);
107 if (groups_length > size)
112 for (i = 0; groups[i]; i++)
113 list[i] = atoi (groups[i]);
117 return groups_length;
121 setgroups (size_t size, const gid_t *list)
126 group_list = g_string_new ("");
127 for (i = 0; i < size; i++)
130 g_string_append (group_list, ",");
131 g_string_append_printf (group_list, "%d", list[i]);
133 g_setenv ("LIGHTDM_TEST_GROUPS", group_list->str, TRUE);
134 g_string_free (group_list, TRUE);
152 setresgid (gid_t rgid, gid_t ugid, gid_t sgid)
170 setresuid (uid_t ruid, uid_t uuid, uid_t suid)
176 redirect_path (const gchar *path)
178 // Don't redirect if inside the running directory
179 if (g_str_has_prefix (path, g_getenv ("LIGHTDM_TEST_ROOT")))
180 return g_strdup (path);
182 if (g_str_has_prefix (path, SYSCONFDIR))
183 return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", path + strlen (SYSCONFDIR), NULL);
185 if (g_str_has_prefix (path, LOCALSTATEDIR))
186 return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "var", path + strlen (LOCALSTATEDIR), NULL);
188 if (g_str_has_prefix (path, DATADIR))
189 return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "usr", "share", path + strlen (DATADIR), NULL);
191 // Don't redirect if inside the build directory
192 if (g_str_has_prefix (path, BUILDDIR))
193 return g_strdup (path);
195 if (g_str_has_prefix (path, "/tmp"))
196 return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "tmp", path + strlen ("/tmp"), NULL);
198 return g_strdup (path);
203 open_wrapper (const char *func, const char *pathname, int flags, mode_t mode)
205 int (*_open) (const char *pathname, int flags, mode_t mode);
206 gchar *new_path = NULL;
209 _open = (int (*)(const char *pathname, int flags, mode_t mode)) dlsym (RTLD_NEXT, func);
211 if (strcmp (pathname, "/dev/console") == 0)
215 console_fd = _open ("/dev/null", flags, mode);
216 fcntl (console_fd, F_SETFD, FD_CLOEXEC);
221 new_path = redirect_path (pathname);
222 fd = _open (new_path, flags, mode);
229 open (const char *pathname, int flags, ...)
235 va_start (ap, flags);
236 mode = va_arg (ap, mode_t);
239 return open_wrapper ("open", pathname, flags, mode);
243 open64 (const char *pathname, int flags, ...)
249 va_start (ap, flags);
250 mode = va_arg (ap, mode_t);
253 return open_wrapper ("open64", pathname, flags, mode);
257 fopen (const char *path, const char *mode)
259 FILE *(*_fopen) (const char *pathname, const char *mode);
260 gchar *new_path = NULL;
263 _fopen = (FILE *(*)(const char *pathname, const char *mode)) dlsym (RTLD_NEXT, "fopen");
265 new_path = redirect_path (path);
266 result = _fopen (new_path, mode);
273 unlinkat (int dirfd, const char *pathname, int flags)
275 int (*_unlinkat) (int dirfd, const char *pathname, int flags);
276 gchar *new_path = NULL;
279 _unlinkat = (int (*)(int dirfd, const char *pathname, int flags)) dlsym (RTLD_NEXT, "unlinkat");
281 new_path = redirect_path (pathname);
282 result = _unlinkat (dirfd, new_path, flags);
289 creat (const char *pathname, mode_t mode)
291 int (*_creat) (const char *pathname, mode_t mode);
292 gchar *new_path = NULL;
295 _creat = (int (*)(const char *pathname, mode_t mode)) dlsym (RTLD_NEXT, "creat");
297 new_path = redirect_path (pathname);
298 result = _creat (new_path, mode);
305 creat64 (const char *pathname, mode_t mode)
307 int (*_creat64) (const char *pathname, mode_t mode);
308 gchar *new_path = NULL;
311 _creat64 = (int (*)(const char *pathname, mode_t mode)) dlsym (RTLD_NEXT, "creat64");
313 new_path = redirect_path (pathname);
314 result = _creat64 (new_path, mode);
321 access (const char *pathname, int mode)
323 int (*_access) (const char *pathname, int mode);
324 gchar *new_path = NULL;
327 /* Look like systemd is always running */
328 if (strcmp (pathname, "/run/systemd/seats/") == 0)
331 _access = (int (*)(const char *pathname, int mode)) dlsym (RTLD_NEXT, "access");
333 new_path = redirect_path (pathname);
334 ret = _access (new_path, mode);
341 stat (const char *path, struct stat *buf)
343 int (*_stat) (const char *path, struct stat *buf);
344 gchar *new_path = NULL;
347 _stat = (int (*)(const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "stat");
349 new_path = redirect_path (path);
350 ret = _stat (new_path, buf);
357 stat64 (const char *path, struct stat64 *buf)
359 int (*_stat64) (const char *path, struct stat64 *buf);
360 gchar *new_path = NULL;
363 _stat64 = (int (*)(const char *path, struct stat64 *buf)) dlsym (RTLD_NEXT, "stat64");
365 new_path = redirect_path (path);
366 ret = _stat64 (new_path, buf);
373 __xstat (int version, const char *path, struct stat *buf)
375 int (*___xstat) (int version, const char *path, struct stat *buf);
376 gchar *new_path = NULL;
379 ___xstat = (int (*)(int version, const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "__xstat");
381 new_path = redirect_path (path);
382 ret = ___xstat (version, new_path, buf);
389 __xstat64 (int version, const char *path, struct stat64 *buf)
391 int (*___xstat64) (int version, const char *path, struct stat64 *buf);
392 gchar *new_path = NULL;
395 ___xstat64 = (int (*)(int version, const char *path, struct stat64 *buf)) dlsym (RTLD_NEXT, "__xstat64");
397 new_path = redirect_path (path);
398 ret = ___xstat64 (version, new_path, buf);
405 __fxstatat(int ver, int dirfd, const char *pathname, struct stat *buf, int flags)
407 int (*___fxstatat) (int ver, int dirfd, const char *pathname, struct stat *buf, int flags);
408 gchar *new_path = NULL;
411 ___fxstatat = (int (*)(int ver, int dirfd, const char *pathname, struct stat *buf, int flags)) dlsym (RTLD_NEXT, "__fxstatat");
413 new_path = redirect_path (pathname);
414 ret = ___fxstatat (ver, dirfd, new_path, buf, flags);
421 __fxstatat64(int ver, int dirfd, const char *pathname, struct stat64 *buf, int flags)
423 int (*___fxstatat64) (int ver, int dirfd, const char *pathname, struct stat64 *buf, int flags);
424 gchar *new_path = NULL;
427 ___fxstatat64 = (int (*)(int ver, int dirfd, const char *pathname, struct stat64 *buf, int flags)) dlsym (RTLD_NEXT, "__fxstatat64");
429 new_path = redirect_path (pathname);
430 ret = ___fxstatat64 (ver, dirfd, new_path, buf, flags);
437 opendir (const char *name)
439 DIR *(*_opendir) (const char *name);
440 gchar *new_path = NULL;
443 _opendir = (DIR *(*)(const char *name)) dlsym (RTLD_NEXT, "opendir");
445 new_path = redirect_path (name);
446 result = _opendir (new_path);
453 mkdir (const char *pathname, mode_t mode)
455 int (*_mkdir) (const char *pathname, mode_t mode);
456 gchar *new_path = NULL;
459 _mkdir = (int (*)(const char *pathname, mode_t mode)) dlsym (RTLD_NEXT, "mkdir");
461 new_path = redirect_path (pathname);
462 result = _mkdir (new_path, mode);
469 chown (const char *pathname, uid_t owner, gid_t group)
471 /* Just fake it - we're not root */
476 chmod (const char *path, mode_t mode)
478 int (*_chmod) (const char *path, mode_t mode);
479 gchar *new_path = NULL;
482 _chmod = (int (*)(const char *path, mode_t mode)) dlsym (RTLD_NEXT, "chmod");
484 new_path = redirect_path (path);
485 result = _chmod (new_path, mode);
492 ioctl (int d, unsigned long request, ...)
494 int (*_ioctl) (int d, int request, ...);
496 _ioctl = (int (*)(int d, int request, ...)) dlsym (RTLD_NEXT, "ioctl");
497 if (d > 0 && d == console_fd)
499 struct vt_stat *console_state;
506 va_start (ap, request);
507 console_state = va_arg (ap, struct vt_stat *);
509 console_state->v_active = active_vt;
512 va_start (ap, request);
513 vt = va_arg (ap, int);
519 status_notify ("VT ACTIVATE VT=%d", active_vt);
532 va_start (ap, request);
533 data = va_arg (ap, void *);
535 return _ioctl (d, request, data);
542 int (*_close) (int fd);
544 if (fd > 0 && fd == console_fd)
547 _close = (int (*)(int fd)) dlsym (RTLD_NEXT, "close");
553 free_user (gpointer data)
555 struct passwd *entry = data;
557 g_free (entry->pw_name);
558 g_free (entry->pw_passwd);
559 g_free (entry->pw_gecos);
560 g_free (entry->pw_dir);
561 g_free (entry->pw_shell);
566 load_passwd_file (void)
568 gchar *path, *data = NULL, **lines;
570 GError *error = NULL;
572 g_list_free_full (user_entries, free_user);
574 getpwent_link = NULL;
576 path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "passwd", NULL);
577 g_file_get_contents (path, &data, NULL, &error);
580 g_warning ("Error loading passwd file: %s", error->message);
581 g_clear_error (&error);
586 lines = g_strsplit (data, "\n", -1);
589 for (i = 0; lines[i]; i++)
591 gchar *line, **fields;
593 line = g_strstrip (lines[i]);
594 fields = g_strsplit (line, ":", -1);
595 if (g_strv_length (fields) == 7)
597 struct passwd *entry = malloc (sizeof (struct passwd));
599 entry->pw_name = g_strdup (fields[0]);
600 entry->pw_passwd = g_strdup (fields[1]);
601 entry->pw_uid = atoi (fields[2]);
602 entry->pw_gid = atoi (fields[3]);
603 entry->pw_gecos = g_strdup (fields[4]);
604 entry->pw_dir = g_strdup (fields[5]);
605 entry->pw_shell = g_strdup (fields[6]);
606 user_entries = g_list_append (user_entries, entry);
616 if (getpwent_link == NULL)
619 if (user_entries == NULL)
621 getpwent_link = user_entries;
625 if (getpwent_link->next == NULL)
627 getpwent_link = getpwent_link->next;
630 return getpwent_link->data;
636 getpwent_link = NULL;
642 getpwent_link = NULL;
646 getpwnam (const char *name)
655 for (link = user_entries; link; link = link->next)
657 struct passwd *entry = link->data;
658 if (strcmp (entry->pw_name, name) == 0)
674 for (link = user_entries; link; link = link->next)
676 struct passwd *entry = link->data;
677 if (entry->pw_uid == uid)
687 free_group (gpointer data)
689 struct group *entry = data;
691 g_free (entry->gr_name);
692 g_free (entry->gr_passwd);
693 g_strfreev (entry->gr_mem);
698 load_group_file (void)
700 gchar *path, *data = NULL, **lines;
702 GError *error = NULL;
704 g_list_free_full (group_entries, free_group);
705 group_entries = NULL;
707 path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "group", NULL);
708 g_file_get_contents (path, &data, NULL, &error);
711 g_warning ("Error loading group file: %s", error->message);
712 g_clear_error (&error);
717 lines = g_strsplit (data, "\n", -1);
720 for (i = 0; lines[i]; i++)
722 gchar *line, **fields;
724 line = g_strstrip (lines[i]);
725 fields = g_strsplit (line, ":", -1);
726 if (g_strv_length (fields) == 4)
728 struct group *entry = malloc (sizeof (struct group));
730 entry->gr_name = g_strdup (fields[0]);
731 entry->gr_passwd = g_strdup (fields[1]);
732 entry->gr_gid = atoi (fields[2]);
733 entry->gr_mem = g_strsplit (fields[3], ",", -1);
734 group_entries = g_list_append (group_entries, entry);
742 getgrnam (const char *name)
748 for (link = group_entries; link; link = link->next)
750 struct group *entry = link->data;
751 if (strcmp (entry->gr_name, name) == 0)
767 for (link = group_entries; link; link = link->next)
769 struct group *entry = link->data;
770 if (entry->gr_gid == gid)
780 pam_start (const char *service_name, const char *user, const struct pam_conv *conversation, pam_handle_t **pamh)
782 pam_handle_t *handle;
784 if (service_name == NULL || conversation == NULL || pamh == NULL)
785 return PAM_SYSTEM_ERR;
787 handle = *pamh = malloc (sizeof (pam_handle_t));
791 handle->service_name = strdup (service_name);
792 handle->user = user ? strdup (user) : NULL;
793 handle->authtok = NULL;
794 handle->ruser = NULL;
796 handle->conversation.conv = conversation->conv;
797 handle->conversation.appdata_ptr = conversation->appdata_ptr;
798 handle->envlist = malloc (sizeof (char *) * 1);
799 handle->envlist[0] = NULL;
805 send_info (pam_handle_t *pamh, const char *message)
807 struct pam_message **msg;
808 struct pam_response *resp = NULL;
810 msg = calloc (1, sizeof (struct pam_message *));
811 msg[0] = malloc (sizeof (struct pam_message));
812 msg[0]->msg_style = PAM_TEXT_INFO;
813 msg[0]->msg = message;
814 pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
826 pam_authenticate (pam_handle_t *pamh, int flags)
828 struct passwd *entry;
829 gboolean password_matches = FALSE;
832 return PAM_SYSTEM_ERR;
834 if (strcmp (pamh->service_name, "test-remote") == 0)
837 struct pam_message **msg;
838 struct pam_response *resp = NULL;
840 msg = malloc (sizeof (struct pam_message *) * 1);
841 msg[0] = malloc (sizeof (struct pam_message));
842 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
843 msg[0]->msg = "remote-login:";
844 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
847 if (result != PAM_SUCCESS)
852 if (resp[0].resp == NULL)
860 pamh->ruser = strdup (resp[0].resp);
864 msg = malloc (sizeof (struct pam_message *) * 1);
865 msg[0] = malloc (sizeof (struct pam_message));
866 msg[0]->msg_style = PAM_PROMPT_ECHO_OFF;
867 msg[0]->msg = "remote-password:";
868 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
871 if (result != PAM_SUCCESS)
876 if (resp[0].resp == NULL)
883 free (pamh->authtok);
884 pamh->authtok = strdup (resp[0].resp);
888 password_matches = strcmp (pamh->ruser, "remote-user") == 0 && strcmp (pamh->authtok, "password") == 0;
890 if (password_matches)
896 /* Prompt for username */
897 if (pamh->user == NULL)
900 struct pam_message **msg;
901 struct pam_response *resp = NULL;
903 msg = malloc (sizeof (struct pam_message *) * 1);
904 msg[0] = malloc (sizeof (struct pam_message));
905 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
906 msg[0]->msg = LOGIN_PROMPT;
907 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
910 if (result != PAM_SUCCESS)
915 if (resp[0].resp == NULL)
921 pamh->user = strdup (resp[0].resp);
926 if (strcmp (pamh->user, "log-pam") == 0)
927 send_info (pamh, "pam_authenticate");
929 /* Crash on authenticate */
930 if (strcmp (pamh->user, "crash-authenticate") == 0)
931 kill (getpid (), SIGSEGV);
933 /* Look up password database */
934 entry = getpwnam (pamh->user);
936 /* Prompt for password if required */
937 if (entry && strcmp (pamh->user, "always-password") != 0 && (strcmp (pamh->service_name, "lightdm-autologin") == 0 || strcmp (entry->pw_passwd, "") == 0))
938 password_matches = TRUE;
941 int i, n_messages = 0, password_index, result;
942 struct pam_message **msg;
943 struct pam_response *resp = NULL;
945 msg = malloc (sizeof (struct pam_message *) * 5);
946 if (strcmp (pamh->user, "info-prompt") == 0)
948 msg[n_messages] = malloc (sizeof (struct pam_message));
949 msg[n_messages]->msg_style = PAM_TEXT_INFO;
950 msg[n_messages]->msg = "Welcome to LightDM";
953 if (strcmp (pamh->user, "multi-info-prompt") == 0)
955 msg[n_messages] = malloc (sizeof (struct pam_message));
956 msg[n_messages]->msg_style = PAM_TEXT_INFO;
957 msg[n_messages]->msg = "Welcome to LightDM";
959 msg[n_messages] = malloc (sizeof (struct pam_message));
960 msg[n_messages]->msg_style = PAM_ERROR_MSG;
961 msg[n_messages]->msg = "This is an error";
963 msg[n_messages] = malloc (sizeof (struct pam_message));
964 msg[n_messages]->msg_style = PAM_TEXT_INFO;
965 msg[n_messages]->msg = "You should have seen three messages";
968 if (strcmp (pamh->user, "multi-prompt") == 0)
970 msg[n_messages] = malloc (sizeof (struct pam_message));
971 msg[n_messages]->msg_style = PAM_PROMPT_ECHO_ON;
972 msg[n_messages]->msg = "Favorite Color:";
975 msg[n_messages] = malloc (sizeof (struct pam_message));
976 msg[n_messages]->msg_style = PAM_PROMPT_ECHO_OFF;
977 msg[n_messages]->msg = "Password:";
978 password_index = n_messages;
980 result = pamh->conversation.conv (n_messages, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
981 for (i = 0; i < n_messages; i++)
984 if (result != PAM_SUCCESS)
989 if (resp[password_index].resp == NULL)
996 password_matches = strcmp (entry->pw_passwd, resp[password_index].resp) == 0;
998 if (password_matches && strcmp (pamh->user, "multi-prompt") == 0)
999 password_matches = strcmp ("blue", resp[0].resp) == 0;
1001 for (i = 0; i < n_messages; i++)
1004 free (resp[i].resp);
1008 /* Do two factor authentication */
1009 if (password_matches && strcmp (pamh->user, "two-factor") == 0)
1011 msg = malloc (sizeof (struct pam_message *) * 1);
1012 msg[0] = malloc (sizeof (struct pam_message));
1013 msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
1014 msg[0]->msg = "OTP:";
1016 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
1021 return PAM_CONV_ERR;
1022 if (resp[0].resp == NULL)
1025 return PAM_CONV_ERR;
1027 password_matches = strcmp (resp[0].resp, "otp") == 0;
1028 free (resp[0].resp);
1033 /* Special user has home directory created on login */
1034 if (password_matches && strcmp (pamh->user, "mount-home-dir") == 0)
1035 g_mkdir_with_parents (entry->pw_dir, 0755);
1037 /* Special user 'change-user1' changes user on authentication */
1038 if (password_matches && strcmp (pamh->user, "change-user1") == 0)
1040 g_free (pamh->user);
1041 pamh->user = g_strdup ("change-user2");
1044 /* Special user 'change-user-invalid' changes to an invalid user on authentication */
1045 if (password_matches && strcmp (pamh->user, "change-user-invalid") == 0)
1047 g_free (pamh->user);
1048 pamh->user = g_strdup ("invalid-user");
1051 if (password_matches)
1054 return PAM_AUTH_ERR;
1058 get_env_value (const char *name_value, const char *name)
1062 for (j = 0; name[j] && name_value[j] && name[j] == name_value[j]; j++);
1063 if (name[j] == '\0' && name_value[j] == '=')
1064 return &name_value[j + 1];
1070 pam_putenv (pam_handle_t *pamh, const char *name_value)
1075 if (pamh == NULL || name_value == NULL)
1076 return PAM_SYSTEM_ERR;
1078 name = strdup (name_value);
1079 for (i = 0; name[i]; i++)
1082 for (i = 0; pamh->envlist[i]; i++)
1084 if (get_env_value (pamh->envlist[i], name))
1089 if (pamh->envlist[i])
1091 free (pamh->envlist[i]);
1092 pamh->envlist[i] = strdup (name_value);
1096 pamh->envlist = realloc (pamh->envlist, sizeof (char *) * (i + 2));
1097 pamh->envlist[i] = strdup (name_value);
1098 pamh->envlist[i + 1] = NULL;
1105 pam_getenv (pam_handle_t *pamh, const char *name)
1109 if (pamh == NULL || name == NULL)
1112 for (i = 0; pamh->envlist[i]; i++)
1115 value = get_env_value (pamh->envlist[i], name);
1124 pam_getenvlist (pam_handle_t *pamh)
1129 return pamh->envlist;
1133 pam_set_item (pam_handle_t *pamh, int item_type, const void *item)
1135 if (pamh == NULL || item == NULL)
1136 return PAM_SYSTEM_ERR;
1143 pamh->tty = strdup ((const char *) item);
1147 return PAM_BAD_ITEM;
1152 pam_get_item (const pam_handle_t *pamh, int item_type, const void **item)
1154 if (pamh == NULL || item == NULL)
1155 return PAM_SYSTEM_ERR;
1160 *item = pamh->service_name;
1168 *item = pamh->authtok;
1172 *item = pamh->ruser;
1175 case PAM_USER_PROMPT:
1176 *item = LOGIN_PROMPT;
1184 *item = &pamh->conversation;
1188 return PAM_BAD_ITEM;
1193 pam_open_session (pam_handle_t *pamh, int flags)
1196 return PAM_SYSTEM_ERR;
1198 if (strcmp (pamh->user, "session-error") == 0)
1199 return PAM_SESSION_ERR;
1201 if (strcmp (pamh->user, "log-pam") == 0)
1202 send_info (pamh, "pam_open_session");
1204 if (strcmp (pamh->user, "make-home-dir") == 0)
1206 struct passwd *entry;
1207 entry = getpwnam (pamh->user);
1208 g_mkdir_with_parents (entry->pw_dir, 0755);
1215 pam_close_session (pam_handle_t *pamh, int flags)
1218 return PAM_SYSTEM_ERR;
1220 if (strcmp (pamh->user, "log-pam") == 0)
1221 send_info (pamh, "pam_close_session");
1227 pam_acct_mgmt (pam_handle_t *pamh, int flags)
1230 return PAM_SYSTEM_ERR;
1233 return PAM_USER_UNKNOWN;
1235 if (strcmp (pamh->user, "log-pam") == 0)
1236 send_info (pamh, "pam_acct_mgmt");
1238 if (strcmp (pamh->user, "denied") == 0)
1239 return PAM_PERM_DENIED;
1240 if (strcmp (pamh->user, "expired") == 0)
1241 return PAM_ACCT_EXPIRED;
1242 if (strcmp (pamh->user, "new-authtok") == 0)
1243 return PAM_NEW_AUTHTOK_REQD;
1249 pam_chauthtok (pam_handle_t *pamh, int flags)
1251 struct passwd *entry;
1253 struct pam_message **msg;
1254 struct pam_response *resp = NULL;
1257 return PAM_SYSTEM_ERR;
1259 if (strcmp (pamh->user, "log-pam") == 0)
1260 send_info (pamh, "pam_chauthtok");
1262 msg = malloc (sizeof (struct pam_message *) * 1);
1263 msg[0] = malloc (sizeof (struct pam_message));
1264 msg[0]->msg_style = PAM_PROMPT_ECHO_OFF;
1265 if ((flags & PAM_CHANGE_EXPIRED_AUTHTOK) != 0)
1266 msg[0]->msg = "Enter new password (expired):";
1268 msg[0]->msg = "Enter new password:";
1269 result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
1272 if (result != PAM_SUCCESS)
1276 return PAM_CONV_ERR;
1277 if (resp[0].resp == NULL)
1280 return PAM_CONV_ERR;
1283 /* Update password database */
1284 entry = getpwnam (pamh->user);
1285 free (entry->pw_passwd);
1286 entry->pw_passwd = resp[0].resp;
1293 pam_setcred (pam_handle_t *pamh, int flags)
1298 return PAM_SYSTEM_ERR;
1300 if (strcmp (pamh->user, "log-pam") == 0)
1301 send_info (pamh, "pam_setcred");
1303 /* Put the test directories into the path */
1304 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"));
1305 pam_putenv (pamh, e);
1308 if (strcmp (pamh->user, "cred-error") == 0)
1309 return PAM_CRED_ERR;
1310 if (strcmp (pamh->user, "cred-expired") == 0)
1311 return PAM_CRED_EXPIRED;
1312 if (strcmp (pamh->user, "cred-unavail") == 0)
1313 return PAM_CRED_UNAVAIL;
1315 /* Join special groups if requested */
1316 if (strcmp (pamh->user, "group-member") == 0 && flags & PAM_ESTABLISH_CRED)
1318 struct group *group;
1322 group = getgrnam ("test-group");
1325 groups_length = getgroups (0, NULL);
1326 if (groups_length < 0)
1327 return PAM_SYSTEM_ERR;
1328 groups = malloc (sizeof (gid_t) * (groups_length + 1));
1329 groups_length = getgroups (groups_length, groups);
1330 if (groups_length < 0)
1331 return PAM_SYSTEM_ERR;
1332 groups[groups_length] = group->gr_gid;
1334 setgroups (groups_length, groups);
1338 /* We need to pass our group overrides down the child process - the environment via PAM seems the only way to do it easily */
1339 pam_putenv (pamh, g_strdup_printf ("LIGHTDM_TEST_GROUPS=%s", g_getenv ("LIGHTDM_TEST_GROUPS")));
1346 pam_end (pam_handle_t *pamh, int pam_status)
1349 return PAM_SYSTEM_ERR;
1351 free (pamh->service_name);
1355 free (pamh->authtok);
1366 pam_strerror (pam_handle_t *pamh, int errnum)
1376 return "Critical error - immediate abort";
1378 return "Failed to load module";
1379 case PAM_SYMBOL_ERR:
1380 return "Symbol not found";
1381 case PAM_SERVICE_ERR:
1382 return "Error in service module";
1383 case PAM_SYSTEM_ERR:
1384 return "System error";
1386 return "Memory buffer error";
1387 case PAM_PERM_DENIED:
1388 return "Permission denied";
1390 return "Authentication failure";
1391 case PAM_CRED_INSUFFICIENT:
1392 return "Insufficient credentials to access authentication data";
1393 case PAM_AUTHINFO_UNAVAIL:
1394 return "Authentication service cannot retrieve authentication info";
1395 case PAM_USER_UNKNOWN:
1396 return "User not known to the underlying authentication module";
1398 return "Have exhausted maximum number of retries for service";
1399 case PAM_NEW_AUTHTOK_REQD:
1400 return "Authentication token is no longer valid; new one required";
1401 case PAM_ACCT_EXPIRED:
1402 return "User account has expired";
1403 case PAM_SESSION_ERR:
1404 return "Cannot make/remove an entry for the specified session";
1405 case PAM_CRED_UNAVAIL:
1406 return "Authentication service cannot retrieve user credentials";
1407 case PAM_CRED_EXPIRED:
1408 return "User credentials expired";
1410 return "Failure setting user credentials";
1411 case PAM_NO_MODULE_DATA:
1412 return "No module specific data is present";
1414 return "Bad item passed to pam_*_item()";
1416 return "Conversation error";
1417 case PAM_AUTHTOK_ERR:
1418 return "Authentication token manipulation error";
1419 case PAM_AUTHTOK_RECOVERY_ERR:
1420 return "Authentication information cannot be recovered";
1421 case PAM_AUTHTOK_LOCK_BUSY:
1422 return "Authentication token lock busy";
1423 case PAM_AUTHTOK_DISABLE_AGING:
1424 return "Authentication token aging disabled";
1426 return "Failed preliminary check by password service";
1428 return "The return value should be ignored by PAM dispatch";
1429 case PAM_MODULE_UNKNOWN:
1430 return "Module is unknown";
1431 case PAM_AUTHTOK_EXPIRED:
1432 return "Authentication token expired";
1433 case PAM_CONV_AGAIN:
1434 return "Conversation is waiting for event";
1435 case PAM_INCOMPLETE:
1436 return "Application needs to call libpam again";
1438 return "Unknown PAM error";
1448 pututxline (const struct utmpx *ut)
1451 if (g_key_file_get_boolean (config, "test-utmp-config", "check-events", NULL))
1455 status = g_string_new ("UTMP");
1456 switch (ut->ut_type)
1459 g_string_append_printf (status, " TYPE=INIT_PROCESS");
1462 g_string_append_printf (status, " TYPE=LOGIN_PROCESS");
1465 g_string_append_printf (status, " TYPE=USER_PROCESS");
1468 g_string_append_printf (status, " TYPE=DEAD_PROCESS");
1471 g_string_append_printf (status, " TYPE=%d", ut->ut_type);
1474 g_string_append_printf (status, " LINE=%s", ut->ut_line);
1476 g_string_append_printf (status, " ID=%s", ut->ut_id);
1478 g_string_append_printf (status, " USER=%s", ut->ut_user);
1480 g_string_append_printf (status, " HOST=%s", ut->ut_host);
1481 status_notify ("%s", status->str);
1482 g_string_free (status, TRUE);
1485 return (struct utmpx *)ut;
1494 updwtmp (const char *wtmp_file, const struct utmp *ut)
1497 if (g_key_file_get_boolean (config, "test-utmp-config", "check-events", NULL))
1501 status = g_string_new ("WTMP");
1502 g_string_append_printf (status, " FILE=%s", wtmp_file);
1503 switch (ut->ut_type)
1506 g_string_append_printf (status, " TYPE=INIT_PROCESS");
1509 g_string_append_printf (status, " TYPE=LOGIN_PROCESS");
1512 g_string_append_printf (status, " TYPE=USER_PROCESS");
1515 g_string_append_printf (status, " TYPE=DEAD_PROCESS");
1518 g_string_append_printf (status, " TYPE=%d", ut->ut_type);
1521 g_string_append_printf (status, " LINE=%s", ut->ut_line);
1523 g_string_append_printf (status, " ID=%s", ut->ut_id);
1525 g_string_append_printf (status, " USER=%s", ut->ut_user);
1527 g_string_append_printf (status, " HOST=%s", ut->ut_host);
1528 status_notify ("%s", status->str);
1529 g_string_free (status, TRUE);
1533 struct xcb_connection_t
1541 xcb_connect_to_display_with_auth_info (const char *display, xcb_auth_info_t *auth, int *screen)
1543 xcb_connection_t *c;
1545 GError *error = NULL;
1547 c = malloc (sizeof (xcb_connection_t));
1548 c->display = g_strdup (display);
1551 if (display == NULL)
1552 display = getenv ("DISPLAY");
1553 if (display == NULL)
1554 c->error = XCB_CONN_CLOSED_PARSE_ERR;
1558 c->socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &error);
1560 g_printerr ("%s\n", error->message);
1561 g_clear_error (&error);
1562 if (c->socket == NULL)
1563 c->error = XCB_CONN_ERROR;
1569 GSocketAddress *address;
1571 /* Skip the hostname, we'll assume it's localhost */
1572 d = g_strdup_printf (".x%s", strchr (display, ':'));
1574 socket_path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), d, NULL);
1576 address = g_unix_socket_address_new (socket_path);
1577 if (!g_socket_connect (c->socket, address, NULL, &error))
1578 c->error = XCB_CONN_ERROR;
1579 g_object_unref (address);
1581 g_printerr ("Failed to connect to X socket %s: %s\n", socket_path, error->message);
1582 g_free (socket_path);
1583 g_clear_error (&error);
1586 // FIXME: Send auth info
1595 xcb_connect (const char *displayname, int *screenp)
1597 return xcb_connect_to_display_with_auth_info(displayname, NULL, screenp);
1601 xcb_connection_has_error (xcb_connection_t *c)
1607 xcb_disconnect (xcb_connection_t *c)
1611 g_object_unref (c->socket);