--- loncom/lond 2001/12/22 21:46:02 1.62 +++ loncom/lond 2002/02/19 21:52:54 1.72 @@ -2,7 +2,7 @@ # The LearningOnline Network # lond "LON Daemon" Server (port "LOND" 5663) # -# $Id: lond,v 1.62 2001/12/22 21:46:02 www Exp $ +# $Id: lond,v 1.72 2002/02/19 21:52:54 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -46,7 +46,11 @@ # 11/26,11/27 Gerd Kortemeyer # 12/20 Scott Harrison # 12/22 Gerd Kortemeyer -# +# YEAR=2002 +# 01/20/02,02/05 Gerd Kortemeyer +# 02/05 Guy Albertelli +# 02/07 Scott Harrison +# 02/12 Gerd Kortemeyer ### # based on "Perl Cookbook" ISBN 1-56592-243-3 @@ -84,6 +88,10 @@ sub catchexception { die($error); } +sub timeout { + &logthis("CRITICAL: TIME OUT ".$$.""); + &catchexception('Timeout'); +} # -------------------------------- Set signal handlers to record abnormal exits $SIG{'QUIT'}=\&catchexception; @@ -131,7 +139,7 @@ open (CONFIG,"$perlvar{'lonTabDir'}/host while ($configline=) { my ($id,$domain,$role,$name,$ip)=split(/:/,$configline); - chomp($ip); + chomp($ip); $ip=~s/\D+$//; $hostid{$ip}=$id; if ($id eq $perlvar{'lonHostID'}) { $thisserver=$name; } $PREFORK++; @@ -158,9 +166,13 @@ $children = 0; # cu sub REAPER { # takes care of dead children $SIG{CHLD} = \&REAPER; my $pid = wait; - $children --; - &logthis("Child $pid died"); - delete $children{$pid}; + if (defined($children{$pid})) { + &logthis("Child $pid died"); + $children --; + delete $children{$pid}; + } else { + &logthis("Unknown Child $pid died"); + } } sub HUNTSMAN { # signal handler for SIGINT @@ -187,6 +199,7 @@ sub checkchildren { &initnewstatus(); &logstatus(); &logthis('Going to check on the children'); + $docdir=$perlvar{'lonDocRoot'}; foreach (sort keys %children) { sleep 1; unless (kill 'USR1' => $_) { @@ -194,6 +207,18 @@ sub checkchildren { &logstatus($$.' is dead'); } } + sleep 5; + foreach (sort keys %children) { + unless (-e "$docdir/lon-status/londchld/$_.txt") { + &logthis('Child '.$_.' did not respond'); + kill 9 => $_; + $emailto="$perlvar{'lonAdmEMail'},$perlvar{'lonSysEMail'}"; + $subj="LON: $perlvar{'lonHostID'} killed lond process $_"; + my $result=`echo 'Killed lond process $_.' | mailto $emailto -s '$subj' > /dev/null`; + $execdir=$perlvar{'lonDaemons'}; + $result=`/bin/cp $execdir/logs/lond.log $execdir/logs/lond.log.$_` + } + } } # --------------------------------------------------------------------- Logging @@ -212,8 +237,16 @@ sub logthis { sub logstatus { my $docdir=$perlvar{'lonDocRoot'}; + { my $fh=IO::File->new(">>$docdir/lon-status/londstatus.txt"); print $fh $$."\t".$status."\t".$lastlog."\n"; + $fh->close(); + } + { + my $fh=IO::File->new(">$docdir/lon-status/londchld/$$.txt"); + print $fh $status."\n".$lastlog."\n".time; + $fh->close(); + } } sub initnewstatus { @@ -222,6 +255,11 @@ sub initnewstatus { my $now=time; my $local=localtime($now); print $fh "LOND status $local - parent $$\n\n"; + opendir(DIR,"$docdir/lon-status/londchld"); + while ($filename=readdir(DIR)) { + unlink("$docdir/lon-status/londchld/$filename"); + } + closedir(DIR); } # -------------------------------------------------------------- Status setting @@ -431,6 +469,7 @@ sub make_new_child { # Child can *not* return from this subroutine. $SIG{INT} = 'DEFAULT'; # make SIGINT kill us as it did before $SIG{USR1}= \&logstatus; + $SIG{ALRM}= \&timeout; $lastlog='Forked '; $status='Forked'; @@ -499,6 +538,7 @@ sub make_new_child { chomp($userinput); &status('Processing '.$hostid{$clientip}.': '.$userinput); my $wasenc=0; + alarm(120); # ------------------------------------------------------------ See if encrypted if ($userinput =~ /^enc/) { if ($cipher) { @@ -600,10 +640,13 @@ sub make_new_child { $pwdcorrect=!$?; } } elsif ($howpwd eq 'krb4') { + $null=pack("C",0); + unless ($upass=~/$null/) { $pwdcorrect=( Authen::Krb4::get_pw_in_tkt($uname,"", $contentpwd,'krbtgt',$contentpwd,1, $upass) == 0); + } else { $pwdcorrect=0; } } elsif ($howpwd eq 'localauth') { $pwdcorrect=&localauth::localauth($uname,$upass, $contentpwd); @@ -627,7 +670,8 @@ sub make_new_child { chomp($npass); $upass=&unescape($upass); $npass=&unescape($npass); - my $proname=propath($udom,$uname); + &logthis("Trying to change password for $uname"); + my $proname=propath($udom,$uname); my $passfilename="$proname/passwd"; if (-e $passfilename) { my $realpasswd; @@ -642,11 +686,42 @@ sub make_new_child { my $ncpass=crypt($npass,$salt); { my $pf = IO::File->new(">$passfilename"); print $pf "internal:$ncpass\n"; } + &logthis("Result of password change for $uname: pwchange_success"); print $client "ok\n"; } else { print $client "non_authorized\n"; } - } else { + } elsif ($howpwd eq 'unix') { + # Unix means we have to access /etc/password + # one way or another. + # First: Make sure the current password is + # correct + $contentpwd=(getpwnam($uname))[1]; + my $pwdcorrect = "0"; + my $pwauth_path="/usr/local/sbin/pwauth"; + unless ($contentpwd eq 'x') { + $pwdcorrect= + (crypt($upass,$contentpwd) eq $contentpwd); + } elsif (-e $pwauth_path) { + open PWAUTH, "|$pwauth_path" or + die "Cannot invoke authentication"; + print PWAUTH "$uname\n$upass\n"; + close PWAUTH; + $pwdcorrect=!$?; + } + if ($pwdcorrect) { + my $execdir=$perlvar{'lonDaemons'}; + my $pf = IO::File->new("|$execdir/lcpasswd"); + print $pf "$uname\n$npass\n$npass\n"; + close $pf; + my $result = ($?>0 ? 'pwchange_failure' + : 'ok'); + &logthis("Result of password change for $uname: $result"); + print $client "$result\n"; + } else { + print $client "non_authorized\n"; + } + } else { print $client "auth_mode_error\n"; } } else { @@ -677,7 +752,7 @@ sub make_new_child { $fpnow.='/'.$fpparts[$i]; unless (-e $fpnow) { unless (mkdir($fpnow,0777)) { - $fperror="error:$!\n"; + $fperror="error:$!"; } } } @@ -1335,6 +1410,7 @@ sub make_new_child { print $client "unknown_cmd\n"; } # -------------------------------------------------------------------- complete + alarm(0); &status('Listening to '.$hostid{$clientip}); } # --------------------------------------------- client unknown or fishy, refuse