Annotation of loncom/lonlocal.pm, revision 1.7

1.2       foxr        1: #
1.7     ! albertel    2: # $Id: lonlocal.pm,v 1.6 2004/06/17 10:15:46 foxr Exp $
1.2       foxr        3: #
                      4: # Copyright Michigan State University Board of Trustees
                      5: #
                      6: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      7: #
                      8: # LON-CAPA is free software; you can redistribute it and/or modify
                      9: # it under the terms of the GNU General Public License as published by
                     10: # the Free Software Foundation; either version 2 of the License, or
                     11: # (at your option) any later version.
                     12: #
                     13: # LON-CAPA is distributed in the hope that it will be useful,
                     14: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     15: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     16: # GNU General Public License for more details.
                     17: #
                     18: # You should have received a copy of the GNU General Public License
                     19: # along with LON-CAPA; if not, write to the Free Software
                     20: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     21: #
                     22: # /home/httpd/html/adm/gpl.txt
                     23: #
                     24: # http://www.lon-capa.org/
                     25: #
                     26: package lonlocal;
                     27: 
                     28: #
                     29: #   Module that provides support for local connections between secure
                     30: #   lonc and secure lond.
                     31: #
                     32: #   A local connection exchanges one-time session keys through a 
                     33: #   file that is written in the certificate directory by lonc and
                     34: #   read/deleted by lond.  The file is created with permissions
                     35: #   rw------- (0600) to prevent it from being snooped unless the system
                     36: #   itself has been broken.  In addition the file will not be around
                     37: #   for very long so it will be hard to find.
                     38: #
                     39: 
                     40: use strict;
                     41: 
                     42: # CPAN/standard modules
                     43: 
                     44: use Crypt::IDEA;
1.3       foxr       45: use Fcntl;
1.2       foxr       46: 
                     47: # LONCAPA modules
                     48: 
                     49: use LONCAPA::Configuration;
                     50: 
                     51: # Global variables:
                     52: 
                     53: my $perlvar;			# Refers to the apache perlsetvar hash.
1.3       foxr       54: my $pathsep   = "/";		# Unix path seperator 
                     55: my $fileindex = 0;		# Per process lonc uniquifier.
                     56: my $lastError;			# Reason for last failure.
                     57: 
1.2       foxr       58: 
1.5       foxr       59: #  Debugging:
                     60: 
1.6       foxr       61: my $DEBUG = 0;
1.5       foxr       62: 
                     63: sub Debug {
                     64:     my $msg = shift;
1.7     ! albertel   65:     if ($DEBUG) { print STDERR "$msg\n"; }
1.5       foxr       66: }
                     67: 
1.2       foxr       68: # Initialization
                     69: 
                     70: $perlvar = LONCAPA::Configuration::read_conf('loncapa.conf');
                     71: 
                     72: 
                     73: #------------------------------------------------------------------------
                     74: #
1.5       foxr       75: # Name          CreateCipherKey
1.2       foxr       76: # Description:  Create an encryption key.
                     77: # Returns:      The key.
                     78: #
                     79: sub CreateCipherKey {
                     80: 
                     81:     my $keylength;
                     82:     my $binaryKey;
                     83:     my $cipherkey;
                     84:     
1.5       foxr       85:     # we'll use the output of /dev/urandom to produce our key.
1.2       foxr       86:     # On a system with decent entropy, this ought to be much more
                     87:     # random than all the playing that used to be done to get a key.
1.5       foxr       88:     # On a system with not so decent entropy we'll still get an ok key.
                     89:     # My concern with /dev/random is that we may block for an indefinite
                     90:     # time period...where for us decent keys are probably good enough.
1.2       foxr       91:     
                     92:     $keylength   =  IDEA::keysize();
1.5       foxr       93:     open(RANDOM, "</dev/urandom");
1.2       foxr       94:     sysread(RANDOM, $binaryKey, $keylength);
                     95:     close RANDOM;
                     96:     
                     97:     #  The key must be returned in a stringified form in order to be
                     98:     #  transmitted to the peer:
                     99:     
                    100:     my $hexdigits = $keylength*2;	# Assume 8 bits/byte.
                    101:     my $template  = "H".$hexdigits;
                    102:     $cipherkey = unpack($template, $binaryKey);
                    103:     
                    104:     return $cipherkey;
                    105: }
                    106: 
                    107: #------------------------------------------------------------------------
                    108: #
                    109: # Name  	CreateKeyFile
                    110: # Description	Creates a private key file and writes an IDEA key into it.  
                    111: #
                    112: # Returns	
                    113: #     A two element list containing:
                    114: #     - 	The private key that was  created
                    115: #     - 	The full path to the file that contains it.
1.3       foxr      116: #     or undef on failure.
1.2       foxr      117: sub CreateKeyFile {
                    118: 
                    119:     # To create the file we need some perlvars to tell us where the
                    120:     # certificate directory. We'll make a file named localkey.$pid
                    121:     # there, and set the mode before writing into it.
                    122:     #
1.3       foxr      123:     $fileindex++;
                    124:     my $CertificateDir = $perlvar->{lonCertificateDirectory};
1.5       foxr      125:     my $Filename       = $CertificateDir.$pathsep.".$fileindex.".$$;
1.3       foxr      126: 
                    127:     # If this file already exists, this is a recoverable error... we just
                    128:     # delete the earlier incarnation of the file.
                    129: 
                    130:     if (-w $Filename) {
                    131: 	unlink $Filename;
                    132:     }
                    133: 
                    134:     # If the file still exists this is really really bad:
                    135:     # It most likely means someone has been devious enough to drop a key file
                    136:     # in place to attemp to spoof the lond.  We'll fail in that case hoping
                    137:     # that the user looks at the log to figure out that local connections
                    138:     # are failing.
                    139:     
                    140:     if( -e $Filename) {
                    141: 	$lastError = "Key file already exists after deletion probably a spoof!";
                    142: 	return undef;
                    143:     }
                    144:     #  Now we can create the file  we use sysopen in order to ensure
                    145:     # the file is created with the appropriate locked down permissions.
                    146: 
                    147:     if(! sysopen(KEYFILE, $Filename, O_CREAT | O_EXCL | O_WRONLY, 0600)) {
1.5       foxr      148: 	$lastError = "Creation of key file failed ".$!;
1.3       foxr      149: 	return undef;
                    150:     }
                    151:     # Create the key, write it to the file and close the file:
                    152: 
                    153:     my $key = CreateCipherKey();
                    154:     print KEYFILE "$key\n";
                    155:     close KEYFILE;
                    156: 
1.5       foxr      157:     return ($key, $Filename);
1.3       foxr      158: 
1.2       foxr      159:     
                    160: }
                    161: 
                    162: 
1.3       foxr      163: # Name  	ReadKeyFile
                    164: # Description	Opens the private local key file and reads the IDEA key from it.
                    165: # Parameters
                    166: #       	Name	          Type	       Description
                    167: #               Filename	  string       path to key file
                    168: #
                    169: # NOTE:
                    170: #   Reading the keyfile is a one-time thing.  This sub destroys the
                    171: #   keyfile after reading it to ensure the one-timedness of the keys they
                    172: #   contain!!
                    173: # Returns	
                    174: #    On success the IDEA key that was written into the key fileon failure undef.
                    175: #
                    176: #
                    177: sub ReadKeyFile {
                    178:     my $Filename = shift;
1.5       foxr      179:     Debug("ReadKeyFile: $Filename");
                    180: 
1.3       foxr      181: 
                    182:     if(! open(KEYFILE, "<$Filename")) {
1.5       foxr      183: 	Debug(" Open of $Filename failed\n");
1.3       foxr      184: 	$lastError = "Key file open failed";
                    185: 	return undef
                    186:     }
                    187:     my $key = <KEYFILE>;
1.5       foxr      188:     chomp($key);
                    189:     Debug(" Read key: $key");
1.3       foxr      190:     close KEYFILE;
                    191:     unlink $Filename;
                    192:     #
                    193:     #  If the filename still exists some spoofer wrote it with the wrong
                    194:     #  permissions:
                    195:     #
                    196:     if(-e $Filename) {
1.5       foxr      197: 	Debug("File did not get deleted");
1.3       foxr      198: 	$lastError = "Key file still exists after unlink";
                    199: 	return undef;
                    200:     }
                    201:     #
                    202:     #  The IDEA key must be  IDEA::keysize*2 characters
                    203:     #  long.   If it  isn't probably someone's trying to break us by
                    204:     #  hitting the timing hole between the file write and read...
                    205:     #  replacing our file... of course if they read this comment they'll
                    206:     #  be too smart to put an incorrectly sized file
                    207:     #
1.5       foxr      208:     my $keylen = length($key);
                    209:     my $rightlen= IDEA::keysize()*2;
                    210:     if($keylen != $rightlen) {
                    211: 	Debug("Key is incorrect length is $keylen sb $rightlen");
1.3       foxr      212: 	$lastError = "Key file has incorrect length";
                    213: 	return undef;
                    214:     }
1.5       foxr      215:     Debug("Returning key: $key to caller");
1.3       foxr      216:     return $key;   
                    217: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>