Diff for /loncom/auth/lonacc.pm between versions 1.159.2.21.2.4 and 1.169

version 1.159.2.21.2.4, 2023/01/23 00:32:03 version 1.169, 2018/01/12 13:33:46
Line 102  use Apache::loncommon(); Line 102  use Apache::loncommon();
 use Apache::lonlocal;  use Apache::lonlocal;
 use Apache::restrictedaccess();  use Apache::restrictedaccess();
 use Apache::blockedaccess();  use Apache::blockedaccess();
 use Apache::lonprotected();  
 use Fcntl qw(:flock);  use Fcntl qw(:flock);
 use LONCAPA qw(:DEFAULT :match);  use LONCAPA qw(:DEFAULT :match);
   
Line 160  sub get_posted_cgi { Line 159  sub get_posted_cgi {
                         if (length($value) == 1) {                          if (length($value) == 1) {
                             $value=~s/[\r\n]$//;                              $value=~s/[\r\n]$//;
                         }                          }
                     }                      } elsif ($fname =~ /\.(xls|doc|ppt)(x|m)$/i) {
                     if ($fname =~ /\.(xls|doc|ppt)(x|m)$/i) {  
                         $value=~s/[\r\n]$//;                          $value=~s/[\r\n]$//;
                     }                      }
                     if (ref($fields) eq 'ARRAY') {                      if (ref($fields) eq 'ARRAY') {
Line 204  sub get_posted_cgi { Line 202  sub get_posted_cgi {
  $fname='';   $fname='';
  $fmime='';   $fmime='';
     }      }
                       if ($i<$#lines && $lines[$i+1]=~/^Content\-Type\:\s*([\w\-\/]+)/i) {
                           # TODO: something with $1 !
                           $i++;
                       }
                       if ($i<$#lines && $lines[$i+1]=~/^Content\-transfer\-encoding\:\s*([\w\-\/]+)/i) {
                           # TODO: something with $1 !
                           $i++;
                       }
     $i++;      $i++;
  }   }
     } else {      } else {
Line 273  sub upload_size_allowed { Line 279  sub upload_size_allowed {
         be identified by the third arg ($usename), except when lonacc is called in           be identified by the third arg ($usename), except when lonacc is called in 
         an internal redirect to /adm/switchserver (e.g., load-balancing following          an internal redirect to /adm/switchserver (e.g., load-balancing following
         successful authentication) -- no cookie set yet.  For that particular case          successful authentication) -- no cookie set yet.  For that particular case
         simply skip the call to sso_login().          simply skip the call to sso_login(). 
   
  returns OK if it was SSO and user was handled.   returns OK if it was SSO and user was handled.
         returns undef if not SSO or no means to handle the user.          returns undef if not SSO or no means to handle the user.
   
         In the case where the session was started from /adm/launch/tiny/$domain/$id,  
         i.e., for a protected link, with launch from another CMS, and user information  
         is accepted from the LTI payload, then, if the user has privileged roles,  
         authentication will be required.  If SSO authentication is with a username  
         and/or domain that differ from the username in the LTI payload and domain  
         in the launch URL, then $r->user() will be unset and /adm/relaunch will be  
         called.  
                   
 =cut  =cut
   
 sub sso_login {  sub sso_login {
     my ($r,$handle,$username) = @_;      my ($r,$handle,$username) = @_;
   
       my $lonidsdir=$r->dir_config('lonIDsDir');
     if (($r->user eq '') || ($username ne '') || ($r->user eq 'public:public') ||      if (($r->user eq '') || ($username ne '') || ($r->user eq 'public:public') ||
         (defined($env{'user.name'}) && (defined($env{'user.domain'}))          (defined($env{'user.name'}) && (defined($env{'user.domain'}))
   && ($handle ne ''))) {    && ($handle ne ''))) {
Line 306  sub sso_login { Line 305  sub sso_login {
     my $query = $r->args;      my $query = $r->args;
     my %form;      my %form;
     if ($query) {      if ($query) {
           my @items = ('role','symb','iptoken');
         my @items = ('role','symb','iptoken','origurl','ttoken',  
                      'ltoken','linkkey','logtoken','sso','lcssowin');  
         &Apache::loncommon::get_unprocessed_cgi($query,\@items);          &Apache::loncommon::get_unprocessed_cgi($query,\@items);
         foreach my $item (@items) {          foreach my $item (@items) {
             if (defined($env{'form.'.$item})) {              if (defined($env{'form.'.$item})) {
Line 326  sub sso_login { Line 323  sub sso_login {
         }          }
     }      }
   
     my ($linkprot,$linkprotuser,$linkprotexit,$linkkey,$deeplinkurl);  
   
 #  
 # If Shibboleth auth is in use, and a dual SSO and non-SSO login page  
 # is in use, then the query string will contain the logtoken item with  
 # a value set to the name of a .tmp file in /home/httpd/perl/tmp  
 # containing the url to display after authentication, and also,  
 # optionally, role and symb, or linkprot or linkkey (deep-link access).  
 #  
 # If Shibboleth auth is in use, but a dual log-in page is not in use,  
 # and the originally requested URL was /tiny/$domain/$id (i.e.,  
 # for deeplinking), then the query string will contain the sso item  
 # with a value set to the name of a .tmp file in /home/httpd/perl/tmp  
 # containing the url to display after authentication, and also,  
 # optionally, linkprot or linkkey (deep-link access).  
 #  
 # Otherwise the query string may contain role and symb, or if the  
 # originally requested URL was /tiny/$domain/$id (i.e. for deeplinking)  
 # then the query string may contain a ttoken item with a value set  
 # to the name of a .tmp file in /home/httpd/perl/tmp containing either  
 # linkprot or linkkey (deep-link access).  
 #  
 # If deep-linked, i.e., the originally requested URL was /tiny/$domain/$id  
 # the linkkey may have originally been sent in POSTed data, which will  
 # have been processed in lontrans.pm  
 #  
   
     if ($form{'ttoken'}) {  
         my %info = &Apache::lonnet::tmpget($form{'ttoken'});  
         &Apache::lonnet::tmpdel($form{'ttoken'});  
         if ($info{'origurl'}) {  
             $form{'origurl'} = $info{'origurl'};  
             if ($form{'origurl'} =~ m{^/tiny/$match_domain/\w+$}) {  
                 $deeplinkurl = $form{'origurl'};  
             }  
         }  
         if ($info{'linkprot'}) {  
             $linkprot = $info{'linkprot'};  
             $linkprotuser = $info{'linkprotuser'};  
             $linkprotexit = $info{'linkprotexit'};  
         } elsif ($info{'linkkey'} ne '') {  
             $linkkey = $info{'linkkey'};  
         }  
     } elsif ($form{'logtoken'}) {  
         my ($firsturl,@rest);  
         my $lonhost = $r->dir_config('lonHostID');  
         my $tmpinfo = &Apache::lonnet::reply('tmpget:'.$form{'logtoken'},$lonhost);  
         my $delete = &Apache::lonnet::tmpdel($form{'logtoken'});  
         unless (($tmpinfo=~/^error/) || ($tmpinfo eq 'con_lost') ||  
                 ($tmpinfo eq 'no_such_host')) {  
             (undef,$firsturl,@rest) = split(/&/,$tmpinfo);  
             if ($firsturl ne '') {  
                 $firsturl = &unescape($firsturl);  
             }  
             foreach my $item (@rest) {  
                 my ($key,$value) = split(/=/,$item);  
                 $form{$key} = &unescape($value);  
             }  
             if ($firsturl =~ m{^/tiny/$match_domain/\w+$}) {  
                 $form{'origurl'} = $firsturl;  
                 $deeplinkurl = $firsturl;  
             } elsif ($firsturl eq '/adm/email') {  
                 $form{'origurl'} = $firsturl;  
             }  
             if ($form{'linkprot'}) {  
                 $linkprot = $form{'linkprot'};  
                 $linkprotuser = $form{'linkprotuser'};  
                 $linkprotexit = $form{'linkprotexit'};  
             } elsif ($form{'linkkey'} ne '') {  
                 $linkkey = $form{'linkkey'};  
             }  
             if ($form{'iptoken'}) {  
                 %sessiondata = &Apache::lonnet::tmpget($form{'iptoken'});  
                 my $delete = &Apache::lonnet::tmpdel($form{'iptoken'});  
             }  
         }  
     } elsif ($form{'sso'}) {  
         my $lonhost = $r->dir_config('lonHostID');  
         my $info = &Apache::lonnet::reply('tmpget:'.$form{'sso'},$lonhost);  
         &Apache::lonnet::tmpdel($form{'sso'});  
         unless (($info=~/^error/) || ($info eq 'con_lost') ||  
                 ($info eq 'no_such_host')) {  
             my ($firsturl,@rest)=split(/\&/,$info);  
             if ($firsturl ne '') {  
                 $form{'origurl'} = &unescape($firsturl);  
                 if ($form{'origurl'} =~ m{^/tiny/$match_domain/\w+$}) {  
                     $deeplinkurl = $form{'origurl'};  
                 }  
             }  
             foreach my $item (@rest) {  
                 my ($key,$value) = split(/=/,$item);  
                 $form{$key} = &unescape($value);  
             }  
             if ($form{'linkprot'}) {  
                 $linkprot = $form{'linkprot'};  
                 $linkprotuser = $form{'linkprotuser'};  
                 $linkprotexit = $form{'linkprotexit'};  
             } elsif ($form{'linkkey'} ne '') {  
                 $linkkey = $form{'linkkey'};  
             }  
         }  
     } elsif ($form{'ltoken'}) {  
         my %link_info = &Apache::lonnet::tmpget($form{'ltoken'});  
         $linkprot = $link_info{'linkprot'};  
         if ($linkprot) {  
             if ($link_info{'linkprotuser'} ne '') {  
                 $linkprotuser = $link_info{'linkprotuser'};  
             }  
             if ($link_info{'linkprotexit'} ne '') {  
                 $linkprotexit = $link_info{'linkprotexit'};  
             }  
         }  
         my $delete = &Apache::lonnet::tmpdel($form{'ltoken'});  
         delete($form{'ltoken'});  
         if ($form{'origurl'} =~ m{^/tiny/$match_domain/\w+$}) {  
             $deeplinkurl = $form{'origurl'};  
         }  
     } elsif ($form{'linkkey'} ne '') {  
         $linkkey = $form{'linkkey'};  
     }  
   
     my $domain = $r->dir_config('lonSSOUserDomain');      my $domain = $r->dir_config('lonSSOUserDomain');
     if ($domain eq '') {      if ($domain eq '') {
         $domain = $r->dir_config('lonDefDomain');          $domain = $r->dir_config('lonDefDomain');
     }      }
     if (($deeplinkurl) && ($linkprot) && ($linkprotuser ne '')) {  
         unless ($linkprotuser eq $user.':'.$domain) {  
             $r->user();  
             my %data = (  
                            origurl => $deeplinkurl,  
                            linkprot => $linkprot,  
                            linkprotuser => $linkprotuser,  
                            linkprotexit => $linkprotexit,  
                        );  
             if ($env{'form.lcssowin'}) {  
                 $data{'lcssowin'} = $env{'form.lcssowin'};  
             }  
             my $token = &Apache::lonnet::tmpput(\%data,$r->dir_config('lonHostID'),'link');  
             unless (($token eq 'con_lost') || ($token eq 'refused') || ($token =~ /^error:/) ||  
                     ($token eq 'unknown_cmd') || ($token eq 'no_such_host')) {  
                 $r->internal_redirect('/adm/relaunch?rtoken='.$token);  
                 $r->set_handlers('PerlHandler'=> undef);  
                 return OK;  
             }  
         }  
     }  
     my $home=&Apache::lonnet::homeserver($user,$domain);      my $home=&Apache::lonnet::homeserver($user,$domain);
     if ($home !~ /(con_lost|no_host|no_such_host)/) {      if ($home !~ /(con_lost|no_host|no_such_host)/) {
  &Apache::lonnet::logthis(" SSO authorized user $user ");   &Apache::lonnet::logthis(" SSO authorized user $user ");
Line 486  sub sso_login { Line 341  sub sso_login {
             ($is_balancer,$otherserver) =              ($is_balancer,$otherserver) =
                 &Apache::lonnet::check_loadbalancing($user,$domain,'login');                  &Apache::lonnet::check_loadbalancing($user,$domain,'login');
             if ($is_balancer) {              if ($is_balancer) {
                 # Check if browser sent a LON-CAPA load balancer cookie (and this is a balancer)                  if ($otherserver eq '') {
                 my ($found_server,$balancer_cookie) = &Apache::lonnet::check_for_balancer_cookie($r);  
                 if (($found_server) && ($balancer_cookie =~ /^\Q$domain\E_\Q$user\E_/)) {  
                     $otherserver = $found_server;  
                 } elsif ($otherserver eq '') {  
                     my $lowest_load;                      my $lowest_load;
                     ($otherserver,undef,undef,undef,$lowest_load) = &Apache::lonnet::choose_server($domain);                      ($otherserver,undef,undef,undef,$lowest_load) = &Apache::lonnet::choose_server($domain);
                     if ($lowest_load > 100) {                      if ($lowest_load > 100) {
                         $otherserver = &Apache::lonnet::spareserver($r,$lowest_load,$lowest_load,1,$domain);                          $otherserver = &Apache::lonnet::spareserver($lowest_load,$lowest_load,1,$domain);
                     }                      }
                     if ($otherserver ne '') {                  }
                         my @hosts = &Apache::lonnet::current_machine_ids();                  if ($otherserver ne '') {
                         if (grep(/^\Q$otherserver\E$/,@hosts)) {                      my @hosts = &Apache::lonnet::current_machine_ids();
                             $hosthere = $otherserver;                      if (grep(/^\Q$otherserver\E$/,@hosts)) {
                         }                          $hosthere = $otherserver;
                     }                      }
                 }                  }
             }              }
Line 509  sub sso_login { Line 360  sub sso_login {
     # login but immediately go to switch server to find us a new       # login but immediately go to switch server to find us a new 
     # machine      # machine
     &Apache::lonauth::success($r,$user,$domain,$home,'noredirect');      &Apache::lonauth::success($r,$user,$domain,$home,'noredirect');
             foreach my $item (keys(%form)) {  
                 $env{'form.'.$item} = $form{$item};  
             }  
             unless (($form{'symb'}) || ($form{'origurl'})) {  
                 unless (($r->uri eq '/adm/roles') || ($r->uri eq '/adm/sso')) {  
                     $env{'form.origurl'} = $r->uri;  
                 }  
             }  
             if (($r->uri eq '/adm/sso') && ($form{'origurl'} =~ m{^/+tiny/+$match_domain/+\w+$})) {  
                 $env{'request.deeplink.login'} = $form{'origurl'};  
             } elsif ($r->uri =~ m{^/+tiny/+$match_domain/+\w+$}) {  
                 $env{'request.deeplink.login'} = $r->uri;  
             }  
             if ($env{'request.deeplink.login'}) {  
                 if ($linkprot) {  
                     $env{'request.linkprot'} = $linkprot;  
                     if ($linkprotuser ne '') {  
                         $env{'request.linkprotuser'} = $linkprotuser;  
                     }  
                     if ($linkprotexit ne '') {  
                         $env{'request.linkprotexit'} = $linkprotexit;  
                     }  
                 } elsif ($linkkey ne '') {  
                     $env{'request.linkkey'} = $linkkey;  
                 }  
             }  
             if (($r->uri eq '/adm/sso') && ($form{'origurl'} eq '/adm/email')) {  
                 if ($form{'display'} && ($env{'form.mailrecip'} eq $user.':'.$domain)) {  
                     $env{'request.display'} = $form{'display'};  
                     $env{'request.mailrecip'} = $env{'form.mailrecip'};  
                 }  
             }  
             $env{'request.sso.login'} = 1;              $env{'request.sso.login'} = 1;
             if (defined($r->dir_config("lonSSOReloginServer"))) {              if (defined($r->dir_config("lonSSOReloginServer"))) {
                 $env{'request.sso.reloginserver'} =                  $env{'request.sso.reloginserver'} =
Line 550  sub sso_login { Line 369  sub sso_login {
             if ($otherserver ne '') {              if ($otherserver ne '') {
                 $redirecturl .= '?otherserver='.$otherserver;                  $redirecturl .= '?otherserver='.$otherserver;
             }              }
             if ($form{'lcssowin'}) {  
                 $redirecturl .= (($redirecturl=~/\?/)?'&':'?') . 'lcssowin=1';  
             }  
     $r->internal_redirect($redirecturl);      $r->internal_redirect($redirecturl);
     $r->set_handlers('PerlHandler'=> undef);      $r->set_handlers('PerlHandler'=> undef);
  } else {   } else {
     # need to login them in, so generate the need data that      # need to login them in, so generate the need data that
     # migrate expects to do login      # migrate expects to do login
             my $ip = &Apache::lonnet::get_requestor_ip($r);      my $ip = $r->get_remote_host();
     my %info=('ip'        => $ip,      my %info=('ip'        => $ip,
       'domain'    => $domain,        'domain'    => $domain,
       'username'  => $user,        'username'  => $user,
       'server'    => $r->dir_config('lonHostID'),        'server'    => $r->dir_config('lonHostID'),
       'sso.login' => 1        'sso.login' => 1
       );        );
             foreach my $item ('role','symb','iptoken','origurl','lcssowin') {              foreach my $item ('role','symb','iptoken') {
                 if (exists($form{$item})) {                  if (exists($form{$item})) {
                     $info{$item} = $form{$item};                      $info{$item} = $form{$item};
                 } elsif ($sessiondata{$item} ne '') {  
                     $info{$item} = $sessiondata{$item};  
                 }                  }
             }              }
             unless (($info{'symb'}) || ($info{'origurl'})) {              unless ($info{'symb'}) {
                 unless (($r->uri eq '/adm/roles') || ($r->uri eq '/adm/sso')) {                  unless (($r->uri eq '/adm/roles') || ($r->uri eq '/adm/sso')) {
                     $info{'origurl'} = $r->uri;                       $info{'origurl'} = $r->uri; 
                 }                  }
             }              }
             if (($r->uri eq '/adm/sso') && ($form{'origurl'} =~ m{^/+tiny/+$match_domain/+\w+$})) {  
                 $info{'deeplink.login'} = $form{'origurl'};  
             } elsif ($r->uri =~ m{^/+tiny/+$match_domain/+\w+$}) {  
                 $info{'deeplink.login'} = $r->uri;  
             }  
             if ($info{'deeplink.login'}) {  
                 if ($linkprot) {  
                     $info{'linkprot'} = $linkprot;  
                     if ($linkprotuser ne '') {  
                         $info{'linkprotuser'} = $linkprotuser;  
                     }  
                     if ($linkprotexit ne '') {  
                         $info{'linkprotexit'} = $linkprotexit;  
                     }  
                 } elsif ($linkkey ne '') {  
                     $info{'linkkey'} = $linkkey;  
                 }  
             }  
             if (($r->uri eq '/adm/sso') && ($form{'origurl'} eq '/adm/email')) {  
                 if ($form{'display'} && ($form{'mailrecip'} eq $user.':'.$domain)) {  
                     $info{'display'} = &escape($form{'display'});  
                     $info{'mailrecip'} = &escape($form{'mailrecip'});  
                 }  
             }  
             if ($r->dir_config("ssodirecturl") == 1) {              if ($r->dir_config("ssodirecturl") == 1) {
                 $info{'origurl'} = $r->uri;                  $info{'origurl'} = $r->uri;
             }              }
Line 611  sub sso_login { Line 401  sub sso_login {
             if (($is_balancer) && ($hosthere)) {              if (($is_balancer) && ($hosthere)) {
                 $info{'noloadbalance'} = $hosthere;                  $info{'noloadbalance'} = $hosthere;
             }              }
     my $token = &Apache::lonnet::tmpput(\%info,$r->dir_config('lonHostID'),'sso');      my $token = 
    &Apache::lonnet::tmpput(\%info,
    $r->dir_config('lonHostID'));
     $env{'form.token'} = $token;      $env{'form.token'} = $token;
     $r->internal_redirect('/adm/migrateuser');      $r->internal_redirect('/adm/migrateuser');
     $r->set_handlers('PerlHandler'=> undef);      $r->set_handlers('PerlHandler'=> undef);
Line 636  sub sso_login { Line 428  sub sso_login {
             $r->subprocess_env->set('SSOUserUnknown' => $user);              $r->subprocess_env->set('SSOUserUnknown' => $user);
             $r->subprocess_env->set('SSOUserDomain' => $domain);              $r->subprocess_env->set('SSOUserDomain' => $domain);
             if (grep(/^sso$/,@cancreate)) {              if (grep(/^sso$/,@cancreate)) {
 #FIXME - need to preserve origurl, role and symb, or linkprot or linkkey for use after account  
 # creation. If lcssowin is 1, createaccount needs to close pop-up and display in main window.  
                 $r->set_handlers('PerlHandler'=> [\&Apache::createaccount::handler]);                  $r->set_handlers('PerlHandler'=> [\&Apache::createaccount::handler]);
                 $r->handler('perl-script');                  $r->handler('perl-script');
             } else {              } else {
Line 677  sub handler { Line 467  sub handler {
     if ($handle eq '') {      if ($handle eq '') {
         unless ((($requrl eq '/adm/switchserver') && (!$r->is_initial_req())) ||          unless ((($requrl eq '/adm/switchserver') && (!$r->is_initial_req())) ||
                 ($requrl =~ m{^/public/$match_domain/$match_courseid/syllabus}) ||                  ($requrl =~ m{^/public/$match_domain/$match_courseid/syllabus}) ||
                 ($requrl =~ m{^/adm/help/}) || ($requrl eq '/adm/sso') ||                  ($requrl =~ m{^/adm/help/}) ||
                 ($requrl =~ m{^/res/$match_domain/$match_username/})) {                  ($requrl =~ m{^/res/$match_domain/$match_username/})) {
     $r->log_reason("Cookie not valid", $r->filename);      $r->log_reason("Cookie not valid", $r->filename);
         }          }
Line 716  sub handler { Line 506  sub handler {
                 my $preserved;                  my $preserved;
                 foreach my $pair (split(/&/,$query)) {                  foreach my $pair (split(/&/,$query)) {
                     my ($name, $value) = split(/=/,$pair);                      my ($name, $value) = split(/=/,$pair);
                     unless (($name eq 'symb') || ($name eq 'usehttp')) {                      unless ($name eq 'symb') {
                         $preserved .= $pair.'&';                          $preserved .= $pair.'&';
                     }                      }
                     if (($env{'request.course.id'}) && ($name eq 'folderpath')) {                      if (($env{'request.course.id'}) && ($name eq 'folderpath')) {
Line 735  sub handler { Line 525  sub handler {
             }              }
         } elsif ($env{'request.course.id'} &&          } elsif ($env{'request.course.id'} &&
                  (($requrl =~ m{^/adm/$match_domain/$match_username/aboutme$}) ||                   (($requrl =~ m{^/adm/$match_domain/$match_username/aboutme$}) ||
                   ($requrl =~ m{^/public/$cdom/$cnum/syllabus$}))) {                    ($requrl eq "/public/$cdom/$cnum/syllabus") ||
                     ($requrl =~ m{^/adm/$cdom/$cnum/\d+/ext\.tool$}))) {
             my $query = $r->args;              my $query = $r->args;
             if ($query) {              if ($query) {
                 foreach my $pair (split(/&/,$query)) {                  foreach my $pair (split(/&/,$query)) {
Line 744  sub handler { Line 535  sub handler {
                         if ($value =~ /^supplemental/) {                          if ($value =~ /^supplemental/) {
                             $suppext = 1;                              $suppext = 1;
                         }                          }
                         last;  
                     }                      }
                 }                  }
             }              }
Line 756  sub handler { Line 546  sub handler {
             my $hostname = $r->hostname();              my $hostname = $r->hostname();
             my $lonhost = &Apache::lonnet::host_from_dns($hostname);              my $lonhost = &Apache::lonnet::host_from_dns($hostname);
             if ($lonhost) {              if ($lonhost) {
                 my $actual = &Apache::lonnet::absolute_url($hostname,1,1);                  my $actual = &Apache::lonnet::absolute_url($hostname);
                 my $expected = $Apache::lonnet::protocol{$lonhost}.'://'.$hostname;                  my $expected = $Apache::lonnet::protocol{$lonhost}.'://'.$hostname;
                 unless ($actual eq $expected) {                  unless ($actual eq $expected) {
                     $env{'request.use_absolute'} = $expected;                      $env{'request.use_absolute'} = $expected;
Line 772  sub handler { Line 562  sub handler {
         my $checkexempt;          my $checkexempt;
         if ($env{'user.loadbalexempt'} eq $r->dir_config('lonHostID')) {          if ($env{'user.loadbalexempt'} eq $r->dir_config('lonHostID')) {
             if ($env{'user.loadbalcheck.time'} + 600 > time) {              if ($env{'user.loadbalcheck.time'} + 600 > time) {
                 $checkexempt = 1;                  $checkexempt = 1;    
             }              }
         }          }
         if ($env{'user.noloadbalance'} eq $r->dir_config('lonHostID')) {          if ($env{'user.noloadbalance'} eq $r->dir_config('lonHostID')) {
             $checkexempt = 1;              $checkexempt = 1;
         }          }
         unless (($checkexempt) || (($requrl eq '/adm/switchserver') && (!$r->is_initial_req()))) {          unless ($checkexempt) {
             ($is_balancer,$otherserver) =              ($is_balancer,$otherserver) =
                 &Apache::lonnet::check_loadbalancing($env{'user.name'},                  &Apache::lonnet::check_loadbalancing($env{'user.name'},
                                                      $env{'user.domain'});                                                       $env{'user.domain'});
             if ($is_balancer) {  
                 # Check if browser sent a LON-CAPA load balancer cookie (and this is a balancer)  
                 my ($found_server,$balancer_cookie) = &Apache::lonnet::check_for_balancer_cookie($r);  
                 if (($found_server) && ($balancer_cookie =~ /^\Q$env{'user.domain'}\E_\Q$env{'user.name'}\E_/)) {  
                     $otherserver = $found_server;  
                 }  
                 unless ($requrl eq '/adm/switchserver') {  
                     $r->set_handlers('PerlResponseHandler'=>  
                                      [\&Apache::switchserver::handler]);  
                 }  
                 if ($otherserver ne '') {  
                     $env{'form.otherserver'} = $otherserver;  
                 }  
                 unless (($env{'form.origurl'}) || ($r->uri eq '/adm/roles') ||  
                         ($r->uri eq '/adm/switchserver') || ($r->uri eq '/adm/sso')) {  
                     $env{'form.origurl'} = $r->uri;  
                 }  
             }  
         }          }
         if ($requrl=~m{^/+tiny/+$match_domain/+\w+$}) {          if ($is_balancer) {
             if ($r->args) {              $r->set_handlers('PerlResponseHandler'=>
                 &Apache::loncommon::get_unprocessed_cgi($r->args,['ttoken']);                               [\&Apache::switchserver::handler]);
                 if (defined($env{'form.ttoken'})) {              if ($otherserver ne '') {
                     my %info = &Apache::lonnet::tmpget($env{'form.ttoken'});                  $env{'form.otherserver'} = $otherserver;
                     if (($info{'origurl'} ne '') && ($info{'origurl'} eq $requrl)) {  
                         my %data;  
                         if (($info{'linkprotuser'} ne '') && ($info{'linkprot'}) &&  
                             ($info{'linkprotuser'} ne $env{'user.name'}.':'.$env{'user.domain'})) {  
                             %data = (  
                                 origurl => $requrl,  
                                 linkprot => $info{'linkprot'},  
                                 linkprotuser => $info{'linkprotuser'},  
                                 linkprotexit => $info{'linkprotexit'},  
                             );  
                         } elsif ($info{'ltoken'} ne '') {  
                             my %ltoken_info = &Apache::lonnet::tmpget($info{'ltoken'});  
                             if (($ltoken_info{'linkprotuser'} ne '') && ($ltoken_info{'linkprot'}) &&  
                                 ($ltoken_info{'linkprotuser'} ne $env{'user.name'}.':'.$env{'user.domain'})) {  
                                 %data = (  
                                     origurl => $requrl,  
                                     linkprot => $ltoken_info{'linkprot'},  
                                     linkprotuser => $ltoken_info{'linkprotuser'},  
                                     linkprotexit => $ltoken_info{'linkprotexit'},  
                                 );  
                             }  
                         }  
                         if (keys(%data)) {  
                             my $delete = &Apache::lonnet::tmpdel($env{'form.ttoken'});  
                             if ($info{'ltoken'} ne '') {  
                                 my $delete = &Apache::lonnet::tmpdel($info{'ltoken'});  
                             }  
                             my $token =  
                                 &Apache::lonnet::tmpput(\%data,$r->dir_config('lonHostID'),'retry');  
                             unless (($token eq 'con_lost') || ($token eq 'refused') || ($token =~ /^error:/) ||  
                                     ($token eq 'unknown_cmd') || ($token eq 'no_such_host')) {  
                                 $r->internal_redirect('/adm/relaunch?rtoken='.$token);  
                                 $r->set_handlers('PerlHandler'=> undef);  
                                 return OK;  
                             }  
                         }  
                     }  
                 }  
             }              }
             if ($env{'user.name'} eq 'public' &&              unless (($env{'form.origurl'}) || ($r->uri eq '/adm/roles') ||
                 $env{'user.domain'} eq 'public') {                      ($r->uri eq '/adm/switchserver') || ($r->uri eq '/adm/sso')) {
                 $env{'request.firsturl'}=$requrl;                  $env{'form.origurl'} = $r->uri;
                 return FORBIDDEN;  
             }              }
           }
           if ($requrl=~m{^/+tiny/+$match_domain/+\w+$}) {
             return OK;              return OK;
         }          }
 # ---------------------------------------------------------------- Check access  # ---------------------------------------------------------------- Check access
  my $now = time;   my $now = time;
         my ($check_symb,$check_access,$check_block,$access,$poss_symb);   if ($requrl !~ m{^/(?:adm|public|prtspool)/}
  if ($requrl !~ m{^/(?:adm|public|(?:prt|zip)spool)/}  
     || $requrl =~ /^\/adm\/.*\/(smppg|bulletinboard)(\?|$ )/x) {      || $requrl =~ /^\/adm\/.*\/(smppg|bulletinboard)(\?|$ )/x) {
             $check_access = 1;      my $access=&Apache::lonnet::allowed('bre',$requrl);
         }  
         if ((!$check_access) && ($env{'request.course.id'})) {  
             if (($requrl eq '/adm/viewclasslist') ||  
                 ($requrl =~ m{^(/adm/wrapper|)\Q/uploaded/$cdom/$cnum/docs/\E}) ||  
                 ($requrl =~ m{^/adm/.*/aboutme$}) ||  
                 ($requrl=~m{^/adm/coursedocs/showdoc/}) ||  
                 ($requrl=~m{^(/adm/wrapper|)/adm/$cdom/$cnum/\d+/ext\.tool$})) {  
                 $check_block = 1;  
             }  
         }  
         if (($env{'request.course.id'}) && (!$suppext)) {  
             $requrl=~/\.(\w+)$/;  
             if ((&Apache::loncommon::fileembstyle($1) eq 'ssi') ||  
                 ($requrl=~/^\/adm\/.*\/(aboutme|smppg|bulletinboard)(\?|$ )/x) ||  
                 ($requrl=~/^\/adm\/wrapper\//) ||  
                 ($requrl=~m|^/adm/coursedocs/showdoc/|) ||  
                 ($requrl=~m|\.problem/smpedit$|) ||  
                 ($requrl=~/^\/public\/.*\/syllabus$/) ||  
                 ($requrl=~/^\/adm\/(viewclasslist|navmaps)$/) ||  
                 ($requrl=~/^\/adm\/.*\/aboutme\/portfolio(\?|$)/) ||  
                 ($requrl=~m{^/adm/$cdom/$cnum/\d+/ext\.tool$})) {  
                 $check_symb = 1;  
             }  
         }  
         if (($check_access) || ($check_block)) {  
             if ($check_symb) {  
                 if ($env{'form.symb'}) {  
                     $poss_symb=&Apache::lonnet::symbclean($env{'form.symb'});  
                 } elsif (($env{'request.course.id'}) && ($r->args ne '')) {  
                     my $query = $r->args;  
                     foreach my $pair (split(/&/,$query)) {  
                         my ($name, $value) = split(/=/,$pair);  
                         $name = &unescape($name);  
                         $value =~ tr/+/ /;  
                         $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;  
                         if ($name eq 'symb') {  
                             $poss_symb = &Apache::lonnet::symbclean($value);  
                             last;  
                         }  
                     }  
                 }  
                 if ($poss_symb) {  
                     my ($possmap,$resid,$url)=&Apache::lonnet::decode_symb($poss_symb);  
                     $url = &Apache::lonnet::clutter($url);  
                     my $toplevelmap = $env{'course.'.$env{'request.course.id'}.'.url'};  
                     unless (($url eq $requrl) && (($possmap eq $toplevelmap) ||  
                                                   (&Apache::lonnet::is_on_map($possmap)))) {  
                         undef($poss_symb);  
                     }  
                     if ($poss_symb) {  
                         if ((!$env{'request.role.adv'}) && ($env{'acc.randomout'}) &&  
                             ($env{'acc.randomout'}=~/\&\Q$poss_symb\E\&/)) {  
                             undef($poss_symb);  
                         } elsif ((!$env{'request.role.adv'}) && ($env{'acc.deeplinkout'}) &&  
                                  ($env{'acc.deeplinkout'}=~/\&\Q$poss_symb\E\&/)) {  
                             undef($poss_symb);  
                         }  
                     }  
                 }  
                 if ($poss_symb) {  
                     $access=&Apache::lonnet::allowed('bre',$requrl,$poss_symb);  
                 } else {  
                     $access=&Apache::lonnet::allowed('bre',$requrl,'','','','',1);  
                 }  
             } else {  
                 my $nodeeplinkcheck;  
                 if (($check_access) && ($requrl =~ /\.(sequence|page)$/)) {  
                     unless ($env{'form.navmap'}) {  
                         if ($r->args ne '') {  
                             &Apache::loncommon::get_unprocessed_cgi($r->args,['navmap']);  
                             unless ($env{'form.navmap'}) {  
                                 $nodeeplinkcheck = 1;  
                             }  
                         }  
                     }  
                 }  
                 my $clientip = &Apache::lonnet::get_requestor_ip($r);  
                 $access=&Apache::lonnet::allowed('bre',$requrl,'','',$clientip,'','',$nodeeplinkcheck);  
             }  
         }  
         if ($check_block) {  
             if ($access eq 'B') {  
                 if ($poss_symb) {  
                     if (&Apache::lonnet::symbverify($poss_symb,$requrl)) {  
                         $env{'request.symb'} = $poss_symb;  
                     }  
                 }  
                 &Apache::blockedaccess::setup_handler($r);  
                 return OK;  
             }  
         } elsif ($check_access) {   
             if ($handle eq '') {              if ($handle eq '') {
                 unless ($access eq 'F') {                  unless ($access eq 'F') {
                     if ($requrl =~ m{^/res/$match_domain/$match_username/}) {                      if ($requrl =~ m{^/res/$match_domain/$match_username/}) {
Line 965  sub handler { Line 608  sub handler {
  return OK;   return OK;
     }      }
             if ($access eq 'B') {              if ($access eq 'B') {
                 if ($poss_symb) {  
                     if (&Apache::lonnet::symbverify($poss_symb,$requrl)) {  
                         $env{'request.symb'} = $poss_symb;  
                     }  
                 }  
                 &Apache::blockedaccess::setup_handler($r);                  &Apache::blockedaccess::setup_handler($r);
                 return OK;                  return OK;
             }              }
             if ($access eq 'D') {  
                 &Apache::lonprotected::setup_handler($r);  
                 return OK;  
             }  
     if (($access ne '2') && ($access ne 'F')) {      if (($access ne '2') && ($access ne 'F')) {
                 if ($requrl =~ m{^/res/}) {                  if ($requrl =~ m{^/res/}) {
                     $access = &Apache::lonnet::allowed('bro',$requrl);                      $access = &Apache::lonnet::allowed('bro',$requrl);
Line 993  sub handler { Line 627  sub handler {
                         }                          }
                     }                      }
                 } elsif (($handle =~ /^publicuser_\d+$/) && (&Apache::lonnet::is_portfolio_url($requrl))) {                  } elsif (($handle =~ /^publicuser_\d+$/) && (&Apache::lonnet::is_portfolio_url($requrl))) {
                     my $clientip = &Apache::lonnet::get_requestor_ip($r);                      my $clientip = $r->get_remote_host();
                     if (&Apache::lonnet::allowed('bre',$requrl,undef,undef,$clientip) ne 'F') {                      if (&Apache::lonnet::allowed('bre',$requrl,undef,undef,$clientip) ne 'F') {
                         $env{'user.error.msg'}="$requrl:bre:1:1:Access Denied";                          $env{'user.error.msg'}="$requrl:bre:1:1:Access Denied";
                         return HTTP_NOT_ACCEPTABLE;                          return HTTP_NOT_ACCEPTABLE;
Line 1024  sub handler { Line 658  sub handler {
     $env{'user.domain'} eq 'public' &&      $env{'user.domain'} eq 'public' &&
     $requrl !~ m{^/+(res|public|uploaded)/} &&      $requrl !~ m{^/+(res|public|uploaded)/} &&
     $requrl !~ m{^/adm/[^/]+/[^/]+/aboutme/portfolio$ }x &&      $requrl !~ m{^/adm/[^/]+/[^/]+/aboutme/portfolio$ }x &&
             $requrl !~ m{^/adm/blockingstatus/.*$} &&          $requrl !~ m{^/adm/blockingstatus/.*$} &&
     $requrl !~ m{^/+adm/(help|logout|restrictedaccess|randomlabel\.png)}) {      $requrl !~ m{^/+adm/(help|logout|restrictedaccess|randomlabel\.png)}) {
     $env{'request.querystring'}=$r->args;      $env{'request.querystring'}=$r->args;
     $env{'request.firsturl'}=$requrl;      $env{'request.firsturl'}=$requrl;
Line 1033  sub handler { Line 667  sub handler {
 # ------------------------------------------------------------- This is allowed  # ------------------------------------------------------------- This is allowed
  if ($env{'request.course.id'}) {   if ($env{'request.course.id'}) {
     &Apache::lonnet::countacc($requrl);      &Apache::lonnet::countacc($requrl);
       $requrl=~/\.(\w+)$/;
             my $query=$r->args;              my $query=$r->args;
             if ($check_symb) {      if ((&Apache::loncommon::fileembstyle($1) eq 'ssi') ||
    ($requrl=~/^\/adm\/.*\/(aboutme|smppg|bulletinboard)(\?|$ )/x) ||
    ($requrl=~/^\/adm\/wrapper\//) ||
    ($requrl=~m|^/adm/coursedocs/showdoc/|) ||
    ($requrl=~m|\.problem/smpedit$|) ||
    ($requrl=~/^\/public\/.*\/syllabus$/) ||
                   ($requrl=~/^\/adm\/(viewclasslist|navmaps)$/) ||
                   ($requrl=~/^\/adm\/.*\/aboutme\/portfolio(\?|$)/) ||
                   ($requrl=~m{^/adm/$cdom/$cnum/\d+/ext\.tool$})) {
 # ------------------------------------- This is serious stuff, get symb and log  # ------------------------------------- This is serious stuff, get symb and log
  my $symb;   my $symb;
  if ($query) {   if ($query) {
Line 1042  sub handler { Line 685  sub handler {
  }   }
  if ($env{'form.symb'}) {   if ($env{'form.symb'}) {
     $symb=&Apache::lonnet::symbclean($env{'form.symb'});      $symb=&Apache::lonnet::symbclean($env{'form.symb'});
                     if (($requrl eq '/adm/navmaps') ||      if ($requrl =~ m|^/adm/wrapper/|
                         ($requrl =~ m{^/adm/wrapper/}) ||   || $requrl =~ m|^/adm/coursedocs/showdoc/|) {
                         ($requrl =~ m{^/adm/coursedocs/showdoc/})) {   my ($map,$mid,$murl)=&Apache::lonnet::decode_symb($symb);
                         unless (&Apache::lonnet::symbverify($symb,$requrl)) {   &Apache::lonnet::symblist($map,$murl => [$murl,$mid],
                             if (&Apache::lonnet::is_on_map($requrl)) {    'last_known' =>[$murl,$mid]);
                                 $symb = &Apache::lonnet::symbread($requrl);  
                                 unless (&Apache::lonnet::symbverify($symb,$requrl)) {  
                                     undef($symb);  
                                 }  
                             }  
                         }  
                         if ($symb) {  
                             if ($requrl eq '/adm/navmaps') {  
                                 my ($map,$mid,$murl)=&Apache::lonnet::decode_symb($symb);  
                                 &Apache::lonnet::symblist($map,$murl => [$murl,$mid]);  
                             } elsif (($requrl =~ m{^/adm/wrapper/}) ||  
                                      ($requrl =~ m{^/adm/coursedocs/showdoc/})) {  
                                 my ($map,$mid,$murl)=&Apache::lonnet::decode_symb($symb);  
                                 if ($map =~ /\.page$/) {  
                                     my $mapsymb = &Apache::lonnet::symbread($map);  
                                     ($map,$mid,$murl)=&Apache::lonnet::decode_symb($mapsymb);  
                                 }  
                                 &Apache::lonnet::symblist($map,$murl => [$murl,$mid],  
                                                           'last_known' =>[$murl,$mid]);  
                             }  
                         }  
     } elsif ((&Apache::lonnet::symbverify($symb,$requrl)) ||      } elsif ((&Apache::lonnet::symbverify($symb,$requrl)) ||
      (($requrl=~m|(.*)/smpedit$|) &&       (($requrl=~m|(.*)/smpedit$|) &&
       &Apache::lonnet::symbverify($symb,$1)) ||        &Apache::lonnet::symbverify($symb,$1)) ||
                              (($requrl=~m|(.*/aboutme)/portfolio$|) &&                               (($requrl=~m|(.*/aboutme)/portfolio$|) &&
                               &Apache::lonnet::symbverify($symb,$1))) {                                &Apache::lonnet::symbverify($symb,$1))) {
  my ($map,$mid,$murl)=&Apache::lonnet::decode_symb($symb);   my ($map,$mid,$murl)=&Apache::lonnet::decode_symb($symb);
                         if (($map =~ /\.page$/) && ($requrl !~ /\.page$/)) {  
                             my $mapsymb = &Apache::lonnet::symbread($map);  
                             ($map,$mid,$murl)=&Apache::lonnet::decode_symb($mapsymb);  
                         }  
  &Apache::lonnet::symblist($map,$murl => [$murl,$mid],   &Apache::lonnet::symblist($map,$murl => [$murl,$mid],
   'last_known' =>[$murl,$mid]);    'last_known' =>[$murl,$mid]);
     } else {      } else {
Line 1091  sub handler { Line 709  sub handler {
                     if ($requrl=~m{^(/adm/.*/aboutme)/portfolio$}) {                      if ($requrl=~m{^(/adm/.*/aboutme)/portfolio$}) {
                         $requrl = $1;                          $requrl = $1;
                     }                      }
     $symb=&Apache::lonnet::symbread($requrl);                      unless ($suppext) {
                     if (&Apache::lonnet::is_on_map($requrl) && $symb) {          $symb=&Apache::lonnet::symbread($requrl);
                         my ($encstate,$invalidsymb);          if (&Apache::lonnet::is_on_map($requrl) && $symb &&
                         unless (&Apache::lonnet::symbverify($symb,$requrl,\$encstate)) {      !&Apache::lonnet::symbverify($symb,$requrl)) {
                             $invalidsymb = 1;      $r->log_reason('Invalid symb for '.$requrl.': '.$symb);
                             #      $env{'user.error.msg'}=
                             # If $env{'request.enc'} inconsistent with encryption expected for $symb          "$requrl:bre:1:1:Invalid Access";
                             # retrieved by lonnet::symbread(), call again to check for an instance of      return HTTP_NOT_ACCEPTABLE; 
                             # $requrl in the course for which expected encryption matches request.enc.          }
                             # If symb for different instance passes lonnet::symbverify(), use that as          if ($symb) {
                             # the symb for $requrl and call &Apache::lonnet::allowed() for that symb.      my ($map,$mid,$murl)=
                             # Report invalid symb if there is no other symb. Redirect to /adm/ambiguous          &Apache::lonnet::decode_symb($symb);
                             # if multiple possible symbs consistent with request.enc available for $requrl.      &Apache::lonnet::symblist($map,$murl =>[$murl,$mid],
                             #        'last_known' =>[$murl,$mid]);
                             if (($env{'request.enc'} && !$encstate) || (!$env{'request.enc'} && $encstate)) {          }
                                 my %possibles;  
                                 my $nocache = 1;  
                                 my $oldsymb = $symb;  
                                 $symb = &Apache::lonnet::symbread($requrl,'','','',\%possibles,$nocache);  
                                 if (($symb) && ($symb ne $oldsymb)) {  
                                     if (&Apache::lonnet::symbverify($symb,$requrl)) {  
                                         my $access=&Apache::lonnet::allowed('bre',$requrl,$symb);  
                                         if ($access eq 'B') {  
                                             $env{'request.symb'} = $symb;  
                                             &Apache::blockedaccess::setup_handler($r);  
                                             return OK;  
                                         } elsif (($access eq '2') || ($access eq 'F')) {  
                                             $invalidsymb = '';  
                                         }  
                                     }  
                                 } elsif (keys(%possibles) > 1) {  
                                     $r->internal_redirect('/adm/ambiguous');  
                                     return OK;  
                                 }  
                             }  
                             if ($invalidsymb) {  
                                 if ($requrl eq '/adm/navmaps') {  
                                     undef($symb);  
                                 } else {  
                                     $r->log_reason('Invalid symb for '.$requrl.': '.$symb);  
                                     $env{'user.error.msg'}=  
                                         "$requrl:bre:1:1:Invalid Access";  
                                     return HTTP_NOT_ACCEPTABLE;  
                                 }  
                             }  
                         }  
                     }  
     if ($symb) {  
  my ($map,$mid,$murl)=  
     &Apache::lonnet::decode_symb($symb);  
                         if ($requrl eq '/adm/navmaps') {  
                             &Apache::lonnet::symblist($map,$murl =>[$murl,$mid]);  
                         } else {  
                             if (($map =~ /\.page$/) && ($requrl !~ /\.page$/)) {  
                                 my $mapsymb = &Apache::lonnet::symbread($map);  
                                 ($map,$mid,$murl)=&Apache::lonnet::decode_symb($mapsymb);  
                             }  
                             &Apache::lonnet::symblist($map,$murl =>[$murl,$mid],  
                                                       'last_known' =>[$murl,$mid]);  
                         }  
     }      }
  }   }
  $env{'request.symb'}=$symb;   $env{'request.symb'}=$symb;
                 if (($env{'request.symbread.cached.'}) && ($env{'request.symbread.cached.'} ne $symb)) {  
                     $env{'request.symbread.cached.'} = $symb;  
                 }  
  &Apache::lonnet::courseacclog($symb);   &Apache::lonnet::courseacclog($symb);
     } else {      } else {
 # ------------------------------------------------------- This is other content  # ------------------------------------------------------- This is other content
Line 1201  sub handler { Line 771  sub handler {
     }      }
 # ------------------------------------ See if this is a viewable portfolio file  # ------------------------------------ See if this is a viewable portfolio file
     if (&Apache::lonnet::is_portfolio_url($requrl)) {      if (&Apache::lonnet::is_portfolio_url($requrl)) {
         my $clientip = &Apache::lonnet::get_requestor_ip($r);          my $clientip = $r->get_remote_host();
  my $access=&Apache::lonnet::allowed('bre',$requrl,undef,undef,$clientip);          my $access=&Apache::lonnet::allowed('bre',$requrl,undef,undef,$clientip);
  if ($access eq 'A') {   if ($access eq 'A') {
     &Apache::restrictedaccess::setup_handler($r);      &Apache::restrictedaccess::setup_handler($r);
     return OK;      return OK;

Removed from v.1.159.2.21.2.4  
changed lines
  Added in v.1.169


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