--- loncom/auth/lonauth.pm 2003/02/26 14:10:38 1.42 +++ loncom/auth/lonauth.pm 2005/07/07 06:18:37 1.69 @@ -1,7 +1,7 @@ # The LearningOnline Network # User Authentication Module # -# $Id: lonauth.pm,v 1.42 2003/02/26 14:10:38 www Exp $ +# $Id: lonauth.pm,v 1.69 2005/07/07 06:18:37 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -25,13 +25,6 @@ # # http://www.lon-capa.org/ # -# 5/21/99,5/22,5/25,5/26,5/27,5/29,6/2,6/11,6/14,6/15 -# 16/11,12/16, -# 1/14,2/24,2/28,2/29,3/7,5/29,5/30,5/31,6/1,6/5,6/29, -# 7/1,7/10,10/2,10/5,10/9,10/26,10/30,11/10, -# 05/28,05/29 Gerd Kortemeyer -# 07/28,08/03 Gerd Kortemeyer -# 8/20 Gerd Kortemeyer package Apache::lonauth; @@ -42,9 +35,11 @@ use CGI qw(:standard); use CGI::Cookie(); use DynaLoader; # for Crypt::DES version use Crypt::DES; -use Apache::lonnet(); +use Apache::loncommon(); +use Apache::lonnet; use Apache::lonmenu(); use Fcntl qw(:flock); +use Apache::lonlocal; my %FORM; @@ -54,59 +49,51 @@ sub success { my ($r, $username, $domain, $authhost,$lowerurl) = @_; my $lonids=$r->dir_config('lonIDsDir'); + my $public=($username eq 'public' && $domain eq 'public'); + # See if old ID present, if so, remove - my $filename; - opendir(DIR,$lonids); - while ($filename=readdir(DIR)) { - if ($filename=~/^$username\_\d+\_$domain\_$authhost\.id$/) { - unlink($lonids.'/'.$filename); - } - } - closedir(DIR); + my ($filename,$cookie,$userroles); + my $now=time; -# Give them a new cookie + if ($public) { + my $max_public=100; + my $oldest; + my $oldest_time=0; + for(my $next=1;$next<=$max_public;$next++) { + if (-e $lonids."/publicuser_$next.id") { + my $mtime=(stat($lonids."/publicuser_$next.id"))[9]; + if ($mtime<$oldest_time || !$oldest_time) { + $oldest_time=$mtime; + $oldest=$next; + } + } else { + $cookie="publicuser_$next"; + last; + } + } + if (!$cookie) { $cookie="publicuser_$oldest"; } + } else { + opendir(DIR,$lonids); + while ($filename=readdir(DIR)) { + if ($filename=~/^$username\_\d+\_$domain\_$authhost\.id$/) { + unlink($lonids.'/'.$filename); + } + } + closedir(DIR); - my $cookie; - my $now=time; - $cookie="$username\_$now\_$domain\_$authhost"; +# Give them a new cookie + $cookie="$username\_$now\_$domain\_$authhost"; + # Initialize roles - my $userroles=Apache::lonnet::rolesinit($domain,$username,$authhost); - + $userroles=Apache::lonnet::rolesinit($domain,$username,$authhost); + } # ------------------------------------ Check browser type and MathML capability - my @browsertype=split(/\&/,$r->dir_config("lonBrowsDet")); - my %mathcap=split(/\&/,$r->dir_config("lonMathML")); - my $httpbrowser=$ENV{"HTTP_USER_AGENT"}; - my $i; - my $clientbrowser='unknown'; - my $clientversion='0'; - my $clientmathml=''; - my $clientunicode='0'; - for ($i=0;$i<=$#browsertype;$i++) { - my ($bname,$match,$notmatch,$vreg,$minv,$univ)=split(/\:/,$browsertype[$i]); - if (($httpbrowser=~/$match/i) && ($httpbrowser!~/$notmatch/i)) { - $clientbrowser=$bname; - $httpbrowser=~/$vreg/i; - $clientversion=$1; - $clientmathml=($clientversion>=$minv); - $clientunicode=($clientversion>=$univ); - } - } - my $clientos='unknown'; - if (($httpbrowser=~/linux/i) || - ($httpbrowser=~/unix/i) || - ($httpbrowser=~/ux/i) || - ($httpbrowser=~/solaris/i)) { $clientos='unix'; } - if (($httpbrowser=~/vax/i) || - ($httpbrowser=~/vms/i)) { $clientos='vms'; } - if ($httpbrowser=~/next/i) { $clientos='next'; } - if (($httpbrowser=~/mac/i) || - ($httpbrowser=~/powerpc/i)) { $clientos='mac'; } - if ($httpbrowser=~/win/i) { $clientos='win'; } - if ($httpbrowser=~/embed/i) { $clientos='pda'; } + my ($httpbrowser,$clientbrowser,$clientversion,$clientmathml, + $clientunicode,$clientos) = &Apache::loncommon::decode_user_agent($r); # -------------------------------------- Any accessibility options to remember? if (($FORM{'interface'}) && ($FORM{'remember'} eq 'true')) { @@ -133,6 +120,15 @@ sub success { if (($userenv{'interface'}) && (!$FORM{'interface'})) { $FORM{'interface'}=$userenv{'interface'}; } + $env{'environment.remote'}=$userenv{'remote'}; + if ($userenv{'texengine'} eq 'ttm') { $clientmathml=1; } + +# --------------- Do not trust query string to be put directly into environment + foreach ('imagesuppress','appletsuppress', + 'embedsuppress','fontenhance','blackwhite', + 'interface','localpath','localres') { + $FORM{$_}=~s/[\n\r\=]//gs; + } # --------------------------------------------------------- Write first profile { @@ -152,15 +148,23 @@ sub success { print $idf "browser.mathml=$clientmathml\n"; print $idf "browser.unicode=$clientunicode\n"; print $idf "browser.os=$clientos\n"; + if ($FORM{'localpath'}) { + print $idf "browser.localpath=$FORM{'localpath'}\n"; + print $idf "browser.localres=$FORM{'localres'}\n"; + } print $idf "request.course.fn=\n"; print $idf "request.course.uri=\n"; print $idf "request.course.sec=\n"; print $idf "request.role=cm\n"; + print $idf "request.role.adv=$env{'user.adv'}\n"; print $idf "request.host=$ENV{'REMOTE_ADDR'}\n"; + if ($public) { + print $idf "environment.remote=off\n"; + } if ($FORM{'interface'}) { $FORM{'interface'}=~s/\W//gs; print $idf "browser.interface=$FORM{'interface'}\n"; - $ENV{'browser.interface'}=$FORM{'interface'}; + $env{'browser.interface'}=$FORM{'interface'}; foreach ('imagesuppress','appletsuppress', 'embedsuppress','fontenhance','blackwhite') { if (($FORM{$_} eq 'true') || @@ -172,8 +176,9 @@ sub success { if ($userroles ne '') { print $idf "$userroles"; } $idf->close(); } - $ENV{'request.role'}='cm'; - $ENV{'browser.type'}=$clientbrowser; + $env{'request.role'}='cm'; + $env{'request.role.adv'}=$env{'user.adv'}; + $env{'browser.type'}=$clientbrowser; # -------------------------------------------------------------------- Log this &Apache::lonnet::log($domain,$username,$authhost, @@ -190,34 +195,49 @@ sub success { # ------------------------------------------------------------ Get cookie ready + if ($public) { return $cookie; } $cookie="lonID=$cookie; path=/"; # -------------------------------------------------------- Menu script and info my $windowinfo=&Apache::lonmenu::open($clientos); my $startupremote=&Apache::lonmenu::startupremote($lowerurl); + my $remoteinfo=&Apache::lonmenu::load_remote_msg($lowerurl); my $setflags=&Apache::lonmenu::setflags(); my $maincall=&Apache::lonmenu::maincall(); + my $bodytag=&Apache::loncommon::bodytag('Successful Login'); + my $add=&addcontent(); + my $continuelink; + if (($env{'browser.interface'} eq 'textual') || + ($env{'environment.remote'} eq 'off')) { + $continuelink="".&mt('Continue').""; + } # ------------------------------------------------- Output for successful login $r->send_cgi_header(< 'Welcome', + 'mes' => 'Welcome to the LearningOnline Network with CAPA. Please wait while your session is being set up', + 'pro' => 'Problems', + 'log' => 'loginproblems.html', + ); $r->print(< Successful Login to the LearningOnline Network with CAPA $startupremote - +$bodytag $setflags $windowinfo -

Welcome!

-Welcome to the LearningOnline Network with CAPA. -Please wait while your session -is being set up.

-Problems?

+

$lt{'wel'}

+$lt{'mes'}.

+$lt{'pro'}?

+$remoteinfo $maincall +$continuelink ENDSUCCESS @@ -227,8 +247,10 @@ ENDSUCCESS sub failed { my ($r,$message) = @_; + my $bodytag=&Apache::loncommon::bodytag('Unsuccessful Login'); + my $add=&addcontent(); $r->send_cgi_header(<print(< Unsuccessful Login to the LearningOnline Network with CAPA - - +$bodytag

Sorry ...

-

$message to use the LearningOnline Network with CAPA

+

$message

+

Please log in again.

+

+Problems?

ENDFAILED } +# --------------------------------------------------------------------- Charset + +sub addcontent { + my $encoding=&Apache::lonlocal::current_encoding; + if ($encoding) { + return '; charset='.$encoding; + } else { + return ''; + } +} + +# ------------------------------------------------------------------ Rerouting! + +sub reroute { + my $r=shift; + my $bodytag=&Apache::loncommon::bodytag('Rerouting'); + $r->send_cgi_header(<print(< + +Rerouting Login to the LearningOnline Network with CAPA + +$bodytag +

Sorry ...

+Please log in again. + + +ENDRFAILED +} + # ---------------------------------------------------------------- Main handler sub handler { my $r = shift; +# Are we re-routing? + if (-e '/home/httpd/html/lon-status/reroute.txt') { + &reroute($r); + return OK; + } + + &Apache::lonlocal::get_language_handle($r); + +# -------------------------------- Prevent users from attempting to login twice + my %cookies=CGI::Cookie->parse($r->header_in('Cookie')); + my $lonid=$cookies{'lonID'}; + my $cookie; + if ($lonid) { + my $handle=$lonid->value; + $handle=~s/\W//g; + my $lonidsdir=$r->dir_config('lonIDsDir'); + if ((-e "$lonidsdir/$handle.id") && ($handle ne '')) { +# Indeed, a valid token is found + $r->send_cgi_header(<print(< + +Already logged in + +$bodytag +

You are already logged in

+

Please either continue the current session or +logout.

+

+Problems?

+ + +ENDFAILED + return OK; + } + } + +# ---------------------------------------------------- No valid token, continue + + my $buffer; - $r->read($buffer,$r->header_in('Content-length')); + $r->read($buffer,$r->header_in('Content-length'),0); my @pairs=split(/&/,$buffer); my $pair; my $name; my $value; undef %FORM; @@ -263,11 +364,16 @@ sub handler { $FORM{$name}=$value; } - if ((!$FORM{'uname'}) || (!$FORM{'upass'}) || (!$FORM{'udom'})) { - failed($r,'Username, password and domain need to be specified'); + if ((!$FORM{'uname'}) || (!$FORM{'upass0'}) || (!$FORM{'udom'})) { + failed($r,'Username, password and domain need to be specified.'); return OK; } + +# split user logging in and "su"-user + + ($FORM{'uname'},$FORM{'suname'})=split(/\:/,$FORM{'uname'}); $FORM{'uname'} =~ s/\W//g; + $FORM{'suname'} =~ s/\W//g; $FORM{'udom'} =~ s/\W//g; my $role = $r->dir_config('lonRole'); @@ -280,10 +386,14 @@ sub handler { $FORM{'serverid'}); if (($tmpinfo=~/^error/) || ($tmpinfo eq 'con_lost')) { - failed($r,'Login token missing, inaccessible or expired'); + failed($r,'Information needed to verify your login information is missing, inaccessible or expired.'); return OK; + } else { + unless (&Apache::lonnet::reply('tmpdel:'.$FORM{'logtoken'}, + $FORM{'serverid'}) eq 'ok') { + &failed($r,'Session could not be opened.'); + } } - my ($key,$firsturl)=split(/&/,$tmpinfo); my $keybin=pack("H16",$key); @@ -295,14 +405,17 @@ sub handler { else { $cipher=new DES $keybin; } + my $upass=''; + for (my $i=0;$i<=2;$i++) { + my $chunk= + $cipher->decrypt(unpack("a8",pack("H16",substr($FORM{'upass'.$i},0,16)))); - my $upass=$cipher->decrypt( - unpack("a8",pack("H16",substr($FORM{'upass'},0,16)))); - - $upass.=$cipher->decrypt( - unpack("a8",pack("H16",substr($FORM{'upass'},16,16)))); + $chunk.= + $cipher->decrypt(unpack("a8",pack("H16",substr($FORM{'upass'.$i},16,16)))); - $upass=substr($upass,1,ord(substr($upass,0,1))); + $chunk=substr($chunk,1,ord(substr($chunk,0,1))); + $upass.=$chunk; + } # ---------------------------------------------------------------- Authenticate my $authhost=Apache::lonnet::authenticate($FORM{'uname'}, @@ -312,15 +425,37 @@ sub handler { # --------------------------------------------------------------------- Failed? if ($authhost eq 'no_host') { - failed($r,'Username and/or password could not be authenticated'); + failed($r,'Username and/or password could not be authenticated.'); return OK; } - if (($firsturl eq '') || ($firsturl eq '/adm/logout')) { + if (($firsturl eq '') || + ($firsturl=~/^\/adm\/(logout|remote)/)) { $firsturl='/adm/roles'; } - - success($r,$FORM{'uname'},$FORM{'udom'},$authhost,$firsturl); +# --------------------------------- Are we attempting to login as somebody else? + if ($FORM{'suname'}) { +# ------------ see if the original user has enough privileges to pull this stunt + if (&Apache::lonnet::privileged($FORM{'uname'},$FORM{'udom'})) { +# ---------------------------------------------------- see if the su-user exists + unless (&Apache::lonnet::homeserver($FORM{'suname'},$FORM{'udom'}) + eq 'no_host') { + &Apache::lonnet::logthis(&Apache::lonnet::homeserver($FORM{'suname'},$FORM{'udom'})); +# ------------------------------ see if the su-user is not too highly privileged + unless (&Apache::lonnet::privileged($FORM{'suname'},$FORM{'udom'})) { +# -------------------------------------------------------- actually switch users + &Apache::lonnet::logperm('User '.$FORM{'uname'}.' at '.$FORM{'udom'}. + ' logging in as '.$FORM{'suname'}); + $FORM{'uname'}=$FORM{'suname'}; + } else { + &Apache::lonnet::logthis('Attempted switch user to privileged user'); + } + } + } else { + &Apache::lonnet::logthis('Non-privileged user attempting switch user'); + } + } + &success($r,$FORM{'uname'},$FORM{'udom'},$authhost,$firsturl); return OK; } 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.