#!/usr/local/bin/perl # @(#)mchp.pl 1.9 08/02/98 # Meta-Password Changing Routine (mchp) - aperrin 6/15/98 # REQUIRES a master (Unix) password; allows changing any of # {unix,smb,mail} passwords. Checks and requires that mail # password <> unix password. # Modified by aperrin 7/20/98 - plan is to run on a machine that has both an smbpasswd # file and a local cache of /etc/shadow, and to make changes then rdist as necessary. # Additional documentaion added 7/7/98 # Changing the main and smb passwords is accomplished using expect scripts; they are named # in $uxcmd and $smbcmd, respectively. Changing the mail password is accomplished by calling # a daemon on a remote machine, called schpd. The format of the line sent to schpd is simply # :username:uid:password hash: # The entire password changing suite is: # - /usr/local/bin/mchp.pl : Meta CHange Password - this program, the user interface. # - /usr/local/bin/chpass.exp : CHange PASSword - manages the chat with /bin/passwd. # - /usr/local/bin/smbpass.exp : SMB PASSword - manages the chat with ~samba/bin/smbpasswd. # - /usr/LOCAL/bin/schpd.pl : Socket CHange Password Daemon - Accepts & does remote chp requests. # The main code is very simple - it asks for a master password and its new version, and confirms # that this is correctly done, all using the chpass.exp script. If this worked, it then asks # if the user wants to change other passwords: mail or smb. use Socket; require "getopts.pl"; &Getopts('dhp:s:u:'); if ($opt_h) { print "Usage: $0 [-h (help)] [-d (debug)] [-s schpd server] [-p schpd port]\n"; print " [-u user]\n"; exit 0; } #globals $uxcmd="/usr/local/bin/chpass.exp"; @saltset = ('a' .. 'z', 'A' .. 'Z', '0' .. '9', '.', '/'); $port = 75; $them = ''; #machine running daemon to connect to $sockaddr = 'S n a4 x8'; $debug = 0; $port = $opt_p if $opt_p; $debug = $opt_d if $opt_d; $them = $opt_m if $opt_m; $mkntpwd = "/home/davis/hdir1/ntadmin/bin/mkntpwd"; chop($hostname = `hostname`); chop($ypmaster = `ypwhich -m passwd.byname`); $islocal="local" if $hostname eq $ypmaster; #get user's login name $user=getlogin || (getpwuid($<))[0] || die "mchp: security quit"; $user=$opt_u if ((!$<) && ($opt_u)); #set $user to -u call if root and -u exists if ($debug && !$<) {print "$0 started as root for $user\n";} sub errtrap { print "Problems were encountered - not changing password(s).\n"; exit 1; } sub ChangeMaster { $olduxpw = "lc"; #set a dummy olduxpw if ($< || !$islocal) { #this is to check for root system 'stty', '-echo'; print "Enter $user\'s current MASTER (Unix) password: "; chop($olduxpw=); } do { print "\nNew MASTER (Unix) password: "; chop($newuxpw=); print "\n"; print "Confirm new MAIN (Unix/Windows) password: "; chop($cnfuxpw=); print "\n"; if($newuxpw ne $cnfuxpw) { print "Passwords don\'t match!\n"; } }until($newuxpw eq $cnfuxpw) ; if ($<) { $pwout=`$uxcmd $olduxpw $newuxpw` || &errtrap; } else { $pwout=`$uxcmd $olduxpw $newuxpw $user $islocal` || &errtrap; } if ($pwout =~ /^\+/) { print "MAIN (Unix/Windows) password changed.\n"; } else { ($junk,$errmsg) = split(/:/,$pwout); print "Error changing password: $errmsg\n"; &errtrap; } } sub ChangeEMail { system 'stty', '-echo'; print "NOTE: Your E-MAIL password MUST be different from your MAIN password.\n"; print "New E-MAIL password: "; chop($newmailpw=); print "\n"; while ($newmailpw eq $newuxpw) { print "Your E-MAIL password MUST be different from your MAIN password!\n"; print "Try again: New E-MAIL password: "; chop($newmailpw=); print "\n"; } $cnfmailpw=""; while ($newmailpw ne $cnfmailpw) { print "Confirm new E-MAIL password: "; chop($cnfmailpw=); print "\n"; if ($newmailpw ne $cnfmailpw) { print "Passwords don\'t match!\n"; } } $sendemail = 1; } sub ChangeSMB { #Unused in current incarnation system 'stty', '-echo'; print "New Windows NT (SMB) password: "; chop($newsmbpw=); print "\n"; $cnfsmbpw=""; while ($newsmbpw ne $cnfsmbpw) { print "Confirm new Windows NT (SMB) password: "; chop($cnfsmbpw=); print "\n"; if ($newsmbpw ne $cnfsmbpw) { print "Passwords don\'t match!\n"; } } $sendsmb = 1; } #Main system 'stty', 'echo'; print "mchp: Changing passwords for $user\n"; &ChangeMaster; &ChangeEMail; $newsmbpw=$newuxpw; $sendsmb=1; $mailline=""; if ($sendemail || $sendsmb) { $lct=time; print "Doing remote password change...\n"; ($pert1, $pert2) = unpack("C2", substr($user,-2,2)); $week = $lct / (60*60*24*7) + $pert1 + $pert2; $nsalt = $saltset[$week % 64] . $saltset[$now % 64]; if ($sendemail) { $cryptmail = crypt($newmailpw,$nsalt); } if ($sendsmb) { chop($smbhashes=`$mkntpwd $newsmbpw`); ($lmhash, $nthash) = split(/:/,$smbhashes); } if ($<) { $useuid = $<; } else { @pwnam = getpwnam($user); $useuid = $pwnam[2]; } $mailline="\:$user\:$useuid\:$cryptmail\:$lmhash\:$nthash\:"; ($scname,$scaliases,$sctype,$sclen,$thisaddr)=gethostbyname($hostname); ($scname,$scaliases,$sctype,$sclen,$thataddr)=gethostbyname($them); $this = pack($sockaddr, &AF_INET, 0, $thisaddr); $that = pack($sockaddr, &AF_INET, $port, $thataddr); socket(S, &AF_INET, &SOCK_STREAM, $proto) || die "Can\'t open socket: $!\n"; bind(S, $this) || die "Can\'t bind: $!\n"; connect(S, $that) || die "Can\'t connect: $!\n"; select(S); $| = 1; select(STDOUT); chop($response = ()); if ($debug) {print "S: $mailline\n";} chop($response = ()); $respcode = substr($response,0,4); if ($debug) {print "