
Estou usando pam_mount.so para montar automaticamente um compartilhamento CIFS para usuários em um cliente Ubuntu 14.04.
pam_mount usa uma configuração local no diretório inicial de cada usuário. Estou executando um script bash com pam_exec que atualiza o arquivo de configuração com o caminho para o compartilhamento CIFS.
O final do meu arquivo /etc/pam.d/common-session é assim:
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
Ao fazer login com SSH ou através da GUI, isso funciona, o script é executado antes da montagem, para que o compartilhamento fique acessível.
No entanto, ao usar su, o script falha e o conf do usuário local não é atualizado, portanto a montagem também falha.
O erro que recebo ao usar su de [accountA] para [accountB] é:
/bin/sed: couldn't open temporary file /home/[accountB]/sednpoogQ: Permission denied
A linha no script que falha é esta:
/bin/sed -i "s|\@S|${XSERVER}|g" /home/${PAM_USER}/.pam_mount.conf.xml
Tentei executar o script em ~/.profile e em outros lugares, funciona perfeitamente, mas não é executado antes do pam_mount.
Então, minha pergunta é: como posso fazer com que pam_exec substitua uma string em um arquivo de texto que reside no diretório inicial de um usuário ao usar su?
Atualizar
Pelos comentários, tentei 'sudo -u [accountb] -i' (depois de incluir @common-session em /etc/pam.d/sudo) e isso não retorna o mesmo erro, funciona. No entanto, não é uma solução aceitável, pois preciso que o su funcione (e isso causa uma solicitação de senha do pam_mount).
Atualização2
Efetuei login com ssh, despejei env em um arquivo e, em seguida, efetuei login com ssh de outra conta, usei su e despejei env em um arquivo.
Comparando os dois (nomes de contas substituídos por accounta e accountb como na pergunta:
$ 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
Atualização3
Adicionado o script completo executado por pam_exec (informações confidenciais substituídas por espaços reservados):
#!/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
Atualização4
Colocar um whoami no script mostra que ao usar su de accounta para accountb, o script é executado por accounta.
Atualização5
Usar a opção 'seteuid' com pam_exec resolveu o problema.
session optional pam_exec.so seteuid log=/var/log/pamexec /usr/local/bin/mdrive_add
whoami agora mostra 'root' ao mudar de A para B e não há problemas de permissão.
Não entendo os termos 'ID de usuário real' e 'ID de usuário efetivo' no manual do pam_exec, mas isso é uma questão para outro dia.
Por padrão, pam_exec.so executará o comando externo com o ID de usuário real do processo de chamada. Especificar esta opção significa que o comando será executado com o ID do usuário efetivo.
Responder1
O problema era que o login su
pam_exec
executava o script como o usuário "antigo", que não tinha permissão para gravar no diretório inicial do "novo" usuário.
Definir a seteuid
opção session optional pam_exec.so log=/var/log/pamexec /usr/local/bin/mdrive_add
fez pam_exec
executar o script como root, o que resolveu o problema:
session optional pam_exec.so seteuid log=/var/log/pamexec /usr/local/bin/mdrive_add
No entanto, a solução "real" provavelmente está sendo configurada /etc/pam.d/su
adequadamente, algo que ainda estou mexendo; Atualizarei esta resposta assim que entender a maneira correta de configurar o /etc/pam.d/su
.