#!/usr/local/bin/expect --
# this line must contain the absolute pathname to expect 
#
# spasswd:  change skey password on cnls gateway machine
#
# Author: Aric Hagberg  (aric@lanl.gov)
# Date: 2 August 1995
# Version 0.91
# http://t7.lanl.gov/People/Aric/Skey
#----------------------------------------------------------------------------
#  	IMPORTANT: This script should only be run on a local machine
#	(the one you are sitting at - not an Xterminal or any other
#	remote display).   Use on a nonlocal machine will comprimise
#	the security of of the S/Key system by sending your secret
#	password across the network.
#
#----------------------------------------------------------------------------
# Description: 	
#		
#	usage:	spasswd [args]
#	where arguments are:"
#		-h              help
#		-k key program  name of skey key program
#		-l username     username
#		-v              verbose
#		-version	prints version
#----------------------------------------------------------------------------
#
# CUSTOMIZABLE VARIABLES  (set defaults for your system)
#
set user            [exec whoami]		
set key_program     "/usr/local/bin/key"
set maxtries	    3
set verify          3
set timeout         30
#
# END OF CUSTOMIZABLE VARIABLES
#----------------------------------------------------------------------------
#
log_user 0
exp_internal 0
#
#	usage and help information
#
proc help {} {
	global display gateway user key_program argv0
        puts "usage: spasswd \[args] "
        puts "  where arguments are:"
        puts "    -h              (help)"
        puts "    -k key program  (key program, default = $key_program)"
        puts "    -l username     (username, default = $user)"
        puts "    -v              (verbose)"
        puts "    -version"
        puts "\n    http://t7.lanl.gov/People/Aric/Skey\n "
	exit
}
#
#	parse command line
#
while {[llength $argv]>0} {
        set flag [lindex $argv 0]
        switch -glob -- $flag \
          "-l" {
                set user [lindex $argv 1]
                set argv [lrange $argv 2 end] 
	} "-v"  {
                log_user 1
		set argv [lrange $argv 1 end]
	}  "-h" {
                help
        }  "-help" {
                help
        }  "-version" {
                puts "Version: spasswd version 0.91"; exit
	}  "-*" {
                exp_send_error "\nUnknown option: $flag\n\n" 
		help
      } default {
			break
		}
}
#
#	connect to gateway
#
spawn telnet cnlsgw1 7779
set telnet_id $spawn_id

#
#	get old password and login to gateway
#
set count 0
while 1 {

expect {
	-re "rname:"   {exp_send "$user\r"}
	timeout {puts "$gateway not responding after $timeout seconds";exit}
}
expect 	{ 
	-re "s/key(.*)" {set key "$expect_out(1,string)"}
	-re "rname:"    {puts "User $user doesn't exist on $gateway"; exit}
	timeout {puts "$gateway not responding after $timeout seconds";exit}
}
#
#	we now have challenge key and are ready to run the local key 
#	program to get and send one-time password
#

if {![info exists password]} {
	set oldtimeout $timeout
	set timeout -1
	stty -echo
	send_user "Old password: "
	expect_user -re "(.*)\n"
	send_user "\n"
	set password $expect_out(1,string)
	stty echo
	set timeout $oldtimeout
}
# 
#	run key program locally and send it the 'secret password'
#
eval spawn "$key_program $key\r"
expect {
	-re "sword: "      {exp_send "$password\r"}
	-re "$key_program" {puts "Can't execute $key_program";exit}
	timeout {puts "Can't execute $key_program";exit}
}
#
#	get and send the one time password to gateway
#
expect {
	-re "(\r\n)+(.+)\r\n" \
	     {set spawn_id $telnet_id;send "$expect_out(2,string)\r"}
	}
expect {
	-re "Denied"   \
	    {send_user "Incorrect password\n";unset password; incr count}
	-re "Updating" {break}
	
	}	
if {$count >= $maxtries} {exp_send_user "Sorry\n";exit}
}
#
#	we are in!  change the password
#
send_user "Your new password must be verified by repeating it $verify times"
	
expect {
	-re "9999:" {send "9999\r\r"}
	timeout {puts "cnlsgw1 not responding after $timeout seconds";exit}
	}	

expect 	{ 
	-re "s/key(.*)\r\ns/key" {set key "$expect_out(1,string)"}
	timeout {puts "cnlsgw1 not responding after $timeout seconds";exit}
}


set oldtimeout $timeout
set timeout -1
set correct 1
while {$correct <= $verify} {
	stty -echo
	send_user "$correct New password: "
	expect_user -re "(.*)\n"
	send_user "\n"
	set password $expect_out(1,string)
	stty echo

	if { $correct == 1} {set oldpass $password}

	if {[string match $oldpass $password]} {
	incr correct
	} else { set correct 1
	send_user "No match: starting over\n"
	}	
}
set timeout $oldtimeout

eval spawn "$key_program $key\r"
expect {
	-re "sword: "      {exp_send "$password\r"}
	-re "$key_program" {puts "Can't execute $key_program";exit}
	timeout {puts "Can't execute $key_program";exit}
}
expect {
	-re "(\r\n)+(.+)\r\n" \
	     {set newpass $expect_out(2,string)\r"}
	}

set spawn_id $telnet_id
send "$newpass\r"
expect {
	-re "ok" {send_user "Password successfully changed\n";exit}
	timeout {send_user "Timeout: Password not changed\n"}
}