From 53f8946416b456476d130334490790c3979d2f82 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 8 Mar 2018 17:14:42 +0100 Subject: [pam-slx-plug] Starting to separate some of the pam/nsswitch logic out of sssd/pam Preparation for our own ldap/ad login handling, sssd will only be used for nsswitch related stuff and fallback. --- .../slx-update-pam-nss.service | 1 + .../etc/systemd/system/slx-update-pam-nss.service | 8 + .../data/opt/openslx/pam/auth-source.d/99-slx-ldap | 183 ++++++++++++++++++ .../data/opt/openslx/pam/common/homedir-passwd | 27 +++ .../pam-slx-plug/data/opt/openslx/pam/exec_account | 50 +++++ .../pam-slx-plug/data/opt/openslx/pam/exec_auth | 204 +++++++++++++++++++++ .../pam-slx-plug/data/opt/openslx/pam/exec_session | 8 + .../pam-slx-plug/data/opt/openslx/pam/mkhome | 13 ++ .../data/opt/openslx/pam/mount.d/99-fallback | 97 ++++++++++ .../data/opt/openslx/pam/systemd/create-pam-config | 121 ++++++++++++ core/modules/pam-slx-plug/module.build | 12 ++ core/modules/pam-slx-plug/module.conf | 3 + 12 files changed, 727 insertions(+) create mode 120000 core/modules/pam-slx-plug/data/etc/systemd/system/multi-user.target.wants/slx-update-pam-nss.service create mode 100644 core/modules/pam-slx-plug/data/etc/systemd/system/slx-update-pam-nss.service create mode 100644 core/modules/pam-slx-plug/data/opt/openslx/pam/auth-source.d/99-slx-ldap create mode 100644 core/modules/pam-slx-plug/data/opt/openslx/pam/common/homedir-passwd create mode 100755 core/modules/pam-slx-plug/data/opt/openslx/pam/exec_account create mode 100755 core/modules/pam-slx-plug/data/opt/openslx/pam/exec_auth create mode 100755 core/modules/pam-slx-plug/data/opt/openslx/pam/exec_session create mode 100755 core/modules/pam-slx-plug/data/opt/openslx/pam/mkhome create mode 100644 core/modules/pam-slx-plug/data/opt/openslx/pam/mount.d/99-fallback create mode 100755 core/modules/pam-slx-plug/data/opt/openslx/pam/systemd/create-pam-config create mode 100644 core/modules/pam-slx-plug/module.build create mode 100644 core/modules/pam-slx-plug/module.conf (limited to 'core/modules/pam-slx-plug') diff --git a/core/modules/pam-slx-plug/data/etc/systemd/system/multi-user.target.wants/slx-update-pam-nss.service b/core/modules/pam-slx-plug/data/etc/systemd/system/multi-user.target.wants/slx-update-pam-nss.service new file mode 120000 index 00000000..450c4948 --- /dev/null +++ b/core/modules/pam-slx-plug/data/etc/systemd/system/multi-user.target.wants/slx-update-pam-nss.service @@ -0,0 +1 @@ +../slx-update-pam-nss.service \ No newline at end of file diff --git a/core/modules/pam-slx-plug/data/etc/systemd/system/slx-update-pam-nss.service b/core/modules/pam-slx-plug/data/etc/systemd/system/slx-update-pam-nss.service new file mode 100644 index 00000000..fa7a8bd0 --- /dev/null +++ b/core/modules/pam-slx-plug/data/etc/systemd/system/slx-update-pam-nss.service @@ -0,0 +1,8 @@ +[Unit] +Description=Create fresh pam config and nsswitch.conf +Before=graphical.target display-manager.target + +[Service] +Type=oneshot +ExecStart=/opt/openslx/pam/systemd/create-pam-config + diff --git a/core/modules/pam-slx-plug/data/opt/openslx/pam/auth-source.d/99-slx-ldap b/core/modules/pam-slx-plug/data/opt/openslx/pam/auth-source.d/99-slx-ldap new file mode 100644 index 00000000..0b5ca0f6 --- /dev/null +++ b/core/modules/pam-slx-plug/data/opt/openslx/pam/auth-source.d/99-slx-ldap @@ -0,0 +1,183 @@ +#!/bin/ash -- sourced + +# Run 'account' or 'auth' PAM mode +# account: +# See if user is allowed to login (=exists in our case) +# auth: +# Try logging in via ldapsearch + +# parameters supplied via +# /opt/openslx/pam/slx-ldap.d/* + +WAIT= + +unset_ldap_vars() { + local vn + for vn in $(set | grep -Eo '^(SHARE|LDAP)_[^=]+'); do + unset "$vn" + done + unset USER_UID USER_GID USER_GROUP REAL_ACCOUNT NETWORK_HOME HOME_MOUNT_OPTS +} + +# ldapsearch can return fields either as +# field: value +# or +# field:: base64encode(value) +# -- handle both cases and return the value +# extract_field [another resultfile [...]] +extract_field() { + local l len file + local field=$1 + shift + while [ $# -gt 0 ]; do + file=$1 + shift + l=$( grep -m 1 -i "^${field}: " "$file" ) + if [ -n "$l" ]; then + len=$(( ${#field} + 2 )) + echo "${l:$len}" + return + fi + l=$( grep -m 1 -i "^${field}:: " "$file" ) + if [ -n "$l" ]; then + len=$(( ${#field} + 3 )) + echo "${l:$len}" | base64 -d + return + fi + done +} + +run_auth() { + local BINDDN SEARCH_ANON SEARCH_USER PW RET + if [ -n "$LDAP_CACERT" ]; then + export LDAPTLS_CACERT="$LDAP_CACERT" + else + unset LDAPTLS_CACERT + fi + # See if user exists + SEARCH_ANON=$(mktemp) + TEMPFILES_LDAP="$TEMPFILES_LDAP $SEARCH_ANON" + for retries in 0 1 1 2 3 END; do + ldapsearch -x -LLL -l 3 -o nettimeout=3 -o ldif-wrap=no \ + -H "$LDAP_URI" -b "$LDAP_BASE" uid="${PAM_USER}" \ + dn distinguishedName homeMount realAccount uid uidNumber gidNumber ${LDAP_ATTR_MOUNT_OPTS} &> "${SEARCH_ANON}" + RET=$? + case "$RET" in + 0) break # OK + ;; + 51|52) sleep 3 # busy, let's try again + ;; + 255) # Network error + # grep the output to see whether the bind succeeded, it should have returned anything but -1 + < "$SEARCH_ANON" grep -q '^ldap_bind:.*(-1)$' || break # If == -1, continue + ;; + *) + slxlog "pam-slxldap-ldapsearch" "Initial ldapsearch for $PAM_USER returned $RET" "$SEARCH_ANON" + WAIT=1 + break + ;; + esac + sleep "$retries" &> /dev/null # lazy END handling + done + BINDDN=$(extract_field "dn" "$SEARCH_ANON") + [ -z "$BINDDN" ] && BINDDN=$(extract_field "distinguishedName" "$SEARCH_ANON") + [ -z "$BINDDN" ] && return 1 + # User exists + if [ "$PAM_TYPE" = "account" ]; then + # 'account' checks just if the user is allowed to log in, bail out + USER_UID=$(extract_field "uidNumber" "$SEARCH_ANON") + USER_GID=$(extract_field "gidNumber" "$SEARCH_ANON") + USER_HOME=$(extract_field "homeDirectory" "$SEARCH_ANON") + return 0 + fi + SEARCH_USER=$(mktemp) + TEMPFILES_LDAP="$TEMPFILES_LDAP $SEARCH_USER" + PW="/run/pw.${RANDOM}.${RANDOM}.${PAM_USER}.${RANDOM}.$$" + for retries in 0 1 1 0; do + if ! mkfifo -m 0600 "${PW}"; then + slxlog "pam-slxldap-fifo" "Could not create FIFO at ${PW}" + return 1 + fi + ( # Blocking write to FIFO, fork into bg. Make sure to use a shell that understands echo -n (busybox ash does) + echo -n "${USER_PASSWORD}" > "${PW}" + ) & + # unquoted LDAP_ATTR_* + ldapsearch -x -LLL -l 5 -o nettimeout=5 -o ldif-wrap=no \ + -H "$LDAP_URI" -b "$LDAP_BASE" uid="${PAM_USER}" -y "${PW}" -D "$BINDDN" uid="${PAM_USER}" \ + homeMount realAccount uid uidNumber gidNumber ${LDAP_ATTR_MOUNT_OPTS} &> "${SEARCH_USER}" + RET=$? + rm -f -- "${PW}" + case "$RET" in + 0|49|50) break # Either success, or access denied / invalid user/pass + ;; + 51|52) sleep 3 # busy, let's try again + ;; + 255) # Network error + # grep the output to see whether the bind succeeded, it should have returned anything but -1 + < "$SEARCH_USER" grep -q '^ldap_bind:.*(-1)$' || break # If == -1, continue + ;; + *) + slxlog "pam-slxldap-ldapsearch" "User-bind for $PAM_USER returned $RET" "$SEARCH_USER" + WAIT=1 + break + ;; + esac + sleep "$retries" + done + [ "$RET" = 0 ] || return 1 + USER_UID=$(extract_field "uidNumber" "$SEARCH_USER" "$SEARCH_ANON") + if [ -z "$USER_UID" ]; then + slxlog --echo "pam-slxldap-nouid" "User $PAM_USER found in ldap, but has no uidNumber" + return 1 + fi + USER_GID=$(extract_field "gidNumber" "$SEARCH_USER" "$SEARCH_ANON") + if [ -z "$USER_GID" ]; then + slxlog --echo "pam-slxldap-nogid" "User $PAM_USER / $USER_UID found in ldap, but has no gidNumber" + unset USER_UID + return 1 + fi + REAL_ACCOUNT=$(extract_field "realAccount" "$SEARCH_USER" "$SEARCH_ANON") + [ -z "$REAL_ACCOUNT" ] && REAL_ACCOUNT=$(extract_field "uid" "$SEARCH_USER" "$SEARCH_ANON") + NETWORK_HOME=$(extract_field "homeMount" "$SEARCH_USER" "$SEARCH_ANON") + USER_HOME=$(extract_field "homeDirectory" "$SEARCH_USER" "$SEARCH_ANON") + HOME_MOUNT_OPTS="${SHARE_HOME_MOUNT_OPTS}" + if [ -n "$LDAP_ATTR_HOME_MOUNT_OPTS" ]; then + RET=$(extract_field "${LDAP_ATTR_HOME_MOUNT_OPTS}" "$SEARCH_USER" "$SEARCH_ANON") + [ -n "$RET" ] && HOME_MOUNT_OPTS="$RET" + fi + # Group - might need another round trip to LDAP + USER_GROUP=$( awk -F: '{ if ($3 == '"$USER_GID"') { print $1; exit } }' /etc/group ) + if [ -z "$USER_GROUP" ]; then + ldapsearch -x -LLL -l 2 -o nettimeout=2 -o ldif-wrap=no \ + -H "$LDAP_URI" -b "$LDAP_BASE" "(&(objectClass=posixGroup)(gidNumber=${USER_GID}))" \ + cn &> "${SEARCH_ANON}" + USER_GROUP=$(extract_field "cn" "$SEARCH_ANON") + fi + return 0 +} + +TEMPFILES_LDAP= + +for s_file in /opt/openslx/pam/slx-ldap.d/*; do + unset_ldap_vars + [ -f "$s_file" ] || continue + . "$s_file" + if [ -z "$LDAP_URI" ] || [ -z "$LDAP_BASE" ]; then + slxlog --echo "pam-slxldap-empty" "LDAP config '$s_file' is missing URI or BASE" + continue + fi + run_auth && break +done + +if [ -z "$USER_UID" ]; then + unset_ldap_vars +fi + +if [ -n "$TEMPFILES_LDAP" ]; then + rm -f -- $TEMPFILES_LDAP +fi + +[ -n "$WAIT" ] && sleep 1 + +true + diff --git a/core/modules/pam-slx-plug/data/opt/openslx/pam/common/homedir-passwd b/core/modules/pam-slx-plug/data/opt/openslx/pam/common/homedir-passwd new file mode 100644 index 00000000..20b7991d --- /dev/null +++ b/core/modules/pam-slx-plug/data/opt/openslx/pam/common/homedir-passwd @@ -0,0 +1,27 @@ +#!/bin/ash -- sourced + +# Required vars from context: +# USER_UID +# USER_GID +# USER_NAME + +# 1) Sanitize the user's home directory, stored and updated in USER_HOME + +# 2) Write entry to /etc/passwd if it doesn't exist + +# Fixup local home path +if [ -z "$USER_HOME" ] || [ "${USER_HOME:0:1}" = '\' ] || [ "${USER_HOME:1:1}" = ':' ]; then + USER_HOME="/home/_temp-home/$USER_NAME" +else + # Make sure it's absolute, replace spaces, '\' and ':' by '_' + USER_HOME=$(echo "$USER_HOME" | sed -r 's,^(/*)(.*)$,/\2,;s/(:|\s|\\)+/_/g') +fi +readonly USER_HOME + +# Add/replace passwd entry if it doesn't exist yet +PASSWD="${USER_NAME}:x:${USER_UID}:${USER_GID}:${USER_NAME}:${USER_HOME}:/bin/bash" +readonly PASSWD +if ! grep -Fxq -- "${PASSWD}" /etc/passwd; then + sed -i "/^${USER_NAME}:/d" /etc/passwd + echo "${PASSWD}" >> /etc/passwd +fi diff --git a/core/modules/pam-slx-plug/data/opt/openslx/pam/exec_account b/core/modules/pam-slx-plug/data/opt/openslx/pam/exec_account new file mode 100755 index 00000000..f481d302 --- /dev/null +++ b/core/modules/pam-slx-plug/data/opt/openslx/pam/exec_account @@ -0,0 +1,50 @@ +#!/bin/ash + +[ "$PAM_TYPE" = "account" ] || exit 1 + +USER_NAME="$PAM_USER" +readonly PAM_USER USER_NAME + +export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/openslx/sbin:/opt/openslx/bin" + +# check for invalid char ':' +if echo "$PAM_USER" | grep -Fq ':'; then + slxlog --echo "pam-format-username" "Username '$PAM_USER' contains disallowed character ':', denying access" + exit 1 +fi + +# check if the script runs as root +[ "x$(whoami)" = "xroot" ] || exit 1 + +# passwd but no shadow hints at a user we added - allow +grep -q "^${PAM_USER}:" "/etc/shadow" && exit 1 +grep -q "^${PAM_USER}:" "/etc/passwd" && exit 0 + +# Have neither, run hooks +for auth_file in /opt/openslx/pam/auth-source.d/*; do + USER_UID= + USER_GID= + [ -f "$auth_file" ] || continue + . "$auth_file" + [ -n "$USER_UID" ] || continue + break +done +readonly USER_UID USER_GID + +[ -n "$USER_UID" ] || exit 1 +# Got ok from hook - cache in passwd if we got a USER_GID +[ -n "$USER_GID" ] || exit 0 # OK without caching, no GID + +if ! echo "$USER_UID" | grep -Exq '[0-9]+'; then + slxlog --echo "pam-format-uid" "'$PAM_USER' has invalid userid '$USER_UID'" + exit 0 +fi +if [ -n "$USER_GID" ] && ! echo "$USER_GID" | grep -Exq '[0-9]+'; then + slxlog --echo "pam-format-gid" "'$PAM_USER' has invalid groupid '$USER_GID'" + exit 0 +fi + +. /opt/openslx/pam/common/homedir-passwd + +exit 0 + diff --git a/core/modules/pam-slx-plug/data/opt/openslx/pam/exec_auth b/core/modules/pam-slx-plug/data/opt/openslx/pam/exec_auth new file mode 100755 index 00000000..ef964d5f --- /dev/null +++ b/core/modules/pam-slx-plug/data/opt/openslx/pam/exec_auth @@ -0,0 +1,204 @@ +#!/bin/ash + +# 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 + +USER_NAME="$PAM_USER" +readonly PAM_USER USER_NAME + +# Needed as pam_script clears PATH +export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/openslx/sbin:/opt/openslx/bin" + +# check for invalid char ':' +if echo "$PAM_USER" | grep -Fq ':'; then + slxlog --echo "pam-format-username" "Username '$PAM_USER' contains disallowed character ':', denying access" + exit 1 +fi + +# check if the script runs as root +[ "x$(whoami)" = "xroot" ] || exit 1 + +# See if we have a shadow entry - skip user in that case +grep -q "^${PAM_USER}:" "/etc/shadow" && exit 1 + +# ppam -- pluggable pluggable authentication module +# Source all scripts in the auth-source.d directory +# until one succeeds. +# A succeeding script should set USER_UID to the +# uidNumber of the user authenticating, additionally +# it must set USER_GID or USER_GROUP (or both). +# Additional variables that can be set are +# NETWORK_HOME (network path to home directory) +# HOME_MOUNT_OPTS (mount options to use) +# REAL_ACCOUNT (real account name in case any +# mapping took place) +for auth_file in /opt/openslx/pam/auth-source.d/*; do + NETWORK_HOME= + HOME_MOUNT_OPTS= + REAL_ACCOUNT= + USER_UID= + USER_GID= + USER_GROUP= + USER_HOME= + [ -f "$auth_file" ] || continue + . "$auth_file" + [ -n "$USER_UID" ] || continue + [ -n "${USER_GID}${USER_GROUP}" ] || continue + break +done +[ -z "$REAL_ACCOUNT" ] && REAL_ACCOUNT="$PAM_USER" +readonly USER_UID REAL_ACCOUNT + +# No success - access denied +[ -z "$USER_UID" ] && exit 1 +[ "x$USER_UID" = "x0" ] && exit 1 + +# Validate +if ! echo "$USER_UID" | grep -Exq '[0-9]+'; then + slxlog --echo "pam-format-uid" "'$PAM_USER' has invalid userid '$USER_UID'" + exit 1 +fi +if [ -n "$USER_GID" ] && ! echo "$USER_GID" | grep -Exq '[0-9]+'; then + slxlog --echo "pam-format-gid" "'$PAM_USER' has invalid groupid '$USER_GID'" + exit 1 +fi +if [ "$(echo "${USER_UID}${USER_GID}${USER_GROUP}${USER_HOME}" | wc -l)" != "1" ]; then + slxlog --echo "pam-format-any" "A ppam module returned multilined attributes for uid/gid/group/home" + exit 1 +fi + +# Make sure group exists locally +GROUPENT= +if [ -n "$USER_GID" ]; then + GROUPENT=$(getent group "$USER_GID" 2>/dev/null) +fi +if [ -z "$GROUPENT" ] && [ -n "$USER_GROUP" ]; then + GROUPENT=$(getent group "$USER_GROUP" 2>/dev/null) +fi +# Force -- neither group nor gid exist yet +if [ -z "$GROUPENT" ]; then + if [ -z "$USER_GROUP" ]; then + USER_GROUP=generic + fi + if [ -n "$USER_GID" ]; then + addgroup -g "$USER_GID" "$USER_GROUP" >/dev/null 2>&1 + else + addgroup "$USER_GROUP" >/dev/null 2>&1 + fi + GROUPENT=$(getent group "$USER_GROUP") +fi + +if [ -n "$GROUPENT" ]; then + [ -z "$USER_GID" ] && USER_GID=$(echo "$GROUPENT" | awk -F ':' '{print $3}') + [ -z "$USER_GROUP" ] && USER_GROUP=$(echo "$GROUPENT" | awk -F ':' '{print $1}') + if ! grep -q "^${USER_GROUP}:" '/etc/group'; then + echo "$GROUPENT" >> '/etc/group' + fi +fi +readonly USER_GID USER_GROUP + +. /opt/openslx/pam/common/homedir-passwd + +# The user's non-persistent home directory mount point, which should be their linux home +TEMP_HOME_DIR="$USER_HOME" +# The user's persistent home directory mount point +PERSISTENT_HOME_DIR="${TEMP_HOME_DIR}/PERSISTENT" +readonly TEMP_HOME_DIR PERSISTENT_HOME_DIR + +############################################################################### +# +# Preparations for volatile /home/ +# +# +# check if we already mounted the home directory +if ! awk '{print $2}' /proc/mounts | grep -Fxq -- "${TEMP_HOME_DIR}"; then + # no home, lets create it + if ! mkdir -p "${TEMP_HOME_DIR}"; then + slxlog --echo "pam-global-mktemphome" "Could not create '${TEMP_HOME_DIR}'." + fi + if ! mount -t tmpfs -o mode=700,size=1024m tmpfs "${TEMP_HOME_DIR}"; then + slxlog --echo "pam-global-tmpfstemphome" "Could not make a tmpfs on '${TEMP_HOME_DIR}'" + fi + if ! chown "${USER_UID}:${USER_GID}" "${TEMP_HOME_DIR}"; then + slxlog --echo "pam-global-chpersistent" "Could not chown '${TEMP_HOME_DIR}' to '${PAM_USER}'." + fi +fi +if [ -n "${REAL_ACCOUNT}" ]; then + echo "${REAL_ACCOUNT}" > "${TEMP_HOME_DIR}/.account" + chmod 0644 "${TEMP_HOME_DIR}/.account" +fi + + +############################################################################### +# +# Preparations for /home//PERSISTENT +# +# +isHomeMounted() { + grep -Fuq " ${PERSISTENT_HOME_DIR} " /proc/mounts +} + +PERSISTENT_OK= +if ! isHomeMounted; then + if ! mkdir -p "${PERSISTENT_HOME_DIR}"; then + slxlog "pam-global-mkpersistent" "Could not create '${PERSISTENT_HOME_DIR}'." + else + for mount_file in /opt/openslx/pam/mount-persistent.d/*; do + [ -f "$mount_file" ] || continue + . "$mount_file" + if isHomeMounted; then + PERSISTENT_OK="yes" + break + fi + done + fi +fi + +# Just try to delete the persistent dir. If the mount was successful, it will not work +# If it was not successful, it will be removed so the user doesn't think he can store +# anything in there +rmdir -- "${PERSISTENT_HOME_DIR}" 2> /dev/null + +# Write warning message to tmpfs home +if [ -n "${PERSISTENT_OK}" ]; then + # home directory mount SUCCESS + # create a WARNING.txt for the user with hint to PERSISTENT + # Remember for hooks in pam_script_auth.d + if [ "${NETWORK_HOME:0:2}" = '//' ]; then + PERSISTENT_NETPATH=$(echo "$NETWORK_HOME" | tr '/' '\') + else + PERSISTENT_NETPATH="$NETWORK_HOME" + fi + export PERSISTENT_NETPATH + cat > "${TEMP_HOME_DIR}/WARNING.txt" < "${TEMP_HOME_DIR}/WARNING.txt" < "$FILE" + [ -n "$OPTS" ] && COMMAND_LINE="$COMMAND_LINE -o ${OPTS:1}" + mount ${COMMAND_LINE} "${NETWORK_HOME}" "${PERSISTENT_HOME_DIR}" >> "${FILE}" 2>&1 & + PID=$! + # Wait max. 1 second; remember PID if this mount call seems to be running after we stop waiting + for waits in 1 2 3 4; do + usleep 250000 + if isHomeMounted; then + # A previously invoked mount call might have succeeded while this one is still running; try to stop it right away + kill "$PID" &> /dev/null + break 3 + fi + kill -0 "$PID" || break + done + kill -0 "$PID" && PIDS="$PIDS $PID" # Remember all PIDs + done +done + +unset USER +unset PASSWD + +if [ -n "$PIDS" ]; then + CNT=0 + while ! isHomeMounted && [ "$CNT" -lt 10 ] && kill -0 $PIDS; do # No quotes + usleep 333000 + CNT=$(( CNT + 1 )) + done + kill -9 $PIDS # Kill any leftovers; No quotes +fi + +if ! isHomeMounted; then + LOG_COMBINED=$(mktemp) + [ -n "$LOGFILES" ] && cat ${LOGFILES} > "$LOG_COMBINED" # No quotes + slxlog --delete "pam-ad-mount" "Mount of '${VOLUME}' to '${PERSISTENT_HOME_DIR}' failed." "${LOG_COMBINED}" +fi + +[ -n "${LOGFILES}" ] && rm -f -- ${LOGFILES} # No quotes +true + diff --git a/core/modules/pam-slx-plug/data/opt/openslx/pam/systemd/create-pam-config b/core/modules/pam-slx-plug/data/opt/openslx/pam/systemd/create-pam-config new file mode 100755 index 00000000..0138d3d0 --- /dev/null +++ b/core/modules/pam-slx-plug/data/opt/openslx/pam/systemd/create-pam-config @@ -0,0 +1,121 @@ +#!/bin/bash +# -- bash for arrays + +export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/openslx/sbin:/opt/openslx/bin" + +declare -a auth +declare -a account +declare -a session +declare -a nss +declare -a dns + +# Our plugin, but account ONLY since it's fast +account+=("[success=%NUM% new_authtok_reqd=done default=ignore] pam_exec.so quiet /opt/openslx/pam/exec_account") + +# unix +auth+=("[success=%NUM% default=ignore] pam_unix.so nodelay") +account+=("[success=%NUM% new_authtok_reqd=done default=ignore] pam_unix.so") +nss+=("files" "cache") + +# check for bwIDM +if [ -x "/opt/openslx/scripts/pam_bwidm" ]; then + auth+=("[success=%NUM% default=ignore] pam_exec.so quiet expose_authtok /opt/openslx/scripts/pam_bwidm") + account+=("[success=%NUM% new_authtok_reqd=done default=ignore] pam_exec.so quiet /opt/openslx/scripts/pam_bwidm") +fi + +# Insert kerberos before our auth module +if [ -s "/etc/ksb5.conf" ]; then + auth+=("optional pam_krb5.so minimum_uid=1000 use_first_pass") + session+=("optional pam_krb5.so minimum_uid=1000") +fi + +# Our plugin, auth now +auth+=("[success=%NUM% default=ignore] pam_exec.so quiet expose_authtok /opt/openslx/pam/exec_auth") + +# sssd if reasonable +if systemctl is-enabled -q sssd.service && grep -q -e '^\s*id_provider' -e '^\s*auth_provider' "/etc/sssd/sssd.conf"; then + auth+=("[success=%NUM% default=ignore] pam_sss.so use_first_pass") + account+=("[success=%NUM% new_authtok_reqd=done default=ignore] pam_sss.so") + nss+=("sss") + # Skip sss if unix worked + session+=("[success=1] pam_unix.so") + session+=("optional pam_sss.so") +else + session+=("optional pam_unix.so") +fi + +# DNS +dns+=("files" "cache") +if systemctl is-enabled -q systemd-resolved; then + dns+=("resolve") +fi +dns+=("dns") + +session+=("optional pam_exec.so quiet /opt/openslx/pam/exec_session") + +# +# Write pam configs +tmpfile=$(mktemp) +# common-auth +skip=$(( ${#auth[@]} + 1 )) +echo "# Generated $(date)" > "$tmpfile" +for line in "${auth[@]}"; do + echo "auth ${line//%NUM%/$skip}" + skip=$(( skip - 1 )) +done >> "$tmpfile" +cat >> "$tmpfile" <<-HERE + auth optional pam_faildelay.so delay=2123123 + auth requisite pam_deny.so + auth required pam_permit.so + auth optional pam_cap.so +HERE +cp -f -- "$tmpfile" "/etc/pam.d/common-auth" + +# common-account +skip=${#account[@]} +echo "# Generated $(date)" > "$tmpfile" +for line in "${account[@]}"; do + echo "account ${line//%NUM%/$skip}" + skip=$(( skip - 1 )) +done >> "$tmpfile" +cat >> "$tmpfile" <<-HERE + account requisite pam_deny.so + account required pam_permit.so +HERE +cp -f -- "$tmpfile" "/etc/pam.d/common-account" + +# common-session +cat > "$tmpfile" <<-HERE + session required pam_permit.so + session optional pam_umask.so + session required pam_systemd.so + session optional pam_env.so readenv=1 + session optional pam_env.so readenv=1 envfile=/etc/default/locale + session optional pam_exec.so quiet /opt/openslx/pam/mkhome +HERE +for line in "${session[@]}"; do + echo "session $line" +done >> "$tmpfile" +cp -f -- "$tmpfile" "/etc/pam.d/common-session" + +# +# Write nsswitch.conf +cat > "/etc/nsswitch.conf" <<-HERE +# Generated $(date) +passwd: ${nss[@]} +group: ${nss[@]} +shadow: files + +hosts: ${dns[@]} +networks: files + +protocols: db files +services: db files +ethers: db files +rpc: db files + +netgroup: nis +HERE + +exit 0 + diff --git a/core/modules/pam-slx-plug/module.build b/core/modules/pam-slx-plug/module.build new file mode 100644 index 00000000..241bcd5e --- /dev/null +++ b/core/modules/pam-slx-plug/module.build @@ -0,0 +1,12 @@ +#!/bin/bash +fetch_source() { + : +} + +build() { + pinfo "Static module, nothing to build." +} + +post_copy() { + : +} diff --git a/core/modules/pam-slx-plug/module.conf b/core/modules/pam-slx-plug/module.conf new file mode 100644 index 00000000..237dd69c --- /dev/null +++ b/core/modules/pam-slx-plug/module.conf @@ -0,0 +1,3 @@ +#!/bin/bash +REQUIRED_BINARIES=" +" -- cgit v1.2.3-55-g7522