You can do that with su
or sudo
, no need for both.
sudo -H -u otheruser bash -c 'echo "I am $USER, with uid $UID"'
The relevant parts of man sudo
:
-H The -H (HOME) option requests that the security policy set
the HOME environment variable to the home directory of the
target user (root by default) as specified by the password
database. Depending on the policy, this may be the default
behavior.
-u user The -u (user) option causes sudo to run the specified
command as a user other than root. To specify a uid
instead of a user name, use #uid. When running commands as
a uid, many shells require that the '#' be escaped with a
backslash ('\'). Security policies may restrict uids to
those listed in the password database. The sudoers policy
allows uids that are not in the password database as long
as the targetpw option is not set. Other security policies
may not support this.
su
can only switch user without providing a password if you are root. See Caleb's answer
You can modify the /etc/pam.d/su
file to allow su
without password. See this answer.
If you modified your auth file to the following, any user that was part of group somegroup
could su
to otheruser
without a password.
auth sufficient pam_rootok.so
auth [success=ignore default=1] pam_succeed_if.so user = otheruser
auth sufficient pam_succeed_if.so use_uid user ingroup somegroup
Then test from terminal
rubo77@local$ su otheruser -c 'echo "hello from $USER"'
hello from otheruser
The -A
sudo option allows you to specify a helper program (in the SUDO_ASKPASS variable) that will ask for the password.
Create a script to ask the password (myaskpass.sh):
#!/bin/bash
zenity --password --title=Authentication
Then insert this line at the beginning of your script:
export SUDO_ASKPASS="/path/to/myaskpass.sh"
and replace all occurences of sudo <command>
with:
sudo -A <command>
You can use whatever password asking program you want instead of zenity
. I had to encapsulate it within a script because SUDO_ASKPASS must point to a file, so it won't work with the --password
option required by zenity
.
The above works like a charm if it runs from command line or if you choose Run in terminal after double click the script file in the file manager, but if you choose Run or try to launch it from a .desktop file every sudo
will ask for the for password again.
If you don't want a terminal window at all, you can store the password in a variable and pipe it to sudo -S
. Maybe there's some security concerns, but I think it's pretty safe (read the comments on this answer).
Insert this line at the beginning of your script:
PASSWD="$(zenity --password --title=Authentication)\n"
and replace all occurences of sudo <command>
with:
echo -e $PASSWD | sudo -S <command>
Best Answer
Since you want to do this in a shell script, a couple of contributions in How to check password with Linux? (on Unix.SE, suggested by A.B.) are especially relevant:
/etc/shadow
gives part of the solution.mkpasswd
command present in Debian (and Ubuntu).To manually check if a string is really some user's password, you must hash it with the same hash algorithm as in the user's shadow entry, with the same salt as in the user's shadow entry. Then it can be compared with the password hash stored there.
I've written a complete, working script demonstrating how to do this.
chkpass
, you can runchkpass user
and it will read a line from standard input and check if it'suser
's password.mkpasswd
utility on which this script depends.Security Notes
It might not be the right approach.
Whether or not an approach like this should be considered secure and otherwise appropriate depends on details about your use case that you haven't provided (as of this writing).
It has not been audited.
Although I've tried to exercise care while writing this script, it has not been properly audited for security vulnerabilities. It is intended as a demonstration, and would be "alpha" software if released as part of a project. Furthermore...
Another user who's "watching" may be able to discover the user's salt.
Due to limitations in how
mkpasswd
accepts salt data, this script contains a known security flaw, which you may or may not consider acceptable depending on use case. By default, users on Ubuntu and most other GNU/Linux systems can view information about processes run by other users (including root), including their command-line arguments. Neither the user's input nor the stored password hash is passed as a command-line argument to any external utility. But the salt, extracted from theshadow
database, is given as a command-line argument tomkpasswd
, since this is the only way that utility accepts a salt as input.If
www-data
) run their code, or/proc
)is able to check the command-line arguments to
mkpasswd
as it is run by this script, then they can obtain a copy of the the user's salt from theshadow
database. They might have to be able to guess when that command is run, but that is sometimes achievable.An attacker with your salt is not as bad as an attacker with your salt and hash, but it's not ideal. The salt doesn't provide enough information for someone to discover your password. But it does allow someone to generate rainbow tables or pre-computed dictionary hashes specific to that user on that system. This is initially worthless, but if your security is compromised at a later date and the full hash is obtained, it could then be cracked more quickly to obtain the user's password before they get a chance to change it.
Thus this security flaw is an exacerbating factor in a more complex attack scenario rather than a fully exploitable vulnerability. And you might consider the above situation far-fetched. But I am reluctant to recommend any method for general, real-world use that leaks any non-public data from
/etc/shadow
to a non-root user.You can avoid this problem completely by:
Be careful how you call this script.
If you allow an untrusted user to run this script as root or to run any process as root that calls this script, be careful. By changing the environment, they can make this script--or any script that runs as root--do anything. Unless you can prevent this from occurring, you must not allow users elevated privileges for running shell scripts.
See 10.4. Shell Scripting Languages (sh and csh Derivatives) in David A. Wheeler's Secure Programming for Linux and Unix HOWTO for more information on this. While his presentation focuses on setuid scripts, other mechanisms can fall prey to some of the same problems if they don't correctly sanitize the environment.
Other Notes
It supports reading hashes from the
shadow
database only.Passwords must be shadowed for this script to work (i.e., their hashes should be in a separate
/etc/shadow
file that only root can read, not in/etc/passwd
).This should always be the case in Ubuntu. In any case, if needed the script can be trivially extended to read password hashes from
passwd
as well asshadow
.Keep
IFS
in mind when modifying this script.I set
IFS=$
at the beginning, since the three data in the hash field of a shadow entry are separated by$
.$
, which is why the hash type and salt are"${ent[1]}"
and"${ent[2]}"
rather than"${ent[0]}"
and"${ent[1]}"
, respectively.The only places in this script where
$IFS
determines how the shell splits or combines words arewhen these data are split into an array, by initializing it from the unquoted
$(
)
command substitution in:when the array is reconstituted into a string to compare to the full field from
shadow
, the"${ent[*]}"
expression in:If you modify the script and have it perform word splitting (or word joining) in other situations, you'll need to set
IFS
to different values for different commands or different parts of the script.If you don't keep this in mind and assume
$IFS
is set to the usual whitespace ($' \t\n'
), you could end up making your script behave in some pretty weird-seeming ways.