Maneira correta de permitir que o usuário insira a senha para um script bash usando apenas a GUI (com o terminal oculto)


8

Eu criei um script bash que usa o kdialog exclusivamente para interagir com o usuário. É iniciado a partir de um arquivo ".desktop" para que o usuário nunca veja o terminal. Parece 100% como um aplicativo GUI (mesmo que seja apenas um script bash). É executado apenas no KDE (Kubuntu 12.04).

Meu único problema é lidar com a entrada de senha de forma segura e conveniente. Não consigo encontrar uma solução satisfatória.

O script foi projetado para ser executado como um usuário normal e solicitar a senha quando um comando sudo for necessário pela primeira vez. Dessa maneira, a maioria dos comandos, aqueles que não exigem direitos sudo, são executados como o usuário normal. O que acontece (quando o script é executado no terminal) é que o usuário solicita sua senha uma vez e o tempo limite padrão do sudo permite que o script termine, incluindo quaisquer comandos adicionais do sudo, sem avisar o usuário novamente. É assim que eu quero que funcione quando executado atrás da GUI também.

O principal problema é que usar kdesudopara iniciar meu script, que é a maneira GUI padrão, significa que o script inteiro é executado pelo usuário root. Portanto, as propriedades dos arquivos são atribuídas ao usuário raiz, não posso confiar ~/em caminhos e muitas outras coisas são menos que ideais. A execução de todo o script como usuário root é apenas uma solução muito insatisfatória e acho que é uma prática ruim.

Aprecio todas as idéias para permitir que um usuário digite a senha do sudo apenas uma vez via GUI, enquanto não executa o script inteiro como root. Obrigado.

Respostas:


14

A -Aopção sudo permite especificar um programa auxiliar (na variável SUDO_ASKPASS) que solicitará a senha.

Crie um script para solicitar a senha (myaskpass.sh):

#!/bin/bash
zenity --password --title=Authentication

Em seguida, insira esta linha no início do seu script:

export SUDO_ASKPASS="/path/to/myaskpass.sh"

e substitua todas as ocorrências de sudo <command>por:

sudo -A <command>

Você pode usar qualquer programa de solicitação de senha que desejar, em vez de zenity. Eu tive que encapsulá-lo em um script porque SUDO_ASKPASS deve apontar para um arquivo, para que não funcione com a --passwordopção exigida por zenity.

O exemplo acima funciona como um encanto se for executado na linha de comando ou se você escolher Executar no terminal após clicar duas vezes no arquivo de script no gerenciador de arquivos, mas se você escolher Executar ou tentar iniciá-lo a partir de um arquivo .desktop, todos sudoos pedidos para senha novamente.


Se você não deseja uma janela de terminal, pode armazenar a senha em uma variável e canalizá-la sudo -S. Talvez haja algumas preocupações de segurança, mas acho que é bastante seguro (leia os comentários nesta resposta ).

Insira esta linha no início do seu script:

PASSWD="$(zenity --password --title=Authentication)\n"

e substitua todas as ocorrências de sudo <command>por:

echo -e $PASSWD | sudo -S <command>

Obrigado. Isso é muito interessante. No entanto, ao usar isso, o tempo limite usual do sudo (por exemplo, 15 minutos) é perdido. Meu script, que possui mais de 50 comandos sudo, solicita a senha do usuário mais de 50 vezes! Pesquisei um pouco e não encontrei uma solução. Você conhece um?
MountainX

Obrigado pela atualização. A alternativa que você sugere é algo que eu descartei devido a preocupações de segurança, mas ao ler os comentários no link que você forneceu, acho que provavelmente é seguro o suficiente. E é uma maneira fácil de resolver o problema. Obrigado.
MountainX

Os testes no meu sistema devem ser sudo -s(minúsculas s) e não sudo -S(maiúsculas s).
WinEunuuchs2Unix 5/17/17

0

Isso se baseia na excelente resposta de Eric Carvalho. Estou postando para elaborar o problema que encontrei. Especificamente, ao usar isso, o tempo limite usual do sudo (por exemplo, 15 minutos) é perdido. Meu script, que possui mais de 50 comandos sudo, solicita a senha do usuário mais de 50 vezes!

Aqui está um exemplo completo de todas as partes da solução. Ele consiste em um script bash, um script "myaskpass", como Eric sugeriu, e um arquivo ".desktop". O conjunto deve ser 100% GUI (sem nenhuma interação terminal); portanto, o arquivo .desktop é essencial (disponível).

$ cat myaskpass.sh 
#!/bin/bash
kdialog --password "Please enter your password: "
exit 0


$ cat askpasstest1.desktop 
#!/usr/bin/env xdg-open
[Desktop Entry]
Comment=SUDO_ASKPASS tester1
Exec=bash /home/user/test/askpasstest1.sh
GenericName=SUDO_ASKPASS tester1
Name=SUDO_ASKPASS tester1
NoDisplay=false
Path[$e]=
StartupNotify=true
Terminal=false
TerminalOptions=
Type=Application
Categories=Application;Utility;
X-KDE-SubstituteUID=false
X-KDE-Username=

E um script de teste em si. Este solicitará sua senha duas vezes ao usar esta solução. (Normalmente, ele solicita apenas uma vez devido ao tempo limite padrão do sudo.)

#!/bin/bash

sudo -k
SUDO_ASKPASS="/home/user/test/myaskpass.sh" sudo -A touch filemadeas_askpass1
touch filemadeas_regularuser1
SUDO_ASKPASS="/home/user/test/myaskpass.sh" sudo -A touch filemadeas_askpass2
touch filemadeas_regularuser2
ls -la filemadeas* > /home/user/test/fma.log
kdialog --title "Files Created" --textbox /home/user/test/fma.log 640 480
sudo rm filemadeas_*
rm fma.log

exit 0

Executando esse script na linha de comando, a senha é solicitada apenas uma vez. Executando a partir da GUI (clicando em .desktop ou .sh no gerenciador de arquivos), todos sudo -Aobtêm a senha. Vou tentar descobrir isso.
Eric Carvalho

Acabei de atualizar minha resposta.
Eric Carvalho

Eric ... você descobriu uma solução para o problema?
Anthony

0

O script a seguir funciona via linha de comando, arquivo da área de trabalho ou clique duas vezes, solicita a senha apenas uma vez e o padrão de comando sudo -Sp '' <your command here> <<<${sudo_password}pode ser usado várias vezes em qualquer lugar do arquivo:

    # get sudo password
    sudo_password=$( gksudo --print-pass --message="Provide permission to make system changes: Type your password or press Cancel." -- : 2>/dev/null )
    # check for null entry or cancellation
    if [[ ${?} != 0 || -z ${sudo_password} ]]
    then
        exit 4
    fi
    if ! sudo -kSp '' [ 1 ] <<<${sudo_password} 2>/dev/null
    then
        exit 4
    fi
    # command
    sudo -Sp '' gedit "/etc/hosts" <<<${sudo_password}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.