--- loncom/auth/lonlogin.pm 2021/09/21 22:54:26 1.184
+++ loncom/auth/lonlogin.pm 2021/10/26 15:52:54 1.192
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Login Screen
#
-# $Id: lonlogin.pm,v 1.184 2021/09/21 22:54:26 raeburn Exp $
+# $Id: lonlogin.pm,v 1.192 2021/10/26 15:52:54 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -38,6 +38,8 @@ use Apache::lonlocal;
use Apache::migrateuser();
use lib '/home/httpd/lib/perl/';
use LONCAPA qw(:DEFAULT :match);
+use URI::Escape;
+use HTML::Entities();
use CGI::Cookie();
sub handler {
@@ -47,18 +49,45 @@ sub handler {
(join('&',$ENV{'QUERY_STRING'},$env{'request.querystring'},
$ENV{'REDIRECT_QUERY_STRING'}),
['interface','username','domain','firsturl','localpath','localres',
- 'token','role','symb','iptoken','btoken','ltoken','linkkey','saml']);
- if (!defined($env{'form.firsturl'})) {
- &Apache::lonacc::get_posted_cgi($r,['firsturl']);
- }
- if (!defined($env{'form.firsturl'})) {
- if ($ENV{'REDIRECT_URL'} =~ m{^/+tiny/+$LONCAPA::match_domain/+\w+$}) {
- $env{'form.firsturl'} = $ENV{'REDIRECT_URL'};
+ 'token','role','symb','iptoken','btoken','ltoken','linkkey','saml',
+ 'sso','retry']);
+ my $lonhost = $r->dir_config('lonHostID');
+ my $linkkey;
+ if (($env{'form.sso'}) || ($env{'form.retry'})) {
+ my $infotoken;
+ if ($env{'form.sso'}) {
+ $infotoken = $env{'form.sso'};
+ } else {
+ $infotoken = $env{'form.retry'};
+ }
+ my $data = &Apache::lonnet::reply('tmpget:'.$infotoken,$lonhost);
+ unless (($data=~/^error/) || ($data eq 'con_lost') ||
+ ($data eq 'no_such_host')) {
+ my %info = &decode_token($data);
+ foreach my $item (keys(%info)) {
+ $env{'form.'.$item} = $info{$item};
+ }
+ &Apache::lonnet::tmpdel($infotoken);
+ }
+ } else {
+ if ($env{'form.linkkey'}) {
+ $linkkey = $env{'form.linkkey'};
+ }
+ if (!defined($env{'form.firsturl'})) {
+ &Apache::lonacc::get_posted_cgi($r,['firsturl']);
+ }
+ if (!defined($env{'form.firsturl'})) {
+ if ($ENV{'REDIRECT_URL'} =~ m{^/+tiny/+$LONCAPA::match_domain/+\w+$}) {
+ $env{'form.firsturl'} = $ENV{'REDIRECT_URL'};
+ }
+ }
+ if (($env{'form.firsturl'} =~ m{^/+tiny/+$LONCAPA::match_domain/+\w+$}) &&
+ (!$env{'form.ltoken'}) && (!$env{'form.linkkey'})) {
+ &Apache::lonacc::get_posted_cgi($r,['linkkey']);
+ }
+ if ($env{'form.firsturl'} eq '/adm/logout') {
+ delete($env{'form.firsturl'});
}
- }
- if (($env{'form.firsturl'} =~ m{^/+tiny/+$LONCAPA::match_domain/+\w+$}) &&
- (!$env{'form.ltoken'}) && (!$env{'form.linkkey'})) {
- &Apache::lonacc::get_posted_cgi($r,['linkkey']);
}
# -- check if they are a migrating user
@@ -110,9 +139,6 @@ sub handler {
return OK;
}
- my $lonhost = $r->dir_config('lonHostID');
- $env{'form.firsturl'} =~ s/(`)/'/g;
-
# 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,1);
@@ -123,7 +149,12 @@ sub handler {
$protocol = 'http' if ($protocol ne 'https');
my $dest = '/adm/roles';
if ($env{'form.firsturl'} ne '') {
- $dest = $env{'form.firsturl'};
+ if ($env{'form.firsturl'} =~ /[^\x00-\xFF]/) {
+ $dest = &uri_escape_utf8($env{'form.firsturl'});
+ } else {
+ $dest = &uri_escape($env{'form.firsturl'});
+ }
+ $dest = &HTML::Entities::encode($dest,"'");
}
my %info = (
balcookie => $lonhost.':'.$balancer_cookie,
@@ -141,7 +172,7 @@ sub handler {
}
my $balancer_token = &Apache::lonnet::tmpput(\%info,$found_server);
if ($balancer_token) {
- $dest .= (($dest=~/\?/)?'&;':'?') . 'btoken='.$balancer_token;
+ $dest .= (($dest=~/\?/)?'&':'?') . 'btoken='.$balancer_token;
}
unless ($found_server eq $lonhost) {
my $alias = &Apache::lonnet::use_proxy_alias($r,$found_server);
@@ -203,7 +234,12 @@ sub handler {
&Apache::loncommon::end_page();
my $dest = '/adm/roles';
if ($env{'form.firsturl'} ne '') {
- $dest = $env{'form.firsturl'};
+ if ($env{'form.firsturl'} =~ /[^\x00-\xFF]/) {
+ $dest = &uri_escape_utf8($env{'form.firsturl'});
+ } else {
+ $dest = &uri_escape($env{'form.firsturl'});
+ }
+ $dest = &HTML::Entities::encode($dest,"'");
}
if (($env{'form.ltoken'}) || ($linkprot)) {
unless ($linkprot) {
@@ -292,7 +328,7 @@ sub handler {
$env{'form.interface'}=~s/\W//g;
(undef,undef,undef,undef,undef,undef,my $clientmobile) =
- &Apache::loncommon::decode_user_agent();
+ &Apache::loncommon::decode_user_agent($r);
my $iconpath=
&Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL'));
@@ -301,7 +337,8 @@ sub handler {
my $defdom = $domain;
if ($lonhost ne '') {
unless ($sessiondata{'sessionserver'}) {
- my $redirect = &check_loginvia($domain,$lonhost,$lonidsdir,$balcookie,$linkprot);
+ my $redirect = &check_loginvia($domain,$lonhost,$lonidsdir,$balcookie,
+ $linkprot,$linkkey);
if ($redirect) {
$r->print($redirect);
return OK;
@@ -385,37 +422,27 @@ sub handler {
if ($uextkey>2147483647) { $uextkey-=4294967296; }
# -------------------------------------------------------- Store away log token
- my $tokenextras;
- if ($env{'form.role'}) {
- $tokenextras = '&role='.&escape($env{'form.role'});
- }
- if ($env{'form.symb'}) {
- if (!$tokenextras) {
- $tokenextras = '&';
- }
- $tokenextras .= '&symb='.&escape($env{'form.symb'});
- }
- if ($env{'form.iptoken'}) {
- if (!$tokenextras) {
- $tokenextras = '&&';
+ my ($tokenextras,$tokentype);
+ my @names = ('role','symb','iptoken','ltoken','linkkey');
+ foreach my $name (@names) {
+ if ($env{'form.'.$name} ne '') {
+ if ($name eq 'ltoken') {
+ my %info = &Apache::lonnet::tmpget($env{'form.ltoken'});
+ if ($info{'linkprot'}) {
+ $tokenextras .= '&linkprot='.&escape($info{'linkprot'});
+ $tokentype = 'link';
+ last;
+ }
+ } else {
+ $tokenextras .= '&'.$name.'='.&escape($env{'form.'.$name});
+ if ($name eq 'linkkey') {
+ $tokentype = 'link';
+ }
+ }
}
- $tokenextras .= '&iptoken='.&escape($env{'form.iptoken'});
}
- if ($env{'form.ltoken'}) {
- my %info = &Apache::lonnet::tmpget($env{'form.ltoken'});
- &Apache::lonnet::tmpdel($env{'form.ltoken'});
- delete($env{'form.ltoken'});
- if ($info{'linkprot'}) {
- if (!$tokenextras) {
- $tokenextras = '&&&';
- }
- $tokenextras .= '&linkprot='.&escape($info{'linkprot'});
- }
- } elsif ($env{'form.linkkey'}) {
- if (!$tokenextras) {
- $tokenextras = '&&&';
- }
- $tokenextras .= '&linkkey='.&escape($env{'form.linkkey'});
+ if ($tokentype) {
+ $tokenextras .= ":$tokentype";
}
my $logtoken=Apache::lonnet::reply(
'tmpput:'.$ukey.$lkey.'&'.$firsturl.$tokenextras,
@@ -428,6 +455,10 @@ sub handler {
if ($logtoken eq 'no_such_host') {
&Apache::lonnet::logthis('No valid logtoken for log-in page -- unable to determine hostname for hostID: '.$lonhost.'. Check entry in hosts.tab');
}
+ if ($env{'form.ltoken'}) {
+ &Apache::lonnet::tmpdel($env{'form.ltoken'});
+ delete($env{'form.ltoken'});
+ }
my $spares='';
my (@sparehosts,%spareservers);
my $sparesref = &Apache::lonnet::this_host_spares($defdom);
@@ -654,7 +685,7 @@ ENDSAMLJS
alink => "$alink",
onload => 'javascript:enableInput();',);
- my ($headextra,$headextra_exempt,@hosts,%defaultdomconf);
+ my ($headextra,$headextra_exempt);
$headextra = $defaultdomconf{$defdom.'.login.headtag_'.$lonhost_in_use};
$headextra_exempt = $defaultdomconf{$domain.'.login.headtag_exempt_'.$lonhost_in_use};
if ($headextra) {
@@ -795,15 +826,36 @@ HEADER
if ($samlssourl ne '') {
$ssologin = $samlssourl;
}
+ if (($logtoken eq 'con_lost') || ($logtoken eq 'no_such_host')) {
+ my $querystring;
+ if ($env{'form.firsturl'} ne '') {
+ $querystring = 'origurl=';
+ if ($env{'form.firsturl'} =~ /[^\x00-\xFF]/) {
+ $querystring .= &uri_escape_utf8($env{'form.firsturl'});
+ } else {
+ $querystring .= &uri_escape($env{'form.firsturl'});
+ }
+ $querystring = &HTML::Entities::encode($querystring,"'");
+ }
+ if ($env{'form.ltoken'} ne '') {
+ $querystring .= (($querystring eq '')?'':'&') . 'ltoken='.
+ &HTML::Entities::encode(&uri_escape($env{'form.ltoken'}));
+ } elsif ($env{'form.linkkey'}) {
+ $querystring .= (($querystring eq '')?'':'&') . 'linkkey='.
+ &HTML::Entities::encode(&uri_escape($env{'form.linkkey'}));
+ }
+ if ($querystring ne '') {
+ $ssologin .= (($ssologin=~/\?/)?'&':'?') . $querystring;
+ }
+ } elsif ($logtoken ne '') {
+ $ssologin .= (($ssologin=~/\?/)?'&':'?') . 'logtoken='.$logtoken;
+ }
my $ssohref;
if ($samlssoimg ne '') {
$ssohref = '';
} else {
$ssohref = ''.$samlssotext.'';
}
- if ($env{'form.firsturl'}) {
- $ssologin .= '?origurl='.&HTML::Entities::encode($env{'form.firsturl'},'<>&"');
- }
if (($env{'form.saml'} eq 'no') ||
(($env{'form.username'} ne '') && ($env{'form.domain'} ne ''))) {
$ssoauthstyle = 'none';
@@ -828,6 +880,11 @@ $coursecatalog
ENDSAML
+ } else {
+ if ($env{'form.ltoken'}) {
+ &Apache::lonnet::tmpdel($env{'form.ltoken'});
+ delete($env{'form.ltoken'});
+ }
}
$r->print(< $linkprot},$desthost);
if ($ltoken) {
- $url .= (($url =~ /\?/) ? '&' : '?').'ltoken='.$ltoken;
+ $url .= (($url =~ /\?/) ? '&' : '?').'ltoken='.$ltoken;
}
+ } elsif ($linkkey) {
+ $url .= (($url =~ /\?/) ? '&' : '?').'linkkey='.&uri_escape($linkkey);
}
my $start_page = &Apache::loncommon::start_page('Switching Server ...',undef,
{'redirect' => [0,$url],});
@@ -1103,5 +1169,19 @@ sub newuser_link {
return ''.$linkname.'';
}
+sub decode_token {
+ my ($info) = @_;
+ my ($firsturl,@rest)=split(/\&/,$info);
+ my %form;
+ if ($firsturl ne '') {
+ $form{'firsturl'} = &unescape($firsturl);
+ }
+ foreach my $item (@rest) {
+ my ($key,$value) = split(/=/,$item);
+ $form{$key} = &unescape($value);
+ }
+ return %form;
+}
+
1;
__END__