--- loncom/LondConnection.pm 2018/09/02 18:30:54 1.53.2.1 +++ loncom/LondConnection.pm 2018/08/07 17:12:09 1.57 @@ -1,7 +1,7 @@ # This module defines and implements a class that represents # a connection to a lond daemon. # -# $Id: LondConnection.pm,v 1.53.2.1 2018/09/02 18:30:54 raeburn Exp $ +# $Id: LondConnection.pm,v 1.57 2018/08/07 17:12:09 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -40,10 +40,12 @@ use LONCAPA::lonlocal; use LONCAPA::lonssl; - - my $DebugLevel=0; my %perlvar; +my %secureconf; +my %badcerts; +my %hosttypes; +my %crlchecked; my $InsecureOk; # @@ -70,8 +72,21 @@ sub ReadConfig { my $perlvarref = read_conf('loncapa.conf'); %perlvar = %{$perlvarref}; $ConfigRead = 1; - + $InsecureOk = $perlvar{loncAllowInsecure}; + + unless (lonssl::Read_Connect_Config(\%secureconf,\%perlvar) eq 'ok') { + Debug(1,"Failed to retrieve secureconf hash.\n"); + } + unless (lonssl::Read_Host_Types(\%hosttypes,\%perlvar) eq 'ok') { + Debug(1,"Failed to retrieve hosttypes hash.\n"); + } + %badcerts = (); + %crlchecked = (); +} + +sub ResetReadConfig { + $ConfigRead = 0; } sub Debug { @@ -161,6 +176,21 @@ sub new { } &Debug(4,$class."::new( ".$DnsName.",".$Port.",".$lonid.")\n"); + my ($conntype,$gotconninfo,$allowinsecure); + if ((ref($secureconf{'connto'}) eq 'HASH') && + (exists($hosttypes{$lonid}))) { + $conntype = $secureconf{'connto'}{$hosttypes{$lonid}}; + if ($conntype ne '') { + if ($conntype ne 'req') { + $allowinsecure = 1; + } + $gotconninfo = 1; + } + } + unless ($gotconninfo) { + $allowinsecure = $InsecureOk; + } + # The host must map to an entry in the hosts table: # We connect to the dns host that corresponds to that # system and use the hostname for the encryption key @@ -176,6 +206,7 @@ sub new { Port => $Port, State => "Initialized", AuthenticationMode => "", + InsecureOK => $allowinsecure, TransactionRequest => "", TransactionReply => "", NextRequest => "", @@ -216,7 +247,15 @@ sub new { # allowed...else give up right away. if(!(defined $key) || !(defined $keyfile)) { - if($InsecureOk) { + my $canconnect = 0; + if (ref($secureconf{'connto'}) eq 'HASH') { + unless ($secureconf{'connto'}->{'dom'} eq 'req') { + $canconnect = 1; + } + } else { + $canconnect = $InsecureOk; + } + if ($canconnect) { $self->{AuthenticationMode} = "insecure"; $self->{TransactionRequest} = "init\n"; } @@ -239,20 +278,20 @@ sub new { my ($ca, $cert) = lonssl::CertificateFile; my $sslkeyfile = lonssl::KeyFile; + my $badcertfile = lonssl::has_badcert_file($self->{LoncapaHim}); - if((defined $ca) && (defined $cert) && (defined $sslkeyfile)) { - + if (($conntype ne 'no') && (defined($ca)) && (defined($cert)) && (defined($sslkeyfile)) && + (!exists($badcerts{$self->{LoncapaHim}})) && !$badcertfile) { $self->{AuthenticationMode} = "ssl"; $self->{TransactionRequest} = "init:ssl:$perlvar{'lonVersion'}\n"; + } elsif ($self->{InsecureOK}) { + # Allowed to do insecure: + $self->{AuthenticationMode} = "insecure"; + $self->{TransactionRequest} = "init::$perlvar{'lonVersion'}\n"; } else { - if($InsecureOk) { # Allowed to do insecure: - $self->{AuthenticationMode} = "insecure"; - $self->{TransactionRequest} = "init::$perlvar{'lonVersion'}\n"; - } - else { # Not allowed to do insecure... - $socket->close; - return undef; - } + # Not allowed to do insecure... + $socket->close; + return undef; } } @@ -399,20 +438,34 @@ sub Readable { } elsif ($ConnectionMode eq "ssl") { if($Response =~ /^ok:ssl/) { # Good ssl... - if($self->ExchangeKeysViaSSL()) { # Success skip to vsn stuff + my $sslresult = $self->ExchangeKeysViaSSL(); + if ($sslresult == 1) { # Success skip to vsn stuff # Need to reset to non blocking: my $flags = fcntl($socket, F_GETFL, 0); fcntl($socket, F_SETFL, $flags | O_NONBLOCK); $self->ToVersionRequest(); return 0; - } - else { # Failed in ssl exchange. + } + else { # Failed in ssl exchange. + if (($sslresult == -1) && (lonssl::LastError == -1) && ($self->{InsecureOK})) { + my $badcertdir = &lonssl::BadCertDir(); + if (($badcertdir) && $self->{LoncapaHim}) { + if (open(my $fh,'>',"$badcertdir/".$self->{LoncapaHim})) { + close($fh); + } + } + $badcerts{$self->{LoncapaHim}} = 1; + &Debug(3,"SSL verification failed: close socket and initiate insecure connection"); + $self->Transition("ReInitNoSSL"); + $socket->close; + return -1; + } &Debug(3,"init:ssl failed key negotiation!"); $self->Transition("Disconnected"); $socket->close; return -1; - } + } } elsif ($Response =~ /^[0-9]+/) { # Old style lond. return $self->CompleteInsecure(); @@ -1002,6 +1055,7 @@ sub CreateCipher { sub ExchangeKeysViaSSL { my $self = shift; my $socket = $self->{Socket}; + my $peer = $self->{LoncapaHim}; # Get our signed certificate, the certificate authority's # certificate and our private key file. All of these @@ -1010,13 +1064,19 @@ sub ExchangeKeysViaSSL { my ($SSLCACertificate, $SSLCertificate) = lonssl::CertificateFile(); my $SSLKey = lonssl::KeyFile(); - + my $CRLFile; + unless ($crlchecked{$peer}) { + $CRLFile = lonssl::CRLFile(); + $crlchecked{$peer} = 1; + } # Promote our connection to ssl and read the key from lond. my $SSLSocket = lonssl::PromoteClientSocket($socket, $SSLCACertificate, $SSLCertificate, - $SSLKey); + $SSLKey, + $peer, + $CRLFile); if(defined $SSLSocket) { my $key = <$SSLSocket>; lonssl::Close($SSLSocket); @@ -1032,7 +1092,7 @@ sub ExchangeKeysViaSSL { else { # Failed!! Debug(3, "Failed to negotiate SSL connection!"); - return 0; + return -1; } # should not get here return 0; @@ -1057,7 +1117,7 @@ sub ExchangeKeysViaSSL { # sub CompleteInsecure { my $self = shift; - if($InsecureOk) { + if ($self->{InsecureOK}) { $self->{AuthenticationMode} = "insecure"; &Debug(8," Transition out of Initialized:insecure"); $self->{TransactionRequest} = $self->{TransactionReply}; @@ -1169,6 +1229,15 @@ sub PeerLoncapaHim { return $self->{LoncapaHim}; } +# +# Get the Authentication mode +# + +sub GetKeyMode { + my $self = shift; + return $self->{AuthenticationMode}; +} + 1; =pod 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.