--- loncom/auth/lonauth.pm 2021/08/07 20:49:10 1.164 +++ loncom/auth/lonauth.pm 2021/10/26 15:52:54 1.168 @@ -1,7 +1,7 @@ # The LearningOnline Network # User Authentication Module # -# $Id: lonauth.pm,v 1.164 2021/08/07 20:49:10 raeburn Exp $ +# $Id: lonauth.pm,v 1.168 2021/10/26 15:52:54 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -298,37 +298,44 @@ sub failed { if ($udom) { $retry .= (($retry=~/\?/)?'&':'?').'domain='.$udom; } - if (exists($form->{role})) { - my $role = &Apache::loncommon::cleanup_html($form->{role}); - if ($role ne '') { - $retry .= (($retry=~/\?/)?'&':'?').'role='.$role; - } - } - if (exists($form->{symb})) { - my $symb = &Apache::loncommon::cleanup_html($form->{symb}); - if ($symb ne '') { - $retry .= (($retry=~/\?/)?'&':'?').'symb='.$symb; - } - } - if (exists($form->{firsturl})) { - my $firsturl = &Apache::loncommon::cleanup_html($form->{firsturl}); - if ($firsturl ne '') { - $retry .= (($retry=~/\?/)?'&':'?').'firsturl='.$firsturl; - if ($firsturl =~ m{^/tiny/$match_domain/\w+$}) { - unless (exists($form->{linkprot})) { - if (exists($form->{linkkey})) { - $retry .= 'linkkey='.$form->{linkkey}; + my $lonhost = $r->dir_config('lonHostID'); + my $querystr; + my $result = &set_retry_token($form,$lonhost,\$querystr); + if ($result eq 'fail') { + if (exists($form->{role})) { + my $role = &Apache::loncommon::cleanup_html($form->{role}); + if ($role ne '') { + $retry .= (($retry=~/\?/)?'&':'?').'role='.$role; + } + } + if (exists($form->{symb})) { + my $symb = &Apache::loncommon::cleanup_html($form->{symb}); + if ($symb ne '') { + $retry .= (($retry=~/\?/)?'&':'?').'symb='.$symb; + } + } + if (exists($form->{firsturl})) { + my $firsturl = &Apache::loncommon::cleanup_html($form->{firsturl}); + if ($firsturl ne '') { + $retry .= (($retry=~/\?/)?'&':'?').'firsturl='.$firsturl; + if ($form->{firsturl} =~ m{^/tiny/$match_domain/\w+$}) { + unless (exists($form->{linkprot})) { + if (exists($form->{linkkey})) { + $retry .= 'linkkey='.$form->{linkkey}; + } } } } } - } - if (exists($form->{linkprot})) { - my $ltoken = &Apache::lonnet::tmpput({linkprot => $form->{'linkprot'}}, - $r->dir_config('lonHostID')); - if ($ltoken) { - $retry .= (($retry =~ /\?/) ? '&' : '?').'ltoken='.$ltoken; + if (exists($form->{linkprot})) { + my $ltoken = &Apache::lonnet::tmpput({linkprot => $form->{'linkprot'}}, + $r->dir_config('lonHostID')); + if ($ltoken) { + $retry .= (($retry =~ /\?/) ? '&' : '?').'ltoken='.$ltoken; + } } + } elsif ($querystr ne '') { + $retry .= (($retry=~/\?/)?'&':'?').$querystr; } my $end_page = &Apache::loncommon::end_page(); &Apache::loncommon::content_type($r,'text/html'); @@ -386,18 +393,17 @@ sub handler { &Apache::lonnet::transfer_profile_to_env($lonidsdir,$handle); &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; - my $start_page = + my $start_page = &Apache::loncommon::start_page('Already logged in'); my $end_page = &Apache::loncommon::end_page(); my $dest = '/adm/roles'; if ($env{'form.firsturl'} ne '') { $dest = $env{'form.firsturl'}; - if (($env{'form.firsturl'} =~ m{^/tiny/$match_domain/\w+$}) && - ($env{'request.course.id'})) { + if (($dest =~ m{^/tiny/$match_domain/\w+$}) && ($env{'request.course.id'})) { my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; - my $symb = &Apache::loncommon::symb_from_tinyurl($env{'form.firsturl'},$cnum,$cdom); + my $symb = &Apache::loncommon::symb_from_tinyurl($dest,$cnum,$cdom); if ($symb) { my $buffer; if ($r->header_in('Content-length') > 0) { @@ -493,37 +499,14 @@ sub handler { return OK; } - my ($key,$firsturl,$rolestr,$symbstr,$iptokenstr,$linkstr)=split(/&/,$tmpinfo); - if ($rolestr) { - $rolestr = &unescape($rolestr); - } - if ($symbstr) { - $symbstr= &unescape($symbstr); - } - if ($iptokenstr) { - $iptokenstr = &unescape($iptokenstr); - } - if ($linkstr) { - $linkstr = &unescape($linkstr); + my ($key,$firsturl,@rest)=split(/&/,$tmpinfo); + foreach my $item (@rest) { + my ($key,$value) = split(/=/,$item); + $form{$key} = &unescape($value); } if ($firsturl =~ m{^/tiny/$match_domain/\w+$}) { $form{'firsturl'} = $firsturl; } - if ($rolestr =~ /^role=/) { - (undef,$form{'role'}) = split('=',$rolestr); - } - if ($symbstr =~ /^symb=/) { - (undef,$form{'symb'}) = split('=',$symbstr); - } - if ($iptokenstr =~ /^iptoken=/) { - (undef,$form{'iptoken'}) = split('=',$iptokenstr); - } - if ($linkstr =~ /^linkprot=/) { - (undef,$form{'linkprot'}) = split('=',$linkstr); - } elsif ($linkstr =~ /^linkkey=/) { - (undef,$form{'linkkey'}) = split('=',$linkstr); - } - my $upass = $ENV{HTTPS} ? $form{'upass0'} : &Apache::loncommon::des_decrypt($key,$form{'upass0'}); @@ -556,7 +539,8 @@ sub handler { return OK; } my $start_page = - &Apache::loncommon::start_page('Create a user account in LON-CAPA'); + &Apache::loncommon::start_page('Create a user account in LON-CAPA', + '',{'no_inline_link' => 1,}); my $lonhost = $r->dir_config('lonHostID'); my $origmail = $Apache::lonnet::perlvar{'lonSupportEMail'}; my $contacts = @@ -700,7 +684,7 @@ sub handler { \%form); my $switchto = '/adm/switchserver?otherserver='.$otherserver; if (($firsturl) && ($firsturl ne '/adm/switchserver') && ($firsturl ne '/adm/roles')) { - $switchto .= '&origurl='.$firsturl; #should escape + $switchto .= '&origurl='.$firsturl; } if ($form{'role'}) { $switchto .= '&role='.$form{'role'}; @@ -710,7 +694,7 @@ sub handler { } if ($form{'linkprot'}) { $env{'request.linkprot'} = $form{'linkprot'}; - } elsif ($form{'linkkey'}) { + } elsif ($form{'linkkey'} ne '') { $env{'request.linkkey'} = $form{'linkkey'}; } if ($form{'firsturl'} =~ m{^/tiny/$match_domain/\w+$}) { @@ -731,7 +715,7 @@ sub handler { \%form); my $switchto = '/adm/switchserver?otherserver='.$otherserver; if (($firsturl) && ($firsturl ne '/adm/switchserver') && ($firsturl ne '/adm/roles')) { - $switchto .= '&origurl='.$firsturl; #should escape + $switchto .= '&origurl='.$firsturl; } if ($form{'role'}) { $switchto .= '&role='.$form{'role'}; @@ -741,7 +725,7 @@ sub handler { } if ($form{'linkprot'}) { $env{'request.linkprot'} = $form{'linkprot'}; - } elsif ($form{'linkkey'}) { + } elsif ($form{'linkkey'} ne '') { $env{'request.linkkey'} = $form{'linkkey'}; } if ($form{'firsturl'} =~ m{^/tiny/$match_domain/\w+$}) { @@ -780,7 +764,7 @@ sub handler { undef,\%form); if ($form{'linkprot'}) { $env{'request.linkprot'} = $form{'linkprot'}; - } elsif ($form{'linkkey'}) { + } elsif ($form{'linkkey'} ne '') { $env{'request.linkkey'} = $form{'linkkey'}; } if ($form{'firsturl'} =~ m{^/tiny/$match_domain/\w+$}) { @@ -800,12 +784,25 @@ sub handler { $extra_env = {'user.linkprotector' => $linkprotector, 'user.linkproturi' => $uri}; } - } elsif ($form{'linkkey'}) { - $extra_env = {'user.deeplinkkey' => $form{'linkkey'}, + } elsif ($form{'linkkey'} ne '') { + $extra_env = {'user.deeplinkkey' => $form{'linkkey'}, 'user.keyedlinkuri' => $form{'firsturl'}}; } if ($form{'firsturl'} =~ m{^/tiny/$match_domain/\w+$}) { &set_deeplink_login(%form); + if ($form{'linkprot'}) { + if (ref($extra_env) eq 'HASH') { + %{$extra_env} = ( %{$extra_env}, 'request.linkprot' => $form{'linkprot'} ); + } else { + $extra_env = {'request.linkprot' => $form{'linkprot'}}; + } + } elsif ($form{'linkkey'} ne '') { + if (ref($extra_env) eq 'HASH') { + %{$extra_env} = ( %{$extra_env}, 'request.linkkey' => $form{'linkkey'} ); + } else { + $extra_env = {'request.linkkey' => $form{'linkkey'}}; + } + } if ($env{'request.deeplink.login'}) { if (ref($extra_env) eq 'HASH') { %{$extra_env} = ( %{$extra_env}, 'request.deeplink.login' => $form{'firsturl'} ); @@ -826,24 +823,36 @@ sub set_deeplink_login { my $cdom = $1; my ($cnum,$symb) = &Apache::loncommon::symb_from_tinyurl($form{'firsturl'},'',$cdom); if ($symb) { - my $disallow; - my $deeplink = &Apache::lonnet::EXT("resource.0.deeplink",$symb); - if ($deeplink ne '') { - my ($state,$others,$listed,$scope,$protect) = split(/,/,$deeplink); - if (($protect ne 'none') && ($protect ne '')) { - my ($acctype,$item) = split(/:/,$protect); - if (($acctype eq 'ltic') || ($acctype eq 'ltid')) { - unless ($form{'linkprot'} eq $protect) { - $disallow = 1; - } - } elsif ($acctype eq 'key') { - unless (form{'linkkey'} eq $item) { - $disallow = 1; + if ($env{'request.course.id'} eq $cdom.'_'.$cnum) { + my ($disallow,$deeplink); + if ($symb =~ /\.(page|sequence)$/) { + my $mapname = &Apache::lonnet::deversion((&Apache::lonnet::decode_symb($symb))[2]); + my $navmap = Apache::lonnavmaps::navmap->new(); + if (ref($navmap)) { + $deeplink = $navmap->get_mapparam(undef,$mapname,'0.deeplink'); + } + } else { + $deeplink = &Apache::lonnet::EXT('resource.0.deeplink',$symb); + } + if ($deeplink ne '') { + my ($state,$others,$listed,$scope,$protect) = split(/,/,$deeplink); + if (($protect ne 'none') && ($protect ne '')) { + my ($acctype,$item) = split(/:/,$protect); + if ($acctype =~ /lti(c|d)$/) { + unless ($form{'linkprot'} eq $item.$1.':'.$env{'request.deeplink.login'}) { + $disallow = 1; + } + } elsif ($acctype eq 'key') { + unless ($form{'linkkey'} eq $item) { + $disallow = 1; + } } } } - } - unless ($disallow) { + unless ($disallow) { + $env{'request.deeplink.login'} = $form{'firsturl'}; + } + } else { $env{'request.deeplink.login'} = $form{'firsturl'}; } } @@ -851,6 +860,35 @@ sub set_deeplink_login { return; } +sub set_retry_token { + my ($form,$lonhost,$querystr) = @_; + if (ref($form) eq 'HASH') { + my ($firsturl,$token,$extras,@names); + @names = ('role','symb','linkprot','linkkey'); + foreach my $name (@names) { + if ($form->{$name} ne '') { + $extras .= '&'.$name.'='.&escape($form->{$name}); + last if ($name eq 'linkprot'); + } + } + my $firsturl = $form->{'firsturl'}; + if (($firsturl ne '') || ($extras ne '')) { + $extras .= ':retry'; + $token = &Apache::lonnet::reply('tmpput:'.&escape($firsturl). + $extras,$lonhost); + if (($token eq 'con_lost') || ($token eq 'no_such_host')) { + return 'fail'; + } else { + if (ref($querystr)) { + $$querystr = 'retry='.$token; + } + return 'ok'; + } + } + } + return; +} + sub check_can_host { my ($r,$form,$authhost,$domdesc) = @_; return unless (ref($form) eq 'HASH'); @@ -911,13 +949,13 @@ sub check_can_host { } else { &success($r,$form->{'uname'},$udom,$authhost,'noredirect',undef, $form); + if ($form->{'firsturl'} =~ m{^/tiny/$match_domain/\w+$}) { + $env{'request.deeplink.login'} = $form->{'firsturl'}; + } if ($form->{'linkprot'}) { $env{'request.linkprot'} = $form->{'linkprot'}; - } elsif ($form->{'firsturl'} =~ m{^/tiny/$match_domain/\w+$}) { - if ($form->{'linkkey'}) { - $env{'request.linkkey'} = $form->{'linkkey'}; - } - $env{'request.deeplink.login'} = $form->{'firsturl'}; + } elsif ($form->{'linkkey'} ne '') { + $env{'request.linkkey'} = $form->{'linkkey'}; } my ($otherserver) = &Apache::lonnet::choose_server($udom); $r->internal_redirect('/adm/switchserver?otherserver='.$otherserver);