New upstream version 2.3.1

This commit is contained in:
Jan Wagner 2021-04-11 11:58:04 +02:00
parent 5c6ba24b61
commit 09f4277f49
42 changed files with 685 additions and 3601 deletions

View file

@ -117,7 +117,7 @@ typedef enum curlhelp_ssl_library {
enum {
REGS = 2,
MAX_RE_SIZE = 256
MAX_RE_SIZE = 1024
};
#include "regex.h"
regex_t preg;
@ -145,6 +145,7 @@ thresholds *thlds;
char user_agent[DEFAULT_BUFFER_SIZE];
int verbose = 0;
int show_extended_perfdata = FALSE;
int show_body = FALSE;
int min_page_len = 0;
int max_page_len = 0;
int redir_depth = 0;
@ -195,6 +196,7 @@ int ssl_version = CURL_SSLVERSION_DEFAULT;
char *client_cert = NULL;
char *client_privkey = NULL;
char *ca_cert = NULL;
int verify_peer_and_host = FALSE;
int is_openssl_callback = FALSE;
#if defined(HAVE_SSL) && defined(USE_OPENSSL)
X509 *cert = NULL;
@ -296,6 +298,28 @@ CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm)
#endif /* USE_OPENSSL */
#endif /* HAVE_SSL */
/* returns a string "HTTP/1.x" or "HTTP/2" */
static char *string_statuscode (int major, int minor)
{
static char buf[10];
switch (major) {
case 1:
snprintf (buf, sizeof (buf), "HTTP/%d.%d", major, minor);
break;
case 2:
case 3:
snprintf (buf, sizeof (buf), "HTTP/%d", major);
break;
default:
/* assuming here HTTP/N with N>=4 */
snprintf (buf, sizeof (buf), "HTTP/%d", major);
break;
}
return buf;
}
/* Checks if the server 'reply' is one of the expected 'statuscodes' */
static int
expected_statuscode (const char *reply, const char *statuscodes)
@ -467,9 +491,11 @@ check_http (void)
if (client_privkey)
handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLKEY, client_privkey), "CURLOPT_SSLKEY");
if (ca_cert) {
handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CAINFO, ca_cert), "CURLOPT_CAINFO");
}
if (ca_cert || verify_peer_and_host) {
/* per default if we have a CA verify both the peer and the
* hostname in the certificate, can be switched off later */
handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CAINFO, ca_cert), "CURLOPT_CAINFO");
handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 1), "CURLOPT_SSL_VERIFYPEER");
handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYHOST, 2), "CURLOPT_SSL_VERIFYHOST");
} else {
@ -640,7 +666,7 @@ check_http (void)
/* Curl errors, result in critical Nagios state */
if (res != CURLE_OK) {
snprintf (msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"),
server_port, res, curl_easy_strerror(res));
server_port, res, errbuf[0] ? errbuf : curl_easy_strerror(res));
die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
}
@ -746,7 +772,8 @@ GOT_FIRST_CERT:
if (curlhelp_parse_statusline (header_buf.buf, &status_line) < 0) {
snprintf (msg, DEFAULT_BUFFER_SIZE, "Unparsable status line in %.3g seconds response time|%s\n",
total_time, perfstring);
die (STATE_CRITICAL, "HTTP CRITICAL HTTP/1.x %ld unknown - %s", code, msg);
/* we cannot know the major/minor version here for sure as we cannot parse the first line */
die (STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", code, msg);
}
/* get result code from cURL */
@ -766,7 +793,9 @@ GOT_FIRST_CERT:
snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"), status_line.first_line);
else
snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: %s\n"), server_port, status_line.first_line);
die (STATE_CRITICAL, "HTTP CRITICAL - %s", msg);
die (STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg,
show_body ? "\n" : "",
show_body ? body_buf.buf : "");
}
if( server_expect_yn ) {
@ -823,8 +852,8 @@ GOT_FIRST_CERT:
/* check status codes, set exit status accordingly */
if( status_line.http_code != code ) {
die (STATE_CRITICAL, _("HTTP CRITICAL HTTP/%d.%d %d %s - different HTTP codes (cUrl has %ld)\n"),
status_line.http_major, status_line.http_minor,
die (STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"),
string_statuscode (status_line.http_major, status_line.http_minor),
status_line.http_code, status_line.msg, code);
}
@ -895,13 +924,15 @@ GOT_FIRST_CERT:
msg[strlen(msg)-3] = '\0';
/* TODO: separate _() msg and status code: die (result, "HTTP %s: %s\n", state_text(result), msg); */
die (result, "HTTP %s: HTTP/%d.%d %d %s%s%s - %d bytes in %.3f second response time %s|%s\n",
state_text(result), status_line.http_major, status_line.http_minor,
die (result, "HTTP %s: %s %d %s%s%s - %d bytes in %.3f second response time %s|%s\n%s%s",
state_text(result), string_statuscode (status_line.http_major, status_line.http_minor),
status_line.http_code, status_line.msg,
strlen(msg) > 0 ? " - " : "",
msg, page_len, total_time,
(display_html ? "</A>" : ""),
perfstring);
perfstring,
(show_body ? body_buf.buf : ""),
(show_body ? "\n" : "") );
/* proper cleanup after die? */
curlhelp_free_statusline(&status_line);
@ -1041,7 +1072,7 @@ redir (curlhelp_write_curlbuf* header_buf)
const UriPathSegmentA* p = uri.pathHead;
for (; p; p = p->next) {
strncat (new_url, "/", DEFAULT_BUFFER_SIZE);
strncat (new_url, uri_string (p->text, buf, DEFAULT_BUFFER_SIZE), DEFAULT_BUFFER_SIZE);
strncat (new_url, uri_string (p->text, buf, DEFAULT_BUFFER_SIZE), DEFAULT_BUFFER_SIZE-1);
}
}
@ -1136,6 +1167,7 @@ process_arguments (int argc, char **argv)
{"client-cert", required_argument, 0, 'J'},
{"private-key", required_argument, 0, 'K'},
{"ca-cert", required_argument, 0, CA_CERT_OPTION},
{"verify-cert", no_argument, 0, 'D'},
{"useragent", required_argument, 0, 'A'},
{"header", required_argument, 0, 'k'},
{"no-body", no_argument, 0, 'N'},
@ -1146,6 +1178,7 @@ process_arguments (int argc, char **argv)
{"use-ipv4", no_argument, 0, '4'},
{"use-ipv6", no_argument, 0, '6'},
{"extended-perfdata", no_argument, 0, 'E'},
{"show-body", no_argument, 0, 'B'},
{"http-version", required_argument, 0, HTTP_VERSION_OPTION},
{0, 0, 0, 0}
};
@ -1170,7 +1203,7 @@ process_arguments (int argc, char **argv)
server_url = strdup(DEFAULT_SERVER_URL);
while (1) {
c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:d:e:p:s:R:r:u:f:C:J:K:nlLS::m:M:NE", longopts, &option);
c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:d:e:p:s:R:r:u:f:C:J:K:DnlLS::m:M:NEB", longopts, &option);
if (c == -1 || c == EOF || c == 1)
break;
@ -1309,6 +1342,11 @@ process_arguments (int argc, char **argv)
test_file(optarg);
ca_cert = optarg;
goto enable_ssl;
#endif
#ifdef LIBCURL_FEATURE_SSL
case 'D': /* verify peer certificate & host */
verify_peer_and_host = TRUE;
goto enable_ssl;
#endif
case 'S': /* use SSL */
#ifdef LIBCURL_FEATURE_SSL
@ -1354,7 +1392,7 @@ process_arguments (int argc, char **argv)
ssl_version = CURL_SSLVERSION_DEFAULT;
#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */
else
usage4 (_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2 (with optional '+' suffix)"));
usage4 (_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2, 1.3 (with optional '+' suffix)"));
}
#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0)
if (got_plus) {
@ -1513,6 +1551,9 @@ process_arguments (int argc, char **argv)
case 'E': /* show extended perfdata */
show_extended_perfdata = TRUE;
break;
case 'B': /* print body content after status line */
show_body = TRUE;
break;
case HTTP_VERSION_OPTION:
curl_http_version = CURL_HTTP_VERSION_NONE;
if (strcmp (optarg, "1.0") == 0) {
@ -1659,7 +1700,7 @@ print_help (void)
printf (" %s\n", "-S, --ssl=VERSION[+]");
printf (" %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents"));
printf (" %s\n", _("auto-negotiation (2 = SSLv2, 3 = SSLv3, 1 = TLSv1, 1.1 = TLSv1.1,"));
printf (" %s\n", _("1.2 = TLSv1.2). With a '+' suffix, newer versions are also accepted."));
printf (" %s\n", _("1.2 = TLSv1.2, 1.3 = TLSv1.3). With a '+' suffix, newer versions are also accepted."));
printf (" %s\n", _("Note: SSLv2 and SSLv3 are deprecated and are usually disabled in libcurl"));
printf (" %s\n", "--sni");
printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)"));
@ -1680,6 +1721,8 @@ print_help (void)
printf (" %s\n", _("matching the client certificate"));
printf (" %s\n", "--ca-cert=FILE");
printf (" %s\n", _("CA certificate file to verify peer against"));
printf (" %s\n", "-D, --verify-cert");
printf (" %s\n", _("Verify the peer's SSL certificate and hostname"));
#endif
printf (" %s\n", "-e, --expect=STRING");
@ -1723,6 +1766,8 @@ print_help (void)
printf (" %s\n", _("Any other tags to be sent in http header. Use multiple times for additional headers"));
printf (" %s\n", "-E, --extended-perfdata");
printf (" %s\n", _("Print additional performance data"));
printf (" %s\n", "-B, --show-body");
printf (" %s\n", _("Print body content below status line"));
printf (" %s\n", "-L, --link");
printf (" %s\n", _("Wrap output in HTML link (obsoleted by urlize)"));
printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport|curl>");
@ -1813,15 +1858,21 @@ print_usage (void)
{
printf ("%s\n", _("Usage:"));
printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname);
printf (" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate file>]\n");
printf (" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate file>] [-D]\n");
printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-a auth]\n");
printf (" [-b proxy_auth] [-f <ok|warning|critcal|follow|sticky|stickyport|curl>]\n");
printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n");
printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n");
printf (" [-A string] [-k string] [-S <version>] [--sni] [-C <warn_age>[,<crit_age>]]\n");
printf (" [-A string] [-k string] [-S <version>] [--sni]\n");
printf (" [-T <content-type>] [-j method]\n");
printf (" [--http-version=<version>]\n");
printf (" %s -H <vhost> | -I <IP-address> -C <warn_age>[,<crit_age>]\n",progname);
printf (" [-p <port>] [-t <timeout>] [-4|-6] [--sni]\n");
printf ("\n");
#ifdef LIBCURL_FEATURE_SSL
printf ("%s\n", _("In the first form, make an HTTP request."));
printf ("%s\n\n", _("In the second form, connect to the server and check the TLS certificate."));
#endif
printf ("%s\n", _("WARNING: check_curl is experimental. Please use"));
printf ("%s\n\n", _("check_http if you need a stable version."));
}
@ -2037,7 +2088,7 @@ get_header_value (const struct phr_header* headers, const size_t nof_headers, co
{
int i;
for( i = 0; i < nof_headers; i++ ) {
if( strncasecmp( header, headers[i].name, max( headers[i].name_len, 4 ) ) == 0 ) {
if(headers[i].name != NULL && strncasecmp( header, headers[i].name, max( headers[i].name_len, 4 ) ) == 0 ) {
return strndup( headers[i].value, headers[i].value_len );
}
}

View file

@ -473,9 +473,23 @@ process_arguments (int argc, char **argv)
case 'a': /* expected address */
if (strlen (optarg) >= ADDRESS_LENGTH)
die (STATE_UNKNOWN, _("Input buffer overflow\n"));
expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**));
expected_address[expected_address_cnt] = strdup(optarg);
expected_address_cnt++;
if (strchr(optarg, ',') != NULL) {
char *comma = strchr(optarg, ',');
while (comma != NULL) {
expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**));
expected_address[expected_address_cnt] = strndup(optarg, comma - optarg);
expected_address_cnt++;
optarg = comma + 1;
comma = strchr(optarg, ',');
}
expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**));
expected_address[expected_address_cnt] = strdup(optarg);
expected_address_cnt++;
} else {
expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**));
expected_address[expected_address_cnt] = strdup(optarg);
expected_address_cnt++;
}
break;
case 'A': /* expect authority */
expect_authority = TRUE;

View file

@ -72,7 +72,7 @@ int maximum_age = -1;
enum {
REGS = 2,
MAX_RE_SIZE = 256
MAX_RE_SIZE = 1024
};
#include "regex.h"
regex_t preg;
@ -1567,6 +1567,10 @@ print_help (void)
print_usage ();
#ifdef HAVE_SSL
printf (_("In the first form, make an HTTP request."));
printf (_("In the second form, connect to the server and check the TLS certificate."));
#endif
printf (_("NOTE: One or both of -H and -I must be specified"));
printf ("\n");
@ -1726,6 +1730,8 @@ print_usage (void)
printf (" [-b proxy_auth] [-f <ok|warning|critcal|follow|sticky|stickyport>]\n");
printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n");
printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n");
printf (" [-A string] [-k string] [-S <version>] [--sni] [-C <warn_age>[,<crit_age>]]\n");
printf (" [-A string] [-k string] [-S <version>] [--sni]\n");
printf (" [-T <content-type>] [-j method]\n");
printf (" %s -H <vhost> | -I <IP-address> -C <warn_age>[,<crit_age>]\n",progname);
printf (" [-p <port>] [-t <timeout>] [-4|-6] [--sni]\n");
}

View file

@ -136,18 +136,18 @@ main (int argc, char **argv)
die (STATE_CRITICAL, "QUERY %s: Fetch row error - %s\n", _("CRITICAL"), error);
}
/* free the result */
mysql_free_result (res);
/* close the connection */
mysql_close (&mysql);
if (! is_numeric(row[0])) {
die (STATE_CRITICAL, "QUERY %s: %s - '%s'\n", _("CRITICAL"), _("Is not a numeric"), row[0]);
}
value = strtod(row[0], NULL);
/* free the result */
mysql_free_result (res);
/* close the connection */
mysql_close (&mysql);
if (verbose >= 3)
printf("mysql result: %f\n", value);

View file

@ -347,7 +347,7 @@ process_arguments (int argc, char **argv)
if (!is_pg_dbname (optarg)) /* checks length and valid chars */
usage2 (_("Database name is not valid"), optarg);
else /* we know length, and know optarg is terminated, so us strcpy */
strcpy (dbName, optarg);
snprintf(dbName, NAMEDATALEN, "%s", optarg);
break;
case 'l': /* login name */
if (!is_pg_logname (optarg))

View file

@ -576,6 +576,9 @@ main (int argc, char **argv)
len = sizeof(perfstr)-strlen(perfstr)-1;
strncat(perfstr, show, len>ptr-show ? ptr-show : len);
if (type)
strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
if (warning_thresholds) {
strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1);
strncat(perfstr, warning_thresholds, sizeof(perfstr)-strlen(perfstr)-1);
@ -588,8 +591,6 @@ main (int argc, char **argv)
strncat(perfstr, critical_thresholds, sizeof(perfstr)-strlen(perfstr)-1);
}
if (type)
strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1);
strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1);
}
}

View file

@ -9,7 +9,7 @@ use Test::More;
use POSIX qw/mktime strftime/;
use NPTest;
plan tests => 57;
plan tests => 58;
my $successOutput = '/OK.*HTTP.*second/';
@ -46,7 +46,7 @@ $res = NPTest->testCmd(
);
cmp_ok( $res->return_code, '==', 2, "Webserver $host_nonresponsive not responding" );
# was CRITICAL only, but both check_curl and check_http print HTTP CRITICAL (puzzle?!)
cmp_ok( $res->output, 'eq', "HTTP CRITICAL - Invalid HTTP response received from host on port 80: cURL returned 28 - Timeout was reached", "Output OK");
like( $res->output, "/HTTP CRITICAL - Invalid HTTP response received from host on port 80: cURL returned 28 - Connection timed out after/", "Output OK");
$res = NPTest->testCmd(
"./$plugin $hostname_invalid -wt 1 -ct 2"
@ -56,7 +56,7 @@ cmp_ok( $res->return_code, '==', 2, "Webserver $hostname_invalid not valid" );
# On Debian, it is Name or service not known, on Darwin, it is No address associated with nodename
# Is also possible to get a socket timeout if DNS is not responding fast enough
# cURL gives us consistent strings from it's own 'lib/strerror.c'
like( $res->output, "/cURL returned 6 - Couldn't resolve host name/", "Output OK");
like( $res->output, "/cURL returned 6 - Could not resolve host:/", "Output OK");
# host header checks
$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http");
@ -94,6 +94,9 @@ SKIP: {
$res = NPTest->testCmd("./$plugin -v -H $host_tls_http:443 -S -p 443");
like( $res->output, '/^Host: '.$host_tls_http.'\s*$/ms', "Host Header OK" );
$res = NPTest->testCmd("./$plugin -v -H $host_tls_http -D -p 443");
like( $res->output, '/(^Host: '.$host_tls_http.'\s*$)|(cURL returned 60)/ms', "Host Header OK" );
};
SKIP: {

View file

@ -21,7 +21,7 @@ use FindBin qw($Bin);
$ENV{'LC_TIME'} = "C";
my $common_tests = 70;
my $common_tests = 72;
my $ssl_only_tests = 8;
# Check that all dependent modules are available
eval "use HTTP::Daemon 6.01;";
@ -188,6 +188,12 @@ sub run_server {
$c->send_basic_header;
$c->send_header('foo');
$c->send_crlf;
} elsif ($r->url->path eq "/header_broken_check") {
$c->send_basic_header;
$c->send_header('foo');
print $c "Test1:: broken\n";
print $c " Test2: leading whitespace\n";
$c->send_crlf;
} elsif ($r->url->path eq "/virtual_port") {
# return sent Host header
$c->send_basic_header;
@ -247,7 +253,7 @@ my $cmd;
# advanced checks with virtual hostname and virtual port
SKIP: {
skip "libcurl version is smaller than $required_version", 6 unless $use_advanced_checks;
# http without virtual port
$cmd = "./$plugin -H $virtual_host -I 127.0.0.1 -p $port_http -u /virtual_port -r ^$virtual_host:$port_http\$";
$result = NPTest->testCmd( $cmd );
@ -259,7 +265,7 @@ SKIP: {
$result = NPTest->testCmd( $cmd );
is( $result->return_code, 0, $cmd);
like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
# http with virtual port (80)
$cmd = "./$plugin -H $virtual_host:80 -I 127.0.0.1 -p $port_http -u /virtual_port -r ^$virtual_host\$";
$result = NPTest->testCmd( $cmd );
@ -321,6 +327,10 @@ sub run_common_tests {
is( $result->return_code, 2, "Missing header string check");
like( $result->output, qr%^HTTP CRITICAL: HTTP/1\.1 200 OK - header 'bar' not found on 'https?://127\.0\.0\.1:\d+/header_check'%, "Shows search string and location");
$result = NPTest->testCmd( "$command -u /header_broken_check" );
is( $result->return_code, 0, "header_check search for string");
like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - 138 bytes in [\d\.]+ second/', "Output correct" );
my $cmd;
$cmd = "$command -u /slow";
$result = NPTest->testCmd( $cmd );