Diff for /loncom/interface/domainprefs.pm between versions 1.372 and 1.381

version 1.372, 2020/09/17 00:35:04 version 1.381, 2021/04/18 02:08:46
Line 176  use Locale::Language; Line 176  use Locale::Language;
 use DateTime::TimeZone;  use DateTime::TimeZone;
 use DateTime::Locale;  use DateTime::Locale;
 use Time::HiRes qw( sleep );  use Time::HiRes qw( sleep );
   use Net::CIDR;
   
 my $registered_cleanup;  my $registered_cleanup;
 my $modified_urls;  my $modified_urls;
Line 220  sub handler { Line 221  sub handler {
                 'coursedefaults','usersessions','loadbalancing',                  'coursedefaults','usersessions','loadbalancing',
                 'requestauthor','selfenrollment','inststatus',                  'requestauthor','selfenrollment','inststatus',
                 'ltitools','ssl','trust','lti','privacy','passwords',                  'ltitools','ssl','trust','lti','privacy','passwords',
                 'proctoring'],$dom);                  'proctoring','wafproxy'],$dom);
     my %encconfig =      my %encconfig =
         &Apache::lonnet::get_dom('encconfig',['ltitools','lti','proctoring'],$dom);          &Apache::lonnet::get_dom('encconfig',['ltitools','lti','proctoring'],$dom);
     if (ref($domconfig{'ltitools'}) eq 'HASH') {      if (ref($domconfig{'ltitools'}) eq 'HASH') {
Line 259  sub handler { Line 260  sub handler {
             }              }
         }          }
     }      }
     my @prefs_order = ('rolecolors','login','defaults','passwords','quotas','autoenroll',      my @prefs_order = ('rolecolors','login','defaults','wafproxy','passwords','quotas',
                        'autoupdate','autocreate','directorysrch','contacts','privacy',                         'autoenroll','autoupdate','autocreate','directorysrch',
                        'usercreation','selfcreation','usermodification','scantron',                         'contacts','privacy','usercreation','selfcreation',
                        'requestcourses','requestauthor','coursecategories',                         'usermodification','scantron','requestcourses','requestauthor',
                        'serverstatuses','helpsettings','coursedefaults',                         'coursecategories','serverstatuses','helpsettings','coursedefaults',
                        'ltitools','proctoring','selfenrollment','usersessions','ssl',                         'ltitools','proctoring','selfenrollment','usersessions','ssl',
                        'trust','lti');                         'trust','lti');
     my %existing;      my %existing;
Line 310  sub handler { Line 311  sub handler {
                       print => \&print_defaults,                        print => \&print_defaults,
                       modify => \&modify_defaults,                        modify => \&modify_defaults,
                     },                      },
           'wafproxy' =>
                       { text => 'Web Application Firewall/Reverse Proxy',
                         help => 'Domain_Configuration_WAF_Proxy',
                         header => [{col1 => 'Domain(s)',
                                     col2 => 'Servers and WAF/Reverse Proxy alias(es)',
                                    },
                                    {col1 => 'Domain(s)',
                                     col2 => 'WAF Configuration',}],
                         print => \&print_wafproxy,
                         modify => \&modify_wafproxy,
                       },
         'passwords' =>          'passwords' =>
                     { text => 'Passwords (Internal authentication)',                      { text => 'Passwords (Internal authentication)',
                       help => 'Domain_Configuration_Passwords',                        help => 'Domain_Configuration_Passwords',
Line 805  sub process_changes { Line 817  sub process_changes {
         $output = &modify_privacy($dom,%domconfig);          $output = &modify_privacy($dom,%domconfig);
     } elsif ($action eq 'passwords') {      } elsif ($action eq 'passwords') {
         $output = &modify_passwords($r,$dom,$confname,$lastactref,%domconfig);          $output = &modify_passwords($r,$dom,$confname,$lastactref,%domconfig);
       } elsif ($action eq 'wafproxy') {
           $output = &modify_wafproxy($dom,$action,$lastactref,%domconfig);
     }      }
     return $output;      return $output;
 }  }
Line 841  sub print_config_box { Line 855  sub print_config_box {
         $output .= &lti_javascript($settings);          $output .= &lti_javascript($settings);
     } elsif ($action eq 'proctoring') {      } elsif ($action eq 'proctoring') {
         $output .= &proctoring_javascript($settings);          $output .= &proctoring_javascript($settings);
       } elsif ($action eq 'wafproxy') {
           $output .= &wafproxy_javascript($dom);
     }      }
     $output .=      $output .=
          '<table class="LC_nested_outer">           '<table class="LC_nested_outer">
Line 882  sub print_config_box { Line 898  sub print_config_box {
             ($action eq 'usermodification') || ($action eq 'defaults') || ($action eq 'coursedefaults') ||              ($action eq 'usermodification') || ($action eq 'defaults') || ($action eq 'coursedefaults') ||
             ($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'ssl') ||              ($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'ssl') ||
             ($action eq 'directorysrch') || ($action eq 'trust') || ($action eq 'helpsettings') ||              ($action eq 'directorysrch') || ($action eq 'trust') || ($action eq 'helpsettings') ||
             ($action eq 'contacts') || ($action eq 'privacy')) {              ($action eq 'contacts') || ($action eq 'privacy') || ($action eq 'wafproxy')) {
             $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);              $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'passwords') {          } elsif ($action eq 'passwords') {
             $output .= $item->{'print'}->('top',$dom,$confname,$settings,\$rowtotal);              $output .= $item->{'print'}->('top',$dom,$confname,$settings,\$rowtotal);
Line 1005  sub print_config_box { Line 1021  sub print_config_box {
             $rowtotal ++;              $rowtotal ++;
         } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') ||          } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') ||
                  ($action eq 'defaults') || ($action eq 'directorysrch') ||                   ($action eq 'defaults') || ($action eq 'directorysrch') ||
                  ($action eq 'helpsettings')) {                   ($action eq 'helpsettings') || ($action eq 'wafproxy')) {
             $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);              $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
         } elsif ($action eq 'scantron') {          } elsif ($action eq 'scantron') {
             $output .= $item->{'print'}->($r,'bottom',$dom,$confname,$settings,\$rowtotal);              $output .= $item->{'print'}->($r,'bottom',$dom,$confname,$settings,\$rowtotal);
Line 2830  function toggleLTITools(form,setting,ite Line 2846  function toggleLTITools(form,setting,ite
 ENDSCRIPT  ENDSCRIPT
 }  }
   
   sub wafproxy_javascript {
       my ($dom) = @_;
       return <<"ENDSCRIPT";
   <script type="text/javascript">
   // <![CDATA[
   function updateWAF() {
       if (document.getElementById('wafproxy_remoteip')) {
           var wafremote = 0;
           if (document.display.wafproxy_remoteip.options[document.display.wafproxy_remoteip.selectedIndex].value == 'h') {
               wafremote = 1;
           }
           var fields = new Array('header','trust');
           for (var i=0; i<fields.length; i++) {
               if (document.getElementById('wafproxy_'+fields[i])) {
                   if (wafremote == 1) {
                       document.getElementById('wafproxy_'+fields[i]).style.display = 'table-row';
                   }
                   else {
                       document.getElementById('wafproxy_'+fields[i]).style.display = 'none';
                   }
               }
           }
           if (document.getElementById('wafproxyranges_$dom')) {
               if (wafremote == 1) {
                   document.getElementById('wafproxyranges_$dom').style.display = 'inline-block';
               } else {
                   for (var i=0; i<document.display.wafproxy_vpnaccess.length; i++) {
                       if (document.display.wafproxy_vpnaccess[i].checked) {
                           if (document.display.wafproxy_vpnaccess[i].value == 0) {
                               document.getElementById('wafproxyranges_$dom').style.display = 'none';
                           }
                       }
                   }
               }
           }
       }
       return;
   }
   
   function checkWAF() {
       if (document.getElementById('wafproxy_remoteip')) {
           var wafvpn = 0;
           for (var i=0; i<document.display.wafproxy_vpnaccess.length; i++) {
               if (document.display.wafproxy_vpnaccess[i].checked) {
                   if (document.display.wafproxy_vpnaccess[i].value == 1) {
                       wafvpn = 1;
                   }
                   break;
               }
           }
           var vpn = new Array('vpnint','vpnext');
           for (var i=0; i<vpn.length; i++) {
               if (document.getElementById('wafproxy_show_'+vpn[i])) {
                   if (wafvpn == 1) {
                       document.getElementById('wafproxy_show_'+vpn[i]).style.display = 'table-row';
                   }
                   else {
                       document.getElementById('wafproxy_show_'+vpn[i]).style.display = 'none';
                   }
               }
           }
           if (document.getElementById('wafproxyranges_$dom')) {
               if (wafvpn == 1) {
                   document.getElementById('wafproxyranges_$dom').style.display = 'inline-block';
               }
               else if (document.display.wafproxy_remoteip.options[document.display.wafproxy_remoteip.selectedIndex].value != 'h') {
                   document.getElementById('wafproxyranges_$dom').style.display = 'none';
               }
           }
       }
       return;
   }
   
   function toggleWAF() {
       if (document.getElementById('wafproxy_table')) {
           var wafproxy = 0;
           for (var i=0; i<document.display.wafproxy_${dom}.length; i++) {
                if (document.display.wafproxy_${dom}[i].checked) {
                    if (document.display.wafproxy_${dom}[i].value == 1) {
                        wafproxy = 1;
                        break;
                   }
               }
           }
           if (wafproxy == 1) {
               document.getElementById('wafproxy_table').style.display='inline';
           }
           else {
              document.getElementById('wafproxy_table').style.display='none';
           }
           if (document.getElementById('wafproxyrow_${dom}')) {
               if (wafproxy == 1) {
                   document.getElementById('wafproxyrow_${dom}').style.display = 'table-row';
               }
               else {
                   document.getElementById('wafproxyrow_${dom}').style.display = 'none';
               }
           }
           if (document.getElementById('nowafproxyrow_$dom')) {
               if (wafproxy == 1) {
                   document.getElementById('nowafproxyrow_${dom}').style.display = 'none';
               }
               else {
                   document.getElementById('nowafproxyrow_${dom}').style.display = 'table-row';
               }
           }
       }
       return;
   }
   // ]]>
   </script>
   
   ENDSCRIPT
   }
   
 sub proctoring_javascript {  sub proctoring_javascript {
     my ($settings) = @_;      my ($settings) = @_;
     my (%ordered,$total,%jstext);      my (%ordered,$total,%jstext);
Line 3767  sub print_contacts { Line 3898  sub print_contacts {
                                                    \%choices,$rownum);                                                     \%choices,$rownum);
         $datatable .= $reports;          $datatable .= $reports;
     } elsif ($position eq 'lower') {      } elsif ($position eq 'lower') {
         $css_class = $rownum%2?' class="LC_odd_row"':'';          my (%current,%excluded,%weights);
         my ($threshold,$sysmail,%excluded,%weights);  
         my ($defaults,$names) = &Apache::loncommon::lon_status_items();          my ($defaults,$names) = &Apache::loncommon::lon_status_items();
         if ($lonstatus{'threshold'} =~ /^\d+$/) {          if ($lonstatus{'threshold'} =~ /^\d+$/) {
             $threshold = $lonstatus{'threshold'};              $current{'errorthreshold'} = $lonstatus{'threshold'};
         } else {          } else {
             $threshold = $defaults->{'threshold'};              $current{'errorthreshold'} = $defaults->{'threshold'};
         }          }
         if ($lonstatus{'sysmail'} =~ /^\d+$/) {          if ($lonstatus{'sysmail'} =~ /^\d+$/) {
             $sysmail = $lonstatus{'sysmail'};              $current{'errorsysmail'} = $lonstatus{'sysmail'};
         } else {          } else {
             $sysmail = $defaults->{'sysmail'};              $current{'errorsysmail'} = $defaults->{'sysmail'};
         }          }
         if (ref($lonstatus{'weights'}) eq 'HASH') {          if (ref($lonstatus{'weights'}) eq 'HASH') {
             foreach my $type ('E','W','N','U') {              foreach my $type ('E','W','N','U') {
Line 3798  sub print_contacts { Line 3928  sub print_contacts {
                 map {$excluded{$_} = 1; } @{$lonstatus{'excluded'}};                  map {$excluded{$_} = 1; } @{$lonstatus{'excluded'}};
             }              }
         }          }
         $datatable .= '<tr'.$css_class.'>'.          foreach my $item ('errorthreshold','errorsysmail') { 
                       '<td class="LC_left_item"><span class="LC_nobreak">'.              $css_class = $rownum%2?' class="LC_odd_row"':'';
                       $titles->{'errorthreshold'}.              $datatable .= '<tr'.$css_class.'>'.
                       '</span></td><td class="LC_left_item">'.                            '<td class="LC_left_item"><span class="LC_nobreak">'.
                       '<input type="text" name="errorthreshold" value="'.                            $titles->{$item}.
                       $threshold.'" size="5" /></td></tr>';                            '</span></td><td class="LC_left_item">'.
         $rownum ++;                            '<input type="text" name="'.$item.'" value="'.
                             $current{$item}.'" size="5" /></td></tr>';
               $rownum ++;
           }
         $css_class = $rownum%2?' class="LC_odd_row"':'';          $css_class = $rownum%2?' class="LC_odd_row"':'';
         $datatable .= '<tr'.$css_class.'>'.          $datatable .= '<tr'.$css_class.'>'.
                       '<td class="LC_left_item">'.                        '<td class="LC_left_item">'.
Line 3850  sub print_contacts { Line 3983  sub print_contacts {
         }          }
         $datatable .= '</tr></table></td></tr>';          $datatable .= '</tr></table></td></tr>';
         $rownum ++;          $rownum ++;
         $css_class = $rownum%2?' class="LC_odd_row"':'';  
         $datatable .= '<tr'.$css_class.'>'.  
                       '<td class="LC_left_item"><span class="LC_nobreak">'.  
                       $titles->{'errorsysmail'}.  
                       '</span></td><td class="LC_left_item">'.  
                       '<input type="text" name="errorsysmail" value="'.  
                       $sysmail.'" size="5" /></td></tr>';  
         $rownum ++;  
     } elsif ($position eq 'bottom') {      } elsif ($position eq 'bottom') {
         my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);          my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
         my (@posstypes,%usertypeshash);          my (@posstypes,%usertypeshash);
Line 6147  sub print_coursedefaults { Line 6272  sub print_coursedefaults {
         my $currcanclone = 'none';          my $currcanclone = 'none';
         my $onclick;          my $onclick;
         my @cloneoptions = ('none','domain');          my @cloneoptions = ('none','domain');
         my %clonetitles = (          my %clonetitles = &Apache::lonlocal::texthash (
                              none     => 'No additional course requesters',                               none     => 'No additional course requesters',
                              domain   => "Any course requester in course's domain",                               domain   => "Any course requester in course's domain",
                              instcode => 'Course requests for official courses ...',                               instcode => 'Course requests for official courses ...',
Line 7164  sub print_passwords { Line 7289  sub print_passwords {
     return $datatable;      return $datatable;
 }  }
   
   sub print_wafproxy {
       my ($position,$dom,$settings,$rowtotal) = @_;
       my $css_class;
       my $itemcount = 0;
       my $datatable;
       my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my (%othercontrol,%otherdoms,%aliases,%values,$setdom,$showdom);
       my %lt = &wafproxy_titles();
       foreach my $server (sort(keys(%servers))) {
           my $serverhome = &Apache::lonnet::get_server_homeID($servers{$server});
           next if ($serverhome eq '');
           my $serverdom;
           if ($serverhome ne $server) {
               $serverdom = &Apache::lonnet::host_domain($serverhome);
               if (($serverdom ne '') && (&Apache::lonnet::domain($serverdom) ne '')) {
                   $othercontrol{$server} = $serverdom;
               }
           } else {
               $serverdom = &Apache::lonnet::host_domain($server);
               next if (($serverdom eq '') || (&Apache::lonnet::domain($serverdom) eq ''));
               if ($serverdom ne $dom) {
                   $othercontrol{$server} = $serverdom;
               } else {
                   $setdom = 1;
                   if (ref($settings) eq 'HASH') {
                       if (ref($settings->{'alias'}) eq 'HASH') {
                           $aliases{$dom} = $settings->{'alias'};
                           if ($aliases{$dom} ne '') {
                               $showdom = 1;
                           }
                       }
                   }
               }
           }
       }
       if ($setdom) {
           %{$values{$dom}} = ();
           if (ref($settings) eq 'HASH') {
               foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext') {
                   $values{$dom}{$item} = $settings->{$item};
               }
           }
       }
       if (keys(%othercontrol)) {
           %otherdoms = reverse(%othercontrol);
           foreach my $domain (keys(%otherdoms)) {
               %{$values{$domain}} = ();
               my %config = &Apache::lonnet::get_dom('configuration',['wafproxy'],$domain);
               if (ref($config{$domain}) eq 'HASH') {
                   if (ref($config{$domain}{'wafproxy'}) eq 'HASH') {
                       $aliases{$domain} = $config{$domain}{'wafproxy'}{'alias'};
                       foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext') {
                           $values{$domain}{$item} = $config{$domain}{'wafproxy'}{$item};
                       }
                   }
               }
           }
       }
       if ($position eq 'top') {
           my %servers = &Apache::lonnet::internet_dom_servers($dom);
           my %aliasinfo;
           foreach my $server (sort(keys(%servers))) {
               $itemcount ++;
               my $dom_in_effect;
               my $aliasrows = '<tr>'.
                               '<td class="LC_left_item">'.&mt('Hostname').':&nbsp;'.
                               &Apache::lonnet::hostname($server).'</td>';
               if ($othercontrol{$server}) {
                   $dom_in_effect = $othercontrol{$server};
                   my $current;
                   if (ref($aliases{$othercontrol{$server}}) eq 'HASH') {
                       $current = $aliases{$othercontrol{$server}{$server}};
                   }
                   if ($current) {
                       $aliasrows .= $current;
                   } else {
                       $aliasrows .= &mt('None in effect');
                   }
                   $aliasrows .= '<td class="LC_left_item"><span class="LC_small">('.
                                 &mt('WAF/Reverse Proxy controlled by domain: [_1]',
                                     '<b>'.$othercontrol{$server}.'</b>').'</span></td>';
               } else {
                   $dom_in_effect = $dom;
                   my $current;
                   if (ref($aliases{$dom}) eq 'HASH') {
                       if ($aliases{$dom}{$server}) {
                           $current = $aliases{$dom}{$server};
                       }
                   }
                   $aliasrows .= '<td class="LC_left_item">'.&mt('WAF/Reverse Proxy Alias').':&nbsp;'.
                                 '<input type="text" name="wafproxy_alias_'.$server.'" '.
                                 'value="'.$current.'" size="30" /></td>';
               }
               $aliasrows .= '</tr>';
               $aliasinfo{$dom_in_effect} .= $aliasrows;
           }
           if ($aliasinfo{$dom}) {
               my ($onclick,$wafon,$wafoff,$showtable);
               $onclick = ' onclick="javascript:toggleWAF();"';
               $wafoff = ' checked="checked"';
               $showtable = ' style="display:none";';
               if ($showdom) {
                   $wafon = $wafoff;
                   $wafoff = '';
                   $showtable = ' style="display:inline;"';
               }
               $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
               $datatable = '<tr'.$css_class.'>'.
                            '<td class="LC_left_item">'.&mt('Domain: [_1]','<b>'.$dom.'</b>').'<br />'.
                            '<span class="LC_nobreak">'.&mt('WAF in use?').'&nbsp;<label>'.
                            '<input type="radio" name="wafproxy_'.$dom.'" value="1"'.$wafon.$onclick.' />'.
                            &mt('Yes').'</label>'.('&nbsp;'x2).'<label>'.
                            '<input type="radio" name="wafproxy_'.$dom.'" value="0"'.$wafoff.$onclick.' />'.
                            &mt('No').'</label></span></td>'.
                            '<td class="LC_left_item">'.
                            '<table id="wafproxy_table"'.$showtable.'>'.$aliasinfo{$dom}.
                            '</table></td></tr>';
               $itemcount++;
           }
           if (keys(%othercontrol)) {
               foreach my $key (sort(keys(%othercontrol))) {
                   $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
                   $datatable = '<tr'.$css_class.'>'.
                                '<td class="LC_left_item">'.&mt('Domain: [_1]','<b>'.$key.'</b>').'</td>'.
                                '<td class="LC_left_item"><table>'.$aliasinfo{$key}.
                                '</table></td></tr>';
                   $itemcount++;
               }
           }
       } else {
           if ($setdom) {
               $itemcount ++;
               $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
               my ($nowafstyle,$wafstyle,$curr_remotip,$currwafdisplay,$vpndircheck,$vpnaliascheck,
                   $currwafvpn,$wafrangestyle);
               $wafstyle = ' style="display:none;"';
               $nowafstyle = ' style="display:table-row;"';
               $currwafdisplay = ' style="display: none"';
               $wafrangestyle = ' style="display: none"';
               $curr_remotip = 'n';
               if ($showdom) {
                   $wafstyle = ' style="display:table-row;"';
                   $nowafstyle =  ' style="display:none;"';
                   if (keys(%{$values{$dom}})) {
                       if ($values{$dom}{remoteip} =~ /^[nmh]$/) {
                           $curr_remotip = $values{$dom}{remoteip};
                       }
                       if ($curr_remotip eq 'h') {
                           $currwafdisplay = ' style="display:table-row"';
                           $wafrangestyle = ' style="display:inline-block;"';
                       }
                   }
                   if (($values{$dom}{'vpnint'} ne '') || ($values{$dom}{'vpnext'} ne '')) {
                       $vpndircheck = ' checked="checked"';
                       $currwafvpn = ' style="display:table-row;"';
                       $wafrangestyle = ' style="display:inline-block;"';
                   } else {
                       $vpnaliascheck = ' checked="checked"';
                       $currwafvpn = ' style="display:none;"';
                   }
               }
               $datatable .= '<tr'.$css_class.' id="nowafproxyrow_'.$dom.'"'.$wafstyle.'>'.
                             '<td class="LC_left_item">'.&mt('Domain: [_1]','<b>'.$dom.'</b>').'</td>'.
                             '<td class="LC_right_item">'.&mt('WAF not in use, nothing to set').'</td>'.
                             '</tr>'.
                             '<tr'.$css_class.' id="wafproxyrow_'.$dom.'"'.$wafstyle.'>'.
                             '<td class="LC_left_item">'.&mt('Domain: [_1]','<b>'.$dom.'</b>').'<br /><br />'.
                             '<div id="wafproxyranges_'.$dom.'">'.&mt('Format for comma separated IP ranges').':<br />'.
                             &mt('A.B.C.D/N or A.B.C.D-E.F.G.H').'</div></td>'.
                             '<td class="LC_left_item"><table>'.
                             '<tr>'.
                             '<td valign="top">'.$lt{'remoteip'}.':&nbsp;'.
                             '<select name="wafproxy_remoteip" id="wafproxy_remoteip" onchange="javascript:updateWAF();">';
               my %ip_methods = &remoteip_methods();
               foreach my $option ('m','h','n') {
                   my $sel;
                   if ($option eq $curr_remotip) {
                      $sel = ' selected="selected"';
                   }
                   $datatable .= '<option value="'.$option.'"'.$sel.'>'.
                                 $ip_methods{$option}.'</option>';
               }
               $datatable .= '</select></td></tr>'."\n".
                             '<tr id="wafproxy_header"'.$currwafdisplay.'><td>'.
                             $lt{'ipheader'}.':&nbsp;'.
                             '<input type="text" value="'.$values{$dom}{'ipheader'}.'" '.
                             'name="wafproxy_ipheader" />'.
                             '</td></tr>'."\n".
                             '<tr id="wafproxy_trust"'.$currwafdisplay.'><td>'.
                             $lt{'trusted'}.':&nbsp;'.
                             '<textarea name="wafproxy_trusted" rows="3" cols="80">'.
                             $values{$dom}{'trusted'}.'</textarea>'.
                             '</td></tr>'."\n".
                             '<tr><td><hr /></td></tr>'."\n".
                             '<tr>'.
                             '<td valign="top">'.$lt{'vpnaccess'}.':<br /><span class="LC_nobreak">'.
                             '<label><input type="radio" name="wafproxy_vpnaccess"'.$vpndircheck.' value="1" onclick="javascript:checkWAF();" />'.
                             $lt{'vpndirect'}.'</label>'.('&nbsp;'x2).
                             '<label><input type="radio" name="wafproxy_vpnaccess"'.$vpnaliascheck.' value="0" onclick="javascript:checkWAF();" />'.
                             $lt{'vpnaliased'}.'</label></span></td></tr>';
               foreach my $item ('vpnint','vpnext') {
                   $datatable .= '<tr id="wafproxy_show_'.$item.'"'.$currwafvpn.'>'.
                                 '<td valign="top">'.$lt{$item}.':&nbsp;'.
                                 '<textarea name="wafproxy_'.$item.'" rows="3" cols="80">'.
                                 $values{$dom}{$item}.'</textarea>'.
                                 '</td></tr>'."\n";
               }
               $datatable .= '</table></td></tr>';
           }
           if (keys(%otherdoms)) {
               foreach my $domain (sort(keys(%otherdoms))) {
                   $itemcount ++;
                   $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
                   $datatable .= '<tr'.$css_class.'>'.
                                 '<td class="LC_left_item">'.&mt('Domain: [_1]',$domain).'</td>'.
                                 '<td class="LC_left_item"><table>';
                   foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext') {
                       my $showval = &mt('None');
                       if ($values{$domain}{$item}) {
                           $showval = $values{$domain}{$item};
                       }
                       $datatable .= '<tr>'.
                                     '<td>'.$lt{$item}.':&nbsp;'.$showval.'</td></tr>';
                   }
                   $datatable .= '</table></td></tr>';
               }
           }
       }
       $$rowtotal += $itemcount;
       return $datatable;
   }
   
   sub wafproxy_titles {
       return &Apache::lonlocal::texthash(
                  remoteip   => "Method for determining user's IP",
                  ipheader   => 'Request header containing remote IP',
                  trusted    => 'Trusted IP range(s)',
                  vpnaccess  => 'Access from institutional VPN',
                  vpndirect  => 'via regular hostname (no WAF)',
                  vpnaliased => 'via aliased hostname (WAF)',
                  vpnint     => 'Internal IP Range(s) for VPN sessions',
                  vpnext     => 'IP Range(s) for backend WAF connections',
                  ssloptions => 'Forwarding http/https',
                  alltossl   => 'WAF forwards both http and https requests to https',
                  ssltossl   => 'WAF forwards http requests to http and https to https',
              );
   }
   
   sub remoteip_methods {
       return &Apache::lonlocal::texthash(
                 m => 'Use Apache mod_remoteip',
                 h => 'Use headers parsed by LON-CAPA',
                 n => 'Not in use',
              );
   }
   
 sub print_usersessions {  sub print_usersessions {
     my ($position,$dom,$settings,$rowtotal) = @_;      my ($position,$dom,$settings,$rowtotal) = @_;
     my ($css_class,$datatable,$itemcount,%checked,%choices);      my ($css_class,$datatable,$itemcount,%checked,%choices);
Line 8199  sub contact_titles { Line 8580  sub contact_titles {
                    'updatesmail'     => 'E-mail from nightly check of LON-CAPA module integrity/updates',                     'updatesmail'     => 'E-mail from nightly check of LON-CAPA module integrity/updates',
                    'idconflictsmail' => 'E-mail from bi-nightly check for multiple users sharing same student/employee ID',                     'idconflictsmail' => 'E-mail from bi-nightly check for multiple users sharing same student/employee ID',
                    'hostipmail'      => 'E-mail from nightly check of hostname/IP network changes',                     'hostipmail'      => 'E-mail from nightly check of hostname/IP network changes',
                    'errorthreshold'  => 'Error/warning threshold for status e-mail',                     'errorthreshold'  => 'Error count threshold for status e-mail to admin(s)',
                    'errorsysmail'    => 'Error threshold for e-mail to core group',                     'errorsysmail'    => 'Error count threshold for e-mail to developer group',
                    'errorweights'    => 'Weights used to compute error count',                     'errorweights'    => 'Weights used to compute error count',
                    'errorexcluded'   => 'Servers with unsent updates excluded from count',                     'errorexcluded'   => 'Servers with unsent updates excluded from count',
                  );                   );
Line 9250  sub print_defaults { Line 9631  sub print_defaults {
                     $datatable .= '</select>&nbsp;'.&mt('Internal ID:').'&nbsp;<b>'.$item.'</b>&nbsp;'.                      $datatable .= '</select>&nbsp;'.&mt('Internal ID:').'&nbsp;<b>'.$item.'</b>&nbsp;'.
                                   '<input type="checkbox" name="inststatus_delete" value="'.$item.'" />'.                                    '<input type="checkbox" name="inststatus_delete" value="'.$item.'" />'.
                                   &mt('delete').'</span></td>'.                                    &mt('delete').'</span></td>'.
                                   '<td class="LC_left_item" colspan="2"><span class="LC_nobreak">'.&mt('Name displayed:').                                    '<td class="LC_left_item" colspan="2"><span class="LC_nobreak">'.&mt('Name displayed').':'.
                                   '<input type="text" size="20" name="inststatus_title_'.$item.'" value="'.$title.'" />'.                                    '<input type="text" size="20" name="inststatus_title_'.$item.'" value="'.$title.'" />'.
                                   '</span></td></tr>';                                    '</span></td></tr>';
                 }                  }
Line 9270  sub print_defaults { Line 9651  sub print_defaults {
                               '<input type="text" size="10" name="addinststatus" value="" />'.                                '<input type="text" size="10" name="addinststatus" value="" />'.
                               '&nbsp;'.&mt('(new)').                                '&nbsp;'.&mt('(new)').
                               '</span></td><td class="LC_left_item" colspan="2"><span class="LC_nobreak">'.                                '</span></td><td class="LC_left_item" colspan="2"><span class="LC_nobreak">'.
                               &mt('Name displayed:').                                &mt('Name displayed').':'.
                               '<input type="text" size="20" name="addinststatus_title" value="" /></span></td>'.                                '<input type="text" size="20" name="addinststatus_title" value="" /></span></td>'.
                               '</tr>'."\n";                                '</tr>'."\n";
                 $rownum ++;                  $rownum ++;
Line 10279  ENDSCRIPT Line 10660  ENDSCRIPT
 sub initialize_categories {  sub initialize_categories {
     my ($itemcount) = @_;      my ($itemcount) = @_;
     my ($datatable,$css_class,$chgstr);      my ($datatable,$css_class,$chgstr);
     my %default_names = (      my %default_names = &Apache::lonlocal::texthash (
                       instcode    => 'Official courses (with institutional codes)',                        instcode    => 'Official courses (with institutional codes)',
                       communities => 'Communities',                        communities => 'Communities',
                       placement   => 'Placement Tests',                        placement   => 'Placement Tests',
Line 15054  sub modify_contacts { Line 15435  sub modify_contacts {
                 $contacts_hash{'contacts'}{'lonstatus'}{$item} = \@excluded;                  $contacts_hash{'contacts'}{'lonstatus'}{$item} = \@excluded;
             }              }
         } elsif ($item eq 'weights') {          } elsif ($item eq 'weights') {
             foreach my $type ('E','W','N') {              foreach my $type ('E','W','N','U') {
                 $env{'form.error'.$item.'_'.$type} =~ s/^\s+|\s+$//g;                  $env{'form.error'.$item.'_'.$type} =~ s/^\s+|\s+$//g;
                 if ($env{'form.error'.$item.'_'.$type} =~ /^\d+$/) {                  if ($env{'form.error'.$item.'_'.$type} =~ /^\d+$/) {
                     unless ($env{'form.error'.$item.'_'.$type} == $lonstatus_defs->{$type}) {                      unless ($env{'form.error'.$item.'_'.$type} == $lonstatus_defs->{$type}) {
Line 16221  sub modify_passwords { Line 16602  sub modify_passwords {
                                 $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).'</li>';                                  $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).'</li>';
                             }                              }
                         } else {                          } else {
                             $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA usedfor verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).'</li>';                              $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).'</li>';
                         }                          }
                         if ($confighash{'passwords'}{'resetremove'}) {                          if ($confighash{'passwords'}{'resetremove'}) {
                             $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" web form not shown').'</li>';                              $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" web form not shown').'</li>';
Line 19426  sub modify_selfenrollment { Line 19807  sub modify_selfenrollment {
     return $resulttext;      return $resulttext;
 }  }
   
   sub modify_wafproxy {
       my ($dom,$action,$lastactref,%domconfig) = @_;
       my %servers = &Apache::lonnet::internet_dom_servers($dom);
       my (%othercontrol,%canset,%values,%curralias,%currvalue,@warnings,%wafproxy,
           %changes,%expirecache);
       foreach my $server (sort(keys(%servers))) {
           my $serverhome = &Apache::lonnet::get_server_homeID($servers{$server});
           if ($serverhome eq $server) {
               my $serverdom = &Apache::lonnet::host_domain($server);
               if ($serverdom eq $dom) {
                   $canset{$server} = 1;
               }
           }
       }
       if (ref($domconfig{'wafproxy'}) eq 'HASH') {
           %{$values{$dom}} = ();
           if (ref($domconfig{'wafproxy'}{'alias'}) eq 'HASH') {
               %curralias = %{$domconfig{'wafproxy'}{'alias'}};
           }
           foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext') {
               $currvalue{$item} = $domconfig{'wafproxy'}{$item};
           }
       }
       my $output;
       if (keys(%canset)) {
           %{$wafproxy{'alias'}} = ();
           foreach my $key (sort(keys(%canset))) {
               if ($env{'form.wafproxy_'.$dom}) {
                   $wafproxy{'alias'}{$key} = $env{'form.wafproxy_alias_'.$key};
                   $wafproxy{'alias'}{$key} =~ s/^\s+|\s+$//g;
                   if ($wafproxy{'alias'}{$key} ne $curralias{$key}) {
                       $changes{'alias'} = 1;
                   }
               } else {
                   $wafproxy{'alias'}{$key} = '';
                   if ($curralias{$key}) {
                       $changes{'alias'} = 1;
                   }
               }
               if ($wafproxy{'alias'}{$key} eq '') {
                   if ($curralias{$key}) {
                       $expirecache{$key} = 1;
                   }
                   delete($wafproxy{'alias'}{$key});
               }
           }
           unless (keys(%{$wafproxy{'alias'}})) {
               delete($wafproxy{'alias'});
           }
           # Localization for values in %warn occus in &mt() calls separately.
           my %warn = (
                        trusted => 'trusted IP range(s)',
                        vpnint => 'internal IP range(s) for VPN sessions(s)',
                        vpnext => 'IP range(s) for backend WAF connections',
                      );
           foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext') {
               my $possible = $env{'form.wafproxy_'.$item};
               $possible =~ s/^\s+|\s+$//g;
               if ($possible ne '') {
                   if ($item eq 'remoteip') {
                       if ($possible =~ /^[mhn]$/) {
                           $wafproxy{$item} = $possible;
                       }
                   } elsif ($item eq 'ipheader') {
                       if ($wafproxy{'remoteip'} eq 'h') {
                           $wafproxy{$item} = $possible;
                       }
                   } else {
                       my (@ok,$count);
                       if (($item eq 'vpnint') || ($item eq 'vpnext')) {
                           unless ($env{'form.wafproxy_vpnaccess'}) {
                               $possible = '';
                           }
                       } elsif ($item eq 'trusted') {
                           unless ($wafproxy{'remoteip'} eq 'h') {
                               $possible = '';
                           }
                       }
                       unless ($possible eq '') {
                           $possible =~ s/[\r\n]+/\s/g;
                           $possible =~ s/\s*-\s*/-/g;
                           $possible =~ s/\s+/,/g;
                       }
                       $count = 0;
                       if ($possible ne '') {
                           foreach my $poss (split(/\,/,$possible)) {
                               $count ++;
                               if (&validate_ip_pattern($poss)) {
                                   push(@ok,$poss);
                               }
                           }
                           if (@ok) {
                               $wafproxy{$item} = join(',',@ok);
                           }
                           my $diff = $count - scalar(@ok);
                           if ($diff) {
                               push(@warnings,'<li>'.
                                    &mt('[quant,_1,IP] invalid and excluded from saved value for [_2]',
                                        $diff,$warn{$item}).
                                    '</li>');
                           }
                       }
                   }
                   if ($wafproxy{$item} ne $currvalue{$item}) {
                       $changes{$item} = 1;
                   }
               } elsif ($currvalue{$item}) {
                   $changes{$item} = 1;
               } 
           }
       } else {
           if (keys(%curralias)) {
               $changes{'alias'} = 1;
           } 
           if (keys(%currvalue)) {
               foreach my $key (keys(%currvalue)) {
                   $changes{$key} = 1;
               }
           }
       }
       if (keys(%changes)) {
           my %defaultshash = (
                                 wafproxy => \%wafproxy,
                              ); 
           my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
                                                    $dom);
           if ($putresult eq 'ok') {
               my $cachetime = 24*60*60;
               my (%domdefaults,$updatedomdefs);
               foreach my $item ('ipheader','trusted','vpnint','vpnext') {
                   if ($changes{$item}) {
                       unless ($updatedomdefs) {
                           %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
                           $updatedomdefs = 1;
                       }
                       if ($wafproxy{$item}) {
                           $domdefaults{'waf_'.$item} = $wafproxy{$item};
                       } elsif (exists($domdefaults{'waf_'.$item})) {
                           delete($domdefaults{'waf_'.$item});
                       } 
                   }
               }
               if ($updatedomdefs) {
                   &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
                   if (ref($lastactref) eq 'HASH') {
                       $lastactref->{'domdefaults'} = 1;
                   }
               }
               if ((exists($wafproxy{'alias'})) || (keys(%expirecache))) {
                   my %updates = %expirecache;
                   foreach my $key (keys(%expirecache)) {
                       &Apache::lonnet::devalidate_cache_new('proxyalias',$key);
                   }
                   if (ref($wafproxy{'alias'}) eq 'HASH') {
                       my $cachetime = 24*60*60;
                       foreach my $key (keys(%{$wafproxy{'alias'}})) {
                           $updates{$key} = 1;
                           &Apache::lonnet::do_cache_new('proxyalias',$key,$wafproxy{'alias'}{$key},
                                                         $cachetime);
                       }
                   }
                   if (ref($lastactref) eq 'HASH') {
                       $lastactref->{'proxyalias'} = \%updates;
                   }
               }
               $output = &mt('Changes were made to Web Application Firewall/Reverse Proxy').'<ul>';
               foreach my $item ('alias','remoteip','ipheader','trusted','vpnint','vpnext') {
                   if ($changes{$item}) {
                       if ($item eq 'alias') {
                           my $numaliased = 0;
                           if (ref($wafproxy{'alias'}) eq 'HASH') {
                               my $shown;
                               if (keys(%{$wafproxy{'alias'}})) {
                                   foreach my $server (sort(keys(%{$wafproxy{'alias'}}))) {
                                       $shown .= '<li>'.&mt('[_1] aliased by [_2]',
                                                            &Apache::lonnet::hostname($server),
                                                            $wafproxy{'alias'}{$server}).'</li>';
                                       $numaliased ++;
                                   }
                                   if ($numaliased) {
                                       $output .= '<li>'.&mt('Aliases for hostnames set to: [_1]',
                                                             '<ul>'.$shown.'</ul>').'</li>';
                                   }
                               }
                           }
                           unless ($numaliased) {
                               $output .= '<li>'.&mt('Aliases deleted for hostnames').'</li>';
                           }
                       } else {
                           if ($item eq 'remoteip') {
                               my %ip_methods = &remoteip_methods();
                               if ($wafproxy{$item} =~ /^[mh]$/) {
                                   $output .= '<li>'.&mt("Method for determining user's IP set to: [_1]",
                                                         $ip_methods{$wafproxy{$item}}).'</li>';
                               } else {
                                   if (($env{'form.wafproxy_'.$dom}) && (ref($wafproxy{'alias'}) eq 'HASH')) {
                                       $output .= '<li>'.&mt("No method in use to get user's real IP (will report IP used by WAF).").
                                                  '</li>';
                                   } else {
                                       $output .= '<li>'.&mt('WAF/Reverse Proxy not in use').'</li>';
                                   }
                               }
                           } elsif ($item eq 'ipheader') {
                               if ($wafproxy{$item}) {
                                   $output .= '<li>'.&mt('Request header with remote IP set to: [_1]',
                                                         $wafproxy{$item}).'</li>';
                               } else {
                                   $output .= '<li>'.&mt('Request header with remote IP deleted').'</li>';
                               }
                           } elsif ($item eq 'trusted') {
                               if ($wafproxy{$item}) {
                                   $output .= '<li>'.&mt('Trusted IP range(s) set to: [_1]',
                                                         $wafproxy{$item}).'</li>';
                               } else {
                                   $output .= '<li>'.&mt('Trusted IP range(s) deleted').'</li>';
                               }
                           } elsif ($item eq 'vpnint') {
                               if ($wafproxy{$item}) {
                                   $output .= '<li>'.&mt('Internal IP Range(s) for VPN sessions set to: [_1]',
                                                          $wafproxy{$item}).'</li>';
                               } else {
                                   $output .= '<li>'.&mt('Internal IP Range(s) for VPN sessions deleted').'</li>';
                               }
                           } elsif ($item eq 'vpnext') {
                               if ($wafproxy{$item}) {
                                   $output .= '<li>'.&mt('IP Range(s) for backend WAF connections set to: [_1]',
                                                          $wafproxy{$item}).'</li>';
                               } else {
                                   $output .= '<li>'.&mt('IP Range(s) for backend WAF connections deleted').'</li>';
                               }
                           }
                       }
                   }
               }
           } else {
               $output = '<span class="LC_error">'.
                         &mt('An error occurred: [_1]',$putresult).'</span>';
           }
       } elsif (keys(%canset)) {
           $output = &mt('No changes made to Web Application Firewall/Reverse Proxy settings');
       }
       if (@warnings) {
           $output .= '<br />'.&mt('Warnings:').'<ul>'.
                          join("\n",@warnings).'</ul>';
       }
       return $output;
   }
   
   sub validate_ip_pattern {
       my ($pattern) = @_;
       if ($pattern =~ /^([^-]+)\-([^-]+)$/) {
           my ($start,$end) = ($1,$2);
           if ((&Net::CIDR::cidrvalidate($start)) && (&Net::CIDR::cidrvalidate($end))) {
               return 1;
           }
       } elsif (&Net::CIDR::cidrvalidate($pattern)) {
           return 1;
       }
       return
   }
   
 sub modify_usersessions {  sub modify_usersessions {
     my ($dom,$lastactref,%domconfig) = @_;      my ($dom,$lastactref,%domconfig) = @_;
     my @hostingtypes = ('version','excludedomain','includedomain');      my @hostingtypes = ('version','excludedomain','includedomain');
Line 20362  sub modify_loadbalancing { Line 21004  sub modify_loadbalancing {
                             $resulttext .= '<li>'.&mt('Load Balancer: [_1] -- cookie use enabled',                              $resulttext .= '<li>'.&mt('Load Balancer: [_1] -- cookie use enabled',
                                                       $balancer).'</li>';                                                         $balancer).'</li>'; 
                         }                          }
                         if (keys(%toupdate)) {                      }
                             my %thismachine;                  }
                             my $updatedhere;                  if (keys(%toupdate)) {
                             my $cachetime = 60*60*24;                      my %thismachine;
                             map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();                      my $updatedhere;
                             foreach my $lonhost (keys(%toupdate)) {                      my $cachetime = 60*60*24;
                                 if ($thismachine{$lonhost}) {                      map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
                                     unless ($updatedhere) {                      foreach my $lonhost (keys(%toupdate)) {
                                         &Apache::lonnet::do_cache_new('loadbalancing',$dom,                          if ($thismachine{$lonhost}) {
                                                                       $defaultshash{'loadbalancing'},                              unless ($updatedhere) {
                                                                       $cachetime);                                  &Apache::lonnet::do_cache_new('loadbalancing',$dom,
                                         $updatedhere = 1;                                                                $defaultshash{'loadbalancing'},
                                     }                                                                $cachetime);
                                 } else {                                  $updatedhere = 1;
                                     my $cachekey = &escape('loadbalancing').':'.&escape($dom);  
                                     &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);  
                                 }  
                             }                              }
                           } else {
                               my $cachekey = &escape('loadbalancing').':'.&escape($dom);
                               &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]);
                         }                          }
                     }                      }
                 }                  }
Line 21140  sub devalidate_remote_domconfs { Line 21782  sub devalidate_remote_domconfs {
     my %thismachine;      my %thismachine;
     map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();      map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
     my @posscached = ('domainconfig','domdefaults','ltitools','usersessions',      my @posscached = ('domainconfig','domdefaults','ltitools','usersessions',
                       'directorysrch','passwdconf','cats');                        'directorysrch','passwdconf','cats','proxyalias');
     if (keys(%servers)) {      if (keys(%servers)) {
         foreach my $server (keys(%servers)) {          foreach my $server (keys(%servers)) {
             next if ($thismachine{$server});              next if ($thismachine{$server});
             my @cached;              my @cached;
             foreach my $name (@posscached) {              foreach my $name (@posscached) {
                 if ($cachekeys->{$name}) {                  if ($cachekeys->{$name}) {
                     push(@cached,&escape($name).':'.&escape($dom));                      if ($name eq 'proxyalias') {
                           if (ref($cachekeys->{$name}) eq 'HASH') {  
                               foreach my $key (keys(%{$cachekeys->{$name}})) {
                                   push(@cached,&escape($name).':'.&escape($key));
                               }
                           }
                       } else {
                           push(@cached,&escape($name).':'.&escape($dom));
                       }
                 }                  }
             }              }
             if (@cached) {              if (@cached) {

Removed from v.1.372  
changed lines
  Added in v.1.381


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