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