Establishing password less connection SunOS using expect - shell

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.

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

ssh expect command with variables

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.

multiple commands in spawn script to copy keys

I'm trying to create a script to copy ssh keys to multiple servers for passwordless login. I have a list of servers entered one per line in serverlist.txt. Below is the script I created.
#!/usr/bin/expect -f
set f [open "serverlist.txt"]
set hosts [split [read $f] "\n"]
close $f
foreach host $hosts {
spawn -noecho sh -c "cat ~/.ssh/id_rsa.pub | ssh -t -o StrictHostKeyChecking=no $host 'mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys'"
expect "assword:";
send "abc123\r"; # sending the password
expect "$"; #expecting the $prompt
send "exit\r";
interact
}
Im getting below error while running this script
send: spawn id exp4 not open
while executing
"send "exit\r""
("foreach" body line 6)
invoked from within
"foreach host $hosts {
spawn -noecho sh -c "cat ~/.ssh/id_rsa.pub | ssh -t -o StrictHostKeyChecking=no $host 'mkdir -p ~/.ssh && cat >> ~/.ssh/authori..."
(file "sshkeys" line 6)
If i commented below lines I'm getting diff error
#expect "assword:";
#send "abc123\r";
#expect "$";
#send "exit\r";
Pseudo-terminal will not be allocated because stdin is not a terminal.
user#1.1.1.1's password:
Pseudo-terminal will not be allocated because stdin is not a terminal.
ssh: mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys: Name or service not known
Note:
ssh-copy-id is not available.
None of the target servers have the .ssh directory created.
Can somebody help me to identify the issue.

Issuing commands on remote linux

I'm looking for any way to do this task with expect:
Mac-mini:~ root# scp file peter#Mac-mini:file2
The authenticity of host 'mac-mini (192.168.1.105)' can't be established.
RSA key fingerprint is b6:12:3e:48:10:e6:d2:1f:8f:57:f4:01:2d:f3:23:89.
Are you sure you want to continue connecting (yes/no)? yes
Password: ********
and issue
crontab -l > crontab.src
#!/usr/bin/expect
set machine0 "Mac-minimini"
set machine1 "Mac-mini"
set machine2 "Mac-pro"
...
set machine19 "Mac-air"
for {set i 1} {$i < 20} {incr i 1} {
eval spawn scp file peter#${machine${i}}:file2
expect "connecting (yes/no)?"
send "yes\r"
#use correct prompt
set prompt ":|#|\\\$"
interact -o -nobuffer -re $prompt return
send "password\r"
interact -o -nobuffer -re $prompt return
send "crontab -l > crontab.src\r"
interact
}
Edit: You can use for loop and concatenate names for each machine using the variable of the loop.(e.g. Mac-mini0, Mac-mini1, ... Mac-mini19)
Edit2: I am not sure if ${machine${i}} works but worth to try..
Set up an ssh key like so:
ssh-keygen -t rsa
Place your public key on the remote machine (assuming you create a key in your home directory called id_rsa)
ssh-copy-id peter#Mac-mini
Then you will be able to scp without entering a password.
autoexpect -f scp file peter#Mac-mini:file2
For the crontab part, am assuming you mean on the remote machine.
autoexpect -f crontab ssh peter#Mac-mini "crontab -l > crontab.src"

Connect to multiple ssh connections through scripts

I have been trying to automatically enter a ssh connection using a script. This previous SOF post has helped me so far. Using one connection works (the first ssh statement). However, I want to create another ssh connection once connected, which I thought could look like this:
#! /bin/bash
# My ssh script
sshpass -p "MY_PASSWORD1" ssh -o StrictHostKeyChecking=no *my_hostname_1*
sshpass -p "MY_PASSWORD2" ssh -o StrictHostKeyChecking=no *my_hostname_2*
When running the script, I get only connected to the my_hostname_1 and the second ssh command is not run until I exit the first ssh connection.
I've tried using an if statement like this:
if [ "$HOSTNAME" = my_host_name_1 ]; then
sshpass -p "MY_PASSWORD2" ssh -o StrictHostKeyChecking=no *my_hostname_2*
fi
but I can't get any commands to be read until I exit the first connection.
Here is a ProxyCommand example as suggested by #lihao:
#!/bin/bash
sshpass -p "MY_PASSWORD2" ssh -o StrictHostKeyChecking=no \
-o ProxyCommand='sshpass -p "MY_PASSWORD1" ssh m_hostname_1 netcat -w 1 %h %p' \
my_hostname_2
You are proxying through the first host to get to the second. This assumes you have netcat installed on my_hostname_2. If not, you'll need to install it.
You can also set this up in your ~/.ssh/config file so you don't need the proxy stuff on the command line:
Host my_hostname_1
HostName my_hostname_1
Host my_hostname_2
HostName my_hostname_2
ProxyCommand ssh my_hostname_1 netcat -w 1 %h %p
However, this is a little trickier with the password handling. While you could put the sshpass here, it's not a great idea to have passwords in plain text. Using key based authentication might be better.
A Bash script is a sequence of commands.
echo moo
echo bar
will run echo moo and wait for it to complete, then run the next command.
You can run a remote command like this:
ssh remote echo moo
which will connect to remote, run the command, and exit. If there are additional commands in the script file after this, the shell which is executing these commands will continue with the next one, obviously on the host where you started the script.
To connect to one host from another, you could in principle do
ssh host1 ssh host2
but the proxy command suggested by #zerodiff improves on several aspects of the experience.

Resources