[LON-CAPA-cvs] cvs: loncom /auth lonacc.pm publiccheck.pm /interface lonaboutme.pm loncommon.pm portfolio.pm /lonnet/perl lonnet.pm

raeburn raeburn at source.lon-capa.org
Mon Dec 1 17:53:01 EST 2014


raeburn		Mon Dec  1 22:53:01 2014 EDT

  Modified files:              
    /loncom/interface	lonaboutme.pm loncommon.pm portfolio.pm 
    /loncom/auth	lonacc.pm publiccheck.pm 
    /loncom/lonnet/perl	lonnet.pm 
  Log:
  - Bug 6690
    - IP-based access control for portfolio files added to existing "conditional" 
      access types used to grant read access to others besides the owner.
  
  
-------------- next part --------------
Index: loncom/interface/lonaboutme.pm
diff -u loncom/interface/lonaboutme.pm:1.157 loncom/interface/lonaboutme.pm:1.158
--- loncom/interface/lonaboutme.pm:1.157	Thu Jun 19 00:36:29 2014
+++ loncom/interface/lonaboutme.pm	Mon Dec  1 22:52:48 2014
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Personal Information Page
 #
-# $Id: lonaboutme.pm,v 1.157 2014/06/19 00:36:29 raeburn Exp $
+# $Id: lonaboutme.pm,v 1.158 2014/12/01 22:52:48 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -401,7 +401,7 @@
 
         } else {
             $r->print('\\\\\textbf{'.&mt('User Notes, Records of Face-To-Face Discussions, and Critical Messages in Course').'}\\\\'.&mt('Shared by course faculty and staff').'\\\\\\\\');
-            &Apache::lonmsgdisplay::disfacetoface($r,$cnum,$cdom, 'tex');
+            &Apache::lonmsgdisplay::disfacetoface($r,$cnum,$cdom,$target);
         }
     }
     if ($target ne 'tex') {
@@ -671,9 +671,11 @@
 sub build_hierarchy {
     my ($r,$cdom,$cnum,$portaccess,$is_course,$filecounts,$mode,$access_info,
         $allfileshash,$group) = @_;
+    my $clientip = $r->get_remote_host();
     foreach my $filename (sort(keys(%{$access_info}))) {
         my $access_status =
-           &Apache::lonnet::get_portfolio_access($cdom,$cnum,$filename,$group,$$access_info{$filename});
+           &Apache::lonnet::get_portfolio_access($cdom,$cnum,$filename,$group,$clientip,
+                                                 $access_info->{$filename});
         if ($portaccess eq 'both') {
             if (($access_status ne 'ok') &&
                 ($access_status !~  /^[^:]+:guest_/)) {
Index: loncom/interface/loncommon.pm
diff -u loncom/interface/loncommon.pm:1.1200 loncom/interface/loncommon.pm:1.1201
--- loncom/interface/loncommon.pm:1.1200	Fri Nov 21 17:59:06 2014
+++ loncom/interface/loncommon.pm	Mon Dec  1 22:52:48 2014
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.1200 2014/11/21 17:59:06 raeburn Exp $
+# $Id: loncommon.pm,v 1.1201 2014/12/01 22:52:48 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -4739,13 +4739,13 @@
 ###############################################
 
 sub check_ip_acc {
-    my ($acc)=@_;
+    my ($acc,$clientip)=@_;
     &Apache::lonxml::debug("acc is $acc");
     if (!defined($acc) || $acc =~ /^\s*$/ || $acc =~/^\s*no\s*$/i) {
         return 1;
     }
     my $allowed=0;
-    my $ip=$env{'request.host'} || $ENV{'REMOTE_ADDR'};
+    my $ip=$env{'request.host'} || $ENV{'REMOTE_ADDR'} || $clientip;
 
     my $name;
     foreach my $pattern (split(',',$acc)) {
Index: loncom/interface/portfolio.pm
diff -u loncom/interface/portfolio.pm:1.253 loncom/interface/portfolio.pm:1.254
--- loncom/interface/portfolio.pm:1.253	Wed Jun 18 17:37:48 2014
+++ loncom/interface/portfolio.pm	Mon Dec  1 22:52:49 2014
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # portfolio browser
 #
-# $Id: portfolio.pm,v 1.253 2014/06/18 17:37:48 raeburn Exp $
+# $Id: portfolio.pm,v 1.254 2014/12/01 22:52:49 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -942,9 +942,11 @@
 
 sub explain_conditionals {
     return
-        &mt('Conditional files are accessible to logged-in users with accounts in the LON-CAPA network, who satisfy the conditions you set.').'<br />'."\n".
-        &mt('The conditions can include affiliation with a particular course or community, or a user account in a specific domain.').'<br />'."\n".
-        &mt('Alternatively access can be granted to people with specific LON-CAPA usernames and domains.');
+        &mt('Conditional files are accessible to users who satisfy the conditions you set.').'<br /><ul>'.
+        '<li>'.&mt('Conditions can be IP-based, in which case no log-in is required').'</li>'.
+        '<li>'.&mt("Conditions can also be based on a user's status, in which case the user needs an account in the LON-CAPA network, and needs to be logged in.").'<br />'."\n".
+        &mt('The status-based conditions can include affiliation with a particular course or community, or a user account in a specific domain.').'<br />'."\n".
+        &mt('Alternatively access can be granted to people with specific LON-CAPA usernames and domains.').'</li></ul>';
 }
 
 sub view_access_settings {
@@ -985,8 +987,9 @@
                       domains => 'Conditional: domain-based',
                       users => 'Conditional: user-based',
                       course => 'Conditional: course/community-based',
+                      ip     => 'Conditional: IP-based',
                      );
-    my @allscopes = ('public','guest','domains','users','course');
+    my @allscopes = ('public','guest','domains','users','course','ip');
     foreach my $scope (@allscopes) {
         if ((!(exists($todisplay{$scope}))) || (ref($todisplay{$scope}) ne 'HASH')) {
             next;
@@ -1063,6 +1066,9 @@
                 } elsif ($scope eq 'users') {
                     my $curr_user_list = &sort_users($content->{'users'});
                     $r->print(&mt('Users: ').$curr_user_list);
+                } elsif ($scope eq 'ip') {
+                    my $curr_ips_list = &sort_ips($content->{'ip'});
+                    $r->print(&mt('IP(s): ').$curr_ips_list);
                 } else {
                     $r->print(' ');
                 }
@@ -1171,7 +1177,7 @@
     my $totalnew = 0;
     my $status = 'new';
     my ($firstitem,$lastitem);
-    my @types = ('course','domains','users');
+    my @types = ('course','domains','users','ip');
     foreach my $newitem (@types) {
         $allnew += $env{'form.new'.$newitem};
     }
@@ -1183,6 +1189,7 @@
            course  => 'course/community',
            domains => 'domain',
            users   => 'user',
+           ip      => 'IP',
         );
         foreach my $newitem (@types) {
             next if ($env{'form.new'.$newitem} <= 0);
@@ -1286,6 +1293,13 @@
 		'udom'  => $udom
 		});
 	}
+    } elsif ($scope eq 'ip') {
+        my $ipslist = $env{'form.ips_'.$num};
+        $ipslist =~ s/\s+//sg;
+        my %ipshash = map { ($_,1) } (split(/,/,$ipslist));
+        foreach my $ip (keys(%ipshash)) {
+            push(@{$record->{'ip'}},$ip);
+        }
     }
     return $record;
 }
@@ -1311,6 +1325,13 @@
     return $curr_user_list;
 }
 
+sub sort_ips {
+    my ($ips) = @_;
+    if (ref($ips) eq 'ARRAY') {
+        return join(",\n",sort(@{$ips}));
+    }
+}
+
 sub access_setting_table {
     my ($r,$url,$filename,$access_controls,$action) = @_;
     my ($public,$publictext);
@@ -1320,6 +1341,7 @@
     my @courses = ();
     my @domains = ();
     my @users = ();
+    my @ips = ();
     my $now = time;
     my $then = $now + (60*60*24*180); # six months approx.
     my ($num,$scope,$publicnum,$guestnum);
@@ -1342,6 +1364,8 @@
                 push(@domains,$key);
             } elsif ($scope eq 'users') {
                 push(@users,$key);
+            } elsif ($scope eq 'ip') {
+                push(@ips,$key);
             }
         }
         $acl_count{$scope} ++;
@@ -1353,7 +1377,7 @@
                            $guesttext,$access_controls,%conditionals);
     } else {
         &condition_setting($r,$access_controls,$now,$then,\%acl_count,
-                           \@domains,\@users,\@courses);
+                           \@domains,\@users,\@courses,\@ips);
     }
     $r->print('</td></tr></table>');
 }
@@ -1398,14 +1422,14 @@
     $r->print(&Apache::loncommon::end_data_table_row());
     $r->print(&Apache::loncommon::end_data_table());
     $r->print('</td></tr><tr><td colspan="3"> </td></tr>'.
-              '<tr><td colspan="3">');
+              '<tr><td colspan="3" valign="top">');
     my $numconditionals = 0;
     my $conditionstext;
     my %cond_status;
-    foreach my $scope ('domains','users','course') {
+    foreach my $scope ('domains','users','course','ip') {
         $numconditionals += $acl_count->{$scope}; 
         if ($acl_count->{$scope} > 0) {
-            if ($conditionstext ne 'Active') { 
+            if ($conditionstext ne 'Active') {
                 foreach my $key (keys(%{$conditionals{$scope}})) {
                     $conditionstext = &acl_status($start->{$key},$end->{$key},$now);
                     if ($conditionstext eq 'Active') {
@@ -1436,24 +1460,20 @@
         &build_access_summary($r,$count,$chg,%conditionals);
         $r->print(&Apache::loncommon::end_data_table());
     } else {
-        $r->print(&make_anchor($url,\%anchor_fields,&mt('Add conditional access')).' '.&mt('based on domain, username, or course/community affiliation.'));
+        $r->print(&make_anchor($url,\%anchor_fields,&mt('Add conditional access')).' '.&mt("based on domain, username, course/community affiliation or user's IP address."));
     }
 }
 
 sub condition_setting {
-    my ($r,$access_controls,$now,$then,$acl_count,$domains,$users,$courses) = @_;
+    my ($r,$access_controls,$now,$then,$acl_count,$domains,$users,$courses,$ips) = @_;
     $r->print('<tr><td valign="top">');
     &access_element($r,'domains',$acl_count,$domains,$access_controls,$now,$then);
     $r->print('</td><td> </td><td valign="top">');
     &access_element($r,'users',$acl_count,$users,$access_controls,$now,$then);
-    $r->print('</td></tr><tr><td colspan="3"></td></tr><tr>');
-    if ($acl_count->{course} > 0) {
-        $r->print('<td colspan="3" valign="top">');
-    } else {
-        $r->print('<td valign="top">');
-    }
+    $r->print('</td></tr><tr><td colspan="3"></td></tr><tr><td valign="top">');
     &access_element($r,'course',$acl_count,$courses,$access_controls,$now,$then);
-    $r->print('</td>');
+    $r->print('</td><td> </td><td valign="top">');
+    &access_element($r,'ip',$acl_count,$ips,$access_controls,$now,$then);
     $r->print('</td></tr></table>');
 }
 
@@ -1473,7 +1493,8 @@
     my %typetext = (
         domains => 'Domain',
         users   => 'User',
-        course  => 'Course/Community'
+        course  => 'Course/Community',
+        ip      => 'IP',
     );
     $r->print('<h3>'.&mt($typetext{$type}.'-based conditional access:').' ');
     if ($$acl_count{$type}) {
@@ -1498,6 +1519,9 @@
     } elsif ($type eq 'users') {
         $showtype = &mt('Users');
         $infotype = 'User';
+    } elsif ($type eq 'ip') {
+        $showtype = &mt('IP-based');
+        $infotype = 'IP';  
     }
     if (@{$items} > 0) {
         my @all_doms;
@@ -1507,7 +1531,6 @@
         $r->print('<th>'.&mt('Action?').'</th><th>'.$showtype.'</th><th>'.
               &mt('Dates available').'</th>');
         if ($type eq 'course' && $status eq 'old') {
-            
             $r->print('<th>'.&mt('Allowed course/community affiliations').
                       '</th>');
             $colspan ++;
@@ -1524,6 +1547,8 @@
                             $then);
             } elsif ($type eq 'users') {
                 &users_row($r,$status,$key,$access_controls,$now,$then);
+            } elsif ($type eq 'ip') {
+                &ips_row($r,$status,$key,$access_controls,$now,$then);
             }
 	    $r->print(&Apache::loncommon::end_data_table_row());
         }
@@ -1702,6 +1727,23 @@
     $r->print('<td>'.&actionbox($status,$num,$scope).'</td><td>'.&mt("Format for users' username:domain information:").'<br /><tt>sparty:msu,illini:uiuc  ... etc.</tt><br /><textarea name="users_'.$num.'" cols="30"  rows="5">'.$curr_user_list.'</textarea></td><td>'.&dateboxes($num,$start,$end).'</td>');
 }
 
+sub ips_row {
+    my ($r,$status,$item,$access_controls,$now,$then) = @_;
+    my ($num,$scope,$end,$start) = &set_identifiers($status,$item,$now,$then,
+                                                    'ip');
+    my $curr_ips_list;
+    if ($status eq 'old') {
+        my $content = $$access_controls{$item};
+        $curr_ips_list = &sort_ips($content->{'ip'});
+    }
+    $r->print('<td>'.&actionbox($status,$num,$scope).'</td><td>'.&mt('Format for IP controls').'<br />'.
+              &mt('[_1] or [_2] or [_3] or [_4] or [_5]','<tt>35.8.*</tt>','<tt>35.8.3.[34-56]</tt>',
+                  '<tt>*.msu.edu</tt>','<tt>35.8.3.34</tt>','<tt>somehostname.pa.msu.edu</tt>').'<br />'.
+              &mt('Use a comma to separate different ranges.').'</br/>'.
+              '<textarea name="ips_'.$num.'" cols="30"  rows="5">'.$curr_ips_list.'</textarea></td>'.
+              '<td>'.&dateboxes($num,$start,$end).'</td>');
+}
+
 sub additional_item {
     my ($type) = @_;
     my $showtype;
@@ -1711,6 +1753,8 @@
         $showtype = 'domain';
     } elsif ($type eq 'users') {
         $showtype = 'user';
+    } elsif ($type eq 'ip') {
+        $showtype = 'IP';
     }
     return
         &mt('Add new '.$showtype.'-based condition(s)?')
@@ -1723,7 +1767,7 @@
     my $output = '<span class="LC_nobreak"><label>';
     if ($status eq 'new') {
         my $checkstate;
-        if ($scope eq 'domains' || $scope eq 'users' || $scope eq 'course') {
+        if ($scope eq 'domains' || $scope eq 'users' || $scope eq 'course' || $scope eq 'ip') {
             $checkstate = 'checked="checked"';
         }
         $output .= '<input type="checkbox" name="activate" value="'.$num.'" '.
@@ -1735,7 +1779,7 @@
                    '<label><input type="checkbox" name="update" value="'.
                    $num.'" />'.&mt('Update');
     }
-    $output .= '</label></span><input type="hidden" name="scope_'.$num.                '" value="'.$scope.'" />';
+    $output .= '</label></span><input type="hidden" name="scope_'.$num.'" value="'.$scope.'" />';
     return $output;
 }
                                                                                    
Index: loncom/auth/lonacc.pm
diff -u loncom/auth/lonacc.pm:1.159 loncom/auth/lonacc.pm:1.160
--- loncom/auth/lonacc.pm:1.159	Sat Oct 18 21:40:06 2014
+++ loncom/auth/lonacc.pm	Mon Dec  1 22:52:54 2014
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Cookie Based Access Handler
 #
-# $Id: lonacc.pm,v 1.159 2014/10/18 21:40:06 raeburn Exp $
+# $Id: lonacc.pm,v 1.160 2014/12/01 22:52:54 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -603,6 +603,12 @@
                             return HTTP_NOT_ACCEPTABLE;
                         }
                     }
+                } elsif (($handle =~ /^publicuser_\d+$/) && (&Apache::lonnet::is_portfolio_url($requrl))) {
+                    my $clientip = $r->get_remote_host();
+                    if (&Apache::lonnet::allowed('bre',$requrl,undef,undef,$clientip) ne 'F') {
+                        $env{'user.error.msg'}="$requrl:bre:1:1:Access Denied";
+                        return HTTP_NOT_ACCEPTABLE;
+                    }
                 } else {
 		    $env{'user.error.msg'}="$requrl:bre:1:1:Access Denied";
 		    return HTTP_NOT_ACCEPTABLE;
@@ -741,7 +747,8 @@
     }
 # ------------------------------------ See if this is a viewable portfolio file
     if (&Apache::lonnet::is_portfolio_url($requrl)) {
-	my $access=&Apache::lonnet::allowed('bre',$requrl);
+        my $clientip = $r->get_remote_host();
+        my $access=&Apache::lonnet::allowed('bre',$requrl,undef,undef,$clientip);
 	if ($access eq 'A') {
 	    &Apache::restrictedaccess::setup_handler($r);
 	    return OK;
Index: loncom/auth/publiccheck.pm
diff -u loncom/auth/publiccheck.pm:1.23 loncom/auth/publiccheck.pm:1.24
--- loncom/auth/publiccheck.pm:1.23	Fri Dec 13 02:10:27 2013
+++ loncom/auth/publiccheck.pm	Mon Dec  1 22:52:54 2014
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Cookie Based Access Handler
 #
-# $Id: publiccheck.pm,v 1.23 2013/12/13 02:10:27 raeburn Exp $
+# $Id: publiccheck.pm,v 1.24 2014/12/01 22:52:54 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -70,7 +70,7 @@
     } elsif (&Apache::lonnet::is_portfolio_url($requrl)) {
 	my (undef,$udom,$unum,$file_name,$group) = 
 	    &Apache::lonnet::parse_portfolio_url($requrl);
-        my $access = &process_portfolio($udom,$unum,$file_name,$group);
+        my $access = &process_portfolio($r,$udom,$unum,$file_name,$group);
         if ($access) {
             &process_public($r,$requrl,$access);
             return OK;
@@ -102,11 +102,12 @@
 }
 
 sub process_portfolio {
-    my ($udom,$unum,$file_name,$group) = @_;
+    my ($r,$udom,$unum,$file_name,$group) = @_;
     my $current_perms = &Apache::lonnet::get_portfile_permissions($udom,$unum);
     my %access_controls = &Apache::lonnet::get_access_controls($current_perms,$group,$file_name);
     my $access = '';
     my $now = time;
+    my $clientip = $r->get_remote_host();
     foreach my $key (keys(%{$access_controls{$file_name}})) {
         my ($num,$scope,$end,$start) = ($key =~ /^([^:]+):([a-z]+)_(\d*)_?(\d*)$/);
         if ($start > $now) {
@@ -119,6 +120,16 @@
             $access = 'public';
             last;
         }
+        if ($scope eq 'ip') {
+            if (ref($access_controls{$file_name}{$key}) eq 'HASH') {
+                if (ref($access_controls{$file_name}{$key}{'ip'}) eq 'ARRAY') {
+                    if (&Apache::loncommon::check_ip_acc(join(',',@{$access_controls{$file_name}{$key}{'ip'}}),$clientip)) {
+                        $access = 'ip';
+                        last;
+                    }
+                }
+            }
+        }
         if ($scope eq 'guest') {
             $access = 'guest';
         }
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.1269 loncom/lonnet/perl/lonnet.pm:1.1270
--- loncom/lonnet/perl/lonnet.pm:1.1269	Mon Nov 24 02:36:21 2014
+++ loncom/lonnet/perl/lonnet.pm	Mon Dec  1 22:53:00 2014
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.1269 2014/11/24 02:36:21 raeburn Exp $
+# $Id: lonnet.pm,v 1.1270 2014/12/01 22:53:00 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -6050,9 +6050,9 @@
 # -------------------------------------------------- portfolio access checking
 
 sub portfolio_access {
-    my ($requrl) = @_;
+    my ($requrl,$clientip) = @_;
     my (undef,$udom,$unum,$file_name,$group) = &parse_portfolio_url($requrl);
-    my $result = &get_portfolio_access($udom,$unum,$file_name,$group);
+    my $result = &get_portfolio_access($udom,$unum,$file_name,$group,$clientip);
     if ($result) {
         my %setters;
         if ($env{'user.name'} eq 'public' && $env{'user.domain'} eq 'public') {
@@ -6078,7 +6078,7 @@
 }
 
 sub get_portfolio_access {
-    my ($udom,$unum,$file_name,$group,$access_hash) = @_;
+    my ($udom,$unum,$file_name,$group,$clientip,$access_hash) = @_;
 
     if (!ref($access_hash)) {
 	my $current_perms = &get_portfile_permissions($udom,$unum);
@@ -6087,7 +6087,7 @@
 	$access_hash = $access_controls{$file_name};
     }
 
-    my ($public,$guest, at domains, at users, at courses, at groups);
+    my ($public,$guest, at domains, at users, at courses, at groups, at ips);
     my $now = time;
     if (ref($access_hash) eq 'HASH') {
         foreach my $key (keys(%{$access_hash})) {
@@ -6111,10 +6111,25 @@
                 push(@courses,$key);
             } elsif ($scope eq 'group') {
                 push(@groups,$key);
+            } elsif ($scope eq 'ip') {
+                push(@ips,$key);
             }
         }
         if ($public) {
             return 'ok';
+        } elsif (@ips > 0) {
+            my $allowed;
+            foreach my $ipkey (@ips) {
+                if (ref($access_hash->{$ipkey}{'ip'}) eq 'ARRAY') {
+                    if (&Apache::loncommon::check_ip_acc(join(',',@{$access_hash->{$ipkey}{'ip'}}),$clientip)) {
+                        $allowed = 1;
+                        last; 
+                    }
+                }
+            }
+            if ($allowed) {
+                return 'ok';
+            }
         }
         if ($env{'user.name'} eq 'public' && $env{'user.domain'} eq 'public') {
             if ($guest) {
@@ -6598,7 +6613,7 @@
 # ------------------------------------------------- Check for a user privilege
 
 sub allowed {
-    my ($priv,$uri,$symb,$role)=@_;
+    my ($priv,$uri,$symb,$role,$clientip)=@_;
     my $ver_orguri=$uri;
     $uri=&deversion($uri);
     my $orguri=$uri;
@@ -6825,7 +6840,7 @@
 	&& $thisallowed ne 'F' 
 	&& $thisallowed ne '2'
 	&& &is_portfolio_url($uri)) {
-	$thisallowed = &portfolio_access($uri);
+	$thisallowed = &portfolio_access($uri,$clientip);
     }
 
 # Full access at system, domain or course-wide level? Exit.


More information about the LON-CAPA-cvs mailing list