1: #
2: # $Id: lonssl.pm,v 1.6 2004/05/28 09:37: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 lonssl;
27: # lonssl.pm
28: # This file contains common functions used by lond and lonc when
29: # negotiating the exchange of the session encryption key via an
30: # SSL tunnel.
31: # See the POD sections and function documentation for more information.
32: #
33:
34: use strict;
35:
36: # CPAN/Standard modules:
37:
38: use English;
39: use IO::Socket::INET;
40: use IO::Socket::SSL;
41:
42: # Loncapa modules:
43:
44: use LONCAPA::Configuration;
45:
46: # Global storage:
47:
48: my $perlvar; # this refers to the apache perlsetvar
49: # variable hash.
50:
51: my $pathsep = "/"; # We're on unix after all.
52:
53:
54: # Initialization code:
55:
56: $perlvar = LONCAPA::Configuration::read_conf('loncapa.conf');
57:
58:
59:
60: #--------------------------------------------------------------------------
61: #
62: # Name PromoteClientSocket
63: # Description Given an ordinary IO::Socket::INET Creates an SSL socket
64: # for a client that is connected to the same server.
65: # Parameters Name Type Description
66: # Socket IO::Socket::INET Original ordinary socket.
67: # CACert string Full path name to the certificate
68: # authority certificate file.
69: # MyCert string Full path name to the certificate
70: # issued to this host.
71: # KeyFile string Full pathname to the host's private
72: # key file for the certificate.
73: # Returns
74: # - Reference to an SSL socket on success
75: # - undef on failure. Reason for failure can be interrogated from
76: # IO::Socket::SSL
77:
78: sub PromoteClientSocket {
79: my ($PlaintextSocket,
80: $CACert,
81: $MyCert,
82: $KeyFile) = @ARG;
83:
84:
85: # To create the ssl socket we need to duplicate the existing
86: # socket. Otherwise closing the ssl socket will close the plaintext socket
87: # too:
88:
89: open (DUPLICATE, "+>$PlaintextSocket");
90:
91: my $client = IO::Socket::SSL->new_from_fd(fileno(DUPLICATE),
92: SSL_user_cert => 1,
93: SSL_key_file => $KeyFile,
94: SSL_cert_file => $MyCert,
95: SSL_ca_fie => $$CACert);
96:
97: return $client; # Undef if the client negotiation fails.
98: }
99:
100: #----------------------------------------------------------------------
101: # Name PromoteServerSocket
102: # Description Given an ordinary IO::Socket::INET Creates an SSL socket
103: # for a server that is connected to the same client.l
104: # Parameters Name Type Description
105: # Socket IO::Socket::INET Original ordinary socket.
106: # CACert string Full path name to the certificate
107: # authority certificate file.
108: # MyCert string Full path name to the certificate
109: # issued to this host.
110: # KeyFile string Full pathname to the host's private
111: # key file for the certificate.
112: # Returns
113: # - Reference to an SSL socket on success
114: # - undef on failure. Reason for failure can be interrogated from
115: # IO::Socket::SSL
116: sub PromoteServerSocket {
117: my ($PlaintextSocket,
118: $CACert,
119: $MyCert,
120: $KeyFile) = @ARG;
121:
122:
123:
124: # To create the ssl socket we need to duplicate the existing
125: # socket. Otherwise closing the ssl socket will close the plaintext socket
126: # too:
127:
128: open (DUPLICATE, "+>$PlaintextSocket");
129:
130: my $client = IO::Socket::SSL->new_from_fd(fileno(DUPLICATE),
131: SSL_server => 1, # Server role.
132: SSL_user_cert => 1,
133: SSL_key_file => $KeyFile,
134: SSL_cert_file => $MyCert,
135: SSL_ca_fie => $$CACert);
136: return $client;
137: }
138:
139: #-------------------------------------------------------------------------
140: #
141: # Name: Close
142: # Description: Properly closes an ssl client or ssl server socket in
143: # a way that keeps the parent socket open.
144: # Parameters: Name Type Description
145: # Socket IO::Socket::SSL SSL Socket gotten from either
146: # PromoteClientSocket or
147: # PromoteServerSocket
148: # Returns:
149: # NONE
150: #
151: sub Close {
152: my $Socket = shift;
153:
154: $Socket->close(SSL_no_shutdown =>1); # Otherwise the parent socket
155: # gets torn down.
156: }
157: #---------------------------------------------------------------------------
158: #
159: # Name GetPeerCertificate
160: # Description Inquires about the certificate of the peer of a connection.
161: # Parameters Name Type Description
162: # SSLSocket IO::Socket::SSL SSL tunnel socket open on
163: # the peer.
164: # Returns
165: # A two element list. The first element of the list is the name of
166: # the certificate authority. The second element of the list is the name
167: # of the owner of the certificate.
168: sub GetPeerCertificate {
169: my $SSLSocket = shift;
170:
171: my $CertOwner = $SSLSocket->peer_certificate("owner");
172: my $CertCA = $SSLSocket->peer_certificate("authority");
173:
174: return \($CertCA, $CertOwner);
175: }
176: #----------------------------------------------------------------------------
177: #
178: # Name CertificateFile
179: # Description Locate the certificate files for this host.
180: # Returns
181: # Returns a two element array. The first element contains the name of
182: # the certificate file for this host. The second element contains the name
183: # of the certificate file for the CA that granted the certificate. If
184: # either file cannot be located, returns undef.
185: #
186: sub CertificateFile {
187:
188: # I need some perl variables from the configuration file for this:
189:
190: my $CertificateDir = $perlvar->{lonCertificateDirectory};
191: my $CaFilename = $perlvar->{lonnetCertificateAuthority};
192: my $CertFilename = $perlvar->{lonnetCertificate};
193:
194: # Ensure the existence of these variables:
195:
196: if((!$CertificateDir) || (!$CaFilename) || (!$CertFilename)) {
197: return undef;
198: }
199:
200: # Build the actual filenames and check for their existence and
201: # readability.
202:
203: my $CaFilename = $CertificateDir.$pathsep.$CaFilename;
204: my $CertFilename = $CertificateDir.$pathsep.$CertFilename;
205:
206: if((! -r $CaFilename) || (! -r $CertFilename)) {
207: return undef;
208: }
209:
210: # Everything works fine!!
211:
212: return \($CaFilename, $CertFilename);
213:
214: }
215: #------------------------------------------------------------------------
216: #
217: # Name KeyFile
218: # Description
219: # Returns the name of the private key file of the current host.
220: # Returns
221: # Returns the name of the key file or undef if the file cannot
222: # be found.
223: #
224: sub KeyFile {
225:
226: # I need some perl variables from the configuration file for this:
227:
228: my $CertificateDir = $perlvar->{lonCertificateDirectory};
229: my $KeyFilename = $perlvar->{lonnetPrivateKey};
230:
231: # Ensure the variables exist:
232:
233: if((!$CertificateDir) || (!$KeyFilename)) {
234: return undef;
235: }
236:
237: # Build the actual filename and ensure that it not only exists but
238: # is also readable:
239:
240: my $KeyFilename = $CertificateDir.$pathsep.$KeyFilename;
241: if(! (-r $KeyFilename)) {
242: return undef;
243: }
244:
245: return $KeyFilename;
246: }
247:
248: 1;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>