--- loncom/lond 2007/04/04 00:49:13 1.372
+++ loncom/lond 2008/03/08 03:17:38 1.398
@@ -2,7 +2,7 @@
# The LearningOnline Network
# lond "LON Daemon" Server (port "LOND" 5663)
#
-# $Id: lond,v 1.372 2007/04/04 00:49:13 albertel Exp $
+# $Id: lond,v 1.398 2008/03/08 03:17:38 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -33,7 +33,6 @@ use strict;
use lib '/home/httpd/lib/perl/';
use LONCAPA;
use LONCAPA::Configuration;
-use Apache::lonnet;
use IO::Socket;
use IO::File;
@@ -53,13 +52,14 @@ use File::Find;
use LONCAPA::lonlocal;
use LONCAPA::lonssl;
use Fcntl qw(:flock);
+use Apache::lonnet;
my $DEBUG = 0; # Non zero to enable debug log entries.
my $status='';
my $lastlog='';
-my $VERSION='$Revision: 1.372 $'; #' stupid emacs
+my $VERSION='$Revision: 1.398 $'; #' stupid emacs
my $remoteVERSION;
my $currenthostid="default";
my $currentdomainid;
@@ -69,7 +69,6 @@ my $clientip; # IP address of client.
my $clientname; # LonCAPA name of client.
my $server;
-my $thisserver; # DNS of us.
my $keymode;
@@ -136,7 +135,7 @@ my @adderrors = ("ok",
"lcuseradd Unable to make www member of users's group",
"lcuseradd Unable to su to root",
"lcuseradd Unable to set password",
- "lcuseradd Usrname has invalid characters",
+ "lcuseradd Username has invalid characters",
"lcuseradd Password has an invalid character",
"lcuseradd User already exists",
"lcuseradd Could not add user.",
@@ -172,19 +171,16 @@ sub ResetStatistics {
# $Socket - Socket open on client.
# $initcmd - The full text of the init command.
#
-# Implicit inputs:
-# $thisserver - Our DNS name.
-#
# Returns:
# IDEA session key on success.
# undef on failure.
#
sub LocalConnection {
my ($Socket, $initcmd) = @_;
- Debug("Attempting local connection: $initcmd client: $clientip me: $thisserver");
+ Debug("Attempting local connection: $initcmd client: $clientip");
if($clientip ne "127.0.0.1") {
&logthis(' LocalConnection rejecting non local: '
- ."$clientip ne $thisserver ");
+ ."$clientip ne 127.0.0.1 ");
close $Socket;
return undef;
} else {
@@ -1000,7 +996,7 @@ sub ping_handler {
my ($cmd, $tail, $client) = @_;
Debug("$cmd $tail $client .. $currenthostid:");
- Reply( $client,"$currenthostid\n","$cmd:$tail");
+ Reply( $client,\$currenthostid,"$cmd:$tail");
return 1;
}
@@ -1070,7 +1066,7 @@ sub establish_key_handler {
$key=substr($key,0,32);
my $cipherkey=pack("H32",$key);
$cipher=new IDEA $cipherkey;
- &Reply($replyfd, "$buildkey\n", "$cmd:$tail");
+ &Reply($replyfd, \$buildkey, "$cmd:$tail");
return 1;
@@ -1107,7 +1103,7 @@ sub load_handler {
my $loadpercent=100*$loadavg/$perlvar{'lonLoadLim'};
- &Reply( $replyfd, "$loadpercent\n", "$cmd:$tail");
+ &Reply( $replyfd, \$loadpercent, "$cmd:$tail");
return 1;
}
@@ -1137,7 +1133,7 @@ sub user_load_handler {
my ($cmd, $tail, $replyfd) = @_;
my $userloadpercent=&Apache::lonnet::userload();
- &Reply($replyfd, "$userloadpercent\n", "$cmd:$tail");
+ &Reply($replyfd, \$userloadpercent, "$cmd:$tail");
return 1;
}
@@ -1180,7 +1176,7 @@ sub user_authorization_type {
} else {
$type .= ':';
}
- &Reply( $replyfd, "$type\n", $userinput);
+ &Reply( $replyfd, \$type, $userinput);
}
return 1;
@@ -1216,7 +1212,7 @@ sub push_file_handler {
# process making the request.
my $reply = &PushFile($userinput);
- &Reply($client, "$reply\n", $userinput);
+ &Reply($client, \$reply, $userinput);
} else {
&Failure( $client, "refused\n", $userinput);
@@ -1268,7 +1264,7 @@ sub du_handler {
chdir($ududir);
find($code,$ududir);
$total_size=int($total_size/1024);
- &Reply($client,"$total_size\n","$cmd:$ududir");
+ &Reply($client,\$total_size,"$cmd:$ududir");
} else {
&Failure($client, "bad_directory:$ududir\n","$cmd:$ududir");
}
@@ -1337,7 +1333,7 @@ sub ls_handler {
$ulsout='no_such_dir';
}
if ($ulsout eq '') { $ulsout='empty'; }
- &Reply($client, "$ulsout\n", $userinput); # This supports debug logging.
+ &Reply($client, \$ulsout, $userinput); # This supports debug logging.
return 1;
@@ -1406,7 +1402,7 @@ sub ls2_handler {
$ulsout='no_such_dir';
}
if ($ulsout eq '') { $ulsout='empty'; }
- &Reply($client, "$ulsout\n", $userinput); # This supports debug logging.
+ &Reply($client, \$ulsout, $userinput); # This supports debug logging.
return 1;
}
®ister_handler("ls2", \&ls2_handler, 0, 1, 0);
@@ -1434,7 +1430,7 @@ sub reinit_process_handler {
if(&ValidManager($cert)) {
chomp($userinput);
my $reply = &ReinitProcess($userinput);
- &Reply( $client, "$reply\n", $userinput);
+ &Reply( $client, \$reply, $userinput);
} else {
&Failure( $client, "refused\n", $userinput);
}
@@ -1518,13 +1514,15 @@ sub authenticate_handler {
# udom - User's domain.
# uname - Username.
# upass - User's password.
+ # checkdefauth - Pass to validate_user() to try authentication
+ # with default auth type(s) if no user account.
- my ($udom,$uname,$upass)=split(/:/,$tail);
+ my ($udom, $uname, $upass, $checkdefauth)=split(/:/,$tail);
&Debug(" Authenticate domain = $udom, user = $uname, password = $upass");
chomp($upass);
$upass=&unescape($upass);
- my $pwdcorrect = &validate_user($udom, $uname, $upass);
+ my $pwdcorrect = &validate_user($udom,$uname,$upass,$checkdefauth);
if($pwdcorrect) {
&Reply( $client, "authorized\n", $userinput);
#
@@ -1609,7 +1607,7 @@ sub change_password_handler {
my $result = &change_unix_password($uname, $npass);
&logthis("Result of password change for $uname: ".
$result);
- &Reply($client, "$result\n", $userinput);
+ &Reply($client, \$result, $userinput);
} else {
# this just means that the current password mode is not
# one we know how to change (e.g the kerberos auth modes or
@@ -1670,9 +1668,9 @@ sub add_user_handler {
}
unless ($fperror) {
my $result=&make_passwd_file($uname, $umode,$npass, $passfilename);
- &Reply($client, $result, $userinput); #BUGBUG - could be fail
+ &Reply($client,\$result, $userinput); #BUGBUG - could be fail
} else {
- &Failure($client, "$fperror\n", $userinput);
+ &Failure($client, \$fperror, $userinput);
}
}
umask($oldumask);
@@ -1739,9 +1737,9 @@ sub change_authentication_handler {
my $result = &change_unix_password($uname, $npass);
&logthis("Result of password change for $uname: ".$result);
if ($result eq "ok") {
- &Reply($client, "$result\n")
+ &Reply($client, \$result);
} else {
- &Failure($client, "$result\n");
+ &Failure($client, \$result);
}
} else {
my $result=&make_passwd_file($uname, $umode,$npass,$passfilename);
@@ -1760,7 +1758,7 @@ sub change_authentication_handler {
&manage_permissions("/$udom/_au", $udom, $uname, "$umode:");
}
}
- &Reply($client, $result, $userinput);
+ &Reply($client, \$result, $userinput);
}
@@ -2099,6 +2097,37 @@ sub rename_user_file_handler {
®ister_handler("renameuserfile", \&rename_user_file_handler, 0,1,0);
#
+# Checks if the specified user has an active session on the server
+# return ok if so, not_found if not
+#
+# Parameters:
+# cmd - The request keyword that dispatched to tus.
+# tail - The tail of the request (colon separated parameters).
+# client - Filehandle open on the client.
+# Return:
+# 1.
+sub user_has_session_handler {
+ my ($cmd, $tail, $client) = @_;
+
+ my ($udom, $uname) = map { &unescape($_) } (split(/:/, $tail));
+
+ &logthis("Looking for $udom $uname");
+ opendir(DIR,$perlvar{'lonIDsDir'});
+ my $filename;
+ while ($filename=readdir(DIR)) {
+ last if ($filename=~/^\Q$uname\E_\d+_\Q$udom\E_/);
+ }
+ if ($filename) {
+ &Reply($client, "ok\n", "$cmd:$tail");
+ } else {
+ &Failure($client, "not_found\n", "$cmd:$tail");
+ }
+ return 1;
+
+}
+®ister_handler("userhassession", \&user_has_session_handler, 0,1,0);
+
+#
# Authenticate access to a user file by checking that the token the user's
# passed also exists in their session file
#
@@ -2114,24 +2143,24 @@ sub token_auth_user_file_handler {
my ($fname, $session) = split(/:/, $tail);
chomp($session);
- my $reply="non_auth\n";
+ my $reply="non_auth";
my $file = $perlvar{'lonIDsDir'}.'/'.$session.'.id';
if (open(ENVIN,"$file")) {
flock(ENVIN,LOCK_SH);
tie(my %disk_env,'GDBM_File',"$file",&GDBM_READER(),0640);
if (exists($disk_env{"userfile.$fname"})) {
- $reply="ok\n";
+ $reply="ok";
} else {
foreach my $envname (keys(%disk_env)) {
if ($envname=~ m|^userfile\.\Q$fname\E|) {
- $reply="ok\n";
+ $reply="ok";
last;
}
}
}
untie(%disk_env);
close(ENVIN);
- &Reply($client, $reply, "$cmd:$tail");
+ &Reply($client, \$reply, "$cmd:$tail");
} else {
&Failure($client, "invalid_token\n", "$cmd:$tail");
}
@@ -2191,13 +2220,13 @@ sub subscribe_handler {
®ister_handler("sub", \&subscribe_handler, 0, 1, 0);
#
-# Determine the version of a resource (?) Or is it return
-# the top version of the resource? Not yet clear from the
-# code in currentversion.
+# Determine the latest version of a resource (it looks for the highest
+# past version and then returns that +1)
#
# Parameters:
# $cmd - The command that got us here.
# $tail - Tail of the command (remaining parameters).
+# (Should consist of an absolute path to a file)
# $client - File descriptor connected to client.
# Returns
# 0 - Requested to exit, caller should shut down.
@@ -2555,10 +2584,11 @@ sub get_profile_entry {
my ($udom,$uname,$namespace,$what) = split(/:/,$tail);
chomp($what);
+
my $replystring = read_profile($udom, $uname, $namespace, $what);
my ($first) = split(/:/,$replystring);
if($first ne "error") {
- &Reply($client, "$replystring\n", $userinput);
+ &Reply($client, \$replystring, $userinput);
} else {
&Failure($client, $replystring." while attempting get\n", $userinput);
}
@@ -2698,7 +2728,7 @@ sub get_profile_keys {
}
if (&untie_user_hash($hashref)) {
$qresult=~s/\&$//;
- &Reply($client, "$qresult\n", $userinput);
+ &Reply($client, \$qresult, $userinput);
} else {
&Failure($client, "error: ".($!+0)." untie(GDBM) Failed ".
"while attempting keys\n", $userinput);
@@ -2768,7 +2798,7 @@ sub dump_profile_database {
}
}
chop($qresult);
- &Reply($client , "$qresult\n", $userinput);
+ &Reply($client , \$qresult, $userinput);
} else {
&Failure( $client, "error: ".($!+0)." untie(GDBM) Failed ".
"while attempting currentdump\n", $userinput);
@@ -2851,7 +2881,7 @@ sub dump_with_regexp {
}
if (&untie_user_hash($hashref)) {
chop($qresult);
- &Reply($client, "$qresult\n", $userinput);
+ &Reply($client, \$qresult, $userinput);
} else {
&Failure( $client, "error: ".($!+0)." untie(GDBM) Failed ".
"while attempting dump\n", $userinput);
@@ -3059,7 +3089,7 @@ sub restore_handler {
}
if (&untie_user_hash($hashref)) {
$qresult=~s/\&$//;
- &Reply( $client, "$qresult\n", $userinput);
+ &Reply( $client, \$qresult, $userinput);
} else {
&Failure($client, "error: ".($!+0)." untie(GDBM) Failed ".
"while attempting restore\n", $userinput);
@@ -3140,7 +3170,7 @@ sub retrieve_chat_handler {
$reply.=&escape($_).':';
}
$reply=~s/\:$//;
- &Reply($client, $reply."\n", $userinput);
+ &Reply($client, \$reply, $userinput);
return 1;
@@ -3277,6 +3307,22 @@ sub put_course_id_handler {
foreach my $pair (@pairs) {
my ($key,$courseinfo) = split(/=/,$pair,2);
$courseinfo =~ s/=/:/g;
+ if (defined($hashref->{$key})) {
+ my $value = &Apache::lonnet::thaw_unescape($hashref->{$key});
+ if (ref($value) eq 'HASH') {
+ my @items = ('description','inst_code','owner','type');
+ my @new_items = split(/:/,$courseinfo,-1);
+ my %storehash;
+ for (my $i=0; $i<@new_items; $i++) {
+ $storehash{$items[$i]} = &unescape($new_items[$i]);
+ }
+ $hashref->{$key} =
+ &Apache::lonnet::freeze_escape(\%storehash);
+ my $unesc_key = &unescape($key);
+ $hashref->{&escape('lasttime:'.$unesc_key)} = $now;
+ next;
+ }
+ }
my @current_items = split(/:/,$hashref->{$key},-1);
shift(@current_items); # remove description
pop(@current_items); # remove last access
@@ -3293,7 +3339,7 @@ sub put_course_id_handler {
}
}
}
- $hashref->{$key}=$courseinfo.':'.$now;
+ $hashref->{$key}=$courseinfo.':'.$now;
}
if (&untie_domain_hash($hashref)) {
&Reply( $client, "ok\n", $userinput);
@@ -3307,12 +3353,54 @@ sub put_course_id_handler {
." tie(GDBM) Failed ".
"while attempting courseidput\n", $userinput);
}
-
return 1;
}
®ister_handler("courseidput", \&put_course_id_handler, 0, 1, 0);
+sub put_course_id_hash_handler {
+ my ($cmd, $tail, $client) = @_;
+ my $userinput = "$cmd:$tail";
+ my ($udom,$mode,$what) = split(/:/, $tail,3);
+ chomp($what);
+ my $now=time;
+ my @pairs=split(/\&/,$what);
+ my $hashref = &tie_domain_hash($udom, "nohist_courseids", &GDBM_WRCREAT());
+ if ($hashref) {
+ foreach my $pair (@pairs) {
+ my ($key,$value)=split(/=/,$pair);
+ my $unesc_key = &unescape($key);
+ if ($mode ne 'timeonly') {
+ if (!defined($hashref->{&escape('lasttime:'.$unesc_key)})) {
+ my $curritems = &Apache::lonnet::thaw_unescape($key);
+ if (ref($curritems) ne 'HASH') {
+ my @current_items = split(/:/,$hashref->{$key},-1);
+ my $lasttime = pop(@current_items);
+ $hashref->{&escape('lasttime:'.$unesc_key)} = $lasttime;
+ } else {
+ $hashref->{&escape('lasttime:'.$unesc_key)} = '';
+ }
+ }
+ $hashref->{$key} = $value;
+ }
+ if ($mode ne 'notime') {
+ $hashref->{&escape('lasttime:'.$unesc_key)} = $now;
+ }
+ }
+ if (&untie_domain_hash($hashref)) {
+ &Reply($client, "ok\n", $userinput);
+ } else {
+ &Failure($client, "error: ".($!+0)." untie(GDBM) Failed ".
+ "while attempting courseidputhash\n", $userinput);
+ }
+ } else {
+ &Failure( $client, "error: ".($!+0)." tie(GDBM) Failed ".
+ "while attempting courseidputhash\n", $userinput);
+ }
+ return 1;
+}
+®ister_handler("courseidputhash", \&put_course_id_hash_handler, 0, 1, 0);
+
# Retrieves the value of a course id resource keyword pattern
# defined since a starting date. Both the starting date and the
# keyword pattern are optional. If the starting date is not supplied it
@@ -3339,6 +3427,15 @@ sub put_course_id_handler {
# owner matches the supplied username and/or domain
# will be returned. Pre-2.2.0 legacy entries from
# nohist_courseiddump will only contain usernames.
+# type - optional parameter for selection
+# regexp_ok - if true, allow the supplied institutional code
+# filter to behave as a regular expression.
+# rtn_as_hash - whether to return the information available for
+# each matched item as a frozen hash of all
+# key, value pairs in the item's hash, or as a
+# colon-separated list of (in order) description,
+# institutional code, and course owner.
+#
# $client - The socket open on the client.
# Returns:
# 1 - Continue processing.
@@ -3346,11 +3443,11 @@ sub put_course_id_handler {
# a reply is written to $client.
sub dump_course_id_handler {
my ($cmd, $tail, $client) = @_;
-
my $userinput = "$cmd:$tail";
my ($udom,$since,$description,$instcodefilter,$ownerfilter,$coursefilter,
- $typefilter,$regexp_ok) =split(/:/,$tail);
+ $typefilter,$regexp_ok,$rtn_as_hash,$selfenrollonly) =split(/:/,$tail);
+ my $now = time;
if (defined($description)) {
$description=&unescape($description);
} else {
@@ -3390,62 +3487,103 @@ sub dump_course_id_handler {
if (defined($regexp_ok)) {
$regexp_ok=&unescape($regexp_ok);
}
-
- unless (defined($since)) { $since=0; }
+ my $unpack = 1;
+ if ($description eq '.' && $instcodefilter eq '.' && $coursefilter eq '.' &&
+ $typefilter eq '.') {
+ $unpack = 0;
+ }
+ if (!defined($since)) { $since=0; }
my $qresult='';
my $hashref = &tie_domain_hash($udom, "nohist_courseids", &GDBM_WRCREAT());
if ($hashref) {
while (my ($key,$value) = each(%$hashref)) {
- my ($descr,$lasttime,$inst_code,$owner,$type);
- my @courseitems = split(/:/,$value);
- $lasttime = pop(@courseitems);
- ($descr,$inst_code,$owner,$type)=@courseitems;
- if ($lasttime<$since) { next; }
+ my ($unesc_key,$lasttime_key,$lasttime,$is_hash,%val,
+ %unesc_val,$selfenroll_end,$selfenroll_types);
+ $unesc_key = &unescape($key);
+ if ($unesc_key =~ /^lasttime:/) {
+ next;
+ } else {
+ $lasttime_key = &escape('lasttime:'.$unesc_key);
+ }
+ if ($hashref->{$lasttime_key} ne '') {
+ $lasttime = $hashref->{$lasttime_key};
+ next if ($lasttime<$since);
+ }
+ my $items = &Apache::lonnet::thaw_unescape($value);
+ if (ref($items) eq 'HASH') {
+ $is_hash = 1;
+ if ($unpack || !$rtn_as_hash) {
+ $unesc_val{'descr'} = $items->{'description'};
+ $unesc_val{'inst_code'} = $items->{'inst_code'};
+ $unesc_val{'owner'} = $items->{'owner'};
+ $unesc_val{'type'} = $items->{'type'};
+ $selfenroll_types = $items->{'selfenroll_types'};
+ $selfenroll_end = $items->{'selfenroll_end_date'};
+ if ($selfenrollonly) {
+ next if (!$selfenroll_types);
+ if (($selfenroll_end > 0) && ($selfenroll_end <= $now)) {
+ next;
+ }
+ }
+ }
+ } else {
+ $is_hash = 0;
+ my @courseitems = split(/:/,$value);
+ $lasttime = pop(@courseitems);
+ next if ($lasttime<$since);
+ ($val{'descr'},$val{'inst_code'},$val{'owner'},$val{'type'}) = @courseitems;
+ }
my $match = 1;
- unless ($description eq '.') {
- my $unescapeDescr = &unescape($descr);
- unless (eval('$unescapeDescr=~/\Q$description\E/i')) {
+ if ($description ne '.') {
+ if (!$is_hash) {
+ $unesc_val{'descr'} = &unescape($val{'descr'});
+ }
+ if (eval{$unesc_val{'descr'} !~ /\Q$description\E/i}) {
$match = 0;
- }
+ }
}
- unless ($instcodefilter eq '.' || !defined($instcodefilter)) {
- my $unescapeInstcode = &unescape($inst_code);
+ if ($instcodefilter ne '.') {
+ if (!$is_hash) {
+ $unesc_val{'inst_code'} = &unescape($val{'inst_code'});
+ }
if ($regexp_ok) {
- unless (eval('$unescapeInstcode=~/$instcodefilter/')) {
+ if (eval{$unesc_val{'inst_code'} !~ /$instcodefilter/}) {
$match = 0;
}
} else {
- unless (eval('$unescapeInstcode=~/\Q$instcodefilter\E/i')) {
+ if (eval{$unesc_val{'inst_code'} !~ /\Q$instcodefilter\E/i}) {
$match = 0;
}
}
}
- unless ($ownerfilter eq '.' || !defined($ownerfilter)) {
- my $unescapeOwner = &unescape($owner);
+ if ($ownerfilter ne '.') {
+ if (!$is_hash) {
+ $unesc_val{'owner'} = &unescape($val{'owner'});
+ }
if (($ownerunamefilter ne '') && ($ownerdomfilter ne '')) {
- if ($unescapeOwner =~ /:/) {
- if (eval('$unescapeOwner !~
- /\Q$ownerunamefilter\E:\Q$ownerdomfilter\E$/i')) {
+ if ($unesc_val{'owner'} =~ /:/) {
+ if (eval{$unesc_val{'owner'} !~
+ /\Q$ownerunamefilter\E:\Q$ownerdomfilter\E$/i}) {
$match = 0;
}
} else {
- if (eval('$unescapeOwner!~/\Q$ownerunamefilter\E/i')) {
+ if (eval{$unesc_val{'owner'} !~ /\Q$ownerunamefilter\E/i}) {
$match = 0;
}
}
} elsif ($ownerunamefilter ne '') {
- if ($unescapeOwner =~ /:/) {
- if (eval('$unescapeOwner!~/\Q$ownerunamefilter\E:[^:]+$/i')) {
+ if ($unesc_val{'owner'} =~ /:/) {
+ if (eval{$unesc_val{'owner'} !~ /\Q$ownerunamefilter\E:[^:]+$/i}) {
$match = 0;
}
} else {
- if (eval('$unescapeOwner!~/\Q$ownerunamefilter\E/i')) {
+ if (eval{$unesc_val{'owner'} !~ /\Q$ownerunamefilter\E/i}) {
$match = 0;
}
}
} elsif ($ownerdomfilter ne '') {
- if ($unescapeOwner =~ /:/) {
- if (eval('$unescapeOwner!~/^[^:]+:\Q$ownerdomfilter\E/')) {
+ if ($unesc_val{'owner'} =~ /:/) {
+ if (eval{$unesc_val{'owner'} !~ /^[^:]+:\Q$ownerdomfilter\E/}) {
$match = 0;
}
} else {
@@ -3455,31 +3593,53 @@ sub dump_course_id_handler {
}
}
}
- unless ($coursefilter eq '.' || !defined($coursefilter)) {
- my $unescapeCourse = &unescape($key);
- unless (eval('$unescapeCourse=~/^$udom(_)\Q$coursefilter\E$/')) {
+ if ($coursefilter ne '.') {
+ if (eval{$unesc_key !~ /^$udom(_)\Q$coursefilter\E$/}) {
$match = 0;
}
}
- unless ($typefilter eq '.' || !defined($typefilter)) {
- my $unescapeType = &unescape($type);
- if ($type eq '') {
+ if ($typefilter ne '.') {
+ if (!$is_hash) {
+ $unesc_val{'type'} = &unescape($val{'type'});
+ }
+ if ($unesc_val{'type'} eq '') {
if ($typefilter ne 'Course') {
$match = 0;
}
- } else {
- unless (eval('$unescapeType=~/^\Q$typefilter\E$/')) {
+ } else {
+ if (eval{$unesc_val{'type'} !~ /^\Q$typefilter\E$/}) {
$match = 0;
}
}
}
if ($match == 1) {
- $qresult.=$key.'='.$descr.':'.$inst_code.':'.$owner.'&';
+ if ($rtn_as_hash) {
+ if ($is_hash) {
+ $qresult.=$key.'='.$value.'&';
+ } else {
+ my %rtnhash = ( 'description' => &unescape($val{'descr'}),
+ 'inst_code' => &unescape($val{'inst_code'}),
+ 'owner' => &unescape($val{'owner'}),
+ 'type' => &unescape($val{'type'}),
+ );
+ my $items = &Apache::lonnet::freeze_escape(\%rtnhash);
+ $qresult.=$key.'='.$items.'&';
+ }
+ } else {
+ if ($is_hash) {
+ $qresult .= $key.'='.&escape($unesc_val{'descr'}).':'.
+ &escape($unesc_val{'inst_code'}).':'.
+ &escape($unesc_val{'owner'}).'&';
+ } else {
+ $qresult .= $key.'='.$val{'descr'}.':'.$val{'inst_code'}.
+ ':'.$val{'owner'}.'&';
+ }
+ }
}
}
if (&untie_domain_hash($hashref)) {
chop($qresult);
- &Reply($client, "$qresult\n", $userinput);
+ &Reply($client, \$qresult, $userinput);
} else {
&Failure($client, "error: ".($!+0)." untie(GDBM) Failed ".
"while attempting courseiddump\n", $userinput);
@@ -3488,8 +3648,6 @@ sub dump_course_id_handler {
&Failure($client, "error: ".($!+0)." tie(GDBM) Failed ".
"while attempting courseiddump\n", $userinput);
}
-
-
return 1;
}
®ister_handler("courseiddump", \&dump_course_id_handler, 0, 1, 0);
@@ -3572,7 +3730,7 @@ sub get_domain_handler {
}
if (&untie_domain_hash($hashref)) {
$qresult=~s/\&$//;
- &Reply($client, "$qresult\n", $userinput);
+ &Reply($client, \$qresult, $userinput);
} else {
&Failure( $client, "error: ".($!+0)." untie(GDBM) Failed ".
"while attempting getdom\n",$userinput);
@@ -3670,7 +3828,7 @@ sub get_id_handler {
}
if (&untie_domain_hash($hashref)) {
$qresult=~s/\&$//;
- &Reply($client, "$qresult\n", $userinput);
+ &Reply($client, \$qresult, $userinput);
} else {
&Failure( $client, "error: ".($!+0)." untie(GDBM) Failed ".
"while attempting idget\n",$userinput);
@@ -3794,7 +3952,7 @@ sub dump_dcmail_handler {
}
if (&untie_domain_hash($hashref)) {
chop($qresult);
- &Reply($client, "$qresult\n", $userinput);
+ &Reply($client, \$qresult, $userinput);
} else {
&Failure($client, "error: ".($!+0)." untie(GDBM) Failed ".
"while attempting dcmaildump\n", $userinput);
@@ -3912,7 +4070,7 @@ sub dump_domainroles_handler {
}
}
unless (@roles < 1) {
- unless (grep/^$trole$/,@roles) {
+ unless (grep/^\Q$trole\E$/,@roles) {
$match = 0;
}
}
@@ -3922,7 +4080,7 @@ sub dump_domainroles_handler {
}
if (&untie_domain_hash($hashref)) {
chop($qresult);
- &Reply($client, "$qresult\n", $userinput);
+ &Reply($client, \$qresult, $userinput);
} else {
&Failure($client, "error: ".($!+0)." untie(GDBM) Failed ".
"while attempting domrolesdump\n", $userinput);
@@ -3976,7 +4134,7 @@ sub tmp_put_handler {
if ($store=IO::File->new(">$execdir/tmp/$id.tmp")) {
print $store $record;
close $store;
- &Reply($client, "$id\n", $userinput);
+ &Reply($client, \$id, $userinput);
} else {
&Failure( $client, "error: ".($!+0)."IO::File->new Failed ".
"while attempting tmpput\n", $userinput);
@@ -4010,7 +4168,7 @@ sub tmp_get_handler {
my $execdir=$perlvar{'lonDaemons'};
if ($store=IO::File->new("$execdir/tmp/$id.tmp")) {
my $reply=<$store>;
- &Reply( $client, "$reply\n", $userinput);
+ &Reply( $client, \$reply, $userinput);
close $store;
} else {
&Failure( $client, "error: ".($!+0)."IO::File->new Failed ".
@@ -4194,7 +4352,7 @@ sub enrollment_enabled_handler {
my ($cdom) = split(/:/, $tail, 2); # Domain we're asking about.
my $outcome = &localenroll::run($cdom);
- &Reply($client, "$outcome\n", $userinput);
+ &Reply($client, \$outcome, $userinput);
return 1;
}
@@ -4221,7 +4379,7 @@ sub get_sections_handler {
my @secs = &localenroll::get_sections($coursecode,$cdom);
my $seclist = &escape(join(':',@secs));
- &Reply($client, "$seclist\n", $userinput);
+ &Reply($client, \$seclist, $userinput);
return 1;
@@ -4250,7 +4408,7 @@ sub validate_course_owner_handler {
$owner = &unescape($owner);
my $outcome = &localenroll::new_course($inst_course_id,$owner,$cdom);
- &Reply($client, "$outcome\n", $userinput);
+ &Reply($client, \$outcome, $userinput);
@@ -4281,7 +4439,7 @@ sub validate_course_section_handler {
my ($inst_course_id, $cdom) = split(/:/, $tail);
my $outcome=&localenroll::validate_courseID($inst_course_id,$cdom);
- &Reply($client, "$outcome\n", $userinput);
+ &Reply($client, \$outcome, $userinput);
return 1;
@@ -4308,14 +4466,14 @@ sub validate_course_section_handler {
sub validate_class_access_handler {
my ($cmd, $tail, $client) = @_;
my $userinput = "$cmd:$tail";
- my ($inst_class,$courseowner,$cdom) = split(/:/, $tail);
- $courseowner = &unescape($courseowner);
+ my ($inst_class,$ownerlist,$cdom) = split(/:/, $tail);
+ my $owners = &unescape($ownerlist);
my $outcome;
eval {
local($SIG{__DIE__})='DEFAULT';
- $outcome=&localenroll::check_section($inst_class,$courseowner,$cdom);
+ $outcome=&localenroll::check_section($inst_class,$owners,$cdom);
};
- &Reply($client,"$outcome\n", $userinput);
+ &Reply($client,\$outcome, $userinput);
return 1;
}
@@ -4476,7 +4634,7 @@ sub get_institutional_defaults_handler {
$result.=&escape($key).'='.&escape($value).'&';
}
$result .= 'code_order='.&escape(join('&',@code_order));
- &Reply($client,$result."\n",$userinput);
+ &Reply($client,\$result,$userinput);
} else {
&Reply($client,"error\n", $userinput);
}
@@ -4487,6 +4645,195 @@ sub get_institutional_defaults_handler {
®ister_handler("autoinstcodedefaults",
\&get_institutional_defaults_handler,0,1,0);
+sub get_institutional_user_rules {
+ my ($cmd, $tail, $client) = @_;
+ my $userinput = "$cmd:$tail";
+ my $dom = &unescape($tail);
+ my (%rules_hash,@rules_order);
+ my $outcome;
+ eval {
+ local($SIG{__DIE__})='DEFAULT';
+ $outcome = &localenroll::username_rules($dom,\%rules_hash,\@rules_order);
+ };
+ if (!$@) {
+ if ($outcome eq 'ok') {
+ my $result;
+ foreach my $key (keys(%rules_hash)) {
+ $result .= &escape($key).'='.&Apache::lonnet::freeze_escape($rules_hash{$key}).'&';
+ }
+ $result =~ s/\&$//;
+ $result .= ':';
+ if (@rules_order > 0) {
+ foreach my $item (@rules_order) {
+ $result .= &escape($item).'&';
+ }
+ }
+ $result =~ s/\&$//;
+ &Reply($client,\$result,$userinput);
+ } else {
+ &Reply($client,"error\n", $userinput);
+ }
+ } else {
+ &Failure($client,"unknown_cmd\n",$userinput);
+ }
+}
+®ister_handler("instuserrules",\&get_institutional_user_rules,0,1,0);
+
+sub get_institutional_id_rules {
+ my ($cmd, $tail, $client) = @_;
+ my $userinput = "$cmd:$tail";
+ my $dom = &unescape($tail);
+ my (%rules_hash,@rules_order);
+ my $outcome;
+ eval {
+ local($SIG{__DIE__})='DEFAULT';
+ $outcome = &localenroll::id_rules($dom,\%rules_hash,\@rules_order);
+ };
+ if (!$@) {
+ if ($outcome eq 'ok') {
+ my $result;
+ foreach my $key (keys(%rules_hash)) {
+ $result .= &escape($key).'='.&Apache::lonnet::freeze_escape($rules_hash{$key}).'&';
+ }
+ $result =~ s/\&$//;
+ $result .= ':';
+ if (@rules_order > 0) {
+ foreach my $item (@rules_order) {
+ $result .= &escape($item).'&';
+ }
+ }
+ $result =~ s/\&$//;
+ &Reply($client,\$result,$userinput);
+ } else {
+ &Reply($client,"error\n", $userinput);
+ }
+ } else {
+ &Failure($client,"unknown_cmd\n",$userinput);
+ }
+}
+®ister_handler("instidrules",\&get_institutional_id_rules,0,1,0);
+
+sub get_institutional_selfcreate_rules {
+ my ($cmd, $tail, $client) = @_;
+ my $userinput = "$cmd:$tail";
+ my $dom = &unescape($tail);
+ my (%rules_hash,@rules_order);
+ my $outcome;
+ eval {
+ local($SIG{__DIE__})='DEFAULT';
+ $outcome = &localenroll::selfcreate_rules($dom,\%rules_hash,\@rules_order);
+ };
+ if (!$@) {
+ if ($outcome eq 'ok') {
+ my $result;
+ foreach my $key (keys(%rules_hash)) {
+ $result .= &escape($key).'='.&Apache::lonnet::freeze_escape($rules_hash{$key}).'&';
+ }
+ $result =~ s/\&$//;
+ $result .= ':';
+ if (@rules_order > 0) {
+ foreach my $item (@rules_order) {
+ $result .= &escape($item).'&';
+ }
+ }
+ $result =~ s/\&$//;
+ &Reply($client,\$result,$userinput);
+ } else {
+ &Reply($client,"error\n", $userinput);
+ }
+ } else {
+ &Failure($client,"unknown_cmd\n",$userinput);
+ }
+}
+®ister_handler("instemailrules",\&get_institutional_selfcreate_rules,0,1,0);
+
+
+sub institutional_username_check {
+ my ($cmd, $tail, $client) = @_;
+ my $userinput = "$cmd:$tail";
+ my %rulecheck;
+ my $outcome;
+ my ($udom,$uname,@rules) = split(/:/,$tail);
+ $udom = &unescape($udom);
+ $uname = &unescape($uname);
+ @rules = map {&unescape($_);} (@rules);
+ eval {
+ local($SIG{__DIE__})='DEFAULT';
+ $outcome = &localenroll::username_check($udom,$uname,\@rules,\%rulecheck);
+ };
+ if (!$@) {
+ if ($outcome eq 'ok') {
+ my $result='';
+ foreach my $key (keys(%rulecheck)) {
+ $result.=&escape($key).'='.&Apache::lonnet::freeze_escape($rulecheck{$key}).'&';
+ }
+ &Reply($client,\$result,$userinput);
+ } else {
+ &Reply($client,"error\n", $userinput);
+ }
+ } else {
+ &Failure($client,"unknown_cmd\n",$userinput);
+ }
+}
+®ister_handler("instrulecheck",\&institutional_username_check,0,1,0);
+
+sub institutional_id_check {
+ my ($cmd, $tail, $client) = @_;
+ my $userinput = "$cmd:$tail";
+ my %rulecheck;
+ my $outcome;
+ my ($udom,$id,@rules) = split(/:/,$tail);
+ $udom = &unescape($udom);
+ $id = &unescape($id);
+ @rules = map {&unescape($_);} (@rules);
+ eval {
+ local($SIG{__DIE__})='DEFAULT';
+ $outcome = &localenroll::id_check($udom,$id,\@rules,\%rulecheck);
+ };
+ if (!$@) {
+ if ($outcome eq 'ok') {
+ my $result='';
+ foreach my $key (keys(%rulecheck)) {
+ $result.=&escape($key).'='.&Apache::lonnet::freeze_escape($rulecheck{$key}).'&';
+ }
+ &Reply($client,\$result,$userinput);
+ } else {
+ &Reply($client,"error\n", $userinput);
+ }
+ } else {
+ &Failure($client,"unknown_cmd\n",$userinput);
+ }
+}
+®ister_handler("instidrulecheck",\&institutional_id_check,0,1,0);
+
+sub institutional_selfcreate_check {
+ my ($cmd, $tail, $client) = @_;
+ my $userinput = "$cmd:$tail";
+ my %rulecheck;
+ my $outcome;
+ my ($udom,$email,@rules) = split(/:/,$tail);
+ $udom = &unescape($udom);
+ $email = &unescape($email);
+ @rules = map {&unescape($_);} (@rules);
+ eval {
+ local($SIG{__DIE__})='DEFAULT';
+ $outcome = &localenroll::selfcreate_check($udom,$email,\@rules,\%rulecheck);
+ };
+ if (!$@) {
+ if ($outcome eq 'ok') {
+ my $result='';
+ foreach my $key (keys(%rulecheck)) {
+ $result.=&escape($key).'='.&Apache::lonnet::freeze_escape($rulecheck{$key}).'&';
+ }
+ &Reply($client,\$result,$userinput);
+ } else {
+ &Reply($client,"error\n", $userinput);
+ }
+ } else {
+ &Failure($client,"unknown_cmd\n",$userinput);
+ }
+}
+®ister_handler("instselfcreatecheck",\&institutional_selfcreate_check,0,1,0);
# Get domain specific conditions for import of student photographs to a course
#
@@ -4639,7 +4986,7 @@ sub inst_usertypes_handler {
}
$res=~s/\&$//;
}
- &Reply($client, "$res\n", $userinput);
+ &Reply($client, \$res, $userinput);
return 1;
}
®ister_handler("inst_usertypes", \&inst_usertypes_handler, 0, 1, 0);
@@ -4907,7 +5254,7 @@ sub catchexception {
$SIG{__DIE__}='DEFAULT';
&status("Catching exception");
&logthis("CRITICAL: "
- ."ABNORMAL EXIT. Child $$ for server $thisserver died through "
+ ."ABNORMAL EXIT. Child $$ for server ".$perlvar{'lonHostID'}." died through "
."a crash with this error msg->[$error]");
&logthis('Famous last words: '.$status.' - '.$lastlog);
if ($client) { print $client "error: $error\n"; }
@@ -5052,7 +5399,8 @@ sub UpdateHosts {
foreach my $child (keys(%children)) {
my $childip = $children{$child};
- if (!defined(&Apache::lonnet::get_hosts_from_ip($childip))) {
+ if ($childip ne '127.0.0.1'
+ && !defined(&Apache::lonnet::get_hosts_from_ip($childip))) {
logthis(' UpdateHosts killing child '
." $child for ip $childip ");
kill('INT', $child);
@@ -5137,9 +5485,14 @@ sub Debug {
#
sub Reply {
my ($fd, $reply, $request) = @_;
- print $fd $reply;
- Debug("Request was $request Reply was $reply");
-
+ if (ref($reply)) {
+ print $fd $$reply;
+ print $fd "\n";
+ if ($DEBUG) { Debug("Request was $request Reply was $$reply"); }
+ } else {
+ print $fd $reply;
+ if ($DEBUG) { Debug("Request was $request Reply was $reply"); }
+ }
$Transactions++;
}
@@ -5489,7 +5842,7 @@ sub make_new_child {
# ---------------- New known client connecting, could mean machine online again
if (&Apache::lonnet::get_host_ip($currenthostid) ne $clientip
&& $clientip ne '127.0.0.1') {
- &Apache::lonnet::reconlonc();
+ &Apache::lonnet::reconlonc($clientname);
}
&logthis("Established connection: $clientname");
&status('Will listen to '.$clientname);
@@ -5692,8 +6045,7 @@ sub get_auth_type
# 0 - The domain,user,password triplet is not a valid user.
#
sub validate_user {
- my ($domain, $user, $password) = @_;
-
+ my ($domain, $user, $password, $checkdefauth) = @_;
# Why negative ~pi you may well ask? Well this function is about
# authentication, and therefore very important to get right.
@@ -5716,8 +6068,21 @@ sub validate_user {
my $null = pack("C",0); # Used by kerberos auth types.
+ if ($howpwd eq 'nouser') {
+ if ($checkdefauth) {
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($domain);
+ if ($domdefaults{'auth_def'} eq 'localauth') {
+ $howpwd = $domdefaults{'auth_def'};
+ $contentpwd = $domdefaults{'auth_arg_def'};
+ } elsif ((($domdefaults{'auth_def'} eq 'krb4') ||
+ ($domdefaults{'auth_def'} eq 'krb5')) &&
+ ($domdefaults{'auth_arg_def'} ne '')) {
+ $howpwd = $domdefaults{'auth_def'};
+ $contentpwd = $domdefaults{'auth_arg_def'};
+ }
+ }
+ }
if ($howpwd ne 'nouser') {
-
if($howpwd eq "internal") { # Encrypted is in local password file.
$validated = (crypt($password, $contentpwd) eq $contentpwd);
}
@@ -5768,11 +6133,22 @@ sub validate_user {
my $credentials= &Authen::Krb5::cc_default();
$credentials->initialize(&Authen::Krb5::parse_name($user.'@'
.$contentpwd));
- my $krbreturn = &Authen::Krb5::get_in_tkt_with_password($krbclient,
- $krbserver,
- $password,
- $credentials);
- $validated = ($krbreturn == 1);
+ my $krbreturn;
+ if (exists(&Authen::Krb5::get_init_creds_password)) {
+ $krbreturn =
+ &Authen::Krb5::get_init_creds_password($krbclient,$password,
+ $krbservice);
+ $validated = (ref($krbreturn) eq 'Authen::Krb5::Creds');
+ } else {
+ $krbreturn =
+ &Authen::Krb5::get_in_tkt_with_password($krbclient,$krbserver,
+ $password,$credentials);
+ $validated = ($krbreturn == 1);
+ }
+ if (!$validated) {
+ &logthis('krb5: '.$user.', '.$contentpwd.', '.
+ &Authen::Krb5::error());
+ }
} else {
$validated = 0;
}
@@ -6018,7 +6394,7 @@ sub subscribe {
# the metadata
unless ($fname=~/\.meta$/) { &unsub("$fname.meta",$clientip); }
$fname=~s/\/home\/httpd\/html\/res/raw/;
- $fname="http://$thisserver/".$fname;
+ $fname="http://".&Apache::lonnet::hostname($perlvar{'lonHostID'})."/".$fname;
$result="$fname\n";
}
} else {
@@ -6061,7 +6437,7 @@ sub change_unix_password {
sub make_passwd_file {
my ($uname, $umode,$npass,$passfilename)=@_;
- my $result="ok\n";
+ my $result="ok";
if ($umode eq 'krb4' or $umode eq 'krb5') {
{
my $pf = IO::File->new(">$passfilename");
@@ -6129,7 +6505,7 @@ sub make_passwd_file {
if($useraddok > 0) {
my $error_text = &lcuseraddstrerror($useraddok);
&logthis("Failed lcuseradd: $error_text");
- $result = "lcuseradd_failed:$error_text\n";
+ $result = "lcuseradd_failed:$error_text";
} else {
my $pf = IO::File->new(">$passfilename");
if($pf) {
@@ -6153,7 +6529,7 @@ sub make_passwd_file {
}
}
} else {
- $result="auth_mode_error\n";
+ $result="auth_mode_error";
}
return $result;
}