1: #
2: # $Id: lonlocal.pm,v 1.3 2004/05/28 10:20:03 foxr Exp $
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 English;
45: use Crypt::IDEA;
46: use Fcntl;
47:
48: # LONCAPA modules
49:
50: use LONCAPA::Configuration;
51:
52: # Global variables:
53:
54: my $perlvar; # Refers to the apache perlsetvar hash.
55: my $pathsep = "/"; # Unix path seperator
56: my $fileindex = 0; # Per process lonc uniquifier.
57: my $lastError; # Reason for last failure.
58:
59:
60: # Initialization
61:
62: $perlvar = LONCAPA::Configuration::read_conf('loncapa.conf');
63:
64:
65: #------------------------------------------------------------------------
66: #
67: # Name BuildKey
68: # Description: Create an encryption key.
69: # Returns: The key.
70: #
71: sub CreateCipherKey {
72:
73: my $keylength;
74: my $binaryKey;
75: my $cipherkey;
76:
77: # we'll use the output of /dev/random to produce our key.
78: # On a system with decent entropy, this ought to be much more
79: # random than all the playing that used to be done to get a key.
80: #
81:
82: $keylength = IDEA::keysize();
83: open(RANDOM, "</dev/random");
84: sysread(RANDOM, $binaryKey, $keylength);
85: close RANDOM;
86:
87: # The key must be returned in a stringified form in order to be
88: # transmitted to the peer:
89:
90: my $hexdigits = $keylength*2; # Assume 8 bits/byte.
91: my $template = "H".$hexdigits;
92: $cipherkey = unpack($template, $binaryKey);
93:
94: return $cipherkey;
95: }
96:
97: #------------------------------------------------------------------------
98: #
99: # Name CreateKeyFile
100: # Description Creates a private key file and writes an IDEA key into it.
101: #
102: # Returns
103: # A two element list containing:
104: # - The private key that was created
105: # - The full path to the file that contains it.
106: # or undef on failure.
107: sub CreateKeyFile {
108:
109: # To create the file we need some perlvars to tell us where the
110: # certificate directory. We'll make a file named localkey.$pid
111: # there, and set the mode before writing into it.
112: #
113: $fileindex++;
114: my $CertificateDir = $perlvar->{lonCertificateDirectory};
115: my $Filename = $CertificateDir.$pathsep.".$fileindex.".$PID;
116:
117: # If this file already exists, this is a recoverable error... we just
118: # delete the earlier incarnation of the file.
119:
120: if (-w $Filename) {
121: unlink $Filename;
122: }
123:
124: # If the file still exists this is really really bad:
125: # It most likely means someone has been devious enough to drop a key file
126: # in place to attemp to spoof the lond. We'll fail in that case hoping
127: # that the user looks at the log to figure out that local connections
128: # are failing.
129:
130: if( -e $Filename) {
131: $lastError = "Key file already exists after deletion probably a spoof!";
132: return undef;
133: }
134: # Now we can create the file we use sysopen in order to ensure
135: # the file is created with the appropriate locked down permissions.
136:
137: if(! sysopen(KEYFILE, $Filename, O_CREAT | O_EXCL | O_WRONLY, 0600)) {
138: $lastError = "Creation of key file failed ".$ERRNO;
139: return undef;
140: }
141: # Create the key, write it to the file and close the file:
142:
143: my $key = CreateCipherKey();
144: print KEYFILE "$key\n";
145: close KEYFILE;
146:
147: return \($key, $Filename);
148:
149:
150: }
151:
152:
153: # Name ReadKeyFile
154: # Description Opens the private local key file and reads the IDEA key from it.
155: # Parameters
156: # Name Type Description
157: # Filename string path to key file
158: #
159: # NOTE:
160: # Reading the keyfile is a one-time thing. This sub destroys the
161: # keyfile after reading it to ensure the one-timedness of the keys they
162: # contain!!
163: # Returns
164: # On success the IDEA key that was written into the key fileon failure undef.
165: #
166: #
167: sub ReadKeyFile {
168: my $Filename = shift;
169:
170: if(! open(KEYFILE, "<$Filename")) {
171: $lastError = "Key file open failed";
172: return undef
173: }
174: my $key = <KEYFILE>;
175: chomp;
176: close KEYFILE;
177: unlink $Filename;
178: #
179: # If the filename still exists some spoofer wrote it with the wrong
180: # permissions:
181: #
182: if(-e $Filename) {
183: $lastError = "Key file still exists after unlink";
184: return undef;
185: }
186: #
187: # The IDEA key must be IDEA::keysize*2 characters
188: # long. If it isn't probably someone's trying to break us by
189: # hitting the timing hole between the file write and read...
190: # replacing our file... of course if they read this comment they'll
191: # be too smart to put an incorrectly sized file
192: #
193: if(length($key) != IDEA::keysize*2) {
194: $lastError = "Key file has incorrect length";
195: return undef;
196: }
197: return $key;
198: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>