File:  [LON-CAPA] / loncom / auth / lonlogin.pm
Revision 1.179: download - view: text, annotated - select for diffs
Sun Jan 27 16:02:43 2019 UTC (5 years, 3 months ago) by raeburn
Branches: MAIN
CVS tags: HEAD
- Bug 6400
  - Enforce access restrictions for content which is deeplink-only (users
    with "advanced priv for current role are exempt).
  - Support "key" link type in deeplink parameter (requested link must either
    be sent with linkkey as element in POSTed data, or with linkkey in query
    string).  Corresponding value must match key set in deeplink parameter.

    1: # The LearningOnline Network
    2: # Login Screen
    3: #
    4: # $Id: lonlogin.pm,v 1.179 2019/01/27 16:02:43 raeburn Exp $
    5: #
    6: # Copyright Michigan State University Board of Trustees
    7: #
    8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
    9: #
   10: # LON-CAPA is free software; you can redistribute it and/or modify
   11: # it under the terms of the GNU General Public License as published by
   12: # the Free Software Foundation; either version 2 of the License, or
   13: # (at your option) any later version.
   14: #
   15: # LON-CAPA is distributed in the hope that it will be useful,
   16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18: # GNU General Public License for more details.
   19: #
   20: # You should have received a copy of the GNU General Public License
   21: # along with LON-CAPA; if not, write to the Free Software
   22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   23: #
   24: # /home/httpd/html/adm/gpl.txt
   25: #
   26: # http://www.lon-capa.org/
   27: #
   28: 
   29: package Apache::lonlogin;
   30: 
   31: use strict;
   32: use Apache::Constants qw(:common);
   33: use Apache::File ();
   34: use Apache::lonnet;
   35: use Apache::loncommon();
   36: use Apache::lonauth();
   37: use Apache::lonlocal;
   38: use Apache::migrateuser();
   39: use lib '/home/httpd/lib/perl/';
   40: use LONCAPA qw(:DEFAULT :match);
   41: use CGI::Cookie();
   42:  
   43: sub handler {
   44:     my $r = shift;
   45: 
   46:     &Apache::loncommon::get_unprocessed_cgi
   47: 	(join('&',$ENV{'QUERY_STRING'},$env{'request.querystring'},
   48: 	      $ENV{'REDIRECT_QUERY_STRING'}),
   49: 	 ['interface','username','domain','firsturl','localpath','localres',
   50: 	  'token','role','symb','iptoken','btoken','ltoken','linkkey']);
   51:     if (!defined($env{'form.firsturl'})) {
   52:         &Apache::lonacc::get_posted_cgi($r,['firsturl']);
   53:     }
   54:     if (!defined($env{'form.firsturl'})) {
   55:         if ($ENV{'REDIRECT_URL'} =~ m{^/+tiny/+$LONCAPA::match_domain/+\w+$}) {
   56:             $env{'form.firsturl'} = $ENV{'REDIRECT_URL'};
   57:         }
   58:     }
   59:     if (($env{'form.firsturl'} =~ m{^/+tiny/+$LONCAPA::match_domain/+\w+$}) &&
   60:         (!$env{'form.ltoken'}) && (!$env{'form.linkkey'})) {
   61:         &Apache::lonacc::get_posted_cgi($r,['linkkey']);
   62:     }
   63: 
   64: # -- check if they are a migrating user
   65:     if (defined($env{'form.token'})) {
   66: 	return &Apache::migrateuser::handler($r);
   67:     }
   68: 
   69: # For "public user" - remove any exising "public" cookie, as user really wants to log-in
   70:     my ($handle,$lonidsdir,$expirepub,$userdom);
   71:     $lonidsdir=$r->dir_config('lonIDsDir');
   72:     unless ($r->header_only) {
   73:         $handle = &Apache::lonnet::check_for_valid_session($r,'lonID',undef,\$userdom);
   74:         if ($handle ne '') {
   75:             if ($handle=~/^publicuser\_/) {
   76:                 unlink($r->dir_config('lonIDsDir')."/$handle.id");
   77:                 undef($handle);
   78:                 undef($userdom);
   79:                 $expirepub = 1;
   80:             }
   81:         }
   82:     }
   83: 
   84:     &Apache::loncommon::no_cache($r);
   85:     &Apache::lonlocal::get_language_handle($r);
   86:     &Apache::loncommon::content_type($r,'text/html');
   87:     if ($expirepub) {
   88:         my $c = new CGI::Cookie(-name    => 'lonPubID',
   89:                                 -value   => '',
   90:                                 -expires => '-10y',);
   91:         $r->header_out('Set-cookie' => $c);
   92:     } elsif (($handle eq '') && ($userdom ne '')) {
   93:         my %cookies=CGI::Cookie->parse($r->header_in('Cookie'));
   94:         foreach my $name (keys(%cookies)) {
   95:             next unless ($name =~ /^lon(|S|Link|Pub)ID$/);
   96:             my $c = new CGI::Cookie(-name    => $name,
   97:                                     -value   => '',
   98:                                     -expires => '-10y',);
   99:             $r->headers_out->add('Set-cookie' => $c);
  100:         }
  101:     }
  102:     $r->send_http_header;
  103:     return OK if $r->header_only;
  104: 
  105: 
  106: # Are we re-routing?
  107:     my $londocroot = $r->dir_config('lonDocRoot'); 
  108:     if (-e "$londocroot/lon-status/reroute.txt") {
  109: 	&Apache::lonauth::reroute($r);
  110: 	return OK;
  111:     }
  112: 
  113:     my $lonhost = $r->dir_config('lonHostID');
  114:     $env{'form.firsturl'} =~ s/(`)/'/g;
  115: 
  116: # Check if browser sent a LON-CAPA load balancer cookie (and this is a balancer)
  117: 
  118:     my ($found_server,$balancer_cookie) = &Apache::lonnet::check_for_balancer_cookie($r,1);
  119:     if ($found_server) {
  120:         my $hostname = &Apache::lonnet::hostname($found_server);
  121:         if ($hostname ne '') {
  122:             my $protocol = $Apache::lonnet::protocol{$found_server};
  123:             $protocol = 'http' if ($protocol ne 'https');
  124:             my $dest = '/adm/roles';
  125:             if ($env{'form.firsturl'} ne '') {
  126:                 $dest = $env{'form.firsturl'};
  127:             }
  128:             my %info = (
  129:                          balcookie => $lonhost.':'.$balancer_cookie,
  130:                        );
  131:             if ($env{'form.ltoken'}) {
  132:                 my %link_info = &Apache::lonnet::tmpget($env{'form.ltoken'});
  133:                 if ($link_info{'linkprot'}) {
  134:                     $info{'linkprot'} = $link_info{'linkprot'};
  135:                 }
  136:                 &Apache::lonnet::tmpdel($env{'form.ltoken'});
  137:                 delete($env{'form.ltoken'});
  138:             } elsif ($env{'form.linkkey'}) {
  139:                 $info{'linkkey'} = $env{'form.linkkey'};
  140:                 delete($env{'form.linkkey'});
  141:             }
  142:             my $balancer_token = &Apache::lonnet::tmpput(\%info,$found_server);
  143:             if ($balancer_token) {
  144:                 $dest .=  (($dest=~/\?/)?'&;':'?') . 'btoken='.$balancer_token;
  145:             }
  146:             my $url = $protocol.'://'.$hostname.$dest;
  147:             my $start_page =
  148:                 &Apache::loncommon::start_page('Switching Server ...',undef,
  149:                                                {'redirect'       => [0,$url],});
  150:             my $end_page   = &Apache::loncommon::end_page();
  151:             $r->print($start_page.$end_page);
  152:             return OK;
  153:         }
  154:     }
  155: 
  156: #
  157: # Check if a LON-CAPA load balancer sent user here because user's browser sent
  158: # it a balancer cookie for an active session on this server.
  159: #
  160: 
  161:     my ($balcookie,$linkprot,$linkkey);
  162:     if ($env{'form.btoken'}) {
  163:         my %info = &Apache::lonnet::tmpget($env{'form.btoken'});
  164:         $balcookie = $info{'balcookie'};
  165:         if ($balcookie) {
  166:             if ($info{'linkprot'}) {
  167:                 $linkprot = $info{'linkprot'};
  168:             } elsif ($info{'linkkey'}) {
  169:                 $linkkey = $info{'linkkey'};
  170:             }
  171:         }    
  172:         &Apache::lonnet::tmpdel($env{'form.btoken'});
  173:         delete($env{'form.btoken'});
  174:     }
  175: 
  176: #
  177: # If browser sent an old cookie for which the session file had been removed
  178: # check if configuration for user's domain has a portal URL set.  If so
  179: # switch user's log-in to the portal.
  180: #
  181: 
  182:     if (($handle eq '') && ($userdom ne '')) {
  183:         my %domdefaults = &Apache::lonnet::get_domain_defaults($userdom);
  184:         if ($domdefaults{'portal_def'} =~ /^https?\:/) {
  185:             my $start_page = &Apache::loncommon::start_page('Switching Server ...',undef,
  186:                                           {'redirect' => [0,$domdefaults{'portal_def'}],});
  187:             my $end_page   = &Apache::loncommon::end_page();
  188:             $r->print($start_page.$end_page);
  189:             return OK;
  190:         }
  191:     }
  192: 
  193: # -------------------------------- Prevent users from attempting to login twice
  194:     if ($handle ne '') {
  195:         &Apache::lonnet::transfer_profile_to_env($lonidsdir,$handle);
  196: 	my $start_page = 
  197: 	    &Apache::loncommon::start_page('Already logged in');
  198: 	my $end_page = 
  199: 	    &Apache::loncommon::end_page();
  200:         my $dest = '/adm/roles';
  201:         if ($env{'form.firsturl'} ne '') {
  202:             $dest = $env{'form.firsturl'};
  203:         }
  204:         if (($env{'form.ltoken'}) || ($linkprot)) {
  205:             unless ($linkprot) {
  206:                 my %info = &Apache::lonnet::tmpget($env{'form.ltoken'});
  207:                 $linkprot = $info{'linkprot'};
  208:                 my $delete = &Apache::lonnet::tmpdel($env{'form.ltoken'});
  209:                 delete($env{'form.ltoken'});
  210:             }
  211:             if ($linkprot) {
  212:                 my ($linkprotector,$deeplink) = split(/:/,$linkprot,2);
  213:                 if ($env{'user.linkprotector'}) {
  214:                     my @protectors = split(/,/,$env{'user.linkprotector'});
  215:                     unless (grep(/^\Q$linkprotector\E$/,@protectors)) {
  216:                         push(@protectors,$linkprotector);
  217:                         @protectors = sort { $a <=> $b } @protectors;
  218:                         &Apache::lonnet::appenv({'user.linkprotector' => join(',',@protectors)});
  219:                     }
  220:                 } else {
  221:                     &Apache::lonnet::appenv({'user.linkprotector' => $linkprotector });
  222:                 }
  223:                 if ($env{'user.linkproturi'}) {
  224:                     my @proturis = split(/,/,$env{'user.linkproturi'});
  225:                     unless (grep(/^\Q$deeplink\E$/,@proturis)) {
  226:                         push(@proturis,$deeplink);
  227:                         @proturis = sort @proturis;
  228:                         &Apache::lonnet::appenv({'user.linkproturi' => join(',',@proturis)});
  229:                     }
  230:                 } else {
  231:                     &Apache::lonnet::appenv({'user.linkproturi' => $deeplink});
  232:                 }
  233:             }
  234:         } elsif (($env{'form.linkkey'}) || ($linkkey)) {
  235:             if ($env{'form.firsturl'} =~ m{^/tiny/$match_domain/\w+$}) {
  236:                 if ($linkkey eq '') {
  237:                     $linkkey = $env{'form.linkkey'};
  238:                 }
  239:                 if ($env{'user.deeplinkkey'}) {
  240:                     my @linkkeys = split(/,/,$env{'user.deeplinkkey'});
  241:                     unless (grep(/^\Q$linkkey\E$/,@linkkeys)) {
  242:                         push(@linkkeys,$linkkey);
  243:                         &Apache::lonnet::appenv({'user.deeplinkkey' => join(',',sort(@linkkeys))});  
  244:                     }
  245:                 } else {
  246:                     &Apache::lonnet::appenv({'user.deeplinkkey' => $linkkey});
  247:                 }
  248:                 my $deeplink = $env{'form.firsturl'}; 
  249:                 if ($env{'user.keyedlinkuri'}) {
  250:                     my @keyeduris = split(/,/,$env{'user.keyedlinkuri'});
  251:                     unless (grep(/^\Q$deeplink\E$/,@keyeduris)) {
  252:                         push(@keyeduris,$deeplink);
  253:                         &Apache::lonnet::appenv({'user.keyedlinkuri' => join(',',sort(@keyeduris))});
  254:                     }
  255:                 } else {
  256:                     &Apache::lonnet::appenv({'user.keyedlinkuri' => $deeplink});
  257:                 }
  258:             }
  259:         }
  260: 	$r->print(
  261:                   $start_page
  262:                  .'<p class="LC_warning">'.&mt('You are already logged in!').'</p>'
  263:                  .'<p>'.&mt('Please either [_1]continue the current session[_2] or [_3]log out[_4].',
  264:                   '<a href="'.$dest.'">','</a>','<a href="/adm/logout">','</a>').'</p>'
  265:                  .$end_page
  266:                  );
  267:         return OK;
  268:     }
  269: 
  270: # ---------------------------------------------------- No valid token, continue
  271: 
  272: # ---------------------------- Not possible to really login to domain "public"
  273:     if ($env{'form.domain'} eq 'public') {
  274: 	$env{'form.domain'}='';
  275: 	$env{'form.username'}='';
  276:     }
  277: 
  278: # ------ Is this page requested because /adm/migrateuser detected an IP change?
  279:     my %sessiondata;
  280:     if ($env{'form.iptoken'}) {
  281:         %sessiondata = &Apache::lonnet::tmpget($env{'form.iptoken'});
  282:         unless ($sessiondata{'sessionserver'}) {
  283:             my $delete = &Apache::lonnet::tmpdel($env{'form.iptoken'});
  284:             delete($env{'form.iptoken'});
  285:         }
  286:     }
  287: # ----------------------------------------------------------- Process Interface
  288:     $env{'form.interface'}=~s/\W//g;
  289: 
  290:     (undef,undef,undef,undef,undef,undef,my $clientmobile) =
  291:         &Apache::loncommon::decode_user_agent();
  292: 
  293:     my $iconpath= 
  294: 	&Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL'));
  295: 
  296:     my $domain = &Apache::lonnet::default_login_domain();
  297:     my $defdom = $domain;
  298:     if ($lonhost ne '') {
  299:         unless ($sessiondata{'sessionserver'}) {
  300:             my $redirect = &check_loginvia($domain,$lonhost,$lonidsdir,$balcookie,$linkprot);
  301:             if ($redirect) {
  302:                 $r->print($redirect);
  303:                 return OK;
  304:             }
  305:         }
  306:     }
  307: 
  308:     if (($sessiondata{'domain'}) &&
  309:         (&Apache::lonnet::domain($sessiondata{'domain'},'description'))) {
  310:         $domain=$sessiondata{'domain'};
  311:     } elsif (($env{'form.domain'}) && 
  312: 	(&Apache::lonnet::domain($env{'form.domain'},'description'))) {
  313: 	$domain=$env{'form.domain'};
  314:     }
  315: 
  316:     my $role    = $r->dir_config('lonRole');
  317:     my $loadlim = $r->dir_config('lonLoadLim');
  318:     my $uloadlim= $r->dir_config('lonUserLoadLim');
  319:     my $servadm = $r->dir_config('lonAdmEMail');
  320:     my $tabdir  = $r->dir_config('lonTabDir');
  321:     my $include = $r->dir_config('lonIncludes');
  322:     my $expire  = $r->dir_config('lonExpire');
  323:     my $version = $r->dir_config('lonVersion');
  324:     my $host_name = &Apache::lonnet::hostname($lonhost);
  325: 
  326: # --------------------------------------------- Default values for login fields
  327:     
  328:     my ($authusername,$authdomain);
  329:     if ($sessiondata{'username'}) {
  330:         $authusername=$sessiondata{'username'};
  331:     } else {
  332:         $env{'form.username'} = &Apache::loncommon::cleanup_html($env{'form.username'});
  333:         $authusername=($env{'form.username'}?$env{'form.username'}:'');
  334:     }
  335:     if ($sessiondata{'domain'}) {
  336:         $authdomain=$sessiondata{'domain'};
  337:     } else {
  338:         $env{'form.domain'} = &Apache::loncommon::cleanup_html($env{'form.domain'});
  339:         $authdomain=($env{'form.domain'}?$env{'form.domain'}:$domain);
  340:     }
  341: 
  342: # ---------------------------------------------------------- Determine own load
  343:     my $loadavg;
  344:     {
  345: 	my $loadfile=Apache::File->new('/proc/loadavg');
  346: 	$loadavg=<$loadfile>;
  347:     }
  348:     $loadavg =~ s/\s.*//g;
  349: 
  350:     my ($loadpercent,$userloadpercent);
  351:     if ($loadlim) {
  352:         $loadpercent=sprintf("%.1f",100*$loadavg/$loadlim);
  353:     }
  354:     if ($uloadlim) {
  355:         $userloadpercent=&Apache::lonnet::userload();
  356:     }
  357: 
  358:     my $firsturl=
  359:     ($env{'request.firsturl'}?$env{'request.firsturl'}:$env{'form.firsturl'});
  360: 
  361: # ----------------------------------------------------------- Get announcements
  362:     my $announcements=&Apache::lonnet::getannounce();
  363: # -------------------------------------------------------- Set login parameters
  364: 
  365:     my @hexstr=('0','1','2','3','4','5','6','7',
  366:                 '8','9','a','b','c','d','e','f');
  367:     my $lkey='';
  368:     for (0..7) {
  369:         $lkey.=$hexstr[rand(15)];
  370:     }
  371: 
  372:     my $ukey='';
  373:     for (0..7) {
  374:         $ukey.=$hexstr[rand(15)];
  375:     }
  376: 
  377:     my $lextkey=hex($lkey);
  378:     if ($lextkey>2147483647) { $lextkey-=4294967296; }
  379: 
  380:     my $uextkey=hex($ukey);
  381:     if ($uextkey>2147483647) { $uextkey-=4294967296; }
  382: 
  383: # -------------------------------------------------------- Store away log token
  384:     my $tokenextras;
  385:     if ($env{'form.role'}) {
  386:         $tokenextras = '&role='.&escape($env{'form.role'});
  387:     }
  388:     if ($env{'form.symb'}) {
  389:         if (!$tokenextras) {
  390:             $tokenextras = '&';
  391:         }
  392:         $tokenextras .= '&symb='.&escape($env{'form.symb'});
  393:     }
  394:     if ($env{'form.iptoken'}) {
  395:         if (!$tokenextras) {
  396:             $tokenextras = '&&';
  397:         }
  398:         $tokenextras .= '&iptoken='.&escape($env{'form.iptoken'});
  399:     }
  400:     if ($env{'form.ltoken'}) {
  401:         my %info = &Apache::lonnet::tmpget($env{'form.ltoken'});
  402:         &Apache::lonnet::tmpdel($env{'form.ltoken'});
  403:         delete($env{'form.ltoken'});
  404:         if ($info{'linkprot'}) {
  405:             if (!$tokenextras) {
  406:                 $tokenextras = '&&&';
  407:             }
  408:             $tokenextras .= '&linkprot='.&escape($info{'linkprot'});
  409:         }
  410:     } elsif ($env{'form.linkkey'}) {
  411:         if (!$tokenextras) {
  412:             $tokenextras = '&&&';
  413:         }
  414:         $tokenextras .= '&linkkey='.&escape($env{'form.linkkey'});
  415:     }
  416:     my $logtoken=Apache::lonnet::reply(
  417:        'tmpput:'.$ukey.$lkey.'&'.$firsturl.$tokenextras,
  418:        $lonhost);
  419: 
  420: # -- If we cannot talk to ourselves, or hostID does not map to a hostname
  421: #    we are in serious trouble
  422: 
  423:     if (($logtoken eq 'con_lost') || ($logtoken eq 'no_such_host')) {
  424:         if ($logtoken eq 'no_such_host') {
  425:             &Apache::lonnet::logthis('No valid logtoken for log-in page -- unable to determine hostname for hostID: '.$lonhost.'. Check entry in hosts.tab');
  426:         }
  427:         my $spares='';
  428: 	my $last;
  429:         foreach my $hostid (sort
  430: 			    {
  431: 				&Apache::lonnet::hostname($a) cmp
  432: 				    &Apache::lonnet::hostname($b);
  433: 			    }
  434: 			    keys(%Apache::lonnet::spareid)) {
  435:             next if ($hostid eq $lonhost);
  436: 	    my $hostname = &Apache::lonnet::hostname($hostid);
  437: 	    next if (($last eq $hostname) || ($hostname eq ''));
  438:             $spares.='<br /><font size="+1"><a href="http://'.
  439:                 $hostname.
  440:                 '/adm/login?domain='.$authdomain.'">'.
  441:                 $hostname.'</a>'.
  442:                 ' '.&mt('(preferred)').'</font>'.$/;
  443: 	    $last=$hostname;
  444:         }
  445:         if ($spares) {
  446:             $spares.= '<br />';
  447:         }
  448:         my %all_hostnames = &Apache::lonnet::all_hostnames();
  449:         foreach my $hostid (sort
  450: 		    {
  451: 			&Apache::lonnet::hostname($a) cmp
  452: 			    &Apache::lonnet::hostname($b);
  453: 		    }
  454: 		    keys(%all_hostnames)) {
  455:             next if ($hostid eq $lonhost || $Apache::lonnet::spareid{$hostid});
  456:             my $hostname = &Apache::lonnet::hostname($hostid);
  457:             next if (($last eq $hostname) || ($hostname eq ''));
  458:             $spares.='<br /><a href="http://'.
  459: 	             $hostname.
  460: 	             '/adm/login?domain='.$authdomain.'">'.
  461: 	             $hostname.'</a>';
  462:             $last=$hostname;
  463:          }
  464:          $r->print(
  465:    '<html>'
  466:   .'<head><title>'
  467:   .&mt('The LearningOnline Network with CAPA')
  468:   .'</title></head>'
  469:   .'<body bgcolor="#FFFFFF">'
  470:   .'<h1>'.&mt('The LearningOnline Network with CAPA').'</h1>'
  471:   .'<img src="/adm/lonKaputt/lonlogo_broken.gif" align="right" />'
  472:   .'<h3>'.&mt('This LON-CAPA server is temporarily not available for login.').'</h3>');
  473:         if ($spares) {
  474:             $r->print('<p>'.&mt('Please attempt to login to one of the following servers:')
  475:                      .'</p>'
  476:                      .$spares);
  477:         }
  478:         $r->print('</body>'
  479:                  .'</html>'
  480:         );
  481:         return OK;
  482:     }
  483: 
  484: # ----------------------------------------------- Apparently we are in business
  485:     $servadm=~s/\,/\<br \/\>/g;
  486: 
  487: # ----------------------------------------------------------- Front page design
  488:     my $pgbg=&Apache::loncommon::designparm('login.pgbg',$domain);
  489:     my $font=&Apache::loncommon::designparm('login.font',$domain);
  490:     my $link=&Apache::loncommon::designparm('login.link',$domain);
  491:     my $vlink=&Apache::loncommon::designparm('login.vlink',$domain);
  492:     my $alink=&Apache::loncommon::designparm('login.alink',$domain);
  493:     my $mainbg=&Apache::loncommon::designparm('login.mainbg',$domain);
  494:     my $loginbox_bg=&Apache::loncommon::designparm('login.sidebg',$domain);
  495:     my $loginbox_header_bgcol=&Apache::loncommon::designparm('login.bgcol',$domain);
  496:     my $loginbox_header_textcol=&Apache::loncommon::designparm('login.textcol',$domain);
  497:     my $logo=&Apache::loncommon::designparm('login.logo',$domain);
  498:     my $img=&Apache::loncommon::designparm('login.img',$domain);
  499:     my $domainlogo=&Apache::loncommon::domainlogo($domain);
  500:     my $showbanner = 1;
  501:     my $showmainlogo = 1;
  502:     if (defined(&Apache::loncommon::designparm('login.showlogo_img',$domain))) {
  503:         $showbanner = &Apache::loncommon::designparm('login.showlogo_img',$domain);
  504:     }
  505:     if (defined(&Apache::loncommon::designparm('login.showlogo_logo',$domain))) {
  506:         $showmainlogo = &Apache::loncommon::designparm('login.showlogo_logo',$domain);
  507:     }
  508:     my $showadminmail;
  509:     my @possdoms = &Apache::lonnet::current_machine_domains();
  510:     if (grep(/^\Q$domain\E$/,@possdoms)) {
  511:         $showadminmail=&Apache::loncommon::designparm('login.adminmail',$domain);
  512:     }
  513:     my $showcoursecat =
  514:         &Apache::loncommon::designparm('login.coursecatalog',$domain);
  515:     my $shownewuserlink = 
  516:         &Apache::loncommon::designparm('login.newuser',$domain);
  517:     my $showhelpdesk =
  518:         &Apache::loncommon::designparm('login.helpdesk',$domain);
  519:     my $now=time;
  520:     my $js = (<<ENDSCRIPT);
  521: 
  522: <script type="text/javascript" language="JavaScript">
  523: // <![CDATA[
  524: function send()
  525: {
  526: this.document.server.elements.uname.value
  527: =this.document.client.elements.uname.value;
  528: 
  529: this.document.server.elements.udom.value
  530: =this.document.client.elements.udom.value;
  531: 
  532: uextkey=this.document.client.elements.uextkey.value;
  533: lextkey=this.document.client.elements.lextkey.value;
  534: initkeys();
  535: 
  536: if(this.document.server.action.substr(0,5) === 'http:'){
  537:     this.document.server.elements.upass0.value
  538:         =getCrypted(this.document.client.elements.upass$now.value);
  539: } else {
  540:     this.document.server.elements.upass0.value
  541:         =this.document.client.elements.upass$now.value;
  542: }
  543: 
  544: this.document.client.elements.uname.value='';
  545: this.document.client.elements.upass$now.value='';
  546: 
  547: this.document.server.submit();
  548: return false;
  549: }
  550: 
  551: function enableInput() {
  552:     this.document.client.elements.upass$now.removeAttribute("readOnly");
  553:     this.document.client.elements.uname.removeAttribute("readOnly");
  554:     this.document.client.elements.udom.removeAttribute("readOnly");
  555:     return;
  556: }
  557: 
  558: // ]]>
  559: </script>
  560: 
  561: ENDSCRIPT
  562: 
  563: # --------------------------------------------------- Print login screen header
  564: 
  565:     my %add_entries = (
  566: 	       bgcolor      => "$mainbg",
  567: 	       text         => "$font",
  568: 	       link         => "$link",
  569: 	       vlink        => "$vlink",
  570: 	       alink        => "$alink",
  571:                onload       => 'javascript:enableInput();',);
  572: 
  573:     my ($lonhost_in_use,$headextra,$headextra_exempt,@hosts,%defaultdomconf);
  574:     @hosts = &Apache::lonnet::current_machine_ids();
  575:     $lonhost_in_use = $lonhost;
  576:     if (@hosts > 1) {
  577:         foreach my $hostid (@hosts) {
  578:             if (&Apache::lonnet::host_domain($hostid) eq $defdom) {
  579:                 $lonhost_in_use = $hostid;
  580:                 last;
  581:             }
  582:         }
  583:     }
  584:     %defaultdomconf = &Apache::loncommon::get_domainconf($defdom);
  585:     $headextra = $defaultdomconf{$defdom.'.login.headtag_'.$lonhost_in_use};
  586:     $headextra_exempt = $defaultdomconf{$domain.'.login.headtag_exempt_'.$lonhost_in_use};
  587:     if ($headextra) {
  588:         my $omitextra;
  589:         if ($headextra_exempt ne '') {
  590:             my @exempt = split(',',$headextra_exempt);
  591:             my $ip = $ENV{'REMOTE_ADDR'};
  592:             if (grep(/^\Q$ip\E$/,@exempt)) {
  593:                 $omitextra = 1;
  594:             }
  595:         }
  596:         unless ($omitextra) {
  597:             my $confname = $defdom.'-domainconfig';
  598:             if ($headextra =~ m{^\Q/res/$defdom/$confname/login/headtag/$lonhost_in_use/\E}) {
  599:                 my $extra = &Apache::lonnet::getfile(&Apache::lonnet::filelocation("",$headextra));
  600:                 unless ($extra eq '-1') {
  601:                     $js .= "\n".$extra."\n";
  602:                 }
  603:             }
  604:         }
  605:     }
  606: 
  607:     $r->print(&Apache::loncommon::start_page('The LearningOnline Network with CAPA Login',$js,
  608: 			       { 'redirect'       => [$expire,'/adm/roles'], 
  609: 				 'add_entries' => \%add_entries,
  610: 				 'only_body'   => 1,}));
  611: 
  612: # ----------------------------------------------------------------------- Texts
  613: 
  614:     my %lt=&Apache::lonlocal::texthash(
  615:           'un'       => 'Username',
  616:           'pw'       => 'Password',
  617:           'dom'      => 'Domain',
  618:           'perc'     => 'percent',
  619:           'load'     => 'Server Load',
  620:           'userload' => 'User Load',
  621:           'catalog'  => 'Course/Community Catalog',
  622:           'log'      => 'Log in',
  623:           'help'     => 'Log-in Help',
  624:           'serv'     => 'Server',
  625:           'servadm'  => 'Server Administration',
  626:           'helpdesk' => 'Contact Helpdesk',
  627:           'forgotpw' => 'Forgot password?',
  628:           'newuser'  => 'New User?',
  629:        );
  630: # -------------------------------------------------- Change password field name
  631: 
  632:     my $forgotpw = &forgotpwdisplay(%lt);
  633:     $forgotpw .= '<br />' if $forgotpw;
  634:     my $loginhelp = &Apache::lonauth::loginhelpdisplay($authdomain);
  635:     if ($loginhelp) {
  636:         $loginhelp = '<a href="'.$loginhelp.'">'.$lt{'help'}.'</a><br />';
  637:     }
  638: 
  639: # ---------------------------------------------------- Serve out DES JavaScript
  640:     {
  641:     my $jsh=Apache::File->new($include."/londes.js");
  642:     $r->print(<$jsh>);
  643:     }
  644: # ---------------------------------------------------------- Serve rest of page
  645: 
  646:     $r->print(
  647:     '<div class="LC_Box"'
  648:    .' style="margin:0 auto; padding:10px; width:90%; height: auto; background-color:#FFFFFF;">'
  649: );
  650: 
  651:     $r->print(<<ENDSERVERFORM);
  652: <form name="server" action="/adm/authenticate" method="post" target="_top">
  653:    <input type="hidden" name="logtoken" value="$logtoken" />
  654:    <input type="hidden" name="serverid" value="$lonhost" />
  655:    <input type="hidden" name="uname" value="" />
  656:    <input type="hidden" name="upass0" value="" />
  657:    <input type="hidden" name="udom" value="" />
  658:    <input type="hidden" name="localpath" value="$env{'form.localpath'}" />
  659:    <input type="hidden" name="localres" value="$env{'form.localres'}" />
  660:   </form>
  661: ENDSERVERFORM
  662:     my $coursecatalog;
  663:     if (($showcoursecat eq '') || ($showcoursecat)) {
  664:         $coursecatalog = &coursecatalog_link($lt{'catalog'}).'<br />';
  665:     }
  666:     my $newuserlink;
  667:     if ($shownewuserlink) {
  668:         $newuserlink = &newuser_link($lt{'newuser'}).'<br />';
  669:     }
  670:     my $logintitle =
  671:         '<h2 class="LC_hcell"'
  672:        .' style="background:'.$loginbox_header_bgcol.';'
  673:        .' color:'.$loginbox_header_textcol.'">'
  674:        .$lt{'log'}
  675:        .'</h2>';
  676: 
  677:     my $noscript_warning='<noscript><span class="LC_warning"><b>'
  678:                         .&mt('Use of LON-CAPA requires Javascript to be enabled in your web browser.')
  679:                         .'</b></span></noscript>';
  680:     my $helpdeskscript;
  681:     my $contactblock = &contactdisplay(\%lt,$servadm,$showadminmail,
  682:                                        $authdomain,\$helpdeskscript,
  683:                                        $showhelpdesk,\@possdoms);
  684: 
  685:     my $mobileargs;
  686:     if ($clientmobile) {
  687:         $mobileargs = 'autocapitalize="off" autocorrect="off"'; 
  688:     }
  689:     my $loginform=(<<LFORM);
  690: <form name="client" action="" onsubmit="return(send())">
  691:   <input type="hidden" name="lextkey" value="$lextkey" />
  692:   <input type="hidden" name="uextkey" value="$uextkey" />
  693:   <b><label for="uname">$lt{'un'}</label>:</b><br />
  694:   <input type="text" name="uname" id="uname" size="15" value="$authusername" readonly="readonly" $mobileargs /><br />
  695:   <b><label for="upass$now">$lt{'pw'}</label>:</b><br />
  696:   <input type="password" name="upass$now" id="upass$now" size="15" readonly="readonly" /><br />
  697:   <b><label for="udom">$lt{'dom'}</label>:</b><br />
  698:   <input type="text" name="udom" id="udom" size="15" value="$authdomain" readonly="readonly" $mobileargs /><br />
  699:   <input type="submit" value="$lt{'log'}" />
  700: </form>
  701: LFORM
  702: 
  703:     if ($showbanner) {
  704:         $r->print(<<HEADER);
  705: <!-- The LON-CAPA Header -->
  706: <div style="background:$pgbg;margin:0;width:100%;">
  707:   <img src="$img" border="0" alt="The Learning Online Network with CAPA" class="LC_maxwidth" />
  708: </div>
  709: HEADER
  710:     }
  711:     $r->print(<<ENDTOP);
  712: <div style="float:left;margin-top:0;">
  713: <div class="LC_Box" style="background:$loginbox_bg;">
  714:   $logintitle
  715:   $loginform
  716:   $noscript_warning
  717: </div>
  718:   
  719: <div class="LC_Box" style="padding-top: 10px;">
  720:   $loginhelp
  721:   $forgotpw
  722:   $contactblock
  723:   $newuserlink
  724:   $coursecatalog
  725: </div>
  726: </div>
  727: 
  728: <div>
  729: ENDTOP
  730:     if ($showmainlogo) {
  731:         $r->print(' <img src="'.$logo.'" alt="" class="LC_maxwidth" />'."\n");
  732:     }
  733: $r->print(<<ENDTOP);
  734: $announcements
  735: </div>
  736: <hr style="clear:both;" />
  737: ENDTOP
  738:     my ($domainrow,$serverrow,$loadrow,$userloadrow,$versionrow);
  739:     $domainrow = <<"END";
  740:       <tr>
  741:        <td  align="left" valign="top">
  742:         <small><b>$lt{'dom'}:&nbsp;</b></small>
  743:        </td>
  744:        <td  align="left" valign="top">
  745:         <small><tt>&nbsp;$domain</tt></small>
  746:        </td>
  747:       </tr>
  748: END
  749:     $serverrow = <<"END";
  750:       <tr>
  751:        <td  align="left" valign="top">
  752:         <small><b>$lt{'serv'}:&nbsp;</b></small>
  753:        </td>
  754:        <td align="left" valign="top">
  755:         <small><tt>&nbsp;$lonhost ($role)</tt></small>
  756:        </td>
  757:       </tr>
  758: END
  759:     if ($loadlim) {
  760:         $loadrow = <<"END";
  761:       <tr>
  762:        <td align="left" valign="top">
  763:         <small><b>$lt{'load'}:&nbsp;</b></small>
  764:        </td>
  765:        <td align="left" valign="top">
  766:         <small><tt>&nbsp;$loadpercent $lt{'perc'}</tt></small>
  767:        </td>
  768:       </tr>
  769: END
  770:     }
  771:     if ($uloadlim) {
  772:         $userloadrow = <<"END";
  773:       <tr>
  774:        <td align="left" valign="top">
  775:         <small><b>$lt{'userload'}:&nbsp;</b></small>
  776:        </td>
  777:        <td align="left" valign="top">
  778:         <small><tt>&nbsp;$userloadpercent $lt{'perc'}</tt></small>
  779:        </td>
  780:       </tr>
  781: END
  782:     }
  783:     if (($version ne '') && ($version ne '<!-- VERSION -->')) {
  784:         $versionrow = <<"END";
  785:       <tr>
  786:        <td colspan="2" align="left">
  787:         <small>$version</small>
  788:        </td>
  789:       </tr>
  790: END
  791:     }
  792: 
  793:     $r->print(<<ENDDOCUMENT);
  794:     <div style="float: left;">
  795:      <table border="0" cellspacing="0" cellpadding="0">
  796: $domainrow
  797: $serverrow
  798: $loadrow    
  799: $userloadrow
  800: $versionrow
  801:      </table>
  802:     </div>
  803:     <div style="float: right;">
  804:     $domainlogo
  805:     </div>
  806:     <br style="clear:both;" />
  807:  </div>
  808: 
  809: <script type="text/javascript">
  810: // <![CDATA[
  811: // the if prevents the script error if the browser can not handle this
  812: if ( document.client.uname ) { document.client.uname.focus(); }
  813: // ]]>
  814: </script>
  815: $helpdeskscript
  816: 
  817: ENDDOCUMENT
  818:     my %endargs = ( 'noredirectlink' => 1, );
  819:     $r->print(&Apache::loncommon::end_page(\%endargs));
  820:     return OK;
  821: }
  822: 
  823: sub check_loginvia {
  824:     my ($domain,$lonhost,$lonidsdir,$balcookie,$linkprot) = @_;
  825:     if ($domain eq '' || $lonhost eq '' || $lonidsdir eq '') {
  826:         return;
  827:     }
  828:     my %domconfhash = &Apache::loncommon::get_domainconf($domain);
  829:     my $loginvia = $domconfhash{$domain.'.login.loginvia_'.$lonhost};
  830:     my $loginvia_exempt = $domconfhash{$domain.'.login.loginvia_exempt_'.$lonhost};
  831:     my $output;
  832:     if ($loginvia ne '') {
  833:         my $noredirect;
  834:         my $ip = $ENV{'REMOTE_ADDR'};
  835:         if ($ip eq '127.0.0.1') {
  836:             $noredirect = 1;
  837:         } else {
  838:             if ($loginvia_exempt ne '') {
  839:                 my @exempt = split(',',$loginvia_exempt);
  840:                 if (grep(/^\Q$ip\E$/,@exempt)) {
  841:                     $noredirect = 1;
  842:                 }
  843:             }
  844:         }
  845:         unless ($noredirect) {
  846:             my ($newhost,$path);
  847:             if ($loginvia =~ /:/) {
  848:                 ($newhost,$path) = split(':',$loginvia);
  849:             } else {
  850:                 $newhost = $loginvia;
  851:             }
  852:             if ($newhost ne $lonhost) {
  853:                 if (&Apache::lonnet::hostname($newhost) ne '') {
  854:                     if ($balcookie) {
  855:                         my ($balancer,$cookie) = split(/:/,$balcookie);
  856:                         if ($cookie =~ /^($match_domain)_($match_username)_([a-f0-9]+)$/) {
  857:                             my ($udom,$uname,$cookieid) = ($1,$2,$3);
  858:                             unless (&Apache::lonnet::delbalcookie($cookie,$balancer) eq 'ok') {
  859:                                 if ((-d $lonidsdir) && (opendir(my $dh,$lonidsdir))) {
  860:                                     while (my $filename=readdir($dh)) {
  861:                                         if ($filename=~/^(\Q$uname\E_\d+_\Q$udom\E_$match_lonid)\.id$/) {
  862:                                             my $handle = $1;
  863:                                             my %hash =
  864:                                                 &Apache::lonnet::get_sessionfile_vars($handle,$lonidsdir,
  865:                                                                                      ['request.balancercookie',
  866:                                                                                       'user.linkedenv']);
  867:                                             if ($hash{'request.balancercookie'} eq "$balancer:$cookieid") {
  868:                                                 if (unlink("$lonidsdir/$filename")) {
  869:                                                     if (($hash{'user.linkedenv'} =~ /^[a-f0-9]+_linked$/) &&
  870:                                                         (-l "$lonidsdir/$hash{'user.linkedenv'}.id") &&
  871:                                                         (readlink("$lonidsdir/$hash{'user.linkedenv'}.id") eq "$lonidsdir/$filename")) {
  872:                                                         unlink("$lonidsdir/$hash{'user.linkedenv'}.id");
  873:                                                     }
  874:                                                 }
  875:                                             }
  876:                                             last;
  877:                                         }
  878:                                     }
  879:                                     closedir($dh);
  880:                                 }
  881:                             }
  882:                         }
  883:                     }
  884:                     $output = &redirect_page($newhost,$path,$linkprot);
  885:                 }
  886:             }
  887:         }
  888:     }
  889:     return $output;
  890: }
  891: 
  892: sub redirect_page {
  893:     my ($desthost,$path,$linkprot) = @_;
  894:     my $hostname = &Apache::lonnet::hostname($desthost);
  895:     my $protocol = $Apache::lonnet::protocol{$desthost};
  896:     $protocol = 'http' if ($protocol ne 'https');
  897:     unless ($path =~ m{^/}) {
  898:         $path = '/'.$path;
  899:     }
  900:     my $url = $protocol.'://'.$hostname.$path;
  901:     if ($env{'form.firsturl'} ne '') {
  902:         $url .='?firsturl='.$env{'form.firsturl'};
  903:     }
  904:     if ($linkprot) {
  905:         my $ltoken = &Apache::lonnet::tmpput({linkprot => $linkprot},$desthost);
  906:         if ($ltoken) {
  907:             $url .= (($url =~ /\?/) ? '&' : '?').'ltoken='.$ltoken;
  908:         }
  909:     }
  910:     my $start_page = &Apache::loncommon::start_page('Switching Server ...',undef,
  911:                                                     {'redirect' => [0,$url],});
  912:     my $end_page   = &Apache::loncommon::end_page();
  913:     return $start_page.$end_page;
  914: }
  915: 
  916: sub contactdisplay {
  917:     my ($lt,$servadm,$showadminmail,$authdomain,$helpdeskscript,$showhelpdesk,
  918:         $possdoms) = @_;
  919:     my $contactblock;
  920:     my $origmail;
  921:     if (ref($possdoms) eq 'ARRAY') {
  922:         if (grep(/^\Q$authdomain\E$/,@{$possdoms})) { 
  923:             $origmail = $Apache::lonnet::perlvar{'lonSupportEMail'};
  924:         }
  925:     }
  926:     my $requestmail = 
  927:         &Apache::loncommon::build_recipient_list(undef,'helpdeskmail',
  928:                                                  $authdomain,$origmail);
  929:     unless ($showhelpdesk eq '0') {
  930:         if ($requestmail =~ m/[^\@]+\@[^\@]+/) {
  931:             $showhelpdesk = 1;
  932:         } else {
  933:             $showhelpdesk = 0;
  934:         }
  935:     }
  936:     if ($servadm && $showadminmail) {
  937:         $contactblock .= $$lt{'servadm'}.':<br />'.
  938:                          '<tt>'.$servadm.'</tt><br />';
  939:     }
  940:     if ($showhelpdesk) {
  941:         $contactblock .= '<a href="javascript:helpdesk()">'.$lt->{'helpdesk'}.'</a><br />';
  942:         my $thisurl = &escape('/adm/login');
  943:         $$helpdeskscript = <<"ENDSCRIPT";
  944: <script type="text/javascript">
  945: // <![CDATA[
  946: function helpdesk() {
  947:     var possdom = document.client.udom.value;
  948:     var codedom = possdom.replace( new RegExp("[^A-Za-z0-9.\\-]","g"),'');
  949:     if (codedom == '') {
  950:         codedom = "$authdomain";
  951:     }
  952:     var querystr = "origurl=$thisurl&codedom="+codedom;
  953:     document.location.href = "/adm/helpdesk?"+querystr;
  954:     return;
  955: }
  956: // ]]>
  957: </script>
  958: ENDSCRIPT
  959:     }
  960:     return $contactblock;
  961: }
  962: 
  963: sub forgotpwdisplay {
  964:     my (%lt) = @_;
  965:     my $prompt_for_resetpw = 1; 
  966:     if ($prompt_for_resetpw) {
  967:         return '<a href="/adm/resetpw">'.$lt{'forgotpw'}.'</a>';
  968:     }
  969:     return;
  970: }
  971: 
  972: sub coursecatalog_link {
  973:     my ($linkname) = @_;
  974:     return <<"END";
  975:       <a href="/adm/coursecatalog">$linkname</a>
  976: END
  977: }
  978: 
  979: sub newuser_link {
  980:     my ($linkname) = @_;
  981:     return '<a href="/adm/createaccount">'.$linkname.'</a>';
  982: }
  983: 
  984: 1;
  985: __END__

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