--- loncom/lond 2004/09/07 14:28:30 1.250 +++ loncom/lond 2004/09/08 10:19:52 1.251 @@ -2,7 +2,7 @@ # The LearningOnline Network # lond "LON Daemon" Server (port "LOND" 5663) # -# $Id: lond,v 1.250 2004/09/07 14:28:30 albertel Exp $ +# $Id: lond,v 1.251 2004/09/08 10:19:52 foxr Exp $ # # Copyright Michigan State University Board of Trustees # @@ -57,7 +57,7 @@ my $DEBUG = 0; # Non zero to ena my $status=''; my $lastlog=''; -my $VERSION='$Revision: 1.250 $'; #' stupid emacs +my $VERSION='$Revision: 1.251 $'; #' stupid emacs my $remoteVERSION; my $currenthostid="default"; my $currentdomainid; @@ -331,8 +331,43 @@ sub InsecureConnection { } - # +# Safely execute a command (as long as it's not a shel command and doesn +# not require/rely on shell escapes. The function operates by doing a +# a pipe based fork and capturing stdout and stderr from the pipe. +# +# Formal Parameters: +# $line - A line of text to be executed as a command. +# Returns: +# The output from that command. If the output is multiline the caller +# must know how to split up the output. +# +# +sub execute_command { + my ($line) = @_; + my @words = split(/\s/, $line); # Bust the command up into words. + my $output = ""; + + my $pid = open(CHILD, "-|"); + + if($pid) { # Parent process + Debug("In parent process for execute_command"); + my @data = ; # Read the child's outupt... + close CHILD; + foreach my $output_line (@data) { + Debug("Adding $output_line"); + $output .= $output_line; # Presumably has a \n on it. + } + + } else { # Child process + close (STDERR); + open (STDERR, ">&STDOUT");# Combine stderr, and stdout... + exec(@words); # won't return. + } + return $output; +} + + # GetCertificate: Given a transaction that requires a certificate, # this function will extract the certificate from the transaction # request. Note that at this point, the only concept of a certificate @@ -1302,6 +1337,9 @@ sub push_file_handler { sub du_handler { my ($cmd, $ududir, $client) = @_; + my ($ududir) = split(/:/,$ududir); # Make 'telnet' testing easier. + my $userinput = "$cmd:$ududir"; + if ($ududir=~/\.\./ || $ududir!~m|^/home/httpd/|) { &Failure($client,"refused\n","$cmd:$ududir"); return 1; @@ -1314,18 +1352,17 @@ sub du_handler { # if (-d $ududir) { # And as Shakespeare would say to make - # assurance double sure, quote the $ududir - # This is in case someone manages to first - # e.g. fabricate a valid directory with a ';' - # in it. Quoting the dir will help - # keep $ududir completely interpreted as a - # directory. - # - my $duout = `du -ks "$ududir" 2>/dev/null`; + # assurance double sure, + # use execute_command to ensure that the command is not executed in + # a shell that can screw us up. + + my $duout = execute_command("du -ks $ududir"); $duout=~s/[^\d]//g; #preserve only the numbers &Reply($client,"$duout\n","$cmd:$ududir"); } else { - &Failure($client, "bad_directory:$ududir","$cmd:$ududir"); + + &Failure($client, "bad_directory:$ududir\n","$cmd:$ududir"); + } return 1; } @@ -1730,7 +1767,7 @@ sub change_authentication_handler { my $result=&make_passwd_file($uname, $umode,$npass,$passfilename); &Reply($client, $result, $userinput); } else { - &Failure($client, "non_authorized", $userinput); # Fail the user now. + &Failure($client, "non_authorized\n", $userinput); # Fail the user now. } } return 1; @@ -2081,14 +2118,14 @@ sub token_auth_user_file_handler { my ($fname, $session) = split(/:/, $tail); chomp($session); - my $reply='non_auth'; + my $reply="non_auth\n"; if (open(ENVIN,$perlvar{'lonIDsDir'}.'/'. $session.'.id')) { while (my $line=) { - if ($line=~ m|userfile\.\Q$fname\E\=|) { $reply='ok'; } + if ($line=~ m|userfile\.\Q$fname\E\=|) { $reply="ok\n"; } } close(ENVIN); - &Reply($client, $reply); + &Reply($client, $reply, "$cmd:$tail"); } else { &Failure($client, "invalid_token\n", "$cmd:$tail"); } @@ -3799,7 +3836,7 @@ sub process_request { $userinput = decipher($userinput); $wasenc=1; if(!$userinput) { # Cipher not defined. - &Failure($client, "error: Encrypted data without negotated key"); + &Failure($client, "error: Encrypted data without negotated key\n"); return 0; } }