| #!/usr/bin/env python |
| |
| """Change passwords on the named machines. passmass host1 host2 host3 . . . |
| Note that login shell prompt on remote machine must end in # or $. """ |
| |
| import pexpect |
| import sys |
| import getpass |
| |
| USAGE = '''passmass host1 host2 host3 . . .''' |
| COMMAND_PROMPT = '[$#] ' |
| TERMINAL_PROMPT = r'Terminal type\?' |
| TERMINAL_TYPE = 'vt100' |
| SSH_NEWKEY = r'Are you sure you want to continue connecting \(yes/no\)\?' |
| |
| |
| def login(host, user, password): |
| |
| child = pexpect.spawn('ssh -l %s %s' % (user, host)) |
| fout = file("LOG.TXT", "wb") |
| child.setlog(fout) |
| |
| i = child.expect([pexpect.TIMEOUT, SSH_NEWKEY, '[Pp]assword: ']) |
| if i == 0: # Timeout |
| print 'ERROR!' |
| print 'SSH could not login. Here is what SSH said:' |
| print child.before, child.after |
| sys.exit(1) |
| if i == 1: # SSH does not have the public key. Just accept it. |
| child.sendline('yes') |
| child.expect('[Pp]assword: ') |
| child.sendline(password) |
| # Now we are either at the command prompt or |
| # the login process is asking for our terminal type. |
| i = child.expect(['Permission denied', TERMINAL_PROMPT, COMMAND_PROMPT]) |
| if i == 0: |
| print 'Permission denied on host:', host |
| sys.exit(1) |
| if i == 1: |
| child.sendline(TERMINAL_TYPE) |
| child.expect(COMMAND_PROMPT) |
| return child |
| |
| # (current) UNIX password: |
| |
| |
| def change_password(child, user, oldpassword, newpassword): |
| |
| child.sendline('passwd') |
| i = child.expect( |
| ['[Oo]ld [Pp]assword', '.current.*password', '[Nn]ew [Pp]assword']) |
| # Root does not require old password, so it gets to bypass the next step. |
| if i == 0 or i == 1: |
| child.sendline(oldpassword) |
| child.expect('[Nn]ew [Pp]assword') |
| child.sendline(newpassword) |
| i = child.expect(['[Nn]ew [Pp]assword', '[Rr]etype', '[Rr]e-enter']) |
| if i == 0: |
| print 'Host did not like new password. Here is what it said...' |
| print child.before |
| child.send(chr(3)) # Ctrl-C |
| child.sendline('') # This should tell remote passwd command to quit. |
| return |
| child.sendline(newpassword) |
| |
| |
| def main(): |
| |
| if len(sys.argv) <= 1: |
| print USAGE |
| return 1 |
| |
| user = raw_input('Username: ') |
| password = getpass.getpass('Current Password: ') |
| newpassword = getpass.getpass('New Password: ') |
| newpasswordconfirm = getpass.getpass('Confirm New Password: ') |
| if newpassword != newpasswordconfirm: |
| print 'New Passwords do not match.' |
| return 1 |
| |
| for host in sys.argv[1:]: |
| child = login(host, user, password) |
| if child is None: |
| print 'Could not login to host:', host |
| continue |
| print 'Changing password on host:', host |
| change_password(child, user, password, newpassword) |
| child.expect(COMMAND_PROMPT) |
| child.sendline('exit') |
| |
| if __name__ == '__main__': |
| try: |
| main() |
| except pexpect.ExceptionPexpect as e: |
| print str(e) |