File:  [LON-CAPA] / loncom / lond
Revision 1.2: download - view: text, annotated - select for diffs
Tue Oct 26 20:24:47 1999 UTC (24 years, 6 months ago) by www
Branches: MAIN
CVS tags: HEAD
Implementation of encryption
Different login mechanisms
IP Spoof Protection

    1: #!/usr/bin/perl
    2: # The LearningOnline Network
    3: # lond "LON Daemon" Server (port "LOND" 5663)
    4: # 5/26/99,6/4,6/10,6/11,6/14,6/15,6/26,6/28,6/30,
    5: # 7/8,7/9,7/10,7/12,7/17,7/19,9/21,
    6: # 10/7,10/8,10/9,10/11,10/13,10/15 Gerd Kortemeyer
    7: # based on "Perl Cookbook" ISBN 1-56592-243-3
    8: # preforker - server who forks first
    9: # runs as a daemon
   10: # HUPs
   11: # uses IDEA encryption
   12: 
   13: use IO::Socket;
   14: use IO::File;
   15: use Apache::File;
   16: use Symbol;
   17: use POSIX;
   18: use Crypt::IDEA;
   19: use LWP::UserAgent();
   20: 
   21: # ------------------------------------ Read httpd access.conf and get variables
   22: 
   23: open (CONFIG,"/etc/httpd/conf/access.conf") || die "Can't read access.conf";
   24: 
   25: while ($configline=<CONFIG>) {
   26:     if ($configline =~ /PerlSetVar/) {
   27: 	my ($dummy,$varname,$varvalue)=split(/\s+/,$configline);
   28:         $perlvar{$varname}=$varvalue;
   29:     }
   30: }
   31: close(CONFIG);
   32: 
   33: $PREFORK=4; # number of children to maintain, at least four spare
   34: 
   35: # ------------------------------------------------------------- Read hosts file
   36: 
   37: open (CONFIG,"$perlvar{'lonTabDir'}/hosts.tab") || die "Can't read host file";
   38: 
   39: while ($configline=<CONFIG>) {
   40:     my ($id,$domain,$role,$name,$ip)=split(/:/,$configline);
   41:     chomp($ip);
   42:     $hostid{$ip}=$id;
   43:     if ($id eq $perlvar{'lonHostID'}) { $thisserver=$name; }
   44:     $PREFORK++;
   45: }
   46: close(CONFIG);
   47: 
   48: # establish SERVER socket, bind and listen.
   49: $server = IO::Socket::INET->new(LocalPort => $perlvar{'londPort'},
   50:                                 Type      => SOCK_STREAM,
   51:                                 Proto     => 'tcp',
   52:                                 Reuse     => 1,
   53:                                 Listen    => 10 )
   54:   or die "making socket: $@\n";
   55: 
   56: # --------------------------------------------------------- Do global variables
   57: 
   58: # global variables
   59: 
   60: $MAX_CLIENTS_PER_CHILD  = 5;        # number of clients each child should 
   61:                                     # process
   62: %children               = ();       # keys are current child process IDs
   63: $children               = 0;        # current number of children
   64: 
   65: sub REAPER {                        # takes care of dead children
   66:     $SIG{CHLD} = \&REAPER;
   67:     my $pid = wait;
   68:     $children --;
   69:     &logthis("Child $pid died");
   70:     delete $children{$pid};
   71: }
   72: 
   73: sub HUNTSMAN {                      # signal handler for SIGINT
   74:     local($SIG{CHLD}) = 'IGNORE';   # we're going to kill our children
   75:     kill 'INT' => keys %children;
   76:     my $execdir=$perlvar{'lonDaemons'};
   77:     unlink("$execdir/logs/lond.pid");
   78:     &logthis("Shutting down");
   79:     exit;                           # clean up with dignity
   80: }
   81: 
   82: sub HUPSMAN {                      # signal handler for SIGHUP
   83:     local($SIG{CHLD}) = 'IGNORE';  # we're going to kill our children
   84:     kill 'INT' => keys %children;
   85:     close($server);                # free up socket
   86:     &logthis("Restarting");
   87:     my $execdir=$perlvar{'lonDaemons'};
   88:     exec("$execdir/lond");         # here we go again
   89: }
   90: 
   91: # --------------------------------------------------------------------- Logging
   92: 
   93: sub logthis {
   94:     my $message=shift;
   95:     my $execdir=$perlvar{'lonDaemons'};
   96:     my $fh=IO::File->new(">>$execdir/logs/lond.log");
   97:     my $now=time;
   98:     my $local=localtime($now);
   99:     print $fh "$local ($$): $message\n";
  100: }
  101: 
  102: # ----------------------------------------------------------- Send USR1 to lonc
  103: 
  104: sub reconlonc {
  105:     my $peerfile=shift;
  106:     &logthis("Trying to reconnect for $peerfile");
  107:     my $loncfile="$perlvar{'lonDaemons'}/logs/lonc.pid";
  108:     if (my $fh=IO::File->new("$loncfile")) {
  109: 	my $loncpid=<$fh>;
  110:         chomp($loncpid);
  111:         if (kill 0 => $loncpid) {
  112: 	    &logthis("lonc at pid $loncpid responding, sending USR1");
  113:             kill USR1 => $loncpid;
  114:             sleep 1;
  115:             if (-e "$peerfile") { return; }
  116:             &logthis("$peerfile still not there, give it another try");
  117:             sleep 5;
  118:             if (-e "$peerfile") { return; }
  119:             &logthis("$peerfile still not there, giving up");
  120:         } else {
  121: 	    &logthis("lonc at pid $loncpid not responding, giving up");
  122:         }
  123:     } else {
  124:         &logthis('lonc not running, giving up');
  125:     }
  126: }
  127: 
  128: # -------------------------------------------------- Non-critical communication
  129: sub subreply {
  130:     my ($cmd,$server)=@_;
  131:     my $peerfile="$perlvar{'lonSockDir'}/$server";
  132:     my $sclient=IO::Socket::UNIX->new(Peer    =>"$peerfile",
  133:                                       Type    => SOCK_STREAM,
  134:                                       Timeout => 10)
  135:        or return "con_lost";
  136:     print $sclient "$cmd\n";
  137:     my $answer=<$sclient>;
  138:     chomp($answer);
  139:     if (!$answer) { $answer="con_lost"; }
  140:     return $answer;
  141: }
  142: 
  143: sub reply {
  144:   my ($cmd,$server)=@_;
  145:   my $answer;
  146:   if ($server ne $perlvar{'lonHostID'}) { 
  147:     $answer=subreply($cmd,$server);
  148:     if ($answer eq 'con_lost') {
  149: 	$answer=subreply("ping",$server);
  150:         if ($answer ne $server) {
  151:            &reconlonc("$perlvar{'lonSockDir'}/$server");
  152:         }
  153:         $answer=subreply($cmd,$server);
  154:     }
  155:   } else {
  156:     $answer='self_reply';
  157:   } 
  158:   return $answer;
  159: }
  160: 
  161: # -------------------------------------------- Return path to profile directory
  162: sub propath {
  163:     my ($udom,$uname)=@_;
  164:     $udom=~s/\W//g;
  165:     $uname=~s/\W//g;
  166:     my $subdir=$uname;
  167:     $subdir =~ s/(.)(.)(.).*/$1\/$2\/$3/;
  168:     my $proname="$perlvar{'lonUsersDir'}/$udom/$subdir/$uname";
  169:     return $proname;
  170: } 
  171: 
  172: # --------------------------------------- Is this the home server of an author?
  173: sub ishome {
  174:     my $author=shift;
  175:     $author=~s/\/home\/httpd\/html\/res\/([^\/]*)\/([^\/]*).*/$1\/$2/;
  176:     my ($udom,$uname)=split(/\//,$author);
  177:     my $proname=propath($udom,$uname);
  178:     if (-e $proname) {
  179: 	return 'owner';
  180:     } else {
  181:         return 'not_owner';
  182:     }
  183: }
  184: 
  185: # ======================================================= Continue main program
  186: # ---------------------------------------------------- Fork once and dissociate
  187: 
  188: $fpid=fork;
  189: exit if $fpid;
  190: die "Couldn't fork: $!" unless defined ($fpid);
  191: 
  192: POSIX::setsid() or die "Can't start new session: $!";
  193: 
  194: # ------------------------------------------------------- Write our PID on disk
  195: 
  196: $execdir=$perlvar{'lonDaemons'};
  197: open (PIDSAVE,">$execdir/logs/lond.pid");
  198: print PIDSAVE "$$\n";
  199: close(PIDSAVE);
  200: &logthis("Starting");
  201: 
  202: # ------------------------------------------------------- Now we are on our own
  203:     
  204: # Fork off our children.
  205: for (1 .. $PREFORK) {
  206:     make_new_child();
  207: }
  208: 
  209: # ----------------------------------------------------- Install signal handlers
  210: 
  211: $SIG{CHLD} = \&REAPER;
  212: $SIG{INT}  = $SIG{TERM} = \&HUNTSMAN;
  213: $SIG{HUP}  = \&HUPSMAN;
  214: 
  215: # And maintain the population.
  216: while (1) {
  217:     sleep;                          # wait for a signal (i.e., child's death)
  218:     for ($i = $children; $i < $PREFORK; $i++) {
  219:         make_new_child();           # top up the child pool
  220:     }
  221: }
  222: 
  223: sub make_new_child {
  224:     my $pid;
  225:     my $cipher;
  226:     my $sigset;
  227:     &logthis("Attempting to start child");    
  228:     # block signal for fork
  229:     $sigset = POSIX::SigSet->new(SIGINT);
  230:     sigprocmask(SIG_BLOCK, $sigset)
  231:         or die "Can't block SIGINT for fork: $!\n";
  232:     
  233:     die "fork: $!" unless defined ($pid = fork);
  234:     
  235:     if ($pid) {
  236:         # Parent records the child's birth and returns.
  237:         sigprocmask(SIG_UNBLOCK, $sigset)
  238:             or die "Can't unblock SIGINT for fork: $!\n";
  239:         $children{$pid} = 1;
  240:         $children++;
  241:         return;
  242:     } else {
  243:         # Child can *not* return from this subroutine.
  244:         $SIG{INT} = 'DEFAULT';      # make SIGINT kill us as it did before
  245:     
  246:         # unblock signals
  247:         sigprocmask(SIG_UNBLOCK, $sigset)
  248:             or die "Can't unblock SIGINT for fork: $!\n";
  249:     
  250:         # handle connections until we've reached $MAX_CLIENTS_PER_CHILD
  251:         for ($i=0; $i < $MAX_CLIENTS_PER_CHILD; $i++) {
  252:             $client = $server->accept()     or last;
  253: 
  254: # =============================================================================
  255:             # do something with the connection
  256: # -----------------------------------------------------------------------------
  257:             # see if we know client and check for spoof IP by challenge
  258:             my $caller=getpeername($client);
  259:             my ($port,$iaddr)=unpack_sockaddr_in($caller);
  260:             my $clientip=inet_ntoa($iaddr);
  261:             my $clientrec=($hostid{$clientip} ne undef);
  262:             &logthis("Connect from $clientip ($hostid{$clientip})");
  263:             my $clientok;
  264:             if ($clientrec) {
  265: 	      my $remotereq=<$client>;
  266:               $remotereq=~s/\W//g;
  267:               if ($remotereq eq 'init') {
  268: 		  my $challenge="$$".time;
  269:                   print $client "$challenge\n";
  270:                   $remotereq=<$client>;
  271:                   $remotereq=~s/\W//g;
  272:                   if ($challenge eq $remotereq) {
  273: 		      $clientok=1;
  274:                       print $client "ok\n";
  275:                   } else {
  276: 		      &logthis("$clientip did not reply challenge");
  277:                   }
  278:               } else {
  279: 		  &logthis("$clientip failed to initialize: >$remotereq<");
  280:               }
  281: 	    } else {
  282:               &logthis("Unknown client $clientip");
  283:             }
  284:             if ($clientok) {
  285: # ---------------- New known client connecting, could mean machine online again
  286: 	      &reconlonc("$perlvar{'lonSockDir'}/$hostid{$clientip}");
  287: # ------------------------------------------------------------ Process requests
  288:               while (my $userinput=<$client>) {
  289:                 chomp($userinput);
  290:                 my $wasenc=0;
  291: # ------------------------------------------------------------ See if encrypted
  292: 		if ($userinput =~ /^enc/) {
  293: 		  if ($cipher) {
  294:                     my ($cmd,$cmdlength,$encinput)=split(/:/,$userinput);
  295: 		    $userinput='';
  296:                     for (my $encidx=0;$encidx<length($encinput);$encidx+=16) {
  297:                        $userinput.=
  298: 			   $cipher->decrypt(
  299:                             pack("H16",substr($encinput,$encidx,16))
  300:                            );
  301: 		    }
  302: 		    $userinput=substr($userinput,0,$cmdlength);
  303:                     $wasenc=1;
  304: 		  }
  305: 		}
  306: # ------------------------------------------------------------- Normal commands
  307: # ------------------------------------------------------------------------ ping
  308: 		   if ($userinput =~ /^ping/) {
  309:                        print $client "$perlvar{'lonHostID'}\n";
  310: # ------------------------------------------------------------------------ pong
  311: 		   } elsif ($userinput =~ /^pong/) {
  312:                        $reply=reply("ping",$hostid{$clientip});
  313:                        print $client "$perlvar{'lonHostID'}:$reply\n"; 
  314: # ------------------------------------------------------------------------ ekey
  315: 		   } elsif ($userinput =~ /^ekey/) {
  316:                        my $buildkey=time.$$.int(rand 100000);
  317:                        $buildkey=~tr/1-6/A-F/;
  318:                        $buildkey=int(rand 100000).$buildkey.int(rand 100000);
  319:                        my $key=$perlvar{'lonHostID'}.$hostid{$clientip};
  320:                        $key=~tr/a-z/A-Z/;
  321:                        $key=~tr/G-P/0-9/;
  322:                        $key=~tr/Q-Z/0-9/;
  323:                        $key=$key.$buildkey.$key.$buildkey.$key.$buildkey;
  324:                        $key=substr($key,0,32);
  325:                        my $cipherkey=pack("H32",$key);
  326:                        $cipher=new IDEA $cipherkey;
  327:                        print $client "$buildkey\n"; 
  328: # ------------------------------------------------------------------------ load
  329: 		   } elsif ($userinput =~ /^load/) {
  330:                        my $loadavg;
  331:                        {
  332:                           my $loadfile=IO::File->new('/proc/loadavg');
  333:                           $loadavg=<$loadfile>;
  334:                        }
  335:                        $loadavg =~ s/\s.*//g;
  336:                        my $loadpercent=100*$loadavg/$perlvar{'lonLoadLim'};
  337: 		       print $client "$loadpercent\n";
  338: # ------------------------------------------------------------------------ auth
  339:                    } elsif ($userinput =~ /^auth/) {
  340: 		     if ($wasenc==1) {
  341:                        my ($cmd,$udom,$uname,$upass)=split(/:/,$userinput);
  342:                        chomp($upass);
  343:                        my $proname=propath($udom,$uname);
  344:                        my $passfilename="$proname/passwd";
  345:                        if (-e $passfilename) {
  346:                           my $pf = IO::File->new($passfilename);
  347:                           my $realpasswd=<$pf>;
  348:                           chomp($realpasswd);
  349:                           my ($howpwd,$contentpwd)=split(/:/,$realpasswd);
  350:                           my $pwdcorrect=0;
  351:                           if ($howpwd eq 'internal') {
  352: 			      $pwdcorrect=
  353: 				  (crypt($upass,$contentpwd) eq $contentpwd);
  354:                           } elsif ($howpwd eq 'unix') {
  355:                               $contentpwd=(getpwnam($uname))[1];
  356:                               $pwdcorrect=
  357:                                   (crypt($upass,$contentpwd) eq $contentpwd);
  358:                           }
  359:                           if ($pwdcorrect) {
  360:                              print $client "authorized\n";
  361:                           } else {
  362:                              print $client "non_authorized\n";
  363:                           }  
  364: 		       } else {
  365:                           print $client "unknown_user\n";
  366:                        }
  367: 		     } else {
  368: 		       print $client "refused\n";
  369: 		     }
  370: # ---------------------------------------------------------------------- passwd
  371:                    } elsif ($userinput =~ /^passwd/) {
  372: 		     if ($wasenc==1) {
  373:                        my 
  374:                        ($cmd,$udom,$uname,$upass,$npass)=split(/:/,$userinput);
  375:                        chomp($npass);
  376:                        my $proname=propath($udom,$uname);
  377:                        my $passfilename="$proname/passwd";
  378:                        if (-e $passfilename) {
  379: 			   my $realpasswd;
  380:                           { my $pf = IO::File->new($passfilename);
  381: 			    $realpasswd=<$pf>; }
  382:                           chomp($realpasswd);
  383:                           my ($howpwd,$contentpwd)=split(/:/,$realpasswd);
  384:                           if ($howpwd eq 'internal') {
  385: 			   if (crypt($upass,$contentpwd) eq $contentpwd) {
  386: 			     my $salt=time;
  387:                              $salt=substr($salt,6,2);
  388: 			     my $ncpass=crypt($npass,$salt);
  389:                              { my $pf = IO::File->new(">$passfilename");
  390:  	  		       print $pf "internal:$ncpass\n";; }             
  391:                              print $client "ok\n";
  392:                            } else {
  393:                              print $client "non_authorized\n";
  394:                            }
  395:                           } else {
  396:                             print $client "auth_mode_error\n";
  397:                           }  
  398: 		       } else {
  399:                           print $client "unknown_user\n";
  400:                        }
  401: 		     } else {
  402: 		       print $client "refused\n";
  403: 		     }
  404: # ------------------------------------------------------------------------ home
  405:                    } elsif ($userinput =~ /^home/) {
  406:                        my ($cmd,$udom,$uname)=split(/:/,$userinput);
  407:                        chomp($uname);
  408:                        my $proname=propath($udom,$uname);
  409:                        if (-e $proname) {
  410:                           print $client "found\n";
  411:                        } else {
  412: 			  print $client "not_found\n";
  413:                        }
  414: # ---------------------------------------------------------------------- update
  415:                    } elsif ($userinput =~ /^update/) {
  416:                        my ($cmd,$fname)=split(/:/,$userinput);
  417:                        my $ownership=ishome($fname);
  418:                        if ($ownership eq 'not_owner') {
  419:                         if (-e $fname) {
  420:                           my ($dev,$ino,$mode,$nlink,
  421:                               $uid,$gid,$rdev,$size,
  422:                               $atime,$mtime,$ctime,
  423:                               $blksize,$blocks)=stat($fname);
  424:                           $now=time;
  425:                           $since=$now-$atime;
  426:                           if ($since>$perlvar{'lonExpire'}) {
  427:                               $reply=
  428:                                     reply("unsub:$fname","$hostid{$clientip}");
  429:                               unlink("$fname");
  430:                           } else {
  431: 			     my $transname="$fname.in.transfer";
  432:                              my $remoteurl=
  433:                                     reply("sub:$fname","$hostid{$clientip}");
  434:                              my $response;
  435:                               {
  436:                              my $ua=new LWP::UserAgent;
  437:                              my $request=new HTTP::Request('GET',"$remoteurl");
  438:                              $response=$ua->request($request,$transname);
  439: 			      }
  440:                              if ($response->is_error()) {
  441: 				 unline($transname);
  442:                                  my $message=$response->status_line;
  443:                                  &logthis(
  444:                                   "LWP GET: $message for $fname ($remoteurl)");
  445:                              } else {
  446:                                  rename($transname,$fname);
  447: 			     }
  448:                           }
  449:                           print $client "ok\n";
  450:                         } else {
  451:                           print $client "not_found\n";
  452:                         }
  453: 		       } else {
  454: 			print $client "rejected\n";
  455:                        }
  456: # ----------------------------------------------------------------- unsubscribe
  457:                    } elsif ($userinput =~ /^unsub/) {
  458:                        my ($cmd,$fname)=split(/:/,$userinput);
  459:                        if (-e $fname) {
  460:                            if (unlink("$fname.$hostid{$clientip}")) {
  461:                               print $client "ok\n";
  462: 			   } else {
  463:                               print $client "not_subscribed\n";
  464: 			   }
  465:                        } else {
  466: 			   print $client "not_found\n";
  467:                        }
  468: # ------------------------------------------------------------------- subscribe
  469:                    } elsif ($userinput =~ /^sub/) {
  470:                        my ($cmd,$fname)=split(/:/,$userinput);
  471:                        my $ownership=ishome($fname);
  472:                        if ($ownership eq 'owner') {
  473:                         if (-e $fname) {
  474:                            $now=time;
  475:                            { 
  476:                             my $sh=IO::File->new(">$fname.$hostid{$clientip}");
  477:                             print $sh "$clientip:$now\n";
  478: 			   }
  479:                            $fname=~s/\/home\/httpd\/html\/res/raw/;
  480:                            $fname="http://$thisserver/".$fname;
  481:                            print $client "$fname\n";
  482:                         } else {
  483: 		      	   print $client "not_found\n";
  484:                         }
  485: 		       } else {
  486:                         print $client "rejected\n";
  487: 		       }
  488: # ------------------------------------------------------------------------- put
  489:                    } elsif ($userinput =~ /^put/) {
  490:                        my ($cmd,$udom,$uname,$namespace,$what)
  491:                           =split(/:/,$userinput);
  492:                        $namespace=~s/\W//g;
  493:                        chomp($what);
  494:                        my $proname=propath($udom,$uname);
  495:                        my $now=time;
  496:                        {
  497: 			   my $hfh;
  498: 			   if (
  499:                              $hfh=IO::File->new(">>$proname/$namespace.hist")
  500: 			       ) { print $hfh "P:$now:$what\n"; }
  501: 		       }
  502:                        my @pairs=split(/\&/,$what);
  503:                        if (dbmopen(%hash,"$proname/$namespace.db",0644)) {
  504:                            foreach $pair (@pairs) {
  505: 			       ($key,$value)=split(/=/,$pair);
  506:                                $hash{$key}=$value;
  507:                            }
  508: 			   if (dbmclose(%hash)) {
  509:                               print $client "ok\n";
  510:                            } else {
  511:                               print $client "error:$!\n";
  512:                            }
  513:                        } else {
  514:                            print $client "error:$!\n";
  515:                        }
  516: # ------------------------------------------------------------------------- get
  517:                    } elsif ($userinput =~ /^get/) {
  518:                        my ($cmd,$udom,$uname,$namespace,$what)
  519:                           =split(/:/,$userinput);
  520:                        $namespace=~s/\W//g;
  521:                        chomp($what);
  522:                        my @queries=split(/\&/,$what);
  523:                        my $proname=propath($udom,$uname);
  524:                        my $qresult='';
  525:                        if (dbmopen(%hash,"$proname/$namespace.db",0644)) {
  526:                            for ($i=0;$i<=$#queries;$i++) {
  527:                                $qresult.="$hash{$queries[$i]}&";
  528:                            }
  529: 			   if (dbmclose(%hash)) {
  530: 		              $qresult=~s/\&$//;
  531:                               print $client "$qresult\n";
  532:                            } else {
  533:                               print $client "error:$!\n";
  534:                            }
  535:                        } else {
  536:                            print $client "error:$!\n";
  537:                        }
  538: # ------------------------------------------------------------------------ eget
  539:                    } elsif ($userinput =~ /^eget/) {
  540:                        my ($cmd,$udom,$uname,$namespace,$what)
  541:                           =split(/:/,$userinput);
  542:                        $namespace=~s/\W//g;
  543:                        chomp($what);
  544:                        my @queries=split(/\&/,$what);
  545:                        my $proname=propath($udom,$uname);
  546:                        my $qresult='';
  547:                        if (dbmopen(%hash,"$proname/$namespace.db",0644)) {
  548:                            for ($i=0;$i<=$#queries;$i++) {
  549:                                $qresult.="$hash{$queries[$i]}&";
  550:                            }
  551: 			   if (dbmclose(%hash)) {
  552: 		              $qresult=~s/\&$//;
  553:                               if ($cipher) {
  554:                                 my $cmdlength=length($qresult);
  555:                                 $qresult.="         ";
  556:                                 my $encqresult='';
  557:                                 for 
  558: 				(my $encidx=0;$encidx<=$cmdlength;$encidx+=8) {
  559:                                  $encqresult.=
  560:                                  unpack("H16",
  561:                                  $cipher->encrypt(substr($qresult,$encidx,8)));
  562:                                 }
  563:                                 print $client "enc:$cmdlength:$encqresult\n";
  564: 			      } else {
  565: 			        print $client "error:no_key\n";
  566:                               }
  567:                            } else {
  568:                               print $client "error:$!\n";
  569:                            }
  570:                        } else {
  571:                            print $client "error:$!\n";
  572:                        }
  573: # ------------------------------------------------------------------------- del
  574:                    } elsif ($userinput =~ /^del/) {
  575:                        my ($cmd,$udom,$uname,$namespace,$what)
  576:                           =split(/:/,$userinput);
  577:                        $namespace=~s/\W//g;
  578:                        chomp($what);
  579:                        my $proname=propath($udom,$uname);
  580:                        my $now=time;
  581:                        {
  582: 			   my $hfh;
  583: 			   if (
  584:                              $hfh=IO::File->new(">>$proname/$namespace.hist")
  585: 			       ) { print $hfh "D:$now:$what\n"; }
  586: 		       }
  587:                        my @keys=split(/\&/,$what);
  588:                        if (dbmopen(%hash,"$proname/$namespace.db",0644)) {
  589:                            foreach $key (@keys) {
  590:                                delete($hash{$key});
  591:                            }
  592: 			   if (dbmclose(%hash)) {
  593:                               print $client "ok\n";
  594:                            } else {
  595:                               print $client "error:$!\n";
  596:                            }
  597:                        } else {
  598:                            print $client "error:$!\n";
  599:                        }
  600: # ------------------------------------------------------------------------ keys
  601:                    } elsif ($userinput =~ /^keys/) {
  602:                        my ($cmd,$udom,$uname,$namespace)
  603:                           =split(/:/,$userinput);
  604:                        $namespace=~s/\W//g;
  605:                        chomp($namespace);
  606:                        my $proname=propath($udom,$uname);
  607:                        my $qresult='';
  608:                        if (dbmopen(%hash,"$proname/$namespace.db",0644)) {
  609:                            foreach $key (keys %hash) {
  610:                                $qresult.="$key&";
  611:                            }
  612: 			   if (dbmclose(%hash)) {
  613: 		              $qresult=~s/\&$//;
  614:                               print $client "$qresult\n";
  615:                            } else {
  616:                               print $client "error:$!\n";
  617:                            }
  618:                        } else {
  619:                            print $client "error:$!\n";
  620:                        }
  621: # ------------------------------------------------------------------------ dump
  622:                    } elsif ($userinput =~ /^dump/) {
  623:                        my ($cmd,$udom,$uname,$namespace)
  624:                           =split(/:/,$userinput);
  625:                        $namespace=~s/\W//g;
  626:                        chomp($namespace);
  627:                        my $proname=propath($udom,$uname);
  628:                        my $qresult='';
  629:                        if (dbmopen(%hash,"$proname/$namespace.db",0644)) {
  630:                            foreach $key (keys %hash) {
  631:                                $qresult.="$key=$hash{$key}&";
  632:                            }
  633: 			   if (dbmclose(%hash)) {
  634: 		              $qresult=~s/\&$//;
  635:                               print $client "$qresult\n";
  636:                            } else {
  637:                               print $client "error:$!\n";
  638:                            }
  639:                        } else {
  640:                            print $client "error:$!\n";
  641:                        }
  642: # ----------------------------------------------------------------------- idput
  643:                    } elsif ($userinput =~ /^idput/) {
  644:                        my ($cmd,$udom,$what)=split(/:/,$userinput);
  645:                        chomp($what);
  646:                        $udom=~s/\W//g;
  647:                        my $proname="$perlvar{'lonUsersDir'}/$udom/ids";
  648:                        my $now=time;
  649:                        {
  650: 			   my $hfh;
  651: 			   if (
  652:                              $hfh=IO::File->new(">>$proname.hist")
  653: 			       ) { print $hfh "P:$now:$what\n"; }
  654: 		       }
  655:                        my @pairs=split(/\&/,$what);
  656:                        if (dbmopen(%hash,"$proname.db",0644)) {
  657:                            foreach $pair (@pairs) {
  658: 			       ($key,$value)=split(/=/,$pair);
  659:                                $hash{$key}=$value;
  660:                            }
  661: 			   if (dbmclose(%hash)) {
  662:                               print $client "ok\n";
  663:                            } else {
  664:                               print $client "error:$!\n";
  665:                            }
  666:                        } else {
  667:                            print $client "error:$!\n";
  668:                        }
  669: # ----------------------------------------------------------------------- idget
  670:                    } elsif ($userinput =~ /^idget/) {
  671:                        my ($cmd,$udom,$what)=split(/:/,$userinput);
  672:                        chomp($what);
  673:                        $udom=~s/\W//g;
  674:                        my $proname="$perlvar{'lonUsersDir'}/$udom/ids";
  675:                        my @queries=split(/\&/,$what);
  676:                        my $qresult='';
  677:                        if (dbmopen(%hash,"$proname.db",0644)) {
  678:                            for ($i=0;$i<=$#queries;$i++) {
  679:                                $qresult.="$hash{$queries[$i]}&";
  680:                            }
  681: 			   if (dbmclose(%hash)) {
  682: 		              $qresult=~s/\&$//;
  683:                               print $client "$qresult\n";
  684:                            } else {
  685:                               print $client "error:$!\n";
  686:                            }
  687:                        } else {
  688:                            print $client "error:$!\n";
  689:                        }
  690: # ------------------------------------------------------------- unknown command
  691:                    } else {
  692:                        # unknown command
  693:                        print $client "unknown_cmd\n";
  694:                    }
  695: # ------------------------------------------------------ client unknown, refuse
  696: 	       }
  697:             } else {
  698: 	        print $client "refused\n";
  699:                 &logthis("Rejected client $clientip, closing connection");
  700:             }              
  701:             &logthis("Disconnect from $clientip ($hostid{$clientip})");
  702: # =============================================================================
  703:         }
  704:     
  705:         # tidy up gracefully and finish
  706:     
  707:         # this exit is VERY important, otherwise the child will become
  708:         # a producer of more and more children, forking yourself into
  709:         # process death.
  710:         exit;
  711:     }
  712: }
  713: 
  714: 
  715: 
  716: 
  717: 

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