15 #include <security/pam_appl.h>
24 #include "configuration.h"
25 #include "session-child.h"
27 #include "console-kit.h"
30 #include "privileges.h"
31 #include "x-authority.h"
32 #include "configuration.h"
34 /* Child process being run */
35 static GPid child_pid = 0;
37 /* Pipe to communicate with daemon */
38 static int from_daemon_output = 0;
39 static int to_daemon_input = 0;
41 static gboolean is_interactive;
42 static gboolean do_authenticate;
43 static gboolean authentication_complete = FALSE;
44 static pam_handle_t *pam_handle;
46 /* Maximum length of a string to pass between daemon and session */
47 #define MAX_STRING_LENGTH 65535
50 write_data (const void *buf, size_t count)
52 if (write (to_daemon_input, buf, count) != count)
53 g_printerr ("Error writing to daemon: %s\n", strerror (errno));
57 write_string (const char *value)
61 length = value ? strlen (value) : -1;
62 write_data (&length, sizeof (length));
64 write_data (value, sizeof (char) * length);
68 read_data (void *buf, size_t count)
72 n_read = read (from_daemon_output, buf, count);
74 g_printerr ("Error reading from daemon: %s\n", strerror (errno));
80 read_string_full (void* (*alloc_fn)(size_t n))
85 if (read_data (&length, sizeof (length)) <= 0)
89 if (length > MAX_STRING_LENGTH)
91 g_printerr ("Invalid string length %d from daemon\n", length);
95 value = (*alloc_fn) (sizeof (char) * (length + 1));
96 read_data (value, length);
105 return read_string_full (g_malloc);
109 pam_conv_cb (int msg_length, const struct pam_message **msg, struct pam_response **resp, void *app_data)
112 gboolean auth_complete = FALSE;
113 struct pam_response *response;
114 gchar *username = NULL;
116 /* FIXME: We don't support communication after pam_authenticate completes */
117 if (authentication_complete)
120 /* Cancel authentication if requiring input */
123 for (i = 0; i < msg_length; i++)
125 if (msg[i]->msg_style == PAM_PROMPT_ECHO_ON || msg[i]->msg_style == PAM_PROMPT_ECHO_OFF)
127 g_printerr ("Stopping PAM conversation, interaction requested but not supported\n");
132 /* Ignore informational messages */
136 /* Check if we changed user */
137 pam_get_item (pam_handle, PAM_USER, (const void **) &username);
139 /* Notify the daemon */
140 write_string (username);
141 write_data (&auth_complete, sizeof (auth_complete));
142 write_data (&msg_length, sizeof (msg_length));
143 for (i = 0; i < msg_length; i++)
145 const struct pam_message *m = msg[i];
146 write_data (&m->msg_style, sizeof (m->msg_style));
147 write_string (m->msg);
151 read_data (&error, sizeof (error));
152 if (error != PAM_SUCCESS)
154 response = calloc (msg_length, sizeof (struct pam_response));
155 for (i = 0; i < msg_length; i++)
157 struct pam_response *r = &response[i];
158 // callers of this function inside pam will expect to be able to call
159 // free() on the strings we give back. So alloc with malloc.
160 r->resp = read_string_full (malloc);
161 read_data (&r->resp_retcode, sizeof (r->resp_retcode));
169 signal_cb (int signum)
171 /* Pass on signal to child, otherwise just quit */
173 kill (child_pid, signum);
181 gchar *x_authority_name;
182 guint16 x_authority_family;
183 guint8 *x_authority_address;
184 gsize x_authority_address_length;
185 gchar *x_authority_number;
186 guint8 *x_authority_data;
187 gsize x_authority_data_length;
189 x_authority_name = read_string ();
190 if (!x_authority_name)
193 read_data (&x_authority_family, sizeof (x_authority_family));
194 read_data (&x_authority_address_length, sizeof (x_authority_address_length));
195 x_authority_address = g_malloc (x_authority_address_length);
196 read_data (x_authority_address, x_authority_address_length);
197 x_authority_number = read_string ();
198 read_data (&x_authority_data_length, sizeof (x_authority_data_length));
199 x_authority_data = g_malloc (x_authority_data_length);
200 read_data (x_authority_data, x_authority_data_length);
202 return x_authority_new (x_authority_family, x_authority_address, x_authority_address_length, x_authority_number, x_authority_name, x_authority_data, x_authority_data_length);
205 /* GNU provides this but we can't rely on that so let's make our own version */
207 updwtmpx (const gchar *wtmp_file, struct utmpx *ut)
211 memset (&u, 0, sizeof (u));
212 u.ut_type = ut->ut_type;
213 u.ut_pid = ut->ut_pid;
215 strncpy (u.ut_line, ut->ut_line, sizeof (u.ut_line));
217 strncpy (u.ut_id, ut->ut_id, sizeof (u.ut_id));
219 strncpy (u.ut_user, ut->ut_user, sizeof (u.ut_user));
221 strncpy (u.ut_host, ut->ut_host, sizeof (u.ut_host));
222 u.ut_tv.tv_sec = ut->ut_tv.tv_sec;
223 u.ut_tv.tv_usec = ut->ut_tv.tv_usec;
225 updwtmp (wtmp_file, &u);
230 audit_event (int type, const gchar *username, uid_t uid, const gchar *remote_host_name, const gchar *tty, gboolean success)
233 const char *op = NULL;
235 auditfd = audit_open ();
237 g_printerr ("Error opening audit socket: %s\n", strerror (errno));
241 if (type == AUDIT_USER_LOGIN)
243 else if (type == AUDIT_USER_LOGOUT)
245 result = success == TRUE ? 1 : 0;
247 if (audit_log_acct_message (auditfd, type, NULL, op, username, uid, remote_host_name, NULL, tty, result) <= 0)
248 g_printerr ("Error writing audit message: %s\n", strerror (errno));
255 session_child_run (int argc, char **argv)
257 struct pam_conv conversation = { pam_conv_cb, NULL };
258 int i, version, fd, result;
259 gboolean auth_complete = TRUE;
262 LogMode log_mode = LOG_MODE_BACKUP_AND_TRUNCATE;
265 gchar **command_argv;
266 GVariantBuilder ck_parameters;
268 int authentication_result;
269 gchar *authentication_result_string;
273 gchar *remote_host_name;
275 XAuthority *x_authority = NULL;
276 gchar *x_authority_filename;
277 GDBusConnection *bus;
278 const gchar *login1_session_id = NULL;
279 gchar *console_kit_cookie = NULL;
280 const gchar *locale_value;
282 static const gchar * const locale_var_names[] = {
301 const gchar *home_directory;
302 GError *error = NULL;
304 #if !defined(GLIB_VERSION_2_36)
308 if (config_get_boolean (config_get_instance (), "LightDM", "lock-memory"))
310 /* Protect memory from being paged to disk, as we deal with passwords */
311 mlockall (MCL_CURRENT | MCL_FUTURE);
314 /* Make input non-blocking */
315 fd = open ("/dev/null", O_RDONLY);
316 dup2 (fd, STDIN_FILENO);
320 fd = open ("/dev/null", O_WRONLY);
321 dup2 (fd, STDOUT_FILENO);
324 /* Get the pipe from the daemon */
327 g_printerr ("Usage: lightdm --session-child INPUTFD OUTPUTFD\n");
330 from_daemon_output = atoi (argv[2]);
331 to_daemon_input = atoi (argv[3]);
332 if (from_daemon_output == 0 || to_daemon_input == 0)
334 g_printerr ("Invalid file descriptors %s %s\n", argv[2], argv[3]);
338 /* Don't let these pipes leak to the command we will run */
339 fcntl (from_daemon_output, F_SETFD, FD_CLOEXEC);
340 fcntl (to_daemon_input, F_SETFD, FD_CLOEXEC);
342 /* Read a version number so we can handle upgrades (i.e. a newer version of session child is run for an old daemon */
343 read_data (&version, sizeof (version));
345 service = read_string ();
346 username = read_string ();
347 read_data (&do_authenticate, sizeof (do_authenticate));
348 read_data (&is_interactive, sizeof (is_interactive));
349 read_string (); /* Used to be class, now we just use the environment variable */
350 tty = read_string ();
351 remote_host_name = read_string ();
352 xdisplay = read_string ();
353 x_authority = read_xauth ();
356 result = pam_start (service, username, &conversation, &pam_handle);
357 if (result != PAM_SUCCESS)
359 g_printerr ("Failed to start PAM: %s", pam_strerror (NULL, result));
365 pam_set_item (pam_handle, PAM_XDISPLAY, xdisplay);
367 pam_set_item (pam_handle, PAM_TTY, xdisplay);
370 pam_set_item (pam_handle, PAM_TTY, tty);
375 struct pam_xauth_data value;
377 value.name = (char *) x_authority_get_authorization_name (x_authority);
378 value.namelen = strlen (x_authority_get_authorization_name (x_authority));
379 value.data = (char *) x_authority_get_authorization_data (x_authority);
380 value.datalen = x_authority_get_authorization_data_length (x_authority);
381 pam_set_item (pam_handle, PAM_XAUTHDATA, &value);
388 const gchar *new_username;
390 authentication_result = pam_authenticate (pam_handle, 0);
392 /* See what user we ended up as */
393 if (pam_get_item (pam_handle, PAM_USER, (const void **) &new_username) != PAM_SUCCESS)
395 pam_end (pam_handle, 0);
399 username = g_strdup (new_username);
401 /* Write record to btmp database */
402 if (authentication_result == PAM_AUTH_ERR)
407 memset (&ut, 0, sizeof (ut));
408 ut.ut_type = USER_PROCESS;
409 ut.ut_pid = getpid ();
412 strncpy (ut.ut_line, xdisplay, sizeof (ut.ut_line));
413 strncpy (ut.ut_id, xdisplay, sizeof (ut.ut_id));
416 strncpy (ut.ut_line, tty + strlen ("/dev/"), sizeof (ut.ut_line));
417 strncpy (ut.ut_user, username, sizeof (ut.ut_user));
419 strncpy (ut.ut_host, xdisplay, sizeof (ut.ut_host));
420 else if (remote_host_name)
421 strncpy (ut.ut_host, remote_host_name, sizeof (ut.ut_host));
422 gettimeofday (&tv, NULL);
423 ut.ut_tv.tv_sec = tv.tv_sec;
424 ut.ut_tv.tv_usec = tv.tv_usec;
426 updwtmpx ("/var/log/btmp", &ut);
429 audit_event (AUDIT_USER_LOGIN, username, -1, remote_host_name, tty, FALSE);
433 /* Check account is valid */
434 if (authentication_result == PAM_SUCCESS)
435 authentication_result = pam_acct_mgmt (pam_handle, 0);
436 if (authentication_result == PAM_NEW_AUTHTOK_REQD)
437 authentication_result = pam_chauthtok (pam_handle, PAM_CHANGE_EXPIRED_AUTHTOK);
440 authentication_result = PAM_SUCCESS;
441 authentication_complete = TRUE;
443 if (authentication_result == PAM_SUCCESS)
445 /* Fail authentication if user doesn't actually exist */
446 user = accounts_get_user_by_name (username);
449 g_printerr ("Failed to get information on user %s: %s\n", username, strerror (errno));
450 authentication_result = PAM_USER_UNKNOWN;
454 /* Set POSIX variables */
455 pam_putenv (pam_handle, "PATH=/usr/local/bin:/usr/bin:/bin");
456 pam_putenv (pam_handle, g_strdup_printf ("USER=%s", username));
457 pam_putenv (pam_handle, g_strdup_printf ("LOGNAME=%s", username));
458 pam_putenv (pam_handle, g_strdup_printf ("HOME=%s", user_get_home_directory (user)));
459 pam_putenv (pam_handle, g_strdup_printf ("SHELL=%s", user_get_shell (user)));
461 /* Let the greeter and user session inherit the system default locale */
462 for (i = 0; locale_var_names[i] != NULL; i++)
464 if ((locale_value = g_getenv (locale_var_names[i])) != NULL)
466 locale_var = g_strdup_printf ("%s=%s", locale_var_names[i], locale_value);
467 pam_putenv (pam_handle, locale_var);
474 authentication_result_string = g_strdup (pam_strerror (pam_handle, authentication_result));
476 /* Report authentication result */
477 write_string (username);
478 write_data (&auth_complete, sizeof (auth_complete));
479 write_data (&authentication_result, sizeof (authentication_result));
480 write_string (authentication_result_string);
482 /* Check we got a valid user */
485 g_printerr ("No user selected during authentication\n");
486 pam_end (pam_handle, 0);
490 /* Stop if we didn't authenticated */
491 if (authentication_result != PAM_SUCCESS)
493 pam_end (pam_handle, 0);
497 /* Get the command to run (blocks) */
498 log_filename = read_string ();
500 read_data (&log_mode, sizeof (log_mode));
504 tty = read_string ();
506 x_authority_filename = read_string ();
510 xdisplay = read_string ();
512 g_object_unref (x_authority);
513 x_authority = read_xauth ();
515 read_data (&env_length, sizeof (env_length));
516 for (i = 0; i < env_length; i++)
517 pam_putenv (pam_handle, read_string ());
518 read_data (&command_argc, sizeof (command_argc));
519 command_argv = g_malloc (sizeof (gchar *) * (command_argc + 1));
520 for (i = 0; i < command_argc; i++)
521 command_argv[i] = read_string ();
522 command_argv[i] = NULL;
524 /* If nothing to run just refresh credentials because we successfully authenticated */
525 if (command_argc == 0)
527 pam_setcred (pam_handle, PAM_REINITIALIZE_CRED);
528 pam_end (pam_handle, 0);
532 /* Redirect stderr to a log file */
535 if (g_path_is_absolute (log_filename))
537 fd = log_file_open (log_filename, log_mode);
538 dup2 (fd, STDERR_FILENO);
540 g_free (log_filename);
546 fd = open ("/dev/null", O_WRONLY);
547 dup2 (fd, STDERR_FILENO);
551 /* Set group membership - these can be overriden in pam_setcred */
554 if (initgroups (username, user_get_gid (user)) < 0)
556 g_printerr ("Failed to initialize supplementary groups for %s: %s\n", username, strerror (errno));
557 _exit (EXIT_FAILURE);
561 /* Set credentials */
562 result = pam_setcred (pam_handle, PAM_ESTABLISH_CRED);
563 if (result != PAM_SUCCESS)
565 g_printerr ("Failed to establish PAM credentials: %s\n", pam_strerror (pam_handle, result));
566 pam_end (pam_handle, 0);
570 /* Open the session */
571 result = pam_open_session (pam_handle, 0);
572 if (result != PAM_SUCCESS)
574 g_printerr ("Failed to open PAM session: %s\n", pam_strerror (pam_handle, result));
575 pam_end (pam_handle, 0);
579 /* Open a connection to the system bus for ConsoleKit - we must keep it open or CK will close the session */
580 bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
582 g_printerr ("Unable to contact system bus: %s", error->message);
585 pam_end (pam_handle, 0);
589 /* Check what logind session we are, or fallback to ConsoleKit */
590 login1_session_id = pam_getenv (pam_handle, "XDG_SESSION_ID");
591 if (login1_session_id)
593 write_string (login1_session_id);
599 g_variant_builder_init (&ck_parameters, G_VARIANT_TYPE ("(a(sv))"));
600 g_variant_builder_open (&ck_parameters, G_VARIANT_TYPE ("a(sv)"));
601 g_variant_builder_add (&ck_parameters, "(sv)", "unix-user", g_variant_new_int32 (user_get_uid (user)));
602 if (g_strcmp0 (pam_getenv (pam_handle, "XDG_SESSION_CLASS"), "greeter") == 0)
603 g_variant_builder_add (&ck_parameters, "(sv)", "session-type", g_variant_new_string ("LoginWindow"));
606 g_variant_builder_add (&ck_parameters, "(sv)", "x11-display", g_variant_new_string (xdisplay));
608 g_variant_builder_add (&ck_parameters, "(sv)", "x11-display-device", g_variant_new_string (tty));
610 if (remote_host_name)
612 g_variant_builder_add (&ck_parameters, "(sv)", "is-local", g_variant_new_boolean (FALSE));
613 g_variant_builder_add (&ck_parameters, "(sv)", "remote-host-name", g_variant_new_string (remote_host_name));
616 g_variant_builder_add (&ck_parameters, "(sv)", "is-local", g_variant_new_boolean (TRUE));
617 console_kit_cookie = ck_open_session (&ck_parameters);
620 write_string (console_kit_cookie);
621 if (console_kit_cookie)
625 value = g_strdup_printf ("XDG_SESSION_COOKIE=%s", console_kit_cookie);
626 pam_putenv (pam_handle, value);
629 runtime_dir = ck_get_xdg_runtime_dir (console_kit_cookie);
633 value = g_strdup_printf ("XDG_RUNTIME_DIR=%s", runtime_dir);
634 pam_putenv (pam_handle, value);
636 g_free (runtime_dir);
641 /* Write X authority */
644 gboolean drop_privileges, result;
646 GError *error = NULL;
648 drop_privileges = geteuid () == 0;
650 privileges_drop (user_get_uid (user), user_get_gid (user));
651 result = x_authority_write (x_authority, XAUTH_WRITE_MODE_REPLACE, x_authority_filename, &error);
653 privileges_reclaim ();
656 g_printerr ("Error writing X authority: %s\n", error->message);
657 g_clear_error (&error);
660 pam_end (pam_handle, 0);
664 value = g_strdup_printf ("XAUTHORITY=%s", x_authority_filename);
665 pam_putenv (pam_handle, value);
669 /* Catch terminate signal and pass it to the child */
670 signal (SIGTERM, signal_cb);
672 /* Run the command as the authenticated user */
673 uid = user_get_uid (user);
674 gid = user_get_gid (user);
675 home_directory = user_get_home_directory (user);
679 /* Make this process its own session */
683 /* Change to this user */
686 if (setgid (gid) != 0)
689 if (setuid (uid) != 0)
693 /* Change working directory */
694 /* NOTE: This must be done after the permissions are changed because NFS filesystems can
695 * be setup so the local root user accesses the NFS files as 'nobody'. If the home directories
696 * are not system readable then the chdir can fail */
697 if (chdir (home_directory) != 0)
702 fd = log_file_open (log_filename, log_mode);
705 dup2 (fd, STDERR_FILENO);
710 /* Run the command */
711 execve (command_argv[0], command_argv, pam_getenvlist (pam_handle));
712 _exit (EXIT_FAILURE);
715 /* Bail out if failed to fork */
718 g_printerr ("Failed to fork session child process: %s\n", strerror (errno));
719 return_code = EXIT_FAILURE;
722 /* Wait for the command to complete (blocks) */
726 if (g_strcmp0 (pam_getenv (pam_handle, "XDG_SESSION_CLASS"), "greeter") != 0)
731 memset (&ut, 0, sizeof (ut));
732 ut.ut_type = USER_PROCESS;
733 ut.ut_pid = child_pid;
736 strncpy (ut.ut_line, xdisplay, sizeof (ut.ut_line));
737 strncpy (ut.ut_id, xdisplay, sizeof (ut.ut_id));
740 strncpy (ut.ut_line, tty + strlen ("/dev/"), sizeof (ut.ut_line));
741 strncpy (ut.ut_user, username, sizeof (ut.ut_user));
743 strncpy (ut.ut_host, xdisplay, sizeof (ut.ut_host));
744 else if (remote_host_name)
745 strncpy (ut.ut_host, remote_host_name, sizeof (ut.ut_host));
746 gettimeofday (&tv, NULL);
747 ut.ut_tv.tv_sec = tv.tv_sec;
748 ut.ut_tv.tv_usec = tv.tv_usec;
750 /* Write records to utmp/wtmp databases */
752 if (!pututxline (&ut))
753 g_printerr ("Failed to write utmpx: %s\n", strerror (errno));
755 updwtmpx ("/var/log/wtmp", &ut);
758 audit_event (AUDIT_USER_LOGIN, username, uid, remote_host_name, tty, TRUE);
762 waitpid (child_pid, &return_code, 0);
766 if (g_strcmp0 (pam_getenv (pam_handle, "XDG_SESSION_CLASS"), "greeter") != 0)
771 memset (&ut, 0, sizeof (ut));
772 ut.ut_type = DEAD_PROCESS;
773 ut.ut_pid = child_pid;
776 strncpy (ut.ut_line, xdisplay, sizeof (ut.ut_line));
777 strncpy (ut.ut_id, xdisplay, sizeof (ut.ut_id));
780 strncpy (ut.ut_line, tty + strlen ("/dev/"), sizeof (ut.ut_line));
781 strncpy (ut.ut_user, username, sizeof (ut.ut_user));
783 strncpy (ut.ut_host, xdisplay, sizeof (ut.ut_host));
784 else if (remote_host_name)
785 strncpy (ut.ut_host, remote_host_name, sizeof (ut.ut_host));
786 gettimeofday (&tv, NULL);
787 ut.ut_tv.tv_sec = tv.tv_sec;
788 ut.ut_tv.tv_usec = tv.tv_usec;
790 /* Write records to utmp/wtmp databases */
792 if (!pututxline (&ut))
793 g_printerr ("Failed to write utmpx: %s\n", strerror (errno));
795 updwtmpx ("/var/log/wtmp", &ut);
798 audit_event (AUDIT_USER_LOGOUT, username, uid, remote_host_name, tty, TRUE);
803 /* Remove X authority */
806 gboolean drop_privileges, result;
807 GError *error = NULL;
809 drop_privileges = geteuid () == 0;
811 privileges_drop (user_get_uid (user), user_get_gid (user));
812 result = x_authority_write (x_authority, XAUTH_WRITE_MODE_REMOVE, x_authority_filename, &error);
814 privileges_reclaim ();
817 g_printerr ("Error removing X authority: %s\n", error->message);
818 g_clear_error (&error);
820 _exit (EXIT_FAILURE);
823 /* Close the Console Kit session */
824 if (console_kit_cookie)
825 ck_close_session (console_kit_cookie);
827 /* Close the session */
828 pam_close_session (pam_handle, 0);
830 /* Remove credentials */
831 pam_setcred (pam_handle, PAM_DELETE_CRED);
833 pam_end (pam_handle, 0);
836 /* Return result of session process to the daemon */