Diff for /loncom/lond between versions 1.553 and 1.563

version 1.553, 2018/12/03 13:20:21 version 1.563, 2020/05/05 20:24:41
Line 80  my $clientsamedom;              # LonCAP Line 80  my $clientsamedom;              # LonCAP
                                 # and client.                                  # and client.
 my $clientsameinst;             # LonCAPA "internet domain" same for   my $clientsameinst;             # LonCAPA "internet domain" same for 
                                 # this host and client.                                  # this host and client.
 my $clientremoteok;             # Client allowed to host domain's users.  my $clientremoteok;             # Current domain permits hosting on client
                                 # (version constraints ignored), not set                                  # (not set if host and client share "internet domain").
                                 # if this host and client share "internet domain".                                   # Values are 0 or 1; 1 if allowed.
 my %clientprohibited;           # Actions prohibited on client;  my %clientprohibited;           # Commands from client prohibited for domain's
                                    # users.
   
 my $server;  my $server;
   
 my $keymode;  my $keymode;
Line 219  my %trust = ( Line 220  my %trust = (
                courseidput => {remote => 1, domroles => 1, enroll => 1},                 courseidput => {remote => 1, domroles => 1, enroll => 1},
                courseidputhash => {remote => 1, domroles => 1, enroll => 1},                 courseidputhash => {remote => 1, domroles => 1, enroll => 1},
                courselastaccess => {remote => 1, domroles => 1, enroll => 1},                 courselastaccess => {remote => 1, domroles => 1, enroll => 1},
                  coursesessions => {institutiononly => 1},
                currentauth => {remote => 1, domroles => 1, enroll => 1},                 currentauth => {remote => 1, domroles => 1, enroll => 1},
                currentdump => {remote => 1, enroll => 1},                 currentdump => {remote => 1, enroll => 1},
                currentversion => {remote=> 1, content => 1},                 currentversion => {remote=> 1, content => 1},
Line 226  my %trust = ( Line 228  my %trust = (
                dcmailput => {remote => 1, domroles => 1},                 dcmailput => {remote => 1, domroles => 1},
                del => {remote => 1, domroles => 1, enroll => 1, content => 1},                 del => {remote => 1, domroles => 1, enroll => 1, content => 1},
                delbalcookie => {institutiononly => 1},                 delbalcookie => {institutiononly => 1},
                  delusersession => {institutiononly => 1},
                deldom => {remote => 1, domroles => 1}, # not currently used                 deldom => {remote => 1, domroles => 1}, # not currently used
                devalidatecache => {institutiononly => 1},                 devalidatecache => {institutiononly => 1},
                domroleput => {remote => 1, enroll => 1},                 domroleput => {remote => 1, enroll => 1},
Line 833  sub PushFile { Line 836  sub PushFile {
     #   hosts.tab  ($filename eq host).      #   hosts.tab  ($filename eq host).
     #   domain.tab ($filename eq domain).      #   domain.tab ($filename eq domain).
     #   dns_hosts.tab ($filename eq dns_host).      #   dns_hosts.tab ($filename eq dns_host).
     #   dns_domain.tab ($filename eq dns_domain).       #   dns_domain.tab ($filename eq dns_domain).
     #   loncapaCAcrl.pem ($filename eq loncapaCAcrl);         #   loncapaCAcrl.pem ($filename eq loncapaCAcrl).
     # Construct the destination filename or reject the request.      # Construct the destination filename or reject the request.
     #      #
     # lonManage is supposed to ensure this, however this session could be      # lonManage is supposed to ensure this, however this session could be
Line 2029  sub read_lonnet_global { Line 2032  sub read_lonnet_global {
                 }                  }
                 if ($what eq 'perlvar') {                  if ($what eq 'perlvar') {
                     if (!exists($packagevars{$what}{'lonBalancer'})) {                      if (!exists($packagevars{$what}{'lonBalancer'})) {
                         if ($dist =~ /^(centos|rhes|fedora|scientific)/) {                          if ($dist =~ /^(centos|rhes|fedora|scientific|oracle)/) {
                             my $othervarref=LONCAPA::Configuration::read_conf('httpd.conf');                              my $othervarref=LONCAPA::Configuration::read_conf('httpd.conf');
                             if (ref($othervarref) eq 'HASH') {                              if (ref($othervarref) eq 'HASH') {
                                 $items->{'lonBalancer'} = $othervarref->{'lonBalancer'};                                  $items->{'lonBalancer'} = $othervarref->{'lonBalancer'};
Line 2347  sub change_password_handler { Line 2350  sub change_password_handler {
     }      }
     if($validated) {      if($validated) {
  my $realpasswd  = &get_auth_type($udom, $uname); # Defined since authd.   my $realpasswd  = &get_auth_type($udom, $uname); # Defined since authd.
   
  my ($howpwd,$contentpwd)=split(/:/,$realpasswd);   my ($howpwd,$contentpwd)=split(/:/,$realpasswd);
           my $notunique;
  if ($howpwd eq 'internal') {   if ($howpwd eq 'internal') {
     &Debug("internal auth");      &Debug("internal auth");
             my $ncpass = &hash_passwd($udom,$npass);              my $ncpass = &hash_passwd($udom,$npass);
     if(&rewrite_password_file($udom, $uname, "internal:$ncpass")) {              my (undef,$method,@rest) = split(/!/,$contentpwd);
               if ($method eq 'bcrypt') {
                   my %passwdconf = &Apache::lonnet::get_passwdconf($udom);
                   if (($passwdconf{'numsaved'}) && ($passwdconf{'numsaved'} =~ /^\d+$/)) {
                       my @oldpasswds;
                       my $userpath = &propath($udom,$uname);
                       my $fullpath = $userpath.'/oldpasswds';
                       if (-d $userpath) {
                           my @oldfiles;
                           if (-e $fullpath) {
                               if (opendir(my $dir,$fullpath)) {
                                   (@oldfiles) = grep(/^\d+$/,readdir($dir));
                                   closedir($dir);
                               }
                               if (@oldfiles) {
                                   @oldfiles = sort { $b <=> $a } (@oldfiles);
                                   my $numremoved = 0;
                                   for (my $i=0; $i<@oldfiles; $i++) {
                                       if ($i>=$passwdconf{'numsaved'}) {
                                           if (-f "$fullpath/$oldfiles[$i]") {
                                               if (unlink("$fullpath/$oldfiles[$i]")) {
                                                   $numremoved ++;
                                               }
                                           }
                                       } elsif (open(my $fh,'<',"$fullpath/$oldfiles[$i]")) {
                                           while (my $line = <$fh>) {
                                               push(@oldpasswds,$line);
                                           }
                                           close($fh);
                                       }
                                   }
                                   if ($numremoved) {
                                       &logthis("unlinked $numremoved old password files for $uname:$udom");
                                   }
                               }
                           }
                           push(@oldpasswds,$contentpwd);
                           foreach my $item (@oldpasswds) {
                               my (undef,$method,@rest) = split(/!/,$item);
                               if ($method eq 'bcrypt') {
                                   my $result = &hash_passwd($udom,$npass,@rest);
                                   if ($result eq $item) {
                                       $notunique = 1;
                                       last;
                                   }
                               }
                           }
                           unless ($notunique) {
                               unless (-e $fullpath) {
                                   if (&mkpath("$fullpath/")) {
                                       chmod(0700,$fullpath);
                                   }
                               }
                               if (-d $fullpath) {
                                   my $now = time;
                                   if (open(my $fh,'>',"$fullpath/$now")) {
                                       print $fh $contentpwd;
                                       close($fh);
                                       chmod(0400,"$fullpath/$now");
                                   }
                               }
                           }
                       }
                   }
               }
               if ($notunique) {
                   my $msg="Result of password change for $uname:$udom - password matches one used before";
                   if ($lonhost) {
                       $msg .= " - request originated from: $lonhost";
                   }
                   &logthis($msg);
                   &Reply($client, "prioruse\n", $userinput);
       } elsif (&rewrite_password_file($udom, $uname, "internal:$ncpass")) {
  my $msg="Result of password change for $uname: pwchange_success";   my $msg="Result of password change for $uname: pwchange_success";
                 if ($lonhost) {                  if ($lonhost) {
                     $msg .= " - request originated from: $lonhost";                      $msg .= " - request originated from: $lonhost";
Line 2369  sub change_password_handler { Line 2444  sub change_password_handler {
     my $result = &change_unix_password($uname, $npass);      my $result = &change_unix_password($uname, $npass);
             if ($result eq 'ok') {              if ($result eq 'ok') {
                 &update_passwd_history($uname,$udom,$howpwd,$context);                  &update_passwd_history($uname,$udom,$howpwd,$context);
              }              }
     &logthis("Result of password change for $uname: ".      &logthis("Result of password change for $uname: ".
      $result);       $result);
     &Reply($client, \$result, $userinput);      &Reply($client, \$result, $userinput);
Line 2380  sub change_password_handler { Line 2455  sub change_password_handler {
     #      #
     &Failure( $client, "auth_mode_error\n", $userinput);      &Failure( $client, "auth_mode_error\n", $userinput);
  }     }  
   
     } else {      } else {
  if ($failure eq '') {   if ($failure eq '') {
     $failure = 'non_authorized';      $failure = 'non_authorized';
Line 2961  sub user_has_session_handler { Line 3035  sub user_has_session_handler {
 }  }
 &register_handler("userhassession", \&user_has_session_handler, 0,1,0);  &register_handler("userhassession", \&user_has_session_handler, 0,1,0);
   
   sub del_usersession_handler {
       my ($cmd, $tail, $client) = @_;
   
       my $result;
       my ($udom, $uname) = map { &unescape($_) } (split(/:/, $tail));
       if (($udom =~ /^$LONCAPA::match_domain$/) && ($uname =~ /^$LONCAPA::match_username$/)) {
           my $lonidsdir = $perlvar{'lonIDsDir'};
           if (-d $lonidsdir) {
               if (opendir(DIR,$lonidsdir)) {
                   my $filename;
                   while ($filename=readdir(DIR)) {
                       if ($filename=~/^\Q$uname\E_\d+_\Q$udom\E_/) {
                           if (tie(my %oldenv,'GDBM_File',"$lonidsdir/$filename",
                                   &GDBM_READER(),0640)) {
                               my $linkedfile;
                               if (exists($oldenv{'user.linkedenv'})) {
                                   $linkedfile = $oldenv{'user.linkedenv'};
                               }
                               untie(%oldenv);
                               $result = unlink("$lonidsdir/$filename");
                               if ($result) {
                                   if ($linkedfile =~ /^[a-f0-9]+_linked$/) {
                                       if (-l "$lonidsdir/$linkedfile.id") {
                                           unlink("$lonidsdir/$linkedfile.id");
                                       }
                                   }
                               }
                           } else {
                               $result = unlink("$lonidsdir/$filename");
                           }
                           last;
                       }
                   }
               }
           }
           if ($result == 1) {
               &Reply($client, "$result\n", "$cmd:$tail");
           } else {
               &Reply($client, "not_found\n", "$cmd:$tail");
           }
       } else {
           &Failure($client, "invalid_user\n", "$cmd:$tail");
       }
       return 1;
   }
   
   &register_handler("delusersession", \&del_usersession_handler, 0,1,0);
   
 #  #
 #  Authenticate access to a user file by checking that the token the user's   #  Authenticate access to a user file by checking that the token the user's 
 #  passed also exists in their session file  #  passed also exists in their session file
Line 4752  sub course_lastaccess_handler { Line 4874  sub course_lastaccess_handler {
 }  }
 &register_handler("courselastaccess",\&course_lastaccess_handler, 0, 1, 0);  &register_handler("courselastaccess",\&course_lastaccess_handler, 0, 1, 0);
   
   sub course_sessions_handler {
       my ($cmd, $tail, $client) = @_;
       my $userinput = "$cmd:$tail";
       my ($cdom,$cnum,$lastactivity) = split(':',$tail);
       my $dbsuffix = '_'.$cdom.'_'.$cnum.'.db';
       my (%sessions,$qresult);
       my $now=time;
       if (opendir(DIR,$perlvar{'lonIDsDir'})) {
           my $filename;
           while ($filename=readdir(DIR)) {
               next if ($filename=~/^\./);
               next if ($filename=~/^publicuser_/);
               next if ($filename=~/^[a-f0-9]+_(linked|lti_\d+)\.id$/);
               if ($filename =~ /^($LONCAPA::match_username)_\d+_($LONCAPA::match_domain)_/) {
                   my ($uname,$udom) = ($1,$2);
                   next unless (-e "$perlvar{'lonDaemons'}/tmp/$uname$dbsuffix");
                   my $mtime = (stat("$perlvar{'lonIDsDir'}/$filename"))[9];
                   if ($lastactivity < 0) {
                       next if ($mtime-$now > $lastactivity);
                   } else {
                       next if ($now-$mtime > $lastactivity);
                   }
                   $sessions{$uname.':'.$udom} = $mtime;
               }
           }
           closedir(DIR); 
       }
       foreach my $user (keys(%sessions)) {
           $qresult.=&escape($user).'='.$sessions{$user}.'&';
       }
       if ($qresult) {
           chop($qresult);
       }
       &Reply($client, \$qresult, $userinput);
       return 1;
   }
   &register_handler("coursesessions",\&course_sessions_handler, 0, 1, 0);
   
 #  #
 # Puts an unencrypted entry in a namespace db file at the domain level   # Puts an unencrypted entry in a namespace db file at the domain level 
 #  #
Line 5552  sub del_balcookie_handler { Line 5712  sub del_balcookie_handler {
                     chomp($line);                      chomp($line);
                     if ($line eq $clientname) {                      if ($line eq $clientname) {
                         $dodelete = 1;                          $dodelete = 1;
                         last;                                last;
                     }                      }
                 }                  }
                 close($fh);                   close($fh);
                 if ($dodelete) {                  if ($dodelete) {
                     if (unlink("$execdir/$cookie.id")) {                      if (unlink("$execdir/$cookie.id")) {
                         $deleted = 1;                          $deleted = 1;
Line 7099  sub UpdateHosts { Line 7259  sub UpdateHosts {
   
     my %oldconf = %secureconf;      my %oldconf = %secureconf;
     my %connchange;      my %connchange;
     if (lonssl::Read_Connect_Config(\%secureconf,\%crlchecked,\%perlvar) eq 'ok') {      if (lonssl::Read_Connect_Config(\%secureconf,\%perlvar,\%crlchecked) eq 'ok') {
         logthis('<font color="blue"> Reloaded SSL connection rules and cleared CRL checking history </font>');          logthis('<font color="blue"> Reloaded SSL connection rules and cleared CRL checking history </font>');
     } else {      } else {
         logthis('<font color="yellow"> Failed to reload SSL connection rules and clear CRL checking history </font>');          logthis('<font color="yellow"> Failed to reload SSL connection rules and clear CRL checking history </font>');
Line 7381  if ($arch eq 'unknown') { Line 7541  if ($arch eq 'unknown') {
     chomp($arch);      chomp($arch);
 }  }
   
 unless (lonssl::Read_Connect_Config(\%secureconf,\%crlchecked,\%perlvar) eq 'ok') {  unless (lonssl::Read_Connect_Config(\%secureconf,\%perlvar,\%crlchecked) eq 'ok') {
     &logthis('<font color="blue">No connectionrules table. Will fallback to loncapa.conf</font>');      &logthis('<font color="blue">No connectionrules table. Will fallback to loncapa.conf</font>');
 }  }
   
Line 7470  sub make_new_child { Line 7630  sub make_new_child {
         &Authen::Krb5::init_context();          &Authen::Krb5::init_context();
   
         my $no_ets;          my $no_ets;
         if ($dist =~ /^(?:centos|rhes|scientific)(\d+)$/) {          if ($dist =~ /^(?:centos|rhes|scientific|oracle)(\d+)$/) {
             if ($1 >= 7) {              if ($1 >= 7) {
                 $no_ets = 1;                  $no_ets = 1;
             }              }
Line 7515  sub make_new_child { Line 7675  sub make_new_child {
     $ConnectionType = "manager";      $ConnectionType = "manager";
     $clientname = $managers{$outsideip};      $clientname = $managers{$outsideip};
  }   }
  my ($clientok,$clientinfoset);   my $clientok;
   
  if ($clientrec || $ismanager) {   if ($clientrec || $ismanager) {
     &status("Waiting for init from $clientip $clientname");      &status("Waiting for init from $clientip $clientname");
Line 7616  sub make_new_child { Line 7776  sub make_new_child {
     }      }
         
  } else {   } else {
                     $clientinfoset = &set_client_info();  
     my $ok = InsecureConnection($client);      my $ok = InsecureConnection($client);
     if($ok) {      if($ok) {
  $clientok = 1;   $clientok = 1;
Line 7654  sub make_new_child { Line 7813  sub make_new_child {
 # ------------------------------------------------------------ Process requests  # ------------------------------------------------------------ Process requests
     my $keep_going = 1;      my $keep_going = 1;
     my $user_input;      my $user_input;
             unless ($clientinfoset) {  
                 $clientinfoset = &set_client_info();  
             }  
             $clientremoteok = 0;  
             unless ($clientsameinst) {  
                 $clientremoteok = 1;  
                 my $defdom = &Apache::lonnet::host_domain($perlvar{'lonHostID'});  
                 %clientprohibited = &get_prohibited($defdom);  
                 if ($clientintdom) {  
                     my $remsessconf = &get_usersession_config($defdom,'remotesession');  
                     if (ref($remsessconf) eq 'HASH') {  
                         if (ref($remsessconf->{'remote'}) eq 'HASH') {  
                             if (ref($remsessconf->{'remote'}->{'excludedomain'}) eq 'ARRAY') {  
                                 if (grep(/^\Q$clientintdom\E$/,@{$remsessconf->{'remote'}->{'excludedomain'}})) {  
                                     $clientremoteok = 0;  
                                 }  
                             }  
                             if (ref($remsessconf->{'remote'}->{'includedomain'}) eq 'ARRAY') {  
                                 if (grep(/^\Q$clientintdom\E$/,@{$remsessconf->{'remote'}->{'includedomain'}})) {  
                                     $clientremoteok = 1;  
                                 } else {  
                                     $clientremoteok = 0;  
                                 }  
                             }  
                         }  
                     }  
                 }  
             }  
     while(($user_input = get_request) && $keep_going) {      while(($user_input = get_request) && $keep_going) {
  alarm(120);   alarm(120);
  Debug("Main: Got $user_input\n");   Debug("Main: Got $user_input\n");
Line 7714  sub make_new_child { Line 7846  sub make_new_child {
   
 #  #
 #  Used to determine if a particular client is from the same domain  #  Used to determine if a particular client is from the same domain
 #  as the current server, or from the same internet domain.  #  as the current server, or from the same internet domain, and
   #  also if the client can host sessions for the domain's users.
   #  A hash is populated with keys set to commands sent by the client
   #  which may not be executed for this domain.
 #  #
 #  Optional input -- the client to check for domain and internet domain.  #  Optional input -- the client to check for domain and internet domain.
 #  If not specified, defaults to the package variable: $clientname  #  If not specified, defaults to the package variable: $clientname
 #  #
 #  If called in array context will not set package variables, but will  #  If called in array context will not set package variables, but will
 #  instead return an array of two values - (a) true if client is in the  #  instead return an array of two values - (a) true if client is in the
 #  same domain as the server, and (b) true if client is in the same internet  #  same domain as the server, and (b) true if client is in the same 
 #  domain.  #  internet domain.
 #  #
 #  If called in scalar context, sets package variables for current client:  #  If called in scalar context, sets package variables for current client:
 #  #
 #  $clienthomedom  - LonCAPA domain of homeID for client.  #  $clienthomedom    - LonCAPA domain of homeID for client.
 #  $clientsamedom  - LonCAPA domain same for this host and client.  #  $clientsamedom    - LonCAPA domain same for this host and client.
 #  $clientintdom   - LonCAPA "internet domain" for client.  #  $clientintdom     - LonCAPA "internet domain" for client.
 #  $clientsameinst - LonCAPA "internet domain" same for this host & client.  #  $clientsameinst   - LonCAPA "internet domain" same for this host & client.
   #  $clientremoteok   - If current domain permits hosting on this client: 1
   #  %clientprohibited - Commands prohibited for domain's users for this client.
   #
   #  if the host and client have the same "internet domain", then the value
   #  of $clientremoteok is not used, and no commands are prohibited.
 #  #
 #  returns 1 to indicate package variables have been set for current client.  #  returns 1 to indicate package variables have been set for current client.
 #  #
Line 7741  sub set_client_info { Line 7881  sub set_client_info {
     my $clientserverhomeID = &Apache::lonnet::get_server_homeID($clienthost);      my $clientserverhomeID = &Apache::lonnet::get_server_homeID($clienthost);
     my $homedom = &Apache::lonnet::host_domain($clientserverhomeID);      my $homedom = &Apache::lonnet::host_domain($clientserverhomeID);
     my $samedom = 0;      my $samedom = 0;
     if ($perlvar{'lonDefDom'} eq $homedom) {      if ($perlvar{'lonDefDomain'} eq $homedom) {
         $samedom = 1;          $samedom = 1;
     }      }
     my $intdom = &Apache::lonnet::internet_dom($clientserverhomeID);      my $intdom = &Apache::lonnet::internet_dom($clientserverhomeID);
Line 7761  sub set_client_info { Line 7901  sub set_client_info {
         $clientsamedom = $samedom;          $clientsamedom = $samedom;
         $clientintdom = $intdom;          $clientintdom = $intdom;
         $clientsameinst = $sameinst;          $clientsameinst = $sameinst;
           if ($clientsameinst) {
               undef($clientremoteok);
               undef(%clientprohibited);
           } else {
               $clientremoteok = &get_remote_hostable($currentdomainid);
               %clientprohibited = &get_prohibited($currentdomainid);
           }
         return 1;          return 1;
     }      }
 }  }
Line 8508  sub sethost { Line 8655  sub sethost {
  eq &Apache::lonnet::get_host_ip($hostid)) {   eq &Apache::lonnet::get_host_ip($hostid)) {
  $currenthostid  =$hostid;   $currenthostid  =$hostid;
  $currentdomainid=&Apache::lonnet::host_domain($hostid);   $currentdomainid=&Apache::lonnet::host_domain($hostid);
           &set_client_info();
 # &logthis("Setting hostid to $hostid, and domain to $currentdomainid");  # &logthis("Setting hostid to $hostid, and domain to $currentdomainid");
     } else {      } else {
  &logthis("Requested host id $hostid not an alias of ".   &logthis("Requested host id $hostid not an alias of ".
Line 8584  sub get_prohibited { Line 8732  sub get_prohibited {
     return %prohibited;      return %prohibited;
 }  }
   
   sub get_remote_hostable {
       my ($dom) = @_;
       my $result;
       if ($clientintdom) {
           $result = 1;
           my $remsessconf = &get_usersession_config($dom,'remotesession');
           if (ref($remsessconf) eq 'HASH') {
               if (ref($remsessconf->{'remote'}) eq 'HASH') {
                   if (ref($remsessconf->{'remote'}->{'excludedomain'}) eq 'ARRAY') {
                       if (grep(/^\Q$clientintdom\E$/,@{$remsessconf->{'remote'}->{'excludedomain'}})) {
                           $result = 0;
                       }
                   }
                   if (ref($remsessconf->{'remote'}->{'includedomain'}) eq 'ARRAY') {
                       if (grep(/^\Q$clientintdom\E$/,@{$remsessconf->{'remote'}->{'includedomain'}})) {
                           $result = 1;
                       } else {
                           $result = 0;
                       }
                   }
               }
           }
       }
       return $result;
   }
   
 sub distro_and_arch {  sub distro_and_arch {
     return $dist.':'.$arch;      return $dist.':'.$arch;
 }  }

Removed from v.1.553  
changed lines
  Added in v.1.563


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