[LON-CAPA-cvs] cvs: loncom / lonssl.pm
foxr
lon-capa-cvs@mail.lon-capa.org
Thu, 17 Jun 2004 09:27:38 -0000
foxr Thu Jun 17 05:27:38 2004 EDT
Modified files:
/loncom lonssl.pm
Log:
Debug ssl based key exchange support
Index: loncom/lonssl.pm
diff -u loncom/lonssl.pm:1.7 loncom/lonssl.pm:1.8
--- loncom/lonssl.pm:1.7 Tue Jun 1 05:53:44 2004
+++ loncom/lonssl.pm Thu Jun 17 05:27:38 2004
@@ -1,5 +1,5 @@
#
-# $Id: lonssl.pm,v 1.7 2004/06/01 09:53:44 foxr Exp $
+# $Id: lonssl.pm,v 1.8 2004/06/17 09:27:38 foxr Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -38,6 +38,9 @@
use IO::Socket::INET;
use IO::Socket::SSL;
+use Fcntl;
+use POSIX;
+
# Loncapa modules:
use LONCAPA::Configuration;
@@ -55,6 +58,39 @@
$perlvar = LONCAPA::Configuration::read_conf('loncapa.conf');
+my $lasterror="";
+
+
+sub LastError {
+ return $lasterror;
+}
+
+#-------------------------------------------------------------------------
+# Name SetFdBlocking -
+# Turn blocking mode on on the file handle. This is required for
+# SSL key negotiation.
+#
+# Parameters:
+# Handle - Reference to the handle to modify.
+# Returns:
+# prior flag settings.
+#
+sub SetFdBlocking {
+ print STDERR "SetFdBlocking called \n";
+ my $Handle = shift;
+
+
+
+ my $flags = fcntl($Handle, F_GETFL, 0);
+ if(!$flags) {
+ print STDERR "SetBLocking fcntl get faild $!\n";
+ }
+ my $newflags = $flags & (~ O_NONBLOCK); # Turn off O_NONBLOCK...
+ if(!fcntl($Handle, F_SETFL, $newflags)) {
+ print STDERR "Can't set non block mode $!\n";
+ }
+ return $flags;
+}
#--------------------------------------------------------------------------
#
@@ -73,6 +109,8 @@
# - Reference to an SSL socket on success
# - undef on failure. Reason for failure can be interrogated from
# IO::Socket::SSL
+# Side effects: socket is left in blocking mode!!
+#
sub PromoteClientSocket {
my ($PlaintextSocket,
@@ -81,18 +119,29 @@
$KeyFile) = @_;
+ print STDERR "Client promotion using key: $KeyFile, Cert: $MyCert, CA: $CACert\n";
+
# To create the ssl socket we need to duplicate the existing
# socket. Otherwise closing the ssl socket will close the plaintext socket
- # too:
-
- open (DUPLICATE, "+>$PlaintextSocket");
+ # too. We also must flip into blocking mode for the duration of the
+ # ssl negotiation phase.. the caller will have to flip to non block if
+ # that's what they want
+
+ my $oldflags = SetFdBlocking($PlaintextSocket);
+ my $dupfno = fcntl($PlaintextSocket, F_DUPFD, 0);
+ print STDERR "Client promotion got dup = $dupfno\n";
+
- my $client = IO::Socket::SSL->new_from_fd(fileno(DUPLICATE),
+ my $client = IO::Socket::SSL->new_from_fd($dupfno,
SSL_user_cert => 1,
SSL_key_file => $KeyFile,
SSL_cert_file => $MyCert,
- SSL_ca_fie => $$CACert);
+ SSL_ca_fie => $CACert);
+ if(!$client) {
+ $lasterror = IO::Socket::SSL::errstr();
+ return undef;
+ }
return $client; # Undef if the client negotiation fails.
}
@@ -112,6 +161,9 @@
# - Reference to an SSL socket on success
# - undef on failure. Reason for failure can be interrogated from
# IO::Socket::SSL
+# Side Effects:
+# Socket is left in blocking mode!!!
+#
sub PromoteServerSocket {
my ($PlaintextSocket,
$CACert,
@@ -124,14 +176,24 @@
# socket. Otherwise closing the ssl socket will close the plaintext socket
# too:
- open (DUPLICATE, "+>$PlaintextSocket");
-
- my $client = IO::Socket::SSL->new_from_fd(fileno(DUPLICATE),
+ print STDERR "Server promotion: Key = $KeyFile, Cert $MyCert CA $CACert\n";
+
+ my $oldflags = SetFdBlocking($PlaintextSocket);
+ my $dupfno = fcntl($PlaintextSocket, F_DUPFD, 0);
+ if (!$dupfno) {
+ print STDERR "dup failed: $!\n";
+ }
+ print STDERR " Fileno = $dupfno\n";
+ my $client = IO::Socket::SSL->new_from_fd($dupfno,
SSL_server => 1, # Server role.
SSL_user_cert => 1,
SSL_key_file => $KeyFile,
SSL_cert_file => $MyCert,
- SSL_ca_fie => $$CACert);
+ SSL_ca_fie => $CACert);
+ if(!$client) {
+ $lasterror = IO::Socket::SSL::errstr();
+ return undef;
+ }
return $client;
}
@@ -170,7 +232,7 @@
my $CertOwner = $SSLSocket->peer_certificate("owner");
my $CertCA = $SSLSocket->peer_certificate("authority");
- return \($CertCA, $CertOwner);
+ return ($CertCA, $CertOwner);
}
#----------------------------------------------------------------------------
#
@@ -193,6 +255,8 @@
# Ensure the existence of these variables:
if((!$CertificateDir) || (!$CaFilename) || (!$CertFilename)) {
+ $lasterror = "Missing info: dir: $CertificateDir CA: $CaFilename "
+ ."Cert: $CertFilename";
return undef;
}
@@ -203,12 +267,14 @@
my $CertFilename = $CertificateDir.$pathsep.$CertFilename;
if((! -r $CaFilename) || (! -r $CertFilename)) {
+ $lasterror = "CA file $CaFilename or Cert File: $CertFilename "
+ ."not readable";
return undef;
}
# Everything works fine!!
- return \($CaFilename, $CertFilename);
+ return ($CaFilename, $CertFilename);
}
#------------------------------------------------------------------------
@@ -230,6 +296,8 @@
# Ensure the variables exist:
if((!$CertificateDir) || (!$KeyFilename)) {
+ $lasterror = "Missing parameter dir: $CertificateDir "
+ ."key: $KeyFilename";
return undef;
}
@@ -238,6 +306,7 @@
my $KeyFilename = $CertificateDir.$pathsep.$KeyFilename;
if(! (-r $KeyFilename)) {
+ $lasterror = "Unreadable key file $KeyFilename";
return undef;
}