--- loncom/auth/lonauth.pm 2015/03/06 21:56:41 1.138
+++ loncom/auth/lonauth.pm 2017/08/08 16:43:54 1.144
@@ -1,7 +1,7 @@
# The LearningOnline Network
# User Authentication Module
#
-# $Id: lonauth.pm,v 1.138 2015/03/06 21:56:41 raeburn Exp $
+# $Id: lonauth.pm,v 1.144 2017/08/08 16:43:54 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -29,11 +29,9 @@
package Apache::lonauth;
use strict;
-use LONCAPA;
+use LONCAPA qw(:DEFAULT :match);
use Apache::Constants qw(:common);
use CGI qw(:standard);
-use DynaLoader; # for Crypt::DES version
-use Crypt::DES;
use Apache::loncommon();
use Apache::lonnet;
use Apache::lonmenu();
@@ -42,6 +40,7 @@ use Fcntl qw(:flock);
use Apache::lonlocal;
use Apache::File();
use HTML::Entities;
+use Digest::MD5;
# ------------------------------------------------------------ Successful login
sub success {
@@ -72,8 +71,26 @@ sub success {
}
}
-# ------------------------------------------------------------ Get cookie ready
- $cookie="lonID=$cookie; path=/";
+# ----------------------------------------------------------- Get cookies ready
+ my ($securecookie,$defaultcookie);
+ if ($ENV{'SERVER_PORT'} == 443) {
+ $securecookie="lonID=$cookie; path=/; HttpOnly; secure";
+ my $lonidsdir=$r->dir_config('lonIDsDir');
+ if (($lonidsdir) && (-e "$lonidsdir/$cookie.id")) {
+ my $linkname=substr(Digest::MD5::md5_hex(Digest::MD5::md5_hex(time(). {}. rand(). $$)), 0, 32).'_linked';
+ if (-e "$lonidsdir/$linkname.id") {
+ unlink("$lonidsdir/$linkname.id");
+ }
+ my $made_symlink = eval { symlink("$lonidsdir/$cookie.id",
+ "$lonidsdir/$linkname.id"); 1 };
+ if ($made_symlink) {
+ $defaultcookie = "lonLinkID=$linkname; path=/; HttpOnly;";
+ &Apache::lonnet::appenv({'user.linkedenv' => "$lonidsdir/$linkname.id"});
+ }
+ }
+ } else {
+ $defaultcookie = "lonID=$cookie; path=/; HttpOnly;";
+ }
# -------------------------------------------------------- Menu script and info
my $destination = $lowerurl;
@@ -122,16 +139,42 @@ sub success {
my $header = '';
my $brcrum = [{'href' => '',
'text' => 'Successful Login'},];
+ my $args = {'bread_crumbs' => $brcrum,};
+ unless ((defined($form->{role})) || (defined($form->{symb}))) {
+ my $update=$env{'user.update.time'};
+ if (!$update) {
+ $update = $env{'user.login.time'};
+ }
+ my %roles_in_env;
+ my $showcount = &Apache::lonroles::roles_from_env(\%roles_in_env,$update);
+ if ($showcount == 1) {
+ foreach my $rolecode (keys(%roles_in_env)) {
+ my ($cid) = ($rolecode =~ m{^\Quser.role.st./\E($match_domain/$match_courseid)(?:/|$)});
+ if ($cid) {
+ my %coursedescription =
+ &Apache::lonnet::coursedescription($cid,{'one_time' => '1'});
+ if ($coursedescription{'type'} eq 'Placement') {
+ $args->{'crstype'} = 'Placement';
+ }
+ last;
+ }
+ }
+ }
+ }
my $start_page=&Apache::loncommon::start_page('Successful Login',
- $header,
- {'bread_crumbs' => $brcrum,});
+ $header,$args);
my $end_page =&Apache::loncommon::end_page();
my $continuelink=''.&mt('Continue').'';
# ------------------------------------------------- Output for successful login
&Apache::loncommon::content_type($r,'text/html');
- $r->header_out('Set-cookie' => $cookie);
+ if ($securecookie) {
+ $r->headers_out->add('Set-cookie' => $securecookie);
+ }
+ if ($defaultcookie) {
+ $r->headers_out->add('Set-cookie' => $defaultcookie);
+ }
$r->send_http_header;
my %lt=&Apache::lonlocal::texthash(
@@ -228,7 +271,6 @@ sub reroute {
sub handler {
my $r = shift;
my $londocroot = $r->dir_config('lonDocRoot');
- my $form;
# Are we re-routing?
if (-e "$londocroot/lon-status/reroute.txt") {
&reroute($r);
@@ -346,8 +388,8 @@ sub handler {
(undef,$form{'iptoken'}) = split('=',$iptokenstr);
}
- my $upass = $ENV{HTTPS} ? join("", @form{qw(upass0 upass1 upass2)})
- : decrypt($key, @form{qw(upass0 upass1 upass2)});
+ my $upass = $ENV{HTTPS} ? $form{'upass0'}
+ : &Apache::loncommon::des_decrypt($key,$form{'upass0'});
# ---------------------------------------------------------------- Authenticate
@@ -445,13 +487,25 @@ sub handler {
unless ($hosthere) {
($is_balancer,$otherserver) =
- &Apache::lonnet::check_loadbalancing($form{'uname'},$form{'udom'});
+ &Apache::lonnet::check_loadbalancing($form{'uname'},$form{'udom'},'login');
+ if ($is_balancer) {
+ if ($otherserver eq '') {
+ my $lowest_load;
+ ($otherserver,undef,undef,undef,$lowest_load) = &Apache::lonnet::choose_server($form{'udom'});
+ if ($lowest_load > 100) {
+ $otherserver = &Apache::lonnet::spareserver($lowest_load,$lowest_load,1,$form{'udom'});
+ }
+ }
+ if ($otherserver ne '') {
+ my @hosts = &Apache::lonnet::current_machine_ids();
+ if (grep(/^\Q$otherserver\E$/,@hosts)) {
+ $hosthere = $otherserver;
+ }
+ }
+ }
}
- if ($is_balancer) {
- if (!$otherserver) {
- ($otherserver) = &Apache::lonnet::choose_server($form{'udom'});
- }
+ if (($is_balancer) && (!$hosthere)) {
if ($otherserver) {
&success($r,$form{'uname'},$form{'udom'},$authhost,'noredirect',undef,
\%form);
@@ -519,40 +573,15 @@ sub handler {
return OK;
}
}
+ if (($is_balancer) && ($hosthere)) {
+ $form{'noloadbalance'} = $hosthere;
+ }
&success($r,$form{'uname'},$form{'udom'},$authhost,$firsturl,undef,
\%form);
return OK;
}
}
-sub decrypt {
- my ($key, @chunks) = @_;
-
- my $keybin = pack("H16",$key);
-
- my $cipher;
- if ($Crypt::DES::VERSION >= 2.03) {
- $cipher = new Crypt::DES $keybin;
- } else {
- $cipher = new DES $keybin;
- }
-
- my $upass='';
- for (my $i=0;$i<=2;$i++) {
- my $chunk =
- $cipher->decrypt(
- unpack("a8",pack("H16",substr($chunks[$i],0,16))));
-
- $chunk .=
- $cipher->decrypt(
- unpack("a8",pack("H16",substr($chunks[$i],16,16))));
-
- $chunk = substr($chunk,1,ord(substr($chunk,0,1)));
- $upass .= $chunk;
- }
- return $upass;
-}
-
sub check_can_host {
my ($r,$form,$authhost,$domdesc) = @_;
return unless (ref($form) eq 'HASH');