[LON-CAPA-cvs] cvs: loncom / lontrans.pm /auth lonacc.pm /interface domainprefs.pm /lonnet/perl lonnet.pm

raeburn raeburn at source.lon-capa.org
Sat Apr 17 22:08:47 EDT 2021


raeburn		Sun Apr 18 02:08:47 2021 EDT

  Modified files:              
    /loncom	lontrans.pm 
    /loncom/interface	domainprefs.pm 
    /loncom/auth	lonacc.pm 
    /loncom/lonnet/perl	lonnet.pm 
  Log:
  - Bug 6914
   - Update domain config UI to support settings documented in
     Domain_Configuration_WAF_Proxy.tex
   - Use /adm/migrateuser to handle redirects when user with a LON-CAPA session
     switches between access via VPN and not via VPN (and vice versa). 
  
  
-------------- next part --------------
Index: loncom/lontrans.pm
diff -u loncom/lontrans.pm:1.29 loncom/lontrans.pm:1.30
--- loncom/lontrans.pm:1.29	Tue Jan  5 04:23:45 2021
+++ loncom/lontrans.pm	Sun Apr 18 02:08:46 2021
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # URL translation for User Files
 #
-# $Id: lontrans.pm,v 1.29 2021/01/05 04:23:45 raeburn Exp $
+# $Id: lontrans.pm,v 1.30 2021/04/18 02:08:46 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -29,8 +29,9 @@
 package Apache::lontrans;
 
 use strict;
-use Apache::Constants qw(:common :remotehost REDIRECT);
+use Apache::Constants qw(:common :remotehost);
 use Apache::lonnet;
+use Apache::loncommon;
 use Apache::File();
 use LONCAPA qw(:DEFAULT :match);
 
@@ -63,9 +64,9 @@
                 $vpnint = $proxyinfo->{'vpnint'};
                 $vpnext = $proxyinfo->{'vpnext'};
             }
-            my $redirect;
+            my ($redirect,$remote_ip);
             if ($hdrhost eq $alias) {
-                my $remote_ip = &Apache::lonnet::get_requestor_ip($r,REMOTE_NOLOOKUP);
+                $remote_ip = &Apache::lonnet::get_requestor_ip($r,REMOTE_NOLOOKUP);
                 if ($vpnext && &Apache::lonnet::ip_match($remote_ip,$vpnext)) {
                     $redirect = $hostname;
                     if ($redirect eq $hdrhost) {
@@ -73,7 +74,7 @@
                     }
                 }
             } elsif ($hdrhost eq $hostname) {
-                my $remote_ip = &Apache::lonnet::get_requestor_ip($r,REMOTE_NOLOOKUP,1);
+                $remote_ip = &Apache::lonnet::get_requestor_ip($r,REMOTE_NOLOOKUP,1);
                 unless (($remote_ip eq '127.0.0.1') || ($remote_ip eq '::1') ||
                         ($remote_ip eq &Apache::lonnet::get_host_ip($lonhost)) ||
                         ($vpnint && &Apache::lonnet::ip_match($remote_ip,$vpnint))) {
@@ -88,14 +89,29 @@
             }
             if ($redirect) {
                 my $uri = $r->uri;
+                unless ($uri eq '/adm/migrateuser') {
+                    my %user;
+                    my $handle = &Apache::lonnet::check_for_valid_session($r,undef,\%user);
+                    if (($handle) && ($user{'name'} ne '') && ($user{'domain'} ne '')) {
+                        my $token = &get_token($r,$remote_ip,\%user);
+                        unless ($token eq '') {
+                            $r->internal_redirect("/adm/migrateuser?token=$token");
+                            $r->set_handlers('PerlHandler'=> undef);
+                            return DECLINED;
+                        }
+                    }
+                }
                 my $protocol = 'http';
                 my $port = $r->get_server_port();
                 if ($port eq '443') {
                     $protocol = 'https';
                 }
-# FIXME should check if logged in, and if so use switchserver/migrateuser approach,
-# possibly moved to Access Handler?
-                $r->header_out(Location => $protocol.'://'.$redirect.$uri);
+                my $querystring = $r->args;
+                my $location = $protocol.'://'.$redirect.$uri;
+                if ($querystring) {
+                    $location .= "?$querystring";
+                }
+                $r->header_out(Location => $location);
                 return REDIRECT;
             }
         }
@@ -171,6 +187,44 @@
     return $redirect;
 }
 
+sub get_token {
+    my ($r,$remote_ip,$userref) = @_;
+    return unless (ref($userref) eq 'HASH');
+    my %user = %{$userref};
+    my %info = ('ip' => $remote_ip,
+                'domain'    => $user{'domain'},
+                'username'  => $user{'name'},
+                'server'    => $r->dir_config('lonHostID'),
+               );
+    my $query = $r->args;
+    if ($query) {
+        foreach my $pair (split(/&/,$query)) {
+            my ($name,$value) = split(/=/,$pair);
+            $name = &LONCAPA::unescape($name);
+            next unless (($name eq 'role') || ($name eq 'symb'));
+            $value =~ tr/+/ /;
+            $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
+            $info{$name} = $value;
+        }
+    }
+    unless ($info{'role'}) {
+        if ($user{'role'} ne '') {
+            $info{'role'} = $user{'role'};
+        }
+    }
+    unless ($info{'symb'}) {
+        unless ($r->uri eq '/adm/roles') {
+             $info{'origurl'} = $r->uri;
+        }
+    }
+    my $token = &Apache::lonnet::tmpput(\%info,$r->dir_config('lonHostID'));
+    unless (($token eq 'con_lost') || ($token eq 'refused') ||
+            ($token eq 'unknown_cmd') || ($token eq 'no_such_host')) {
+        return $token;
+    }
+    return;
+}
+
 1;
 __END__
 
Index: loncom/interface/domainprefs.pm
diff -u loncom/interface/domainprefs.pm:1.380 loncom/interface/domainprefs.pm:1.381
--- loncom/interface/domainprefs.pm:1.380	Sat Mar  6 13:39:54 2021
+++ loncom/interface/domainprefs.pm	Sun Apr 18 02:08:46 2021
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Handler to set domain-wide configuration settings
 #
-# $Id: domainprefs.pm,v 1.380 2021/03/06 13:39:54 raeburn Exp $
+# $Id: domainprefs.pm,v 1.381 2021/04/18 02:08:46 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -311,16 +311,16 @@
                       print => \&print_defaults,
                       modify => \&modify_defaults,
                     },
-        'wafproxy' =>  
-                    { text => 'Web Application Firewall/Reverse Proxy',  
+        'wafproxy' =>
+                    { text => 'Web Application Firewall/Reverse Proxy',
                       help => 'Domain_Configuration_WAF_Proxy',
-                      header => [{col1 => 'Domain server',
-                                  col2 => 'Alias for WAF/Reverse Proxy',
+                      header => [{col1 => 'Domain(s)',
+                                  col2 => 'Servers and WAF/Reverse Proxy alias(es)',
                                  },
-                                 {col1 => 'Setting',
-                                  col2 => 'Value',}],
+                                 {col1 => 'Domain(s)',
+                                  col2 => 'WAF Configuration',}],
                       print => \&print_wafproxy,
-                      modify => \&modify_wafproxy, 
+                      modify => \&modify_wafproxy,
                     },
         'passwords' =>
                     { text => 'Passwords (Internal authentication)',
@@ -855,6 +855,8 @@
         $output .= &lti_javascript($settings);
     } elsif ($action eq 'proctoring') {
         $output .= &proctoring_javascript($settings);
+    } elsif ($action eq 'wafproxy') {
+        $output .= &wafproxy_javascript($dom);
     }
     $output .=
          '<table class="LC_nested_outer">
@@ -2844,6 +2846,121 @@
 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 {
     my ($settings) = @_;
     my (%ordered,$total,%jstext);
@@ -7178,32 +7295,43 @@
     my $itemcount = 0;
     my $datatable;
     my %servers = &Apache::lonnet::internet_dom_servers($dom);
-    my (%othercontrol,%otherdoms,%aliases,%values,$setdom);
+    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);
-            $othercontrol{$server} = $serverdom;
+            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') {
-                    %{$values{$dom}} = ();
                     if (ref($settings->{'alias'}) eq 'HASH') {
                         $aliases{$dom} = $settings->{'alias'};
-                    }
-                    foreach my $item ('ipheader','trusted','vpnint','vpnext') {
-                        $values{$dom}{$item} = $settings->{$item};
+                        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)) {
@@ -7212,7 +7340,7 @@
             if (ref($config{$domain}) eq 'HASH') {
                 if (ref($config{$domain}{'wafproxy'}) eq 'HASH') {
                     $aliases{$domain} = $config{$domain}{'wafproxy'}{'alias'};
-                    foreach my $item ('ipheader','trusted','vpnint','vpnext') {
+                    foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext') {
                         $values{$domain}{$item} = $config{$domain}{'wafproxy'}{$item};
                     }
                 }
@@ -7221,59 +7349,152 @@
     }
     if ($position eq 'top') {
         my %servers = &Apache::lonnet::internet_dom_servers($dom);
+        my %aliasinfo;
         foreach my $server (sort(keys(%servers))) {
-            $itemcount ++; 
-            $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
-            $datatable .= '<tr'.$css_class.'>'.
-                          '<td>'.&mt('Hostname').': '.
-                                &Apache::lonnet::hostname($server).'</td>'.
-                          '<td class="LC_right_item">';
+            $itemcount ++;
+            my $dom_in_effect;
+            my $aliasrows = '<tr>'.
+                            '<td class="LC_left_item">'.&mt('Hostname').': '.
+                            &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) {
-                    $datatable .= $current;
+                    $aliasrows .= $current;
                 } else {
-                    $datatable .= &mt('None in effect');
+                    $aliasrows .= &mt('None in effect');
                 }
-                $datatable .= '<br /><span class="LC_small">('.
+                $aliasrows .= '<td class="LC_left_item"><span class="LC_small">('.
                               &mt('WAF/Reverse Proxy controlled by domain: [_1]',
-                                  '<b>'.$othercontrol{$server}.'</b>').'</span>';
+                                  '<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};
                     }
                 }
-                $datatable .= '<input type="text" name="wafproxy_alias_'.$server.'" '.
-                              'value="'.$current.'" size="30" />';
+                $aliasrows .= '<td class="LC_left_item">'.&mt('WAF/Reverse Proxy Alias').': '.
+                              '<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?').' <label>'.
+                         '<input type="radio" name="wafproxy_'.$dom.'" value="1"'.$wafon.$onclick.' />'.
+                         &mt('Yes').'</label>'.(' '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++;
             }
-            $datatable .= '</td></tr>';
         }
     } else {
         if ($setdom) {
             $itemcount ++;
             $css_class = $itemcount%2 ? ' class="LC_odd_row"' : '';
-            $datatable .= '<tr'.$css_class.'>'.
+            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 />'.
-                          &mt('Format for comma separated IP blocks').':<br />'.
-                          &mt('A.B.C.D/N or A.B.C.D - E.F.G.H').'</td>'.
-                          '<td class="LC_left_item"><table>';
-            foreach my $item ('ipheader','trusted','vpnint','vpnext') {
-                $datatable .= '<tr>'.
-                              '<td valign="top">'.$lt{$item}.': ';
-                if ($item eq 'ipheader') {
-                    $datatable .= '<input type="text" value="'.$values{$dom}{$item}.'" '.
-                                  'name="wafproxy_'.$item.'" />';
- 
-                } else {
-                    $datatable .= '<textarea name="wafproxy_'.$item.'" rows="3" cols="80">'.
-                                  $values{$dom}{$item}.'</textarea>';
-                }
-                $datatable .= '</td></tr>';
+                          '<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'}.': '.
+                          '<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'}.': '.
+                          '<input type="text" value="'.$values{$dom}{'ipheader'}.'" '.
+                          'name="wafproxy_ipheader" />'.
+                          '</td></tr>'."\n".
+                          '<tr id="wafproxy_trust"'.$currwafdisplay.'><td>'.
+                          $lt{'trusted'}.': '.
+                          '<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>'.(' '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}.': '.
+                              '<textarea name="wafproxy_'.$item.'" rows="3" cols="80">'.
+                              $values{$dom}{$item}.'</textarea>'.
+                              '</td></tr>'."\n";
             }
             $datatable .= '</table></td></tr>';
         }
@@ -7284,15 +7505,15 @@
                 $datatable .= '<tr'.$css_class.'>'.
                               '<td class="LC_left_item">'.&mt('Domain: [_1]',$domain).'</td>'.
                               '<td class="LC_left_item"><table>';
-                foreach my $item ('ipheader','trusted','vpnint','vpnext') {
+                foreach my $item ('remoteip','ipheader','trusted','vpnint','vpnext') {
                     my $showval = &mt('None');
                     if ($values{$domain}{$item}) {
-                        $showval = $values{$domain}{$item}; 
+                        $showval = $values{$domain}{$item};
                     }
                     $datatable .= '<tr>'.
                                   '<td>'.$lt{$item}.': '.$showval.'</td></tr>';
                 }
-                $datatable .= '</table></td></tr>'; 
+                $datatable .= '</table></td></tr>';
             }
         }
     }
@@ -7302,10 +7523,25 @@
 
 sub wafproxy_titles {
     return &Apache::lonlocal::texthash(
-               vpnint => 'Internal IP Range(s) for VPN sessions',
-               vpnext => 'IP Range for backend WAF connections',
-               trusted => 'Trusted IP range(s)',
-               ipheader => 'Custom request header',
+               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',
            );
 }
 
@@ -19582,26 +19818,33 @@
             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 ('ipheader','trusted','exempt') {
-                        $currvalue{$item} = $domconfig{'wafproxy'}{$item};
-                    }
-                }
             }
         }
     }
+    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))) {
-            $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;
+            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}) {
@@ -19616,21 +19859,39 @@
         # Localization for values in %warn occus in &mt() calls separately.
         my %warn = (
                      trusted => 'trusted IP range(s)',
-                     exempt => 'exempt IP range(s)', 
+                     vpnint => 'internal IP range(s) for VPN sessions(s)',
+                     vpnext => 'IP range(s) for backend WAF connections',
                    );
-        foreach my $item ('ipheader','trusted','exempt') {
+        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 'ipheader') {
-                    $wafproxy{$item} = $possible;
+                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);
-                    $possible =~ s/[\r\n]+/\s/g;
-                    $possible =~ s/\s*-\s*/-/g;
-                    $possible =~ s/\s+/,/g;
+                    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) {
+                    if ($possible ne '') {
                         foreach my $poss (split(/\,/,$possible)) {
                             $count ++;
                             if (&validate_ip_pattern($poss)) {
@@ -19647,15 +19908,22 @@
                                      $diff,$warn{$item}).
                                  '</li>');
                         }
-                        if ($wafproxy{$item} ne $currvalue{$item}) {
-                            $changes{$item} = 1; 
-                        }
                     }
                 }
-            } else {
-                if ($currvalue{$item}) {
+                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;
             }
         }
     }
@@ -19668,7 +19936,7 @@
         if ($putresult eq 'ok') {
             my $cachetime = 24*60*60;
             my (%domdefaults,$updatedomdefs);
-            foreach my $item ('ipheader','trusted','exempt') {
+            foreach my $item ('ipheader','trusted','vpnint','vpnext') {
                 if ($changes{$item}) {
                     unless ($updatedomdefs) {
                         %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
@@ -19705,7 +19973,7 @@
                 }
             }
             $output = &mt('Changes were made to Web Application Firewall/Reverse Proxy').'<ul>';
-            foreach my $item ('alias','ipheader','trusted','exempt') {
+            foreach my $item ('alias','remoteip','ipheader','trusted','vpnint','vpnext') {
                 if ($changes{$item}) {
                     if ($item eq 'alias') {
                         my $numaliased = 0;
@@ -19728,26 +19996,46 @@
                             $output .= '<li>'.&mt('Aliases deleted for hostnames').'</li>';
                         }
                     } else {
-                        if ($item eq 'ipheader') {
+                        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('Custom request header set to [_1]',
+                                $output .= '<li>'.&mt('Request header with remote IP set to: [_1]',
                                                       $wafproxy{$item}).'</li>';
                             } else {
-                                $output .= '<li>'.&mt('Custom request header deleted').'</li>';
+                                $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]',
+                                $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 'exempt') {
+                        } 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('Exempt IP range(s) set to [_1]',
+                                $output .= '<li>'.&mt('IP Range(s) for backend WAF connections set to: [_1]',
                                                        $wafproxy{$item}).'</li>';
                             } else {
-                                $output .= '<li>'.&mt('Exempt IP range(s) deleted').'</li>';
+                                $output .= '<li>'.&mt('IP Range(s) for backend WAF connections deleted').'</li>';
                             }
                         }
                     }
Index: loncom/auth/lonacc.pm
diff -u loncom/auth/lonacc.pm:1.188 loncom/auth/lonacc.pm:1.189
--- loncom/auth/lonacc.pm:1.188	Wed Feb 10 11:35:40 2021
+++ loncom/auth/lonacc.pm	Sun Apr 18 02:08:46 2021
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Cookie Based Access Handler
 #
-# $Id: lonacc.pm,v 1.188 2021/02/10 11:35:40 raeburn Exp $
+# $Id: lonacc.pm,v 1.189 2021/04/18 02:08:46 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -559,7 +559,7 @@
             my $hostname = $r->hostname();
             my $lonhost = &Apache::lonnet::host_from_dns($hostname);
             if ($lonhost) {
-                my $actual = &Apache::lonnet::absolute_url($hostname);
+                my $actual = &Apache::lonnet::absolute_url($hostname,1,1);
                 my $exphostname = &Apache::lonnet::hostname($lonhost);
                 my $expected = $Apache::lonnet::protocol{$lonhost}.'://'.$hostname;
                 unless ($actual eq $expected) {
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.1446 loncom/lonnet/perl/lonnet.pm:1.1447
--- loncom/lonnet/perl/lonnet.pm:1.1446	Fri Apr  9 02:01:11 2021
+++ loncom/lonnet/perl/lonnet.pm	Sun Apr 18 02:08:47 2021
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.1446 2021/04/09 02:01:11 raeburn Exp $
+# $Id: lonnet.pm,v 1.1447 2021/04/18 02:08:47 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -3482,11 +3482,29 @@
 # --------------------------------------------------------- Server Side Include
 
 sub absolute_url {
-    my ($host_name) = @_;
+    my ($host_name,$unalias,$keep_proto) = @_;
     my $protocol = ($ENV{'SERVER_PORT'} == 443?'https://':'http://');
     if ($host_name eq '') {
 	$host_name = $ENV{'SERVER_NAME'};
     }
+    if ($unalias) {
+        my $alias = &get_proxy_alias();
+        if ($alias eq $host_name) {
+            my $lonhost = $perlvar{'lonHostID'};
+            my $hostname = &hostname($lonhost);
+            my $lcproto; 
+            if (($keep_proto) || ($hostname eq '')) {
+                $lcproto = $protocol;
+            } else {
+                $lcproto = $protocol{$lonhost};
+                $lcproto = 'http' if ($lcproto ne 'https');
+                $lcproto .= '://';
+            }
+            unless ($hostname eq '') {
+                return $lcproto.$hostname;
+            }
+        }
+    }
     return $protocol.$host_name;
 }
 
@@ -3503,12 +3521,13 @@
 sub ssi {
 
     my ($fn,%form)=@_;
-    my $request;
+    my ($host,$request,$response);
+    $host = &absolute_url('',1);
 
     $form{'no_update_last_known'}=1;
     &Apache::lonenc::check_encrypt(\$fn);
     if (%form) {
-      $request=new HTTP::Request('POST',&absolute_url().$fn);
+      $request=new HTTP::Request('POST',$host.$fn);
       $request->content(join('&',map { 
             my $name = escape($_);
             "$name=" . ( ref($form{$_}) eq 'ARRAY' 
@@ -3516,7 +3535,7 @@
             : &escape($form{$_}) );    
         } keys(%form)));
     } else {
-      $request=new HTTP::Request('GET',&absolute_url().$fn);
+      $request=new HTTP::Request('GET',$host.$fn);
     }
 
     $request->header(Cookie => $ENV{'HTTP_COOKIE'});
@@ -3530,8 +3549,8 @@
                                  ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:'')))) {
         $islocal = 1;
     }
-    my $response= &LONCAPA::LWPReq::makerequest($lonhost,$request,'',\%perlvar,
-                                                '','','',$islocal);
+    $response= &LONCAPA::LWPReq::makerequest($lonhost,$request,'',\%perlvar,
+                                             '','','',$islocal);
 
     if (wantarray) {
 	return ($response->content, $response);
@@ -14336,7 +14355,17 @@
     my ($r,$nolookup,$noproxy) = @_;
     my $from_ip;
     if (ref($r)) {
-        $from_ip = $r->get_remote_host($nolookup);
+        if ($r->can('useragent_ip')) {
+            if ($noproxy && $r->can('client_ip')) {
+                $from_ip = $r->client_ip();
+            } else {
+                $from_ip = $r->useragent_ip();
+            }
+        } elsif ($r->connection->can('remote_ip')) {
+            $from_ip = $r->connection->remote_ip();
+        } else {
+            $from_ip = $r->get_remote_host($nolookup);
+        }
     } else {
         $from_ip = $ENV{'REMOTE_ADDR'};
     }


More information about the LON-CAPA-cvs mailing list