Empty NewSessionTicket: test session resumption
Reviewed-by: Matt Caswell <matt@openssl.org>
This commit is contained in:
parent
7f6d90ac75
commit
cf7f85927c
@ -82,7 +82,7 @@ my $proxy = TLSProxy::Proxy->new(
|
|||||||
top_file("apps", "server.pem")
|
top_file("apps", "server.pem")
|
||||||
);
|
);
|
||||||
|
|
||||||
plan tests => 6;
|
plan tests => 8;
|
||||||
|
|
||||||
#Test 1: By default with no existing session we should get a session ticket
|
#Test 1: By default with no existing session we should get a session ticket
|
||||||
#Expected result: ClientHello extension seen; ServerHello extension seen
|
#Expected result: ClientHello extension seen; ServerHello extension seen
|
||||||
@ -143,6 +143,28 @@ $proxy->filter(\&ticket_filter);
|
|||||||
$proxy->start();
|
$proxy->start();
|
||||||
checkmessages(6, "Empty ticket test", 1, 1, 1, 1);
|
checkmessages(6, "Empty ticket test", 1, 1, 1, 1);
|
||||||
|
|
||||||
|
#Test 7-8: Client keeps existing ticket on empty ticket.
|
||||||
|
clearall();
|
||||||
|
($fh, $session) = tempfile();
|
||||||
|
$proxy->serverconnects(3);
|
||||||
|
$proxy->filter(undef);
|
||||||
|
$proxy->clientflags("-sess_out ".$session);
|
||||||
|
$proxy->start();
|
||||||
|
$proxy->clear();
|
||||||
|
$proxy->clientflags("-sess_in ".$session." -sess_out ".$session);
|
||||||
|
$proxy->filter(\&inject_empty_ticket_filter);
|
||||||
|
$proxy->clientstart();
|
||||||
|
#Expected result: ClientHello extension seen; ServerHello extension seen;
|
||||||
|
# NewSessionTicket message seen; Abbreviated handshake.
|
||||||
|
checkmessages(7, "Empty ticket resumption test", 1, 1, 1, 0);
|
||||||
|
clearall();
|
||||||
|
$proxy->clientflags("-sess_in ".$session);
|
||||||
|
$proxy->filter(undef);
|
||||||
|
$proxy->clientstart();
|
||||||
|
#Expected result: ClientHello extension seen; ServerHello extension not seen;
|
||||||
|
# NewSessionTicket message not seen; Abbreviated handshake.
|
||||||
|
checkmessages(8, "Empty ticket resumption test", 1, 0, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
sub ticket_filter
|
sub ticket_filter
|
||||||
{
|
{
|
||||||
@ -156,6 +178,36 @@ sub ticket_filter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub inject_empty_ticket_filter {
|
||||||
|
my $proxy = shift;
|
||||||
|
|
||||||
|
foreach my $message (@{$proxy->message_list}) {
|
||||||
|
if ($message->mt == TLSProxy::Message::MT_NEW_SESSION_TICKET) {
|
||||||
|
# Only inject the message first time we're called.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my @new_message_list = ();
|
||||||
|
foreach my $message (@{$proxy->message_list}) {
|
||||||
|
push @new_message_list, $message;
|
||||||
|
if ($message->mt == TLSProxy::Message::MT_SERVER_HELLO) {
|
||||||
|
$message->set_extension(TLSProxy::ClientHello::EXT_SESSION_TICKET, "");
|
||||||
|
$message->repack();
|
||||||
|
# Tack NewSessionTicket onto the ServerHello record.
|
||||||
|
# This only works if the ServerHello is exactly one record.
|
||||||
|
my $record = ${$message->records}[0];
|
||||||
|
|
||||||
|
my $offset = $message->startoffset + $message->encoded_length;
|
||||||
|
my $newsessionticket = TLSProxy::NewSessionTicket->new(
|
||||||
|
1, "", [$record], $offset, []);
|
||||||
|
$newsessionticket->repack();
|
||||||
|
push @new_message_list, $newsessionticket;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$proxy->message_list([@new_message_list]);
|
||||||
|
}
|
||||||
|
|
||||||
sub checkmessages($$$$$$)
|
sub checkmessages($$$$$$)
|
||||||
{
|
{
|
||||||
my ($testno, $testname, $testch, $testsh, $testtickseen, $testhand) = @_;
|
my ($testno, $testname, $testch, $testsh, $testtickseen, $testhand) = @_;
|
||||||
|
@ -370,24 +370,34 @@ sub repack
|
|||||||
$lenhi = length($self->data) >> 8;
|
$lenhi = length($self->data) >> 8;
|
||||||
$msgdata = pack('CnC', $self->mt, $lenhi, $lenlo).$self->data;
|
$msgdata = pack('CnC', $self->mt, $lenhi, $lenlo).$self->data;
|
||||||
|
|
||||||
|
|
||||||
if ($numrecs == 0) {
|
if ($numrecs == 0) {
|
||||||
#The message is fully contained within one record
|
#The message is fully contained within one record
|
||||||
my ($rec) = @{$self->records};
|
my ($rec) = @{$self->records};
|
||||||
my $recdata = $rec->decrypt_data;
|
my $recdata = $rec->decrypt_data;
|
||||||
|
|
||||||
if (length($msgdata) != ${$self->message_frag_lens}[0]
|
my $old_length;
|
||||||
+ TLS_MESSAGE_HEADER_LENGTH) {
|
|
||||||
#Message length has changed! Better adjust the record length
|
# We use empty message_frag_lens to indicates that pre-repacking,
|
||||||
my $diff = length($msgdata) - ${$self->message_frag_lens}[0]
|
# the message wasn't present. The first fragment length doesn't include
|
||||||
- TLS_MESSAGE_HEADER_LENGTH;
|
# the TLS header, so we need to check and compute the right length.
|
||||||
$rec->len($rec->len + $diff);
|
if (@{$self->message_frag_lens}) {
|
||||||
|
$old_length = ${$self->message_frag_lens}[0] +
|
||||||
|
TLS_MESSAGE_HEADER_LENGTH;
|
||||||
|
} else {
|
||||||
|
$old_length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$rec->data(substr($recdata, 0, $self->startoffset)
|
my $prefix = substr($recdata, 0, $self->startoffset);
|
||||||
.($msgdata)
|
my $suffix = substr($recdata, $self->startoffset + $old_length);
|
||||||
.substr($recdata, ${$self->message_frag_lens}[0]
|
|
||||||
+ TLS_MESSAGE_HEADER_LENGTH));
|
$rec->decrypt_data($prefix.($msgdata).($suffix));
|
||||||
|
# TODO(openssl-team): don't keep explicit lengths.
|
||||||
|
# (If a length override is ever needed to construct invalid packets,
|
||||||
|
# use an explicit override field instead.)
|
||||||
|
$rec->decrypt_len(length($rec->decrypt_data));
|
||||||
|
$rec->len($rec->len + length($msgdata) - $old_length);
|
||||||
|
# Don't support re-encryption.
|
||||||
|
$rec->data($rec->decrypt_data);
|
||||||
|
|
||||||
#Update the fragment len in case we changed it above
|
#Update the fragment len in case we changed it above
|
||||||
${$self->message_frag_lens}[0] = length($msgdata)
|
${$self->message_frag_lens}[0] = length($msgdata)
|
||||||
@ -471,5 +481,10 @@ sub message_frag_lens
|
|||||||
}
|
}
|
||||||
return $self->{message_frag_lens};
|
return $self->{message_frag_lens};
|
||||||
}
|
}
|
||||||
|
sub encoded_length
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
return TLS_MESSAGE_HEADER_LENGTH + length($self->data);
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -93,9 +93,6 @@ sub new
|
|||||||
flight => 0,
|
flight => 0,
|
||||||
record_list => [],
|
record_list => [],
|
||||||
message_list => [],
|
message_list => [],
|
||||||
|
|
||||||
#Private
|
|
||||||
message_rec_list => []
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return bless $self, $class;
|
return bless $self, $class;
|
||||||
@ -110,7 +107,6 @@ sub clear
|
|||||||
$self->{flight} = 0;
|
$self->{flight} = 0;
|
||||||
$self->{record_list} = [];
|
$self->{record_list} = [];
|
||||||
$self->{message_list} = [];
|
$self->{message_list} = [];
|
||||||
$self->{message_rec_list} = [];
|
|
||||||
$self->{serverflags} = "";
|
$self->{serverflags} = "";
|
||||||
$self->{clientflags} = "";
|
$self->{clientflags} = "";
|
||||||
$self->{serverconnects} = 1;
|
$self->{serverconnects} = 1;
|
||||||
@ -274,7 +270,6 @@ sub clientstart
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sub process_packet
|
sub process_packet
|
||||||
{
|
{
|
||||||
my ($self, $server, $packet) = @_;
|
my ($self, $server, $packet) = @_;
|
||||||
@ -296,7 +291,6 @@ sub process_packet
|
|||||||
#list of messages in those records
|
#list of messages in those records
|
||||||
my @ret = TLSProxy::Record->get_records($server, $self->flight, $packet);
|
my @ret = TLSProxy::Record->get_records($server, $self->flight, $packet);
|
||||||
push @{$self->record_list}, @{$ret[0]};
|
push @{$self->record_list}, @{$ret[0]};
|
||||||
$self->{message_rec_list} = $ret[0];
|
|
||||||
push @{$self->{message_list}}, @{$ret[1]};
|
push @{$self->{message_list}}, @{$ret[1]};
|
||||||
|
|
||||||
print "\n";
|
print "\n";
|
||||||
@ -349,11 +343,6 @@ sub record_list
|
|||||||
my $self = shift;
|
my $self = shift;
|
||||||
return $self->{record_list};
|
return $self->{record_list};
|
||||||
}
|
}
|
||||||
sub message_list
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
return $self->{message_list};
|
|
||||||
}
|
|
||||||
sub success
|
sub success
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
@ -446,4 +435,16 @@ sub serverconnects
|
|||||||
}
|
}
|
||||||
return $self->{serverconnects};
|
return $self->{serverconnects};
|
||||||
}
|
}
|
||||||
|
# This is a bit ugly because the caller is responsible for keeping the records
|
||||||
|
# in sync with the updated message list; simply updating the message list isn't
|
||||||
|
# sufficient to get the proxy to forward the new message.
|
||||||
|
# But it does the trick for the one test (test_sslsessiontick) that needs it.
|
||||||
|
sub message_list
|
||||||
|
{
|
||||||
|
my $self = shift;
|
||||||
|
if (@_) {
|
||||||
|
$self->{message_list} = shift;
|
||||||
|
}
|
||||||
|
return $self->{message_list};
|
||||||
|
}
|
||||||
1;
|
1;
|
||||||
|
@ -80,7 +80,6 @@ sub new
|
|||||||
$self->{session} = "";
|
$self->{session} = "";
|
||||||
$self->{ciphersuite} = 0;
|
$self->{ciphersuite} = 0;
|
||||||
$self->{comp_meth} = 0;
|
$self->{comp_meth} = 0;
|
||||||
$self->{extensions_len} = 0;
|
|
||||||
$self->{extensions_data} = "";
|
$self->{extensions_data} = "";
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
@ -124,7 +123,6 @@ sub parse
|
|||||||
$self->session($session);
|
$self->session($session);
|
||||||
$self->ciphersuite($ciphersuite);
|
$self->ciphersuite($ciphersuite);
|
||||||
$self->comp_meth($comp_meth);
|
$self->comp_meth($comp_meth);
|
||||||
$self->extensions_len($extensions_len);
|
|
||||||
$self->extension_data(\%extensions);
|
$self->extension_data(\%extensions);
|
||||||
|
|
||||||
$self->process_data();
|
$self->process_data();
|
||||||
@ -149,6 +147,7 @@ sub set_message_contents
|
|||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $data;
|
my $data;
|
||||||
|
my $extensions = "";
|
||||||
|
|
||||||
$data = pack('n', $self->server_version);
|
$data = pack('n', $self->server_version);
|
||||||
$data .= $self->random;
|
$data .= $self->random;
|
||||||
@ -156,14 +155,16 @@ sub set_message_contents
|
|||||||
$data .= $self->session;
|
$data .= $self->session;
|
||||||
$data .= pack('n', $self->ciphersuite);
|
$data .= pack('n', $self->ciphersuite);
|
||||||
$data .= pack('C', $self->comp_meth);
|
$data .= pack('C', $self->comp_meth);
|
||||||
$data .= pack('n', $self->extensions_len);
|
|
||||||
foreach my $key (keys %{$self->extension_data}) {
|
foreach my $key (keys %{$self->extension_data}) {
|
||||||
my $extdata = ${$self->extension_data}{$key};
|
my $extdata = ${$self->extension_data}{$key};
|
||||||
$data .= pack("n", $key);
|
$extensions .= pack("n", $key);
|
||||||
$data .= pack("n", length($extdata));
|
$extensions .= pack("n", length($extdata));
|
||||||
$data .= $extdata;
|
$extensions .= $extdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$data .= pack('n', length($extensions));
|
||||||
|
$data .= $extensions;
|
||||||
$self->data($data);
|
$self->data($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,14 +217,6 @@ sub comp_meth
|
|||||||
}
|
}
|
||||||
return $self->{comp_meth};
|
return $self->{comp_meth};
|
||||||
}
|
}
|
||||||
sub extensions_len
|
|
||||||
{
|
|
||||||
my $self = shift;
|
|
||||||
if (@_) {
|
|
||||||
$self->{extensions_len} = shift;
|
|
||||||
}
|
|
||||||
return $self->{extensions_len};
|
|
||||||
}
|
|
||||||
sub extension_data
|
sub extension_data
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
@ -232,4 +225,9 @@ sub extension_data
|
|||||||
}
|
}
|
||||||
return $self->{extension_data};
|
return $self->{extension_data};
|
||||||
}
|
}
|
||||||
|
sub set_extension
|
||||||
|
{
|
||||||
|
my ($self, $ext_type, $ext_data) = @_;
|
||||||
|
$self->{extension_data}{$ext_type} = $ext_data;
|
||||||
|
}
|
||||||
1;
|
1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user