[LON-CAPA-cvs] cvs: loncom / lond /interface domainprefs.pm /lonnet/perl lonnet.pm
raeburn
raeburn at source.lon-capa.org
Mon Mar 13 14:30:12 EDT 2017
raeburn Mon Mar 13 18:30:12 2017 EDT
Modified files:
/loncom lond
/loncom/interface domainprefs.pm
/loncom/lonnet/perl lonnet.pm
Log:
- Domain configuration for internally authenticated users.
- (a) Option to switch from crypt to bcrypt automatically when user is authenticated.
- (b) Option to set bcrypt cost.
- (c) Option to compare bcrypt cost for user with current domain config
when user is authenticated.
Defaults are: (a) No, (b) 10; (c) No
-------------- next part --------------
Index: loncom/lond
diff -u loncom/lond:1.532 loncom/lond:1.533
--- loncom/lond:1.532 Tue Feb 28 05:42:06 2017
+++ loncom/lond Mon Mar 13 18:30:02 2017
@@ -2,7 +2,7 @@
# The LearningOnline Network
# lond "LON Daemon" Server (port "LOND" 5663)
#
-# $Id: lond,v 1.532 2017/02/28 05:42:06 raeburn Exp $
+# $Id: lond,v 1.533 2017/03/13 18:30:02 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -65,7 +65,7 @@
my $status='';
my $lastlog='';
-my $VERSION='$Revision: 1.532 $'; #' stupid emacs
+my $VERSION='$Revision: 1.533 $'; #' stupid emacs
my $remoteVERSION;
my $currenthostid="default";
my $currentdomainid;
@@ -2323,12 +2323,8 @@
my $plainsalt = substr($rest[1],0,22);
$salt = Crypt::Eksblowfish::Bcrypt::de_base64($plainsalt);
} else {
- my $defaultcost;
- my %domconfig =
- &Apache::lonnet::get_dom('configuration',['password'],$domain);
- if (ref($domconfig{'password'}) eq 'HASH') {
- $defaultcost = $domconfig{'password'}{'cost'};
- }
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($domain);
+ my $defaultcost = $domdefaults{'intauth_cost'};
if (($defaultcost eq '') || ($defaultcost =~ /D/)) {
$cost = 10;
} else {
@@ -7372,7 +7368,6 @@
."Attempted insecure connection disallowed </font>");
close $client;
$clientok = 0;
-
}
}
} else {
@@ -7381,7 +7376,6 @@
."$clientip failed to initialize: >$remotereq< </font>");
&status('No init '.$clientip);
}
-
} else {
&logthis(
"<font color='blue'>WARNING: Unknown client $clientip</font>");
@@ -7618,15 +7612,25 @@
# domain - domain of the user.
# name - User's name.
# contents - New contents of the file.
+# saveold - (optional). If true save old file in a passwd.bak file.
# Returns:
# 0 - Failed.
# 1 - Success.
#
sub rewrite_password_file {
- my ($domain, $user, $contents) = @_;
+ my ($domain, $user, $contents, $saveold) = @_;
my $file = &password_filename($domain, $user);
if (defined $file) {
+ if ($saveold) {
+ my $bakfile = $file.'.bak';
+ if (CopyFile($file,$bakfile)) {
+ chmod(0400,$bakfile);
+ &logthis("Old password saved in passwd.bak for internally authenticated user: $user:$domain");
+ } else {
+ &logthis("Failed to save old password in passwd.bak for internally authenticated user: $user:$domain");
+ }
+ }
my $pf = IO::File->new(">$file");
if($pf) {
print $pf "$contents\n";
@@ -7717,20 +7721,27 @@
$contentpwd = $domdefaults{'auth_arg_def'};
}
}
- }
+ }
if ($howpwd ne 'nouser') {
if($howpwd eq "internal") { # Encrypted is in local password file.
if (length($contentpwd) == 13) {
$validated = (crypt($password,$contentpwd) eq $contentpwd);
if ($validated) {
- my $ncpass = &hash_passwd($domain,$password);
- if (&rewrite_password_file($domain,$user,"$howpwd:$ncpass")) {
- &update_passwd_history($user,$domain,$howpwd,'conversion');
- &logthis("Validated password hashed with bcrypt for $user:$domain");
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($domain);
+ if ($domdefaults{'intauth_switch'}) {
+ my $ncpass = &hash_passwd($domain,$password);
+ my $saveold;
+ if ($domdefaults{'intauth_switch'} == 2) {
+ $saveold = 1;
+ }
+ if (&rewrite_password_file($domain,$user,"$howpwd:$ncpass",$saveold)) {
+ &update_passwd_history($user,$domain,$howpwd,'conversion');
+ &logthis("Validated password hashed with bcrypt for $user:$domain");
+ }
}
}
} else {
- $validated = &check_internal_passwd($password,$contentpwd,$domain);
+ $validated = &check_internal_passwd($password,$contentpwd,$domain,$user);
}
}
elsif ($howpwd eq "unix") { # User is a normal unix user.
@@ -7800,24 +7811,35 @@
}
sub check_internal_passwd {
- my ($plainpass,$stored,$domain) = @_;
+ my ($plainpass,$stored,$domain,$user) = @_;
my (undef,$method, at rest) = split(/!/,$stored);
- if ($method eq "bcrypt") {
+ if ($method eq 'bcrypt') {
my $result = &hash_passwd($domain,$plainpass, at rest);
if ($result ne $stored) {
return 0;
}
- # Upgrade to a larger number of rounds if necessary
- my $defaultcost;
- my %domconfig =
- &Apache::lonnet::get_dom('configuration',['password'],$domain);
- if (ref($domconfig{'password'}) eq 'HASH') {
- $defaultcost = $domconfig{'password'}{'cost'};
- }
- if (($defaultcost eq '') || ($defaultcost =~ /D/)) {
- $defaultcost = 10;
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($domain);
+ if ($domdefaults{'intauth_check'}) {
+ # Upgrade to a larger number of rounds if necessary
+ my $defaultcost = $domdefaults{'intauth_cost'};
+ if (($defaultcost eq '') || ($defaultcost =~ /D/)) {
+ $defaultcost = 10;
+ }
+ if (int($rest[0])<int($defaultcost)) {
+ if ($domdefaults{'intauth_check'} == 1) {
+ my $ncpass = &hash_passwd($domain,$plainpass);
+ if (&rewrite_password_file($domain,$user,"internal:$ncpass")) {
+ &update_passwd_history($user,$domain,'internal','update cost');
+ &logthis("Validated password hashed with bcrypt for $user:$domain");
+ }
+ return 1;
+ } elsif ($domdefaults{'intauth_check'} == 2) {
+ return 0;
+ }
+ }
+ } else {
+ return 1;
}
- return 1 unless($rest[0]<$defaultcost);
}
return 0;
}
Index: loncom/interface/domainprefs.pm
diff -u loncom/interface/domainprefs.pm:1.293 loncom/interface/domainprefs.pm:1.294
--- loncom/interface/domainprefs.pm:1.293 Sat Feb 25 20:30:52 2017
+++ loncom/interface/domainprefs.pm Mon Mar 13 18:30:07 2017
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
-# $Id: domainprefs.pm,v 1.293 2017/02/25 20:30:52 raeburn Exp $
+# $Id: domainprefs.pm,v 1.294 2017/03/13 18:30:07 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -265,6 +265,8 @@
help => 'Domain_Configuration_LangTZAuth',
header => [{col1 => 'Setting',
col2 => 'Value'},
+ {col1 => 'Internal Authentication',
+ col2 => 'Value'},
{col1 => 'Institutional user types',
col2 => 'Assignable to e-mail usernames'}],
print => \&print_defaults,
@@ -808,7 +810,7 @@
if (($action eq 'autoupdate') || ($action eq 'usercreation') ||
($action eq 'selfcreation') || ($action eq 'selfenrollment') ||
($action eq 'usersessions') || ($action eq 'coursecategories') ||
- ($action eq 'trust') || ($action eq 'contacts')) {
+ ($action eq 'trust') || ($action eq 'contacts') || ($action eq 'defaults')) {
if ($action eq 'coursecategories') {
$output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);
$colspan = ' colspan="2"';
@@ -6131,7 +6133,10 @@
sub print_defaults {
my ($position,$dom,$settings,$rowtotal) = @_;
my $rownum = 0;
- my ($datatable,$css_class);
+ my ($datatable,$css_class,$titles);
+ unless ($position eq 'bottom') {
+ $titles = &defaults_titles($dom);
+ }
if ($position eq 'top') {
my @items = ('auth_def','auth_arg_def','lang_def','timezone_def',
'datelocale_def','portal_def');
@@ -6144,7 +6149,6 @@
$defaults{$item} = $domdefaults{$item};
}
}
- my $titles = &defaults_titles($dom);
foreach my $item (@items) {
if ($rownum%2) {
$css_class = '';
@@ -6192,8 +6196,87 @@
$datatable .= '</td></tr>';
$rownum ++;
}
+ } elsif ($position eq 'middle') {
+ my @items = ('intauth_cost','intauth_check','intauth_switch');
+ my %defaults;
+ if (ref($settings) eq 'HASH') {
+ %defaults = %{$settings};
+ if ($defaults{'intauth_cost'} !~ /^\d+$/) {
+ $defaults{'intauth_cost'} = 10;
+ }
+ if ($defaults{'intauth_check'} !~ /^(0|1|2)$/) {
+ $defaults{'intauth_check'} = 0;
+ }
+ if ($defaults{'intauth_switch'} !~ /^(0|1|2)$/) {
+ $defaults{'intauth_switch'} = 0;
+ }
+ } else {
+ %defaults = (
+ 'intauth_cost' => 10,
+ 'intauth_check' => 0,
+ 'intauth_switch' => 0,
+ );
+ }
+ foreach my $item (@items) {
+ if ($rownum%2) {
+ $css_class = '';
+ } else {
+ $css_class = ' class="LC_odd_row" ';
+ }
+ $datatable .= '<tr'.$css_class.'>'.
+ '<td><span class="LC_nobreak">'.$titles->{$item}.
+ '</span></td><td class="LC_left_item" colspan="3">';
+ if ($item eq 'intauth_switch') {
+ my @options = (0,1,2);
+ my %optiondesc = &Apache::lonlocal::texthash (
+ 0 => 'No',
+ 1 => 'Yes',
+ 2 => 'Yes, and copy existing passwd file to passwd.bak file',
+ );
+ $datatable .= '<table width="100%">';
+ foreach my $option (@options) {
+ my $checked = ' ';
+ if ($defaults{$item} eq $option) {
+ $checked = ' checked="checked"';
+ }
+ $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.
+ '<label><input type="radio" name="'.$item.
+ '" value="'.$option.'"'.$checked.' />'.
+ $optiondesc{$option}.'</label></span></td></tr>';
+ }
+ $datatable .= '</table>';
+ } elsif ($item eq 'intauth_check') {
+ my @options = (0,1,2);
+ my %optiondesc = &Apache::lonlocal::texthash (
+ 0 => 'No',
+ 1 => 'Yes, allow login then update passwd file using default cost (if higher)',
+ 2 => 'Yes, disallow login if stored cost is less than domain default',
+ );
+ $datatable .= '<table wisth="100%">';
+ foreach my $option (@options) {
+ my $checked = ' ';
+ my $onclick;
+ if ($defaults{$item} eq $option) {
+ $checked = ' checked="checked"';
+ }
+ if ($option == 2) {
+ $onclick = ' onclick="javascript:warnIntAuth(this);"';
+ }
+ $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.
+ '<label><input type="radio" name="'.$item.
+ '" value="'.$option.'"'.$checked.$onclick.' />'.
+ $optiondesc{$option}.'</label></span></td></tr>';
+ }
+ $datatable .= '</table>';
+ } else {
+ $datatable .= '<input type="text" name="'.$item.'" value="'.
+ $defaults{$item}.'" size="3" onblur="javascript:warnIntAuth(this);" />';
+ }
+ $datatable .= '</td></tr>';
+ $rownum ++;
+ }
} else {
- my (%defaults);
+ my %defaults;
if (ref($settings) eq 'HASH') {
if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH') &&
(ref($settings->{'inststatusguest'}) eq 'ARRAY')) {
@@ -6288,6 +6371,9 @@
'timezone_def' => 'Default timezone',
'datelocale_def' => 'Default locale for dates',
'portal_def' => 'Portal/Default URL',
+ 'intauth_cost' => 'Encryption cost for bcrypt (positive integer)',
+ 'intauth_check' => 'Check bcrypt cost if authenticated',
+ 'intauth_switch' => 'Existing crypt-based switched to bcrypt on authentication',
);
if ($dom) {
my $uprimary_id = &Apache::lonnet::domain($dom,'primary');
@@ -6823,7 +6909,35 @@
sub defaults_javascript {
my ($settings) = @_;
- return unless (ref($settings) eq 'HASH');
+ my $intauthcheck = &mt('Warning: disallowing login for an authenticated user if the stored cost is less than the default will require a password reset by/for the user.');
+ my $intauthcost = &mt('Warning: bcrypt encryption cost for internal authentication must be an integer.');
+ &js_escape(\$intauthcheck);
+ &js_escape(\$intauthcost);
+ my $intauthjs = <<"ENDSCRIPT";
+
+function warnIntAuth(field) {
+ if (field.name == 'intauth_check') {
+ if (field.value == '2') {
+ alert('$intauthcheck');
+ }
+ }
+ if (field.name == 'intauth_cost') {
+ field.value.replace(/\s/g,'');
+ if (field.value != '') {
+ var regexdigit=/^\\d+\$/;
+ if (!regexdigit.test(field.value)) {
+ alert('$intauthcost');
+ }
+ }
+ }
+ return;
+}
+
+ENDSCRIPT
+
+ if (ref($settings) ne 'HASH') {
+ return &Apache::lonhtmlcommon::scripttag($intauthjs);
+ }
if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {
my $maxnum = scalar(@{$settings->{'inststatusorder'}});
if ($maxnum eq '') {
@@ -6877,10 +6991,14 @@
return;
}
+$intauthjs
+
// ]]>
</script>
ENDSCRIPT
+ } else {
+ return &Apache::lonhtmlcommon::scripttag($intauthjs);
}
}
@@ -11734,7 +11852,8 @@
my ($dom,$lastactref,%domconfig) = @_;
my ($resulttext,$mailmsgtxt,%newvalues,%changes, at errors);
my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
- my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def','portal_def');
+ my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def',
+ 'portal_def','intauth_cost','intauth_check','intauth_switch');
my @authtypes = ('internal','krb4','krb5','localauth');
foreach my $item (@items) {
$newvalues{$item} = $env{'form.'.$item};
@@ -11776,6 +11895,24 @@
push(@errors,$item);
}
}
+ } elsif ($item eq 'intauth_cost') {
+ if ($newvalues{$item} ne '') {
+ if ($newvalues{$item} =~ /\D/) {
+ push(@errors,$item);
+ }
+ }
+ } elsif ($item eq 'intauth_check') {
+ if ($newvalues{$item} ne '') {
+ unless ($newvalues{$item} =~ /^(0|1|2)$/) {
+ push(@errors,$item);
+ }
+ }
+ } elsif ($item eq 'intauth_switch') {
+ if ($newvalues{$item} ne '') {
+ unless ($newvalues{$item} =~ /^(0|1|2)$/) {
+ push(@errors,$item);
+ }
+ }
}
if (grep(/^\Q$item\E$/, at errors)) {
$newvalues{$item} = $domdefaults{$item};
@@ -11930,6 +12067,28 @@
localauth => 'loc',
);
$value = $authnames{$shortauth{$value}};
+ } elsif ($item eq 'intauth_switch') {
+ my %optiondesc = &Apache::lonlocal::texthash (
+ 0 => 'No',
+ 1 => 'Yes',
+ 2 => 'Yes, and copy existing passwd file to passwd.bak file',
+ );
+ if ($value =~ /^(0|1|2)$/) {
+ $value = $optiondesc{$value};
+ } else {
+ $value = &mt('none -- defaults to No');
+ }
+ } elsif ($item eq 'intauth_check') {
+ my %optiondesc = &Apache::lonlocal::texthash (
+ 0 => 'No',
+ 1 => 'Yes, allow login then update passwd file using default cost (if higher)',
+ 2 => 'Yes, disallow login if stored cost is less than domain default',
+ );
+ if ($value =~ /^(0|1|2)$/) {
+ $value = $optiondesc{$value};
+ } else {
+ $value = &mt('none -- defaults to No');
+ }
}
$resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$title->{$item},$value).'</li>';
$mailmsgtext .= "$title->{$item} set to $value\n";
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.1339 loncom/lonnet/perl/lonnet.pm:1.1340
--- loncom/lonnet/perl/lonnet.pm:1.1339 Tue Feb 28 05:42:12 2017
+++ loncom/lonnet/perl/lonnet.pm Mon Mar 13 18:30:12 2017
@@ -1,7 +1,7 @@
# The LearningOnline Network
# TCP networking package
#
-# $Id: lonnet.pm,v 1.1339 2017/02/28 05:42:12 raeburn Exp $
+# $Id: lonnet.pm,v 1.1340 2017/03/13 18:30:12 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -2269,6 +2269,9 @@
$domdefaults{'timezone_def'} = $domconfig{'defaults'}{'timezone_def'};
$domdefaults{'datelocale_def'} = $domconfig{'defaults'}{'datelocale_def'};
$domdefaults{'portal_def'} = $domconfig{'defaults'}{'portal_def'};
+ $domdefaults{'intauth_cost'} = $domconfig{'defaults'}{'intauth_cost'};
+ $domdefaults{'intauth_switch'} = $domconfig{'defaults'}{'intauth_switch'};
+ $domdefaults{'intauth_check'} = $domconfig{'defaults'}{'intauth_check'};
} else {
$domdefaults{'lang_def'} = &domain($domain,'lang_def');
$domdefaults{'auth_def'} = &domain($domain,'auth_def');
More information about the LON-CAPA-cvs
mailing list