How to check from commandline if sudo authentication failed? - linux

I was making a graphical front end to sudo for myself in bash scripting. Using something like gksudo is not an option for me, because the OS that I use doesn't provide one.
I designed it this way-
#!/bin/bash
sudo -S $# <<< $(/usr/lib/gtkdialog/box_passwd "$USER password" "Enter password" 2>/dev/null)
STATUS=$?
if [ $STATUS -eq 127 ]; then
/usr/lib/gtkdialog/box_splash -bg red -fg white -timeout 5 -text "sudo not found!"
exit 1
fi
while [ $STATUS -ne 0 ]; do
sudo -S $# <<< $(/usr/lib/gtkdialog/box_passwd "$USER password" "Authentication failed! Please retry" 2>/dev/null)
export STATUS=$?
done
(Note that /usr/lib/gtkdialog/box_passwd and /usr/lib/gtkdialog/box_splash are specific to this OS).
It works if I remove the while loop. But then the program would ask for the password only once, even if it was wrong. But currently, the while loop many a times doesn't end, because even if authentication is correct, sudo may also return 1 if the program it runs is not found or the program returns 1.
So how can I make this code run the while loop only if authentication for sudo is failed, and not other times when sudo returns 1?
EDIT: Just to make it clear, /usr/lib/gtkdialog/box_passwd is used here as graphical program to prompt the user for his/her password, which /usr/lib/gtkdialog/box_passwd passes to its stdout (prints to its stdout). /usr/lib/gtkdialog/box_splash is a program which just creates a new window and show some specific message

In some OSes, the man page for sudo specifies which error messages would come from sudo. If your OS does that, you can grep stderr for these messages.
Otherwise, sudo isn't very helpful in that department, but if your usage of sudo is simple (no fancy configuration in /etc/sudoers, and no specific commands are configured to be allowed by sudo), then you can just do something like:
#!/bin/bash
sudo -S true <<< $(/usr/lib/gtkdialog/box_passwd "$USER password" "Enter password" 2>/dev/null)
export STATUS=$?
if [ $STATUS -eq 127 ]; then
/usr/lib/gtkdialog/box_splash -bg red -fg white -timeout 5 -text "sudo not found!"
exit 1
fi
while [ $STATUS -ne 0 ]; do
sudo -S true <<< $(/usr/lib/gtkdialog/box_passwd "$USER password" "Authentication failed! Please retry" 2>/dev/null)
STATUS=$?
done
sudo "$#"
Namely, you don't run the command, you just run a dummy command (true in this case, which never fails).
In the default configuration, sudo remembers you for a few minutes.
So if you run sudo "$#" immediately after sudo true succeeded, sudo wouldn't ask you for a password in order to run the actual command.

Related

ssh to different nodes using shell scripting

I am using below code to ssh to different nodes and find if an user exists or not. If the user doesn't exist it will create it.
The script works fine if I don't do ssh but it fails if I do ssh.
How can I go through different nodes using this script?
for node in `nodes.txt`
usr=root
ssh $usr#$node
do
if [ $(id -u) -eq 0 ]; then
read -p "Enter username : " username
read -s -p "Enter password : " password
egrep "^$username" /etc/passwd >/dev/null
if [ $? -eq 0 ]; then
echo "$username exists!"
exit 1
else
pass=$(perl -e 'print crypt($ARGV[0], "password")' $password)
useradd -m -p $pass $username
[ $? -eq 0 ] && echo "User has been added to system!" || echo "F
ailed to add a user!"
fi
else
echo "Only root may add a user to the system"
exit 2
fi
done
Your script has grave syntax errors. I guess the for loop at the beginning is what you attempted to add but you totally broke the script in the process.
The syntax for looping over lines in a file is
while read -r line; do
.... # loop over "$line"
done <nodes.txt
(or marginally for line in $(cat nodes.txt); do ... but this has multiple issues; see http://mywiki.wooledge.org/DontReadLinesWithFor for details).
If the intent is to actually run the remainder of the script in the ssh you need to pass it to the ssh command. Something like this:
while read -r node; do
read -p "Enter user name: " username
read -p -s "Enter password: "
ssh root#"$node" "
# Note addition of -q option and trailing :
egrep -q '^$username:' /etc/passwd ||
useradd -m -p \"\$(perl -e 'print crypt(\$ARGV[0], \"password\")' \"$password\")" '$username'" </dev/null
done <nodes.txt
Granted, the command you pass to ssh can be arbitrarily complex, but you will want to avoid doing interactive I/O inside a root-privileged remote script, and generally make sure the remote command is as quiet and robust as possible.
The anti-pattern command; if [ $? -eq 0 ]; then ... is clumsy but very common. The purpose of if is to run a command and examine its result code, so this is better and more idiomatically written if command; then ... (which can be even more succinctly written command && ... or ! command || ... if you only need the then or the else part, respectively, of the full long-hand if/then/else structure).
Maybe you should only do the remote tasks via ssh. All the rest runs local.
ssh $user#$node egrep "^$username" /etc/passwd >/dev/null
and
ssh $user#$node useradd -m -p $pass $username
It might also be better to ask for username and password outside of the loop if you want to create the same user on all nodes.

Can you sudo with input whiptail?

I want to ask your sudo password with whiptail password and then use it to run sudo script.sh this is possible?
I have tried this sudo command with the whiptail input for password
sudo -S <<< $psw script.sh
echo $ psw | sudo -S
Full Code
#!/bin/bash
#Password Input
psw=$(whiptail --title "Test Password Box" --passwordbox "Enter your password and choose Ok to continue." 10 60 3>&1 1>&2 2>&3)
#Password If
exitstatus=$?
if [ $exitstatus = 0 ]; then
sudo -S <<< $psw script.sh
else
#Password If cancel
whiptail --title "Cancel" --msgbox "Operation Cancel" 10 60
fi
A quick check shows the script should work (works for me). Your script is calling sudo separately from whiptail, so the two are not interfering with each other's use of the terminal.
The script should begin with
#!/bin/bash
because it uses the here-string
<<< $psw

Working around sudo in shell script child process

So the reason I am asking this is because I'm running two programs simultaneously that are persistent, on the child process a programm is running that requires sudo rights.
#!/bin/bash
echo "Name the file:"
read filename
while [[ 1 -lt 2 ]]
do
if [ -f /home/max/dump/$filename.eth ]; then
echo "File already exist."
read filename
else
break
fi
done
#Now calling a new terminal for dumping
gnome-terminal --title="tcpdump" -e "sh /home/max/dump/dump.sh $filename.eth"
ping -c 1 0 > /dev/null **Waiting for tcpdump to create file**
#Packet analysis program is being executed
Script dump.sh
#!/bin/bash
filename=$1
echo password | sudo tcpdump -i 2 -s 60000 -w /home/max/dump/$filename -U
host 192.168.3.2
#Sudo still asks me for my password though password is piped into stdin

How to make a script run commands as root

I'm new to Ubuntu and bash scripts, but I just made runUpdates.sh and added this to my .profile to run it:
if [ -f "$HOME/bin/runUpdates.sh" ]; then
. "$HOME/bin/runUpdates.sh"
fi
The problem I'm having is, I want the script to run as if root is running it (because I don't want to type my sudo password)
I found a few places that I should be able to do sudo chown root.root <my script> and sudo chmod 4755 <my script> and when I run it, it should run as root. But it's not...
The script looks good to me. What am I missing? -rwxr-xr-x 1 root root 851 Mar 23 21:14 runUpdates.sh*
Can you please help me run the commands in this script as root? I don't really want to change the sudors file, I really just want to run the commands in this script at root (if possible).
#!/bin/sh
echo "user is ${USER}"
#check for updates
update=`cat /var/lib/update-notifier/updates-available | head -c 2 | tail -c 1`;
if [ "$update" = "0" ]; then
echo -e "No updates found.\n";
else
read -p "Do you wish to install updates? [yN] " yn
if [ "$yn" != "y" ] && [ "$yn" != "Y" ]; then
echo -e 'No\n';
else
echo "Please wait...";
echo `sudo apt-get update`;
echo `sudo apt-get upgrade`;
echo `sudo apt-get dist-upgrade`;
echo -e "Done!\n";
fi
fi
#check for restart
restartFile=`/usr/lib/update-notifier/update-motd-reboot-required`;
if [ ! -z "$restartFile" ]; then
echo "$restartFile";
read -p "Do you wish to REBOOT? [yN] " yn
if [ "$yn" != "y" ] && [ "$yn" != "Y" ]; then
echo -e 'No\n';
else
echo `sudo shutdown -r now`;
fi
fi
I added the user is to debug, it always outputs my user not root, and prompts for the sudo password (since I'm calling the commands with sudo) or tells me are you root? (if I remove sudo)
Also, is there a way to output the update commands stdout in real time, not just one block when they finish?
(I also tried with the shebang as #!/bin/bash)
setuid does not work on shell scripts for security reasons. If you want to run a script as root without a password, you can edit /etc/sudoers to allow it to be run with sudo without a password.
To "update in real time", you would run the command directly instead of using echo.
Its not safe to do, you should probably use sudoers but if you really need/want to, you can do it with something like this:
echo <root password> | sudo -S echo -n 2>/dev/random 1>/dev/random
sudo <command>
This works because sudo doesn't require a password for a brief window after successfully being used.
SUID root scripts were phased out many years ago if you really want to run scripts as root you need to wrap them in an executable, you can see an example on how to do this on my blog:
http://scriptsandoneliners.blogspot.com/2015/01/sanitizing-dangerous-yet-useful-commands.html
The example is how to change executable permissions and place a filter around other executables using a shell script but the concept of wrapping a shell script works for SUID as well, the resulting executable file from the shell script can be made SUID.
https://help.ubuntu.com/community/Sudoers

Sudo: parted: command not found while executing script to format disk

I am trying to create a script to format a newly added disk on a VM in vmware. I want to run the script with a sudouser.
echo "- - -" > /sys/class/scsi_host/host0/scan
echo "scsi add-single-device 0 0 1 0" > /proc/scsi/scsi
dev=/dev/disk/by-path/*-scsi-0:0:1:0
count=0
while [ ! -r ${dev} ]; do
count=$(($count+1))
if [ $count -gt 5 ]; then
echo "New disk for target is not visible by the OS"
exit 1
fi
echo $count
sleep 5
done
dev=$(readlink -f $dev) || exit 1
parted -s -- $dev mklabel msdos
When I run the script as sudo ./mount.sh, the script fails saying "parted: command not found". I added the path for parted in the PATH variable for the sudouser. What am I missing? Where did I go wrong?
I tried adding sudo to each command individually, then the script fails in the while loop. Do I need to add any more permissions for the sudouser? Or is there any implementation error? Am I missing something? Please help me.
I observed that this happens when I try to run any of the commands in /sbin/
sudo ifconfig throws sudo: ifconfig: command not found

Resources