#!/bin/sh
#
# Monta automáticamente un directorio personal cifrado para todo usuario
# que pertenezca al grupo "crypto". Debe usarse con pam_exec, añadiendo
# al final de /etc/pam.d/common-sesssion lo siguiente:
#
# auth      optional pam_exec.so seteuid expose_authtok /usr/local/bin/mgocryptfs
# session   optional pam_exec.so /usr/local/bin/mgocryptfs
#
# Pueden añadirse tras el nombre del ejecutable los siguientes argumentos:
#
# dir=ruta    Dirección donde se verán los datos descrifrados. La ruta
#             de los datos cifrados es la misma, pero anteponiendo un ".". Las
#             rutas relativas se consideran respecto al directorio de usuario.
#
# create=0|1  Para que se cree automáticamente el directorio cifrado,
#             si no existe. Si su valor es 0 y no existe el directorio, el
#             script no intentará ningún montaje.
#
# group=grupo Grupo al que pertenecen los usuarios con directorio cifrado.
#             Por defecto es crypto.
#
# La contraseña para descifrar el contenido del directorio debe ser la misma
# que la de usuario. cryfs aún no permite cambiar la contraseña de cifrado.

while [ $# -gt 0 ]; do
   eval $1
   shift
done
[ -n "$dir" ] || dir="Cifrado"
[ -n "$group" ] || group="crypto"
[ -n "$create" ] || create=0

HOME=$(getent passwd ${PAM_USER} | cut -f6 -d:)

[ -n "$HOME" ] || exit 0

# Si no pertenece al grupo, no se hace nada
id -Gn "$PAM_USER" | grep -qw $group || exit 0

if echo $dir | grep -q '^[^/]'; then # La ruta es relativa
   dir="$HOME/$dir"
fi

mount_cryfs() {
   local PASSWORD=`cat`
   local PLAIN="$dir"
   local CIPHER="$(dirname $dir)/.$(basename $dir)"

   # Comprobamos si ya está montado
   mount | awk '$3 == "'"$PLAIN"'"' | grep -q '' && exit 0

   if [ ! -f "$CIPHER/gocryptfs.conf" ]; then
      [ $create -eq 1 ] || exit 0

      mkdir -p "$CIPHER" "$PLAIN"
      gocryptfs -init -extpass "/usr/bin/printf $PASSWORD" "$CIPHER"
      chown -R ${PAM_USER}:$group "$CIPHER" "$PLAIN"
   fi

   runuser -u "${PAM_USER}" -- /usr/bin/gocryptfs -extpass "/usr/bin/printf $PASSWORD" "$CIPHER" "$PLAIN"
}

case "$PAM_TYPE" in
   auth)
      mount_cryfs
      ;;
   open_session)
      # Ya se monta el directorio en auth
      ;;
   close_session)
      # Sólo Si no hay más sesiones abiertas de usuario y el directorio está montado, desmontamos
      w | grep -q ^$PAM_USER || { mount | awk '$3 == "'"$dir"'"' | grep -q '' && fusermount -u "$dir"; }
      ;;
   *)
      exit 0
      ;;
esac
