[LON-CAPA-cvs] cvs: loncom(version_2_11_X) /auth lonlogin.pm

raeburn raeburn at source.lon-capa.org
Sun Dec 12 06:47:03 EST 2021


raeburn		Sun Dec 12 11:47:03 2021 EDT

  Modified files:              (Branch: version_2_11_X)
    /loncom/auth	lonlogin.pm 
  Log:
  - For 2.11
    Backport 1.183, 1.184, 1.185, 1.186, 1.187 (part), 1.188, 1.189, 1.190,
              1.191, 1.192 (part), 1.193
  
  
-------------- next part --------------
Index: loncom/auth/lonlogin.pm
diff -u loncom/auth/lonlogin.pm:1.158.2.12 loncom/auth/lonlogin.pm:1.158.2.13
--- loncom/auth/lonlogin.pm:1.158.2.12	Mon Jan  4 03:49:10 2021
+++ loncom/auth/lonlogin.pm	Sun Dec 12 11:47:03 2021
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Login Screen
 #
-# $Id: lonlogin.pm,v 1.158.2.12 2021/01/04 03:49:10 raeburn Exp $
+# $Id: lonlogin.pm,v 1.158.2.13 2021/12/12 11:47:03 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -38,6 +38,8 @@
 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,16 +49,39 @@
 	(join('&',$ENV{'QUERY_STRING'},$env{'request.querystring'},
 	      $ENV{'REDIRECT_QUERY_STRING'}),
 	 ['interface','username','domain','firsturl','localpath','localres',
-	  'token','role','symb','iptoken','btoken']);
-    if (!defined($env{'form.firsturl'})) {
-        &Apache::lonacc::get_posted_cgi($r,['firsturl']);
-    }
+	  'token','role','symb','iptoken','btoken','saml','sso','retry']);
 
 # -- check if they are a migrating user
     if (defined($env{'form.token'})) {
 	return &Apache::migrateuser::handler($r);
     }
 
+    my $lonhost = $r->dir_config('lonHostID');
+    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 (!defined($env{'form.firsturl'})) {
+            &Apache::lonacc::get_posted_cgi($r,['firsturl']);
+        }
+        if ($env{'form.firsturl'} eq '/adm/logout') {
+            delete($env{'form.firsturl'});
+        }
+    }
+
 # For "public user" - remove any exising "public" cookie, as user really wants to log-in
     my ($handle,$lonidsdir,$expirepub,$userdom);
     $lonidsdir=$r->dir_config('lonIDsDir');
@@ -101,9 +126,6 @@
 	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);
@@ -114,14 +136,25 @@
             $protocol = 'http' if ($protocol ne 'https');
             my $dest = '/adm/roles';
             if ($env{'form.firsturl'} ne '') {
-                $dest = $env{'form.firsturl'};
+                $dest = &HTML::Entities::encode($env{'form.firsturl'},'\'"<>&');
             }
             my %info = (
                          balcookie => $lonhost.':'.$balancer_cookie,
                        );
+            if ($env{'form.role'}) {
+                $info{'role'} = $env{'form.role'};
+            }
+            if ($env{'form.symb'}) {
+                $info{'symb'} = $env{'form.symb'};
+            }
             my $balancer_token = &Apache::lonnet::tmpput(\%info,$found_server);
-            if ($balancer_token) {
-                $dest .=  (($dest=~/\?/)?'&;':'?') . 'btoken='.$balancer_token;
+            unless (($balancer_token eq 'con_lost') || ($balancer_token eq 'refused') ||
+                    ($balancer_token eq 'unknown_cmd') || ($balancer_token eq 'no_such_host')) {
+                $dest .=  (($dest=~/\?/)?'&':'?') . 'btoken='.$balancer_token;
+            }
+            unless ($found_server eq $lonhost) {
+                my $alias = &Apache::lonnet::use_proxy_alias($r,$found_server);
+                $hostname = $alias if ($alias ne '');
             }
             my $url = $protocol.'://'.$hostname.$dest;
             my $start_page =
@@ -163,8 +196,6 @@
         }
     }
 
-    $env{'form.firsturl'} =~ s/(`)/'/g;
-
 # -------------------------------- Prevent users from attempting to login twice
     if ($handle ne '') {
         &Apache::lonnet::transfer_profile_to_env($lonidsdir,$handle);
@@ -174,7 +205,7 @@
 	    &Apache::loncommon::end_page();
         my $dest = '/adm/roles';
         if ($env{'form.firsturl'} ne '') {
-            $dest = $env{'form.firsturl'}; 
+            $dest = &HTML::Entities::encode($env{'form.firsturl'},'\'"<>&');
         }
 	$r->print(
               $start_page
@@ -207,7 +238,7 @@
     $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,23 +332,14 @@
 
 # -------------------------------------------------------- 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 @names = ('role','symb','iptoken');
+    foreach my $name (@names) {
+        if ($env{'form.'.$name} ne '') {
+            $tokenextras .= '&'.$name.'='.&escape($env{'form.'.$name});
         }
-        $tokenextras .= '&iptoken='.&escape($env{'form.iptoken'});
     }
     my $logtoken=Apache::lonnet::reply(
-       'tmpput:'.$ukey.$lkey.'&'.$firsturl.$tokenextras,
+       'tmpput:'.$ukey.$lkey.'&'.&escape($firsturl).$tokenextras,
        $lonhost);
 
 # -- If we cannot talk to ourselves, or hostID does not map to a hostname
@@ -475,17 +497,9 @@
 
 ENDSCRIPT
 
-# --------------------------------------------------- Print login screen header
-
-    my %add_entries = (
-	       bgcolor      => "$mainbg",
-	       text         => "$font",
-	       link         => "$link",
-	       vlink        => "$vlink",
-	       alink        => "$alink",
-               onload       => 'javascript:enableInput();',);
-
-    my ($lonhost_in_use,$headextra,$headextra_exempt, at hosts,%defaultdomconf);
+    my ($lonhost_in_use, at hosts,%defaultdomconf,$saml_prefix,$saml_landing,
+        $samlssotext,$samlnonsso,$samlssoimg,$samlssoalt,$samlssourl,$samltooltip);
+    %defaultdomconf = &Apache::loncommon::get_domainconf($defdom);
     @hosts = &Apache::lonnet::current_machine_ids();
     $lonhost_in_use = $lonhost;
     if (@hosts > 1) {
@@ -496,7 +510,67 @@
             }
         }
     }
-    %defaultdomconf = &Apache::loncommon::get_domainconf($defdom);
+    $saml_prefix = $defdom.'.login.saml_';
+    if ($defaultdomconf{$saml_prefix.$lonhost_in_use}) {
+        $saml_landing = 1;
+        $samlssotext = $defaultdomconf{$saml_prefix.'text_'.$lonhost_in_use};
+        $samlnonsso = $defaultdomconf{$saml_prefix.'notsso_'.$lonhost_in_use};
+        $samlssoimg = $defaultdomconf{$saml_prefix.'img_'.$lonhost_in_use};
+        $samlssoalt = $defaultdomconf{$saml_prefix.'alt_'.$lonhost_in_use};
+        $samlssourl = $defaultdomconf{$saml_prefix.'url_'.$lonhost_in_use};
+        $samltooltip = $defaultdomconf{$saml_prefix.'title_'.$lonhost_in_use};
+    }
+    if ($saml_landing) {
+       if ($samlssotext eq '') {
+           $samlssotext = 'SSO Login';
+       }
+       if ($samlnonsso eq '') {
+           $samlnonsso = 'Non-SSO Login';
+       }
+       $js .= <<"ENDSAMLJS";
+
+<script type="text/javascript">
+// <![CDATA[
+function toggleLClogin() {
+    if (document.getElementById('LC_standard_login')) {
+        if (document.getElementById('LC_standard_login').style.display == 'none') {
+            document.getElementById('LC_standard_login').style.display = 'inline-block';
+            if (document.getElementById('LC_login_text')) {
+                document.getElementById('LC_login_text').innerHTML = '$samlnonsso';
+            }
+            if (document.getElementById('LC_SSO_login')) {
+                document.getElementById('LC_SSO_login').style.display = 'none';
+            }
+        } else {
+            document.getElementById('LC_standard_login').style.display = 'none';
+            if (document.getElementById('LC_login_text')) {
+                document.getElementById('LC_login_text').innerHTML = '$samlssotext';
+            }
+            if (document.getElementById('LC_SSO_login')) {
+                document.getElementById('LC_SSO_login').style.display = 'inline-block';
+            }
+        }
+    }
+    return;
+}
+
+// ]]>
+</script>
+
+ENDSAMLJS
+    }
+
+# --------------------------------------------------- Print login screen header
+
+    my %add_entries = (
+	       bgcolor      => "$mainbg",
+	       text         => "$font",
+	       link         => "$link",
+	       vlink        => "$vlink",
+	       alink        => "$alink",
+               onload       => 'javascript:enableInput();',);
+
+    my ($headextra,$headextra_exempt);
     $headextra = $defaultdomconf{$defdom.'.login.headtag_'.$lonhost_in_use};
     $headextra_exempt = $defaultdomconf{$domain.'.login.headtag_exempt_'.$lonhost_in_use};
     if ($headextra) {
@@ -541,6 +615,7 @@
           'helpdesk' => 'Contact Helpdesk',
           'forgotpw' => 'Forgot password?',
           'newuser'  => 'New User?',
+          'change'   => 'Change?',
        );
 # -------------------------------------------------- Change password field name
 
@@ -602,7 +677,7 @@
         $mobileargs = 'autocapitalize="off" autocorrect="off"'; 
     }
     my $loginform=(<<LFORM);
-<form name="client" action="" onsubmit="return(send())">
+<form name="client" action="" onsubmit="return(send())" id="lclogin">
   <input type="hidden" name="lextkey" value="$lextkey" />
   <input type="hidden" name="uextkey" value="$uextkey" />
   <b><label for="uname">$lt{'un'}</label>:</b><br />
@@ -623,8 +698,70 @@
 </div>
 HEADER
     }
-    $r->print(<<ENDTOP);
-<div style="float:left;margin-top:0;">
+
+    my $stdauthformstyle = 'inline-block';
+    my $ssoauthstyle = 'none';
+    my $logintype;
+    $r->print('<div style="float:left;margin-top:0;">');
+    if ($saml_landing) {
+        $ssoauthstyle = 'inline-block';
+        $stdauthformstyle = 'none';
+        $logintype = $samlssotext;
+        my $ssologin = '/adm/sso';
+        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 ($querystring ne '') {
+                $ssologin .= (($ssologin=~/\?/)?'&':'?') . $querystring;
+            }
+        } elsif ($logtoken ne '') {
+            $ssologin .= (($ssologin=~/\?/)?'&':'?') . 'logtoken='.$logtoken;
+        }
+        my $ssohref;
+        if ($samlssoimg ne '') {
+            $ssohref = '<a href="'.$ssologin.'" title="'.$samltooltip.'"><img src="'.$samlssoimg.'" alt="'.$samlssoalt.'" /></a>';
+        } else {
+            $ssohref = '<a href="'.$ssologin.'">'.$samlssotext.'</a>';
+        }
+        if (($env{'form.saml'} eq 'no') ||
+            (($env{'form.username'} ne '') && ($env{'form.domain'} ne ''))) {
+            $ssoauthstyle = 'none';
+            $stdauthformstyle = 'inline-block';
+            $logintype = $samlnonsso;
+        }
+        $r->print(<<ENDSAML);
+<p>
+Log-in type:
+<span style="font-weight:bold" id="LC_login_text">$logintype</span><br />
+<span><a href="javascript:toggleLClogin();" style="color:#000000">$lt{'change'}</a></span>
+</p>
+<div style="display:$ssoauthstyle" id="LC_SSO_login">
+<div class="LC_Box" style="padding-top: 10px;">
+$ssohref
+$noscript_warning
+</div>
+<div class="LC_Box" style="padding-top: 10px;">
+$loginhelp
+$contactblock
+$coursecatalog
+</div>
+</div>
+ENDSAML
+    }
+
+    $r->print(<<ENDLOGIN);
+<div style="display:$stdauthformstyle;" id="LC_standard_login">
 <div class="LC_Box" style="background:$loginbox_bg;">
   $logintitle
   $loginform
@@ -640,8 +777,8 @@
 </div>
 </div>
 
-<div>
-ENDTOP
+ENDLOGIN
+    $r->print('</div><div>'."\n");
     if ($showmainlogo) {
         $r->print(' <img src="'.$logo.'" alt="" class="LC_maxwidth" />'."\n");
     }
@@ -814,7 +951,14 @@
     }
     my $url = $protocol.'://'.$hostname.$path;
     if ($env{'form.firsturl'} ne '') {
-        $url .='?firsturl='.$env{'form.firsturl'};
+        my $querystring;
+        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,"'");
+        $url .='?firsturl='.$querystring;
     }
     my $start_page = &Apache::loncommon::start_page('Switching Server ...',undef,
                                                     {'redirect' => [0,$url],});
@@ -890,5 +1034,19 @@
     return '<a href="/adm/createaccount">'.$linkname.'</a>';
 }
 
+sub decode_token {
+    my ($info) = @_;
+    my ($firsturl, at 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__


More information about the LON-CAPA-cvs mailing list