Trouble logging in user using su and expect script - bash

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?

First of all, here's the correct way to do what you want to do:
Give your web server user sudo permissions to run ./website/calcgrade.sh as any user, without requiring a password.
Have the web server authenticate the user however you see fit.
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

Related

Shell script for remote login with password

I'm trying to write a shell script for remote login that doesn't ask for a password. Here's what I've tried and when I execute it, it still does ask for a password. Here's the code :
#!/usr/bin/expect -f
spawn ssh ronnie-pc
expect "Password:"
send "password\r"
interact
I'm not sure if this is the right way to do it and it takes a lot of time to login.
why use shell? use pythons pexpect which works everywhere and easy to use.

Login to su and take the password from the same script

I'm trying to automate the build process which is done on linux server.
to do that first i need to login to the su and then perform the tasks for stopping and starting the server. I've written shell script to do that but there are some problems I'm facing,
1) even though I'm providing password from script using expect & send it tasks for password on terminal.
2) doing echo'password' | sudo -S su takes password automatically but says wrong even if it is right.
3) and when i put the password through terminal manually using su I get logged in to the su but the rest of the commands in script does not gets executed unless i do exit.
The script I've tried is,
echo 'password\n' | sudo -S su ##it says wrong password for su
commands to be performed after logging to su
exit
I've tried expect and send too,
su expect"Password" send "password\n";
and rest of the code here
but it's not fetching password from send automatically, I've to put it manually.
I would really appreciate if someone can help me with this!!
sudo requires the password of the user calling it, not the password of the superuser (or the user specified by the -u option). That may seem backwards, but the idea is that sudo can be configured to provide fine-grained control over what you are actually allowed to run as the superuser, rather than giving you access to the superuser account itself. Also, sudo keeps a log of who does what for auditing purposes.
If you used the wrong password, use the right password instead. Like others have already commented, sudo requires your password, not root's.
Additionally, your script is wrong. The sequence su; echo hello; exit will run a root shell with su, then when that shell exits, run echo hello and exit in your current shell.
You want this instead:
sudo -S sh -c 'echo hello'
The su is completely superfluous because sudo already takes care of switching to the root user, and offers a more convenient syntax for running commands as another user to boot. The sh -c '...' isn't strictly required in this example, but will probably be useful if you have more than one command which you wish to execute using elevated privileges. (Make sure you understand the implications. A useful commandment is to try to run even less code as sudo than you currently do. Always.)

Shell script to automate SonicWall firewall SSH session not working

I'm trying to write a shell script (Bash) to log into a SonicWall firewall device and issue a command to perform automated backups of the devices ruleset. I prefer to do this in Bash but I will accept a python, perl, except, or applescript solution. If it cannot be done in bash please mention that.
Problems:
1.) SSH server on firewall is custom, a user name and password has to be specified after issuing a
$ ssh server.com
so no matter what username you issue e.g.
$ ssh admin#server.com
the SSH server still presents a username and password box after
2.) The SSH server is minimal and I cannot use public-keys
I tried using a here-document but it isn't working and it results in an immediate "connection closed by remote host".
The command I need to execute takes the form of this:
export preferences ftp "ftp.server.com" "user1" "mypassword" "output.exp"
Connecting gives me this:
$ ssh admin#server.com
Copyright (c) 2010 SonicWALL, Inc.
User:
After a username is issued it brings up the password prompt:
User:user1
Password:
I tried a here-document to no avail.
$ ssh server <<+
user1
mypassword
export preferences ftp "ftp.server.com" "user1" "mypassword" "output.exp"
exit
+
Pseudo-terminal will not be allocated because stdin is not a terminal.
Connection to 10.1.1.1 closed by remote host.
I tried using echo to pipe in commands too but that doesn't work either.
Typing the commands in manually works just fine.
Any help on this would be greatly appreciated.
As others have suggested, expect is probably what you want to use here.
Here's a short example of how to work with it from bash to get you started:
login=root
IP=127.0.01
password=helloworld
# +whatever variables you need to use
# Run the expect script from bash
expect_sh=$(expect -c "
spawn ssh $login#$IP
expect \"password:\"
send \"$password\r\"
expect \"#\"
send \"cd $dest_dir\r\"
expect \"#\"
send \"chmod +x $server_side_script $other_script\r\"
expect \"#\"
send \"./$device_side_script\r\"
expect \"#\"
send \"cat results_file\r\"
expect \"#\"
send \"exit\r\"
")
# Output or do something with the results
echo "$expect_sh"
You can automate the ssh session using the original expect, here is a nice article discussing it in detail: http://solar1.net/drupal/automating%20SSH%20with%20expect or the Python module pexepect: http://linux.byexamples.com/archives/346/python-how-to-access-ssh-with-pexpect/
I'm not a BASH expert but i had to do something where interactive password prompts was causing me a problem.
Basically your script needs to wait to be asked to enter login credentials, and pass them when prompted in order to login, once logged in you can issue the command.
I recommend looking at spawning "expect" sessions. Basically in your script you use expect to basically say "i expect to see password: in the response, when i do, i need to pass in the following data".
Here's the wiki page which helps explain it http://en.wikipedia.org/wiki/Expect
and if you google around you will find lots of help.
that didn't work for me.
I had to pass the variables to the script at launch.
Example launch script login2.sh, with three arguments:
-bash-4.1$ ./login2.sh Jan2**** HIE_SUPER 10.244.112.182

Bash Script to SSH into a machine without prompting password and without using keys

I realize this question has been asked a few times but I could not find a relevant answer anywhere in my searching.
I am working in a development environment where security is not an issue and anyone could just guess the password if the thought for a few seconds.
What I am trying to do is simple. I have created an alias function in my local .bashrc file and I would like this function to automatically log into a machine with a default password.
My current implementation looks something like this:
function s () {
ssh root#192.168.1.$1
}
When I run it I get something like this:
~]s 122
ssh root#192.168.1.122
root#192.168.1.122's password:
Using Bash, and not using RSA keys I would like to get this to use the default password 'password'.
I've tried the following where IP and User have already been set.
Do=$(expect -c "
spawn ssh $User#${IP[0]}.${IP[1]}.${IP[2]}.${IP[3]}
expect \"yes/no\"
send \"yes\r\"
expect \"assword\" send \"password\"")
echo $Do
$Do
It gives the follwing error:
Connecting and logging into server using expect
usage: send [args] string
while executing
"send"
invoked from within
"expect "assword" send "password""
Administrator#192.168.1.176's password:
bash: spawn: command not found...
Using the following command I am able to connect a machine. If I remove the interact it just runs the uptime command and closes the connection. With the interact command I am unable to see what I am typing or actually interact with the machine. Any ideas?
Do=$(expect -c "spawn ssh $User#${IP[0]}.${IP[1]}.${IP[2]}.${IP[3]}; set timeout 4; expect \"assword\"; send \"password\n\"; expect \"test\"; send \"uptime\n\"; interact;");echo $Do;
You can do this with the expect tool: http://expect.sourceforge.net/
It's widely available, so depending on your system, the equivalent of sudo apt-get install expect or yum install expect will install it.
Here's an example of an expect script with ssh. This logs you in and gives you control of the interactive prompt:
#!/usr/bin/expect
set login "root"
set addr "127.0.0.1"
set pw "password"
spawn ssh $login#$addr
expect "$login#$addr\'s password:"
send "$pw\r"
expect "#"
send "cd /developer\r"
interact
Here's an example of how to use expect as part of a bash script. This logs in with ssh, cd to /var, runs a script, then exits the ssh session.
#!/bin/bash
...
login_via_ssh_and_do_stuff() {
# build the expect script in bash
expect_sh=$(expect -c "
spawn ssh root#127.0.0.1
expect \"password:\"
send \"password\r\"
expect \"#\"
send \"cd /var\r\"
expect \"#\"
send \"chmod +x my_script.sh\r\"
expect \"#\"
send \"./my_script.sh\r\"
expect \"#\"
send \"exit\r\"
")
# run the expect script
echo "$expect_sh"
}
You can leave these snippets in a script on your local system, and then just alias to the scripts.
Also: I know you said security isn't an issue, but I'd like to just note, again, that the "proper" way to ssh without using a password is to use a ssh key-pair =)
Use sshpass which is available in package repositories on major Linux-es.
For example, when password is in password.txt file:
sshpass -fpassword.txt ssh username#hostname
sshpass runs ssh in a dedicated tty, fooling it into thinking it is
getting the password from an interactive user.

Connecting to a remote server and switching user with bash/expect

First post, thanks in advance for any help.
I'm somewhat new to scripting in general but I've managed to build a nice wrapper in bash that's designed to collect some variables and then make some connections to a couple of remote boxes and do some things related to a web statistics system and launch some hadoop processes. Basically a series of tedious tasks that I'm trying to automate. (unnecessary details complete).
The problem I'm running into is finding a way to effectively connect to those remove servers, authenticate as as a regular user, then switch users for various tasks. Here's the relevant code:
#!/bin/sh
#Script's run as root. this asks for the sudoers pass
read -p "Enter password for $SUDO_USER: " -s password
#Defines some testing commands I want to pass to a remote box
CMD="hostname; id; sudo su -; id; pwd;"
#launches an expect script with some defined variables as arguments.
/home/ME/scripts/derp.expect $SUDO_USER $definedremoteserver "$command" "$password"
Now the expect script being used:
#!/usr/bin/expect
#expect script to help with SSH connections for the urchinizer bash script
set arg1 [lindex $argv 0]
set arg2 [lindex $argv 1]
set arg3 [lindex $argv 2]
set arg4 [lindex $argv 3]
spawn ssh -oStrictHostKeyChecking=no $arg1#$arg2 "$arg3"
expect "password:"
send "$arg4\r"
interact
expect "password"
send "$arg4\r"
interact
I'm having trouble determining why this fails. I've researched quite a bit and have tried numerous variations of the code. Basically when I run this, it takes my pass and I'm able to make the initial connection. Then the script tries to switch user and the second expect fails. The first 'id' and 'hostname' output successfully. When the user switch happens, the second expect doesn't work and I'm left with just a password prompt. I enter my pass anyway (which displays in plain text for some reason) and the script just hangs without outputting the second 'id' and 'pwd' commands I'm trying to use to verify that this is working.
If I actually login to that box and do a sudo -i or sudo su - this is what the password prompt looks like:
[sudo] password for my.name:
So for the second (not working) expect, I've tried a few different variations with somewhat different results but no success.
Sorry for the long post. This has been driving be nuts. Is what I'm trying to do possible? Is there a smarter way to handle this? Anyone spot any obvious mistakes? Also, a secondary question... how do wildcards work in those expect lines?
If you can, use some scripting language as Perl, Python or Ruby with some module for SSH.
For instance, using Perl and the Net::OpenSSH module:
use Net::OpenSSH;
my $ssh = Net::OpenSSH->new($host, user => $user, password => $password);
my $output = $ssh->capture({stdin_data => "$sudo_password\n"},
'sudo', '-Sk', '-p', '', '--',
'ls', '/');
You should use "Public Key Authentication" instead of "Password Authentication" in OpenSSH.
1: create the private/public key pair for the user you want to login with this command:
ssh-keygen -t rsa
Do not supply passwords, choose the default path (enter, enter, enter).
This should be done for each of your SSH machines (clients and servers).
2: from each client machine you want to login from, copy your new public key file content to your favourite text editor (notepad, gvim, etc)
cat ~/.ssh/id_rsa.pub
You should now have all your client's public keys pasted into your editor, something like this:
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAt9sGP1PKR1XzpozHQc9ufyzOnePHCnRzUhdfSvfQTzJO28CgnHwhANdaBeOrLq5b+VOoPJFj5NquYXmJ6YikSJCwHlvfewA/5p0IkucsJLxqYQMDRhyeXb9fCk85MoNRJjAd+Cst+gI9Cwpp1ysLMDY77k/a9eT3ExkgbGd6mdtfjAlP/o/rRMcqNwp9Pdhh6kkxrM0v1ceNSTbTeO7XCLvekqtRiwjWImhQs56JVbB/RLySNKtqjbpr7Zhn1m+p6+vmBmgwF3xBBvzziYfMm/vG1ZvvGIsI3dxRDWuSZ8+o63w7Y20M9NQn4QkqV6NFjX3conBiDGtDBKain2zj6Q== dino#blackbigone
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0JR6d9LWgvPCbvBajrbVly3cxX7ZkbH4+MUBu+ak2G5SGLbGBcwdi3JquBAT1+U/hl+TKKUUw1XjjjazdjgYCHWIguDWzmqoyT4bQN2aymNoqD35T+LWAaqwC36m95fRfJh3HSOtx7KXpsBZjvR40rg901f8ReIjBoL7G620rrsRDqaDS08Mm6TjThBrCeTYX2YzugodpUNP2evwFOBMrYw/TIcX5Lza8xRCctm8MRodsx/yvuYuZJSanVLs3Q6sJ/n9o20L8Jt1Fu1cnyxJTs9THiLOnZyrTBXvbKJymit6p3hfDpDlWtO/crNeyt0H8jJcZfiCnhQwfib2VMMqJw== erica#blackbigone
3: paste the ascii armored public keys you have in your text editor into ~/.ssh/authorized_keys file on each SSH server you want to login into. You must be the user you want to login. Create the file if it doesn't exists.
This way you are granting the permission to login to the server where you created the authorized_keys file to all users presenting with the given public keys.
The login is successful if the user have the correct matching private key.
Once logged in on the remote server, you can use sudo (you have to configure /etc/sudoers file first with the visudo command) to execute commands by another user.
To avoid sudo to request for a password (because you are authenticated in /etc/sudoers...) you have to set the NOPASSWD flag, like the line below:
%admin ALL=(ALL) NOPASSWD: ALL

Resources