diff --git a/.travis.yml b/.travis.yml index cf8c922e..1875fc7b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,20 +1,20 @@ -dist: bionic +dist: focal env: - TEST_WITH_NETWORK=1 language: perl perl: - - "5.30" - - "5.28" + - "5.32" + - "5.30.2" - "5.26" - - "5.24" - - "5.22" - - "5.16" + - "5.14.4" before_install: - - eval $(curl https://travis-perl.github.io/init) - - sudo apt-get install -y libidn11-dev + # quoting preserves newlines in the script and then avoid error if the + # script contains comments + - eval "$(curl https://travis-perl.github.io/init)" + - sudo apt-get install -y libidn2-dev - cpan-install --deps Devel::CheckLib Module::Install Module::Install::XSUtil install: diff --git a/Changes b/Changes index 9042becb..972d85f3 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,14 @@ Release history for Zonemaster component Zonemaster-LDNS +2.2.2 2022-06-09 + + [Features] + - Gives more freedom when configuring (#134, #129, #96) + - Replaces libidn with libidn2 (#133, #131) + + [Fixes] + - Clarifies README on --ed25519 (#142) + 2.2.1 2021-12-03 [Features] diff --git a/Dockerfile b/Dockerfile index 16d0168f..2d5a9283 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ RUN apk add --no-cache \ # Compile-time dependencies build-base \ ldns-dev \ - libidn-dev \ + libidn2-dev \ make \ openssl-dev \ perl-app-cpanminus \ @@ -32,5 +32,5 @@ COPY --from=build /usr/local/lib/perl5/site_perl/Zonemaster /usr/local/lib/perl5 RUN apk add --no-cache \ # Run-time dependencies ldns \ - libidn \ + libidn2 \ perl diff --git a/Makefile.PL b/Makefile.PL index dbf3e396..cf5c342f 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -14,17 +14,69 @@ all_from 'lib/Zonemaster/LDNS.pm'; repository 'https://github.com/zonemaster/zonemaster-ldns'; bugtracker 'https://github.com/zonemaster/zonemaster-ldns/issues'; +=head1 Optional features + +=over + +=item --[no-]ed25519 + +Enable (or disable) support for Ed25519 in both openssl and ldns. +Enabled by default. + +=item --[no-]idn + +Enable (or disable) support for converting IDN labels in U-label format (with +non-ASCII Unicode characters) to the same IDN labels in A-label format (encoded +in ASCII). +Enabled by default. + +=item --[no-]internal-ldns + +When enabled, an included version of ldns is statically linked into +Zonemaster::LDNS. +When disabled, libldns is dynamically linked just like other dependencies. +Enabled by default. + +=item --[no-]randomize + +Experimental. +Randomizes the capitalization of returned domain names. +Disabled by default. + +=item --prefix-openssl=PATH + +Search for OpenSSL headers and libraries in PATH. +The LDNS script will look for an "include" and a "lib" folder. + +=item --openssl-inc=PATH + +Search for OpenSSL include in PATH. +The PATH is passed to the LDNS compiler via the CFLAGS variable. + +=item --openssl-lib=PATH + +Search for OpenSSL library in PATH. +The PATH is passed to the LDNS compiler via the LDFLAGS variable. + +=back + +=cut + my $opt_ed25519 = 1; my $opt_idn = 1; my $opt_internal_ldns = 1; my $opt_randomize = 0; my $opt_prefix_openssl = ""; +my $opt_openssl_inc = ""; +my $opt_openssl_lib = ""; GetOptions( 'ed25519!' => \$opt_ed25519, 'idn!' => \$opt_idn, 'internal-ldns!' => \$opt_internal_ldns, 'randomize!' => \$opt_randomize, 'prefix-openssl=s' => \$opt_prefix_openssl, + 'openssl-inc=s' => \$opt_openssl_inc, + 'openssl-lib=s' => \$opt_openssl_lib, ); configure_requires 'Devel::CheckLib'; @@ -42,12 +94,31 @@ cc_src_paths 'src'; # OpenSSL my %assert_lib_args_openssl; -if ( $opt_prefix_openssl ) { - print "Custom prefix for OpenSSL: $opt_prefix_openssl\n"; - cc_include_paths "$opt_prefix_openssl/include"; - cc_libs "-L$opt_prefix_openssl/lib", "crypto"; - $assert_lib_args_openssl{incpath} = "$opt_prefix_openssl/include"; - $assert_lib_args_openssl{libpath} = "$opt_prefix_openssl/lib"; +my $custom_openssl = ( $opt_prefix_openssl or $opt_openssl_inc or $opt_openssl_lib ); +if ( $custom_openssl ) { + my $openssl_incpath = ""; + my $openssl_libpath = ""; + + if ( $opt_prefix_openssl ) { + print "Custom prefix for OpenSSL: $opt_prefix_openssl\n"; + $openssl_incpath = "$opt_prefix_openssl/include"; + $openssl_libpath = "$opt_prefix_openssl/lib"; + } + + if ( $opt_openssl_inc ) { + print "Custom include directory for OpenSSL: $opt_openssl_inc\n"; + $openssl_incpath = "$opt_openssl_inc"; + } + + if ( $opt_openssl_lib ) { + print "Custom library directory for OpenSSL: $opt_openssl_lib\n"; + $openssl_libpath = "$opt_openssl_lib"; + } + + cc_include_paths "$openssl_incpath"; + cc_libs "-L$openssl_libpath", "crypto"; + $assert_lib_args_openssl{incpath} = "$openssl_incpath"; + $assert_lib_args_openssl{libpath} = "$openssl_libpath"; } else { cc_libs 'crypto'; @@ -99,12 +170,11 @@ else { if ( $opt_idn ) { print "Feature idn enabled\n"; check_lib_or_exit( - lib => 'idn', - header => 'idna.h', + lib => 'idn2', + header => 'idn2.h', function => - 'if(strcmp(IDNA_ACE_PREFIX,"xn--")==0) return 0; else return 1;' - ); - cc_libs 'idn'; + 'return IDN2_OK;'); + cc_libs 'idn2'; cc_define '-DWE_CAN_HAZ_IDN'; } else { @@ -156,11 +226,18 @@ CONFIGURE_FLAGS += --disable-ldns-config --disable-dane END_CONFIGURE_FLAGS - my $openssl_make = <= 1.1.1 unless [Ed25519] is disabled) - * `libidn` (if [IDN] is enabled) + * `libidn2` (if [IDN] is enabled) * `libldns` (if [Internal ldns] is disabled; libldns >= 1.7.0, or libldns >= 1.7.1 if [Ed25519] is enabled) @@ -127,11 +127,12 @@ commands. Enabled by default. Disabled with `--no-ed25519` -Requires support for Ed25519 in both openssl and ldns. +Requires support for algorithms Ed25519 and Ed448 in both openssl and ldns. > > *Note:* Zonemaster Engine relies on this feature for its analysis when Ed25519 -> (algorithm 15) is being used in DNS records. +> (DNSKEY algorithm 15) or Ed448 (DNSKEY algorithm 16) is being used in DNSSEC +> signatures. > ### IDN @@ -139,7 +140,7 @@ Requires support for Ed25519 in both openssl and ldns. Enabled by default. Disable with `--no-idn`. -If the IDN feature is enabled, the GNU `libidn` library will be used to +If the IDN feature is enabled, the GNU `libidn2` library will be used to add a simple function that converts strings from Perl's internal encoding to IDNA domain name format. In order to convert strings from whatever encoding you have to Perl's @@ -173,7 +174,8 @@ Randomizes the capitalization of returned domain names. ### Custom OpenSSL Disabled by default. -Enabled with `--prefix-openssl=/path/to/openssl`. +Enabled with `--prefix-openssl=/path/to/openssl` or +`--openssl-inc=/path/to/openssl_inc` or `--openssl-lib=/path/to/openssl_lib` Enabling this makes the build tools look for OpenSSL in a non-standard place. @@ -185,6 +187,10 @@ Technically this does two things: > **Note:** The `lib` directory under the given path must be known to the > dynamic linker or feature checks will fail. +If both headers and libraries directories (`include` and `lib`) are not in the +same parent directory, use `--openssl-inc` and `--openssl-lib` options to +specify both paths. + [DNS::LDNS]: http://search.cpan.org/~erikoest/DNS-LDNS/ [Docker Hub]: https://hub.docker.com/u/zonemaster diff --git a/include/LDNS.h b/include/LDNS.h index 53bfb29c..9de985a9 100644 --- a/include/LDNS.h +++ b/include/LDNS.h @@ -13,7 +13,7 @@ #include #ifdef WE_CAN_HAZ_IDN -#include +#include #endif /* ldns 1.6.17 does not have this in its header files, but it is in the published documentation and we need it */ diff --git a/lib/Zonemaster/LDNS.pm b/lib/Zonemaster/LDNS.pm index dc8ca885..1bea10bf 100644 --- a/lib/Zonemaster/LDNS.pm +++ b/lib/Zonemaster/LDNS.pm @@ -2,7 +2,7 @@ package Zonemaster::LDNS; use 5.014; -our $VERSION = '2.2.1'; +our $VERSION = '2.2.2'; use parent 'Exporter'; our @EXPORT_OK = qw[to_idn has_idn ldns_version load_zonefile]; @@ -46,12 +46,12 @@ labels converted to A-labels unless they are already in ASCII. Assumes that the strings have been converted to Perl's internal encoding before it's called. Can be exported, but is not by default. -This function requires that GNU libidn was present when L was +This function requires that GNU libidn2 was present when L was compiled. If not, calling C will result in an exception getting thrown. =item has_idn() -Takes no arguments. Returns true if libidn was present at compilation, false if not. +Takes no arguments. Returns true if libidn2 was present at compilation, false if not. =item has_gost() diff --git a/src/LDNS.xs b/src/LDNS.xs index f2e8c980..becb9075 100644 --- a/src/LDNS.xs +++ b/src/LDNS.xs @@ -18,8 +18,8 @@ to_idn(...) if (SvPOK(ST(i))) { - status = idna_to_ascii_8z(SvPVutf8_nolen(obj), &out, IDNA_ALLOW_UNASSIGNED); - if (status == IDNA_SUCCESS) + status = idn2_to_ascii_8z(SvPVutf8_nolen(obj), &out, IDN2_ALLOW_UNASSIGNED); + if (status == IDN2_OK) { SV *new = newSVpv(out,0); SvUTF8_on(new); /* We know the string is plain ASCII, so let Perl know too */ @@ -28,12 +28,12 @@ to_idn(...) } else { - croak("Error: %s\n", idna_strerror(status)); + croak("Error: %s\n", idn2_strerror(status)); } } } #else - croak("libidn not installed"); + croak("libidn2 not installed"); #endif } diff --git a/t/idn.t b/t/idn.t index 86c16c7b..a00dd103 100644 --- a/t/idn.t +++ b/t/idn.t @@ -7,7 +7,7 @@ use utf8; BEGIN { use_ok( "Zonemaster::LDNS" => qw[:all] ) } no warnings 'uninitialized'; -if (exception {to_idn("whatever")} =~ /libidn not installed/) { +if (exception {to_idn("whatever")} =~ /libidn2 not installed/) { ok(!has_idn(), 'No IDN'); done_testing; exit; diff --git a/t/rr.t b/t/rr.t index b13e9353..9b7aa66b 100644 --- a/t/rr.t +++ b/t/rr.t @@ -103,8 +103,8 @@ subtest 'DNSKEY' => sub { isa_ok( $rr, 'Zonemaster::LDNS::RR::DNSKEY' ); ok( $rr->flags == 256 or $rr->flags == 257 ); is( $rr->protocol, 3 ); - # Alg 8 will replace 5. Now (December 2017) both are used. - ok( $rr->algorithm == 5 or $rr->algorithm == 8 ); + # Alg 8 has replaced 5. Now (February 2022) only alg 8 is used. + ok( $rr->algorithm == 8 ); } } }; @@ -122,9 +122,9 @@ subtest 'RRSIG' => sub { is( $rr->signer, 'se.' ); is( $rr->labels, 1 ); if ( $rr->typecovered eq 'DNSKEY' ) { - # .SE KSK should not change very often. 59407 will replace 59747. - # Now (December 2017) both are used. - ok( $rr->keytag == 59747 or $rr->keytag == 59407 ); + # .SE KSK should not change very often. 59407 has replaced 59747. + # Now (February 2022) only 59407 is used. + ok( $rr->keytag == 59407 ); } } } @@ -172,19 +172,17 @@ subtest 'DS' => sub { my $pd = $se->query( 'nic.se', 'DS' ); plan skip_all => 'No response, cannot test' if not $pd; + # As of February 2022, new KSK with keytag 22643 and algo 13 is used my $nic_key = Zonemaster::LDNS::RR->new( - 'nic.se IN DNSKEY 257 3 5 AwEAAdhJAx197qFpGGXuQn8XH0tQpQSfjvLKMcreRvJyO+f3F3weIHR3 6E8DObolHFp+m1YkxsgnHYjUFN4E9sKa38ZXU0oHTSsB3adExJkINA/t INDlKrzUDn4cIbyUCqHNGe0et+lHmjmfZdj62GJlHgVmxizYkoBd7Rg0 wxzEOo7CA3ZadaHuqmVJ2HvqRCoe+5NDsYpnDia7WggvLTe0vorV6kDc u6d5N9AUPwBsR7YUkbetfXMtUebux71kHCGUJdmzp84MeDi9wXYIssjR oTC5wUF2H3I2Mnj5GqdyBwQCdj5otFbRAx3jiMD+ROxXJxOFdFq7fWi1 yPqUf1jpJ+8=' + 'nic.se IN DNSKEY 257 3 13 lkpZSlU70pd1LHrXqZttOAYKmX046YqYQg1aQJsv1y0xKr+qJS+3Ue1tM5VCYPU3lKuzq93nz0Lm/AV9jeoumQ==' ); my $made = Zonemaster::LDNS::RR->new_from_string( 'nic.se IN NS a.ns.se' ); foreach my $rr ( $pd->answer ) { isa_ok( $rr, 'Zonemaster::LDNS::RR::DS' ); - is( $rr->keytag, 16696 ); - is( $rr->algorithm, 5 ); + is( $rr->keytag, 22643 ); + is( $rr->algorithm, 13 ); ok( $rr->digtype == 1 or $rr->digtype == 2 ); - ok( - $rr->hexdigest eq '40079ddf8d09e7f10bb248a69b6630478a28ef969dde399f95bc3b39f8cbacd7' - or $rr->hexdigest eq 'ef5d421412a5eaf1230071affd4f585e3b2b1a60' - ); + ok( $rr->hexdigest eq 'aa0b38f6755c2777992a74935d50a2a3480effef1a60bf8643d12c307465c9da' ); ok( $rr->verify( $nic_key ), 'derived from expected DNSKEY' ); ok( !$rr->verify( $made ), 'does not match a non-DS non-DNSKEY record' ); }