Add a capability for TLSProxy to wait for a session before killing s_client
authorMatt Caswell <matt@openssl.org>
Fri, 20 Jan 2017 12:08:51 +0000 (12:08 +0000)
committerMatt Caswell <matt@openssl.org>
Mon, 30 Jan 2017 10:18:22 +0000 (10:18 +0000)
TLSProxy normally fires off s_client, which creates a connection to the
server. TLSProxy also pipes some data to send to the process and s_client
automatically exits when the pipe hits eof. Unfortunately this means that
it sends the data and closes before it has processed the NewSessionTicket
returned from the server in TLSv1.3. This commits adds an option for
s_client to stay loaded until the sesion has been processed. A side effect
of this is that s_client never sends a close_notify in this mode, so we
count success as seeing that data has been transferred.

Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2259)

util/TLSProxy/Message.pm
util/TLSProxy/Proxy.pm

index 99c3689..ab90586 100644 (file)
@@ -74,6 +74,7 @@ use constant {
     EXT_EXTENDED_MASTER_SECRET => 23,
     EXT_SESSION_TICKET => 35,
     EXT_KEY_SHARE => 40,
+    EXT_PSK => 41,
     EXT_SUPPORTED_VERSIONS => 43,
     EXT_PSK_KEX_MODES => 45,
     EXT_RENEGOTIATE => 65281,
@@ -99,6 +100,7 @@ my $end = 0;
 my @message_rec_list = ();
 my @message_frag_lens = ();
 my $ciphersuite = 0;
+my $successondata = 0;
 
 sub clear
 {
@@ -108,6 +110,7 @@ sub clear
     $server = 0;
     $success = 0;
     $end = 0;
+    $successondata = 0;
     @message_rec_list = ();
     @message_frag_lens = ();
 }
@@ -219,6 +222,11 @@ sub get_messages
     } elsif ($record->content_type == TLSProxy::Record::RT_APPLICATION_DATA) {
         print "  [ENCRYPTED APPLICATION DATA]\n";
         print "  [".$record->decrypt_data."]\n";
+
+        if ($successondata) {
+            $success = 1;
+            $end = 1;
+        }
     } elsif ($record->content_type == TLSProxy::Record::RT_ALERT) {
         my ($alertlev, $alertdesc) = unpack('CC', $record->decrypt_data);
         #A CloseNotify from the client indicates we have finished successfully
@@ -507,5 +515,12 @@ sub encoded_length
     my $self = shift;
     return TLS_MESSAGE_HEADER_LENGTH + length($self->data);
 }
-
+sub successondata
+{
+    my $class = shift;
+    if (@_) {
+        $successondata = shift;
+    }
+    return $successondata;
+}
 1;
index 2e90ab0..cee3bc5 100644 (file)
@@ -49,6 +49,7 @@ sub new
         serverconnects => 1,
         serverpid => 0,
         reneg => 0,
+        sessionfile => undef,
 
         #Public read
         execute => $execute,
@@ -110,6 +111,7 @@ sub clearClient
     $self->{record_list} = [];
     $self->{message_list} = [];
     $self->{clientflags} = "";
+    $self->{sessionfile} = undef;
     $is_tls13 = 0;
     $ciphersuite = undef;
 
@@ -226,6 +228,9 @@ sub clientstart
             if ($self->clientflags ne "") {
                 $execcmd .= " ".$self->clientflags;
             }
+            if (defined $self->sessionfile) {
+                $execcmd .= " -ign_eof";
+            }
             exec($execcmd);
         }
     }
@@ -295,6 +300,16 @@ sub clientstart
         }
     }
 
+    for (my $ctr = 0;
+         defined $self->sessionfile()
+            && (!(-f $self->sessionfile()) || $ctr == 3);
+         $ctr++) {
+        sleep 1;
+    }
+
+    die "Session file not created"
+        if (defined $self->sessionfile() && !(-f $self->sessionfile()));
+
     END:
     print "Connection closed\n";
     if($server_sock) {
@@ -540,6 +555,22 @@ sub reneg
     return $self->{reneg};
 }
 
+#Setting a sessionfile means that the client will not close until the given
+#file exists. This is useful in TLSv1.3 where otherwise s_client will close
+#immediately at the end of the handshake, but before the session has been
+#received from the server. A side effect of this is that s_client never sends
+#a close_notify, so instead we consider success to be when it sends application
+#data over the connection.
+sub sessionfile
+{
+    my $self = shift;
+    if (@_) {
+        $self->{sessionfile} = shift;
+        TLSProxy::Message->successondata(1);
+    }
+    return $self->{sessionfile};
+}
+
 sub ciphersuite
 {
     my $class = shift;