ssh expect command with variables - shell

I am planning to take password from file instead of passing parameter to the script
set cmd1 {`cat passwdfile.txt | grep -w pj | cut -d";" -f5`}
spawn ssh username#servername
expect "password: "
send "$cmd1\r"
expect "$ "
send "ps -ef |grep planning1\r"
expect "$ "
send "exit\r"
Error
username#servername's password:
Permission denied, please try again.
Why it is not taking password from the file ??

At the point where ssh is asking for a password, you don't have access to a shell, so the backticks and all the rest will be sent as plain characters as the password.
Assuming that file exists on your local machine, get the password before you spawn:
set pw [exec grep -w pj passwdfile.txt | cut -d\; -f5]
spawn ssh ...
expect "password: "
send "$pw\r"
Of course it's terribly insecure to store passwords in plain text. You should set up ssh keys to allow you to log in without having to type a password.

Related

How to match this [admin#MikroTik] > in bash script (expect)?

I am trying to write a script that will auto configure mikrotik router, but some weird character appears as soon as password is sent through the script and logins the router. Below is the script that i wrote,
#!/bin/bash
read -p "Enter IP Address: " Public_IP
read -p "Enter username: " Username
read -sp "Enter Password: " Password
echo
expect -c "
spawn ssh -o StrictHostKeyChecking=no $Username#$Public_IP
set timeout -1
expect "password:"
send "$Password\r"
expect "\[admin*"
sleep 4
expect "\[admin*"
"
While I run this script I see below the following in the image,
So what i want to accomplish is to see the second image and send some commands for example;
/ip arp print
send above commmand for instance.
image after running the script
the actual interface i want to get and send command like that
you need to add +tc after username in ssh command
spawn ssh -o StrictHostKeyChecking=no $Username+tc#$Public_IP
it´s works for me

Establishing password less connection SunOS using expect

The host system from where I am trying to establish remote connection is running on SunOS. There isn't ssh-copy-id available on the system.
After searching, I found that the following command, when executed will mimic the ssh-copy-id function.
cat ~/.ssh/id_rsa.pub | ssh remotehost 'cat >>~/.ssh/authorized_keys && echo "Host Key Copied"'
I am trying to write a script using expect for doing this operation but it is failing with the following error.
Code:
#!/usr/bin/expect -f
#!/bin/bash
set username [lindex $argv 0]
set password [lindex $argv 1]
set host [lindex $argv 2]
cat ~/.ssh/id_rsa.pub | ssh remotehost 'cat >>~/.ssh/authorized_keys && echo \"Host Key Copied\"'
expect "Password:"
send "$password\n"
expect eof
Error:
invalid command name "cat"
while executing
"cat ~/.ssh/id_rsa.pub | ssh remotehost 'cat >>~/.ssh/authorized_keys && echo \"Host Key Copied\"'"
(file "./remote.sh" line 8)
From search, I understood that expect won't entertain shell commands by default. Could someone help in resolving my issue. Thanks in advance.
You're missing the spawn command: spawn launches the process that you're interacting with. You're also missing the ssh-copy-id command:
spawn ssh-copy-id $username#$host
expect ...
However, what you're doing is greatly reducing security. Passing the password in clear text on the command line, where it will likely be stored in your shell's history file.

bash: while read loop - stop if there is variable sshpass

i have a problem with my bash script. I read line by line the variable lvm_path_exec, that works. I confirmed it with echo "lvmpath".
But as soon as i place a sshpass command into the while statement the script only process the first line which got grepped.
If there is no sshpass command all lines of lvmpath_exec get processed.
Do you see the error?
lvmpath_exec=$(sshpass -p "${password[$i]}" ssh ${user[$i]}#${ip[$i]} -p ${port[$i]} lvdisplay | grep datatest -A 3 | grep Path | awk '{ print $3 }')
echo "$lvmpath_exec" | while read lvmpath
do
lvmname=datatest
snap=_snapshot
snapname=$lvmname$snap
lvcreate=$(sshpass -p "${password[$i]}" ssh ${user[$i]}#${ip[$i]} -p ${port[$i]} lvcreate -L20G -s -n $snapname $lvmpath)
snap_path=$(sshpass -p "${password[$i]}" ssh ${user[$i]}#${ip[$i]} -p ${port[$i]} lvdisplay | grep $snapname -A 3 | grep Path | awk '{ print $3 }')
transfer=$(sshpass -p "${password[$i]}" ssh ${user[$i]}#${ip[$i]} -p ${port[$i]} "dd if=$snap_path | gzip -c" > /tmp/$snapname)
delsnap=$(sshpass -p "${password[$i]}" ssh ${user[$i]}#${ip[$i]} -p ${port[$i]} lvremove -f $snap_path)
done
UPDATE
I fixed it:
replace
echo "$lvmpath_exec" | while read lvmpath
with
for lvmpath in $lvmpath_exec
But shouldnt it work with while read too?
sshpass works by manipulating stdin to fool ssh into thinking it is getting the password from an interactive user. When you use a ... | while style loop, the loop iterates for every line coming from stdin, which sshpass wipes out after the first call, that's why only the first line gets executed. The for loop doesn't use stdin, that's why it doesn't have this problem.
As man sshpass explains, this tool is inherently insecure and you should really be using public key authentication instead. Also keep in mind that it has other ways of passing the password, using the -p flag is the least safe method of all, and any other method would be safer, for example the -e flag seems trivially easy. I know you might insist you have a legitimate use case, but this is so important I'm just gonna quote from the man page:
First and foremost, users of sshpass should realize that ssh's insis‐
tance on only getting the password interactively is not without reason.
It is close to impossible to securely store the password, and users of
sshpass should consider whether ssh's public key authentication pro‐
vides the same end-user experience, while involving less hassle and
being more secure.
The -p option should be considered the least secure of all of sshpass's
options. All system users can see the password in the command line
with a simple "ps" command. Sshpass makes a minimal attempt to hide the
password, but such attempts are doomed to create race conditions with‐
out actually solving the problem. Users of sshpass are encouraged to
use one of the other password passing techniques, which are all more
secure.
have you tried this..have not tried though
export SSHPASS=password[$i]
sshpass -e ssh -oBatchMode=no user[$i]#{ip[$i]} ..

send: spawn id exp7 not open

When I try to execute autoexpect file I get an error send: spawn id exp7 not open
Here is my file sh.exp:
#!/usr/bin/expect
# mysql credentials and connection data
db_host='localhost'
db_name='webui_dev'
db_user='root'
db_pass=''
new_db_name='db_2011'
expect <<EOF
log_user 0
spawn mysql -h $db_host -u $db_user -p $db_pass 'create database $new_db_name'
expect "password:"
send "$db_pass\r"
log_user 1
expect eof
EOF
Can't find where is an error.
Try quoting your variables properly:
spawn mysql -h "$db_host" -u "$db_user" -p "$db_pass" "create database $new_db_name"
Variables not quoted in double quotes are subject to word splitting and pathname expansion. And variables under single quotes don't expand. Read more about shell quoting here.
Update: It seems that you're actually expanding it through a here document, but it would still apply since your arguments still need to be quoted in expect. This is what it would appear as input to expect:
log_user 0
spawn mysql -h "localhost" -u "root" -p "" "create database db_2011"
expect "password:"
send "\r"
log_user 1
expect eof
This is how it would appear if you haven't quoted it yet:
...
spawn mysql -h localhost -u root -p 'create database db_2011'
...
UPDATE:
The cause of the problem actually is because mysql ends quickly without showing a prompt for password due to the extra argument. The solution is to send the command manually. It's also preferable to just run the whole script as an expect script, not an embedded one for lesser confusion
#!/usr/bin/expect
# mysql credentials and connection data
set db_host "localhost"
set db_name "webui_dev"
set db_user "root"
set db_pass ""
set new_db_name "db_2011"
log_user 0
spawn mysql -h "$db_host" -u "$db_user" -p
expect "password:"
send "$db_pass\r"
expect "mysql>"
send "create database $new_db_name; exit; \r"
log_user 1
expect eof
Save the script as an expect file and run it with expect -f expect_file.

how to pass password to a command in bash

I want to write a bash script that will execute one command in the script, and the command need read some thing as password. So how can I pass the password to the command in the script?
$ota_gen -k $ota_key -i $1 -p $ota_tools $2 $ota_out_file
ota_key is a private key that need to be visited with a password, so how can I do it?
thank you.
ps: thanks hlovdal for help.
expect maybe what can help. But I don't know if it can interact with bash script, such as how to pass parameters from script to expect.
A quite common tool for feeding programs with proper input (like for instance passwords) non-interactively is the tool expect. The following example is given on the wikipedia page:
# Assume $remote_server, $my_user_id, $my_password, and $my_command were read in earlier
# in the script.
# Open a telnet session to a remote server, and wait for a username prompt.
spawn telnet $remote_server
expect "username:"
# Send the username, and then wait for a password prompt.
send "$my_user_id\r"
expect "password:"
# Send the password, and then wait for a shell prompt.
send "$my_password\r"
expect "%"
# Send the prebuilt command, and then wait for another shell prompt.
send "$my_command\r"
expect "%"
# Capture the results of the command into a variable. This can be displayed, or written to disk.
set results $expect_out(buffer)
# Exit the telnet session, and wait for a special end-of-file character.
send "exit\r"
expect eof
OK, I google and get the answer of how to interact with expect in bash script.
I have added lines bellow in my script.Ant it tack effect.
th
EXEC=$(expect -c "
spawn $ota_gen -k $ota_key -i $1 -p $ota_tools $2 $ota_out_file
expect \"Enter password for .... key>\"
send \"$PASSWD\r\"
interact
")
echo $EXEC
If you are passing sensitive information around and use it regularly you are probably best encrypting it.
Putting something like
#create key as follows - will prompt for password
#echo -n 'secret you want encrypted' | openssl enc -aes-256-cbc -a -salt -pbkdf2|base64
export MY_SECRET='VTJGc2RHVmtYMTlzVnBGWXNYUitLWlpYT3BWdStaQXJXeUVwc1JORnFsNWswZXJKT1dkRWpsWkxLWVFnK1hONQo='
Into your .bashrc will give you an encrypted environment variable that you can access where ever you need a secret, and you will be prompted for you passphrase/password that you used when creating the environment variable.
In the example above it is 'secret'
You access it is a command as follows
`echo $MY_SECRET|base64 --decode|openssl enc -aes-256-cbc -a -d -salt -pbkdf2 `
e.g.
xfreerpd /parameters.... /p:`echo $MY_SECRET|base64 --decode|openssl enc -aes-256-cbc -a -d -salt -pbkdf2`
For your query where $ota_key is the secret
$ota_gen -k $ota_key -i $1 -p $ota_tools $2 $ota_out_file
You can create the variable as follows
ota_key=`echo -n 'secret you want encrypted' | openssl enc -aes-256-cbc -a -salt -pbkdf2|base64`
Then use it as follows
$ota_gen -k `echo $ota_key|base64 --decode|openssl enc -aes-256-cbc -a -d -salt -pbkdf2 ` -i $1 -p $ota_tools $2 $ota_out_file
openssh will prompt you for a password to encrypt and decrypt each time, you can supply one as part of the command, but then you are just hiding things from the history etc. Have a look at https://www.tecmint.com/generate-encrypt-decrypt-random-passwords-in-linux/ for some info on using openssh for this. https://www.serverlab.ca/tutorials/linux/administration-linux/how-to-base64-encode-and-decode-from-command-line/ for base64 and How to assign an output to a shellscript variable? for different options on command substitution I have used back-tick ` above
PS Adding a function like
get-key()
{
echo -n "$1"|base64 --decode|openssl enc -aes-256-cbc -a -d -salt -pbkdf2
}
To your bashrc gives you quick access to the secret if you need it

Resources