--- loncom/lcinstallfile 2009/02/20 11:26:34 1.1 +++ loncom/lcinstallfile 2009/02/24 11:52:03 1.2 @@ -24,8 +24,8 @@ # # 2/17/2009 - Ron FOx # - -http://www.lon-capa.org/ +# +# http://www.lon-capa.org/ # # This file is a setuid script that allows lond or other www programs to install # a file in the lon capa table directory. @@ -41,12 +41,15 @@ http://www.lon-capa.org/ use strict; -my $LONCAPAHOME = '/home/httpd; # Adjust if loncapa isn't installed here. +my $LONCAPAHOME = '/home/httpd'; # Adjust if loncapa isn't installed here. -use lib "$LONCAPAHOME/perl/lib"; +use lib "/home/httpd/lib/perl"; use LONCAPA; use LONCAPA::Configuration; use IO::File; +use File::Copy; + + # # Exit codes: @@ -57,8 +60,9 @@ use IO::File; # 4 - source_file_name does not exist. # 5 - destination file does not exist (not allowed to create new files). # 6 - Some file operation failed. +# 7 - Invalid table filename. # -$noprint = 0; +my $noprint = 0; # # Ensure we are www: # @@ -76,21 +80,37 @@ if ($wwwid!=$>) { # my $argc = scalar(@ARGV); if ($argc != 2) { - print("Usage: lcinstallfile sourcepath destfile\n") unlesss $noprint; + print("Usage: lcinstallfile sourcepath destfile\n") unless $noprint; exit 2; } -my $sorcepath = $ARGV[0]; +my $sourcepath = $ARGV[0]; my $destfile = $ARGV[1]; + + # Ensure the source file exists, and root can write it.: -&enable_root_capability; +# since this is a setuid program, the sourcepath and destfile +# must be pattern extracted else they are considered insecure and +# therefore not validated. +# loncapa table files are all of the form. +# something.tab where something is all letters and _'s. +# +if ($sourcepath =~ /^(\w+\.tab)$/) { + $sourcepath = $1; +} else { + print ("Invalid characters in filename $sourcepath \n") unless $noprint; + exit 7; +} + + if (! -r $sourcepath) { - &disable_root_capability; print("File $sourcepath either does not exist or cannot be read") unless $noprint; exit 4; } +&enable_root_capability; + # # Figure out where the lontab directory is and create the destinationfile name: # @@ -98,10 +118,20 @@ if (! -r $sourcepath) { # so ensure that the final destination file actually exists. # my $config_vars = LONCAPA::Configuration::read_conf('loncapa.conf'); -my %config = %{$configvars}; +my %config = %{$config_vars}; my $tab_dir = $config{'lonTabDir'}; -my $final_file = $tabdir.'/'.$destfile; +my $final_file = $tab_dir.'/'.$destfile; + +# +# Now sanitize the final file: + +if ($final_file =~ /^([\w\/]+\.tab)$/) { + $final_file = $1; +} else { + print ("$final_file failed regexp match\n") unless $noprint; + exit 7; +} if (! -w $final_file) { &disable_root_capability; @@ -111,16 +141,17 @@ if (! -w $final_file) { # # Copy the destination file to a backup: # -if (!File::Copy($final_file, $final_file.'.backup')) { +if (!copy($final_file, $final_file.'.backup')) { &disable_root_capability; print ("Failed to create backup copy of $final_file\n") unless $noprint; exit 6; } +&enable_root_capability; # Install the new file to a temp file in the same dir so it can be mv'd in place # this prevents the possibility we wind up with a partial file.: -if (!File::Copy($sourcepath, $final_file.'.new')) { +if (!copy($sourcepath, $final_file.'.new')) { &disable_root_capability; print("Failed to copy $sourcepath to a tempfile\n") unless $noprint; exit 6; @@ -128,24 +159,25 @@ if (!File::Copy($sourcepath, $final_file # # Move the temp file to the final file # -if (!rename($final_path.'.new', $final_path)) { +if (!rename($final_file.'.new', $final_file)) { &disable_root_capability; - print ("Failed to move installed file $final_path.new to final resting place\n") + print ("Failed to move installed file $final_file.new to final resting place\n") unless $noprint; exit 6; } # Ready to exit with success -&disble_root_capability; -print ("$sourcepaht installed to $final_file\n") unless $noprint; +&disable_root_capability; +print ("$sourcepath installed to $final_file\n") unless $noprint; exit 0; + #------------------------------------------------------------------------- # # subs that control the setuid-edness of the program. -# ---------------------------------------------- have setuid script run as root +# have setuid script run as root sub enable_root_capability { if ($wwwid==$>) { ($<,$>)=($>,0); @@ -157,7 +189,7 @@ sub enable_root_capability { return $>; } -# ----------------------------------------------- have setuid script run as www +# have setuid script run as www sub disable_root_capability { if ($wwwid==$<) { ($<,$>)=($>,$<);