--- loncom/lond 2004/02/17 21:02:37 1.176 +++ loncom/lond 2004/06/01 09:58:30 1.192 @@ -2,7 +2,7 @@ # The LearningOnline Network # lond "LON Daemon" Server (port "LOND" 5663) # -# $Id: lond,v 1.176 2004/02/17 21:02:37 albertel Exp $ +# $Id: lond,v 1.192 2004/06/01 09:58:30 foxr Exp $ # # Copyright Michigan State University Board of Trustees # @@ -53,7 +53,7 @@ my $DEBUG = 0; # Non zero to ena my $status=''; my $lastlog=''; -my $VERSION='$Revision: 1.176 $'; #' stupid emacs +my $VERSION='$Revision: 1.192 $'; #' stupid emacs my $remoteVERSION; my $currenthostid; my $currentdomainid; @@ -225,8 +225,8 @@ sub ValidManager { # 1 - Success. # sub CopyFile { - my $oldfile = shift; - my $newfile = shift; + + my ($oldfile, $newfile) = @_; # The file must exist: @@ -326,8 +326,8 @@ sub AdjustHostContents { # 0 - failure and $! has an errno. # sub InstallFile { - my $Filename = shift; - my $Contents = shift; + + my ($Filename, $Contents) = @_; my $TempFile = $Filename.".tmp"; # Open the file for write: @@ -564,8 +564,8 @@ sub isValidEditCommand { # file being edited. # sub ApplyEdit { - my $directive = shift; - my $editor = shift; + + my ($directive, $editor) = @_; # Break the directive down into its command and its parameters # (at most two at this point. The meaning of the parameters, if in fact @@ -649,8 +649,8 @@ sub AdjustOurHost { # editor - Editor containing the file. # sub ReplaceConfigFile { - my $filename = shift; - my $editor = shift; + + my ($filename, $editor) = @_; CopyFile ($filename, $filename.".old"); @@ -749,7 +749,7 @@ sub catchexception { $SIG{'QUIT'}='DEFAULT'; $SIG{__DIE__}='DEFAULT'; &status("Catching exception"); - &logthis("CRITICAL: " + &logthis("CRITICAL: " ."ABNORMAL EXIT. Child $$ for server $thisserver died through " ."a crash with this error msg->[$error]"); &logthis('Famous last words: '.$status.' - '.$lastlog); @@ -760,7 +760,7 @@ sub catchexception { sub timeout { &status("Handling Timeout"); - &logthis("CRITICAL: TIME OUT ".$$.""); + &logthis("CRITICAL: TIME OUT ".$$.""); &catchexception('Timeout'); } # -------------------------------- Set signal handlers to record abnormal exits @@ -822,7 +822,7 @@ sub REAPER { # ta if (defined($children{$pid})) { &logthis("Child $pid died"); delete($children{$pid}); - } else { + } elsif ($pid > 0) { &logthis("Unknown Child $pid died"); } } while ( $pid > 0 ); @@ -843,7 +843,7 @@ sub HUNTSMAN { # si &logthis("Free socket: ".shutdown($server,2)); # free up socket my $execdir=$perlvar{'lonDaemons'}; unlink("$execdir/logs/lond.pid"); - &logthis("CRITICAL: Shutting down"); + &logthis("CRITICAL: Shutting down"); &status("Done killing children"); exit; # clean up with dignity } @@ -853,7 +853,7 @@ sub HUPSMAN { # sig &status("Killing children for restart (HUP)"); kill 'INT' => keys %children; &logthis("Free socket: ".shutdown($server,2)); # free up socket - &logthis("CRITICAL: Restarting"); + &logthis("CRITICAL: Restarting"); my $execdir=$perlvar{'lonDaemons'}; unlink("$execdir/logs/lond.pid"); &status("Restarting self (HUP)"); @@ -1015,9 +1015,8 @@ sub Debug { # request - Original request from client. # sub Reply { - my $fd = shift; - my $reply = shift; - my $request = shift; + + my ($fd, $reply, $request) = @_; print $fd $reply; Debug("Request was $request Reply was $reply"); @@ -1095,11 +1094,11 @@ sub reconlonc { kill USR1 => $loncpid; } else { &logthis( - "CRITICAL: " + "CRITICAL: " ."lonc at pid $loncpid not responding, giving up"); } } else { - &logthis('CRITICAL: lonc not running, giving up'); + &logthis('CRITICAL: lonc not running, giving up'); } } @@ -1203,7 +1202,7 @@ my $execdir=$perlvar{'lonDaemons'}; open (PIDSAVE,">$execdir/logs/lond.pid"); print PIDSAVE "$$\n"; close(PIDSAVE); -&logthis("CRITICAL: ---------- Starting ----------"); +&logthis("CRITICAL: ---------- Starting ----------"); &status('Starting'); @@ -1258,8 +1257,18 @@ sub make_new_child { # the pid hash. # my $caller = getpeername($client); - my ($port,$iaddr)=unpack_sockaddr_in($caller); - $clientip=inet_ntoa($iaddr); + my ($port,$iaddr); + if (defined($caller) && length($caller) > 0) { + ($port,$iaddr)=unpack_sockaddr_in($caller); + } else { + &logthis("Unable to determine who caller was, getpeername returned nothing"); + } + if (defined($iaddr)) { + $clientip=inet_ntoa($iaddr); + } else { + &logthis("Unable to determine clinetip"); + $clientip='Unavailable'; + } if ($pid) { # Parent records the child's birth and returns. @@ -1330,18 +1339,18 @@ sub make_new_child { print $client "ok\n"; } else { &logthis( - "WARNING: $clientip did not reply challenge"); + "WARNING: $clientip did not reply challenge"); &status('No challenge reply '.$clientip); } } else { &logthis( - "WARNING: " + "WARNING: " ."$clientip failed to initialize: >$remotereq< "); &status('No init '.$clientip); } } else { &logthis( - "WARNING: Unknown client $clientip"); + "WARNING: Unknown client $clientip"); &status('Hung up on '.$clientip); } if ($clientok) { @@ -1355,7 +1364,7 @@ sub make_new_child { } &reconlonc("$perlvar{'lonSockDir'}/$id"); } - &logthis("Established connection: $clientname"); + &logthis("Established connection: $clientname"); &status('Will listen to '.$clientname); # ------------------------------------------------------------ Process requests while (my $userinput=<$client>) { @@ -1552,7 +1561,7 @@ sub make_new_child { $pwdcorrect=0; # log error if it is not a bad password if ($krb4_error != 62) { - &logthis('krb4:'.$uname.','.$contentpwd.','. + &logthis('krb4:'.$uname.','. &Authen::Krb4::get_err_txt($Authen::Krb4::error)); } } @@ -1818,12 +1827,21 @@ sub make_new_child { } elsif ($userinput =~ /^fetchuserfile/) { # Client clear or enc. if(isClient) { my ($cmd,$fname)=split(/:/,$userinput); - my ($udom,$uname,$ufile)=split(/\//,$fname); + my ($udom,$uname,$ufile) = ($fname =~ m|^([^/]+)/([^/]+)/(.+)$|); my $udir=propath($udom,$uname).'/userfiles'; unless (-e $udir) { mkdir($udir,0770); } if (-e $udir) { - $ufile=~s/^[\.\~]+//; - $ufile=~s/\///g; + $ufile=~s/^[\.\~]+//; + my $path = $udir; + if ($ufile =~m|(.+)/([^/]+)$|) { + my @parts=split('/',$1); + foreach my $part (@parts) { + $path .= '/'.$part; + if ((-e $path)!=1) { + mkdir($path,0770); + } + } + } my $destname=$udir.'/'.$ufile; my $transname=$udir.'/'.$ufile.'.in.transit'; my $remoteurl='http://'.$clientip.'/userfiles/'.$fname; @@ -1852,7 +1870,37 @@ sub make_new_child { } } else { Reply($client, "refused\n", $userinput); - + } +# --------------------------------------------------------- remove a user file + } elsif ($userinput =~ /^removeuserfile/) { # Client clear or enc. + if(isClient) { + my ($cmd,$fname)=split(/:/,$userinput); + my ($udom,$uname,$ufile) = ($fname =~ m|^([^/]+)/([^/]+)/(.+)$|); + &logthis("$udom - $uname - $ufile"); + if ($ufile =~m|/\.\./|) { + # any files paths with /../ in them refuse + # to deal with + print $client "refused\n"; + } else { + my $udir=propath($udom,$uname); + if (-e $udir) { + my $file=$udir.'/userfiles/'.$ufile; + if (-e $file) { + unlink($file); + if (-e $file) { + print $client "failed\n"; + } else { + print $client "ok\n"; + } + } else { + print $client "not_found\n"; + } + } else { + print $client "not_home\n"; + } + } + } else { + Reply($client, "refused\n", $userinput); } # ------------------------------------------ authenticate access to a user file } elsif ($userinput =~ /^tokenauthuserfile/) { # Client only @@ -1863,7 +1911,7 @@ sub make_new_child { if (open(ENVIN,$perlvar{'lonIDsDir'}.'/'. $session.'.id')) { while (my $line=) { - if ($line=~/userfile\.$fname\=/) { $reply='ok'; } + if ($line=~ m|userfile\.\Q$fname\E\=|) { $reply='ok'; } } close(ENVIN); print $client $reply."\n"; @@ -1879,7 +1927,7 @@ sub make_new_child { if(isClient) { my ($cmd,$fname)=split(/:/,$userinput); if (-e $fname) { - print $client &unsub($client,$fname,$clientip); + print $client &unsub($fname,$clientip); } else { print $client "not_found\n"; } @@ -2006,12 +2054,12 @@ sub make_new_child { } else { print $client "error: ".($!+0) ." untie(GDBM) failed ". - "while attempting put\n"; + "while attempting inc\n"; } } else { print $client "error: ".($!) ." tie(GDBM) Failed ". - "while attempting put\n"; + "while attempting inc\n"; } } else { print $client "refused\n"; @@ -2337,7 +2385,6 @@ sub make_new_child { my $proname=propath($udom,$uname); my %hash; if (tie(%hash,'GDBM_File',"$proname/$namespace.db",&GDBM_READER(),0640)) { - study($regexp); while (my ($key,$value) = each(%hash)) { if ($regexp eq '.') { $qresult.=$key.'='.$value.'&'; @@ -2575,7 +2622,7 @@ sub make_new_child { $qresult.=$key.'='.$descr.'&'; } else { my $unescapeVal = &unescape($descr); - if (eval('$unescapeVal=~/$description/i')) { + if (eval('$unescapeVal=~/\Q$description\E/i')) { $qresult.="$key=$descr&"; } } @@ -2830,14 +2877,14 @@ sub make_new_child { } else { print $client "refused\n"; $client->close(); - &logthis("WARNING: " + &logthis("WARNING: " ."Rejected client $clientip, closing connection"); } } # ============================================================================= - &logthis("CRITICAL: " + &logthis("CRITICAL: " ."Disconnect from $clientip ($clientname)"); @@ -2862,10 +2909,8 @@ sub make_new_child { # sub ManagePermissions { - my $request = shift; - my $domain = shift; - my $user = shift; - my $authtype= shift; + + my ($request, $domain, $user, $authtype) = @_; # See if the request is of the form /$domain/_au if($request =~ /^(\/$domain\/_au)$/) { # It's an author rolesput... @@ -2882,8 +2927,8 @@ sub ManagePermissions # sub GetAuthType { - my $domain = shift; - my $user = shift; + + my ($domain, $user) = @_; Debug("GetAuthType( $domain, $user ) \n"); my $proname = &propath($domain, $user); @@ -2992,17 +3037,36 @@ sub chatadd { sub unsub { my ($fname,$clientip)=@_; my $result; + my $unsubs = 0; # Number of successful unsubscribes: + + + # An old way subscriptions were handled was to have a + # subscription marker file: + + Debug("Attempting unlink of $fname.$clientname"); if (unlink("$fname.$clientname")) { - $result="ok\n"; - } else { - $result="not_subscribed\n"; - } + $unsubs++; # Successful unsub via marker file. + } + + # The more modern way to do it is to have a subscription list + # file: + if (-e "$fname.subscription") { my $found=&addline($fname,$clientname,$clientip,''); - if ($found) { $result="ok\n"; } + if ($found) { + $unsubs++; + } + } + + # If either or both of these mechanisms succeeded in unsubscribing a + # resource we can return ok: + + if($unsubs) { + $result = "ok\n"; } else { - if ($result != "ok\n") { $result="not_subscribed\n"; } + $result = "not_subscribed\n"; } + return $result; } @@ -3124,6 +3188,16 @@ sub make_passwd_file { } } elsif ($umode eq 'unix') { { + # + # Don't allow the creation of privileged accounts!!! that would + # be real bad!!! + # + my $uid = getpwnam($uname); + if((defined $uid) && ($uid == 0)) { + &logthis(">>>Attempted to create privilged account blocked"); + return "no_priv_account_error\n"; + } + my $execpath="$perlvar{'lonDaemons'}/"."lcuseradd"; { &Debug("Executing external: ".$execpath);