diff --git a/lib/Zonemaster/CLI.pm b/lib/Zonemaster/CLI.pm index 989f008..02d4a34 100644 --- a/lib/Zonemaster/CLI.pm +++ b/lib/Zonemaster/CLI.pm @@ -34,12 +34,12 @@ use Zonemaster::Engine::Normalization qw[normalize_name]; use Zonemaster::Engine::Logger::Entry; use Zonemaster::Engine::Translator; use Zonemaster::Engine::Util qw[parse_hints]; +use Zonemaster::Engine::Validation qw[validate_ipv4 validate_ipv6]; our %numeric = Zonemaster::Engine::Logger::Entry->levels; our $JSON = JSON::XS->new->allow_blessed->convert_blessed->canonical; -Readonly our $IPV4_RE => qr/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/; -Readonly our $IPV6_RE => qr/^[0-9a-f:]*:[0-9a-f:]+(:[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})?$/i; +Readonly our $DS_RE => qr/^(?:[[:digit:]]+,){3}[[:xdigit:]]+$/; STDOUT->autoflush( 1 ); @@ -618,6 +618,14 @@ sub run { ( my $errors, $domain ) = normalize_name( decode( 'utf8', $domain ) ); + if ( $self->ns and @{ $self->ns } > 0 ) { + $self->check_fake_delegation( $domain ); + } + + if ( $self->ds and @{ $self->ds } ) { + $self->check_fake_ds( $domain ); + } + if ( scalar @$errors > 0 ) { my $error_message; foreach my $err ( @$errors ) { @@ -639,14 +647,6 @@ sub run { Zonemaster::Engine::Recursor->add_fake_addresses( '.', $hints_data ); } - if ( $self->ns and @{ $self->ns } > 0 ) { - $self->add_fake_delegation( $domain ); - } - - if ( $self->ds and @{ $self->ds } ) { - $self->add_fake_ds( $domain ); - } - if ( $self->profile or $self->test ) { # Separate initialization from main output in human readable output mode print "\n" if $fh_diag eq *STDOUT; @@ -686,6 +686,14 @@ sub run { print $header; } + if ( $self->ns and @{ $self->ns } > 0 ) { + $self->add_fake_delegation( $domain ); + } + + if ( $self->ds and @{ $self->ds } ) { + $self->add_fake_ds( $domain ); + } + # Actually run tests! eval { if ( $self->test and @{ $self->test } > 0 ) { @@ -814,10 +822,9 @@ sub run { return; } -sub add_fake_delegation { - my ( $self, $domain ) = @_; - my @ns_with_no_ip; - my %data; + +sub check_fake_delegation { + my ( $self ) = @_; foreach my $pair ( @{ $self->ns } ) { my ( $name, $ip ) = split( '/', $pair, 2 ); @@ -839,16 +846,42 @@ sub add_fake_delegation { if ( $ip ) { my $net_ip = Net::IP::XS->new( $ip ); - if ( ( $ip =~ /($IPV4_RE)/ && Net::IP::XS::ip_is_ipv4( $ip ) ) - or - ( $ip =~ /($IPV6_RE)/ && Net::IP::XS::ip_is_ipv6( $ip ) ) - ) { - push @{ $data{ $name } }, $ip; - } - else { + unless( validate_ipv4( $ip ) or validate_ipv6( $ip ) ) + { die Net::IP::XS::Error() ? "Invalid IP address in --ns argument:\n\t". Net::IP::XS::Error() ."\n" : "Invalid IP address in --ns argument.\n"; } } + } + + return; +} + +sub check_fake_ds { + my ( $self ) = @_; + + foreach my $str ( @{ $self->ds } ) { + unless ( $str =~ /$DS_RE/ ) { + say STDERR __( "--ds ds data must be in the form \"keytag,algorithm,type,digest\". E.g. space is not permitted anywhere in the string."); + exit( 1 ); + } + } + + return; +} + +sub add_fake_delegation { + my ( $self, $domain ) = @_; + my @ns_with_no_ip; + my %data; + + foreach my $pair ( @{ $self->ns } ) { + my ( $name, $ip ) = split( '/', $pair, 2 ); + + ( my $errors, $name ) = normalize_name( decode( 'utf8', $name ) ); + + if ( $ip ) { + push @{ $data{ $name } }, $ip; + } else { push @ns_with_no_ip, $name; }