Comment entrer le mot de passe une seule fois dans un script bash nécessitant sudo

21

Les données

  • Je souhaite que les utilisateurs opérateurs sur cette machine montent leurs propres partages cifs
  • Le sudoersfichier contient déjà la /bin/mount -t cifs //*/* /media/* -o username=*commande pour tous les opérateurs
  • Je veux que les utilisateurs montent un cifspartage via un script en tapant le mot de passe une seule fois, pas deux.
  • Le mot de passe sudo et le mot de passe cifs sont identiques.

Ce que j'ai déjà

Ce script fonctionne:

#!/bin/bash
sudo 'mount -t cifs //192.168.1.1/home /media/$USER/home -o username=$USER'

... mais cela oblige les utilisateurs à taper deux fois le même mot de passe!

  • Une fois pour sudo
  • Une fois pour la monture elle-même

Cela fonctionnerait également:

#!/bin/bash
echo -n Password: 
read -s szPassword
echo $szPassword | sudo -S sh -c 'echo $szPassword | mount -t cifs //192.168.1.1/home /media/$USER/home -o username=$USER'

... mais cela m'obligerait à permettre à tous les utilisateurs opérateurs de pouvoirsudo sh (problème de sécurité majeur)

Question

Comment monter un partage cifs dans bash ¹ sans mettre shle sudoersfichier ni créer un fichier permanent / temporaire ???

Note 1: pas de python, perl, C, Go, ... s'il vous plait?
Remarque 2: je sais que je peux simplement supprimer le mot de passe dans le sudoersfichier, mais j'essaie de renforcer la sécurité, pas de la desserrer, sans renoncer à la commodité ...

Fabby
la source
2
Et alors printf "%s\n" "$szPassword" "$szPassword" | sudo -S mount -t cifs / ...?
muru
Essayer ça maintenant! @Muru
Fabby

Réponses:

24

Vous devriez plutôt faire appel à l'utilisateur en utilisant sudo as sudo script. vérifiez simplement si le script est exécuté en tant que root, sinon demandez-le

if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root, use sudo "$0" instead" 1>&2
   exit 1
fi

N'essayez pas de capturer le mot de passe de vos utilisateurs.

Braiam
la source
1
Peut-être que je manque quelque chose, mais pouvez-vous expliquer comment cela réduit le nombre d'invites de mot de passe de deux à un? Sinon, je ne vois pas comment cela répond à la question.
Oliphaunt - réintègre Monica
@Oliphaunt Je ne vois pas deux invites de mot de passe, pouvez-vous expliquer cela? De plus, cette réponse n'est pas ce que OP veut, mais ce dont il a besoin. Est une solution propre et appropriée lorsque vous devez exécuter des commandes en tant que root et comment les autres utilitaires font (vérifiez si root, sinon renflouez)
Braiam
1
Le problème de l'OP (si je comprends bien) est que l'utilisateur est invité à saisir son mot de passe par sudopuis (après s'être authentifié avec succès) à nouveau par mount. Dans leur cas d'utilisation, ces mots de passe sont identiques, je peux donc comprendre pourquoi l'OP souhaite que l'utilisateur n'ait à saisir ce mot de passe qu'une seule fois. Je ne pense pas que votre solution y contribue. Je suis d'accord qu'il ne faut pas capturer les mots de passe.
Oliphaunt - réintègre Monica
Merci, mais j'aurais peut-être un peu simplifié la question un peu: c'est déjà un script, contient déjà ce test (sauf le 1>&2), est dans le démarrage automatique et il n'était qu'un partage cifs, mais maintenant c'est trois, donc vraiment un mot de passe est nécessaire. (Il contient déjà ce test au cas où quelqu'un d'autre, non membre du groupe des opérateurs,
tenterait
@Fabby, je pense toujours que vous abordez le problème de manière incorrecte. Pour ces cas, il est possible de "mémoriser" le mot de passe d'un partage CIFS / SMB en toute sécurité (modification ~/.smbcredentialspar exemple), et même sans avoir besoin de sudo (si vous utilisez gvfs, umount ou polkit).
Braiam
7

Je suis stupide!

Le script suivant:

#!/bin/bash
read -p "Password: " -s szPassword
printf "%s\n" "$szPassword" | sudo --stdin mount -t cifs //192.168.1.1/home /media/$USER/home -o username=$USER,password="$szPassword"

fonctionne et:

  1. Ne crée aucun fichier contenant des mots de passe
  2. Permet à l'utilisateur de taper un seul mot de passe pour plusieurs partages (y compris ceux de Windows)
  3. N'a pas besoin d'accorder des privilèges supplémentaires. :-)
Fabby
la source
1
1 question: cela fait-il écho à la commande dans la liste des processus?
Rinzwind
3
@Rinzwind en tant que intégré, il ne devrait pas être en bash ou zsh. La commande mount pourrait cependant.
muru
<<<pourrait également être utilisé à la place de printf , mais la meilleure approche serait de supprimer readcomplètement et de l'utiliser sudo --stdintout seul. Quelque chose comme l' $ printf "Type out your password\n" && sudo --stdin apt-get update utilisateur peut toujours taper le mot de passe sudo. et cela ne le mettra pas dans la liste des processus. Mais bien sûr, il existe une quantité infinie d'autres problèmes de sécurité possibles, comme les enregistreurs de frappe, les vulnérabilités potentielles dans sudo, et bla, et bla, et bla dans l'infini
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy: N'hésitez pas à éditer , mec!
Fabby
3

Ne nécessite aucun sudomot de passe pour exécuter cette commande; l'invite de mot de passe mountreste.

Dans sudoers, incluez quelque chose comme

ALL        ALL = NOPASSWD: /bin/mount -t cifs //*/* /media/* -o username=*

Après avoir inclus cela, sudone demandera plus de mot de passe pour cette commande spécifique; l'utilisateur doit toujours fournir un mot de passe à la mountcommande.

Remarque : J'ai pris la commande mot pour mot de ce que vous avez inclus dans la question; Je n'ai pas vérifié si ses caractères génériques permettraient aux utilisateurs de faire quelque chose de méchant. Lisez la sudoerspage de manuel pour des exemples de méchanceté. En particulier, notez que cette ligne sudoerspermet à l'utilisateur d'ajouter un nombre quelconque de -ocommutateurs ou d'autres arguments à mount. Vous voudrez peut-être repenser votre approche, par exemple en ajoutant un script tel que @Braiam le propose et en autorisant son exécution sudosans authentification supplémentaire. Le script garantit ensuite que les utilisateurs ne peuvent exécuter que la forme spécifique mountque vous souhaitez qu'ils exécutent.

De plus, au lieu de permettre cela à tous les utilisateurs, vous pouvez également limiter cela aux membres d'un certain groupe, par exemple, vous pouvez créer un groupe cifsmountet ensuite avoir

%cifsmount ALL = NOPASSWD: /bin/mount -t cifs //*/* /media/* -o username=*
Oliphaunt - réintègre Monica
la source
@Fabby Désolé, mais qu'est-ce qui est si dangereux à ce sujet? Je détecte peut-être aussi un soupçon de sarcasme, pas sûr.
Oliphaunt - réintègre Monica
eh bien, même si sudo ne nécessite pas de mot de passe, mount peut tout de même exiger un mot de passe. Le fichier / etc / sudoers peut être utilisé pour que sudo ne nécessite pas de mot de passe. Cela n'affecterait pas le fait que mount demande un mot de passe. Si une personne n'a pas réussi à monter, sudo finirait par exécuter une commande qui échoue, ce qui n'est probablement pas un problème.
TOOGAM
@TOOGAM C'était mon intention. Un mot de passe au lieu de deux.
Oliphaunt - réintègre Monica
Mon intention est de garder un groupe "d'opérateurs" dans le fichier sudoers donc si un opérateur essaie de monter ses propres trucs, ils doivent toujours taper un mot de passe, mais pour monter les montages d'opérateurs "standard", ils n'ont qu'à taper le mot de passe une fois au lieu de 5 fois ... Mais votre solution pourrait fonctionner pour d'autres, donc voté positivement ... (et les commentaires originaux supprimés)
Fabby
1

Une solution générale à ces problèmes consiste à placer le préambule suivant en haut de votre sudo nécessitant des scripts:

#!/bin/bash
case $EUID in
   0) : cool we are already root - fall through ;;
   *) # not root, become root for the rest of this session
      # (and ask for the sudo password only once)
      sudo $0 "$@" ;;
esac
# now the present process is effective-UID  (root)
# so there's no need to put sudo in front of commands

any more commands here will run as superuser ...

Évidemment, cela a un inconvénient en ce sens que si certaines commandes du script ne nécessitent pas d' sudoêtre exécutées, il y a une élévation inutile des privilèges ici.

Quoi qu'il en soit, j'ai pensé partager cette petite astuce. La meilleure chose à ce sujet, c'est que si vous êtes déjà root efficace-uid (par exemple si vous l'avez déjà appelé sous sudo), il fait gracieusement la bonne chose. Donner également une erreur et vous forcer à retaper / réexécuter (avec sudo) est moins convivial.

Vous pouvez également vouloir vérifier la timestamp_timeoutvariable dans man 5 sudoerslaquelle indique sudode se souvenir des informations d'identification de l'utilisateur pour un nombre limité de minutes (et peut être fractionnaire).

arielf
la source
J'ai simplifié le script pour obtenir une réponse simple: le script contient déjà: #test if root: if not: bail out if [[ $EUID -ne 0 ]]; then echo "This script must be run as root, use sudo "$0" instead" 1>&2 exit 1 fi Le fait est qu'il contient également plusieurs montures avec le même mot de passe (encore une fois: supprimé), mais merci quand même ...
Fabby
1
Le fait est que la solution ci-dessus ne nécessiterait qu'une seule saisie du mot de passe (pour sudo). Cela ne devrait pas nécessiter d'autre. De plus, c'est un problème général (et plus élégant que de donner une erreur et d'avoir à retaper la commande avec sudo) pour tous les problèmes similaires, même lorsqu'ils nécessitent plusieurs (plus de deux) commandes privilégiées.
arielf
Cela devrait, mais ce n'est pas le cas ! ;-) C'est parce que chaque montage de partage cifs nécessite également un mot de passe. (car il peut être différent du mot de passe Ubuntu, mais dans ce cas, ce n'est pas le cas car les opérateurs gardent leurs mots de passe Windows et Ubuntu synchronisés)
Fabby