summaryrefslogtreecommitdiffstats
path: root/util/perl/TLSProxy/Message.pm
diff options
context:
space:
mode:
Diffstat (limited to 'util/perl/TLSProxy/Message.pm')
-rw-r--r--util/perl/TLSProxy/Message.pm187
1 files changed, 158 insertions, 29 deletions
diff --git a/util/perl/TLSProxy/Message.pm b/util/perl/TLSProxy/Message.pm
index ce22187569..c5e822e90d 100644
--- a/util/perl/TLSProxy/Message.pm
+++ b/util/perl/TLSProxy/Message.pm
@@ -11,6 +11,7 @@ package TLSProxy::Message;
use TLSProxy::Alert;
+use constant DTLS_MESSAGE_HEADER_LENGTH => 12;
use constant TLS_MESSAGE_HEADER_LENGTH => 4;
#Message types
@@ -18,6 +19,7 @@ use constant {
MT_HELLO_REQUEST => 0,
MT_CLIENT_HELLO => 1,
MT_SERVER_HELLO => 2,
+ MT_HELLO_VERIFY_REQUEST => 3,
MT_NEW_SESSION_TICKET => 4,
MT_ENCRYPTED_EXTENSIONS => 8,
MT_CERTIFICATE => 11,
@@ -42,7 +44,9 @@ use constant {
use constant {
AL_DESC_CLOSE_NOTIFY => 0,
AL_DESC_UNEXPECTED_MESSAGE => 10,
+ AL_DESC_BAD_RECORD_MAC => 20,
AL_DESC_ILLEGAL_PARAMETER => 47,
+ AL_DESC_PROTOCOL_VERSION => 70,
AL_DESC_NO_RENEGOTIATION => 100
};
@@ -50,6 +54,7 @@ my %message_type = (
MT_HELLO_REQUEST, "HelloRequest",
MT_CLIENT_HELLO, "ClientHello",
MT_SERVER_HELLO, "ServerHello",
+ MT_HELLO_VERIFY_REQUEST, "HelloVerifyRequest",
MT_NEW_SESSION_TICKET, "NewSessionTicket",
MT_ENCRYPTED_EXTENSIONS, "EncryptedExtensions",
MT_CERTIFICATE, "Certificate",
@@ -172,6 +177,7 @@ sub get_messages
my $class = shift;
my $serverin = shift;
my $record = shift;
+ my $isdtls = shift;
my @messages = ();
my $message;
@@ -216,8 +222,14 @@ sub get_messages
$recoffset = $messlen - length($payload);
$payload .= substr($record->decrypt_data, 0, $recoffset);
push @message_frag_lens, $recoffset;
- $message = create_message($server, $mt, $payload,
- $startoffset);
+ if ($isdtls) {
+ # We must set $msgseq, $msgfrag, $msgfragoffs
+ die "Internal error: cannot handle partial dtls messages\n"
+ }
+ $message = create_message($server, $mt,
+ #$msgseq, $msgfrag, $msgfragoffs,
+ 0, 0, 0,
+ $payload, $startoffset, $isdtls);
push @messages, $message;
$payload = "";
@@ -232,21 +244,36 @@ sub get_messages
while ($record->decrypt_len > $recoffset) {
#We are at the start of a new message
- if ($record->decrypt_len - $recoffset < 4) {
+ my $msgheaderlen = $isdtls ? DTLS_MESSAGE_HEADER_LENGTH
+ : TLS_MESSAGE_HEADER_LENGTH;
+ if ($record->decrypt_len - $recoffset < $msgheaderlen) {
#Whilst technically probably valid we can't cope with this
die "End of record in the middle of a message header\n";
}
@message_rec_list = ($record);
my $lenhi;
my $lenlo;
- ($mt, $lenhi, $lenlo) = unpack('CnC',
- substr($record->decrypt_data,
- $recoffset));
+ my $msgseq;
+ my $msgfrag;
+ my $msgfragoffs;
+ if ($isdtls) {
+ my $msgfraghi;
+ my $msgfraglo;
+ my $msgfragoffshi;
+ my $msgfragoffslo;
+ ($mt, $lenhi, $lenlo, $msgseq, $msgfraghi, $msgfraglo, $msgfragoffshi, $msgfragoffslo) =
+ unpack('CnCnnCnC', substr($record->decrypt_data, $recoffset));
+ $msgfrag = ($msgfraghi << 8) | $msgfraglo;
+ $msgfragoffs = ($msgfragoffshi << 8) | $msgfragoffslo;
+ } else {
+ ($mt, $lenhi, $lenlo) =
+ unpack('CnC', substr($record->decrypt_data, $recoffset));
+ }
$messlen = ($lenhi << 8) | $lenlo;
- print " Message type: $message_type{$mt}\n";
+ print " Message type: $message_type{$mt}($mt)\n";
print " Message Length: $messlen\n";
$startoffset = $recoffset;
- $recoffset += 4;
+ $recoffset += $msgheaderlen;
$payload = "";
if ($recoffset <= $record->decrypt_len) {
@@ -257,8 +284,9 @@ sub get_messages
$messlen);
$recoffset += $messlen;
push @message_frag_lens, $messlen;
- $message = create_message($server, $mt, $payload,
- $startoffset);
+ $message = create_message($server, $mt, $msgseq,
+ $msgfrag, $msgfragoffs,
+ $payload, $startoffset, $isdtls);
push @messages, $message;
$payload = "";
@@ -307,14 +335,18 @@ sub get_messages
#construct it
sub create_message
{
- my ($server, $mt, $data, $startoffset) = @_;
+ my ($server, $mt, $msgseq, $msgfrag, $msgfragoffs, $data, $startoffset, $isdtls) = @_;
my $message;
#We only support ClientHello in this version...needs to be extended for
#others
if ($mt == MT_CLIENT_HELLO) {
$message = TLSProxy::ClientHello->new(
+ $isdtls,
$server,
+ $msgseq,
+ $msgfrag,
+ $msgfragoffs,
$data,
[@message_rec_list],
$startoffset,
@@ -323,7 +355,24 @@ sub create_message
$message->parse();
} elsif ($mt == MT_SERVER_HELLO) {
$message = TLSProxy::ServerHello->new(
+ $isdtls,
+ $server,
+ $msgseq,
+ $msgfrag,
+ $msgfragoffs,
+ $data,
+ [@message_rec_list],
+ $startoffset,
+ [@message_frag_lens]
+ );
+ $message->parse();
+ } elsif ($mt == MT_HELLO_VERIFY_REQUEST) {
+ $message = TLSProxy::HelloVerifyRequest->new(
+ $isdtls,
$server,
+ $msgseq,
+ $msgfrag,
+ $msgfragoffs,
$data,
[@message_rec_list],
$startoffset,
@@ -332,7 +381,11 @@ sub create_message
$message->parse();
} elsif ($mt == MT_ENCRYPTED_EXTENSIONS) {
$message = TLSProxy::EncryptedExtensions->new(
+ $isdtls,
$server,
+ $msgseq,
+ $msgfrag,
+ $msgfragoffs,
$data,
[@message_rec_list],
$startoffset,
@@ -341,7 +394,11 @@ sub create_message
$message->parse();
} elsif ($mt == MT_CERTIFICATE) {
$message = TLSProxy::Certificate->new(
+ $isdtls,
$server,
+ $msgseq,
+ $msgfrag,
+ $msgfragoffs,
$data,
[@message_rec_list],
$startoffset,
@@ -350,7 +407,11 @@ sub create_message
$message->parse();
} elsif ($mt == MT_CERTIFICATE_REQUEST) {
$message = TLSProxy::CertificateRequest->new(
+ $isdtls,
$server,
+ $msgseq,
+ $msgfrag,
+ $msgfragoffs,
$data,
[@message_rec_list],
$startoffset,
@@ -359,7 +420,11 @@ sub create_message
$message->parse();
} elsif ($mt == MT_CERTIFICATE_VERIFY) {
$message = TLSProxy::CertificateVerify->new(
+ $isdtls,
$server,
+ $msgseq,
+ $msgfrag,
+ $msgfragoffs,
$data,
[@message_rec_list],
$startoffset,
@@ -368,7 +433,11 @@ sub create_message
$message->parse();
} elsif ($mt == MT_SERVER_KEY_EXCHANGE) {
$message = TLSProxy::ServerKeyExchange->new(
+ $isdtls,
$server,
+ $msgseq,
+ $msgfrag,
+ $msgfragoffs,
$data,
[@message_rec_list],
$startoffset,
@@ -376,19 +445,36 @@ sub create_message
);
$message->parse();
} elsif ($mt == MT_NEW_SESSION_TICKET) {
- $message = TLSProxy::NewSessionTicket->new(
- $server,
- $data,
- [@message_rec_list],
- $startoffset,
- [@message_frag_lens]
- );
+ if ($isdtls) {
+ $message = TLSProxy::NewSessionTicket->new_dtls(
+ $server,
+ $msgseq,
+ $msgfrag,
+ $msgfragoffs,
+ $data,
+ [@message_rec_list],
+ $startoffset,
+ [@message_frag_lens]
+ );
+ } else {
+ $message = TLSProxy::NewSessionTicket->new(
+ $server,
+ $data,
+ [@message_rec_list],
+ $startoffset,
+ [@message_frag_lens]
+ );
+ }
$message->parse();
} else {
#Unknown message type
$message = TLSProxy::Message->new(
+ $isdtls,
$server,
$mt,
+ $msgseq,
+ $msgfrag,
+ $msgfragoffs,
$data,
[@message_rec_list],
$startoffset,
@@ -423,18 +509,26 @@ sub alert
sub new
{
my $class = shift;
- my ($server,
+ my ($isdtls,
+ $server,
$mt,
+ $msgseq,
+ $msgfrag,
+ $msgfragoffs,
$data,
$records,
$startoffset,
$message_frag_lens) = @_;
my $self = {
+ isdtls => $isdtls,
server => $server,
data => $data,
records => $records,
mt => $mt,
+ msgseq => $msgseq,
+ msgfrag => $msgfrag,
+ msgfragoffs => $msgfragoffs,
startoffset => $startoffset,
message_frag_lens => $message_frag_lens,
dupext => -1
@@ -463,12 +557,21 @@ sub repack
$self->set_message_contents();
- my $lenhi;
- my $lenlo;
+ my $lenlo = length($self->data) & 0xff;
+ my $lenhi = length($self->data) >> 8;
- $lenlo = length($self->data) & 0xff;
- $lenhi = length($self->data) >> 8;
- $msgdata = pack('CnC', $self->mt, $lenhi, $lenlo).$self->data;
+ if ($self->{isdtls}) {
+ my $msgfraghi = $self->msgfrag >> 8;
+ my $msgfraglo = $self->msgfrag & 0xff;
+ my $msgfragoffshi = $self->msgfragoffs >> 8;
+ my $msgfragoffslo = $self->msgfragoffs & 0xff;
+
+ $msgdata = pack('CnCnnCnC', $self->mt, $lenhi, $lenlo, $self->msgseq,
+ $msgfraghi, $msgfraglo,
+ $msgfragoffshi, $msgfragoffslo).$self->data;
+ } else {
+ $msgdata = pack('CnC', $self->mt, $lenhi, $lenlo).$self->data;
+ }
if ($numrecs == 0) {
#The message is fully contained within one record
@@ -476,13 +579,14 @@ sub repack
my $recdata = $rec->decrypt_data;
my $old_length;
+ my $msg_header_len = $self->{isdtls} ? DTLS_MESSAGE_HEADER_LENGTH
+ : TLS_MESSAGE_HEADER_LENGTH;
# We use empty message_frag_lens to indicates that pre-repacking,
# the message wasn't present. The first fragment length doesn't include
# the TLS header, so we need to check and compute the right length.
if (@{$self->message_frag_lens}) {
- $old_length = ${$self->message_frag_lens}[0] +
- TLS_MESSAGE_HEADER_LENGTH;
+ $old_length = ${$self->message_frag_lens}[0] + $msg_header_len;
} else {
$old_length = 0;
}
@@ -529,8 +633,7 @@ sub repack
$rec->len(length($rec->data));
#Update the fragment len in case we changed it above
- ${$self->message_frag_lens}[0] = length($msgdata)
- - TLS_MESSAGE_HEADER_LENGTH;
+ ${$self->message_frag_lens}[0] = length($msgdata) - $msg_header_len;
return;
}
@@ -578,6 +681,30 @@ sub mt
}
return $self->{mt};
}
+sub msgseq
+{
+ my $self = shift;
+ if (@_) {
+ $self->{msgseq} = shift;
+ }
+ return $self->{msgseq};
+}
+sub msgfrag
+{
+ my $self = shift;
+ if (@_) {
+ $self->{msgfrag} = shift;
+ }
+ return $self->{msgfrag};
+}
+sub msgfragoffs
+{
+ my $self = shift;
+ if (@_) {
+ $self->{msgfragoffs} = shift;
+ }
+ return $self->{msgfragoffs};
+}
sub data
{
my $self = shift;
@@ -613,7 +740,9 @@ sub message_frag_lens
sub encoded_length
{
my $self = shift;
- return TLS_MESSAGE_HEADER_LENGTH + length($self->data);
+ my $msg_header_len = $self->{isdtls} ? DTLS_MESSAGE_HEADER_LENGTH
+ : TLS_MESSAGE_HEADER_LENGTH;
+ return $msg_header_len + length($self->data);
}
sub dupext
{