Diff for /loncom/Attic/lchtmldir between versions 1.3 and 1.17

version 1.3, 2002/05/03 03:43:54 version 1.17, 2005/06/21 11:00:21
Line 41 Line 41
 #    NSCL  #    NSCL
 #    Michigan State University8  #    Michigan State University8
 #    East Lansing, MI 48824-1321  #    East Lansing, MI 48824-1321
   #
 #   General flow of control:  #   General flow of control:
 #   1. Validate process state (must be run as www).  #   1. Validate process state (must be run as www).
 #   2. Validate parameters:  Need two parameters:  #   2. Validate parameters:  Need two parameters:
Line 61 Line 61
 #       - internal - www:www/2775  #       - internal - www:www/2775
 #       - local    - www:www/2775  #       - local    - www:www/2775
 #  #
   #
 #  #
 #   Take a few precautions to be sure that we're not vulnerable to trojan  #   Take a few precautions to be sure that we're not vulnerable to trojan
 #   horses and other fine issues:  #   horses and other fine issues:
 #  #
 use strict;   use strict; 
   use Fcntl qw(:mode);
   use DirHandle;
   use POSIX;
   
 $ENV{'PATH'} = '/bin:/usr/bin:/usr/local/sbin:/home/httpd/perl';  $ENV{'PATH'} = '/bin:/usr/bin:/usr/local/sbin:/home/httpd/perl';
 delete @ENV{qw{IFS CDPATH ENV BASH_ENV}};  delete @ENV{qw{IFS CDPATH ENV BASH_ENV}};
   
 my $DEBUG = 0;                         # .nonzero -> Debug printing enabled.  my $DEBUG = 1;                         # .nonzero -> Debug printing enabled.
   my $path_sep = "/"; # Unix like operating systems.
   
   
 # If the UID of the running process is not www exit with error.  # If the UID of the running process is not www exit with error.
Line 117  if($DEBUG) { Line 121  if($DEBUG) {
   
 if( $authentication ne "unix:"     &&  if( $authentication ne "unix:"     &&
     $authentication ne "internal:" &&      $authentication ne "internal:" &&
     $authentication ne "krb4:"     &&      $authentication !~ /^krb(4|5):(.*)/ &&
     $authentication ne "localauth:") {      $authentication ne "localauth:") {
     if($DEBUG) {      if($DEBUG) {
  print("Invalid authentication parameter: ".$authentication."\n");   print("Invalid authentication parameter: ".$authentication."\n");
Line 140  my $safeuser = $patt; Line 144  my $safeuser = $patt;
 if($DEBUG) {  if($DEBUG) {
     print("Save username = $safeuser \n");      print("Save username = $safeuser \n");
 }  }
 if(($username ne $safeuser) or ($safeuser!~/^[A-za-z]/)) {  if(($username ne $safeuser) or ($safeuser!~/^[A-z]/)) {
     if($DEBUG) {      if($DEBUG) {
  print("User name $username had illegal characters\n");   print("User name $username had illegal characters\n");
     }      }
Line 167  if(($dirtry1 ne $dir) or ($dirtry2 ne $d Line 171  if(($dirtry1 ne $dir) or ($dirtry2 ne $d
   
 # As root, create the directory.  # As root, create the directory.
   
 my $fulldir = $dirtry1."/public_html";  my $homedir = $dirtry1;
   my $fulldir = $homedir."/public_html";
   
 if($DEBUG) {  if($DEBUG) {
     print("Full directory path is: $fulldir \n");      print("Full directory path is: $fulldir \n");
 }  }
Line 175  if(!( -e $dirtry1)) { Line 181  if(!( -e $dirtry1)) {
     if($DEBUG) {      if($DEBUG) {
  print("User's home directory $dirtry1 does not exist\n");   print("User's home directory $dirtry1 does not exist\n");
     }      }
     exit 6;      if ($authentication eq "unix:") {
           exit 6;
       }
   }
   if ($authentication eq "unix:") {
       # check whether group $safeuser exists.
       my $usergroups = `id -nG $safeuser`;
       if (! grep /^$safeuser$/, split(/\s+/,$usergroups)) { 
           if($DEBUG) {
               print("Group \"$safeuser\" does not exist or $safeuser is not a member of that group.\n");
           }
           exit 7;
       }
 }  }
   
   
   
 &EnableRoot;  &EnableRoot;
   
   #  If authentication is internal and the top level directory exists
   #  give it the right permissions (in case this is a modification.
   
   if ($authentication eq "internal:") {
       chmod(0711, $homedir); # so www can enter ~/public_html.
   }
   
 &System("/bin/mkdir -p $fulldir")   unless (-e $fulldir);  &System("/bin/mkdir -p $fulldir")   unless (-e $fulldir);
     unless(-e $fulldir."/index.html") {      unless(-e $fulldir."/index.html") {
  open OUT,">".$fulldir."/index.html";   open OUT,">".$fulldir."/index.html";
Line 187  if(!( -e $dirtry1)) { Line 215  if(!( -e $dirtry1)) {
  <head>   <head>
  <title>$safeuser</title>   <title>$safeuser</title>
         </head>          </head>
         <body>          <body bgcolor="#ccffdd">
         <h1>$safeuser</h1>          <h1>$safeuser Construction Space</h1>
             <h2>
               The Learning<i>Online</i> Network with Computer-Assisted Personalized Approach
             </h2>
           <p>            <p>
             Learning Online Network  This is your construction space within LON-CAPA, where you would construct resources which are meant to be
   used across courses and institutions.
           </p>            </p>
           <p>            <p>
             This area provides for:  Material within this area can only be seen and edited by $safeuser and designated co-authors. To make
   it available to students and other instructors, the material needs to be published.
           </p>            </p>
           <ul>  
              <li>resource construction</li>  
              <li>resource publication</li>  
              <li>record-keeping</li>  
           </ul>  
         </body>          </body>
        </html>         </html>
 END  END
     close OUT;      close OUT;
     }      }
 &System("/bin/chmod  02775  $fulldir");  
 &System("/bin/chmod  0775  $fulldir"."/index.html");  &System("/bin/chmod  02770  $fulldir");
   &System("/bin/chmod  0770  $fulldir"."/index.html");
   
   
 # Based on the authentiation mode, set the ownership of the directory.  # Based on the authentiation mode, set the ownership of the directory.
   
 if($authentication eq "unix:") { # Unix mode authentication...  if($authentication eq "unix:") { # Unix mode authentication...
           print "Unix auth\n";
          &System("/bin/chown -R   $safeuser:$safeuser"." ".$fulldir);
     &System("/bin/chown -R   $username".":".$username." ".$fulldir);      &JoinGroup($safeuser);
     &JoinGroup($username);  } else {
       # Internal, Kerberos, and Local authentication are for users
       # who do not have unix accounts on the system.  Therefore we
 }      # will give ownership of their public_html directories to www:www
 elsif ($authentication eq "internal:") { # Internal authentication.      # If the user is an internal auth user, the rest of the directory tree
       # gets owned by root.  This chown is needed in case what's really happening
     &System("/bin/chown -R www:www  $fulldir");      # is that a file system user is being demoted to internal user...
 }  
 elsif ($authentication eq "krb4:") { # Kerberos version 4 authentication      if($authentication eq "internal:") {
     &System("/bin/chown -R $username".':'.$username." ".$fulldir);   #  In case the user was a unix/filesystem authenticated user,
     &JoinGroup($username);   #  we'll take a bit of time here to write  a script in the
 }   #  user's home directory that can reset ownerships and permissions
 elsif ($authentication eq "localauth:") { # Local authentiation   #  back the way the used to be.
     &System("/bin/chown -R  $username".':'.$username."  $fulldir");  
 }   # This can take long enough for lond to time out, so we'll do it
 else {   # in a separate process that we'll not wait for.
     if($DEBUG) {   #
  print("Authentication not legal".$authentication);   my $fpid = fork;
    if($fpid) {
       &DisableRoot;
       exit 0;
    } else {
       print "Forked\n";
       POSIX::setsid(); # Disassociate from parent.
       print "Separate session\n";
       &write_restore_script($homedir);
       print "Restore script written\n";
       &System("/bin/chown -R root:root ".$homedir);
       &System("/bin/chown -R www:www  ".$fulldir);
       print "Exiting\n";
       exit 0;
    }
       } else {
    &System("/bin/chown -R www:www  ".$fulldir);
     }      }
     &DisableRoot;  
     exit 5;  
   
 }  }
 &DisableRoot;  &DisableRoot;
Line 261  sub EnableRoot { Line 304  sub EnableRoot {
  # root capability is already enabled   # root capability is already enabled
     }      }
     if($DEBUG) {      if($DEBUG) {
  print("Enable Root - id =  $> \n");   print("Enable Root - id =  $> $<\n");
     }      }
     return $>;        return $>;  
 }  }
Line 278  sub DisableRoot { Line 321  sub DisableRoot {
  print("Disable root: id = ".$>."\n");   print("Disable root: id = ".$>."\n");
     }      }
 }  }
   #
   #  Join the www user to the user's group.
   #  we must be running with euid as root at this time.
   #
 sub JoinGroup {  sub JoinGroup {
     my $usergroup = shift;      my $usergroup = shift;
   
     my $groups = `/usr/bin/groups www`;      my $groups = `/usr/bin/groups www`;
       # untaint
       my ($safegroups)=($groups=~/:\s+([\s\w]+)/);
       $groups=$safegroups;
     chomp $groups; $groups=~s/^\S+\s+\:\s+//;      chomp $groups; $groups=~s/^\S+\s+\:\s+//;
     my @grouplist=split(/\s+/,$groups);      my @grouplist=split(/\s+/,$groups);
     my @ugrouplist=grep {!/www|$usergroup/} @grouplist;      my @ugrouplist=grep {!/www|$usergroup/} @grouplist;
Line 294  sub JoinGroup { Line 343  sub JoinGroup {
  }   }
  exit 6;   exit 6;
     }      }
           if (-e '/var/run/httpd.pid') {
    open(PID,'/var/run/httpd.pid');
    my $pid=<PID>;
    close(PID);
    my ($safepid) = $pid=~ /(\d+)/;
    $pid = $safepid;
    if ($pid) {
       my $status = system("kill -USR1 $safepid");
    }
       }
 }  }
   
   
   
 sub System {  sub System {
     my $command = shift;      my ($command,@args) = @_;
     if($DEBUG) {      if($DEBUG) {
  print("system: $command \n");   print("system: $command with args ".join(' ',@args)."\n");
     }      }
     system($command);      system($command,@args);
   }
   
   
   
   
   
   #
   #   This file contains code to recursively process
   #   a Directory.  This is a bit more powerful
   #   than File::Find in that we pass the full
   #   stat info to the processing function.
   #     For each file in the specified directory subtree, 
   #   The user's Code reference is invoked for all files, regular and otherwise
   #   except:
   #      ., ..
   #
   #  Parameters:
   #     code_ref    - Code reference, invoked for each file in the tree.
   #                   as follows:  CodeRef(directory, name, statinfo)
   #                   directory the path to the directory holding the file.
   #                   name      the name of the file within Directory.
   #                   statinfo  a reference to the stat of the file.
   #     start_dir   - The starting point of the directory walk.
   #
   # NOTE:
   #   Yes, we could have just used File::Find, but since we have to get the
   #   stat anyway, this is actually simpler, as File::Find would have gotten
   #   the stat to figure out the file type and then we would have gotten it
   #   again.
   #
   
   sub process_tree {
       my ($code_ref, $start_dir)  = @_;
   
       my $dir = new DirHandle $start_dir; 
       if (!defined($dir)) {
           print "Failed to  open dirhandle: $start_dir\n";
       }
   
       # Now iterate through this level of the tree:
   
       while (defined (my $name = $dir->read)) {
    next if $name =~/^\.\.?$/;       # Skip ., .. (see cookbook pg 319)
   
    my $full_name   = $start_dir.$path_sep.$name; # Full filename path.
    my @stat_info  = lstat($full_name);
    my $mode       = $stat_info[2];
    my $type       = $mode & 0170000; #  File type.
   
    # Unless the file type is a symlink, call the user code:
   
    unless ($type == S_IFLNK) {
       &$code_ref($start_dir, $name, \@stat_info);
    }
   
    # If the entry is a directory, we need to recurse:
   
   
    if (($type ==  S_IFDIR) != 0) {
       &process_tree($code_ref, $full_name);
    }
       }
   
   }
   #
   #   Callback from process_tree to write the script lines
   #   requried to restore files to current ownership and permission.
   # Parameters:
   #    dir         - Name of the directory the file lives in.
   #    name        - Name of the file itself.
   #    statinfo    - Array from lstat called on the file.
   #
   #
   sub write_script {
       my ($dir, $name, $statinfo) = @_;
   
       my $fullname = $dir.$path_sep.$name;
   
       #  We're going to '' the name, but we need to deal with embedded
       #  ' characters.  Using " is much worse as we'd then have to
       #  escape all the shell escapes too.  This way all we need
       #  to do is replace ' with '\''
   
       $fullname =~ s/\'/\'\\\'\'/g;
   
       my $perms    = $statinfo->[2] & 0777; # Just permissions.
       printf CHMODSCRIPT "chmod 0%o '%s'\n", $perms, $fullname;
       printf CHMODSCRIPT "chown %d:%d '%s'\n", $statinfo->[4], $statinfo->[5], 
                                            $fullname
   
   
   }
   # 
   #    Write a script in the user's home directory that can restore
   #    the permissions and ownerhips of all the files in the directory
   #    tree to their current ownerships and permissions.  This is done
   #    prior to making the user into an internally authenticated user
   #    in case they were previously file system authenticated and
   #    need to go back.
   #      The file we will create will be of the form
   #        restore_n.sh  Where n is a number that we will keep
   #   incrementing as needed until there isn't a file by that name.
   #   
   # Parameters:
   #    dir      - Path to the user's home directory.
   #
   sub write_restore_script {
       my ($dir)   = @_;
   
       #   Create a unique file:
   
       my $version_number     = 0;
       my $filename           = 'restore_'.$version_number.'.sh';
       my $full_name           = $dir.$path_sep.$filename;
   
       while(-e $full_name) {
    $version_number++;
    $filename         = 'restore_'.$version_number.'.sh';
    $full_name        = $dir.$path_sep.$filename;
       }
       # $full_name is the full path of a file that does not yet exist
       # of the form we want:
   
       open(CHMODSCRIPT, "> $full_name");
   
       &process_tree(\&write_script, $dir);
   
       close(CHMODSCRIPT);
   
       chmod(0750, $full_name);
   
 }  }
   
   

Removed from v.1.3  
changed lines
  Added in v.1.17


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