diff options
author | Simon Rettberg | 2018-03-09 11:48:27 +0100 |
---|---|---|
committer | Simon Rettberg | 2018-03-09 11:48:27 +0100 |
commit | 9b33230f3c6235990335fa73c071ff53e89dcfd8 (patch) | |
tree | b8402ad0a60d5ceda5408302a215623685d4647a | |
parent | [pam-slx-plug] Handle sssd.conf generation (diff) | |
download | mltk-9b33230f3c6235990335fa73c071ff53e89dcfd8.tar.gz mltk-9b33230f3c6235990335fa73c071ff53e89dcfd8.tar.xz mltk-9b33230f3c6235990335fa73c071ff53e89dcfd8.zip |
[run-virt] pwdaemon now drops privs, no more su hack; support pam-slx-plug
If usage of pam-slx-plug is detected, we'll use the approprivate environment
variables to detect the mount domain, not the global /opt/openslx/inc/shares
-rwxr-xr-x | core/modules/run-virt/compile | 5 | ||||
-rw-r--r-- | core/modules/run-virt/data/opt/openslx/scripts/pam_script_auth.d/99-run_virt_credentials | 64 | ||||
-rw-r--r-- | core/modules/run-virt/pw_daemon.c | 40 |
3 files changed, 78 insertions, 31 deletions
diff --git a/core/modules/run-virt/compile b/core/modules/run-virt/compile deleted file mode 100755 index 4db15686..00000000 --- a/core/modules/run-virt/compile +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -rm -- winres.exe -i686-w64-mingw32-gcc -std=c99 -Os -Wl,--subsystem,windows -o winres.exe winres.c -lole32 -luuid -lgdi32 #-lws2_32 -strip winres.exe && echo "Successfully created winres.exe" diff --git a/core/modules/run-virt/data/opt/openslx/scripts/pam_script_auth.d/99-run_virt_credentials b/core/modules/run-virt/data/opt/openslx/scripts/pam_script_auth.d/99-run_virt_credentials index 941f0047..211f780e 100644 --- a/core/modules/run-virt/data/opt/openslx/scripts/pam_script_auth.d/99-run_virt_credentials +++ b/core/modules/run-virt/data/opt/openslx/scripts/pam_script_auth.d/99-run_virt_credentials @@ -12,38 +12,60 @@ if [ -n "$TEMP_HOME_DIR" ]; then echo "${PERSISTENT_NETPATH}" > "${TEMP_HOME_DIR}/.home" chmod 0644 "${TEMP_HOME_DIR}/.home" fi + # pwdaemon + # Figure out username XUSER="${REAL_ACCOUNT}" [ -z "$XUSER" ] && XUSER="${PAM_USER}" # Figure out domain XDOMAIN= - # Take explicitly configured domain - if [ -s "/opt/openslx/inc/shares" ]; then - . /opt/openslx/inc/shares - XDOMAIN="${SHARE_DOMAIN}" - fi - if [ "x$XDOMAIN" != "x#" ]; then - # Guess domain - if [ -z "$XDOMAIN" ] && [ -n "$PERSISTENT_HOME_DIR" ]; then - XDOMAIN=$(grep -F " ${PERSISTENT_HOME_DIR} " "/proc/mounts" | grep -m1 -F 'domain=' | sed -r 's/^.*[ ,]domain=([^ ,]*)[ ,].*$/\1/g') - fi - if [ -z "$XDOMAIN" ]; then - XDOMAIN=$(<"/etc/ldap.conf" grep -m1 -i '^BASE\s.*DC=' | grep -o -E -i 'DC=([^,;]+)' | head -n 1 | cut -c 4-) + + if [ -d "/opt/openslx/pam/slx-ldap.d" ]; then + # New pretty approach - modular with multiple auth sources + if [ -n "$LDAP_DOMAIN_OVERRIDE" ]; then + [ "x$LDAP_DOMAIN_OVERRIDE" != "x#" ] && XDOMAIN="$LDAP_DOMAIN_OVERRIDE" + else + if [ -z "$XDOMAIN" ] && [ -n "$PERSISTENT_HOME_DIR" ]; then + XDOMAIN=$(grep -F " ${PERSISTENT_HOME_DIR} " "/proc/mounts" | grep -m1 -F 'domain=' | sed -r 's/^.*[ ,]domain=([^ ,]*)[ ,].*$/\1/g') + fi + if [ -z "$XDOMAIN" ] && [ -n "$USER_DN" ]; then + XDOMAIN=$(echo "$USER_DN" | grep -o -E -i 'DC=([^,;]+)' | head -n 1 | cut -c 4-) + fi + if [ -z "$XDOMAIN" ] && [ -n "$LDAP_BASE" ]; then + XDOMAIN=$(echo "$LDAP_BASE" | grep -o -E -i 'DC=([^,;]+)' | head -n 1 | cut -c 4-) + fi + if [ -z "$XDOMAIN" ]; then + XDOMAIN="WORKGROUP" + fi fi - if [ -z "$XDOMAIN" ]; then - XDOMAIN=$(<"/etc/sssd/sssd.conf" grep -m1 -i '^ldap_search_base\s*=.*DC=' | grep -o -E -i 'DC=[^,;]+' | head -n 1 | cut -c 4-) + else + # Old approach - just one global config + # Take explicitly configured domain + if [ -s "/opt/openslx/inc/shares" ]; then + . /opt/openslx/inc/shares + XDOMAIN="${SHARE_DOMAIN}" fi - if [ -n "$XDOMAIN" ]; then - XDOMAIN=$(echo "$XDOMAIN" | tr '[a-z]' '[A-Z]') + if [ "x$XDOMAIN" = "x#" ]; then + XDOMAIN= else - XDOMAIN="WORKGROUP" + # Guess domain + if [ -z "$XDOMAIN" ] && [ -n "$PERSISTENT_HOME_DIR" ]; then + XDOMAIN=$(grep -F " ${PERSISTENT_HOME_DIR} " "/proc/mounts" | grep -m1 -F 'domain=' | sed -r 's/^.*[ ,]domain=([^ ,]*)[ ,].*$/\1/g') + fi + if [ -z "$XDOMAIN" ]; then + XDOMAIN=$(<"/etc/ldap.conf" grep -m1 -i '^BASE\s.*DC=' | grep -o -E -i 'DC=([^,;]+)' | head -n 1 | cut -c 4-) + fi + if [ -z "$XDOMAIN" ]; then + XDOMAIN=$(<"/etc/sssd/sssd.conf" grep -m1 -i '^ldap_search_base\s*=.*DC=' | grep -o -E -i 'DC=[^,;]+' | head -n 1 | cut -c 4-) + fi + if [ -z "$XDOMAIN" ]; then + XDOMAIN="WORKGROUP" + fi fi - XDOMAIN="${XDOMAIN}\\" - else - XDOMAIN= fi - USERNAME="${XDOMAIN}${XUSER}" PASSWORD="$PAM_AUTHTOK" PWSOCKET="${TEMP_HOME_DIR}/.pwsocket" su -c 'pwdaemon --daemon &' "${PAM_USER}" & + [ -n "$XDOMAIN" ] && XDOMAIN="$(echo "$XDOMAIN" | tr '[a-z]' '[A-Z]')\\" + USERNAME="${XDOMAIN}${XUSER}" PASSWORD="$PAM_AUTHTOK" PWSOCKET="${TEMP_HOME_DIR}/.pwsocket" pwdaemon --daemon "${USER_UID}" unset XUSER XDOMAIN fi fi diff --git a/core/modules/run-virt/pw_daemon.c b/core/modules/run-virt/pw_daemon.c index 768a5b00..46a380d7 100644 --- a/core/modules/run-virt/pw_daemon.c +++ b/core/modules/run-virt/pw_daemon.c @@ -15,6 +15,7 @@ #include <sys/socket.h> #include <sys/prctl.h> #include <sys/un.h> +#include <grp.h> static const ssize_t KEYLEN = 16; @@ -25,7 +26,7 @@ static size_t passwordLen = 0; static uint8_t *key1 = NULL, *key2 = NULL; static char *key1s = NULL, *key2s = NULL; -static int mode_daemon(); +static int mode_daemon(const uid_t uidNumber); static int mode_query(const char *socketPath); static void sig_handler(int sig); static int setup_vars(const char *envuser, const char *envpass); @@ -36,12 +37,18 @@ static int init_udp(); int main(int argc, char **argv) { - if (argc > 1 && strcmp(argv[1], "--daemon") == 0) { - return mode_daemon(); + if (argc > 2 && strcmp(argv[1], "--daemon") == 0) { + char *end = NULL; + uid_t uid = (uid_t)strtoul(argv[2], &end, 10); + if (argv[2][0] == '\0' || *end != '\0') { + fprintf(stderr, "Invalid uidNumber\n"); + return 1; + } + return mode_daemon(uid); } else if (argc > 2 && strcmp(argv[1], "--query") == 0) { return mode_query(argv[2]); } - fprintf(stderr, "Invalid call. Use --daemon or --query\n"); + fprintf(stderr, "Invalid call. Use --daemon [uidNumber] or --query [unixSocket]\n"); return 1; } @@ -90,7 +97,7 @@ static int mode_query(const char *socketPath) return 0; } -static int mode_daemon() +static int mode_daemon(const uid_t uidNumber) { int listenFd, udpPort = -1; struct sockaddr_un addr; @@ -98,6 +105,7 @@ static int mode_daemon() const char *envuser = getenv("USERNAME"); const char *envpass = getenv("PASSWORD"); const char *pwsocket = getenv("PWSOCKET"); + gid_t gidNumber = 65534; memset(&addr, 0, sizeof(addr)); memset(&sig, 0, sizeof(sig)); if (envuser == NULL) { @@ -116,6 +124,26 @@ static int mode_daemon() fprintf(stderr, "Error setting up variables\n"); return 1; } + // Drop privs + setgroups(1, &gidNumber); + if (setregid(gidNumber, gidNumber) == -1) { + fprintf(stderr, "Warn: Could not switch to group 'nogroup'\n"); + } + if (setreuid(uidNumber, uidNumber) == -1) { + fprintf(stderr, "Warn: Could not switch to user %d\n", (int)uidNumber); + } + // Only bail out if we're not running as the user requested + setuid(0); + setgid(0); + if (getuid() != uidNumber || geteuid() != uidNumber) { + fprintf(stderr, "Fatal: Currently running as user %d\n", (int)getuid()); + return 1; + } + if (getgid() == 0 || getegid() == 0) { + fprintf(stderr, "Fatal: Current process gid is 0 (root)\n"); + return 1; + } + // Create unix socket listenFd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); if (listenFd == -1) { perror("Could not create unix socket"); @@ -138,6 +166,8 @@ static int mode_daemon() perror("Cannot listen on unix socket"); return 1; } + // Daemon + daemon( 0, 0 ); // Mainloop sig.sa_handler = &sig_handler; sigaction(SIGCHLD, &sig, NULL); |