File:  [LON-CAPA] / loncom / lcinstallfile
Revision 1.5: download - view: text, annotated - select for diffs
Tue Oct 12 10:14:25 2010 UTC (13 years, 5 months ago) by foxr
Branches: MAIN
CVS tags: version_2_12_X, version_2_11_X, version_2_11_4_uiuc, version_2_11_4_msu, version_2_11_4, version_2_11_3_uiuc, version_2_11_3_msu, version_2_11_3, version_2_11_2_uiuc, version_2_11_2_msu, version_2_11_2_educog, version_2_11_2, version_2_11_1, version_2_11_0_RC3, version_2_11_0_RC2, version_2_11_0_RC1, version_2_11_0, version_2_10_X, version_2_10_1, version_2_10_0_RC2, version_2_10_0, loncapaMITrelate_1, language_hyphenation_merge, language_hyphenation, HEAD, BZ4492-merge, BZ4492-feature_horizontal_radioresponse, BZ4492-feature_Support_horizontal_radioresponse, BZ4492-Support_horizontal_radioresponse
Make this usable in fc13 which won't allow re-elevation of euid
once euid is set to the actual uid.

    1: #!/usr/bin/perl
    2: #
    3: # Copyright Michigan State University Board of Trustees
    4: #
    5: # $Id: lcinstallfile,v 1.5 2010/10/12 10:14:25 foxr Exp $
    6: #
    7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
    8: #
    9: # LON-CAPA is free software; you can redistribute it and/or modify
   10: # it under the terms of the GNU General Public License as published by
   11: # the Free Software Foundation; either version 2 of the License, or 
   12: # (at your option) any later version.
   13: #
   14: # LON-CAPA is distributed in the hope that it will be useful,
   15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17: # GNU General Public License for more details.
   18: #
   19: # You should have received a copy of the GNU General Public License
   20: # along with LON-CAPA; if not, write to the Free Software
   21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   22: #
   23: # /home/httpd/html/adm/gpl.txt
   24: #
   25: #
   26: #
   27: # 2/17/2009 - Ron Fox
   28: #
   29: # http://www.lon-capa.org/
   30: #
   31: #  This file is a setuid script that allows lond or other www programs to install
   32: #  a file in the lon capa table directory.
   33: #
   34: #  Invocation is as follows:
   35: #    lcinstallfile  source_file_name dest_name
   36: #
   37: #  source_file_name - The full path for the source file.
   38: #  dest_name        - The destination filename.  This will always be in the
   39: #                     table file directory for this server.
   40: #
   41: 
   42: 
   43: use strict;
   44: 
   45: use lib "/home/httpd/lib/perl";     # Adjust if loncapa lib isn't installed here.
   46: use LONCAPA;
   47: use LONCAPA::Configuration;
   48: use IO::File;
   49: use File::Copy;
   50: 
   51: 
   52: 
   53: #
   54: # Exit codes:
   55: #
   56: # 0    - ok
   57: # 1    - Initial user ID was not www
   58: # 3    - Usage error not enough command line arguments.
   59: # 4    - source_file_name does not exist.
   60: # 5    - destination file does not exist (not allowed to create new files).
   61: # 6    - Some file operation failed.
   62: # 7    - Invalid table filename.
   63: #
   64: my $noprint = 1;
   65: #
   66: #   Ensure we are www:
   67: #
   68: # 
   69: print ("In lcinstallfile\n") unless $noprint;
   70: 
   71: my $wwwid=getpwnam('www');
   72: #&disable_root_capability;
   73: if ($wwwid!=$<) {
   74:     print("User ID mismatch.  This program must be run as user 'www'\n")
   75: 	unless $noprint;
   76:     exit 1;
   77: }
   78: #
   79: #  Ensure we have the right number of command args:
   80: #
   81: my $argc = scalar(@ARGV);
   82: if ($argc != 2) {
   83:     print("Usage: lcinstallfile sourcepath destfile had $argc parameters\n") unless $noprint;
   84:     exit 2;
   85: }
   86: my $sourcepath = $ARGV[0];
   87: my $destfile  = $ARGV[1];
   88: 
   89: print("From: $sourcepath to: $destfile\n") unless $noprint;
   90: 
   91: 
   92: # Ensure the source file exists, and root can write it.:
   93: 
   94: # since this is a setuid program, the sourcepath and destfile
   95: # must be pattern extracted else they are considered insecure and
   96: # therefore not validated.  
   97: # loncapa table files are all of the form.
   98: #  something.tab where something is all letters and _'s.
   99: #
  100: if ($sourcepath =~ /^([\w\/]+\.\w+)$/) {
  101:     $sourcepath = $1;
  102: } else {
  103:     print ("Invalid characters in filename '$sourcepath' \n") unless $noprint;
  104:     exit 7;
  105: }
  106: 
  107: 
  108: if (! -r $sourcepath) {
  109:     print("File $sourcepath either does not exist or cannot be read") unless $noprint;
  110:     exit 4;
  111:     
  112: }
  113: &enable_root_capability;
  114: 
  115: #
  116: #  Figure out where the lontab directory is and create the destinationfile name:
  117: #
  118: #  We're not allowed to create new files, only replace existing files
  119: #  so ensure that the final destination file actually exists.
  120: #
  121: 
  122: 
  123: #
  124: # Now sanitize the final file:
  125: 
  126: my $final_file;
  127: if ($destfile =~ /^([\w\/]+\.\w+)$/) {
  128:     $final_file = $1;
  129: } else {
  130:     print ("'$final_file' failed regexp match\n") unless $noprint;
  131:     exit 7;
  132: }
  133: 
  134: if (! -w $final_file) {
  135:     &disable_root_capability;
  136:     print("The $final_file is either not writable, or does not exist.\n") unless $noprint;
  137:     exit 5;
  138: }
  139: #
  140: # Copy the destination file to a backup:
  141: #
  142: if (!copy($final_file, $final_file.'.backup')) {
  143:     &disable_root_capability;
  144:     print ("Failed to create backup copy of $final_file\n") unless $noprint;
  145:     exit 6;
  146: }
  147: &enable_root_capability;
  148: 
  149: #  Install the new file to a temp file in the same dir so it can be mv'd in place
  150: #  this prevents the possibility we wind up with a partial file.:
  151: 
  152: if (!copy($sourcepath, $final_file.'.new')) {
  153:     &disable_root_capability;
  154:     print("Failed to copy $sourcepath to a tempfile\n") unless $noprint;
  155:     exit 6;
  156: }
  157: #
  158: #  Move the temp file to the final file
  159: #
  160: if (!rename($final_file.'.new', $final_file)) {
  161:     &disable_root_capability;
  162:     print ("Failed to move installed file $final_file.new to final resting place\n")
  163: 	unless $noprint;
  164:     exit 6;
  165: }
  166: 
  167: #  Ready to exit with success
  168: 
  169: &disable_root_capability;
  170: print ("$sourcepath installed to $final_file\n") unless $noprint;
  171: exit 0;
  172: 
  173: 
  174: #-------------------------------------------------------------------------
  175: #
  176: #  subs that control the setuid-edness of the program.
  177: 
  178: #  have setuid script run as root
  179: sub enable_root_capability {
  180:     if ($wwwid==$>) {
  181: 	($<,$>)=($>,0);
  182: 	($(,$))=($),0);
  183:     } else {
  184: 	# root capability is already enabled
  185:     }
  186:     print ("Effective uid = $>\n");
  187:     return $>;
  188: }
  189: 
  190: #  have setuid script run as www
  191: sub disable_root_capability {
  192:     if ($wwwid==$<) {
  193: 	($<,$>)=($>,$<);
  194: 	($(,$))=($),$();
  195:     } else {
  196: 	# root capability is already disabled
  197:     }
  198: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>