From 791890741be350722566371483d575d7cabebc8d Mon Sep 17 00:00:00 2001 From: Richard Hansen Date: Sun, 2 Aug 2020 22:46:52 -0400 Subject: [PATCH] Move `use=cisco` and `use=cisco-asa` to `%builtinfw` --- Makefile.am | 1 + ddclient.in | 101 +++++++++++++++++++++++-------------------- t/builtinfw_query.pl | 27 ++++++++++++ 3 files changed, 83 insertions(+), 46 deletions(-) create mode 100644 t/builtinfw_query.pl diff --git a/Makefile.am b/Makefile.am index 636f379..ceef877 100644 --- a/Makefile.am +++ b/Makefile.am @@ -70,6 +70,7 @@ AM_PL_LOG_FLAGS = -Mstrict -w \ -I'$(abs_top_srcdir)'/t/lib \ -MDevel::Autoflush handwritten_tests = \ + t/builtinfw_query.pl \ t/geturl_connectivity.pl \ t/geturl_ssl.pl \ t/is-and-extract-ipv4.pl \ diff --git a/ddclient.in b/ddclient.in index b6db09c..6612167 100755 --- a/ddclient.in +++ b/ddclient.in @@ -112,7 +112,7 @@ my %builtinweb = ( 'nsupdate.info-ipv6' => {'url' => 'http://ipv6.nsupdate.info/myip'}, 'zoneedit' => {'url' => 'http://dynamic.zoneedit.com/checkip.html'}, ); -my %builtinfw = ( +our %builtinfw = ( '2wire' => { 'name' => '2Wire 1701HG Gateway', 'url' => '/xslt?PAGE=B01', @@ -153,6 +153,57 @@ my %builtinfw = ( 'url' => '/shell/show+ip+interfaces', 'skip' => '.*inet', }, + 'cisco' => { + 'name' => 'Cisco FW', + 'query' => sub { + my ($h) = @_; + # Stuff added to support Cisco router ip http daemon + # User fw-login should only have level 1 access to prevent + # password theft. This is pretty harmless. + my $queryif = opt('if', $h); + + # Convert slashes to protected value "\/" + $queryif =~ s%\/%\\\/%g; + + # Protect special HTML characters (like '?') + $queryif =~ s/([\?&= ])/sprintf("%%%02x", ord($1))/ge; + + my $url = sprintf("http://%s/level/1/exec/show/ip/interface/brief/%s/CR", + opt('fw', $h), $queryif); + my $reply = geturl( + url => $url, + login => opt('fw-login', $h), + password => opt('fw-password', $h), + ignore_ssl_option => 1, + ) // ''; + return ($url, $reply); + }, + }, + 'cisco-asa' => { + 'name' => 'Cisco ASA', + 'query' => sub { + my ($h) = @_; + # Stuff added to support Cisco ASA ip https daemon + # User fw-login should only have level 1 access to prevent + # password theft. This is pretty harmless. + my $queryif = opt('if', $h); + + # Convert slashes to protected value "\/" + $queryif =~ s%\/%\\\/%g; + + # Protect special HTML characters (like '?') + $queryif =~ s/([\?&= ])/sprintf("%%%02x", ord($1))/ge; + + my $url = sprintf("https://%s/exec/show%20interface%20%s", opt('fw', $h), $queryif); + my $reply = geturl( + url => $url, + login => opt('fw-login', $h), + password => opt('fw-password', $h), + ignore_ssl_option => 1, + ) // ''; + return ($url, $reply); + }, + }, 'dlink-524' => { 'name' => 'D-Link DI-524', 'url' => '/st_device.html', @@ -356,8 +407,6 @@ my %ip_strategies = ( 'fw' => ": obtain IP from a firewall/router device by visiting the URL given by '-fw '", 'if' => ": obtain IP from the interface given by '-if '", 'cmd' => ": obtain IP by running the command given by '-cmd '", - 'cisco' => ": obtain IP from Cisco FW device at the address given by '-fw
'", - 'cisco-asa' => ": obtain IP from Cisco ASA device at the address given by '-fw
'", map({ $_ => sprintf(": obtain IP from %s device at the address given by '-fw
'", $builtinfw{$_}->{'name'}) } keys(%builtinfw)), @@ -365,7 +414,7 @@ my %ip_strategies = ( sub ip_strategies_usage { return map({ sprintf(" -use=%-22s %s.", $_, $ip_strategies{$_}) } - ('ip', 'web', 'if', 'cmd', 'fw', sort('cisco', 'cisco-asa', keys(%builtinfw)))); + ('ip', 'web', 'if', 'cmd', 'fw', sort(keys(%builtinfw)))); } sub setv { @@ -2250,49 +2299,9 @@ sub get_ip { $reply = geturl(proxy => opt('proxy', $h), url => $url) // ''; } - } elsif (($use eq 'cisco')) { - # Stuff added to support Cisco router ip http daemon - # User fw-login should only have level 1 access to prevent - # password theft. This is pretty harmless. - my $queryif = opt('if', $h); + } elsif (defined(my $query = $builtinfw{$use}{query})) { $skip = opt('fw-skip', $h) // ''; - - # Convert slashes to protected value "\/" - $queryif =~ s%\/%\\\/%g; - - # Protect special HTML characters (like '?') - $queryif =~ s/([\?&= ])/sprintf("%%%02x", ord($1))/ge; - - $url = "http://" . opt('fw', $h) . "/level/1/exec/show/ip/interface/brief/${queryif}/CR"; - $reply = geturl( - url => $url, - login => opt('fw-login', $h), - password => opt('fw-password', $h), - ignore_ssl_option => 1, - ) // ''; - $arg = $url; - - } elsif (($use eq 'cisco-asa')) { - # Stuff added to support Cisco ASA ip https daemon - # User fw-login should only have level 1 access to prevent - # password theft. This is pretty harmless. - my $queryif = opt('if', $h); - $skip = opt('fw-skip', $h) // ''; - - # Convert slashes to protected value "\/" - $queryif =~ s%\/%\\\/%g; - - # Protect special HTML characters (like '?') - $queryif =~ s/([\?&= ])/sprintf("%%%02x", ord($1))/ge; - - $url = "https://" . opt('fw', $h) . "/exec/show%20interface%20${queryif}"; - $reply = geturl( - url => $url, - login => opt('fw-login', $h), - password => opt('fw-password', $h), - ignore_ssl_option => 1, - ) // ''; - $arg = $url; + ($arg, $reply) = &$query($h); } else { $url = opt('fw', $h) // ''; diff --git a/t/builtinfw_query.pl b/t/builtinfw_query.pl new file mode 100644 index 0000000..2086cda --- /dev/null +++ b/t/builtinfw_query.pl @@ -0,0 +1,27 @@ +use Test::More; +eval { require Test::MockModule; } or plan(skip_all => $@); +SKIP: { eval { require Test::Warnings; } or skip($@, 1); } +eval { require 'ddclient'; } or BAIL_OUT($@); + +my $debug_msg; +my $module = Test::MockModule->new('ddclient'); +# Note: 'mock' is used instead of 'redefine' because 'redefine' is not available in the versions of +# Test::MockModule distributed with old Debian and Ubuntu releases. +$module->mock('debug', sub { + BAIL_OUT("debug already called") if defined($debug_msg); + $debug_msg = sprintf(shift, @_); +}); +my $got_host; +$ddclient::builtinfw{dummy_device} = { + name => 'dummy device for testing', + query => sub { ($got_host) = @_; return ("asdf", "192.0.2.5 foo 192.0.2.123 bar"); }, +}; +$ddclient::globals{'fw-skip'} = 'foo'; + +my $got = ddclient::get_ip('dummy_device', 'dummy_host'); + +is($got_host, 'dummy_host', "host is passed through"); +is($got, '192.0.2.123', "returned IP matches"); +like($debug_msg, qr/\basdf\b/, "returned arg is properly handled"); + +done_testing();