web-dev-qa-db-fra.com

autorisation sed refusée lors de l'utilisation de pam_exec avec su

J'utilise pam_mount.so pour monter automatiquement un partage CIFS pour les utilisateurs sur un client Ubuntu 14.04.

pam_mount utilise une conf locale dans le répertoire de base de chaque utilisateur. J'exécute un script bash avec pam_exec qui met à jour le fichier de configuration avec le chemin d'accès au partage CIFS.

La fin de mon fichier /etc/pam.d/common-session ressemble à ceci:

session required    pam_unix.so 
session optional    pam_exec.so log=/var/log/pamexec /usr/local/bin/mdrive_add
session optional    pam_mount.so 
session optional    pam_ldap.so 
session optional    pam_systemd.so

Lorsque vous vous connectez avec SSH ou via l'interface graphique, cela fonctionne, le script est exécuté avant le montage, de sorte que le partage est accessible.

Cependant, lors de l'utilisation de su, le script échoue et la conf de l'utilisateur local n'est pas mise à jour. Le montage échoue également.

L'erreur que je reçois lorsque j'utilise su de [accountA] à [accountB] est la suivante:

/bin/sed: couldn't open temporary file /home/[accountB]/sednpoogQ: Permission denied

La ligne du script qui échoue est la suivante:

/bin/sed -i "s|\@S|${XSERVER}|g" /home/${PAM_USER}/.pam_mount.conf.xml

J'ai essayé d'exécuter le script à partir de ~/.profile et d'autres endroits, cela fonctionne parfaitement, mais n'est pas exécuté avant pam_mount.

Ma question est donc la suivante: comment puis-je obtenir que pam_exec remplace une chaîne dans un fichier texte résidant dans le répertoire de base d'un utilisateur lors de l'utilisation de su?

Mise à jour

D'après les commentaires, j'ai essayé 'Sudo -u [accountb] -i' (après avoir inclus @ common-session dans /etc/pam.d/Sudo) et cela ne renvoie pas la même erreur, cela fonctionne. Cependant, ce n'est pas une solution acceptable, car j'ai besoin de su pour fonctionner (et cela provoque une invite de mot de passe de pam_mount).

pdate2

Je me suis connecté avec ssh, j'ai envoyé un fichier env dans un fichier, puis je me suis connecté avec ssh à partir d'un autre compte, utilisé su et un fichier env avec env.

En comparant les deux (noms de compte remplacés par accounta et accountb comme dans la question:

$ comm -3 <(sort ssh_list.txt ) <(sort su_list.txt)
    PASSWD_FD=0
    _PMT_DEBUG_LEVEL=0
    PWD=/home/[accounta]
PWD=/home/[accountb]
SHLVL=1
    SHLVL=2
    SSH_CLIENT=10.112.9.87 58090 22
SSH_CLIENT=10.112.9.87 58695 22
    SSH_CONNECTION=10.112.9.87 58090 10.80.0.68 22
SSH_CONNECTION=10.112.9.87 58695 10.80.0.68 22
SSH_TTY=/dev/pts/13
    SSH_TTY=/dev/pts/14
    XDG_RUNTIME_DIR=/run/user/1000
XDG_RUNTIME_DIR=/run/user/10006
    XDG_SESSION_ID=6
XDG_SESSION_ID=7

Mise à jour

Ajout du script complet exécuté par pam_exec (informations sensibles remplacées par des espaces réservés):

#!/bin/bash
USERN=$PAM_USER
if grep -q @S /home/${USERN}/.pam_mount.conf.xml || grep -q @P /home/${USERN}/.pam_mount.conf.xml; then
    BASEDIR=`ldapsearch -LLL -H ldaps://dc.example.org:3269 -D "[email protected]" -b "DC=c,DC=sdu,DC=dk" -w [secretpw] "sAMAccountName=${USERN}" dn`;
    PREFIX="dn:: "
    BASEDIR=${BASEDIR#$PREFIX}
    PREFIX="dn: "
    BASEDIR=${BASEDIR#$PREFIX}
    BASEDIR=`echo $BASEDIR | tr -d ' '`
    if [[ $BASEDIR != *","* ]]
        then
               BASEDIR=`echo $BASEDIR | base64 --decode`
        fi
    BASEDIR=`echo $BASEDIR | tr -d ' \n' | awk -F "DC=" '{ st = index($0,"DC=");print substr($0,st+0)}'`;
    DOMAIN=`echo $BASEDIR | sed 's/,DC=/./g' | sed 's/DC=//'`;
    OUTPUT=`ping -c 1 -t 10 $DOMAIN | grep icmp`
    HOMEDIR='\\fallbackserver\share'
    if [[ -n "$OUTPUT" ]]
        then
            DC=`echo $OUTPUT| cut -d' ' -f 4`
            HOMEDIR=`ldapsearch -LLL -H ldaps://$DC:636 -D "[email protected]" -b "${BASEDIR}" -w [secretpw] "sAMAccountName=${USERN}" homeDirectory | grep homeDirectory | awk '{print $2}'`;
        fi
    CHOMEDIR=$(echo ${HOMEDIR} | sed 's/\\/\//g')

    XSERVER=`echo $CHOMEDIR | cut -f3 -d/`
    XPATH=`echo $CHOMEDIR | cut -f4- -d/`



    /bin/sed -i "s|\@S|${XSERVER}|g" /home/${USERN}/.pam_mount.conf.xml
    /bin/sed -i "s|\@P|${XPATH}|g" /home/${USERN}/.pam_mount.conf.xml
fi

pdate4

Placer un whoami dans le script indique que lors de l'utilisation de su de accounta à accountb, le script est exécuté par accounta.

Mise à jour 5

L'utilisation de l'option 'seteuid' avec pam_exec a résolu le problème. session optional pam_exec.so seteuid log=/var/log/pamexec /usr/local/bin/mdrive_add

whoami affiche maintenant 'root' lors du basculement de A à B et il n'y a pas de problème d'autorisation.

Je ne comprends pas les termes "ID utilisateur réel" et "ID utilisateur effectif" dans le manuel pour pam_exec, mais c'est une question pour un autre jour.

Par défaut, pam_exec.so exécutera la commande externe avec l'ID utilisateur réel du processus appelant. Spécifier cette option signifie que la commande est exécutée avec l'ID utilisateur effectif.

2
Tobias

Le problème était que la connexion via supam_exec exécutait le script en tant qu '"ancien" utilisateur, qui n'était pas autorisé à écrire dans le répertoire de base du "nouvel" utilisateur.

La définition de l'option seteuid dans session optional pam_exec.so log=/var/log/pamexec /usr/local/bin/mdrive_add a pour effet que pam_exec exécute le script en tant que root, ce qui a résolu le problème:

session optional pam_exec.so seteuid log=/var/log/pamexec /usr/local/bin/mdrive_add

Cependant, la "vraie" solution consiste probablement à configurer /etc/pam.d/su correctement, ce qui me préoccupe encore; Je mettrai à jour cette réponse dès que je comprendrai la bonne façon de configurer /etc/pam.d/su.

0
kos