Skip to content

Commit

Permalink
initial checkin
Browse files Browse the repository at this point in the history
  • Loading branch information
jsmoriss committed Jan 5, 2016
1 parent e9465ec commit 0c3640d
Show file tree
Hide file tree
Showing 2 changed files with 242 additions and 0 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@

# sshchpwd.exp

Expect script to change login passwords using SSH

A few years ago I was supporting a very diverse environment with Solaris, AIX, and Linux servers; some with password logins, public/private key authentication, and several with SecurID passwords. All accounts were local, passwords expired every three months, and the accounts locked after three failed logins — so you can imagine the mess this created if you didn’t go around every server at least every three months. After I’d accumulated about half a dozen passwords, I wrote an Expect script to login and change my password and wrapped it with a bash script to try every old password I had. Since some servers needed a SecurID number to login, the bash script would pause on those and prompt me for the token before continuing. I’ve seen a few Expect scripts to change passwords, but none that can handle one-time tokens (like SecurID), expired passwords (changed before arriving at the prompt), and the variety of prompts to support Solaris, AIX, Linux, etc.

237 changes: 237 additions & 0 deletions sshchpwd.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
#!/usr/bin/expect -f
#
# /usr/local/bin/sshchpwd.exp
#
# Expect script to change login passwords using SSH, with support for one-time
# tokens (like SecurID), expired passwords (changed before arriving at the
# prompt), on Solaris, AIX, Linux, etc.
#
# License: GPLv3
# License URI: http://www.gnu.org/licenses/gpl.txt
#
# Copyright 2012-2016 Jean-Sebastien Morisset (http://surniaulula.com/)
#
# Example:
#
# $ export OLD_PASSWORD="oldpwd"
# $ export NEW_PASSWORD="newpwd"
# $ ./sshchpwd {server} {port} {token}
#
# The {port} and {token} command-line parameters are optional. If the server
# uses SecurID (or another one-time password), enter it on the command-line as
# the third parameter.

set timeout 15
set server [lindex $argv 0]
set port [lindex $argv 1]
set tokpwd [lindex $argv 2]
set oldpwd $env(OLD_PASSWORD)
set newpwd $env(NEW_PASSWORD)
set prompt "\[>%\\$#\] "

if { $port == "" } { set port "22" }
if { $tokpwd == "" } { set tokpwd $oldpwd }

send_user "connecting to $server on port $port\n"
spawn ssh -p $port $server

# Mission of this first expect - get to the shell command prompt. If the
# password is expired and we have to change it before getting to the prompt,
# then exit 0 (success).

expect {
"(yes/no)? " {
send_user " (detected unknown host key - accepting)\n"
send "yes\n"
send_user " (continuing expect loop)\n"
exp_continue
}
"assword:" {
send_user " (detected password login prompt - possibly token)\n"
send "$tokpwd\n"
expect {
" UNIX password:" {
send_user " (detected additional password prompt - old password)\n"
send "$oldpwd\n"
send_user " (continuing expect loop)\n"
exp_continue
}
-nocase "old password:" {
send_user " (detected password expired prompt)\n"
send "$oldpwd\n"
send_user " (continuing expect loop)\n"
exp_continue
}
-re "not match the|password mismatch" {
send_user " (assuming expired password change failed)\n"
send "passwd\n"
expect {
-nocase "old password:" {
send_user " (trying with new password)\n"
send "$newpwd\n"
expect {
-re "\[nN\]ew \[pP\]assword:|\[nN\]ew \[pP\]assword \[aA\]gain:" {
send_user "\nPassword is current.\n"
exit 0
}
"not match the" {
send_user "\nPassword change failed.\n"
exit 1
}
default {
send_user "\nPassword change failed.\n"
exit 1
}
}
}
default {
send_user "\nPassword change failed.\n"
exit 1
}
}
}
-re "\[nN\]ew \[pP\]assword:|\[nN\]ew \[pP\]assword \[aA\]gain:" {
send "$newpwd\n"
expect {
"between changes." {
send_user "\nPassword change failed.\n"
exit 1
}
-re "\[nN\]ew \[pP\]assword:|\[nN\]ew \[pP\]assword \[aA\]gain:" {
send "$newpwd\n"
expect {
-re "$prompt" {
send_user " (detected shell command prompt)\n"
send_user "Password successfully changed.\n"
exit 0
}
"Connection to " {
send_user " (detected connection closed - assuming password change successful)\n"
send_user "Password successfully changed.\n"
exit 0
}
default {
send_user "\nPassword change failed.\n"
exit 1
}
}
}
}
}
"assword:" {
send "$newpwd\n"
expect {
" UNIX password:" {
send_user "\nNew password is expired!\n"
exit 1
}
-nocase "old password:" {
send_user "\nNew password is expired!\n"
exit 1
}
"assword:" {
send_user "\nAutomated login failed.\n"
exit 1
}
-re "$prompt" {
send_user " (detected shell command prompt)\n"
send_user "Password is current.\n"
exit 0
}
default {
send_user "\nAutomated login failed.\n"
exit 1
}
}
}
-re "$prompt" { send_user " (detected shell command prompt)\n" }
}
}
-re "$prompt" { send_user " (detected shell command prompt)\n" }
}

send "\n"

expect {
-re "$prompt" {
send_user " (changing password at prompt)\n"
send "passwd\n"
expect {
-re "\[oO\]ld \[pP\]assword:| UNIX \[pP\]assword:" {
send "$oldpwd\n"
expect {
"You must wait longer" {
send_user "\nPassword change failed.\n"
exit 1
}
-re "not match the|password mismatch" {
send "passwd\n"
expect {
-nocase "old password:" {
send_user " (trying with new password)\n"
send "$newpwd\n"
expect {
-re "\[nN\]ew \[pP\]assword:|\[nN\]ew \[pP\]assword \[aA\]gain:" {
send_user "\nPassword is current.\n"
exit 0
}
"not match the" {
send_user "\nPassword change failed.\n"
exit 1
}
default {
send_user "\nPassword change failed.\n"
exit 1
}
}
}
default {
send_user "\nPassword change failed.\n"
exit 1
}
}
}
-re "\[nN\]ew \[pP\]assword:|\[nN\]ew \[pP\]assword \[aA\]gain:" {
send "$newpwd\n"
expect {
"between changes." {
send_user "\nPassword change failed.\n"
exit 1
}
-re "\[nN\]ew \[pP\]assword:|\[nN\]ew \[pP\]assword \[aA\]gain:" {
send "$newpwd\n"
expect {
-re "$prompt" {
send_user " (detected return to shell command prompt)\n"
send_user "Password successfully changed.\n"
exit 0
}
default {
send_user "\nPassword change failed.\n"
exit 1
}
}
}
"BAD PASSWORD" {
send_user "\nPassword change failed.\n"
exit 1
}
default {
send_user "\nPassword change failed.\n"
exit 1
}
}
}
default {
send_user "\nPassword change failed.\n"
exit 1
}
}
}
}
}
default {
send_user "\nAutomated login failed.\n"
exit 1
}
}

0 comments on commit 0c3640d

Please sign in to comment.