--- loncom/lond 2000/09/25 20:22:58 1.21 +++ loncom/lond 2001/11/16 06:19:33 1.55 @@ -8,7 +8,19 @@ # 03/07,05/31 Gerd Kortemeyer # 06/26 Scott Harrison # 06/29,06/30,07/14,07/15,07/17,07/20,07/25,09/18 Gerd Kortemeyer +# 12/05 Scott Harrison +# 12/05,12/13,12/29 Gerd Kortemeyer +# Jan 01 Scott Harrison +# 02/12 Gerd Kortemeyer +# 03/15 Scott Harrison +# 03/24 Gerd Kortemeyer +# 04/02 Scott Harrison +# 05/11,05/28,08/30 Gerd Kortemeyer +# 9/30,10/22,11/13,11/15 Scott Harrison # +# $Id: lond,v 1.55 2001/11/16 06:19:33 harris41 Exp $ +### + # based on "Perl Cookbook" ISBN 1-56592-243-3 # preforker - server who forks first # runs as a daemon @@ -24,6 +36,25 @@ use Crypt::IDEA; use LWP::UserAgent(); use GDBM_File; use Authen::Krb4; +use lib '/home/httpd/lib/perl/'; +use localauth; + +# grabs exception and records it to log before exiting +sub catchexception { + my ($error)=@_; + $SIG{'QUIT'}='DEFAULT'; + $SIG{__DIE__}='DEFAULT'; + &logthis("CRITICAL: " + ."ABNORMAL EXIT. Child $$ for server $wasserver died through " + ."a crash with this error msg->[$error]"); + if ($client) { print $client "error: $error\n"; } + die($error); +} + +# -------------------------------- Set signal handlers to record abnormal exits + +$SIG{'QUIT'}=\&catchexception; +$SIG{__DIE__}=\&catchexception; # ------------------------------------ Read httpd access.conf and get variables @@ -38,6 +69,16 @@ while ($configline=) { } close(CONFIG); +# ----------------------------- Make sure this process is running from user=www +my $wwwid=getpwnam('www'); +if ($wwwid!=$<) { + $emailto="$perlvar{'lonAdmEMail'},$perlvar{'lonSysEMail'}"; + $subj="LON: $perlvar{'lonHostID'} User ID mismatch"; + system("echo 'User ID mismatch. lond must be run as user www.' |\ + mailto $emailto -s '$subj' > /dev/null"); + exit 1; +} + # --------------------------------------------- Check if other instance running my $pidfile="$perlvar{'lonDaemons'}/logs/lond.pid"; @@ -103,6 +144,7 @@ sub HUPSMAN { # sig kill 'INT' => keys %children; close($server); # free up socket &logthis("CRITICAL: Restarting"); + unlink("$execdir/logs/lond.pid"); my $execdir=$perlvar{'lonDaemons'}; exec("$execdir/lond"); # here we go again } @@ -328,7 +370,8 @@ sub make_new_child { my $clientip=inet_ntoa($iaddr); my $clientrec=($hostid{$clientip} ne undef); &logthis( -"INFO: Connect from $clientip ($hostid{$clientip})"); +"INFO: Connection $i, $clientip ($hostid{$clientip})" + ); my $clientok; if ($clientrec) { my $remotereq=<$client>; @@ -413,6 +456,28 @@ sub make_new_child { $loadavg =~ s/\s.*//g; my $loadpercent=100*$loadavg/$perlvar{'lonLoadLim'}; print $client "$loadpercent\n"; +# ----------------------------------------------------------------- currentauth + } elsif ($userinput =~ /^currentauth/) { + if ($wasenc==1) { + my ($cmd,$udom,$uname)=split(/:/,$userinput); + my $proname=propath($udom,$uname); + my $passfilename="$proname/passwd"; + if (-e $passfilename) { + my $pf = IO::File->new($passfilename); + my $realpasswd=<$pf>; + chomp($realpasswd); + my ($howpwd,$contentpwd)=split(/:/,$realpasswd); + my $availablecontent=''; + if ($howpwd eq 'krb4') { + $availablecontent=$contentpwd; + } + print $client "$howpwd:$availablecontent\n"; + } else { + print $client "unknown_user\n"; + } + } else { + print $client "refused\n"; + } # ------------------------------------------------------------------------ auth } elsif ($userinput =~ /^auth/) { if ($wasenc==1) { @@ -432,14 +497,27 @@ sub make_new_child { (crypt($upass,$contentpwd) eq $contentpwd); } elsif ($howpwd eq 'unix') { $contentpwd=(getpwnam($uname))[1]; - $pwdcorrect= - (crypt($upass,$contentpwd) eq $contentpwd); + 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=!$?; + } } elsif ($howpwd eq 'krb4') { $pwdcorrect=( Authen::Krb4::get_pw_in_tkt($uname,"", $contentpwd,'krbtgt',$contentpwd,1, $upass) == 0); - } + } elsif ($howpwd eq 'localauth') { + $pwdcorrect=&localauth::localauth($uname,$upass, + $contentpwd); + } if ($pwdcorrect) { print $client "authorized\n"; } else { @@ -457,6 +535,8 @@ sub make_new_child { my ($cmd,$udom,$uname,$upass,$npass)=split(/:/,$userinput); chomp($npass); + $upass=&unescape($upass); + $npass=&unescape($npass); my $proname=propath($udom,$uname); my $passfilename="$proname/passwd"; if (-e $passfilename) { @@ -471,7 +551,7 @@ sub make_new_child { $salt=substr($salt,6,2); my $ncpass=crypt($npass,$salt); { my $pf = IO::File->new(">$passfilename"); - print $pf "internal:$ncpass\n";; } + print $pf "internal:$ncpass\n"; } print $client "ok\n"; } else { print $client "non_authorized\n"; @@ -485,6 +565,143 @@ sub make_new_child { } else { print $client "refused\n"; } +# -------------------------------------------------------------------- makeuser + } elsif ($userinput =~ /^makeuser/) { + if ($wasenc==1) { + my + ($cmd,$udom,$uname,$umode,$npass)=split(/:/,$userinput); + chomp($npass); + $npass=&unescape($npass); + my $proname=propath($udom,$uname); + my $passfilename="$proname/passwd"; + if (-e $passfilename) { + print $client "already_exists\n"; + } elsif ($udom ne $perlvar{'lonDefDomain'}) { + print $client "not_right_domain\n"; + } else { + @fpparts=split(/\//,$proname); + $fpnow=$fpparts[0].'/'.$fpparts[1].'/'.$fpparts[2]; + $fperror=''; + for ($i=3;$i<=$#fpparts;$i++) { + $fpnow.='/'.$fpparts[$i]; + unless (-e $fpnow) { + unless (mkdir($fpnow,0777)) { + $fperror="error:$!\n"; + } + } + } + unless ($fperror) { + if ($umode eq 'krb4') { + { + my $pf = IO::File->new(">$passfilename"); + print $pf "krb4:$npass\n"; + } + print $client "ok\n"; + } elsif ($umode eq 'internal') { + my $salt=time; + $salt=substr($salt,6,2); + my $ncpass=crypt($npass,$salt); + { + my $pf = IO::File->new(">$passfilename"); + print $pf "internal:$ncpass\n"; + } + print $client "ok\n"; + } elsif ($umode eq 'localauth') { + { + my $pf = IO::File->new(">$passfilename"); + print $pf "localauth:$npass\n"; + } + print $client "ok\n"; + } elsif ($umode eq 'unix') { + { + my $execpath="$perlvar{'lonDaemons'}/". + "lcuseradd"; + { + my $se = IO::File->new("|$execpath"); + print $se "$uname\n"; + print $se "$npass\n"; + print $se "$npass\n"; + } + my $pf = IO::File->new(">$passfilename"); + print $pf "unix:\n"; + } + print $client "ok\n"; + } elsif ($umode eq 'none') { + { + my $pf = IO::File->new(">$passfilename"); + print $pf "none:\n"; + } + print $client "ok\n"; + } else { + print $client "auth_mode_error\n"; + } + } else { + print $client "$fperror\n"; + } + } + } else { + print $client "refused\n"; + } +# -------------------------------------------------------------- changeuserauth + } elsif ($userinput =~ /^changeuserauth/) { + if ($wasenc==1) { + my + ($cmd,$udom,$uname,$umode,$npass)=split(/:/,$userinput); + chomp($npass); + $npass=&unescape($npass); + my $proname=propath($udom,$uname); + my $passfilename="$proname/passwd"; + if ($udom ne $perlvar{'lonDefDomain'}) { + print $client "not_right_domain\n"; + } else { + if ($umode eq 'krb4') { + { + my $pf = IO::File->new(">$passfilename"); + print $pf "krb4:$npass\n"; + } + print $client "ok\n"; + } elsif ($umode eq 'internal') { + my $salt=time; + $salt=substr($salt,6,2); + my $ncpass=crypt($npass,$salt); + { + my $pf = IO::File->new(">$passfilename"); + print $pf "internal:$ncpass\n"; + } + print $client "ok\n"; + } elsif ($umode eq 'localauth') { + { + my $pf = IO::File->new(">$passfilename"); + print $pf "localauth:$npass\n"; + } + print $client "ok\n"; + } elsif ($umode eq 'unix') { + { + my $execpath="$perlvar{'lonDaemons'}/". + "lcuseradd"; + { + my $se = IO::File->new("|$execpath"); + print $se "$uname\n"; + print $se "$npass\n"; + print $se "$npass\n"; + } + my $pf = IO::File->new(">$passfilename"); + print $pf "unix:\n"; + } + print $client "ok\n"; + } elsif ($umode eq 'none') { + { + my $pf = IO::File->new(">$passfilename"); + print $pf "none:\n"; + } + print $client "ok\n"; + } else { + print $client "auth_mode_error\n"; + } + } + } else { + print $client "refused\n"; + } # ------------------------------------------------------------------------ home } elsif ($userinput =~ /^home/) { my ($cmd,$udom,$uname)=split(/:/,$userinput); @@ -522,12 +739,13 @@ sub make_new_child { $response=$ua->request($request,$transname); } if ($response->is_error()) { - unline($transname); + unlink($transname); my $message=$response->status_line; &logthis( "LWP GET: $message for $fname ($remoteurl)"); } else { if ($remoteurl!~/\.meta$/) { + my $ua=new LWP::UserAgent; my $mrequest= new HTTP::Request('GET',$remoteurl.'.meta'); my $mresponse= @@ -569,9 +787,15 @@ sub make_new_child { } else { $now=time; { - my $sh=IO::File->new(">$fname.$hostid{$clientip}"); - print $sh "$clientip:$now\n"; + my $sh; + if ($sh= + IO::File->new(">$fname.$hostid{$clientip}")) { + print $sh "$clientip:$now\n"; + } } + unless ($fname=~/\.meta$/) { + unlink("$fname.meta.$hostid{$clientip}"); + } $fname=~s/\/home\/httpd\/html\/res/raw/; $fname="http://$thisserver/".$fname; print $client "$fname\n"; @@ -607,7 +831,7 @@ sub make_new_child { chomp($what); my $proname=propath($udom,$uname); my $now=time; - { + unless ($namespace=~/^nohist\_/) { my $hfh; if ( $hfh=IO::File->new(">>$proname/$namespace.hist") @@ -732,7 +956,7 @@ sub make_new_child { chomp($what); my $proname=propath($udom,$uname); my $now=time; - { + unless ($namespace=~/^nohist\_/) { my $hfh; if ( $hfh=IO::File->new(">>$proname/$namespace.hist") @@ -803,7 +1027,7 @@ sub make_new_child { chomp($what); my $proname=propath($udom,$uname); my $now=time; - { + unless ($namespace=~/^nohist\_/) { my $hfh; if ( $hfh=IO::File->new(">>$proname/$namespace.hist") @@ -822,7 +1046,8 @@ sub make_new_child { $allkeys.=$key.':'; $hash{"$version:$rid:$key"}=$value; } - $allkeys=~s/:$//; + $hash{"$version:$rid:timestamp"}=$now; + $allkeys.='timestamp'; $hash{"$version:keys:$rid"}=$allkeys; if (untie(%hash)) { print $client "ok\n"; @@ -868,17 +1093,30 @@ sub make_new_child { } # ------------------------------------------------------------------- querysend } elsif ($userinput =~ /^querysend/) { - my ($cmd,$query)=split(/:/,$userinput); + my ($cmd,$query, + $custom,$customshow)=split(/:/,$userinput); $query=~s/\n*$//g; - print $client sqlreply("$hostid{$clientip}\&$query")."\n"; + unless ($custom or $customshow) { + print $client "". + sqlreply("$hostid{$clientip}\&$query")."\n"; + } + else { + print $client "". + sqlreply("$hostid{$clientip}\&$query". + "\&$custom"."\&$customshow")."\n"; + } # ------------------------------------------------------------------ queryreply } elsif ($userinput =~ /^queryreply/) { my ($cmd,$id,$reply)=split(/:/,$userinput); my $store; my $execdir=$perlvar{'lonDaemons'}; if ($store=IO::File->new(">$execdir/tmp/$id")) { + $reply=~s/\&/\n/g; print $store $reply; close $store; + my $store2=IO::File->new(">$execdir/tmp/$id.end"); + print $store2 "done\n"; + close $store2; print $client "ok\n"; } else { @@ -972,15 +1210,25 @@ sub make_new_child { my $ulsout=''; my $ulsfn; if (-e $ulsdir) { - while ($ulsfn=<$ulsdir/*>) { - my @ulsstats=stat($ulsfn); + if (opendir(LSDIR,$ulsdir)) { + while ($ulsfn=readdir(LSDIR)) { + my @ulsstats=stat($ulsdir.'/'.$ulsfn); $ulsout.=$ulsfn.'&'.join('&',@ulsstats).':'; } + closedir(LSDIR); + } } else { $ulsout='no_such_dir'; } if ($ulsout eq '') { $ulsout='empty'; } print $client "$ulsout\n"; +# ------------------------------------------------------------------ Hanging up + } elsif (($userinput =~ /^exit/) || + ($userinput =~ /^init/)) { + &logthis( + "Client $clientip ($hostid{$clientip}) hanging up: $userinput"); + print $client "bye\n"; + last; # ------------------------------------------------------------- unknown command } else { # unknown command