version 1.20, 2000/09/18 14:57:43
|
version 1.72, 2002/02/19 21:52:54
|
Line 1
|
Line 1
|
#!/usr/bin/perl |
#!/usr/bin/perl |
# The LearningOnline Network |
# The LearningOnline Network |
# lond "LON Daemon" Server (port "LOND" 5663) |
# lond "LON Daemon" Server (port "LOND" 5663) |
|
# |
|
# $Id$ |
|
# |
|
# Copyright Michigan State University Board of Trustees |
|
# |
|
# This file is part of the LearningOnline Network with CAPA (LON-CAPA). |
|
# |
|
# LON-CAPA is free software; you can redistribute it and/or modify |
|
# it under the terms of the GNU General Public License as published by |
|
# the Free Software Foundation; either version 2 of the License, or |
|
# (at your option) any later version. |
|
# |
|
# LON-CAPA is distributed in the hope that it will be useful, |
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
# GNU General Public License for more details. |
|
# |
|
# You should have received a copy of the GNU General Public License |
|
# along with LON-CAPA; if not, write to the Free Software |
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
# |
|
# /home/httpd/html/adm/gpl.txt |
|
# |
|
# http://www.lon-capa.org/ |
|
# |
# 5/26/99,6/4,6/10,6/11,6/14,6/15,6/26,6/28,6/30, |
# 5/26/99,6/4,6/10,6/11,6/14,6/15,6/26,6/28,6/30, |
# 7/8,7/9,7/10,7/12,7/17,7/19,9/21, |
# 7/8,7/9,7/10,7/12,7/17,7/19,9/21, |
# 10/7,10/8,10/9,10/11,10/13,10/15,11/4,11/16, |
# 10/7,10/8,10/9,10/11,10/13,10/15,11/4,11/16, |
Line 8
|
Line 33
|
# 03/07,05/31 Gerd Kortemeyer |
# 03/07,05/31 Gerd Kortemeyer |
# 06/26 Scott Harrison |
# 06/26 Scott Harrison |
# 06/29,06/30,07/14,07/15,07/17,07/20,07/25,09/18 Gerd Kortemeyer |
# 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 |
|
# YEAR=2001 |
|
# 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,11/16 Scott Harrison |
|
# 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 |
# based on "Perl Cookbook" ISBN 1-56592-243-3 |
# preforker - server who forks first |
# preforker - server who forks first |
# runs as a daemon |
# runs as a daemon |
Line 24 use Crypt::IDEA;
|
Line 68 use Crypt::IDEA;
|
use LWP::UserAgent(); |
use LWP::UserAgent(); |
use GDBM_File; |
use GDBM_File; |
use Authen::Krb4; |
use Authen::Krb4; |
|
use lib '/home/httpd/lib/perl/'; |
|
use localauth; |
|
|
|
my $status=''; |
|
my $lastlog=''; |
|
|
|
# grabs exception and records it to log before exiting |
|
sub catchexception { |
|
my ($error)=@_; |
|
$SIG{'QUIT'}='DEFAULT'; |
|
$SIG{__DIE__}='DEFAULT'; |
|
&logthis("<font color=red>CRITICAL: " |
|
."ABNORMAL EXIT. Child $$ for server $wasserver died through " |
|
."a crash with this error msg->[$error]</font>"); |
|
&logthis('Famous last words: '.$status.' - '.$lastlog); |
|
if ($client) { print $client "error: $error\n"; } |
|
$server->close(); |
|
die($error); |
|
} |
|
|
|
sub timeout { |
|
&logthis("<font color=ref>CRITICAL: TIME OUT ".$$."</font>"); |
|
&catchexception('Timeout'); |
|
} |
|
# -------------------------------- Set signal handlers to record abnormal exits |
|
|
|
$SIG{'QUIT'}=\&catchexception; |
|
$SIG{__DIE__}=\&catchexception; |
|
|
# ------------------------------------ Read httpd access.conf and get variables |
# ------------------------------------ Read httpd access.conf and get variables |
|
|
Line 38 while ($configline=<CONFIG>) {
|
Line 110 while ($configline=<CONFIG>) {
|
} |
} |
close(CONFIG); |
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 |
# --------------------------------------------- Check if other instance running |
|
|
my $pidfile="$perlvar{'lonDaemons'}/logs/lond.pid"; |
my $pidfile="$perlvar{'lonDaemons'}/logs/lond.pid"; |
Line 57 open (CONFIG,"$perlvar{'lonTabDir'}/host
|
Line 139 open (CONFIG,"$perlvar{'lonTabDir'}/host
|
|
|
while ($configline=<CONFIG>) { |
while ($configline=<CONFIG>) { |
my ($id,$domain,$role,$name,$ip)=split(/:/,$configline); |
my ($id,$domain,$role,$name,$ip)=split(/:/,$configline); |
chomp($ip); |
chomp($ip); $ip=~s/\D+$//; |
$hostid{$ip}=$id; |
$hostid{$ip}=$id; |
if ($id eq $perlvar{'lonHostID'}) { $thisserver=$name; } |
if ($id eq $perlvar{'lonHostID'}) { $thisserver=$name; } |
$PREFORK++; |
$PREFORK++; |
Line 84 $children = 0; # cu
|
Line 166 $children = 0; # cu
|
sub REAPER { # takes care of dead children |
sub REAPER { # takes care of dead children |
$SIG{CHLD} = \&REAPER; |
$SIG{CHLD} = \&REAPER; |
my $pid = wait; |
my $pid = wait; |
$children --; |
if (defined($children{$pid})) { |
&logthis("Child $pid died"); |
&logthis("Child $pid died"); |
delete $children{$pid}; |
$children --; |
|
delete $children{$pid}; |
|
} else { |
|
&logthis("Unknown Child $pid died"); |
|
} |
} |
} |
|
|
sub HUNTSMAN { # signal handler for SIGINT |
sub HUNTSMAN { # signal handler for SIGINT |
local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children |
local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children |
kill 'INT' => keys %children; |
kill 'INT' => keys %children; |
|
&logthis("Free socket: ".shutdown($server,2)); # free up socket |
my $execdir=$perlvar{'lonDaemons'}; |
my $execdir=$perlvar{'lonDaemons'}; |
unlink("$execdir/logs/lond.pid"); |
unlink("$execdir/logs/lond.pid"); |
&logthis("<font color=red>CRITICAL: Shutting down</font>"); |
&logthis("<font color=red>CRITICAL: Shutting down</font>"); |
Line 101 sub HUNTSMAN { # si
|
Line 188 sub HUNTSMAN { # si
|
sub HUPSMAN { # signal handler for SIGHUP |
sub HUPSMAN { # signal handler for SIGHUP |
local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children |
local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children |
kill 'INT' => keys %children; |
kill 'INT' => keys %children; |
close($server); # free up socket |
&logthis("Free socket: ".shutdown($server,2)); # free up socket |
&logthis("<font color=red>CRITICAL: Restarting</font>"); |
&logthis("<font color=red>CRITICAL: Restarting</font>"); |
|
unlink("$execdir/logs/lond.pid"); |
my $execdir=$perlvar{'lonDaemons'}; |
my $execdir=$perlvar{'lonDaemons'}; |
exec("$execdir/lond"); # here we go again |
exec("$execdir/lond"); # here we go again |
} |
} |
|
|
|
sub checkchildren { |
|
&initnewstatus(); |
|
&logstatus(); |
|
&logthis('Going to check on the children'); |
|
$docdir=$perlvar{'lonDocRoot'}; |
|
foreach (sort keys %children) { |
|
sleep 1; |
|
unless (kill 'USR1' => $_) { |
|
&logthis ('Child '.$_.' is dead'); |
|
&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 |
# --------------------------------------------------------------------- Logging |
|
|
sub logthis { |
sub logthis { |
Line 115 sub logthis {
|
Line 229 sub logthis {
|
my $fh=IO::File->new(">>$execdir/logs/lond.log"); |
my $fh=IO::File->new(">>$execdir/logs/lond.log"); |
my $now=time; |
my $now=time; |
my $local=localtime($now); |
my $local=localtime($now); |
|
$lastlog=$local.': '.$message; |
print $fh "$local ($$): $message\n"; |
print $fh "$local ($$): $message\n"; |
} |
} |
|
|
|
# ------------------------------------------------------------------ Log status |
|
|
|
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 { |
|
my $docdir=$perlvar{'lonDocRoot'}; |
|
my $fh=IO::File->new(">$docdir/lon-status/londstatus.txt"); |
|
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 |
|
|
|
sub status { |
|
my $what=shift; |
|
my $now=time; |
|
my $local=localtime($now); |
|
$status=$local.': '.$what; |
|
} |
|
|
# -------------------------------------------------------- Escape Special Chars |
# -------------------------------------------------------- Escape Special Chars |
|
|
Line 264 open (PIDSAVE,">$execdir/logs/lond.pid")
|
Line 416 open (PIDSAVE,">$execdir/logs/lond.pid")
|
print PIDSAVE "$$\n"; |
print PIDSAVE "$$\n"; |
close(PIDSAVE); |
close(PIDSAVE); |
&logthis("<font color=red>CRITICAL: ---------- Starting ----------</font>"); |
&logthis("<font color=red>CRITICAL: ---------- Starting ----------</font>"); |
|
&status('Starting'); |
|
|
# ------------------------------------------------------- Now we are on our own |
# ------------------------------------------------------- Now we are on our own |
|
|
Line 274 for (1 .. $PREFORK) {
|
Line 427 for (1 .. $PREFORK) {
|
|
|
# ----------------------------------------------------- Install signal handlers |
# ----------------------------------------------------- Install signal handlers |
|
|
|
&status('Forked children'); |
|
|
$SIG{CHLD} = \&REAPER; |
$SIG{CHLD} = \&REAPER; |
$SIG{INT} = $SIG{TERM} = \&HUNTSMAN; |
$SIG{INT} = $SIG{TERM} = \&HUNTSMAN; |
$SIG{HUP} = \&HUPSMAN; |
$SIG{HUP} = \&HUPSMAN; |
|
$SIG{USR1} = \&checkchildren; |
|
|
# And maintain the population. |
# And maintain the population. |
while (1) { |
while (1) { |
|
&status('Sleeping'); |
sleep; # wait for a signal (i.e., child's death) |
sleep; # wait for a signal (i.e., child's death) |
|
&logthis('Woke up'); |
|
&status('Woke up'); |
for ($i = $children; $i < $PREFORK; $i++) { |
for ($i = $children; $i < $PREFORK; $i++) { |
make_new_child(); # top up the child pool |
make_new_child(); # top up the child pool |
} |
} |
Line 304 sub make_new_child {
|
Line 463 sub make_new_child {
|
or die "Can't unblock SIGINT for fork: $!\n"; |
or die "Can't unblock SIGINT for fork: $!\n"; |
$children{$pid} = 1; |
$children{$pid} = 1; |
$children++; |
$children++; |
|
&status('Started child '.$pid); |
return; |
return; |
} else { |
} else { |
# Child can *not* return from this subroutine. |
# Child can *not* return from this subroutine. |
$SIG{INT} = 'DEFAULT'; # make SIGINT kill us as it did before |
$SIG{INT} = 'DEFAULT'; # make SIGINT kill us as it did before |
|
$SIG{USR1}= \&logstatus; |
|
$SIG{ALRM}= \&timeout; |
|
$lastlog='Forked '; |
|
$status='Forked'; |
|
|
# unblock signals |
# unblock signals |
sigprocmask(SIG_UNBLOCK, $sigset) |
sigprocmask(SIG_UNBLOCK, $sigset) |
or die "Can't unblock SIGINT for fork: $!\n"; |
or die "Can't unblock SIGINT for fork: $!\n"; |
Line 317 sub make_new_child {
|
Line 481 sub make_new_child {
|
|
|
# handle connections until we've reached $MAX_CLIENTS_PER_CHILD |
# handle connections until we've reached $MAX_CLIENTS_PER_CHILD |
for ($i=0; $i < $MAX_CLIENTS_PER_CHILD; $i++) { |
for ($i=0; $i < $MAX_CLIENTS_PER_CHILD; $i++) { |
|
&status('Idle, waiting for connection'); |
$client = $server->accept() or last; |
$client = $server->accept() or last; |
|
&status('Accepted connection'); |
# ============================================================================= |
# ============================================================================= |
# do something with the connection |
# do something with the connection |
# ----------------------------------------------------------------------------- |
# ----------------------------------------------------------------------------- |
Line 328 sub make_new_child {
|
Line 493 sub make_new_child {
|
my $clientip=inet_ntoa($iaddr); |
my $clientip=inet_ntoa($iaddr); |
my $clientrec=($hostid{$clientip} ne undef); |
my $clientrec=($hostid{$clientip} ne undef); |
&logthis( |
&logthis( |
"<font color=yellow>INFO: Connect from $clientip ($hostid{$clientip})</font>"); |
"<font color=yellow>INFO: Connection $i, $clientip ($hostid{$clientip})</font>" |
|
); |
|
&status("Connecting $clientip ($hostid{$clientip})"); |
my $clientok; |
my $clientok; |
if ($clientrec) { |
if ($clientrec) { |
|
&status("Waiting for init from $clientip ($hostid{$clientip})"); |
my $remotereq=<$client>; |
my $remotereq=<$client>; |
$remotereq=~s/\W//g; |
$remotereq=~s/\W//g; |
if ($remotereq eq 'init') { |
if ($remotereq eq 'init') { |
my $challenge="$$".time; |
my $challenge="$$".time; |
print $client "$challenge\n"; |
print $client "$challenge\n"; |
|
&status( |
|
"Waiting for challenge reply from $clientip ($hostid{$clientip})"); |
$remotereq=<$client>; |
$remotereq=<$client>; |
$remotereq=~s/\W//g; |
$remotereq=~s/\W//g; |
if ($challenge eq $remotereq) { |
if ($challenge eq $remotereq) { |
Line 344 sub make_new_child {
|
Line 514 sub make_new_child {
|
} else { |
} else { |
&logthis( |
&logthis( |
"<font color=blue>WARNING: $clientip did not reply challenge</font>"); |
"<font color=blue>WARNING: $clientip did not reply challenge</font>"); |
print $client "bye\n"; |
&status('No challenge reply '.$clientip); |
} |
} |
} else { |
} else { |
&logthis( |
&logthis( |
"<font color=blue>WARNING: " |
"<font color=blue>WARNING: " |
."$clientip failed to initialize: >$remotereq< </font>"); |
."$clientip failed to initialize: >$remotereq< </font>"); |
print $client "bye\n"; |
&status('No init '.$clientip); |
} |
} |
} else { |
} else { |
&logthis( |
&logthis( |
"<font color=blue>WARNING: Unknown client $clientip</font>"); |
"<font color=blue>WARNING: Unknown client $clientip</font>"); |
print $client "bye\n"; |
&status('Hung up on '.$clientip); |
} |
} |
if ($clientok) { |
if ($clientok) { |
# ---------------- New known client connecting, could mean machine online again |
# ---------------- New known client connecting, could mean machine online again |
&reconlonc("$perlvar{'lonSockDir'}/$hostid{$clientip}"); |
&reconlonc("$perlvar{'lonSockDir'}/$hostid{$clientip}"); |
&logthis( |
&logthis( |
"<font color=green>Established connection: $hostid{$clientip}</font>"); |
"<font color=green>Established connection: $hostid{$clientip}</font>"); |
|
&status('Will listen to '.$hostid{$clientip}); |
# ------------------------------------------------------------ Process requests |
# ------------------------------------------------------------ Process requests |
while (my $userinput=<$client>) { |
while (my $userinput=<$client>) { |
chomp($userinput); |
chomp($userinput); |
|
&status('Processing '.$hostid{$clientip}.': '.$userinput); |
my $wasenc=0; |
my $wasenc=0; |
|
alarm(120); |
# ------------------------------------------------------------ See if encrypted |
# ------------------------------------------------------------ See if encrypted |
if ($userinput =~ /^enc/) { |
if ($userinput =~ /^enc/) { |
if ($cipher) { |
if ($cipher) { |
Line 413 sub make_new_child {
|
Line 586 sub make_new_child {
|
$loadavg =~ s/\s.*//g; |
$loadavg =~ s/\s.*//g; |
my $loadpercent=100*$loadavg/$perlvar{'lonLoadLim'}; |
my $loadpercent=100*$loadavg/$perlvar{'lonLoadLim'}; |
print $client "$loadpercent\n"; |
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 |
# ------------------------------------------------------------------------ auth |
} elsif ($userinput =~ /^auth/) { |
} elsif ($userinput =~ /^auth/) { |
if ($wasenc==1) { |
if ($wasenc==1) { |
Line 432 sub make_new_child {
|
Line 627 sub make_new_child {
|
(crypt($upass,$contentpwd) eq $contentpwd); |
(crypt($upass,$contentpwd) eq $contentpwd); |
} elsif ($howpwd eq 'unix') { |
} elsif ($howpwd eq 'unix') { |
$contentpwd=(getpwnam($uname))[1]; |
$contentpwd=(getpwnam($uname))[1]; |
$pwdcorrect= |
my $pwauth_path="/usr/local/sbin/pwauth"; |
(crypt($upass,$contentpwd) eq $contentpwd); |
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') { |
} elsif ($howpwd eq 'krb4') { |
|
$null=pack("C",0); |
|
unless ($upass=~/$null/) { |
$pwdcorrect=( |
$pwdcorrect=( |
Authen::Krb4::get_pw_in_tkt($uname,"", |
Authen::Krb4::get_pw_in_tkt($uname,"", |
$contentpwd,'krbtgt',$contentpwd,1, |
$contentpwd,'krbtgt',$contentpwd,1, |
$upass) == 0); |
$upass) == 0); |
} |
} else { $pwdcorrect=0; } |
|
} elsif ($howpwd eq 'localauth') { |
|
$pwdcorrect=&localauth::localauth($uname,$upass, |
|
$contentpwd); |
|
} |
if ($pwdcorrect) { |
if ($pwdcorrect) { |
print $client "authorized\n"; |
print $client "authorized\n"; |
} else { |
} else { |
Line 457 sub make_new_child {
|
Line 668 sub make_new_child {
|
my |
my |
($cmd,$udom,$uname,$upass,$npass)=split(/:/,$userinput); |
($cmd,$udom,$uname,$upass,$npass)=split(/:/,$userinput); |
chomp($npass); |
chomp($npass); |
my $proname=propath($udom,$uname); |
$upass=&unescape($upass); |
|
$npass=&unescape($npass); |
|
&logthis("Trying to change password for $uname"); |
|
my $proname=propath($udom,$uname); |
my $passfilename="$proname/passwd"; |
my $passfilename="$proname/passwd"; |
if (-e $passfilename) { |
if (-e $passfilename) { |
my $realpasswd; |
my $realpasswd; |
Line 471 sub make_new_child {
|
Line 685 sub make_new_child {
|
$salt=substr($salt,6,2); |
$salt=substr($salt,6,2); |
my $ncpass=crypt($npass,$salt); |
my $ncpass=crypt($npass,$salt); |
{ my $pf = IO::File->new(">$passfilename"); |
{ my $pf = IO::File->new(">$passfilename"); |
print $pf "internal:$ncpass\n";; } |
print $pf "internal:$ncpass\n"; } |
|
&logthis("Result of password change for $uname: pwchange_success"); |
print $client "ok\n"; |
print $client "ok\n"; |
} else { |
} else { |
print $client "non_authorized\n"; |
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"; |
print $client "auth_mode_error\n"; |
} |
} |
} else { |
} else { |
Line 485 sub make_new_child {
|
Line 730 sub make_new_child {
|
} else { |
} else { |
print $client "refused\n"; |
print $client "refused\n"; |
} |
} |
|
# -------------------------------------------------------------------- makeuser |
|
} elsif ($userinput =~ /^makeuser/) { |
|
my $oldumask=umask(0077); |
|
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:$!"; |
|
} |
|
} |
|
} |
|
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"; |
|
} |
|
umask($oldumask); |
|
# -------------------------------------------------------------- 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 |
# ------------------------------------------------------------------------ home |
} elsif ($userinput =~ /^home/) { |
} elsif ($userinput =~ /^home/) { |
my ($cmd,$udom,$uname)=split(/:/,$userinput); |
my ($cmd,$udom,$uname)=split(/:/,$userinput); |
Line 522 sub make_new_child {
|
Line 906 sub make_new_child {
|
$response=$ua->request($request,$transname); |
$response=$ua->request($request,$transname); |
} |
} |
if ($response->is_error()) { |
if ($response->is_error()) { |
unline($transname); |
unlink($transname); |
my $message=$response->status_line; |
my $message=$response->status_line; |
&logthis( |
&logthis( |
"LWP GET: $message for $fname ($remoteurl)"); |
"LWP GET: $message for $fname ($remoteurl)"); |
} else { |
} else { |
if ($remoteurl!~/\.meta$/) { |
if ($remoteurl!~/\.meta$/) { |
|
my $ua=new LWP::UserAgent; |
my $mrequest= |
my $mrequest= |
new HTTP::Request('GET',$remoteurl.'.meta'); |
new HTTP::Request('GET',$remoteurl.'.meta'); |
my $mresponse= |
my $mresponse= |
Line 569 sub make_new_child {
|
Line 954 sub make_new_child {
|
} else { |
} else { |
$now=time; |
$now=time; |
{ |
{ |
my $sh=IO::File->new(">$fname.$hostid{$clientip}"); |
my $sh; |
print $sh "$clientip:$now\n"; |
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=~s/\/home\/httpd\/html\/res/raw/; |
$fname="http://$thisserver/".$fname; |
$fname="http://$thisserver/".$fname; |
print $client "$fname\n"; |
print $client "$fname\n"; |
Line 607 sub make_new_child {
|
Line 998 sub make_new_child {
|
chomp($what); |
chomp($what); |
my $proname=propath($udom,$uname); |
my $proname=propath($udom,$uname); |
my $now=time; |
my $now=time; |
{ |
unless ($namespace=~/^nohist\_/) { |
my $hfh; |
my $hfh; |
if ( |
if ( |
$hfh=IO::File->new(">>$proname/$namespace.hist") |
$hfh=IO::File->new(">>$proname/$namespace.hist") |
Line 732 sub make_new_child {
|
Line 1123 sub make_new_child {
|
chomp($what); |
chomp($what); |
my $proname=propath($udom,$uname); |
my $proname=propath($udom,$uname); |
my $now=time; |
my $now=time; |
{ |
unless ($namespace=~/^nohist\_/) { |
my $hfh; |
my $hfh; |
if ( |
if ( |
$hfh=IO::File->new(">>$proname/$namespace.hist") |
$hfh=IO::File->new(">>$proname/$namespace.hist") |
Line 774 sub make_new_child {
|
Line 1165 sub make_new_child {
|
} |
} |
# ------------------------------------------------------------------------ dump |
# ------------------------------------------------------------------------ dump |
} elsif ($userinput =~ /^dump/) { |
} elsif ($userinput =~ /^dump/) { |
my ($cmd,$udom,$uname,$namespace) |
my ($cmd,$udom,$uname,$namespace,$regexp) |
=split(/:/,$userinput); |
=split(/:/,$userinput); |
$namespace=~s/\//\_/g; |
$namespace=~s/\//\_/g; |
$namespace=~s/\W//g; |
$namespace=~s/\W//g; |
|
if (defined($regexp)) { |
|
$regexp=&unescape($regexp); |
|
} else { |
|
$regexp='.'; |
|
} |
my $proname=propath($udom,$uname); |
my $proname=propath($udom,$uname); |
my $qresult=''; |
my $qresult=''; |
if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_READER,0640)) { |
if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_READER,0640)) { |
foreach $key (keys %hash) { |
foreach $key (keys %hash) { |
$qresult.="$key=$hash{$key}&"; |
if (eval('$key=~/$regexp/')) { |
|
$qresult.="$key=$hash{$key}&"; |
|
} |
} |
} |
if (untie(%hash)) { |
if (untie(%hash)) { |
$qresult=~s/\&$//; |
$qresult=~s/\&$//; |
Line 803 sub make_new_child {
|
Line 1201 sub make_new_child {
|
chomp($what); |
chomp($what); |
my $proname=propath($udom,$uname); |
my $proname=propath($udom,$uname); |
my $now=time; |
my $now=time; |
{ |
unless ($namespace=~/^nohist\_/) { |
my $hfh; |
my $hfh; |
if ( |
if ( |
$hfh=IO::File->new(">>$proname/$namespace.hist") |
$hfh=IO::File->new(">>$proname/$namespace.hist") |
Line 822 sub make_new_child {
|
Line 1220 sub make_new_child {
|
$allkeys.=$key.':'; |
$allkeys.=$key.':'; |
$hash{"$version:$rid:$key"}=$value; |
$hash{"$version:$rid:$key"}=$value; |
} |
} |
$allkeys=~s/:$//; |
$hash{"$version:$rid:timestamp"}=$now; |
|
$allkeys.='timestamp'; |
$hash{"$version:keys:$rid"}=$allkeys; |
$hash{"$version:keys:$rid"}=$allkeys; |
if (untie(%hash)) { |
if (untie(%hash)) { |
print $client "ok\n"; |
print $client "ok\n"; |
Line 854 sub make_new_child {
|
Line 1253 sub make_new_child {
|
my $key; |
my $key; |
$qresult.="$scope:keys=$vkeys&"; |
$qresult.="$scope:keys=$vkeys&"; |
foreach $key (@keys) { |
foreach $key (@keys) { |
$qresult.="$version:$key=".$hash{"$scope:$rid:$key"}."&"; |
$qresult.="$scope:$key=".$hash{"$scope:$rid:$key"}."&"; |
} |
} |
} |
} |
if (untie(%hash)) { |
if (untie(%hash)) { |
Line 868 sub make_new_child {
|
Line 1267 sub make_new_child {
|
} |
} |
# ------------------------------------------------------------------- querysend |
# ------------------------------------------------------------------- querysend |
} elsif ($userinput =~ /^querysend/) { |
} elsif ($userinput =~ /^querysend/) { |
my ($cmd,$query)=split(/:/,$userinput); |
my ($cmd,$query, |
|
$custom,$customshow)=split(/:/,$userinput); |
$query=~s/\n*$//g; |
$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 |
# ------------------------------------------------------------------ queryreply |
} elsif ($userinput =~ /^queryreply/) { |
} elsif ($userinput =~ /^queryreply/) { |
my ($cmd,$id,$reply)=split(/:/,$userinput); |
my ($cmd,$id,$reply)=split(/:/,$userinput); |
my $store; |
my $store; |
my $execdir=$perlvar{'lonDaemons'}; |
my $execdir=$perlvar{'lonDaemons'}; |
if ($store=IO::File->new(">$execdir/tmp/$id")) { |
if ($store=IO::File->new(">$execdir/tmp/$id")) { |
|
$reply=~s/\&/\n/g; |
print $store $reply; |
print $store $reply; |
close $store; |
close $store; |
|
my $store2=IO::File->new(">$execdir/tmp/$id.end"); |
|
print $store2 "done\n"; |
|
close $store2; |
print $client "ok\n"; |
print $client "ok\n"; |
} |
} |
else { |
else { |
Line 972 sub make_new_child {
|
Line 1384 sub make_new_child {
|
my $ulsout=''; |
my $ulsout=''; |
my $ulsfn; |
my $ulsfn; |
if (-e $ulsdir) { |
if (-e $ulsdir) { |
while ($ulsfn=<$ulsdir/*>) { |
if (opendir(LSDIR,$ulsdir)) { |
my @ulsstats=stat($ulsfn); |
while ($ulsfn=readdir(LSDIR)) { |
|
my @ulsstats=stat($ulsdir.'/'.$ulsfn); |
$ulsout.=$ulsfn.'&'.join('&',@ulsstats).':'; |
$ulsout.=$ulsfn.'&'.join('&',@ulsstats).':'; |
} |
} |
|
closedir(LSDIR); |
|
} |
} else { |
} else { |
$ulsout='no_such_dir'; |
$ulsout='no_such_dir'; |
} |
} |
if ($ulsout eq '') { $ulsout='empty'; } |
if ($ulsout eq '') { $ulsout='empty'; } |
print $client "$ulsout\n"; |
print $client "$ulsout\n"; |
|
# ------------------------------------------------------------------ Hanging up |
|
} elsif (($userinput =~ /^exit/) || |
|
($userinput =~ /^init/)) { |
|
&logthis( |
|
"Client $clientip ($hostid{$clientip}) hanging up: $userinput"); |
|
print $client "bye\n"; |
|
$client->close(); |
|
last; |
# ------------------------------------------------------------- unknown command |
# ------------------------------------------------------------- unknown command |
} else { |
} else { |
# unknown command |
# unknown command |
print $client "unknown_cmd\n"; |
print $client "unknown_cmd\n"; |
} |
} |
# ------------------------------------------------------ client unknown, refuse |
# -------------------------------------------------------------------- complete |
|
alarm(0); |
|
&status('Listening to '.$hostid{$clientip}); |
} |
} |
|
# --------------------------------------------- client unknown or fishy, refuse |
} else { |
} else { |
print $client "refused\n"; |
print $client "refused\n"; |
|
$client->close(); |
&logthis("<font color=blue>WARNING: " |
&logthis("<font color=blue>WARNING: " |
."Rejected client $clientip, closing connection</font>"); |
."Rejected client $clientip, closing connection</font>"); |
} |
} |
Line 1000 sub make_new_child {
|
Line 1427 sub make_new_child {
|
|
|
# tidy up gracefully and finish |
# tidy up gracefully and finish |
|
|
|
$client->close(); |
|
$server->close(); |
|
|
# this exit is VERY important, otherwise the child will become |
# this exit is VERY important, otherwise the child will become |
# a producer of more and more children, forking yourself into |
# a producer of more and more children, forking yourself into |
# process death. |
# process death. |
Line 1007 sub make_new_child {
|
Line 1437 sub make_new_child {
|
} |
} |
} |
} |
|
|
|
# ----------------------------------- POD (plain old documentation, CPAN style) |
|
|
|
=head1 NAME |
|
|
|
lond - "LON Daemon" Server (port "LOND" 5663) |
|
|
|
=head1 SYNOPSIS |
|
|
|
Should only be run as user=www. Invoked by loncron. |
|
|
|
=head1 DESCRIPTION |
|
|
|
Preforker - server who forks first. Runs as a daemon. HUPs. |
|
Uses IDEA encryption |
|
|
|
=head1 README |
|
|
|
Not yet written. |
|
|
|
=head1 PREREQUISITES |
|
|
|
IO::Socket |
|
IO::File |
|
Apache::File |
|
Symbol |
|
POSIX |
|
Crypt::IDEA |
|
LWP::UserAgent() |
|
GDBM_File |
|
Authen::Krb4 |
|
|
|
=head1 COREQUISITES |
|
|
|
=head1 OSNAMES |
|
|
|
linux |
|
|
|
=head1 SCRIPT CATEGORIES |
|
|
|
Server/Process |
|
|
|
=cut |
|
|
|
|
|
|