--- loncom/lond 2003/08/12 03:28:31 1.134
+++ loncom/lond 2003/08/26 11:15:57 1.140
@@ -2,7 +2,7 @@
# The LearningOnline Network
# lond "LON Daemon" Server (port "LOND" 5663)
#
-# $Id: lond,v 1.134 2003/08/12 03:28:31 albertel Exp $
+# $Id: lond,v 1.140 2003/08/26 11:15:57 foxr Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -50,6 +50,13 @@
# population). Since the time averaged connection rate is close to zero
# because lonc's purpose is to maintain near continuous connnections,
# preforking is not really needed.
+# 08/xx/2003 Ron Fox: Add management requests. Management requests
+# will be validated via a call to ValidateManager. At present, this
+# is done by simple host verification. In the future we can modify
+# this function to do a certificate check.
+# Management functions supported include:
+# - pushing /home/httpd/lonTabs/hosts.tab
+# - pushing /home/httpd/lonTabs/domain.tab
###
use strict;
@@ -74,12 +81,14 @@ my $DEBUG = 0; # Non zero to ena
my $status='';
my $lastlog='';
-my $VERSION='$Revision: 1.134 $'; #' stupid emacs
+my $VERSION='$Revision: 1.140 $'; #' stupid emacs
my $remoteVERSION;
my $currenthostid;
my $currentdomainid;
my $client;
+my $clientip;
+
my $server;
my $thisserver;
@@ -126,6 +135,44 @@ my @adderrors = ("ok",
#
+# GetCertificate: Given a transaction that requires a certificate,
+# this function will extract the certificate from the transaction
+# request. Note that at this point, the only concept of a certificate
+# is the hostname to which we are connected.
+#
+# Parameter:
+# request - The request sent by our client (this parameterization may
+# need to change when we really use a certificate granting
+# authority.
+#
+sub GetCertificate {
+ my $request = shift;
+
+ return $clientip;
+}
+
+
+#
+# ValidManager: Determines if a given certificate represents a valid manager.
+# in this primitive implementation, the 'certificate' is
+# just the connecting loncapa client name. This is checked
+# against a valid client list in the configuration.
+#
+#
+sub ValidManager {
+ my $certificate = shift;
+
+ my $hostentry = $hostid{$certificate};
+ if ($hostentry ne undef) {
+ &logthis('Authenticating manager'.
+ " $hostentry");
+ return 1;
+ } else {
+ &logthis(' Failed manager authentication '.
+ "$certificate ");
+ }
+}
+#
# Convert an error return code from lcpasswd to a string value.
#
sub lcpasswdstrerror {
@@ -527,7 +574,6 @@ sub make_new_child {
sigprocmask(SIG_BLOCK, $sigset)
or die "Can't block SIGINT for fork: $!\n";
- my $clientip;
die "fork: $!" unless defined ($pid = fork);
if ($pid) {
@@ -645,7 +691,7 @@ sub make_new_child {
if ($userinput =~ /^ping/) {
print $client "$currenthostid\n";
# ------------------------------------------------------------------------ pong
- } elsif ($userinput =~ /^pong/) {
+ }elsif ($userinput =~ /^pong/) {
my $reply=&reply("ping",$hostid{$clientip});
print $client "$currenthostid:$reply\n";
# ------------------------------------------------------------------------ ekey
@@ -676,6 +722,10 @@ sub make_new_child {
} elsif ($userinput =~ /^userload/) {
my $userloadpercent=&userload();
print $client "$userloadpercent\n";
+
+#
+# Transactions requiring encryption:
+#
# ----------------------------------------------------------------- currentauth
} elsif ($userinput =~ /^currentauth/) {
if ($wasenc==1) {
@@ -690,6 +740,30 @@ sub make_new_child {
} else {
print $client "refused\n";
}
+#--------------------------------------------------------------------- pushfile
+ } elsif($userinput =~ /^pushfile/) {
+ if($wasenc == 1) {
+ my $cert = GetCertificate($userinput);
+ if(ValidManager($cert)) {
+ print $client "ok\n";
+ } else {
+ print $client "refused\n";
+ }
+ } else {
+ print $client "refused\n";
+ }
+#--------------------------------------------------------------------- reinit
+ } elsif($userinput =~ /^reinit/) {
+ if ($wasenc == 1) {
+ my $cert = GetCertificate($userinput);
+ if(ValidManager($cert)) {
+ print $client "ok\n";
+ } else {
+ print $client "refused\n";
+ }
+ } else {
+ print $client "refused\n";
+ }
# ------------------------------------------------------------------------ auth
} elsif ($userinput =~ /^auth/) {
if ($wasenc==1) {
@@ -801,10 +875,18 @@ sub make_new_child {
my $salt=time;
$salt=substr($salt,6,2);
my $ncpass=crypt($npass,$salt);
- { my $pf = IO::File->new(">$passfilename");
- print $pf "internal:$ncpass\n"; }
- &logthis("Result of password change for $uname: pwchange_success");
- print $client "ok\n";
+ {
+ my $pf;
+ if ($pf = IO::File->new(">$passfilename")) {
+ print $pf "internal:$ncpass\n";
+ &logthis("Result of password change for $uname: pwchange_success");
+ print $client "ok\n";
+ } else {
+ &logthis("Unable to open $uname passwd to change password");
+ print $client "non_authorized\n";
+ }
+ }
+
} else {
print $client "non_authorized\n";
}
@@ -1726,6 +1808,19 @@ sub make_new_child {
}
if ($ulsout eq '') { $ulsout='empty'; }
print $client "$ulsout\n";
+# ----------------------------------------------------------------- setannounce
+ } elsif ($userinput =~ /^setannounce/) {
+ my ($cmd,$announcement)=split(/:/,$userinput);
+ chomp($announcement);
+ $announcement=&unescape($announcement);
+ if (my $store=IO::File->new('>'.$perlvar{'lonDocRoot'}.
+ '/announcement.txt')) {
+ print $store $announcement;
+ close $store;
+ print $client "ok\n";
+ } else {
+ print $client "error: ".($!+0)."\n";
+ }
# ------------------------------------------------------------------ Hanging up
} elsif (($userinput =~ /^exit/) ||
($userinput =~ /^init/)) {
@@ -2098,8 +2193,8 @@ sub userload {
my $curtime=time;
while ($filename=readdir(LONIDS)) {
if ($filename eq '.' || $filename eq '..') {next;}
- my ($atime)=(stat($perlvar{'lonIDsDir'}.'/'.$filename))[8];
- if ($curtime-$atime < 3600) { $numusers++; }
+ my ($mtime)=(stat($perlvar{'lonIDsDir'}.'/'.$filename))[9];
+ if ($curtime-$mtime < 3600) { $numusers++; }
}
closedir(LONIDS);
}
@@ -2381,6 +2476,17 @@ Send along temporarily stored informatio
List part of a user's directory.
+=item pushtable
+
+Pushes a file in /home/httpd/lonTab directory. Currently limited to:
+hosts.tab and domain.tab. The old file is copied to *.tab.backup but
+must be restored manually in case of a problem with the new table file.
+pushtable requires that the request be encrypted and validated via
+ValidateManager. The form of the command is:
+enc:pushtable tablename \n
+where pushtable, tablename and will be encrypted, but \n is a
+cleartext newline.
+
=item Hanging up (exit or init)
What to do when a client tells the server that they (the client)
@@ -2391,6 +2497,7 @@ are leaving the network.
If B is sent an unknown command (not in the list above),
it replys to the client "unknown_cmd".
+
=item UNKNOWN CLIENT
If the anti-spoofing algorithm cannot verify the client,