File:  [LON-CAPA] / loncom / Attic / lchtmldir
Revision 1.9: download - view: text, annotated - select for diffs
Mon Oct 18 10:56:50 2004 UTC (19 years, 7 months ago) by foxr
Branches: MAIN
CVS tags: HEAD
DEFECT 550: Reset ownership of top level user directory if internal.
     This is required for Fs -> internal auth changes of authors.

    1: #!/usr/bin/perl
    2: 
    3: # The Learning Online Network with CAPA
    4: #
    5: # Copyright Michigan State University Board of Trustees
    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: # http://www.lon-capa.org/
   26: #
   27: #  lchtmldir - LONC-CAPA setuid script to:
   28: #              o If necessary, add a public_html directory 
   29: #                to the specified user home directory.
   30: #              o Set the permissions according to the authentication type.
   31: #
   32: #  Motivations:
   33: #     Originally, account creation would create a public_html
   34: #     directory for unix authorized people only.  It is possible to have
   35: #     Kerberos, internal and locally authorized 'users' which may be authors
   36: #     and hence need a properly owned an protected public_html directory
   37: #     to serve as their construction space.
   38: #
   39: #  Author:
   40: #    Ron Fox
   41: #    NSCL
   42: #    Michigan State University8
   43: #    East Lansing, MI 48824-1321
   44: 
   45: #   General flow of control:
   46: #   1. Validate process state (must be run as www).
   47: #   2. Validate parameters:  Need two parameters:
   48: #         o Homedir  - Home diretory of user 
   49: #         o Username - Name of the user.
   50: #         o AuthMode - Authentication mode, can be:
   51: #                      - unix
   52: #                      - internal
   53: #                      - krb4
   54: #                      - localauth
   55: #  3. Untaint the usename and home directory
   56: #
   57: #  4. As root if necessary, create $Homedir/public_html
   58: #  5. Set ownership/permissions according to authentication mode (AuthMode)
   59: #       - unix - ~owner:www/2775
   60: #       - krb4 - ~owner:www/2775
   61: #       - internal - www:www/2775
   62: #       - local    - www:www/2775
   63: #
   64: 
   65: #
   66: #   Take a few precautions to be sure that we're not vulnerable to trojan
   67: #   horses and other fine issues:
   68: #
   69: use strict; 
   70: 
   71: $ENV{'PATH'} = '/bin:/usr/bin:/usr/local/sbin:/home/httpd/perl';
   72: delete @ENV{qw{IFS CDPATH ENV BASH_ENV}};
   73: 
   74: my $DEBUG = 0;                         # .nonzero -> Debug printing enabled.
   75: 
   76: 
   77: # If the UID of the running process is not www exit with error.
   78: 
   79: if ($DEBUG) {
   80:     print("Checking uid...\n");
   81: }
   82: my $wwwid = getpwnam('www');
   83: &DisableRoot;
   84: if($wwwid != $>) {
   85:     if ($DEBUG) {
   86: 	print("User ID incorrect.  This program must be run as user 'www'\n");
   87:     }
   88:     exit 1;			# Exit with error status.
   89: }
   90: 
   91: # There must be three 'command line' parameters.  The first
   92: # is the home directory of the user.
   93: # The second is the name of the user.  This is only referenced
   94: # in code branches dealing with unix mode authentication.
   95: # The last is the authentication mode which must be one of unix, internal
   96: # krb4 or localauth.
   97: #   If there is an error in the argument count or countents, we exit with an
   98: # error.
   99: 
  100: if ($DEBUG) {
  101:     print("Checking parameters: \n");
  102: }
  103: if(@ARGV != 3) {
  104:     if($DEBUG) {
  105: 	print("Error: lchtmldir need 3 parameters \n");
  106:     }
  107:     exit 2;
  108: }
  109: my ($dir,$username,$authentication) = @ARGV;
  110: 
  111: if($DEBUG) {
  112:     print ("Directory = $dir \n");
  113:     print ("User      = $username \n");
  114:     print ("Authmode  = $authentication \n");
  115: 
  116: }
  117: 
  118: if( $authentication ne "unix:"     &&
  119:     $authentication ne "internal:" &&
  120:     $authentication !~ /^krb(4|5):(.*)/ &&
  121:     $authentication ne "localauth:") {
  122:     if($DEBUG) {
  123: 	print("Invalid authentication parameter: ".$authentication."\n");
  124: 	print("Should be one of: unix, internal, krb4, localauth\n");
  125:     }
  126:     exit 3;
  127: }
  128: 
  129: # Untaint the username.
  130: 
  131: my $match = $username =~ /^(\w+)$/;
  132: my $patt  = $1;
  133:  
  134: if($DEBUG) {
  135:    print("Username word match flag = ".$match."\n");
  136:     print("Match value = ".$patt."\n");
  137: }
  138: 
  139: my $safeuser = $patt;
  140: if($DEBUG) {
  141:     print("Save username = $safeuser \n");
  142: }
  143: if(($username ne $safeuser) or ($safeuser!~/^[A-za-z]/)) {
  144:     if($DEBUG) {
  145: 	print("User name $username had illegal characters\n");
  146:     }
  147:     exit 4;
  148: }
  149: 
  150: #untaint the base directory require that the dir contain only 
  151: # alphas, / numbers or underscores, and end in /$safeuser
  152: 
  153: $dir =~ /(^([\w\/]+))/;
  154: 
  155: my $dirtry1 = $1;
  156: 
  157: $dir =~ /$\/$safeuser/;
  158: my $dirtry2 = $1;
  159: 
  160: if(($dirtry1 ne $dir) or ($dirtry2 ne $dir)) {
  161:     if ($DEBUG) {
  162: 	print("Directory $dir is not a valid home for $safeuser\n");
  163:     }
  164:     exit 5;
  165: }
  166: 
  167: 
  168: # As root, create the directory.
  169: 
  170: my $homedir = $dirtry1;
  171: my $fulldir = $homedir."/public_html";
  172: 
  173: if($DEBUG) {
  174:     print("Full directory path is: $fulldir \n");
  175: }
  176: if(!( -e $dirtry1)) {
  177:     if($DEBUG) {
  178: 	print("User's home directory $dirtry1 does not exist\n");
  179:     }
  180:     if ($authentication eq "unix:") {
  181:         exit 6;
  182:     }
  183: }
  184: &EnableRoot;
  185: 
  186: &System("/bin/mkdir -p $fulldir")   unless (-e $fulldir);
  187:     unless(-e $fulldir."/index.html") {
  188: 	open OUT,">".$fulldir."/index.html";
  189: 	print OUT<<END;
  190: 	<html>
  191: 	<head>
  192: 	<title>$safeuser</title>
  193:         </head>
  194:         <body bgcolor="#ccffdd">
  195:         <h1>$safeuser Construction Space</h1>
  196:           <h2>
  197:             The Learning<i>Online</i> Network with Computer-Assisted Personalized Approach
  198:           </h2>
  199:           <p>
  200: This is your construction space within LON-CAPA, where you would construct resources which are meant to be
  201: used across courses and institutions.
  202:           </p>
  203:           <p>
  204: Material within this area can only be seen and edited by $safeuser and designated co-authors. To make
  205: it available to students and other instructors, the material needs to be published.
  206:           </p>
  207:         </body>
  208:        </html>
  209: END
  210:     close OUT;
  211:     }
  212: 
  213: &System("/bin/chmod  02775  $fulldir");
  214: &System("/bin/chmod  0775  $fulldir"."/index.html");
  215: 
  216: 
  217: # Based on the authentiation mode, set the ownership of the directory.
  218: 
  219: if($authentication eq "unix:") {	# Unix mode authentication...
  220:     &System("/bin/chown -R   $safeuser".":".$safeuser." ".$fulldir);
  221:     &JoinGroup($safeuser);
  222: } else {
  223:     # Internal, Kerberos, and Local authentication are for users
  224:     # who do not have unix accounts on the system.  Therefore we
  225:     # will give ownership of their public_html directories to www:www
  226:     # If the user is an internal auth user, the rest of the directory tree
  227:     # gets owned by root.  This chown is needed in case what's really happening
  228:     # is that a file system user is being demoted to internal user...
  229: 
  230:     if($authentication eq "internal:") {
  231: 	&System("/bin/chown -R root:root ".$homedir);
  232:     }
  233:     &System("/bin/chown -R www:www  ".$fulldir);
  234: }
  235: &DisableRoot;
  236: 
  237: exit 0;
  238: 
  239: #----------------------------------------------------------------------
  240: #
  241: #  Local utility procedures.
  242: #  These include:
  243: #     EnableRoot - Start running as root.
  244: #     DisableRoot- Stop running as root.
  245: #     JoinGroup  - Join www to the specified group.
  246: 
  247: # Turn on as root:
  248: 
  249: sub EnableRoot {
  250:     if ($wwwid==$>) {
  251: 	($<,$>)=($>,$<);
  252: 	($(,$))=($),$();
  253:     }
  254:     else {
  255: 	# root capability is already enabled
  256:     }
  257:     if($DEBUG) {
  258: 	print("Enable Root - id =  $> $<\n");
  259:     }
  260:     return $>;  
  261: }
  262: 
  263: sub DisableRoot {
  264:     if ($wwwid==$<) {
  265: 	($<,$>)=($>,$<);
  266: 	($(,$))=($),$();
  267:     }
  268:     else {
  269: 	# root capability is already disabled
  270:     }
  271:     if($DEBUG) {
  272: 	print("Disable root: id = ".$>."\n");
  273:     }
  274: }
  275: 
  276: sub JoinGroup {
  277:     my $usergroup = shift;
  278: 
  279:     my $groups = `/usr/bin/groups www`;
  280:     # untaint
  281:     my ($safegroups)=($groups=~/:\s+([\s\w]+)/);
  282:     $groups=$safegroups;
  283:     chomp $groups; $groups=~s/^\S+\s+\:\s+//;
  284:     my @grouplist=split(/\s+/,$groups);
  285:     my @ugrouplist=grep {!/www|$usergroup/} @grouplist;
  286:     my $gl=join(',',(@ugrouplist,$usergroup));
  287:     if (&System('/usr/sbin/usermod','-G',$gl,'www')) {
  288: 	if($DEBUG) {
  289: 	    print "Error. Could not make www a member of the group ".
  290: 		"\"$usergroup\".\n";
  291: 	}
  292: 	exit 6;
  293:     }
  294:     
  295: }
  296: 
  297: 
  298: 
  299: sub System {
  300:     my ($command,@args) = @_;
  301:     if($DEBUG) {
  302: 	print("system: $command with args ".join(' ',@args)."\n");
  303:     }
  304:     system($command,@args);
  305: }
  306: 
  307: 
  308: 
  309: 

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