#!/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 # Needed as pam_script/pam_exec 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 SCRIPT_USER=$(whoami) readonly SCRIPT_USER [ "x$SCRIPT_USER" = "xroot" ] || [ "x$SCRIPT_USER" = "x$PAM_USER" ] || exit 1 grepname=$( echo "$PAM_USER" | sed 's/\./\\./g;s/*/\\*/g' ) if [ "$SCRIPT_USER" = "root" ]; then # See if we have a shadow entry - skip user in that case grep -q -i "^${grepname}:" "/etc/shadow" && exit 1 else # Running in user context - user must be known from before grep -q "^${grepname}:x:.*:.*:${grepname}@SLX:" "/etc/passwd" || exit 1 fi # 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= USER_DN= USER_INFO_FILE= [ -f "$auth_file" ] || continue . "$auth_file" [ -n "$USER_UID" ] || continue [ -n "${USER_GID}${USER_GROUP}" ] || continue break done # No success - access denied [ -z "$USER_UID" ] && exit 1 # No root [ "$USER_UID" = "0" ] && exit 1 [ -z "$REAL_ACCOUNT" ] && REAL_ACCOUNT="$PAM_USER" readonly USER_UID REAL_ACCOUNT USER_NAME # Confirm caps matches! if [ "$USER_NAME" != "$PAM_USER" ]; then echo "Capitalization mismatch: '$PAM_USER' vs. '$USER_NAME'" >&2 exit 1 fi # 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 # If not run as root, we're done here as the directory mount stuff etc. doesn't make any sense [ "$SCRIPT_USER" = "root" ] || exit 0 # 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 "uid=${USER_UID},gid=${USER_GID},mode=0700,size=1024m" tmpfs "${TEMP_HOME_DIR}"; then slxlog --echo "pam-global-tmpfstemphome" "Could not make a tmpfs on '${TEMP_HOME_DIR}'" fi # mount another tmpfs into subdir so we can create files that the user cannot modify # but still read, while at the same time preventing any other user from reading it mkdir -p "${TEMP_HOME_DIR}/.openslx" mount -t tmpfs -o size=1m,uid=0,gid=0,mode=0755 tmpfs "${TEMP_HOME_DIR}/.openslx" fi if [ -n "${REAL_ACCOUNT}" ]; then echo "${REAL_ACCOUNT}" > "${TEMP_HOME_DIR}/.openslx/account" chmod 0644 "${TEMP_HOME_DIR}/.openslx/account" fi if [ -n "$USER_INFO_FILE" ] && [ -s "$USER_INFO_FILE" ]; then mv -- "$USER_INFO_FILE" "${TEMP_HOME_DIR}/.openslx/ldap" chmod 0644 "${TEMP_HOME_DIR}/.openslx/ldap" 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.d/*; do [ -f "$mount_file" ] || continue . "$mount_file" if isHomeMounted; then PERSISTENT_OK="yes" break fi done fi else PERSISTENT_OK="yes" 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 cat > "${TEMP_HOME_DIR}/WARNING.txt" < "${TEMP_HOME_DIR}/WARNING.txt" <