Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use bash/expect to check if an SSH login works

My team manages many servers, and company policy dictates that the passwords on these servers must be changed every couple of weeks. Sometimes, our official database of passwords gets out of date for whatever reason (people forget to update it, usually), but we cannot identify this sometimes until months later, since we don't consistently use every server.

I want to write a script that will scrape the passwords from the database, and use those passwords to attempt an (ssh) login to each server every night, and send an email with the results to the team. I am able to scrape the database for login information, but I'm not sure how to check whether ssh login was successful or not in expect.

I cannot use public key authentication for this task. I want password authentication so I can verify the passwords.

I disable public-key authentication by specifying the following file:

PasswordAuthentication=yes
PubkeyAuthentication=no

My attempts at the expect script:

# $1 = host, $2 = user, $3 = password, $4 = config file
expect -c "spawn ssh $2@$1 -F $4
expect -re \".*?assword.*?\"
send \"$3\n\"
...
send \'^D\'"

I thought maybe exit status could indicate the success? Couldn't find anything in the man pages though.

like image 631
Daniel Kats Avatar asked Sep 05 '12 13:09

Daniel Kats


2 Answers

I've been using something like the script below for a similar task.

#!/bin/sh
# Run using expect from path \
exec expect -f "$0" "$@"
# Above line is only executed by sh
set i 0; foreach n $argv {set [incr i] $n}
set pid [ spawn -noecho ssh $1@$3 $4 ]
set timeout 30
expect {
    "(yes/no)" {
        sleep 1
        send "yes\n"
        exp_continue
    }
    "(y/n)" {
        sleep 1
        send "y\n"
        exp_continue
    }
    password {
        sleep 1
        send "$2\n"
        exp_continue
    }
    Password {
        sleep 1
        send "$2\n"
        exp_continue
    }
    "Last login" {
        interact
    }
    "Permission denied" {
        puts "Access not granted, aborting..."
        exit 1
    }
    timeout {
        puts "Timeout expired, aborting..."
        exit 1
    }
    eof {
        #puts "EOF reached."
    }
}
set status [split [wait $pid]]
set osStatus [lindex $status 2]
set procStatus [lindex $status 3]
if { $osStatus == 0 } {
    exit $procStatus
} else {
    exit $procStatus
}
like image 150
crowbent Avatar answered Nov 15 '22 19:11

crowbent


Do you specifically need to check if you can obtain a shell or is trying to execute a command also OK ?

If you just want to check authentication, you may want to do ssh asimplecommand (using echo, hostname, or something as such) and check if you get the expected result.

You may also want to launch ssh with -v option, and look for Authentication succeeded (at the debug1 log level).

like image 36
Francois G Avatar answered Nov 15 '22 20:11

Francois G