[LON-CAPA-cvs] cvs: newloncapa /types LondConnection.pm

foxr lon-capa-cvs@mail.lon-capa.org
Wed, 09 Apr 2003 01:08:14 -0000


foxr		Tue Apr  8 21:08:14 2003 EDT

  Modified files:              
    /newloncapa/types	LondConnection.pm 
  Log:
  1. Read in hosts.tab file so that:
  2. Opens are now done with a parameter that is the loncapa hostname
     rather than the IP hostname.
  
  
Index: newloncapa/types/LondConnection.pm
diff -u newloncapa/types/LondConnection.pm:1.4 newloncapa/types/LondConnection.pm:1.5
--- newloncapa/types/LondConnection.pm:1.4	Tue Apr  1 18:22:35 2003
+++ newloncapa/types/LondConnection.pm	Tue Apr  8 21:08:14 2003
@@ -9,8 +9,22 @@
 use Fcntl;
 use POSIX;
 use Crypt::IDEA;
+use LONCAPA::Configuration;
 
-$DebugLevel=10;
+my $DebugLevel=10;
+
+#   Read the configuration file for apache to get the perl
+#   variable set.
+
+my $perlvarref = LONCAPA::Configuration::read_conf('loncapa.conf');
+my %perlvar    = %{$perlvarref};
+my $hoststab   = 
+    LONCAPA::Configuration::read_hosts(
+            "$perlvar{'lonTabDir'}/hosts.tab") || 
+    die "Can't read host table!!";
+my %hostshash  = %{$hoststab};
+
+close(CONFIG);
 
 sub Debug {
     my $level   = shift;
@@ -50,7 +64,8 @@
 =pod
   Construct a new lond connection.
   Parameters (besides the class name) include:
-=item hostname - host the remote lond is on.
+=item hostname - host the remote lond is on. 
+    This host is a host in the hosts.tab file
 =item port     - port number the remote lond is listening on.
 =cut
 sub new {
@@ -58,7 +73,22 @@
     my $Hostname = shift;	# Name of host to connect to.
     my $Port     = shift;	# Port to connect 
     &Debug(4,$class."::new( ".$Hostname.",".$Port.")\n");
-    my $self     = { Host               => $Hostname,
+
+    # The host must map to an entry in the hosts table:
+    #  We connect to the dns host that corresponds to that
+    #  system and use the hostname for the encryption key 
+    #  negotion.  In the objec these become the Host and
+    #  LoncapaHim fields of the object respectively.
+    #
+    if (!exists $hostshash{$Hostname}) {
+	return undef;		# No such host!!!
+    }
+    my @ConfigLine = @{$hostshash{$Hostname}};
+    my $DnsName    = $ConfigLine[3]; # 4'th item is dns of host.
+    Debug(5, "Connecting to ".$DnsName);
+    # Now create the object...
+    my $self     = { Host               => $DnsName,
+		     LoncapaHim         => $Hostname,
 	             Port               => $Port,
 	             State              => "Initialized",
 	             TransactionRequest => "",
@@ -165,7 +195,7 @@
 	    return 0;
 	} elsif ($self->{State}  eq "ReceivingKey") {
 	    my $buildkey = $self->{TransactionReply};
-	    my $key = $self->{Host}.$perlvar{'lonHostID'};
+	    my $key = $self->{LoncapaHim}.$perlvar{'lonHostID'};
 	    $key=~tr/a-z/A-Z/;
 	    $key=~tr/G-P/0-9/;
 	    $key=~tr/Q-Z/0-9/;
@@ -183,6 +213,17 @@
 		return 0;
 	    }
 	} elsif ($self->{State}  eq "ReceivingReply") {
+
+	    # If the data are encrypted, decrypt first.
+
+	    my $answer = $self->{TransactionReply};
+	    if($answer =~ /^enc\:/) {
+		$answer = $self->Decrypt($answer);
+		$self->{TransactionReply} = $answer;
+	    }
+
+	    # finish the transaction
+
 	    $self->{InformWritable}     = 0;
 	    $self->{InformReadable}     = 0;
 	    $self->{Timeoutable}        = 0;
@@ -296,6 +337,13 @@
     if($self->{State} ne "Idle") {
 	return -1;		# Error indicator.
     }
+    # if the transaction is to be encrypted encrypt the data:
+
+    if($data =~ /^encrypt\:/) {
+	$data = $self->Encrypt($data);
+    }
+
+    # Setup the trasaction
 
     $self->{TransactionRequest} = $data;
     $self->{TransactionReply}   = "";
@@ -369,12 +417,88 @@
     return $self->{Timeoutable};
 }
 
-
+=pod
+  Returns the reply from the last transaction.
+=cut
 sub GetReply {
     my $self = shift;
     return $self->{TransactionReply};
 }
+
+=pod
+  Returns the encrypted version of the command string.
+  The command input string is of the form:
+  encrypt:command
+  The output string can be directly sent to lond as it's of the form:
+  enc:length:<encodedrequest>
+'
+=cut
+sub Encrypt {
+    my $self    = shift;		# Reference to the object.
+    my $request = shift;	        # Text to send.
+
+   
+    # Split the encrypt: off the request and figure out it's length.
+    # the cipher works in blocks of 8 bytes.
+
+    my $cmd = $request;
+    $cmd    =~ s/^encrypt\://;	# strip off encrypt:
+    chomp($cmd);		# strip off trailing \n
+    my     $length=length($cmd);	# Get the string length.
+    $cmd .= "         ";	# Pad with blanks so we can fill out a block.
+
+    # encrypt the request in 8 byte chunks to create the encrypted
+    # output request.
+
+    my $Encoded = '';
+    for(my $index = 0; $index <= $length; $index += 8) {
+	$Encoded .= 
+	    unpack("H16", 
+		   $self->{Cipher}->encrypt(substr($cmd, 
+						   $index, 8)));
+    }
+
+    # Build up the answer as enc:length:$encrequest.
+
+    $request = "enc:$length:$Encoded\n";
+    return $request;
+    
     
+}
+=pod 
+    Decrypt
+    Decrypt a response from the server.  The response is in the form:
+  enc:<length>:<encrypted data>
+=cut
+sub Decrypt {
+    my $self      = shift;	# Recover reference to object
+    my $encrypted = shift;	# This is the encrypted data.
+
+    #  Bust up the response into length, and encryptedstring:
+
+    my ($enc, $length, $EncryptedString) = split(/:/,$encrypted);
+    chomp($EncryptedString);
+
+    # Decode the data in 8 byte blocks.  The string is encoded
+    # as hex digits so there are two characters per byte:
+
+    $decrpyted = "";
+    for(my $index = 0; $index < length($EncryptedString);
+	$index += 16) {
+	$decrypted .= $self->{Cipher}->decrypt(
+				    pack("H16",
+					 substr($EncryptedString,
+						$index, 
+						16)));
+    }
+    #  the answer may have trailing pads to fill out a block.
+    #  $length tells us the actual length of the decrypted string:
+
+    $decrypted = substr($decrypted, 0, $length);
+
+    return $decrypted;
+
+}
 1;
 
 =pod
@@ -428,7 +552,10 @@
     The client to manage the work flow for the object.
 =item SetTimeoutCallback -Set a function to be called when a transaction times
     out.  The function will be called with the object as its sole parameter.
-
+=item Encrypt - Encrypts a block of text according to the cipher negotiated
+       with the peer (assumes the text is a command).
+=item Decrypt - Decrypts a block of text according to the cipher negotiated
+       with the peer (assumes the block was a reply.
 
 =head2 The following are selector member functions: