--- loncom/lonssl.pm 2006/08/25 17:49:15 1.10 +++ loncom/lonssl.pm 2018/07/29 03:03:36 1.16 @@ -1,5 +1,5 @@ # -# $Id: lonssl.pm,v 1.10 2006/08/25 17:49:15 albertel Exp $ +# $Id: lonssl.pm,v 1.16 2018/07/29 03:03:36 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -37,6 +37,7 @@ use strict; use IO::Socket::INET; use IO::Socket::SSL; +use Net::SSLeay; use Fcntl; use POSIX; @@ -115,6 +116,7 @@ sub SetFdBlocking { # issued to this host. # KeyFile string Full pathname to the host's private # key file for the certificate. +# peer string lonHostID of remote LON-CAPA server # Returns # - Reference to an SSL socket on success # - undef on failure. Reason for failure can be interrogated from @@ -126,10 +128,11 @@ sub PromoteClientSocket { my ($PlaintextSocket, $CACert, $MyCert, - $KeyFile) = @_; + $KeyFile, + $peer) = @_; - Debug("Client promotion using key: $KeyFile, Cert: $MyCert, CA: $CACert\n"); + Debug("Client promotion using key: $KeyFile, Cert: $MyCert, CA: $CACert, Remote Host: $peer\n"); # To create the ssl socket we need to duplicate the existing # socket. Otherwise closing the ssl socket will close the plaintext socket @@ -141,12 +144,24 @@ sub PromoteClientSocket { my $dupfno = fcntl($PlaintextSocket, F_DUPFD, 0); Debug("Client promotion got dup = $dupfno\n"); + # Starting with IO::Socket::SSL rev. 1.79, carp warns that a verify + # mode of SSL_VERIFY_NONE should be explicitly set for client, if + # verification is not to be used, and SSL_verify_mode is not set. + # Starting with rev. 1.95, the default became SSL_VERIFY_PEER which + # prevents an SSL connection to lond unless SSL_verifycn_name is set + # to the lonHostID of the remote host, (and the remote certificate has + # the remote lonHostID as CN, and has been signed by the LON-CAPA CA. + # Set SSL_verify_mode to Net::SSLeay::VERIFY_PEER() instead of to + # SSL_VERIFY_PEER for compatibility with IO::Socket::SSL rev. 1.01 + # used by CentOS/RHEL/Scientific Linux 5). my $client = IO::Socket::SSL->new_from_fd($dupfno, - SSL_user_cert => 1, + SSL_use_cert => 1, SSL_key_file => $KeyFile, SSL_cert_file => $MyCert, - SSL_ca_fie => $CACert); + SSL_ca_file => $CACert, + SSL_verifycn_name => $peer, + SSL_verify_mode => Net::SSLeay::VERIFY_PEER()); if(!$client) { $lasterror = IO::Socket::SSL::errstr(); @@ -158,7 +173,7 @@ sub PromoteClientSocket { #---------------------------------------------------------------------- # Name PromoteServerSocket # Description Given an ordinary IO::Socket::INET Creates an SSL socket -# for a server that is connected to the same client.l +# for a server that is connected to the same client. # Parameters Name Type Description # Socket IO::Socket::INET Original ordinary socket. # CACert string Full path name to the certificate @@ -167,6 +182,7 @@ sub PromoteClientSocket { # issued to this host. # KeyFile string Full pathname to the host's private # key file for the certificate. +# peer string lonHostID of remote LON-CAPA client # Returns # - Reference to an SSL socket on success # - undef on failure. Reason for failure can be interrogated from @@ -178,7 +194,8 @@ sub PromoteServerSocket { my ($PlaintextSocket, $CACert, $MyCert, - $KeyFile) = @_; + $KeyFile, + $peer) = @_; @@ -196,10 +213,12 @@ sub PromoteServerSocket { Debug(" Fileno = $dupfno\n"); my $client = IO::Socket::SSL->new_from_fd($dupfno, SSL_server => 1, # Server role. - SSL_user_cert => 1, + SSL_use_cert => 1, SSL_key_file => $KeyFile, SSL_cert_file => $MyCert, - SSL_ca_fie => $CACert); + SSL_ca_file => $CACert, + SSL_verifycn_name => $peer, + SSL_verify_mode => Net::SSLeay::VERIFY_PEER()); if(!$client) { $lasterror = IO::Socket::SSL::errstr(); return undef; @@ -323,4 +342,64 @@ sub KeyFile { return $KeyFilename; } +sub Read_Connect_Config { + my ($secureconf,$perlvarref) = @_; + return unless (ref($secureconf) eq 'HASH'); + + unless (ref($perlvarref) eq 'HASH') { + $perlvarref = $perlvar; + } + + # Clean out the old table first. + foreach my $key (keys(%{$secureconf})) { + delete($secureconf->{$key}); + } + + my $result; + my $tablename = $perlvarref->{'lonTabDir'}."/connectionrules.tab"; + if (open(my $fh,"<$tablename")) { + while (my $line = <$fh>) { + chomp($line); + my ($name,$value) = split(/=/,$line); + if ($value =~ /^(?:no|yes|req)$/) { + if ($name =~ /^conn(to|from)_(dom|intdom|other)$/) { + $secureconf->{'conn'.$1}{$2} = $value; + } + } + } + close($fh); + return 'ok'; + } + return; +} + +sub Read_Host_Types { + my ($hosttypes,$perlvarref) = @_; + return unless (ref($hosttypes) eq 'HASH'); + + unless (ref($perlvarref) eq 'HASH') { + $perlvarref = $perlvar; + } + + # Clean out the old table first. + foreach my $key (keys(%{$hosttypes})) { + delete($hosttypes->{$key}); + } + + my $result; + my $tablename = $perlvarref->{'lonTabDir'}."/hosttypes.tab"; + if (open(my $fh,"<$tablename")) { + while (my $line = <$fh>) { + chomp($line); + my ($name,$value) = split(/:/,$line); + if (($name ne '') && ($value =~ /^(dom|intdom|other)$/)) { + $hosttypes->{$name} = $value; + } + } + close($fh); + return 'ok'; + } + return; +} + 1;