1*a7148ab3SEnji Cooper# Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. 2e0c4386eSCy Schubert# 3e0c4386eSCy Schubert# Licensed under the Apache License 2.0 (the "License"). You may not use 4e0c4386eSCy Schubert# this file except in compliance with the License. You can obtain a copy 5e0c4386eSCy Schubert# in the file LICENSE in the source distribution or at 6e0c4386eSCy Schubert# https://www.openssl.org/source/license.html 7e0c4386eSCy Schubert 8e0c4386eSCy Schubertpackage OpenSSL::Test::Utils; 9e0c4386eSCy Schubert 10e0c4386eSCy Schubertuse strict; 11e0c4386eSCy Schubertuse warnings; 12e0c4386eSCy Schubert 13e0c4386eSCy Schubertuse Exporter; 14e0c4386eSCy Schubertuse vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); 15e0c4386eSCy Schubert$VERSION = "0.1"; 16e0c4386eSCy Schubert@ISA = qw(Exporter); 17e0c4386eSCy Schubert@EXPORT = qw(alldisabled anydisabled disabled config available_protocols 18e0c4386eSCy Schubert have_IPv4 have_IPv6); 19e0c4386eSCy Schubert 20e0c4386eSCy Schubert=head1 NAME 21e0c4386eSCy Schubert 22e0c4386eSCy SchubertOpenSSL::Test::Utils - test utility functions 23e0c4386eSCy Schubert 24e0c4386eSCy Schubert=head1 SYNOPSIS 25e0c4386eSCy Schubert 26e0c4386eSCy Schubert use OpenSSL::Test::Utils; 27e0c4386eSCy Schubert 28e0c4386eSCy Schubert my @tls = available_protocols("tls"); 29e0c4386eSCy Schubert my @dtls = available_protocols("dtls"); 30e0c4386eSCy Schubert alldisabled("dh", "dsa"); 31e0c4386eSCy Schubert anydisabled("dh", "dsa"); 32e0c4386eSCy Schubert 33e0c4386eSCy Schubert config("fips"); 34e0c4386eSCy Schubert 35e0c4386eSCy Schubert have_IPv4(); 36e0c4386eSCy Schubert have_IPv6(); 37e0c4386eSCy Schubert 38e0c4386eSCy Schubert=head1 DESCRIPTION 39e0c4386eSCy Schubert 40e0c4386eSCy SchubertThis module provides utility functions for the testing framework. 41e0c4386eSCy Schubert 42e0c4386eSCy Schubert=cut 43e0c4386eSCy Schubert 44e0c4386eSCy Schubertuse OpenSSL::Test qw/:DEFAULT bldtop_file/; 45e0c4386eSCy Schubert 46e0c4386eSCy Schubert=over 4 47e0c4386eSCy Schubert 48e0c4386eSCy Schubert=item B<available_protocols STRING> 49e0c4386eSCy Schubert 50e0c4386eSCy SchubertReturns a list of strings for all the available SSL/TLS versions if 51e0c4386eSCy SchubertSTRING is "tls", or for all the available DTLS versions if STRING is 52e0c4386eSCy Schubert"dtls". Otherwise, it returns the empty list. The strings in the 53e0c4386eSCy Schubertreturned list can be used with B<alldisabled> and B<anydisabled>. 54e0c4386eSCy Schubert 55e0c4386eSCy Schubert=item B<alldisabled ARRAY> 56e0c4386eSCy Schubert 57e0c4386eSCy Schubert=item B<anydisabled ARRAY> 58e0c4386eSCy Schubert 59e0c4386eSCy SchubertIn an array context returns an array with each element set to 1 if the 60e0c4386eSCy Schubertcorresponding feature is disabled and 0 otherwise. 61e0c4386eSCy Schubert 62e0c4386eSCy SchubertIn a scalar context, alldisabled returns 1 if all of the features in 63e0c4386eSCy SchubertARRAY are disabled, while anydisabled returns 1 if any of them are 64e0c4386eSCy Schubertdisabled. 65e0c4386eSCy Schubert 66e0c4386eSCy Schubert=item B<config STRING> 67e0c4386eSCy Schubert 68e0c4386eSCy SchubertReturns an item from the %config hash in \$TOP/configdata.pm. 69e0c4386eSCy Schubert 70e0c4386eSCy Schubert=item B<have_IPv4> 71e0c4386eSCy Schubert 72e0c4386eSCy Schubert=item B<have_IPv6> 73e0c4386eSCy Schubert 74e0c4386eSCy SchubertReturn true if IPv4 / IPv6 is possible to use on the current system. 75*a7148ab3SEnji CooperAdditionally, B<have_IPv6> also checks how OpenSSL was configured, 76*a7148ab3SEnji Cooperi.e. if IPv6 was explicitly disabled with -DOPENSSL_USE_IPv6=0. 77e0c4386eSCy Schubert 78e0c4386eSCy Schubert=back 79e0c4386eSCy Schubert 80e0c4386eSCy Schubert=cut 81e0c4386eSCy Schubert 82e0c4386eSCy Schubertour %available_protocols; 83e0c4386eSCy Schubertour %disabled; 84e0c4386eSCy Schubertour %config; 85*a7148ab3SEnji Cooperour %target; 86e0c4386eSCy Schubertmy $configdata_loaded = 0; 87e0c4386eSCy Schubert 88e0c4386eSCy Schubertsub load_configdata { 89e0c4386eSCy Schubert # We eval it so it doesn't run at compile time of this file. 90e0c4386eSCy Schubert # The latter would have bldtop_file() complain that setup() hasn't 91e0c4386eSCy Schubert # been run yet. 92e0c4386eSCy Schubert my $configdata = bldtop_file("configdata.pm"); 93e0c4386eSCy Schubert eval { require $configdata; 94e0c4386eSCy Schubert %available_protocols = %configdata::available_protocols; 95e0c4386eSCy Schubert %disabled = %configdata::disabled; 96e0c4386eSCy Schubert %config = %configdata::config; 97*a7148ab3SEnji Cooper %target = %configdata::target; 98e0c4386eSCy Schubert }; 99e0c4386eSCy Schubert $configdata_loaded = 1; 100e0c4386eSCy Schubert} 101e0c4386eSCy Schubert 102e0c4386eSCy Schubert# args 103e0c4386eSCy Schubert# list of 1s and 0s, coming from check_disabled() 104e0c4386eSCy Schubertsub anyof { 105e0c4386eSCy Schubert my $x = 0; 106e0c4386eSCy Schubert foreach (@_) { $x += $_ } 107e0c4386eSCy Schubert return $x > 0; 108e0c4386eSCy Schubert} 109e0c4386eSCy Schubert 110e0c4386eSCy Schubert# args 111e0c4386eSCy Schubert# list of 1s and 0s, coming from check_disabled() 112e0c4386eSCy Schubertsub allof { 113e0c4386eSCy Schubert my $x = 1; 114e0c4386eSCy Schubert foreach (@_) { $x *= $_ } 115e0c4386eSCy Schubert return $x > 0; 116e0c4386eSCy Schubert} 117e0c4386eSCy Schubert 118e0c4386eSCy Schubert# args 119e0c4386eSCy Schubert# list of strings, all of them should be names of features 120e0c4386eSCy Schubert# that can be disabled. 121e0c4386eSCy Schubert# returns a list of 1s (if the corresponding feature is disabled) 122e0c4386eSCy Schubert# and 0s (if it isn't) 123e0c4386eSCy Schubertsub check_disabled { 124e0c4386eSCy Schubert return map { exists $disabled{lc $_} ? 1 : 0 } @_; 125e0c4386eSCy Schubert} 126e0c4386eSCy Schubert 127e0c4386eSCy Schubert# Exported functions ################################################# 128e0c4386eSCy Schubert 129e0c4386eSCy Schubert# args: 130e0c4386eSCy Schubert# list of features to check 131e0c4386eSCy Schubertsub anydisabled { 132e0c4386eSCy Schubert load_configdata() unless $configdata_loaded; 133e0c4386eSCy Schubert my @ret = check_disabled(@_); 134e0c4386eSCy Schubert return @ret if wantarray; 135e0c4386eSCy Schubert return anyof(@ret); 136e0c4386eSCy Schubert} 137e0c4386eSCy Schubert 138e0c4386eSCy Schubert# args: 139e0c4386eSCy Schubert# list of features to check 140e0c4386eSCy Schubertsub alldisabled { 141e0c4386eSCy Schubert load_configdata() unless $configdata_loaded; 142e0c4386eSCy Schubert my @ret = check_disabled(@_); 143e0c4386eSCy Schubert return @ret if wantarray; 144e0c4386eSCy Schubert return allof(@ret); 145e0c4386eSCy Schubert} 146e0c4386eSCy Schubert 147e0c4386eSCy Schubert# !!! Kept for backward compatibility 148e0c4386eSCy Schubert# args: 149e0c4386eSCy Schubert# single string 150e0c4386eSCy Schubertsub disabled { 151e0c4386eSCy Schubert anydisabled(@_); 152e0c4386eSCy Schubert} 153e0c4386eSCy Schubert 154e0c4386eSCy Schubertsub available_protocols { 155e0c4386eSCy Schubert load_configdata() unless $configdata_loaded; 156e0c4386eSCy Schubert my $protocol_class = shift; 157e0c4386eSCy Schubert if (exists $available_protocols{lc $protocol_class}) { 158e0c4386eSCy Schubert return @{$available_protocols{lc $protocol_class}} 159e0c4386eSCy Schubert } 160e0c4386eSCy Schubert return (); 161e0c4386eSCy Schubert} 162e0c4386eSCy Schubert 163e0c4386eSCy Schubertsub config { 164e0c4386eSCy Schubert load_configdata() unless $configdata_loaded; 165e0c4386eSCy Schubert return $config{$_[0]}; 166e0c4386eSCy Schubert} 167e0c4386eSCy Schubert 168e0c4386eSCy Schubert# IPv4 / IPv6 checker 169e0c4386eSCy Schubertmy $have_IPv4 = -1; 170e0c4386eSCy Schubertmy $have_IPv6 = -1; 171e0c4386eSCy Schubertmy $IP_factory; 172e0c4386eSCy Schubertsub check_IP { 173e0c4386eSCy Schubert my $listenaddress = shift; 174e0c4386eSCy Schubert 175e0c4386eSCy Schubert eval { 176e0c4386eSCy Schubert require IO::Socket::IP; 177e0c4386eSCy Schubert my $s = IO::Socket::IP->new( 178e0c4386eSCy Schubert LocalAddr => $listenaddress, 179e0c4386eSCy Schubert LocalPort => 0, 180e0c4386eSCy Schubert Listen=>1, 181e0c4386eSCy Schubert ); 182e0c4386eSCy Schubert $s or die "\n"; 183e0c4386eSCy Schubert $s->close(); 184e0c4386eSCy Schubert }; 185e0c4386eSCy Schubert if ($@ eq "") { 186e0c4386eSCy Schubert return 1; 187e0c4386eSCy Schubert } 188e0c4386eSCy Schubert 189e0c4386eSCy Schubert eval { 190e0c4386eSCy Schubert require IO::Socket::INET6; 191e0c4386eSCy Schubert my $s = IO::Socket::INET6->new( 192e0c4386eSCy Schubert LocalAddr => $listenaddress, 193e0c4386eSCy Schubert LocalPort => 0, 194e0c4386eSCy Schubert Listen=>1, 195e0c4386eSCy Schubert ); 196e0c4386eSCy Schubert $s or die "\n"; 197e0c4386eSCy Schubert $s->close(); 198e0c4386eSCy Schubert }; 199e0c4386eSCy Schubert if ($@ eq "") { 200e0c4386eSCy Schubert return 1; 201e0c4386eSCy Schubert } 202e0c4386eSCy Schubert 203e0c4386eSCy Schubert eval { 204e0c4386eSCy Schubert require IO::Socket::INET; 205e0c4386eSCy Schubert my $s = IO::Socket::INET->new( 206e0c4386eSCy Schubert LocalAddr => $listenaddress, 207e0c4386eSCy Schubert LocalPort => 0, 208e0c4386eSCy Schubert Listen=>1, 209e0c4386eSCy Schubert ); 210e0c4386eSCy Schubert $s or die "\n"; 211e0c4386eSCy Schubert $s->close(); 212e0c4386eSCy Schubert }; 213e0c4386eSCy Schubert if ($@ eq "") { 214e0c4386eSCy Schubert return 1; 215e0c4386eSCy Schubert } 216e0c4386eSCy Schubert 217e0c4386eSCy Schubert return 0; 218e0c4386eSCy Schubert} 219e0c4386eSCy Schubert 220e0c4386eSCy Schubertsub have_IPv4 { 221e0c4386eSCy Schubert if ($have_IPv4 < 0) { 222e0c4386eSCy Schubert $have_IPv4 = check_IP("127.0.0.1"); 223e0c4386eSCy Schubert } 224e0c4386eSCy Schubert return $have_IPv4; 225e0c4386eSCy Schubert} 226e0c4386eSCy Schubert 227e0c4386eSCy Schubertsub have_IPv6 { 228e0c4386eSCy Schubert if ($have_IPv6 < 0) { 229*a7148ab3SEnji Cooper load_configdata() unless $configdata_loaded; 230*a7148ab3SEnji Cooper # If OpenSSL is configured with IPv6 explicitly disabled, no IPv6 231*a7148ab3SEnji Cooper # related tests should be performed. In other words, pretend IPv6 232*a7148ab3SEnji Cooper # isn't present. 233*a7148ab3SEnji Cooper $have_IPv6 = 0 234*a7148ab3SEnji Cooper if grep { $_ eq 'OPENSSL_USE_IPV6=0' } @{$config{CPPDEFINES}}; 235*a7148ab3SEnji Cooper # Similarly, if a config target has explicitly disabled IPv6, no 236*a7148ab3SEnji Cooper # IPv6 related tests should be performed. 237*a7148ab3SEnji Cooper $have_IPv6 = 0 238*a7148ab3SEnji Cooper if grep { $_ eq 'OPENSSL_USE_IPV6=0' } @{$target{defines}}; 239*a7148ab3SEnji Cooper } 240*a7148ab3SEnji Cooper if ($have_IPv6 < 0) { 241e0c4386eSCy Schubert $have_IPv6 = check_IP("::1"); 242e0c4386eSCy Schubert } 243e0c4386eSCy Schubert return $have_IPv6; 244e0c4386eSCy Schubert} 245e0c4386eSCy Schubert 246e0c4386eSCy Schubert=head1 SEE ALSO 247e0c4386eSCy Schubert 248e0c4386eSCy SchubertL<OpenSSL::Test> 249e0c4386eSCy Schubert 250e0c4386eSCy Schubert=head1 AUTHORS 251e0c4386eSCy Schubert 252e0c4386eSCy SchubertStephen Henson E<lt>steve@openssl.orgE<gt> and 253e0c4386eSCy SchubertRichard Levitte E<lt>levitte@openssl.orgE<gt> 254e0c4386eSCy Schubert 255e0c4386eSCy Schubert=cut 256e0c4386eSCy Schubert 257e0c4386eSCy Schubert1; 258