1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
4 * This file is part of tlm (Tiny Login Manager)
6 * Copyright (C) 2013-2015 Intel Corporation.
8 * Contact: Amarnath Valluri <amarnath.valluri@linux.intel.com>
9 * Jussi Laako <jussi.laako@linux.intel.com>
10 * Imran Zaman <imran.zaman@intel.com>
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
38 #include <sys/types.h>
41 #include <sys/ioctl.h>
43 #include <sys/socket.h>
48 #include <glib/gstdio.h>
50 #include "tlm-session.h"
51 #include "tlm-auth-session.h"
52 #include "common/tlm-log.h"
53 #include "common/tlm-utils.h"
54 #include "common/tlm-error.h"
55 #include "common/tlm-config-general.h"
56 #include "common/tlm-config-seat.h"
67 static GParamSpec *pspecs[N_PROPERTIES];
71 SIG_SESSION_TERMINATED,
76 static guint signals[SIG_MAX];
78 struct _TlmSessionPrivate
85 struct termios tty_state;
91 TlmAuthSession *auth_session;
96 gchar *xdg_runtime_dir;
97 gboolean setup_runtime_dir;
98 gboolean can_emit_signal;
100 gboolean session_pause;
104 G_DEFINE_TYPE_WITH_PRIVATE (TlmSession, tlm_session, G_TYPE_OBJECT);
107 tlm_session_dispose (GObject *self)
109 TlmSession *session = TLM_SESSION(self);
110 TlmSessionPrivate *priv = session->priv;
111 DBG("disposing session: %s", priv->service);
112 priv->can_emit_signal = FALSE;
114 tlm_session_terminate (session);
115 while (priv->is_child_up)
116 g_main_context_iteration(NULL, TRUE);
118 g_clear_object (&session->priv->config);
120 G_OBJECT_CLASS (tlm_session_parent_class)->dispose (self);
124 tlm_session_finalize (GObject *self)
126 //TlmSession *session = TLM_SESSION(self);
127 G_OBJECT_CLASS (tlm_session_parent_class)->finalize (self);
131 _session_set_property (GObject *obj,
136 TlmSession *session = TLM_SESSION(obj);
137 TlmSessionPrivate *priv = tlm_session_get_instance_private (session);
139 switch (property_id) {
141 priv->config = g_value_dup_object (value);
144 g_free (priv->seat_id);
145 priv->seat_id = g_value_dup_string (value);
148 priv->service = g_value_dup_string (value);
151 priv->username = g_value_dup_string (value);
153 case PROP_ENVIRONMENT:
154 priv->env_hash = (GHashTable *) g_value_get_pointer (value);
156 g_hash_table_ref (priv->env_hash);
159 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
164 _session_get_property (GObject *obj,
169 TlmSession *session = TLM_SESSION(obj);
170 TlmSessionPrivate *priv = tlm_session_get_instance_private (session);
172 switch (property_id) {
174 g_value_set_object (value, priv->config);
177 g_value_set_string (value, priv->seat_id);
180 g_value_set_string (value, priv->service);
183 g_value_set_string (value, priv->username);
185 case PROP_ENVIRONMENT:
186 g_value_set_pointer (value, priv->env_hash);
189 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
194 tlm_session_class_init (TlmSessionClass *klass)
196 GObjectClass *g_klass = G_OBJECT_CLASS (klass);
198 g_klass->dispose = tlm_session_dispose ;
199 g_klass->finalize = tlm_session_finalize;
200 g_klass->set_property = _session_set_property;
201 g_klass->get_property = _session_get_property;
203 pspecs[PROP_CONFIG] =
204 g_param_spec_object ("config",
206 "Configuration object",
209 G_PARAM_STATIC_STRINGS);
211 g_param_spec_string ("seat",
215 G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS);
216 pspecs[PROP_SERVICE] =
217 g_param_spec_string ("service",
218 "authentication service",
221 G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS);
222 pspecs[PROP_USERNAME] =
223 g_param_spec_string ("username",
225 "Unix user name of user to login",
227 G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS);
228 pspecs[PROP_ENVIRONMENT] =
229 g_param_spec_pointer ("environment",
230 "environment variables",
231 "Environment variables for the session",
232 G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS);
234 g_object_class_install_properties (g_klass, N_PROPERTIES, pspecs);
236 signals[SIG_SESSION_CREATED] = g_signal_new ("session-created",
237 TLM_TYPE_SESSION, G_SIGNAL_RUN_LAST,
238 0, NULL, NULL, NULL, G_TYPE_NONE,
241 signals[SIG_SESSION_TERMINATED] = g_signal_new ("session-terminated",
242 TLM_TYPE_SESSION, G_SIGNAL_RUN_LAST,
243 0, NULL, NULL, NULL, G_TYPE_NONE,
246 signals[SIG_AUTHENTICATED] = g_signal_new ("authenticated",
247 TLM_TYPE_SESSION, G_SIGNAL_RUN_LAST,
248 0, NULL, NULL, NULL, G_TYPE_NONE,
251 signals[SIG_SESSION_ERROR] = g_signal_new ("session-error",
252 TLM_TYPE_SESSION, G_SIGNAL_RUN_LAST,
253 0, NULL, NULL, NULL, G_TYPE_NONE,
259 tlm_session_init (TlmSession *session)
261 TlmSessionPrivate *priv = tlm_session_get_instance_private (session);
263 priv->tty_dev = NULL;
264 priv->service = NULL;
265 priv->env_hash = NULL;
266 priv->auth_session = NULL;
267 priv->sessionid = NULL;
268 priv->child_watch_id = 0;
269 priv->is_child_up = FALSE;
270 priv->can_emit_signal = TRUE;
271 priv->config = tlm_config_new ();
274 session->priv = priv;
278 _setenv_to_session (const gchar *key, const gchar *val,
279 TlmSessionPrivate *user_data)
281 TlmSessionPrivate *priv = (TlmSessionPrivate *) user_data;
282 if (priv->session_pause)
283 tlm_auth_session_set_env (priv->auth_session,
285 (const gchar *) val);
287 setenv ((const char *) key, (const char *) val, 1);
291 _prepare_terminal (TlmSessionPrivate *priv)
294 struct stat tty_stat;
295 gchar strerr_buf[MAX_STRERROR_LEN] = {0,};
297 DBG ("VTNR is %u", priv->vtnr);
298 if (priv->vtnr > 0) {
299 priv->tty_dev = g_strdup_printf ("/dev/tty%u", priv->vtnr);
301 gchar tty_name[TTY_NAME_MAX+1] = {0,};
302 if (0 == ttyname_r(0, tty_name, TTY_NAME_MAX+1))
303 priv->tty_dev = g_strdup (tty_name);
305 priv->tty_dev = NULL;
307 DBG ("trying to setup TTY '%s'", priv->tty_dev);
308 if (!priv->tty_dev) {
312 if (access (priv->tty_dev, R_OK|W_OK)) {
313 WARN ("TTY not accessible: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
316 if (lstat (priv->tty_dev, &tty_stat)) {
317 WARN ("lstat() failed: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
320 if (tty_stat.st_nlink > 1 ||
321 !S_ISCHR (tty_stat.st_mode) ||
322 strncmp (priv->tty_dev, "/dev/", 5)) {
323 WARN ("Invalid TTY");
327 tty_fd = open (priv->tty_dev, O_RDWR | O_NONBLOCK);
329 WARN ("open() failed: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
332 if (!isatty (tty_fd)) {
334 WARN ("isatty() failed");
337 if (fstat (tty_fd, &tty_stat) == 0) {
338 priv->tty_uid = tty_stat.st_uid;
339 priv->tty_gid = tty_stat.st_gid;
344 if (ioctl (tty_fd, TCGETS, &priv->tty_state) < 0)
345 WARN ("ioctl(TCGETS) failed: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
347 if (fchown (tty_fd, tlm_user_get_uid (priv->username), -1)) {
348 WARN ("Changing TTY access rights failed");
351 if (ioctl(tty_fd, KDGKBMODE, &priv->kb_mode) < 0) {
352 DBG("ioctl(KDGKBMODE get) failed: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
354 DBG ("ioctl(KDGKBMODE get) val: %d", priv->kb_mode);
360 g_clear_string (&priv->tty_dev);
366 _setup_terminal (TlmSessionPrivate *priv, int tty_fd)
369 gchar strerr_buf[MAX_STRERROR_LEN] = {0,};
371 if (ioctl (tty_fd, TIOCSCTTY, 1) < 0)
372 WARN ("ioctl(TIOCSCTTY) failed: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
373 tty_pgid = getpgid (getpid ());
374 if (ioctl (tty_fd, TIOCSPGRP, &tty_pgid) < 0) {
375 WARN ("ioctl(TIOCSPGRP) failed: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
378 if (ioctl (tty_fd, KDSKBMODE, K_OFF) < 0) {
379 DBG ("ioctl(KDSKBMODE set) failed: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
388 _reset_terminal (TlmSessionPrivate *priv)
391 gchar strerr_buf[MAX_STRERROR_LEN] = {0,};
396 tty_fd = open (priv->tty_dev, O_RDWR | O_NONBLOCK);
398 WARN ("open() failed: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
402 if (priv->kb_mode >= 0 &&
403 ioctl (tty_fd, KDSKBMODE, priv->kb_mode) < 0) {
404 DBG ("ioctl(KDSKBMODE reset) failed: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
408 if (ioctl (tty_fd, TCFLSH, TCIOFLUSH) < 0)
409 DBG ("ioctl(TCFLSH) failed: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
411 if (ioctl (tty_fd, TCSETS, &priv->tty_state) < 0)
412 DBG ("ioctl(TCSETSF) failed: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
414 if (fchown (tty_fd, priv->tty_uid, priv->tty_gid))
415 WARN ("Changing TTY access rights failed");
420 g_clear_string (&priv->tty_dev);
424 _set_environment (TlmSessionPrivate *priv)
426 gchar **envlist = tlm_auth_session_get_envlist(priv->auth_session);
427 gchar *home_dir = NULL, *shell = NULL;
431 for (env = envlist; *env != NULL; ++env) {
432 DBG ("ENV : %s", *env);
439 const gchar *path = tlm_config_get_string (priv->config,
441 TLM_CONFIG_GENERAL_SESSION_PATH);
443 path = "/usr/local/bin:/usr/bin:/bin";
444 _setenv_to_session ("PATH", path, priv);
446 _setenv_to_session ("USER", priv->username, priv);
447 _setenv_to_session ("LOGNAME", priv->username, priv);
448 home_dir = tlm_user_get_home_dir (priv->username);
451 _setenv_to_session ("HOME", home_dir, priv);
454 shell = tlm_user_get_shell (priv->username);
457 _setenv_to_session ("SHELL", shell, priv);
461 if (!tlm_config_has_key (priv->config,
463 TLM_CONFIG_GENERAL_NSEATS))
464 _setenv_to_session ("XDG_SEAT", priv->seat_id, priv);
466 const gchar *xdg_data_dirs =
467 tlm_config_get_string (priv->config,
469 TLM_CONFIG_GENERAL_DATA_DIRS);
471 xdg_data_dirs = "/usr/share:/usr/local/share";
472 _setenv_to_session ("XDG_DATA_DIRS", xdg_data_dirs, priv);
474 if (priv->xdg_runtime_dir)
475 _setenv_to_session ("XDG_RUNTIME_DIR", priv->xdg_runtime_dir, priv);
478 g_hash_table_foreach (priv->env_hash,
479 (GHFunc) _setenv_to_session,
486 _clear_session (TlmSession *session)
488 TlmSessionPrivate *priv = tlm_session_get_instance_private (session);
490 _reset_terminal (priv);
492 if (priv->setup_runtime_dir)
493 tlm_utils_delete_dir (priv->xdg_runtime_dir);
495 if (priv->timer_id) {
496 g_source_remove (priv->timer_id);
500 if (priv->child_watch_id) {
501 g_source_remove (priv->child_watch_id);
502 priv->child_watch_id = 0;
505 if (priv->auth_session)
506 g_clear_object (&priv->auth_session);
508 if (priv->env_hash) {
509 g_hash_table_unref (priv->env_hash);
510 priv->env_hash = NULL;
512 g_clear_string (&priv->seat_id);
513 g_clear_string (&priv->service);
514 g_clear_string (&priv->username);
515 g_clear_string (&priv->sessionid);
516 g_clear_string (&priv->xdg_runtime_dir);
525 g_spawn_close_pid (pid);
527 TlmSession *session = TLM_SESSION (data);
529 DBG ("Sessiond(%p) with pid (%d) closed with status %d", session, pid,
532 session->priv->child_pid = 0;
533 session->priv->is_child_up = FALSE;
534 _clear_session (session);
535 if (session->priv->can_emit_signal)
536 g_signal_emit (session, signals[SIG_SESSION_TERMINATED], 0);
545 guint rtdir_perm = 0700;
546 const gchar *rtdir_perm_str;
548 const char *shell = NULL;
549 const char *env_shell = NULL;
552 gchar **args_iter = NULL;
553 TlmSessionPrivate *priv = session->priv;
554 gchar strerr_buf[MAX_STRERROR_LEN] = {0,};
556 priv = session->priv;
558 priv->username = g_strdup (tlm_auth_session_get_username (
559 priv->auth_session));
560 DBG ("session ID : %s", priv->sessionid);
562 if (tlm_config_has_key (priv->config,
564 TLM_CONFIG_GENERAL_SETUP_RUNTIME_DIR)) {
565 priv->setup_runtime_dir = tlm_config_get_boolean (priv->config,
567 TLM_CONFIG_GENERAL_SETUP_RUNTIME_DIR,
570 priv->setup_runtime_dir = tlm_config_get_boolean (priv->config,
572 TLM_CONFIG_GENERAL_SETUP_RUNTIME_DIR,
575 rtdir_perm_str = tlm_config_get_string (priv->config,
577 TLM_CONFIG_GENERAL_RUNTIME_MODE);
579 rtdir_perm_str = tlm_config_get_string (priv->config,
581 TLM_CONFIG_GENERAL_RUNTIME_MODE);
582 uid_str = g_strdup_printf ("%u", tlm_user_get_uid (priv->username));
583 priv->xdg_runtime_dir = g_build_filename ("/run/user",
587 if (priv->setup_runtime_dir) {
588 tlm_utils_delete_dir (priv->xdg_runtime_dir);
589 if (g_mkdir_with_parents ("/run/user", 0755))
590 WARN ("g_mkdir_with_parents(\"/run/user\") failed");
592 sscanf(rtdir_perm_str, "%o", &rtdir_perm);
593 DBG ("setting up XDG_RUNTIME_DIR=%s mode=%o",
594 priv->xdg_runtime_dir, rtdir_perm);
595 if (g_mkdir (priv->xdg_runtime_dir, rtdir_perm))
596 WARN ("g_mkdir(\"%s\") failed", priv->xdg_runtime_dir);
597 if (chown (priv->xdg_runtime_dir,
598 tlm_user_get_uid (priv->username),
599 tlm_user_get_gid (priv->username)))
600 WARN ("chown(\"%s\"): %s", priv->xdg_runtime_dir, strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
601 if (chmod (priv->xdg_runtime_dir, rtdir_perm))
602 WARN ("chmod(\"%s\"): %s", priv->xdg_runtime_dir, strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
604 DBG ("not setting up XDG_RUNTIME_DIR");
607 gboolean setup_terminal;
608 if (tlm_config_has_key (priv->config,
610 TLM_CONFIG_GENERAL_SETUP_TERMINAL)) {
611 setup_terminal = tlm_config_get_boolean (priv->config,
613 TLM_CONFIG_GENERAL_SETUP_TERMINAL,
616 setup_terminal = tlm_config_get_boolean (priv->config,
618 TLM_CONFIG_GENERAL_SETUP_TERMINAL,
621 if (setup_terminal) {
622 tty_fd = _prepare_terminal (priv);
624 WARN ("Failed to prepare terminal");
629 priv->child_pid = fork ();
630 if (priv->child_pid) {
633 DBG ("establish handler for the child pid %u", priv->child_pid);
634 session->priv->child_watch_id = g_child_watch_add (priv->child_pid,
635 (GChildWatchFunc)_on_child_down_cb, session);
636 session->priv->is_child_up = TRUE;
640 /* ==================================
641 * this is child process here onwards
642 * ================================== */
647 //close all open descriptors other than stdin, stdout, stderr
648 open_max = sysconf (_SC_OPEN_MAX);
649 for (fd = 3; fd < open_max; fd++) {
650 if (fcntl (fd, F_SETFD, FD_CLOEXEC) < -1) {
651 WARN ("Failed to close desriptor '%d', error: %s",
652 fd, strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
656 uid_t target_uid = tlm_user_get_uid (priv->username);
657 gid_t target_gid = tlm_user_get_gid (priv->username);
659 /*if (getppid() == 1) {
660 if (setsid () == (pid_t) -1)
661 WARN ("setsid() failed: %s", strerror (errno));
664 WARN ("setpgrp() failed: %s", strerror (errno));
667 DBG ("old pgid=%u", getpgrp ());
668 if (setsid () == (pid_t) -1)
669 WARN ("setsid() failed: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
670 DBG ("new pgid=%u", getpgrp());
672 if (setup_terminal) {
673 /* usually terminal settings are handled by PAM */
674 _setup_terminal (priv, tty_fd);
677 if (initgroups (priv->username, target_gid))
678 WARN ("initgroups() failed: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
679 if (setregid (target_gid, target_gid))
680 WARN ("setregid() failed: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
681 if (setreuid (target_uid, target_uid))
682 WARN ("setreuid() failed: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
684 int grouplist_len = NGROUPS_MAX;
685 gid_t grouplist[NGROUPS_MAX];
686 grouplist_len = getgroups (grouplist_len, grouplist);
687 DBG ("group membership:");
688 for (i = 0; i < grouplist_len; i++)
689 DBG ("\t%s", getgrgid (grouplist[i])->gr_name);
691 DBG (" state:\n\truid=%d, euid=%d, rgid=%d, egid=%d (%s)",
692 getuid(), geteuid(), getgid(), getegid(), priv->username);
693 _set_environment (priv);
696 home = getenv("HOME");
698 DBG ("changing directory to : %s", home);
699 if (chdir (home) < 0)
700 WARN ("Failed to change directroy : %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
701 } else WARN ("Could not get home directory");
703 shell = tlm_config_get_string (priv->config,
705 TLM_CONFIG_GENERAL_SESSION_CMD);
707 shell = tlm_config_get_string (priv->config,
709 TLM_CONFIG_GENERAL_SESSION_CMD);
711 args = tlm_utils_split_command_line (shell);
715 if((env_shell = getenv("SHELL"))) {
716 /* use shell if no override configured */
717 args = g_new0 (gchar *, 2);
718 args[0] = g_strdup (env_shell);
720 /* in case shell is not defined, fall back to systemd --user */
721 args = g_new0 (gchar *, 3);
722 args[0] = g_strdup ("systemd");
723 args[1] = g_strdup ("--user");
727 if (signal (SIGINT, SIG_DFL) == SIG_ERR)
728 WARN ("failed reset SIGINT: %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
732 while (args_iter && *args_iter) {
733 DBG ("\targv[%d]: %s", i, *args_iter);
736 execvp (args[0], args);
737 /* we reach here only in case of error */
739 DBG ("execl(): %s", strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
747 return g_object_new (TLM_TYPE_SESSION, NULL);
751 tlm_session_start (TlmSession *session,
752 const gchar *seat_id, const gchar *service,
753 const gchar *username, const gchar *password,
754 GHashTable *environment)
756 GError *error = NULL;
757 g_return_val_if_fail (session && TLM_IS_SESSION(session), FALSE);
758 TlmSessionPrivate *priv = tlm_session_get_instance_private (session);
759 const gchar *session_type;
761 if (!seat_id || !service || !username) {
762 error = TLM_GET_ERROR_FOR_ID (TLM_ERROR_SESSION_CREATION_FAILURE,
763 "Unable to create PAM sesssion as input data is invalid "
764 "seatid(%p) service(%p) username(%p)", seat_id, service,
766 g_signal_emit (session, signals[SIG_SESSION_ERROR], 0, error);
767 g_error_free (error);
771 g_object_set (G_OBJECT (session), "seat", seat_id, "service", service,
772 "username", username, "environment", environment, NULL);
774 priv->vtnr = tlm_config_get_uint (priv->config,
776 TLM_CONFIG_SEAT_VTNR,
778 gchar *tty_name = priv->vtnr > 0 ?
779 g_strdup_printf ("tty%u", priv->vtnr) : NULL;
780 priv->auth_session = tlm_auth_session_new (priv->service, priv->username,
784 if (!priv->auth_session) {
785 error = TLM_GET_ERROR_FOR_ID (TLM_ERROR_SESSION_CREATION_FAILURE,
786 "Unable to create PAM sesssion");
787 g_signal_emit (session, signals[SIG_SESSION_ERROR], 0, error);
788 g_error_free (error);
792 session_type = tlm_config_get_string (priv->config,
794 TLM_CONFIG_GENERAL_SESSION_TYPE);
796 session_type = tlm_config_get_string (priv->config,
798 TLM_CONFIG_GENERAL_SESSION_TYPE);
799 if (!tlm_config_has_key (priv->config,
801 TLM_CONFIG_GENERAL_NSEATS))
802 tlm_auth_session_putenv (priv->auth_session,
806 tlm_auth_session_putenv (priv->auth_session,
809 tlm_auth_session_putenv (priv->auth_session,
813 if (priv->vtnr > 0) {
814 gchar *vtnr_str = g_strdup_printf("%u", priv->vtnr);
815 tlm_auth_session_putenv (priv->auth_session,
821 if (!tlm_auth_session_authenticate (priv->auth_session, &error)) {
823 //consistant error message flow
824 GError *err = TLM_GET_ERROR_FOR_ID (
825 TLM_ERROR_SESSION_CREATION_FAILURE,
826 "%d:%s", error->code, error->message);
827 g_error_free (error);
830 error = TLM_GET_ERROR_FOR_ID (TLM_ERROR_SESSION_CREATION_FAILURE,
831 "Unable to authenticate PAM sesssion");
833 g_signal_emit (session, signals[SIG_SESSION_ERROR], 0, error);
834 g_error_free (error);
837 g_signal_emit (session, signals[SIG_AUTHENTICATED], 0);
839 if (!tlm_auth_session_open (priv->auth_session, &error)) {
841 error = TLM_GET_ERROR_FOR_ID (TLM_ERROR_SESSION_CREATION_FAILURE,
842 "Unable to open PAM sesssion");
844 g_signal_emit (session, signals[SIG_SESSION_ERROR], 0, error);
845 g_error_free (error);
848 priv->sessionid = g_strdup (tlm_auth_session_get_sessionid (
849 priv->auth_session));
850 tlm_utils_log_utmp_entry (priv->username);
852 priv->session_pause = tlm_config_get_boolean (priv->config,
854 TLM_CONFIG_GENERAL_PAUSE_SESSION,
856 if (!priv->session_pause) {
857 _exec_user_session (session);
858 g_signal_emit (session, signals[SIG_SESSION_CREATED], 0,
859 priv->sessionid ? priv->sessionid : "");
861 g_signal_emit (session, signals[SIG_SESSION_CREATED], 0,
862 priv->sessionid ? priv->sessionid : "");
870 _terminate_timeout (gpointer user_data)
872 TlmSession *session = TLM_SESSION(user_data);
873 TlmSessionPrivate *priv = tlm_session_get_instance_private (session);
874 gchar strerr_buf[MAX_STRERROR_LEN] = {0,};
876 switch (priv->last_sig)
879 DBG ("child %u didn't respond to SIGHUP, sending SIGTERM",
881 if (killpg (getpgid (priv->child_pid), SIGTERM))
882 WARN ("killpg(%u, SIGTERM): %s",
883 getpgid (priv->child_pid),
884 strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
885 priv->last_sig = SIGTERM;
886 return G_SOURCE_CONTINUE;
888 DBG ("child %u didn't respond to SIGTERM, sending SIGKILL",
890 if (killpg (getpgid (priv->child_pid), SIGKILL))
891 WARN ("killpg(%u, SIGKILL): %s",
892 getpgid (priv->child_pid),
893 strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
894 priv->last_sig = SIGKILL;
895 return G_SOURCE_CONTINUE;
897 DBG ("child %u didn't respond to SIGKILL, process is stuck in kernel",
900 _clear_session (session);
901 if (session->priv->can_emit_signal) {
902 GError *error = TLM_GET_ERROR_FOR_ID (
903 TLM_ERROR_SESSION_TERMINATION_FAILURE,
904 "Unable to terminate session - process is stuck"
906 g_signal_emit (session, signals[SIG_SESSION_ERROR], 0, error);
907 g_error_free (error);
909 return G_SOURCE_REMOVE;
911 WARN ("%d has unknown signaling state %d",
915 return G_SOURCE_REMOVE;
919 tlm_session_terminate (TlmSession *session)
921 g_return_if_fail (session && TLM_IS_SESSION(session));
922 TlmSessionPrivate *priv = tlm_session_get_instance_private (session);
924 DBG ("Session Terminate");
926 if (!priv->is_child_up) {
927 DBG ("no child process is running - closing pam session");
928 _clear_session (session);
929 if (session->priv->can_emit_signal)
930 g_signal_emit (session, signals[SIG_SESSION_TERMINATED], 0);
934 if (killpg (getpgid (priv->child_pid), SIGHUP) < 0)
936 gchar strerr_buf[MAX_STRERROR_LEN] = {0,};
937 WARN ("kill(%u, SIGHUP): %s",
938 getpgid (priv->child_pid),
939 strerror_r(errno, strerr_buf, MAX_STRERROR_LEN));
941 priv->last_sig = SIGHUP;
942 priv->timer_id = g_timeout_add_seconds (
943 tlm_config_get_uint (priv->config, TLM_CONFIG_GENERAL,
944 TLM_CONFIG_GENERAL_TERMINATE_TIMEOUT, 3),