Odd behaviour with Expect password update script


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Odd behaviour with Expect password update script
# 1  
Old 01-12-2014
Odd behaviour with Expect password update script

Hi there. I've been forced by circumstance to write an expect script to handle password updates on a number of servers. There's a mix of Solaris 8, 9, 10, RedHat and Ubuntu. There's no chance the client will allow us to hook them up to a directory, so we have to make do.

This script is mostly intended for myself and my colleagues to update our own passwords, but I've built in the ability for it to update a user's passwords. I've also elected to use ssh $server sudo passwd to get around the not-standardised password policies. It has a wrapper script written in bash, so in the near future I may enforce a password policy there.

I've found some unexpected behaviour though. As part of error-handling, I'm trying to cater for instances where the script logs in to a server as the sysadmin, but finds that their password is expired. Here's the relevant bit of the script, and hopefully the comments will help you follow the logic:

Code:
# Open the connection and invoke sudo passwd
spawn ssh -q -o StrictHostKeyChecking=no -t $server $sudo passwd $user
expect {
        # Set the default action to catch any unexpected responses
        default {
                send_user -- "\nERROR: I was unable to connect to $server for some reason.  Please try manually.\n"
                exit 1
        }

        # Pre-check for a server that we might not have an ssh key on yet
        -re "$whoami@$server's \[pP\]assword:" {
                send_log -- "\nWARN: $whoami doesn't appear to have an sshkey setup for $server.  You might want to resolve that.\n"
                send "$adminpass\r"
                exp_continue
        }

###### Note: the below block doesn't really work that well.  The if statement is fine, but the sending of the adminpass is echo'd back, which messes the following expect

        # Firstly, cater for password expiry for the admin account
        -re "\\\(current\\\) UNIX \[pP\]assword:|\[oO\]ld \[pP\]assword:" {
                # We need to test if the $user variable is the same as $whoami
                # This is to cater for instances where the admin is updating his/her own password
                # If true, it's sensible to feed the adminpass as their oldpwd, and newpass as their newpwd
                # Otherwise if they're updating a user, we don't want to set the admin's newpwd to the user's newpwd!

                if { $whoami != $user } {
                        send_user -- "\nWARN: It looks like you're updating a user's password\nI don't want to set your password to the user's password.\n"
                        send_log -- "\nWARN: $whoami's account is expired on $server and needs to be manually sorted out.\n"
                        # Try to end the remote session with Ctrl-D
                        send \004
                        exit 1
                } else {
                        # If the above test passes, we assume the Admin is updating his/her own password and continue
                        send "$adminpass\r"
                        expect {
                                default {
                                        send_user -- "\nERROR: It appears we can't authenticate to $server.  You'll need to resolve that manually.\n"
                                        exit 1
                                }
                                -re "\[nN\]ew UNIX \[pP\]assword:|\[nN\]ew \[pP\]assword:|\[aA\]gain:|\[rR\]etype|\[rR\]e-enter|\[rR\]eenter" {
                                        # Imitate inferior, slow, meatbag humans.  Mitigates mismatches.
                                        sleep 2
                                        send "$newpass\r"
                                        # exp_continue loops us back to the expect, capturing the second New Password prompt
                                        exp_continue
                                }
                                "BAD PASSWORD" {
                                        send_user -- "\nWARN: Password change failed for $whoami on $server due to the password not being acceptable.  Try a more complex password.\n"
                                        exit 1
                                }
                                # Upon completion of the password change, passwd should tell us it was successful.  We use this to exit
                                # This prevents erroneous triggering of the default condition
                                -re "updated|successfully" {
                                        send_log -- "\nINFO: Password updated on $server for $whoami.\n"
                                        exit 0
                                }
                        }
                }
        }

Here's the behaviour (sanitised and using QWERTYuiop12345 as an example password)

Code:
$ expect expect.chpwd examplehost me
spawn ssh -q -o StrictHostKeyChecking=no -t examplehost sudo passwd me
me@examplehost's password:
WARNING: Your password has expired.
You must change your password now and login again!
Changing password for user me.
Changing password for me
(current) UNIX password:
QWERTYuiop12345

passwd: Authentication token manipulation error

ERROR: It appears we can't authenticate to examplehost.  You'll need to resolve that manually.

And here's the debug:

Code:
expect: does "" (spawn_id exp7) match regular expression "me@examplehost's [pP]assword:"? Gate "me@examplehost's ?assword:"? gate=no
"\(current\) UNIX [pP]assword:|[oO]ld [pP]assword:"? (No Gate, RE only) gate=yes re=no
"\[sudo\] password for|[pP]assword:"? (No Gate, RE only) gate=yes re=no
me@examplehost's password:
expect: does "me@examplehost's password: " (spawn_id exp7) match regular expression "me@examplehost's [pP]assword:"? Gate "me@examplehost's ?assword:"? gate=yes re=yes
expect: set expect_out(0,string) "me@examplehost's password:"
expect: set expect_out(spawn_id) "exp7"
expect: set expect_out(buffer) "me@examplehost's password:"
send: sending "QWERTYuiop12345\n\r" to { exp7 }
expect: continuing expect

expect: does " " (spawn_id exp7) match regular expression "me@examplehost's [pP]assword:"? Gate "me@examplehost's ?assword:"? gate=no
"\(current\) UNIX [pP]assword:|[oO]ld [pP]assword:"? (No Gate, RE only) gate=yes re=no
"\[sudo\] password for|[pP]assword:"? (No Gate, RE only) gate=yes re=no


expect: does " \r\n" (spawn_id exp7) match regular expression "me@examplehost's [pP]assword:"? Gate "me@examplehost's ?assword:"? gate=no
"\(current\) UNIX [pP]assword:|[oO]ld [pP]assword:"? (No Gate, RE only) gate=yes re=no
"\[sudo\] password for|[pP]assword:"? (No Gate, RE only) gate=yes re=no
WARNING: Your password has expired.
You must change your password now and login again!

expect: does " \r\nWARNING: Your password has expired.\r\nYou must change your password now and login again!\r\n" (spawn_id exp7) 
match regular expression "me@examplehost's [pP]assword:"? Gate "me@examplehost's ?assword:"? gate=no
"\(current\) UNIX [pP]assword:|[oO]ld [pP]assword:"? (No Gate, RE only) gate=yes re=no
"\[sudo\] password for|[pP]assword:"? (No Gate, RE only) gate=yes re=no
Changing password for user me.
Changing password for me
(current) UNIX password:

expect: does " \r\nWARNING: Your password has expired.\r\nYou must change your password now and login again!\r\nChanging password for user me.\r\nChanging password for me\r\n(current) UNIX password: \r\n" (spawn_id exp7) 
match regular expression "me@examplehost's [pP]assword:"? Gate "me@examplehost's ?assword:"? gate=no
"\(current\) UNIX [pP]assword:|[oO]ld [pP]assword:"? (No Gate, RE only) gate=yes re=yes
expect: set expect_out(0,string) "(current) UNIX password:"
expect: set expect_out(spawn_id) "exp7"
expect: set expect_out(buffer) " \r\nWARNING: Your password has expired.\r\nYou must change your password now and login again!\r\nChanging password for user me.\r\nChanging password for me\r\n(current) UNIX password:"
send: sending "QWERTYuiop12345\n\r" to { exp7 }
Gate keeper glob pattern for '[nN]ew UNIX [pP]assword:|[nN]ew [pP]assword:|[aA]gain:|[rR]etype|[rR]e-enter|[rR]eenter' is ''. Not usable, disabling the performance booster.
Gate keeper glob pattern for 'updated|successfully' is ''. Not usable, disabling the performance booster.

expect: does " \r\n" (spawn_id exp7) match regular expression "[nN]ew UNIX [pP]assword:|[nN]ew [pP]assword:|[aA]gain:|[rR]etype|[rR]e-enter|[rR]eenter"? (No Gate, RE only) gate=yes re=no
"BAD PASSWORD"? no
"updated|successfully"? (No Gate, RE only) gate=yes re=no
QWERTYuiop12345


expect: does " \r\nQWERTYuiop12345\r\n\r\n" (spawn_id exp7) match regular expression "[nN]ew UNIX [pP]assword:|[nN]ew [pP]assword:|[aA]gain:|[rR]etype|[rR]e-enter|[rR]eenter"? (No Gate, RE only) gate=yes re=no
"BAD PASSWORD"? no
"updated|successfully"? (No Gate, RE only) gate=yes re=no
passwd: Authentication token manipulation error

expect: does " \r\nQWERTYuiop12345\r\n\r\npasswd: Authentication token manipulation error\r\r\n" (spawn_id exp7) 
match regular expression "[nN]ew UNIX [pP]assword:|[nN]ew [pP]assword:|[aA]gain:|[rR]etype|[rR]e-enter|[rR]eenter"? (No Gate, RE only) gate=yes re=no
"BAD PASSWORD"? no
"updated|successfully"? (No Gate, RE only) gate=yes re=no
expect: read eof
expect: set expect_out(spawn_id) "exp7"
expect: set expect_out(buffer) " \r\nQWERTYuiop12345\r\n\r\npasswd: Authentication token manipulation error\r\r\n"

ERROR: It appears we can't authenticate to examplehost.  You'll need to resolve that manually.

So you can see that -re "$whoami@$server's \[pP\]assword:" is found, the password is sent, and the script moves on. It then finds (current) UNIX password: and dutifully sends the password, however that password is printed out to the console (echoing off the remote ssh process?) and we get an Authentication token manipulation error.

The if/else works fine. I've also commented it entirely out and just had

Code:
        -re "\\\(current\\\) UNIX \[pP\]assword:|\[oO\]ld \[pP\]assword:" {
                send "$adminpass\r"
                exp_continue
        }

with the same behaviour. Could it be the buffer?

Apart from this one niggle, the rest of the script works exactly as desired.

Any thoughts appreciated.
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Expect script not passing password / commands ??

Newbie here. My goal is to have the expect script log into the Ubuntu 18.04 server and run two commands (lsb_release -a and ip addr) and eventually pipe the output/results to a file. For now, I would be happy to get this one command or two to run successfully. How to fix this? #!/usr/bin/expect ... (3 Replies)
Discussion started by: jacob600
3 Replies

2. Shell Programming and Scripting

Expect script not expecting the password prompt

I have a script that does an SSH into a remote node. It should expect the prompt and send the password. #!/usr/bin/expect set user ; set pass ; spawn ssh $user@E-Internal expect { -re "RSA key fingerprint" {send "yes\r"} timeout... (1 Reply)
Discussion started by: Junaid Subhani
1 Replies

3. Shell Programming and Scripting

Odd Behaviour for Set and IFS variable

Ok, so I'm playing around with delimters and reading files. and I came across this behaviour that I thought was a bit odd, regarding how the set command takes values... If I run this: IFS=$'-' #Assigns the - as the default delimiter for bash set I-love-my-gf-a-lot #uses set to put a bunch of... (1 Reply)
Discussion started by: Lost in Cyberia
1 Replies

4. Shell Programming and Scripting

SFTP or scp with password in a batch script without using SSH keys and expect script

Dear All, I have a requirement where I have to SFTP or SCP a file in a batch script. Unfortunately, the destination server setup is such that it doesn't allow for shell command line login. So, I am not able to set up SSH keys. My source server is having issues with Expect. So, unable to use... (5 Replies)
Discussion started by: ss112233
5 Replies

5. Shell Programming and Scripting

Passing Password to SSH without using expect in a Script

How can I pass password in SSH command without using expect in a shell program. I don't have expect installed on my Solaris server. #!/bin/bash ssh user@hotname (how to supply pass in script?:wall:) Experts please help its very urgent. Shrawan Kumar Sahu (4 Replies)
Discussion started by: ss135r
4 Replies

6. UNIX for Advanced & Expert Users

Encrypt the password ,source it in a expect script...!!

Hello folks I have a conf file ,say 'pass.conf' ,which is storing ascii password : PASS1111. I need to encrypt this password once and store it in a file. I ,then need to write a script which would read this encrypted password and decrypts it.The o/p o this script shud be this decrypted... (8 Replies)
Discussion started by: ak835
8 Replies

7. Solaris

odd behaviour of app writes to mirrored volumes

Hi, Normally, I setup my volumes under Solaris (doesnt matter, 8 or 10), as vxassist -g dg01 -U gen make vol01 500m dg0101, then I do a mirror vxassist -g dg01 mirror vol01 dg0102. Which is legal and does work, however, when the primary dg01 array (or simply in this case, the volume)... (2 Replies)
Discussion started by: mrmurdock
2 Replies

8. Shell Programming and Scripting

Expect script strange behaviour

Hi people, I'm having some strange behaviour with an 'expect' script. spawn csession blah expect "Username: " send "userblah\r" expect "Password: " send "passwordblah\r" interact When I execute the script as root it runs perfectly. However, when executed as any other... (0 Replies)
Discussion started by: GarciasMuffin
0 Replies

9. Shell Programming and Scripting

odd behaviour with quoted input strings

I'm working with a java-based monitoring tool (Solaris/x86) which can be configured to call a shell script when a particular event occurs. The java app sends a set of quoted strings as input to the shell script. The problem I'm running into is that the shell script, when called by the java app,... (0 Replies)
Discussion started by: iron_horse
0 Replies

10. Shell Programming and Scripting

Expect Script....encrypt password and use

Could someone please help me...I have an expect script. There's a need for a log in during the script and a password is required...right now the password is just a variable in the expect script...what would be the best way to put that in an encrypted flat file and have the expect script pull the... (2 Replies)
Discussion started by: cubs0729
2 Replies
Login or Register to Ask a Question