home *** CD-ROM | disk | FTP | other *** search
- #!/usr/skunk/bin/expect --
- # mkpasswd - make a password, if username given, set it.
- # Author: Don Libes, NIST
-
- # defaults
- set length 9
- set minnum 2
- set minlower 2
- set minupper 2
- set verbose 0
- set distribute 0
-
- if [file executable /bin/yppasswd] {
- set defaultprog /bin/yppasswd
- } else {
- set defaultprog /bin/passwd
- }
- set prog $defaultprog
-
- while {[llength $argv]>0} {
- set flag [lindex $argv 0]
- switch -- $flag \
- "-l" {
- set length [lindex $argv 1]
- set argv [lrange $argv 2 end]
- } "-d" {
- set minnum [lindex $argv 1]
- set argv [lrange $argv 2 end]
- } "-c" {
- set minlower [lindex $argv 1]
- set argv [lrange $argv 2 end]
- } "-C" {
- set minupper [lindex $argv 1]
- set argv [lrange $argv 2 end]
- } "-v" {
- set verbose 1
- set argv [lrange $argv 1 end]
- } "-p" {
- set prog [lindex $argv 1]
- set argv [lrange $argv 2 end]
- } "-2" {
- set distribute 1
- set argv [lrange $argv 1 end]
- } default {
- set user [lindex $argv 0]
- set argv [lrange $argv 1 end]
- break
- }
- }
-
- if {[llength $argv]} {
- puts "usage: mkpasswd \[args] \[user]"
- puts " where arguments are:"
- puts " -l # (length of password, default = $length)"
- puts " -d # (min # of digits, default = $minnum)"
- puts " -c # (min # of lowercase chars, default = $minlower)"
- puts " -C # (min # of uppercase chars, default = $minupper)"
- puts " -v (verbose, show passwd interaction)"
- puts " -p prog (program to set password, default = $defaultprog)"
- exit 1
- }
-
- if {$minnum + $minlower + $minupper > $length} {
- puts "impossible to generate $length-character password\
- with $minnum numbers, $minlower lowercase letters,\
- and $minupper uppercase letters"
- exit 1
- }
-
- # if there is any underspecification, use additional lowercase letters
- set minlower [expr $length - ($minnum + $minupper)]
-
- set lpass "" ;# password chars typed by left hand
- set rpass "" ;# password chars typed by right hand
-
- # insert char into password at a random position
- proc insert {pvar char} {
- upvar $pvar p
-
- set p [linsert $p [rand [expr 1+[llength $p]]] $char]
- }
-
- set _ran [pid]
-
- proc rand {m} {
- global _ran
-
- set period 233280
- set _ran [expr ($_ran*9301 + 49297) % $period]
- expr int($m*($_ran/double($period)))
- }
-
- # choose left or right starting hand
- set initially_left [set isleft [rand 2]]
-
- # given a size, distribute between left and right hands
- # taking into account where we left off
- proc psplit {max lvar rvar} {
- upvar $lvar left $rvar right
- global isleft
-
- if {$isleft} {
- set right [expr $max/2]
- set left [expr $max-$right]
- set isleft [expr !($max%2)]
- } else {
- set left [expr $max/2]
- set right [expr $max-$left]
- set isleft [expr $max%2]
- }
- }
-
- if {$distribute} {
- set lkeys {q w e r t a s d f g z x c v b}
- set rkeys {y u i o p h j k l n m}
- set lnums {1 2 3 4 5 6}
- set rnums {7 8 9 0}
- } else {
- set lkeys {a b c d e f g h i j k l m n o p q r s t u v w x y z}
- set rkeys {a b c d e f g h i j k l m n o p q r s t u v w x y z}
- set lnums {0 1 2 3 4 5 6 7 8 9}
- set rnums {0 1 2 3 4 5 6 7 8 9}
- }
-
- set lkeys_length [llength $lkeys]
- set rkeys_length [llength $rkeys]
- set lnums_length [llength $lnums]
- set rnums_length [llength $rnums]
-
- psplit $minnum left right
- for {set i 0} {$i<$left} {incr i} {
- insert lpass [lindex $lnums [rand $lnums_length]]
- }
- for {set i 0} {$i<$right} {incr i} {
- insert rpass [lindex $rnums [rand $rnums_length]]
- }
-
- psplit $minlower left right
- for {set i 0} {$i<$left} {incr i} {
- insert lpass [lindex $lkeys [rand $lkeys_length]]
- }
- for {set i 0} {$i<$right} {incr i} {
- insert rpass [lindex $rkeys [rand $rkeys_length]]
- }
-
- psplit $minupper left right
- for {set i 0} {$i<$left} {incr i} {
- insert lpass [string toupper [lindex $lkeys [rand $lkeys_length]]]
- }
- for {set i 0} {$i<$right} {incr i} {
- insert rpass [string toupper [lindex $rkeys [rand $rkeys_length]]]
- }
-
- # merge results together
- if {$initially_left} {
- regexp "(\[^ ]*) *(.*)" "$lpass" x password lpass
- while {[llength $lpass]} {
- regexp "(\[^ ]*) *(.*)" "$password$rpass" x password rpass
- regexp "(\[^ ]*) *(.*)" "$password$lpass" x password lpass
- }
- if {[llength $rpass]} {
- append password $rpass
- }
- } else {
- regexp "(\[^ ]*) *(.*)" "$rpass" x password rpass
- while {[llength $rpass]} {
- regexp "(\[^ ]*) *(.*)" "$password$lpass" x password lpass
- regexp "(\[^ ]*) *(.*)" "$password$rpass" x password rpass
- }
- if {[llength $lpass]} {
- append password $lpass
- }
- }
-
- if {[info exists user]} {
- if {!$verbose} {
- log_user 0
- }
-
- spawn $prog $user
- expect {
- "assword:" {
- send "$password\r"
- exp_continue
- }
- }
-
- # if user isn't watching, check status
- if {!$verbose} {
- if {[lindex [wait] 3]} {
- puts -nonewline "$expect_out(buffer)"
- exit 1
- }
- }
- }
-
- if {$verbose} {
- puts -nonewline "password for $user is "
- }
- puts "$password"
-