1#! /usr/bin/env perl 2# Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. 3# 4# Licensed under the Apache License 2.0 (the "License"). You may not use 5# this file except in compliance with the License. You can obtain a copy 6# in the file LICENSE in the source distribution or at 7# https://www.openssl.org/source/license.html 8 9use strict; 10use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/; 11use OpenSSL::Test::Utils; 12use TLSProxy::Proxy; 13 14my $test_name = "test_sslvertol"; 15setup($test_name); 16 17plan skip_all => "TLSProxy isn't usable on $^O" 18 if $^O =~ /^(VMS)$/; 19 20plan skip_all => "$test_name needs the dynamic engine feature enabled" 21 if disabled("engine") || disabled("dynamic-engine"); 22 23plan skip_all => "$test_name needs the sock feature enabled" 24 if disabled("sock"); 25 26plan skip_all => "$test_name needs TLS enabled" 27 if alldisabled(available_protocols("tls")); 28 29$ENV{OPENSSL_ia32cap} = '~0x200000200000000'; 30my $proxy = TLSProxy::Proxy->new( 31 \&vers_tolerance_filter, 32 cmdstr(app(["openssl"]), display => 1), 33 srctop_file("apps", "server.pem"), 34 (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}) 35); 36 37my @available_tls_versions = (); 38foreach (available_protocols("tls")) { 39 unless (disabled($_)) { 40 note("Checking enabled protocol $_"); 41 m|^([a-z]+)(\d)(_\d)?|; 42 my $versionname; 43 if (defined $3) { 44 $versionname = 'TLSProxy::Record::VERS_'.uc($1).'_'.$2.$3; 45 note("'$1', '$2', '$3' => $versionname"); 46 } else { 47 $versionname = 'TLSProxy::Record::VERS_'.uc($1).'_'.$2.'_0'; 48 note("'$1', '$2' => $versionname"); 49 } 50 push @available_tls_versions, eval $versionname; 51 } 52} 53note("TLS versions we can expect: ", join(", ", @available_tls_versions)); 54 55#This file does tests without the supported_versions extension. 56#See 70-test_sslversions.t for tests with supported versions. 57 58#Test 1: Asking for TLS1.4 should pass and negotiate the maximum 59#available TLS version according to configuration below TLS1.3 60my $client_version = TLSProxy::Record::VERS_TLS_1_4; 61my $previous_version = tls_version_below(TLSProxy::Record::VERS_TLS_1_3); 62$proxy->clientflags("-no_tls1_3"); 63$proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; 64plan tests => 3; 65SKIP: { 66 skip "There are too few protocols enabled for test 1", 1 67 unless defined $previous_version; 68 69 my $record = pop @{$proxy->record_list}; 70 ok((note("Record version received: ".$record->version()), 71 TLSProxy::Message->success()) 72 && $record->version() == $previous_version, 73 "Version tolerance test, below TLS 1.4 and not TLS 1.3"); 74} 75 76#Test 2: Asking for TLS1.3 with that disabled should succeed and negotiate 77#the highest configured TLS version below that. 78$client_version = TLSProxy::Record::VERS_TLS_1_3; 79$previous_version = tls_version_below($client_version); 80SKIP: { 81 skip "There are too few protocols enabled for test 2", 1 82 unless defined $previous_version; 83 84 $proxy->clear(); 85 $proxy->clientflags("-no_tls1_3"); 86 $proxy->start(); 87 my $record = pop @{$proxy->record_list}; 88 ok((note("Record version received: ".$record->version()), 89 TLSProxy::Message->success()) 90 && $record->version() == $previous_version, 91 "Version tolerance test, max version but not TLS 1.3"); 92} 93 94#Test 3: Testing something below SSLv3 should fail. We must disable TLS 1.3 95#to avoid having the 'supported_versions' extension kick in and override our 96#desires. 97$client_version = TLSProxy::Record::VERS_SSL_3_0 - 1; 98$proxy->clear(); 99$proxy->clientflags("-no_tls1_3"); 100$proxy->start(); 101my $record = pop @{$proxy->record_list}; 102ok((note("Record version received: ". 103 (defined $record ? $record->version() : "none")), 104 TLSProxy::Message->fail()), 105 "Version tolerance test, SSL < 3.0"); 106 107sub vers_tolerance_filter 108{ 109 my $proxy = shift; 110 111 # We're only interested in the initial ClientHello 112 if ($proxy->flight != 0) { 113 return; 114 } 115 116 foreach my $message (@{$proxy->message_list}) { 117 if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO) { 118 #Set the client version 119 #Anything above the max supported version should succeed 120 #Anything below SSLv3 should fail 121 $message->client_version($client_version); 122 $message->repack(); 123 } 124 } 125} 126 127sub tls_version_below { 128 if (@_) { 129 my $term = shift; 130 my $res = undef; 131 132 foreach (@available_tls_versions) { 133 $res = $_ if $_ < $term; 134 } 135 return $res; 136 } 137 return $available_tls_versions[-1]; 138} 139