Post by Ben BoeckelPost by Nicholas MarriottMaybe. Can you give a bit more explanation? What is systemd-logind and
why does this option have anything to do with PAM? Why does it need PAM
to kill processes on logout?
If applications do nothing, they will be killed on logout. If, instead,
the application declares that it holds a session via PAM, it will be
left alone (my tests with Rawhide so far indicate that something isn't
quite right and isn't happening as setting it doesn't really do much).
Ok I see, but this really ties into my question below. Why this change?
Unix has always worked in the same way. If you logout then programs are
case they sit around until you kill them.
And sysadmins of course can kill your stuff whenever they like.
it. Seems pretty standard? I don't follow why this is different for
systemd.
right now).
and tmux uses it on Linux. Shouldn't this code be part of glibc instead
If it has to be managed by the application then I don't agree. It is
to every application which is just a disaster.
The bulk of this at least needs to be in osdep-linux.c.
Post by Ben Boeckel--Ben
diff --git a/trunk/configure.ac b/trunk/configure.ac
index ba00a79..fce018b 100644
--- a/trunk/configure.ac
+++ b/trunk/configure.ac
@@ -56,6 +56,13 @@ AC_ARG_ENABLE(
)
AM_CONDITIONAL(IS_STATIC, test "x" = xyes)
+# PAM support?
+AC_ARG_ENABLE(
+ pam,
+ AC_HELP_STRING(--enable-pam, create a PAM session on server startup),
+ found_pam=$enable_pam
+)
+
# Is this gcc?
AM_CONDITIONAL(IS_GCC, test "x$GCC" = xyes)
AC_MSG_CHECKING(for gcc that whines about -I)
@@ -121,6 +128,18 @@ if test "x$found_curses" = xno; then
AC_MSG_ERROR("curses not found")
fi
+if test "x$enable_pam" = xyes; then
+ # Look for libpam.
+ AC_SEARCH_LIBS(pam_start, [pam], found_pam=yes, found_pam=no)
+ # Look for libpam_misc.
+ AC_SEARCH_LIBS(misc_conv, [pam_misc], found_pam_misc=yes, found_pam_misc=no)
+ if test "x$found_pam" = xno || test "x$found_pam_misc" = xno; then
+ AC_MSG_ERROR("PAM not found")
+ else
+ AC_DEFINE(ENABLE_PAM)
+ fi
+fi
+
# Look for networking libraries.
AC_SEARCH_LIBS(b64_ntop, resolv)
AC_SEARCH_LIBS(__b64_ntop, resolv)
diff --git a/trunk/server.c b/trunk/server.c
index c442c66..4fc3b9d 100644
--- a/trunk/server.c
+++ b/trunk/server.c
@@ -16,6 +16,11 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#ifdef ENABLE_PAM
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
+#endif
+
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -26,6 +31,9 @@
#include <errno.h>
#include <event.h>
#include <fcntl.h>
+#ifdef ENABLE_PAM
+#include <pwd.h>
+#endif
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -52,6 +60,11 @@ struct event server_ev_second;
struct paste_stack global_buffers;
+#ifdef ENABLE_PAM
+pam_handle_t *pam_handle;
+int pam_last_status;
+#endif
+
int server_create_socket(void);
void server_loop(void);
int server_should_shutdown(void);
@@ -65,6 +78,10 @@ void server_child_stopped(pid_t, int);
void server_second_callback(int, short, void *);
void server_lock_server(void);
void server_lock_sessions(void);
+#ifdef ENABLE_PAM
+void server_pam_init(void);
+void server_pam_teardown(void);
+#endif
/* Create server socket. */
int
@@ -152,6 +169,9 @@ server_start(void)
mode_key_init_trees();
key_bindings_init();
utf8_build();
+#ifdef ENABLE_PAM
+ server_pam_init();
+#endif
start_time = time(NULL);
log_debug("socket path %s", socket_path);
@@ -199,6 +219,9 @@ server_start(void)
set_signals(server_signal_callback);
server_loop();
+#ifdef ENABLE_PAM
+ server_pam_teardown();
+#endif
exit(0);
}
@@ -522,3 +545,63 @@ server_lock_sessions(void)
}
}
}
+
+#ifdef ENABLE_PAM
+/* Start a PAM session */
+void
+server_pam_init(void)
+{
+ struct passwd *passwd_struct;
+ struct pam_conv conv;
+
+ pam_handle = NULL;
+
+ passwd_struct = getpwuid(geteuid());
+
+ if (!passwd_struct) {
+ log_warnx("getpwuid error: %s", strerror(errno));
+ return;
+ }
+
+ conv.conv = misc_conv;
+ conv.appdata_ptr = NULL;
+
+ pam_last_status = pam_start("tmux", passwd_struct->pw_name, &conv, &pam_handle);
+
+ if (pam_last_status != PAM_SUCCESS) {
+ pam_handle = NULL;
+ log_warnx("pam_start error: %s", pam_strerror(pam_handle, pam_last_status));
+ return;
+ }
+
+ pam_last_status = pam_open_session(pam_handle, 0);
+
+ if (pam_last_status != PAM_SUCCESS) {
+ pam_handle = NULL;
+ log_warnx("pam_open_session error: %s", pam_strerror(pam_handle, pam_last_status));
+ return;
+ }
+}
+
+/* Teardown a PAM session */
+void
+server_pam_teardown(void)
+{
+ if (!pam_handle) {
+ return;
+ }
+
+ pam_last_status = pam_close_session(pam_handle, 0);
+
+ if (pam_last_status != PAM_SUCCESS) {
+ pam_handle = NULL;
+ log_warnx("pam_close_session error: %s", pam_strerror(pam_handle, pam_last_status));
+ return;
+ }
+ pam_last_status = pam_end(pam_handle, pam_last_status);
+
+ if (pam_last_status != PAM_SUCCESS) {
+ log_warnx("pam_end error: %s", pam_strerror(pam_handle, pam_last_status));
+ }
+}
+#endif