- I want operator users on this machine to mount their own cifs shares
sudoersfile already contains the
/bin/mount -t cifs //*/* /media/* -o username=*command for all operators
- I want the users to mount a
cifsshare through a script typing the password only once, not twice.
- The sudo password and the cifs password are identical.
What I already have
This script works:
#!/bin/bash sudo 'mount -t cifs //192.168.1.1/home /media/$USER/home -o username=$USER'
…but it requires the users to type the same password twice!
- Once for
- Once for the mount itself
This would also work:
#!/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'
…but this would require me to allow all operator users to be able to
sudo sh (major security problem)
How to mount a cifs share in bash¹ without putting
sh in the
sudoers file nor creating a permanent/temporary file???
Note 1: no python, perl, C, Go, … please?
Note 2: I know I can just remove the password through the
sudoers file, but I’m trying to tighten security, not loosen it, without giving up convenience…
Here is Solutions:
You should instead make the user do the call of using sudo as
sudo script. just check if the script is being run as root, if not ask for it
if [[ $EUID -ne 0 ]]; then echo "This script must be run as root, use sudo "$0" instead" 1>&2 exit 1 fi
Don’t try to capture the password of your users.
The following script:
#!/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"
just works and:
- Doesn’t create any files containing passwords
- Allows the user to type only one password for multiple shares (including Windows ones)
- Has no need for extra privileges to be granted. 🙂
sudo password for executing this command; the password prompt for
sudoers, include something like
ALL ALL = NOPASSWD: /bin/mount -t cifs //*/* /media/* -o username=*
After including this,
sudo will no longer ask for a password for this specific command; the user still needs to provide a password to the
Note: I took the command verbatim from what you included in the question; I didn’t check whether its wildcards would allow for users to do something nasty. Read the
sudoers manpage for examples of nastiness. In particular, note that this line in
sudoers allows the user to add any number of
-o switches or other arguments to
mount. You may want to rethink your approach, e.g. by adding a script such as @Braiam proposes and allow running that through
sudo without extra authentication. The script then ensures that users can only run the specific form of
mount that you want them to run.
Also, instead of allowing this for all users, you could also limit this to members of a certain group, e.g. you could create a group
cifsmount and then have
%cifsmount ALL = NOPASSWD: /bin/mount -t cifs //*/* /media/* -o username=*
A general solution to these issues is to put the following preamble at the top of your sudo requiring 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 "[email protected]" ;; 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 ...
Obviously, this has a downside in that if some commands in the script don’t require
sudo to run, there’s an unnecessary elevation of privileges here.
Anyway, thought I would share this little tip. The nicest thing about it, is that if you’re already effective-uid root (e.g. if you already called it under sudo) it gracefully does the right thing. Also giving an error and forcing you to retype/rerun (with sudo) is less friendly.
You may also want to check out the
timestamp_timeout variable in
man 5 sudoers which tells
sudo to remember user credentials for a limited number of minutes (and can be fractional).
Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂