From 323208e9cc7657de36914670db41e52078562b64 Mon Sep 17 00:00:00 2001 From: Richard Hansen Date: Sun, 21 Jun 2020 23:18:53 -0400 Subject: [PATCH] Add `geturl` connectivity unit tests Addresses #232 --- .github/workflows/ci.yml | 7 + Makefile.am | 9 +- configure.ac | 10 + ddclient.in | 3 +- t/geturl_connectivity.pl | 89 ++++ t/lib/ddclient/Test/Fake/HTTPD.pm | 381 ++++++++++++++++++ .../Test/Fake/HTTPD/dummy-ca-cert.pem | 80 ++++ .../Test/Fake/HTTPD/dummy-server-cert.pem | 165 ++++++++ .../Test/Fake/HTTPD/dummy-server-key.pem | 28 ++ 9 files changed, 770 insertions(+), 2 deletions(-) create mode 100644 t/geturl_connectivity.pl create mode 100644 t/lib/ddclient/Test/Fake/HTTPD.pm create mode 100644 t/lib/ddclient/Test/Fake/HTTPD/dummy-ca-cert.pem create mode 100644 t/lib/ddclient/Test/Fake/HTTPD/dummy-server-cert.pem create mode 100644 t/lib/ddclient/Test/Fake/HTTPD/dummy-server-key.pem diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 84f0b5f..a110f52 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,14 @@ jobs: automake \ ca-certificates \ git \ + libhttp-daemon-perl \ + libhttp-daemon-ssl-perl \ + libio-socket-inet6-perl \ + libio-socket-ip-perl \ + libplack-perl \ + libtest-tcp-perl \ libtest-warnings-perl \ + liburi-perl \ make \ ; - uses: actions/checkout@v2 diff --git a/Makefile.am b/Makefile.am index 0fc3bf0..e05d368 100644 --- a/Makefile.am +++ b/Makefile.am @@ -58,6 +58,8 @@ sysconf_DATA = ddclient.conf install-data-local: $(MKDIR_P) '$(DESTDIR)$(localstatedir)'/cache/ddclient +AM_TESTS_ENVIRONMENT = \ + abs_top_srcdir='$(abs_top_srcdir)'; export abs_top_srcdir; LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ $(top_srcdir)/build-aux/tap-driver.sh TEST_EXTENSIONS = .pl @@ -67,8 +69,13 @@ AM_PL_LOG_FLAGS = -Mstrict -w \ -I'$(abs_top_builddir)' \ -I'$(abs_top_srcdir)'/t/lib handwritten_tests = \ + t/geturl_connectivity.pl \ t/parse_assignments.pl generated_tests = \ t/version.pl TESTS = $(handwritten_tests) $(generated_tests) -EXTRA_DIST += $(handwritten_tests) +EXTRA_DIST += $(handwritten_tests) \ + t/lib/ddclient/Test/Fake/HTTPD.pm \ + t/lib/ddclient/Test/Fake/HTTPD/dummy-ca-cert.pem \ + t/lib/ddclient/Test/Fake/HTTPD/dummy-server-cert.pem \ + t/lib/ddclient/Test/Fake/HTTPD/dummy-server-key.pem diff --git a/configure.ac b/configure.ac index b9677a8..fbf9461 100644 --- a/configure.ac +++ b/configure.ac @@ -53,7 +53,17 @@ m4_foreach_w([_m], [ # then some tests will be skipped, but no tests should fail. Only # prints a warning if not installed. m4_foreach_w([_m], [ + Carp + Exporter + HTTP::Daemon=6.12 + HTTP::Daemon::SSL + HTTP::Message::PSGI + IO::Socket::IP + Scalar::Util + Test::TCP Test::Warnings + Time::HiRes + URI ], [AX_PROG_PERL_MODULES([_m], [], [AC_MSG_WARN([some tests may be skipped due to missing module _m])])]) diff --git a/ddclient.in b/ddclient.in index 1508d8a..61a8c44 100755 --- a/ddclient.in +++ b/ddclient.in @@ -66,7 +66,8 @@ local $lineno = ''; $ENV{'PATH'} = (exists($ENV{PATH}) ? "$ENV{PATH}:" : "") . "/sbin:/usr/sbin:/bin:/usr/bin:/etc:/usr/lib:"; -my ($result, %config, %globals, %cache); +our %globals; +my ($result, %config, %cache); my $saved_cache; my %saved_opt; my $daemon; diff --git a/t/geturl_connectivity.pl b/t/geturl_connectivity.pl new file mode 100644 index 0000000..1a35d76 --- /dev/null +++ b/t/geturl_connectivity.pl @@ -0,0 +1,89 @@ +use Test::More; +eval { require ddclient::Test::Fake::HTTPD; } or plan(skip_all => $@); +SKIP: { eval { require Test::Warnings; } or skip($@, 1); } +eval { require 'ddclient'; } or BAIL_OUT($@); +my $has_http_daemon_ssl = eval { require HTTP::Daemon::SSL; }; +my $ipv6_supported = eval { + require IO::Socket::IP; + my $ipv6_socket = IO::Socket::IP->new( + Domain => 'PF_INET6', + LocalHost => '::1', + Listen => 1, + ); + defined($ipv6_socket); +}; +my $http_daemon_supports_ipv6 = eval { + require HTTP::Daemon; + HTTP::Daemon->VERSION(6.12); +}; + +# To aid in debugging, uncomment the following lines. (They are normally left commented to avoid +# accidentally interfering with the Test Anything Protocol messages written by Test::More.) +#STDOUT->autoflush(1); +#$ddclient::globals{'verbose'} = 1; + +my $certdir = "$ENV{abs_top_srcdir}/t/lib/ddclient/Test/Fake/HTTPD"; +$ddclient::globals{'ssl_ca_file'} = "$certdir/dummy-ca-cert.pem"; + +sub run_httpd { + my ($ipv6, $ssl) = @_; + return undef if $ssl && !$has_http_daemon_ssl; + return undef if $ipv6 && (!$ipv6_supported || !$http_daemon_supports_ipv6); + my $httpd = ddclient::Test::Fake::HTTPD->new( + host => $ipv6 ? '::1' : '127.0.0.1', + scheme => $ssl ? 'https' : 'http', + daemon_args => { + SSL_cert_file => "$certdir/dummy-server-cert.pem", + SSL_key_file => "$certdir/dummy-server-key.pem", + V6Only => 1, + }, + ); + $httpd->run(sub { + # Echo back the full request. + return [ 200, [ 'Content-Type' => 'application/octet-stream' ], [ $_[0]->as_string() ] ]; + }); + diag(sprintf("started IPv%s%s server running at %s", + $ipv6 ? '6' : '4', $ssl ? ' SSL' : '', $httpd->endpoint())); + return $httpd; +} + +my %httpd = ( + '4' => { 'http' => run_httpd(0, 0), 'https' => run_httpd(0, 1) }, + '6' => { 'http' => run_httpd(1, 0), 'https' => run_httpd(1, 1) }, +); + +# Note: IPv* client to IPv6 server is not expected to work unless $globals{'ipv6'} is true. +my @test_cases = ( + { ipv6_opt => 0, client_ipv => '', server_ipv => '4', ssl => 0 }, + { ipv6_opt => 0, client_ipv => '', server_ipv => '4', ssl => 1 }, + { ipv6_opt => 0, client_ipv => '4', server_ipv => '4', ssl => 0 }, + { ipv6_opt => 0, client_ipv => '4', server_ipv => '4', ssl => 1 }, + { ipv6_opt => 0, client_ipv => '6', server_ipv => '6', ssl => 0 }, + { ipv6_opt => 0, client_ipv => '6', server_ipv => '6', ssl => 1 }, + { ipv6_opt => 1, client_ipv => '', server_ipv => '4', ssl => 0 }, + { ipv6_opt => 1, client_ipv => '', server_ipv => '4', ssl => 1 }, + { ipv6_opt => 1, client_ipv => '', server_ipv => '6', ssl => 0 }, + { ipv6_opt => 1, client_ipv => '', server_ipv => '6', ssl => 1 }, + { ipv6_opt => 1, client_ipv => '4', server_ipv => '4', ssl => 0 }, + { ipv6_opt => 1, client_ipv => '4', server_ipv => '4', ssl => 1 }, + { ipv6_opt => 1, client_ipv => '6', server_ipv => '6', ssl => 0 }, + { ipv6_opt => 1, client_ipv => '6', server_ipv => '6', ssl => 1 }, +); + +for my $tc (@test_cases) { + SKIP: { + skip("IPv6 not supported on this system", 1) + if $tc->{server_ipv} eq '6' && !$ipv6_supported; + skip("HTTP::Daemon too old for IPv6 support", 1) + if $tc->{server_ipv} eq '6' && !$http_daemon_supports_ipv6; + skip("HTTP::Daemon::SSL not available", 1) if $tc->{ssl} && !$has_http_daemon_ssl; + my $uri = $httpd{$tc->{server_ipv}}{$tc->{ssl} ? 'https' : 'http'}->endpoint(); + my $name = sprintf("IPv%s client to %s (-%sipv6)", + $tc->{client_ipv} || '*', $uri, $tc->{ipv6_opt} ? '' : 'no'); + $ddclient::globals{'ipv6'} = $tc->{ipv6_opt}; + my $got = ddclient::geturl({ url => $uri, ipversion => $tc->{client_ipv} }); + isnt($got // '', '', $name); + } +} + +done_testing(); diff --git a/t/lib/ddclient/Test/Fake/HTTPD.pm b/t/lib/ddclient/Test/Fake/HTTPD.pm new file mode 100644 index 0000000..0a7ba85 --- /dev/null +++ b/t/lib/ddclient/Test/Fake/HTTPD.pm @@ -0,0 +1,381 @@ +# Copied from https://metacpan.org/pod/release/MASAKI/Test-Fake-HTTPD-0.08/lib/Test/Fake/HTTPD.pm +# and modified as follows: +# * Patched with https://github.com/masaki/Test-Fake-HTTPD/pull/4 to add IPv6 support. +# * Changed package name to ddclient::Test::Fake::HTTPD. +# +# License: This library is free software; you can redistribute it and/or modify it under the same +# terms as Perl itself. + +package ddclient::Test::Fake::HTTPD; + +use 5.008_001; +use strict; +use warnings; +use HTTP::Daemon; +use HTTP::Message::PSGI qw(res_from_psgi); +use Test::TCP qw(wait_port); +use URI; +use Time::HiRes (); +use Scalar::Util qw(blessed weaken); +use Carp qw(croak); +use Exporter qw(import); + +our $VERSION = '0.08'; +$VERSION = eval $VERSION; + +our @EXPORT = qw( + run_http_server run_https_server + extra_daemon_args +); + +our $ENABLE_SSL = eval { require HTTP::Daemon::SSL; 1 }; +sub enable_ssl { $ENABLE_SSL } + +our %EXTRA_DAEMON_ARGS = (); +sub extra_daemon_args (%) { %EXTRA_DAEMON_ARGS = @_ } + +sub run_http_server (&) { + my $app = shift; + __PACKAGE__->new->run($app); +} + +sub run_https_server (&) {} # noop +if ($ENABLE_SSL) { + no warnings 'redefine'; + *run_https_server = sub (&) { + my $app = shift; + __PACKAGE__->new(scheme => 'https')->run($app); + }; +} + +sub new { + my ($class, %args) = @_; + bless { + host => '127.0.0.1', + timeout => 5, + listen => 5, + scheme => 'http', + %args + }, $class; +} + +our $DAEMON_MAP = { + http => 'HTTP::Daemon', + https => 'HTTP::Daemon::SSL', +}; + +sub _daemon_class { + my $self = shift; + return $DAEMON_MAP->{$self->{scheme}}; +} + +sub run { + my ($self, $app) = @_; + + my %extra_daemon_args = $self->{daemon_args} && ref $self->{daemon_args} eq 'HASH' + ? %{ $self->{daemon_args} } + : %EXTRA_DAEMON_ARGS; + + $self->{server} = Test::TCP->new( + ($self->host ? (host => $self->host) : ()), + code => sub { + my $port = shift; + + my $d; + for (1..10) { + $d = $self->_daemon_class->new( + # Note: IO::Socket::IP ignores LocalAddr if LocalHost is set. + ($self->host ? (LocalAddr => $self->host) : ()), + LocalPort => $port, + Timeout => $self->{timeout}, + Proto => 'tcp', + Listen => $self->{listen}, + ($self->_is_win32 ? () : (ReuseAddr => 1)), + %extra_daemon_args, + ) and last; + Time::HiRes::sleep(0.1); + } + + croak(sprintf("failed to listen on address %s port %s%s", + $self->host || '', + $self->port || '', + $@ eq '' ? '' : ": $@")) unless $d; + + $d->accept; # wait for port check from parent process + + while (my $c = $d->accept) { + while (my $req = $c->get_request) { + my $res = $self->_to_http_res($app->($req)); + $c->send_response($res); + } + $c->close; + undef $c; + } + }, + ($self->{port} ? (port => $self->{port}) : ()), + ); + + weaken($self); + $self; +} + +sub scheme { + my $self = shift; + return $self->{scheme}; +} + +sub host { + my $self = shift; + return $self->{host}; +} + +sub port { + my $self = shift; + return $self->{server} ? $self->{server}->port : 0; +} + +sub host_port { + my $self = shift; + return $self->endpoint->host_port; +} + +sub endpoint { + my $self = shift; + my $uri = URI->new($self->scheme . ':'); + my $host = $self->host; + $host = 'localhost' if !defined($host) || $host eq '0.0.0.0' || $host eq '::'; + $uri->host($host); + $uri->port($self->port); + return $uri; +} + +sub _is_win32 { $^O eq 'MSWin32' } + +sub _is_psgi_res { + my ($self, $res) = @_; + return unless ref $res eq 'ARRAY'; + return unless @$res == 3; + return unless $res->[0] && $res->[0] =~ /^\d{3}$/; + return unless ref $res->[1] eq 'ARRAY' || ref $res->[1] eq 'HASH'; + return 1; +} + +sub _to_http_res { + my ($self, $res) = @_; + + my $http_res; + if (blessed($res) and $res->isa('HTTP::Response')) { + $http_res = $res; + } + elsif (blessed($res) and $res->isa('Plack::Response')) { + $http_res = res_from_psgi($res->finalize); + } + elsif ($self->_is_psgi_res($res)) { + $http_res = res_from_psgi($res); + } + + croak(sprintf '%s: response must be HTTP::Response or Plack::Response or PSGI', __PACKAGE__) + unless $http_res; + + return $http_res; +} + +1; + +=head1 NAME + +Test::Fake::HTTPD - a fake HTTP server + +=head1 SYNOPSIS + +DSL-style + + use Test::Fake::HTTPD; + + my $httpd = run_http_server { + my $req = shift; + # ... + + # 1. HTTP::Response ok + return $http_response; + # 2. Plack::Response ok + return $plack_response; + # 3. PSGI response ok + return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello World' ] ]; + }; + + printf "Listening on address:port %s\n", $httpd->host_port; + # or + printf "Listening on address %s port %s\n", $httpd->host, $httpd->port; + + # access to fake HTTP server + use LWP::UserAgent; + my $res = LWP::UserAgent->new->get($httpd->endpoint); # "http://127.0.0.1:{port}" + + # Stop http server automatically at destruction time. + +OO-style + + use Test::Fake::HTTPD; + + my $httpd = Test::Fake::HTTPD->new( + timeout => 5, + daemon_args => { ... }, # HTTP::Daemon args + ); + + $httpd->run(sub { + my $req = shift; + # ... + [ 200, [ 'Content-Type', 'text/plain' ], [ 'Hello World' ] ]; + }); + + # Stop http server automatically at destruction time. + +=head1 DESCRIPTION + +Test::Fake::HTTPD is a fake HTTP server module for testing. + +=head1 FUNCTIONS + +=over 4 + +=item * C + +Starts HTTP server and returns the guard instance. + + my $httpd = run_http_server { + my $req = shift; + # ... + return $http_or_plack_or_psgi_res; + }; + + # can use $httpd guard object, same as OO-style + LWP::UserAgent->new->get($httpd->endpoint); + +=item * C + +Starts B server and returns the guard instance. + +If you use this method, you MUST install L. + + extra_daemon_args + SSL_key_file => "certs/server-key.pem", + SSL_cert_file => "certs/server-cert.pem"; + + my $httpd = run_https_server { + my $req = shift; + # ... + return $http_or_plack_or_psgi_res; + }; + + # can use $httpd guard object, same as OO-style + my $ua = LWP::UserAgent->new( + ssl_opts => { + SSL_verify_mode => 0, + verify_hostname => 0, + }, + ); + $ua->get($httpd->endpoint); + +=back + +=head1 METHODS + +=over 4 + +=item * C + +Returns a new instance. + + my $httpd = Test::Fake::HTTPD->new(%args); + +C<%args> are: + +=over 8 + +=item * C + +timeout value (default: 5) + +=item * C + +queue size for listen (default: 5) + +=item * C + +local address to listen on (default: 127.0.0.1) + +=item * C + +TCP port to listen on (default: auto detection) + +=back + + my $httpd = Test::Fake::HTTPD->new( + timeout => 10, + listen => 10, + port => 3333, + ); + +=item * C + +Starts this HTTP server. + + $httpd->run(sub { ... }); + +=item * C + +Returns a scheme of running, "http" or "https". + + my $scheme = $httpd->scheme; + +=item * C + +Returns the address the server is listening on. + +=item * C + +Returns the TCP port the server is listening on. + + my $port = $httpd->port; + +=item * C + +Returns the host:port from C (e.g., "127.0.0.1:1234", "[::1]:1234"). + + my $host_port = $httpd->host_port; + +=item * C + +Returns a URI object to the running server (e.g., "http://127.0.0.1:1234", +"https://[::1]:1234"). If C returns C, C<''>, C<'0.0.0.0'>, +or C<'::'>, the host portion of the URI is set to C. + + use LWP::UserAgent; + + my $res = LWP::UserAgent->new->get($httpd->endpoint); + + my $url = $httpd->endpoint; + $url->path('/foo/bar'); + my $res = LWP::UserAgent->new->get($url); + +=back + +=head1 AUTHOR + +NAKAGAWA Masaki Emasaki@cpan.orgE + +=head1 THANKS TO + +xaicron + +=head1 LICENSE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=head1 SEE ALSO + +L, L, L, L + +=cut diff --git a/t/lib/ddclient/Test/Fake/HTTPD/dummy-ca-cert.pem b/t/lib/ddclient/Test/Fake/HTTPD/dummy-ca-cert.pem new file mode 100644 index 0000000..e42921e --- /dev/null +++ b/t/lib/ddclient/Test/Fake/HTTPD/dummy-ca-cert.pem @@ -0,0 +1,80 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 11:82:5d:80:30:4c:a9:6d:ed:68:88:10:c8:90:4d:08:50:3c:4c:b0 + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root Certification Authority + Validity + Not Before: Jul 3 19:47:44 2020 GMT + Not After : Jul 4 19:47:44 2120 GMT + Subject: CN=Root Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:c5:f2:d9:a9:48:a2:06:dc:89:7d:e8:ab:2e:1f: + 70:ea:da:82:46:45:4e:42:38:6e:8d:a6:3e:28:84: + f1:25:c0:ea:25:af:61:ca:87:38:a5:7b:3f:d0:3a: + 57:82:c7:eb:f1:b5:b4:70:0e:71:69:22:5f:ae:49: + d3:51:df:19:97:bf:00:c3:de:99:3a:4d:f3:6d:4a: + bf:73:7e:b1:aa:72:40:b1:0d:fc:d4:af:11:f5:a9: + 7e:c3:36:7a:ac:25:86:a4:3e:7a:fe:3f:0f:22:f7: + d6:87:15:ba:33:c1:36:c3:79:4d:79:b3:ca:a5:2d: + 15:9a:63:ad:38:32:99:74:76:d7:72:7e:2f:69:ff: + 7b:b0:f6:79:ad:da:2d:9f:51:4e:d9:70:15:9c:83: + e9:10:8c:ec:7f:39:27:5d:b9:6e:86:c9:93:54:6b: + aa:82:12:82:b0:32:36:c5:94:6c:48:bb:3f:c6:af: + ef:1c:e1:0c:18:e6:0c:4c:bf:58:67:5b:1a:cd:15: + 62:37:40:40:5f:1d:76:e2:24:01:28:65:cc:ed:3f: + e1:f1:08:79:94:12:13:4c:4c:e2:a4:53:b8:fe:78: + 7f:07:00:cd:c1:3a:7b:0e:f4:35:ce:83:c7:f3:ce: + 71:9d:1f:7b:88:66:bc:b6:39:5e:26:28:e5:ef:5a: + 0d:05 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 21:E8:DE:B6:D8:64:01:72:02:C5:1C:CA:16:0C:D9:05:1A:14:A1:0C + X509v3 Authority Key Identifier: + keyid:21:E8:DE:B6:D8:64:01:72:02:C5:1C:CA:16:0C:D9:05:1A:14:A1:0C + + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 9d:4c:17:84:f3:83:90:97:a7:df:e5:af:53:ac:d7:75:94:c4: + a0:29:fa:d7:8f:a6:f8:fa:4b:d6:5e:d2:6e:8d:6d:46:89:1f: + 7b:30:2c:2d:d3:3b:b6:64:1d:ec:ad:60:c1:96:4b:9a:bc:f9: + d0:5d:af:a1:73:f7:03:99:8a:e2:59:47:48:1c:8f:7a:99:97: + 20:78:e2:16:16:e4:c3:c9:82:4e:25:58:23:75:c9:9c:71:67: + 8e:c4:79:e1:b9:ac:d9:c2:51:41:3d:a6:bf:07:0b:4b:14:8c: + ca:42:0f:c3:b7:71:c0:fb:3e:5e:de:2b:e5:7f:92:52:50:12: + 4f:63:a5:fa:3b:63:59:fa:37:3f:42:f4:ec:13:a0:c7:5d:0c: + 9c:cd:6b:32:96:e7:44:da:5f:8c:cf:c7:51:eb:81:3b:cc:e8: + 39:41:0c:a1:bb:8f:3a:f8:b1:ee:2b:97:f4:13:c9:a8:9c:1c: + 2f:2f:51:57:e4:0c:4e:2b:29:7f:5e:12:72:63:8c:bb:40:2c: + 97:14:bf:1e:7a:66:bc:64:af:78:80:64:19:37:ca:7a:f3:de: + 15:e6:23:1d:d0:90:7d:e6:5f:21:88:23:c5:23:ca:f2:29:00: + 1d:9a:7a:58:37:6d:a9:9e:ab:24:b1:c6:c5:3b:46:11:a7:53: + 80:ef:aa:9c +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgIUEYJdgDBMqW3taIgQyJBNCFA8TLAwDQYJKoZIhvcNAQEL +BQAwJzElMCMGA1UEAwwcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAgFw0y +MDA3MDMxOTQ3NDRaGA8yMTIwMDcwNDE5NDc0NFowJzElMCMGA1UEAwwcUm9vdCBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAMXy2alIogbciX3oqy4fcOragkZFTkI4bo2mPiiE8SXA6iWvYcqHOKV7 +P9A6V4LH6/G1tHAOcWkiX65J01HfGZe/AMPemTpN821Kv3N+sapyQLEN/NSvEfWp +fsM2eqwlhqQ+ev4/DyL31ocVujPBNsN5TXmzyqUtFZpjrTgymXR213J+L2n/e7D2 +ea3aLZ9RTtlwFZyD6RCM7H85J125bobJk1RrqoISgrAyNsWUbEi7P8av7xzhDBjm +DEy/WGdbGs0VYjdAQF8dduIkAShlzO0/4fEIeZQSE0xM4qRTuP54fwcAzcE6ew70 +Nc6Dx/POcZ0fe4hmvLY5XiYo5e9aDQUCAwEAAaNjMGEwHQYDVR0OBBYEFCHo3rbY +ZAFyAsUcyhYM2QUaFKEMMB8GA1UdIwQYMBaAFCHo3rbYZAFyAsUcyhYM2QUaFKEM +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUA +A4IBAQCdTBeE84OQl6ff5a9TrNd1lMSgKfrXj6b4+kvWXtJujW1GiR97MCwt0zu2 +ZB3srWDBlkuavPnQXa+hc/cDmYriWUdIHI96mZcgeOIWFuTDyYJOJVgjdcmccWeO +xHnhuazZwlFBPaa/BwtLFIzKQg/Dt3HA+z5e3ivlf5JSUBJPY6X6O2NZ+jc/QvTs +E6DHXQyczWsyludE2l+Mz8dR64E7zOg5QQyhu486+LHuK5f0E8monBwvL1FX5AxO +Kyl/XhJyY4y7QCyXFL8eema8ZK94gGQZN8p6894V5iMd0JB95l8hiCPFI8ryKQAd +mnpYN22pnqskscbFO0YRp1OA76qc +-----END CERTIFICATE----- diff --git a/t/lib/ddclient/Test/Fake/HTTPD/dummy-server-cert.pem b/t/lib/ddclient/Test/Fake/HTTPD/dummy-server-cert.pem new file mode 100644 index 0000000..c198ebe --- /dev/null +++ b/t/lib/ddclient/Test/Fake/HTTPD/dummy-server-cert.pem @@ -0,0 +1,165 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 11:82:5d:80:30:4c:a9:6d:ed:68:88:10:c8:90:4d:08:50:3c:4c:b1 + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root Certification Authority + Validity + Not Before: Jul 3 19:47:44 2020 GMT + Not After : Jul 4 19:47:44 2120 GMT + Subject: CN=localhost + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:e7:3f:9a:d6:f8:4d:c3:89:69:1f:ab:95:00:b4: + 20:eb:36:72:e1:47:ba:0c:d8:20:76:9f:78:ec:f2: + d4:1c:2d:47:6c:79:a7:af:ce:e8:f6:91:c1:e8:f2: + 77:41:3b:37:70:36:13:f2:5b:30:45:eb:74:d0:f4: + 37:6e:20:d5:5a:aa:de:fc:df:72:b2:07:bb:da:1c: + 66:b7:72:20:cf:34:5f:55:f0:23:36:c3:9f:01:54: + 45:70:65:e5:2a:b3:03:b1:9e:73:dc:a2:32:cb:02: + e0:60:89:a5:f4:9a:87:e2:8a:bc:4d:80:1b:93:c2: + 61:d5:10:eb:ed:6c:fc:a0:b3:a5:22:3c:03:02:72: + e1:71:08:86:42:03:3a:0d:7b:6e:1c:f3:bb:3d:ad: + a8:e4:c2:3f:7c:0a:eb:bd:c1:89:1d:f1:bc:ed:43: + 7e:47:94:e0:f3:17:6d:13:96:be:af:74:e5:20:25: + 71:95:c5:7f:26:d2:28:a4:ee:bd:12:fe:04:e8:8b: + 46:da:7f:e1:fc:54:c0:dc:52:be:55:e2:49:25:ca: + 21:09:cf:e2:ed:e9:70:26:24:62:2e:89:6e:22:2d: + 8c:20:3d:83:f7:d1:b5:e1:74:1c:5d:b9:cb:b6:d5: + 60:93:06:96:1c:cc:b4:0a:4e:00:6a:04:d6:ba:2f: + ea:c7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 72:14:A2:93:7E:96:27:D7:E9:F0:89:D7:53:52:11:11:D9:B5:5B:8B + X509v3 Authority Key Identifier: + keyid:21:E8:DE:B6:D8:64:01:72:02:C5:1C:CA:16:0C:D9:05:1A:14:A1:0C + + X509v3 Subject Alternative Name: + DNS:localhost, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1 + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication + Signature Algorithm: sha256WithRSAEncryption + 29:03:4e:91:19:6b:48:b4:09:89:fb:33:47:bf:43:97:57:f1: + 23:0a:e7:89:22:df:7b:05:97:cf:2c:3f:2f:26:2f:db:81:2e: + 88:40:97:ce:58:a5:c3:d0:78:08:2a:89:d7:a6:fd:87:9a:22: + 2b:82:e8:5e:f9:96:56:8b:09:7c:84:35:08:20:c5:1e:ba:fb: + 7f:aa:92:5d:2c:1e:6e:35:51:6d:8b:f4:de:ba:01:43:a0:7f: + e0:03:f8:94:5f:8a:c5:a9:4b:64:dd:64:ae:8e:79:d3:48:11: + 77:c4:78:a9:14:dc:08:29:76:bd:ea:9d:88:09:b4:95:9c:29: + 41:96:77:21:ce:a7:cb:ba:5b:05:38:bc:5b:06:63:24:f4:41: + 25:b3:4d:45:86:95:f1:8a:41:b4:4d:8a:20:70:b9:99:88:a6: + 96:93:b3:81:6d:80:06:49:29:47:fd:30:83:3f:e5:ef:52:97: + d2:92:fb:43:ba:fd:fe:15:bf:a3:84:55:e5:c9:db:3e:5f:00: + 14:28:3f:86:8e:72:65:cb:2c:e5:8e:75:39:14:e7:e5:82:92: + 6e:fb:3d:ab:40:1c:c9:f8:6c:bc:a4:b1:68:b5:8f:58:82:78: + a1:94:8e:c9:b7:fb:bb:bd:aa:cd:f5:0c:d9:00:70:fb:4f:ca: + 3d:d1:e7:6b +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIUEYJdgDBMqW3taIgQyJBNCFA8TLEwDQYJKoZIhvcNAQEL +BQAwJzElMCMGA1UEAwwcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAgFw0y +MDA3MDMxOTQ3NDRaGA8yMTIwMDcwNDE5NDc0NFowFDESMBAGA1UEAwwJbG9jYWxo +b3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5z+a1vhNw4lpH6uV +ALQg6zZy4Ue6DNggdp947PLUHC1HbHmnr87o9pHB6PJ3QTs3cDYT8lswRet00PQ3 +biDVWqre/N9ysge72hxmt3IgzzRfVfAjNsOfAVRFcGXlKrMDsZ5z3KIyywLgYIml +9JqH4oq8TYAbk8Jh1RDr7Wz8oLOlIjwDAnLhcQiGQgM6DXtuHPO7Pa2o5MI/fArr +vcGJHfG87UN+R5Tg8xdtE5a+r3TlICVxlcV/JtIopO69Ev4E6ItG2n/h/FTA3FK+ +VeJJJcohCc/i7elwJiRiLoluIi2MID2D99G14XQcXbnLttVgkwaWHMy0Ck4AagTW +ui/qxwIDAQABo4GhMIGeMB0GA1UdDgQWBBRyFKKTfpYn1+nwiddTUhER2bVbizAf +BgNVHSMEGDAWgBQh6N622GQBcgLFHMoWDNkFGhShDDAsBgNVHREEJTAjgglsb2Nh +bGhvc3SHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwCQYDVR0TBAIwADAOBgNVHQ8B +Af8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEB +ACkDTpEZa0i0CYn7M0e/Q5dX8SMK54ki33sFl88sPy8mL9uBLohAl85YpcPQeAgq +idem/YeaIiuC6F75llaLCXyENQggxR66+3+qkl0sHm41UW2L9N66AUOgf+AD+JRf +isWpS2TdZK6OedNIEXfEeKkU3Agpdr3qnYgJtJWcKUGWdyHOp8u6WwU4vFsGYyT0 +QSWzTUWGlfGKQbRNiiBwuZmIppaTs4FtgAZJKUf9MIM/5e9Sl9KS+0O6/f4Vv6OE +VeXJ2z5fABQoP4aOcmXLLOWOdTkU5+WCkm77PatAHMn4bLyksWi1j1iCeKGUjsm3 ++7u9qs31DNkAcPtPyj3R52s= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 11:82:5d:80:30:4c:a9:6d:ed:68:88:10:c8:90:4d:08:50:3c:4c:b0 + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Root Certification Authority + Validity + Not Before: Jul 3 19:47:44 2020 GMT + Not After : Jul 4 19:47:44 2120 GMT + Subject: CN=Root Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:c5:f2:d9:a9:48:a2:06:dc:89:7d:e8:ab:2e:1f: + 70:ea:da:82:46:45:4e:42:38:6e:8d:a6:3e:28:84: + f1:25:c0:ea:25:af:61:ca:87:38:a5:7b:3f:d0:3a: + 57:82:c7:eb:f1:b5:b4:70:0e:71:69:22:5f:ae:49: + d3:51:df:19:97:bf:00:c3:de:99:3a:4d:f3:6d:4a: + bf:73:7e:b1:aa:72:40:b1:0d:fc:d4:af:11:f5:a9: + 7e:c3:36:7a:ac:25:86:a4:3e:7a:fe:3f:0f:22:f7: + d6:87:15:ba:33:c1:36:c3:79:4d:79:b3:ca:a5:2d: + 15:9a:63:ad:38:32:99:74:76:d7:72:7e:2f:69:ff: + 7b:b0:f6:79:ad:da:2d:9f:51:4e:d9:70:15:9c:83: + e9:10:8c:ec:7f:39:27:5d:b9:6e:86:c9:93:54:6b: + aa:82:12:82:b0:32:36:c5:94:6c:48:bb:3f:c6:af: + ef:1c:e1:0c:18:e6:0c:4c:bf:58:67:5b:1a:cd:15: + 62:37:40:40:5f:1d:76:e2:24:01:28:65:cc:ed:3f: + e1:f1:08:79:94:12:13:4c:4c:e2:a4:53:b8:fe:78: + 7f:07:00:cd:c1:3a:7b:0e:f4:35:ce:83:c7:f3:ce: + 71:9d:1f:7b:88:66:bc:b6:39:5e:26:28:e5:ef:5a: + 0d:05 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 21:E8:DE:B6:D8:64:01:72:02:C5:1C:CA:16:0C:D9:05:1A:14:A1:0C + X509v3 Authority Key Identifier: + keyid:21:E8:DE:B6:D8:64:01:72:02:C5:1C:CA:16:0C:D9:05:1A:14:A1:0C + + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha256WithRSAEncryption + 9d:4c:17:84:f3:83:90:97:a7:df:e5:af:53:ac:d7:75:94:c4: + a0:29:fa:d7:8f:a6:f8:fa:4b:d6:5e:d2:6e:8d:6d:46:89:1f: + 7b:30:2c:2d:d3:3b:b6:64:1d:ec:ad:60:c1:96:4b:9a:bc:f9: + d0:5d:af:a1:73:f7:03:99:8a:e2:59:47:48:1c:8f:7a:99:97: + 20:78:e2:16:16:e4:c3:c9:82:4e:25:58:23:75:c9:9c:71:67: + 8e:c4:79:e1:b9:ac:d9:c2:51:41:3d:a6:bf:07:0b:4b:14:8c: + ca:42:0f:c3:b7:71:c0:fb:3e:5e:de:2b:e5:7f:92:52:50:12: + 4f:63:a5:fa:3b:63:59:fa:37:3f:42:f4:ec:13:a0:c7:5d:0c: + 9c:cd:6b:32:96:e7:44:da:5f:8c:cf:c7:51:eb:81:3b:cc:e8: + 39:41:0c:a1:bb:8f:3a:f8:b1:ee:2b:97:f4:13:c9:a8:9c:1c: + 2f:2f:51:57:e4:0c:4e:2b:29:7f:5e:12:72:63:8c:bb:40:2c: + 97:14:bf:1e:7a:66:bc:64:af:78:80:64:19:37:ca:7a:f3:de: + 15:e6:23:1d:d0:90:7d:e6:5f:21:88:23:c5:23:ca:f2:29:00: + 1d:9a:7a:58:37:6d:a9:9e:ab:24:b1:c6:c5:3b:46:11:a7:53: + 80:ef:aa:9c +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgIUEYJdgDBMqW3taIgQyJBNCFA8TLAwDQYJKoZIhvcNAQEL +BQAwJzElMCMGA1UEAwwcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAgFw0y +MDA3MDMxOTQ3NDRaGA8yMTIwMDcwNDE5NDc0NFowJzElMCMGA1UEAwwcUm9vdCBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAMXy2alIogbciX3oqy4fcOragkZFTkI4bo2mPiiE8SXA6iWvYcqHOKV7 +P9A6V4LH6/G1tHAOcWkiX65J01HfGZe/AMPemTpN821Kv3N+sapyQLEN/NSvEfWp +fsM2eqwlhqQ+ev4/DyL31ocVujPBNsN5TXmzyqUtFZpjrTgymXR213J+L2n/e7D2 +ea3aLZ9RTtlwFZyD6RCM7H85J125bobJk1RrqoISgrAyNsWUbEi7P8av7xzhDBjm +DEy/WGdbGs0VYjdAQF8dduIkAShlzO0/4fEIeZQSE0xM4qRTuP54fwcAzcE6ew70 +Nc6Dx/POcZ0fe4hmvLY5XiYo5e9aDQUCAwEAAaNjMGEwHQYDVR0OBBYEFCHo3rbY +ZAFyAsUcyhYM2QUaFKEMMB8GA1UdIwQYMBaAFCHo3rbYZAFyAsUcyhYM2QUaFKEM +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUA +A4IBAQCdTBeE84OQl6ff5a9TrNd1lMSgKfrXj6b4+kvWXtJujW1GiR97MCwt0zu2 +ZB3srWDBlkuavPnQXa+hc/cDmYriWUdIHI96mZcgeOIWFuTDyYJOJVgjdcmccWeO +xHnhuazZwlFBPaa/BwtLFIzKQg/Dt3HA+z5e3ivlf5JSUBJPY6X6O2NZ+jc/QvTs +E6DHXQyczWsyludE2l+Mz8dR64E7zOg5QQyhu486+LHuK5f0E8monBwvL1FX5AxO +Kyl/XhJyY4y7QCyXFL8eema8ZK94gGQZN8p6894V5iMd0JB95l8hiCPFI8ryKQAd +mnpYN22pnqskscbFO0YRp1OA76qc +-----END CERTIFICATE----- diff --git a/t/lib/ddclient/Test/Fake/HTTPD/dummy-server-key.pem b/t/lib/ddclient/Test/Fake/HTTPD/dummy-server-key.pem new file mode 100644 index 0000000..c732d65 --- /dev/null +++ b/t/lib/ddclient/Test/Fake/HTTPD/dummy-server-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDnP5rW+E3DiWkf +q5UAtCDrNnLhR7oM2CB2n3js8tQcLUdseaevzuj2kcHo8ndBOzdwNhPyWzBF63TQ +9DduINVaqt7833KyB7vaHGa3ciDPNF9V8CM2w58BVEVwZeUqswOxnnPcojLLAuBg +iaX0mofiirxNgBuTwmHVEOvtbPygs6UiPAMCcuFxCIZCAzoNe24c87s9rajkwj98 +Cuu9wYkd8bztQ35HlODzF20Tlr6vdOUgJXGVxX8m0iik7r0S/gToi0baf+H8VMDc +Ur5V4kklyiEJz+Lt6XAmJGIuiW4iLYwgPYP30bXhdBxducu21WCTBpYczLQKTgBq +BNa6L+rHAgMBAAECggEBAMSWe+m4mVNb47R6x2cbush7N1pxAaedrKtrkv/Mx6lU +jN2Y5oc9HStQakrApcUctFp+fqKQBw/JxTtGAkFrRDWaAYtz4iubC4W2k1PsgBvm +aA3E4grSbsBQhd+xoAqWuNMs405zzT5sqZcoLZ8uJ8rdKouwFsGchFL/2bGz72gk +8smGqMdH4sQep3kJhJyWio47C7pC1qnG1xNmsfJ7+MkEL/+b95WsbNUTZHkAFzE8 +l5BBLILXR10EqGCAWiuz9WGffw7JASyrV1spojOmPBneBDhfLSgWjuv/0S1pUxVx +iZWDlukHPUVQWaDWQxE9Uscup3hORRENTOIJpBsYWhECgYEA9qACG2oHCa+a3xj/ +QMdWKWVZeMnKUDlpPhlyC9ue+K4NMBSzgG3K1qURX0xAvkPEApYKBh+rqvJqTMYk +N5K+CfLaU53Weyko5v5xPj3aSnGVsYazkoxfZ31MbbIqn+JPoNjYafTo2SZJsaQ6 +Y416FMxlWf7eR4rZGr1iqptSWvUCgYEA8An2Qdk+NMGYrnL6xr+AKygm2ri1Mz7k +XVr/jhkUxhBsvPumNQAVQaEuWAx6Mwgs+uzgJrsW8UCVAta/Jo+dWlCewqrpTsIh +jJZjkP9H91oEA6GkUNy9JI6j3KRQ6I5rGNr8nJrJ4c9+yLZa85BTkTriHvZl5zZX +SberAyPREUsCgYEAx9C4JFHxRc27Ispz9J4MlxmANjb37au2MxQWrLjRwhXypWQA +UyuhTesLejSjuAPbiWTa1j9OrQAfU/itW0FPK2xRq7GUFtEwTIcWZSFj/TCt4dmL +IE8O9SA1jiLuGgAYF+/Y13AQP++fgYfXrtTvdm5sJ1Ax87DxWZLbn/Kb9QkCgYEA +xjgDwlbKVrh0A8LxMcSb64eJpl6XS40o+aqWlFpD3Fdd5CWPF/9Mjliys4UCODgN +JN0NMQ6YIHsrUh/R098OmrEumSSX6zDGkZjy+Z7FaA5OeE04KopOKu0bha2vHovV +Br53kj8EbVNyp/5mVvGdALX2Wokwl2E5baedMceW8scCgYAwhrNIV1I6f76EgXP6 +3XU1B5c6VVk/Mlaid1Y7IrqPrhp1vcY2txZQ/NFEnvS1UMTvTskccgpIJJLd27D7 +CxDQGrXTfFOONZN6KzArGtX/m3PiTs6Mz3Zn8R5rJsCvda4kxEu0WV9KqZRSDGoM +pAawXm36qael22agLPA2zeH9Gg== +-----END PRIVATE KEY-----