From 901b5c1add8917438105dc4f7c9d2883edea4849 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Fri, 10 Jan 2020 17:30:17 +0100 Subject: [run-virt/pam-slx-plug] Always spawn pwdaemon, and one instance only --- .../data/opt/openslx/pam/exec_auth_final | 25 ++++++++----- .../auth-final-exec.d/99-pwdaemon-fallback.sh | 5 +++ core/modules/run-virt/pw_daemon.c | 41 ++++++++++++++++------ 3 files changed, 52 insertions(+), 19 deletions(-) create mode 100755 core/modules/run-virt/data/opt/openslx/pam/hooks/auth-final-exec.d/99-pwdaemon-fallback.sh diff --git a/core/modules/pam-slx-plug/data/opt/openslx/pam/exec_auth_final b/core/modules/pam-slx-plug/data/opt/openslx/pam/exec_auth_final index 3d12d20f..6ddd2bfb 100755 --- a/core/modules/pam-slx-plug/data/opt/openslx/pam/exec_auth_final +++ b/core/modules/pam-slx-plug/data/opt/openslx/pam/exec_auth_final @@ -3,23 +3,32 @@ # This is executed in the pam_auth phase, after any real # authentication module succeeded. It will execute all scripts in # /opt/openslx/pam/hooks/auth-final-exec.d -# This is in contrast to /opt/openslx/pam/hooks/auth-slx-success.d +# This is in contrast to /opt/openslx/pam/hooks/auth-slx-source.d # which only executes if one of the pam-slx-plugins succeeded authing, # but then offers further variables detailing the auth environment. export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/openslx/sbin:/opt/openslx/bin" -# Remove password from stdin -cat &> /dev/null & -waitpid=$! +source_dir=/opt/openslx/pam/hooks/auth-final-exec.d +readonly source_dir +[ -d "$source_dir" ] || exit 0 + +# grab the password from stdin asap +[ "$PAM_TYPE" = "auth" ] || exit 1 +unset USER_PASSWORD +read -r USER_PASSWORD > /dev/null 2>&1 +readonly USER_PASSWORD +[ -z "$USER_PASSWORD" ] && echo "No password given." && exit 1 # Only as root [ "$(whoami)" != "root" ] && exit 0 -source_dir=/opt/openslx/pam/hooks/auth-final-exec.d -readonly source_dir +# Set other vars +getent="$( getent passwd "$PAM_USER" )" +USER_UID="$( printf "%s" "$getent" | awk -F: '{print $3; exit}' )" +TEMP_HOME_DIR="$( printf "%s" "$getent" | awk -F: '{print $6; exit}' )" -[ -d "$source_dir" ] || exit 0 +export USER_PASSWORD USER_UID TEMP_HOME_DIR for file in $source_dir/*; do [ -e "$file" ] || continue # Dir empty, will be the unglobbed string @@ -34,6 +43,4 @@ for file in $source_dir/*; do "$file" || slxlog "pam-auth-final" "$file didn't exit with code 0" done -kill "$waitpid" - exit 0 diff --git a/core/modules/run-virt/data/opt/openslx/pam/hooks/auth-final-exec.d/99-pwdaemon-fallback.sh b/core/modules/run-virt/data/opt/openslx/pam/hooks/auth-final-exec.d/99-pwdaemon-fallback.sh new file mode 100755 index 00000000..e1347e41 --- /dev/null +++ b/core/modules/run-virt/data/opt/openslx/pam/hooks/auth-final-exec.d/99-pwdaemon-fallback.sh @@ -0,0 +1,5 @@ +#!/bin/ash + +USERNAME="${PAM_USER}" PASSWORD="${USER_PASSWORD}" PWSOCKET="${TEMP_HOME_DIR}/.pwsocket" pwdaemon --daemon "${USER_UID}" +exit 0 + diff --git a/core/modules/run-virt/pw_daemon.c b/core/modules/run-virt/pw_daemon.c index 8c7e8198..59e2f48b 100644 --- a/core/modules/run-virt/pw_daemon.c +++ b/core/modules/run-virt/pw_daemon.c @@ -52,17 +52,16 @@ int main(int argc, char **argv) return 1; } -static int mode_query(const char *socketPath) +static int connect_local(const char *socketPath, int quiet) { - int fd; struct sockaddr_un remote; struct timeval tv; - char buffer[200]; - ssize_t ret; - fd = socket(AF_UNIX, SOCK_STREAM, 0); + int fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd == -1) { - perror("Cannot create unix socket for connecting"); - return 1; + if (!quiet) { + perror("Cannot create unix socket for connecting"); + } + return -1; } memset(&remote, 0, sizeof(remote)); remote.sun_family = AF_UNIX; @@ -72,9 +71,23 @@ static int mode_query(const char *socketPath) setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); if (connect(fd, (struct sockaddr*)&remote, sizeof(remote)) == -1) { - perror("Cannot connect to pw daemon"); - return 1; + if (!quiet) { + perror("Cannot connect to pw daemon"); + } + close(fd); + return -1; } + return fd; +} + +static int mode_query(const char *socketPath) +{ + int fd; + char buffer[200]; + ssize_t ret; + fd = connect_local(socketPath, 0); + if (fd == -1) + return 1; if (write(fd, "GET", 3) == -1) { perror("Writing to pw daemon failed"); return 1; @@ -99,7 +112,7 @@ static int mode_query(const char *socketPath) static int mode_daemon(const uid_t uidNumber) { - int listenFd, udpPort = -1; + int listenFd, udpPort = -1, testFd; struct sockaddr_un addr; struct sigaction sig; const char *envuser = getenv("USERNAME"); @@ -120,6 +133,14 @@ static int mode_daemon(const uid_t uidNumber) fprintf(stderr, "PWSOCKET not set\n"); return 1; } + // See if already running + testFd = connect_local(pwsocket, 1); + if (testFd != -1) { + close(testFd); + // Already running + return 0; + } + // Prepeare vars if (setup_vars(envuser, envpass) == -1) { fprintf(stderr, "Error setting up variables\n"); return 1; -- cgit v1.2.3-55-g7522