--- loncom/lonlocal.pm 2004/05/28 09:39:11 1.2 +++ loncom/lonlocal.pm 2004/06/17 10:15:46 1.6 @@ -1,5 +1,5 @@ # -# $Id: lonlocal.pm,v 1.2 2004/05/28 09:39:11 foxr Exp $ +# $Id: lonlocal.pm,v 1.6 2004/06/17 10:15:46 foxr Exp $ # # Copyright Michigan State University Board of Trustees # @@ -41,8 +41,8 @@ use strict; # CPAN/standard modules -use English; use Crypt::IDEA; +use Fcntl; # LONCAPA modules @@ -51,6 +51,19 @@ use LONCAPA::Configuration; # Global variables: my $perlvar; # Refers to the apache perlsetvar hash. +my $pathsep = "/"; # Unix path seperator +my $fileindex = 0; # Per process lonc uniquifier. +my $lastError; # Reason for last failure. + + +# Debugging: + +my $DEBUG = 0; + +sub Debug { + my $msg = shift; + print STDERR "$msg\n"; +} # Initialization @@ -59,7 +72,7 @@ $perlvar = LONCAPA::Configuration::read_ #------------------------------------------------------------------------ # -# Name BuildKey +# Name CreateCipherKey # Description: Create an encryption key. # Returns: The key. # @@ -69,13 +82,15 @@ sub CreateCipherKey { my $binaryKey; my $cipherkey; - # we'll use the output of /dev/random to produce our key. + # we'll use the output of /dev/urandom to produce our key. # On a system with decent entropy, this ought to be much more # random than all the playing that used to be done to get a key. - # + # On a system with not so decent entropy we'll still get an ok key. + # My concern with /dev/random is that we may block for an indefinite + # time period...where for us decent keys are probably good enough. $keylength = IDEA::keysize(); - open(RANDOM, "{lonCertificateDirectory}; + my $Filename = $CertificateDir.$pathsep.".$fileindex.".$$; + + # If this file already exists, this is a recoverable error... we just + # delete the earlier incarnation of the file. + + if (-w $Filename) { + unlink $Filename; + } + + # If the file still exists this is really really bad: + # It most likely means someone has been devious enough to drop a key file + # in place to attemp to spoof the lond. We'll fail in that case hoping + # that the user looks at the log to figure out that local connections + # are failing. + + if( -e $Filename) { + $lastError = "Key file already exists after deletion probably a spoof!"; + return undef; + } + # Now we can create the file we use sysopen in order to ensure + # the file is created with the appropriate locked down permissions. + + if(! sysopen(KEYFILE, $Filename, O_CREAT | O_EXCL | O_WRONLY, 0600)) { + $lastError = "Creation of key file failed ".$!; + return undef; + } + # Create the key, write it to the file and close the file: + + my $key = CreateCipherKey(); + print KEYFILE "$key\n"; + close KEYFILE; + + return ($key, $Filename); + } +# Name ReadKeyFile +# Description Opens the private local key file and reads the IDEA key from it. +# Parameters +# Name Type Description +# Filename string path to key file +# +# NOTE: +# Reading the keyfile is a one-time thing. This sub destroys the +# keyfile after reading it to ensure the one-timedness of the keys they +# contain!! +# Returns +# On success the IDEA key that was written into the key fileon failure undef. +# +# +sub ReadKeyFile { + my $Filename = shift; + Debug("ReadKeyFile: $Filename"); + + + if(! open(KEYFILE, "<$Filename")) { + Debug(" Open of $Filename failed\n"); + $lastError = "Key file open failed"; + return undef + } + my $key = ; + chomp($key); + Debug(" Read key: $key"); + close KEYFILE; + unlink $Filename; + # + # If the filename still exists some spoofer wrote it with the wrong + # permissions: + # + if(-e $Filename) { + Debug("File did not get deleted"); + $lastError = "Key file still exists after unlink"; + return undef; + } + # + # The IDEA key must be IDEA::keysize*2 characters + # long. If it isn't probably someone's trying to break us by + # hitting the timing hole between the file write and read... + # replacing our file... of course if they read this comment they'll + # be too smart to put an incorrectly sized file + # + my $keylen = length($key); + my $rightlen= IDEA::keysize()*2; + if($keylen != $rightlen) { + Debug("Key is incorrect length is $keylen sb $rightlen"); + $lastError = "Key file has incorrect length"; + return undef; + } + Debug("Returning key: $key to caller"); + return $key; +}