su - like in "Super User" or "Switch User"

mail

How to use su non-interactively ?

Before going further, be aware that using su non-interactively is a bad idea because it exposes the account password, no matter how you proceed.
I'm considering this solution here in a very specific context :
  • I'm deploying VMs from a template
  • in the template, the root account has a default password. This password is not public, but it's known by members of our team and is something pretty generic, definitely not good enough for production machines.
  • one of the first actions made on a fresh VM is to change the root password
  • now, what I'd like to do, is to make sure this password has actually been changed on all VMs
  • this check should be automated so that we can check VMs on-demand. This is why the non-interactive mode is acceptable here : the default password is already used by our automation tool for the first connection to a fresh VM

Using su non-interactively :

This is as simple as : echo password | su
  • login='root'; password='password'; echo "$password" | su "$login" -c 'whoami'
    Password: root		Password:  is the prompt output by su, root is the result of whoami
  • login='root'; password='password'; output=$(echo "$password" | su "$login" -c 'whoami'); echo -e "\n$output"
    Password:		same prompt again
    root			same result again
  • login='root'; password='password'; output=$(echo "$password" | su "$login" -c 'whoami' 2>/dev/null); echo "$output"
    root

Alternate solution :

In the context of checking whether the current password is a known default password, an alternate solution would be to hash this default password and check whether the hashed value exists in /etc/shadow :
login='root'; password='password';
salt=$(awk -F'$' -v login="$login" '$0 ~ login { print $3 }' /etc/shadow)
passwordHash=$(openssl passwd -6 -salt "$salt" "$password")
grep -c "$passwordHash" /etc/shadow
This method can not be said "better" than the one above because :
  • it discloses the password too
  • it must be run as root to read /etc/shadow
mail

su

Usage

change user ID or become superuser

Flags

Flag Usage
- -l --login Make the shell a login shell :
  • the environment will be changed to what would be expected if the user actually logged in as the specified user (otherwise —when not using - -l --login— the environment is passed along, with the exception of PATH)
  • this unsets all environment variables EXCEPT :
    These are given values as described in the friendly manual, please
  • and "cds" into the target user's home directory
details : man7.org, ss64.com
-c command --command=command Pass the command command to the shell.
-s shell --shell=shell Invoke the shell shell

Example

If "sudo su -" returns This account is currently not available.

Trying to become root ends either on su: Authentication failure or on su: Permission denied

In the scenarios below, running either su or su - makes no difference.
What I've tested :
as a member of the root group + su + right password
logged as root, as expected
as a member of the root group + su + wrong password
su: Authentication failure
not as a member of the root group + su + any password (right or wrong makes no difference)
su: Permission denied

This behavior is caused by this uncommented line of /etc/pam.d/su which forces users to be a member of group root before they can use su :

auth	required	pam_wheel.so	group=root

Some tests as root :

su bob -c whoami
bob					as expected 

su bob -c whoami; echo $HOME
bob					as above
/root					the echo came once the su was over, then this is no surprise

su bob -c "whoami; echo $HOME"
bob					this is still part of the su -c , so no surprise
/root					thanks to the ", $HOME is substituted with its current value, then the whole string is passed to su -c  (details)

su bob -c 'whoami; echo $HOME'
bob					no change 
/home/bob				thanks to the ', the whole expression is sent as-is to su -c  (no substitution), then executed as bob

value=42; su bob -c "echo $HOME [$value]"; su bob -c 'echo $HOME [$value]'
/root [42]				this is just to emphasize 
/home/bob []				on the example above