Introdução
Quem nunca precisou usar o sudo dentro de um shell script e percebeu que não é possível passar a senha pela entrada padrão? Se você alguma vez já fez:
$ echo 'minhasenha' | sudo su
percebeu que o sudo se recusa a ler a senha enviada pelo echo e continua a mostrar o prompt de leitura da senha.
Nesse post iremos aprender como passar a senha de um usuário para o sudo usando a entrada padrão.
A Manpage
Lendo a manpage do sudo vemos a seguinte opção:
-S The -S (stdin) option causes sudo to read the password from the standard input instead of the terminal device. The password must be followed by a newline character.
Essa opção permite a passagem da senha pela entrada padrão e a única exigência é que deve haver um ‘\n’ no fim da senha.
Usando a opção -S do sudo
Para testar essa opção, suponha que o usuário atual tem senha “minhasenha” e que ele deseja executar um comando qualquer como root. Assim, o seguinte comando deve ser digitado:
$ echo 'minhasenha' | sudo -S id uid=0(root) gid=0(root) groups=0(root),3(sys),7(lp)
Veja que o comando id foi executado como root (uid=0).
Nota sobre segurança
Usar a dupla de comandos echo + sudo -S não é muito seguro, pois a senha fica disponível em clean text para qualquer usuário com permissão de leitura em seu script. Por causa disso, aconselho a não usar esse tipo de sintaxe para não expor sua senha para pessoas indesejáveis, mesmo que só você use o seu sistema.
Qual o objetivo da opção -S ?
Se usar a sintaxe echo+sudo pode expor a senha para outros usuários então por que criaram essa opção? O objetivo dessa opção é para que um programa gráfico de autenticação passe a senha para o sudo sem que a senha em si seja mostrada. Usando um programa gráfico ao invés de um simples echo faz com que a senha seja lida dinamicamente não precisando armazená-la no código fonte do script.
zenity + sudo
Para exemplificar um uso ideal da opção -S, vou montar um simples programinha gráfico de autenticação em shell script:
#!/bin/bash # Autor: Marcos Paulo Ferreira (daemonio) # undefinido gmail com # daemoniolabs.wordpress.com # # [zensudo.sh] # Script que simula uma autenticação usando # o zenity e o sudo. # # OBS: Executar o sudo em seu próprio usuário, a senha # não é verificada. Executar o script mais de uma # vez em um curto intervalo de tempo, implica no sudo nem # considerar a senha de entrada. # Isso porque o sudo tem um tempo que ele fica sem pedir a senha. # # Qui Out 20 18:36:37 BRST 2011 # while true do resp=$(zenity --password) # Pega a senha do login gráfico senha=$(echo "$resp" | cut -f1 -d'|') # Passa a senha echo $senha | sudo -S -u root zenity --info --text "Bem vindo: r00t" 1 2>/dev/null && exit # Perguntar se quer tentar novamente. zenity --question --text 'Erro. Tentar novamente?' # Sair se pressionou cancelar. (( $? )) && exit done #EOF
Para usar:
$ ./zensudo.sh
Digite sua senha e se tudo ocorrer corretamente, a mensagem “Bem vindo: r00t” aparecerá na sua tela.
Opção -A do sudo
O sudo pode invocar um login gráfico através da opção -A e desse modo, dispensando o uso da opção -S:
Primeiro, deve-se criar o script gráfico que passará a senha para o sudo:
$ chmod +x /tmp/logingrafico $ cat /tmp/logingrafico #!/bin/bash zenity --password
Depois devemos setar a variável SUDO_ASKPASS com o nome do script:
$ export SUDO_ASKPASS='/tmp/logingrafico'
Em seguida, basta chamar o sudo com a opção -A e também passar o comando que se deseja executar como root:
$ sudo -A id # digite a senha no login gráfico uid=0(root) gid=0(root) groups=0(root),3(sys),7(lp)
Conclusão
O utilitário sudo é indispensável na utilização de sistemas *nix, pois facilita bastante a troca de usuários para a execução de comandos. Uma de suas opções permite que o usuário passe a sua própria senha pela entrada padrão. Porém, não é aconselhável passar a senha em texto limpo, via echo por exemplo, e sempre que possível, utilizar-se de uma aplicação gráfica para isso.
Referências
[1] sudo: lendo a senha automaticamente através de shell script by Valter Ferraz Sanches (Acessado em: Outubro/2011)
http://www.vivaolinux.com.br/dica/sudo-lendo-a-senha-automaticamente-atraves-de-shell-script
O uso do export é opcional e a linha:
$ SUDO_ASKPASS=’/tmp/logingrafico’ sudo -A
também “passa” a variável de ambiente SUDO_ASKPASS para o sudo.
Daemonio,
t+
Olá amigo! Não estou conseguindo obter exito com este script:
sudo -k | \
zenity –entry \
–width=200 \
–height=80 \
–title=”SENHA DE USUÁRIO” \
–text=”Entre com a senha aqui abaixo:” \
–entry-text “” \
–hide-text | sudo -S aptitude purge linux-image-$ESC | zenity –list –title “KernelClean” –text ” Iniciando processo de remoção…\n” –column “Status” –width=700 –height=400
fi
Recebe a senha do zenity ( entrada padrão ) inicia o processo e de repente dá a informação:
Gostaria de remover? [Y/N].Abortar
E não consigo resolver isto. Ja tentei de várias formas, li o man do sudo e coisa e tal, mas nada. Pode me ajudar se puder? Agradeço a atenção!
Wilson
Olá Wilson,
Acredito que o único problema esteja no segundo zenity. Ele só vai ser executado se o sudo retornar sucesso, ou seja,
se a senha foi verificada. Para isso, troque o | por && (AND). Fica assim:
#!/bin/bash
zenity –entry \
–width=200 \
–height=80 \
–title=”SENHA DE USUÁRIO” \
–text=”Entre com a senha aqui abaixo:” \
–entry-text “” \
–hide-text | sudo -S aptitude purge linux-image-$ESC && zenity –list –title “KernelClean” –text ” Iniciando processo de remoção…\n” –column “Status” –width=700 –height=400
Quando digito a senha correta, o aptitude é executado como root e no mesmo instante a tela do zenity aparece.
Penso que seja isso.
Abraços.
Tudo bem, Daemonio ?
Obrigado pela prontidão do seu tempo! O problema está na realidade com o aptitude em relação a senha vinda do zenity. Mesmo trocando o pipe por && (AND), nada se alterou. Consultei hoje o livro (Linux, Prática e Certificação LPI) do Bonan e encontrei a solução, ao menos eficiente para esta situação e que resolveu o impasse. Ao invés de utilizar o aptitude eu utilizo o “dpkg –purge” que além de remover o kernel, também remove arquivos de configuração por completo, tendo praticamente o mesmo efeito. O mais curioso é que o comando (sudo aptitude purge linux-image…) executado diretamente no terminal funciona perfeitamente, mas vindo do zenity esbarra na questão que você me alertou apropriadamente a despeito do retorno da verificação da senha, que não sei por que cargas d’agua não funciona nem com reza brava. Mas o mais importante é que houve como resolver! Deixo aqui no teu site a “Dica/solução” caso alguém mais passe pelo mesmo problema. E mais uma vez obrigado pela ajuda e um grande abraço amigo.
sudo -k | \
zenity –entry \
–width=200 \
–height=80 \
–title=”SENHA DE USUÁRIO” \
–text=”Entre com a senha aqui abaixo:” \
–entry-text “” \
–hide-text | sudo -S dpkg –purge linux-image-$ESC | zenity –list \
–title “KernelClean” \
–text “Iniciando processo de remoção…\n” \
–column “Status” –width=700 –height=400
Olá Wilson,
Pela resposta que te dei, nem pensei que a saída do aptitude era para ser a entrada do zenity. Aí nesse caso nem faria sentido usar o ‘&&’, tinha que ser o pipe mesmo. ;)
Como estou usando Fedora, aí não tem como eu executar os comandos que você me passou (aptitude, dpkg, etc). Mas o mais importante é que você já resolveu o problema. Fica aqui a solução para que está passando por isso.
Abraços.