--- loncom/lonlocal.pm 2004/05/28 09:39:11 1.2 +++ loncom/lonlocal.pm 2004/05/28 10:20:03 1.3 @@ -1,5 +1,5 @@ # -# $Id: lonlocal.pm,v 1.2 2004/05/28 09:39:11 foxr Exp $ +# $Id: lonlocal.pm,v 1.3 2004/05/28 10:20:03 foxr Exp $ # # Copyright Michigan State University Board of Trustees # @@ -43,6 +43,7 @@ use strict; use English; use Crypt::IDEA; +use Fcntl; # LONCAPA modules @@ -51,6 +52,10 @@ 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. + # Initialization @@ -98,15 +103,96 @@ sub CreateCipherKey { # A two element list containing: # - The private key that was created # - The full path to the file that contains it. -# +# or undef on failure. sub CreateKeyFile { # To create the file we need some perlvars to tell us where the # certificate directory. We'll make a file named localkey.$pid # there, and set the mode before writing into it. # - + $fileindex++; + my $CertificateDir = $perlvar->{lonCertificateDirectory}; + my $Filename = $CertificateDir.$pathsep.".$fileindex.".$PID; + + # 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 ".$ERRNO; + 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; + + if(! open(KEYFILE, "<$Filename")) { + $lastError = "Key file open failed"; + return undef + } + my $key = ; + chomp; + close KEYFILE; + unlink $Filename; + # + # If the filename still exists some spoofer wrote it with the wrong + # permissions: + # + if(-e $Filename) { + $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 + # + if(length($key) != IDEA::keysize*2) { + $lastError = "Key file has incorrect length"; + return undef; + } + return $key; +}