diff options
author | Lorenz <12514511+RincewindsHat@users.noreply.github.com> | 2023-02-06 12:06:10 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-06 12:06:10 (GMT) |
commit | e0dfb0622d19a4b4340dab9a315cb4b649f6f1e4 (patch) | |
tree | 21ccc76338be77623013b0cb0ce6f472381340e3 /plugins | |
parent | 843f17918886edd5c8d14e5a9967785c654053c8 (diff) | |
parent | 03efbb8e4f736bf2df5d9477dd4191501fe035ea (diff) | |
download | monitoring-plugins-e0dfb0622d19a4b4340dab9a315cb4b649f6f1e4.tar.gz |
Merge pull request #1840 from RincewindsHat/check_http_end_chunk_only
check_http: fix for single zero size chunk only
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/check_http.c | 8 | ||||
-rwxr-xr-x | plugins/tests/check_http.t | 70 |
2 files changed, 76 insertions, 2 deletions
diff --git a/plugins/check_http.c b/plugins/check_http.c index 5fa310f..8dda046 100644 --- a/plugins/check_http.c +++ b/plugins/check_http.c | |||
@@ -1462,7 +1462,13 @@ char *unchunk_content(const char *content) { | |||
1462 | memcpy(result + (overall_size - size_of_chunk), start_of_chunk, size_of_chunk); | 1462 | memcpy(result + (overall_size - size_of_chunk), start_of_chunk, size_of_chunk); |
1463 | } | 1463 | } |
1464 | 1464 | ||
1465 | result[overall_size] = '\0'; | 1465 | if (overall_size == 0 && result == NULL) { |
1466 | // We might just have received the end chunk without previous content, so result is never allocated | ||
1467 | result = calloc(1, sizeof(char)); | ||
1468 | // No error handling here, we can only return NULL anyway | ||
1469 | } else { | ||
1470 | result[overall_size] = '\0'; | ||
1471 | } | ||
1466 | return result; | 1472 | return result; |
1467 | } | 1473 | } |
1468 | 1474 | ||
diff --git a/plugins/tests/check_http.t b/plugins/tests/check_http.t index d766ac3..6078b27 100755 --- a/plugins/tests/check_http.t +++ b/plugins/tests/check_http.t | |||
@@ -9,12 +9,14 @@ use strict; | |||
9 | use Test::More; | 9 | use Test::More; |
10 | use NPTest; | 10 | use NPTest; |
11 | use FindBin qw($Bin); | 11 | use FindBin qw($Bin); |
12 | use IO::Socket::INET; | ||
12 | 13 | ||
13 | $ENV{'LC_TIME'} = "C"; | 14 | $ENV{'LC_TIME'} = "C"; |
14 | 15 | ||
15 | my $common_tests = 71; | 16 | my $common_tests = 71; |
16 | my $virtual_port_tests = 8; | 17 | my $virtual_port_tests = 8; |
17 | my $ssl_only_tests = 12; | 18 | my $ssl_only_tests = 12; |
19 | my $chunked_encoding_special_tests = 1; | ||
18 | # Check that all dependent modules are available | 20 | # Check that all dependent modules are available |
19 | eval "use HTTP::Daemon 6.01;"; | 21 | eval "use HTTP::Daemon 6.01;"; |
20 | plan skip_all => 'HTTP::Daemon >= 6.01 required' if $@; | 22 | plan skip_all => 'HTTP::Daemon >= 6.01 required' if $@; |
@@ -30,7 +32,7 @@ if ($@) { | |||
30 | plan skip_all => "Missing required module for test: $@"; | 32 | plan skip_all => "Missing required module for test: $@"; |
31 | } else { | 33 | } else { |
32 | if (-x "./$plugin") { | 34 | if (-x "./$plugin") { |
33 | plan tests => $common_tests * 2 + $ssl_only_tests + $virtual_port_tests; | 35 | plan tests => $common_tests * 2 + $ssl_only_tests + $virtual_port_tests + $chunked_encoding_special_tests; |
34 | } else { | 36 | } else { |
35 | plan skip_all => "No $plugin compiled"; | 37 | plan skip_all => "No $plugin compiled"; |
36 | } | 38 | } |
@@ -51,6 +53,7 @@ my $port_http = 50000 + int(rand(1000)); | |||
51 | my $port_https = $port_http + 1; | 53 | my $port_https = $port_http + 1; |
52 | my $port_https_expired = $port_http + 2; | 54 | my $port_https_expired = $port_http + 2; |
53 | my $port_https_clientcert = $port_http + 3; | 55 | my $port_https_clientcert = $port_http + 3; |
56 | my $port_hacked_http = $port_http + 4; | ||
54 | 57 | ||
55 | # This array keeps sockets around for implementing timeouts | 58 | # This array keeps sockets around for implementing timeouts |
56 | my @persist; | 59 | my @persist; |
@@ -72,6 +75,28 @@ if (!$pid) { | |||
72 | } | 75 | } |
73 | push @pids, $pid; | 76 | push @pids, $pid; |
74 | 77 | ||
78 | # Fork the hacked HTTP server | ||
79 | undef $pid; | ||
80 | $pid = fork; | ||
81 | defined $pid or die "Failed to fork"; | ||
82 | if (!$pid) { | ||
83 | # this is the fork | ||
84 | undef @pids; | ||
85 | my $socket = new IO::Socket::INET ( | ||
86 | LocalHost => '0.0.0.0', | ||
87 | LocalPort => $port_hacked_http, | ||
88 | Proto => 'tcp', | ||
89 | Listen => 5, | ||
90 | Reuse => 1 | ||
91 | ); | ||
92 | die "cannot create socket $!n" unless $socket; | ||
93 | my $local_sock = $socket->sockport(); | ||
94 | print "server waiting for client connection on port $local_sock\n"; | ||
95 | run_hacked_http_server ( $socket ); | ||
96 | die "hacked http server stopped"; | ||
97 | } | ||
98 | push @pids, $pid; | ||
99 | |||
75 | if (exists $servers->{https}) { | 100 | if (exists $servers->{https}) { |
76 | # Fork a normal HTTPS server | 101 | # Fork a normal HTTPS server |
77 | $pid = fork; | 102 | $pid = fork; |
@@ -207,6 +232,37 @@ sub run_server { | |||
207 | } | 232 | } |
208 | } | 233 | } |
209 | 234 | ||
235 | sub run_hacked_http_server { | ||
236 | my $socket = shift; | ||
237 | |||
238 | # auto-flush on socket | ||
239 | $| = 1; | ||
240 | |||
241 | |||
242 | while(1) | ||
243 | { | ||
244 | # waiting for a new client connection | ||
245 | my $client_socket = $socket->accept(); | ||
246 | |||
247 | # get information about a newly connected client | ||
248 | my $client_address = $client_socket->peerhost(); | ||
249 | my $client_portn = $client_socket->peerport(); | ||
250 | print "connection from $client_address:$client_portn"; | ||
251 | |||
252 | # read up to 1024 characters from the connected client | ||
253 | my $data = ""; | ||
254 | $client_socket->recv($data, 1024); | ||
255 | print "received data: $data"; | ||
256 | |||
257 | # write response data to the connected client | ||
258 | $data = "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\n"; | ||
259 | $client_socket->send($data); | ||
260 | |||
261 | # notify client that response has been sent | ||
262 | shutdown($client_socket, 1); | ||
263 | } | ||
264 | } | ||
265 | |||
210 | END { | 266 | END { |
211 | foreach my $pid (@pids) { | 267 | foreach my $pid (@pids) { |
212 | if ($pid) { print "Killing $pid\n"; kill "INT", $pid } | 268 | if ($pid) { print "Killing $pid\n"; kill "INT", $pid } |
@@ -222,6 +278,7 @@ if ($ARGV[0] && $ARGV[0] eq "-d") { | |||
222 | my $result; | 278 | my $result; |
223 | my $command = "./$plugin -H 127.0.0.1"; | 279 | my $command = "./$plugin -H 127.0.0.1"; |
224 | 280 | ||
281 | run_chunked_encoding_special_test( {command => "$command -p $port_hacked_http"}); | ||
225 | run_common_tests( { command => "$command -p $port_http" } ); | 282 | run_common_tests( { command => "$command -p $port_http" } ); |
226 | SKIP: { | 283 | SKIP: { |
227 | skip "HTTP::Daemon::SSL not installed", $common_tests + $ssl_only_tests if ! exists $servers->{https}; | 284 | skip "HTTP::Daemon::SSL not installed", $common_tests + $ssl_only_tests if ! exists $servers->{https}; |
@@ -511,3 +568,14 @@ sub run_common_tests { | |||
511 | }; | 568 | }; |
512 | is( $@, "", $cmd ); | 569 | is( $@, "", $cmd ); |
513 | } | 570 | } |
571 | |||
572 | sub run_chunked_encoding_special_test { | ||
573 | my ($opts) = @_; | ||
574 | my $command = $opts->{command}; | ||
575 | |||
576 | $cmd = "$command -u / -s 'ChunkedEncodingSpecialTest'"; | ||
577 | eval { | ||
578 | $result = NPTest->testCmd( $cmd, 5 ); | ||
579 | }; | ||
580 | is( $@, "", $cmd ); | ||
581 | } | ||