Trouble logging in user using su and expect script

user3791260 picture user3791260 · Mar 20, 2015 · Viewed 7.5k times · Source

I am working on making a website for a class that you log into with a username and password, and then it takes you to a page that shows your grades in the class.

The website is being run with a bash script, and will be hosted on a machine where the users already have a username and password to login.

I also have a script called calcgrade.sh that will calculate the grades for either the user who is currently logged in, or the user passed to the script as an argument.

So originally, I was going to use this command:

echo -e "$password\n" | sudo -Sk -u $user ./website/calcgrade.sh

to run calcgrade.sh as the user of the website. However, I found out that sudo asks for the password of the user who is currently logged in, not the target user you are trying to run a command as.

So after some reading, I found a better option would be to use su with an expect script, but I can't get it to work. Here is the code for the expect script (currently username and password are hard coded in for testing):

#!/usr/bin/expect

log_user 0

spawn /bin/su myusername
expect "Password: "
send "mypassword"
spawn "./website/calcgrade.sh"

interact

When I run this script, it doesn't seem to log in the user with su, as it goes on to run calcgrade.sh with my account, rather than the user's.

Do you see what is wrong with my script? Or can you see a better way to do what I want?

Also, another problem with this method is that calcgrade.sh is supposed to send some output to stderr, but when I run it with the expect script, the error messages get sent to the website (the server works by sending the html for the website to stdout). Is there a way around this, or might it be better to have the expect script just check with su if username/password is correct, and then if so, then run ./calcgrade.sh $user afterwards?

Answer

that other guy picture that other guy · Mar 20, 2015

First of all, here's the correct way to do what you want to do:

  1. Give your web server user sudo permissions to run ./website/calcgrade.sh as any user, without requiring a password.
  2. Have the web server authenticate the user however you see fit.
  3. Have it run sudo -u someuser ./website/calcgrade.sh, no password required.

Now let's look at why your approach didn't work:

It's commonly believed that su switches user. This is not the case. It actually starts a new shell running as another user.

This means that you can't spawn su otheruser, let it finish, and then afterwards spawn calcgrade.sh.

Instead you have to run su otheruser, and then send commands to the shell that su starts:

#!/usr/bin/expect 

log_user 0

spawn /bin/su someuser 
expect "Password: "
send "somepassword\n" 

# Now wait for a prompt and send the command to run
expect "$"
send "./website/calcgrade.sh\n"
interact