--- loncom/auth/lonacc.pm 2009/07/23 17:40:29 1.126 +++ loncom/auth/lonacc.pm 2013/12/13 02:10:27 1.149 @@ -1,7 +1,7 @@ # The LearningOnline Network # Cookie Based Access Handler # -# $Id: lonacc.pm,v 1.126 2009/07/23 17:40:29 raeburn Exp $ +# $Id: lonacc.pm,v 1.149 2013/12/13 02:10:27 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -89,8 +89,6 @@ store attempted access =head1 NOTABLE SUBROUTINES -=over - =cut @@ -103,9 +101,9 @@ use Apache::lonnet; use Apache::loncommon(); use Apache::lonlocal; use Apache::restrictedaccess(); -use Apache::blockedaccess(); +use Apache::blockedaccess(); use Fcntl qw(:flock); -use LONCAPA; +use LONCAPA qw(:DEFAULT :match); sub cleanup { my ($r)=@_; @@ -156,7 +154,13 @@ sub get_posted_cgi { for ($i=0;$i<=$#lines;$i++) { if ($lines[$i]=~/^--\Q$contentsep\E/) { if ($name) { - chomp($value); + chomp($value); + if (($r->uri eq '/adm/portfolio') && + ($name eq 'uploaddoc')) { + if (length($value) == 1) { + $value=~s/[\r\n]$//; + } + } if (ref($fields) eq 'ARRAY') { next if (!grep(/^\Q$name\E$/,@{$fields})); } @@ -224,6 +228,8 @@ sub get_posted_cgi { =pod +=over + =item upload_size_allowed() Perform size checks for file uploads to essayresponse items in course context. @@ -258,20 +264,23 @@ sub upload_size_allowed { =item sso_login() handle the case of the single sign on user, at this point $r->user - will be set and valid now need to find the loncapa user info and possibly - balance them - returns OK if it was a SSO and user was handled - undef if not SSO or no means to hanle the user + will be set and valid now need to find the loncapa user info, and possibly + balance them. If $r->user() is set this means either it was either set by + SSO or by checkauthen.pm if a valid cookie was found. The latter case can + be identified by the third arg ($usename). + + returns OK if it was SSO and user was handled. + returns undef if not SSO or no means to handle the user. =cut sub sso_login { - my ($r,$handle) = @_; + my ($r,$handle,$username) = @_; my $lonidsdir=$r->dir_config('lonIDsDir'); - if (!($r->user - && (!defined($env{'user.name'}) && !defined($env{'user.domain'})) - && ($handle eq ''))) { + if (($r->user eq '') || ($username ne '') || + (defined($env{'user.name'}) && (defined($env{'user.domain'})) + && ($handle ne ''))) { # not an SSO case or already logged in return undef; } @@ -281,36 +290,67 @@ sub sso_login { my $query = $r->args; my %form; if ($query) { - foreach my $pair (split(/&/,$query)) { - my ($name, $value) = split(/=/,$pair); - $name = &unescape($name); - if (($name eq 'role') || ($name eq 'symb')) { - $value =~ tr/+/ /; - $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; - $form{$name} = $value; + my @items = ('role','symb','iptoken'); + &Apache::loncommon::get_unprocessed_cgi($query,\@items); + foreach my $item (@items) { + if (defined($env{'form.'.$item})) { + $form{$item} = $env{'form.'.$item}; } } } - my $domain = $r->dir_config('lonDefDomain'); + my %sessiondata; + if ($form{'iptoken'}) { + %sessiondata = &Apache::lonnet::tmpget($form{'iptoken'}); + my $delete = &Apache::lonnet::tmpdel($form{'token'}); + } + + my $domain = $r->dir_config('lonSSOUserDomain'); + if ($domain eq '') { + $domain = $r->dir_config('lonDefDomain'); + } my $home=&Apache::lonnet::homeserver($user,$domain); if ($home !~ /(con_lost|no_host|no_such_host)/) { &Apache::lonnet::logthis(" SSO authorized user $user "); - if ($r->dir_config("lonBalancer") eq 'yes') { - # login but immeaditly go to switch server to find us a new + my ($is_balancer,$otherserver,$hosthere); + if ($form{'iptoken'}) { + if (($sessiondata{'domain'} eq $form{'udom'}) && + ($sessiondata{'username'} eq $form{'uname'})) { + $hosthere = 1; + } + } + unless ($hosthere) { + ($is_balancer,$otherserver) = + &Apache::lonnet::check_loadbalancing($user,$domain); + } + + if ($is_balancer) { + # login but immediately go to switch server to find us a new # machine - &Apache::lonauth::success($r,$user,$domain,$home,'noredirect','',\%form); + &Apache::lonauth::success($r,$user,$domain,$home,'noredirect'); $env{'request.sso.login'} = 1; if (defined($r->dir_config("lonSSOReloginServer"))) { $env{'request.sso.reloginserver'} = $r->dir_config('lonSSOReloginServer'); } - $r->internal_redirect('/adm/switchserver'); + my $redirecturl = '/adm/switchserver'; + if ($otherserver ne '') { + $redirecturl .= '?otherserver='.$otherserver; + } + $r->internal_redirect($redirecturl); $r->set_handlers('PerlHandler'=> undef); } else { # need to login them in, so generate the need data that # migrate expects to do login - my %info=('ip' => $r->connection->remote_ip(), + my $ip; + my $c = $r->connection; + eval { + $ip = $c->remote_ip(); + }; + if ($@) { + $ip = $c->client_ip(); + } + my %info=('ip' => $ip, 'domain' => $domain, 'username' => $user, 'server' => $r->dir_config('lonHostID'), @@ -367,29 +407,29 @@ sub sso_login { sub handler { my $r = shift; my $requrl=$r->uri; - if (&Apache::lonnet::is_domainimage($requrl)) { + + if ($requrl =~ m{^/res/adm/pages/[^/]+\.(gif|png)$}) { return OK; } - if ($requrl =~ m{^/res/adm/pages/[^/]+\.(gif|png)$}) { + if (&Apache::lonnet::is_domainimage($requrl)) { return OK; } - my $handle = &Apache::lonnet::check_for_valid_session($r); + my %user; + my $handle = &Apache::lonnet::check_for_valid_session($r,undef,\%user); - my $result = &sso_login($r,$handle); + my $result = &sso_login($r,$handle,$user{'name'}); if (defined($result)) { return $result; } + my ($is_balancer,$otherserver); - if ($r->dir_config("lonBalancer") eq 'yes') { - $r->set_handlers('PerlResponseHandler'=> - [\&Apache::switchserver::handler]); - } - if ($handle eq '') { - $r->log_reason("Cookie $handle not valid", $r->filename); + unless (($requrl eq '/adm/switchserver') && (!$r->is_initial_req())) { + $r->log_reason("Cookie not valid", $r->filename); + } } elsif ($handle ne '') { # ------------------------------------------------------ Initialize Environment @@ -406,6 +446,11 @@ sub handler { if ($env{'user.name'} ne '' && $env{'user.domain'} ne '') { # -------------------------------------------------------------- Resource State + my ($cdom,$cnum); + if ($env{'request.course.id'}) { + $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + } if ($requrl=~/^\/+(res|uploaded)\//) { $env{'request.state'} = "published"; } else { @@ -413,10 +458,70 @@ sub handler { } $env{'request.filename'} = $r->filename; $env{'request.noversionuri'} = &Apache::lonnet::deversion($requrl); + my $suppext; + if ($requrl =~ m{^/adm/wrapper/ext/}) { + my $query = $r->args; + if ($query) { + my $preserved; + foreach my $pair (split(/&/,$query)) { + my ($name, $value) = split(/=/,$pair); + unless ($name eq 'symb') { + $preserved .= $pair.'&'; + } + if (($env{'request.course.id'}) && ($name eq 'folderpath')) { + if ($value =~ /^supplemental/) { + $suppext = 1; + } + } + } + $preserved =~ s/\&$//; + if ($preserved) { + $env{'request.external.querystring'} = $preserved; + } + } + } elsif ($env{'request.course.id'} && + (($requrl =~ m{^/adm/$match_domain/$match_username/aboutme$}) || + ($requrl =~ m{^/public/$cdom/$cnum/syllabus$}))) { + my $query = $r->args; + if ($query) { + foreach my $pair (split(/&/,$query)) { + my ($name, $value) = split(/=/,$pair); + if ($name eq 'folderpath') { + if ($value =~ /^supplemental/) { + $suppext = 1; + } + } + } + } + } # -------------------------------------------------------- Load POST parameters &Apache::lonacc::get_posted_cgi($r); +# ------------------------------------------------------ Check if load balancer + + my $checkexempt; + if ($env{'user.loadbalexempt'} eq $r->dir_config('lonHostID')) { + if ($env{'user.loadbalcheck.time'} + 600 > time) { + $checkexempt = 1; + } + } + if ($env{'user.noloadbalance'} eq $r->dir_config('lonHostID')) { + $checkexempt = 1; + } + unless ($checkexempt) { + ($is_balancer,$otherserver) = + &Apache::lonnet::check_loadbalancing($env{'user.name'}, + $env{'user.domain'}); + } + if ($is_balancer) { + $r->set_handlers('PerlResponseHandler'=> + [\&Apache::switchserver::handler]); + if ($otherserver ne '') { + $env{'form.otherserver'} = $otherserver; + } + } + # ---------------------------------------------------------------- Check access my $now = time; if ($requrl !~ m{^/(?:adm|public|prtspool)/} @@ -435,8 +540,24 @@ sub handler { return OK; } if (($access ne '2') && ($access ne 'F')) { - $env{'user.error.msg'}="$requrl:bre:1:1:Access Denied"; - return HTTP_NOT_ACCEPTABLE; + if ($requrl =~ m{^/res/}) { + $access = &Apache::lonnet::allowed('bro',$requrl); + if ($access ne 'F') { + if ($requrl eq '/res/lib/templates/simpleproblem.problem/smpedit') { + $access = &Apache::lonnet::allowed('bre','/res/lib/templates/simpleproblem.problem'); + if ($access 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; + } + } + } else { + $env{'user.error.msg'}="$requrl:bre:1:1:Access Denied"; + return HTTP_NOT_ACCEPTABLE; + } } } if ($requrl =~ m|^/prtspool/|) { @@ -459,6 +580,7 @@ sub handler { $env{'user.domain'} eq 'public' && $requrl !~ m{^/+(res|public|uploaded)/} && $requrl !~ m{^/adm/[^/]+/[^/]+/aboutme/portfolio$ }x && + $requrl !~ m{^/adm/blockingstatus/.*$} && $requrl !~ m{^/+adm/(help|logout|restrictedaccess|randomlabel\.png)}) { $env{'request.querystring'}=$r->args; $env{'request.firsturl'}=$requrl; @@ -470,15 +592,17 @@ sub handler { $requrl=~/\.(\w+)$/; my $query=$r->args; if ((&Apache::loncommon::fileembstyle($1) eq 'ssi') || - ($requrl=~/^\/adm\/.*\/(aboutme|navmaps|smppg|bulletinboard)(\?|$ )/x) || + ($requrl=~/^\/adm\/.*\/(aboutme|smppg|bulletinboard)(\?|$ )/x) || ($requrl=~/^\/adm\/wrapper\//) || ($requrl=~m|^/adm/coursedocs/showdoc/|) || ($requrl=~m|\.problem/smpedit$|) || - ($requrl=~/^\/public\/.*\/syllabus$/)) { + ($requrl=~/^\/public\/.*\/syllabus$/) || + ($requrl=~/^\/adm\/(viewclasslist|navmaps)$/) || + ($requrl=~/^\/adm\/.*\/aboutme\/portfolio(\?|$)/)) { # ------------------------------------- This is serious stuff, get symb and log my $symb; if ($query) { - &Apache::loncommon::get_unprocessed_cgi($query,['symb']); + &Apache::loncommon::get_unprocessed_cgi($query,['symb','folderpath']); } if ($env{'form.symb'}) { $symb=&Apache::lonnet::symbclean($env{'form.symb'}); @@ -489,7 +613,9 @@ sub handler { 'last_known' =>[$murl,$mid]); } elsif ((&Apache::lonnet::symbverify($symb,$requrl)) || (($requrl=~m|(.*)/smpedit$|) && - &Apache::lonnet::symbverify($symb,$1))) { + &Apache::lonnet::symbverify($symb,$1)) || + (($requrl=~m|(.*/aboutme)/portfolio$|) && + &Apache::lonnet::symbverify($symb,$1))) { my ($map,$mid,$murl)=&Apache::lonnet::decode_symb($symb); &Apache::lonnet::symblist($map,$murl => [$murl,$mid], 'last_known' =>[$murl,$mid]); @@ -501,19 +627,24 @@ sub handler { return HTTP_NOT_ACCEPTABLE; } } else { - $symb=&Apache::lonnet::symbread($requrl); - if (&Apache::lonnet::is_on_map($requrl) && $symb && - !&Apache::lonnet::symbverify($symb,$requrl)) { - $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); - &Apache::lonnet::symblist($map,$murl =>[$murl,$mid], - 'last_known' =>[$murl,$mid]); + if ($requrl=~m{^(/adm/.*/aboutme)/portfolio$}) { + $requrl = $1; + } + unless ($suppext) { + $symb=&Apache::lonnet::symbread($requrl); + if (&Apache::lonnet::is_on_map($requrl) && $symb && + !&Apache::lonnet::symbverify($symb,$requrl)) { + $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); + &Apache::lonnet::symblist($map,$murl =>[$murl,$mid], + 'last_known' =>[$murl,$mid]); + } } } $env{'request.symb'}=$symb; @@ -522,9 +653,7 @@ sub handler { # ------------------------------------------------------- This is other content &Apache::lonnet::courseacclog($requrl); } - my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};; - my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};; - if ($requrl =~ m{^/+uploaded/\Q$cdom\E/\Q$cnum\E/docs/.+\.html?$}) { + if ($requrl =~ m{^/+uploaded/\Q$cdom\E/\Q$cnum\E/(docs|supplemental)/.+\.html?$}) { if (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) { if ($query) { &Apache::loncommon::get_unprocessed_cgi($query,['forceedit']); @@ -533,9 +662,29 @@ sub handler { } } } + } elsif ($requrl =~ m{^/+uploaded/\Q$cdom\E/\Q$cnum\E/portfolio/syllabus/.+\.html?$}) { + if (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) { + if ($query) { + &Apache::loncommon::get_unprocessed_cgi($query,['forceedit','editmode']); + if (($env{'form.forceedit'}) || ($env{'form.editmode'})) { + $env{'request.state'} = 'edit'; + } + } + } } } return OK; + } else { + my $defdom=$r->dir_config('lonDefDomain'); + ($is_balancer,$otherserver) = + &Apache::lonnet::check_loadbalancing(undef,$defdom); + if ($is_balancer) { + $r->set_handlers('PerlResponseHandler'=> + [\&Apache::switchserver::handler]); + if ($otherserver ne '') { + $env{'form.otherserver'} = $otherserver; + } + } } # -------------------------------------------- See if this is a public resource if ($requrl=~m|^/+adm/+help/+|) { 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.