summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Nierlein <sven@nierlein.de>2021-08-10 10:22:49 (GMT)
committerGitHub <noreply@github.com>2021-08-10 10:22:49 (GMT)
commitf1be271c3c492ae1af4674e3a60307b57a6c4539 (patch)
tree17705ecdbf22cc15d7c7b03a9e4ae1e896396b83
parent5a2400cc2a9e76787320632ea402f6d8378d5124 (diff)
parent67088216abd866cc28dc438af1e89ca9de60c48d (diff)
downloadmonitoring-plugins-f1be271.tar.gz
Merge pull request #1700 from monitoring-plugins/feature_check_curl
Feature check curl
-rw-r--r--plugins/check_curl.c85
1 files changed, 77 insertions, 8 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index 59e398b..5990b95 100644
--- a/plugins/check_curl.c
+++ b/plugins/check_curl.c
@@ -55,6 +55,12 @@ const char *email = "devel@monitoring-plugins.org";
55 55
56#include <arpa/inet.h> 56#include <arpa/inet.h>
57 57
58#if defined(HAVE_SSL) && defined(USE_OPENSSL)
59#include <openssl/opensslv.h>
60#endif
61
62#include <netdb.h>
63
58#define MAKE_LIBCURL_VERSION(major, minor, patch) ((major)*0x10000 + (minor)*0x100 + (patch)) 64#define MAKE_LIBCURL_VERSION(major, minor, patch) ((major)*0x10000 + (minor)*0x100 + (patch))
59 65
60#define DEFAULT_BUFFER_SIZE 2048 66#define DEFAULT_BUFFER_SIZE 2048
@@ -206,6 +212,7 @@ int maximum_age = -1;
206int address_family = AF_UNSPEC; 212int address_family = AF_UNSPEC;
207curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN; 213curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN;
208int curl_http_version = CURL_HTTP_VERSION_NONE; 214int curl_http_version = CURL_HTTP_VERSION_NONE;
215int automatic_decompression = FALSE;
209 216
210int process_arguments (int, char**); 217int process_arguments (int, char**);
211void handle_curl_option_return_code (CURLcode res, const char* option); 218void handle_curl_option_return_code (CURLcode res, const char* option);
@@ -285,7 +292,9 @@ int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
285 * TODO: is the last certificate always the server certificate? 292 * TODO: is the last certificate always the server certificate?
286 */ 293 */
287 cert = X509_STORE_CTX_get_current_cert(x509_ctx); 294 cert = X509_STORE_CTX_get_current_cert(x509_ctx);
295#if OPENSSL_VERSION_NUMBER >= 0x10100000L
288 X509_up_ref(cert); 296 X509_up_ref(cert);
297#endif
289 if (verbose>=2) { 298 if (verbose>=2) {
290 puts("* SSL verify callback with certificate:"); 299 puts("* SSL verify callback with certificate:");
291 X509_NAME *subject, *issuer; 300 X509_NAME *subject, *issuer;
@@ -363,12 +372,55 @@ handle_curl_option_return_code (CURLcode res, const char* option)
363} 372}
364 373
365int 374int
375lookup_host (const char *host, char *buf, size_t buflen)
376{
377 struct addrinfo hints, *res, *result;
378 int errcode;
379 void *ptr;
380
381 memset (&hints, 0, sizeof (hints));
382 hints.ai_family = address_family;
383 hints.ai_socktype = SOCK_STREAM;
384 hints.ai_flags |= AI_CANONNAME;
385
386 errcode = getaddrinfo (host, NULL, &hints, &result);
387 if (errcode != 0)
388 return errcode;
389
390 res = result;
391
392 while (res) {
393 inet_ntop (res->ai_family, res->ai_addr->sa_data, buf, buflen);
394 switch (res->ai_family) {
395 case AF_INET:
396 ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr;
397 break;
398 case AF_INET6:
399 ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
400 break;
401 }
402 inet_ntop (res->ai_family, ptr, buf, buflen);
403 if (verbose >= 1)
404 printf ("* getaddrinfo IPv%d address: %s\n",
405 res->ai_family == PF_INET6 ? 6 : 4, buf);
406 res = res->ai_next;
407 }
408
409 freeaddrinfo(result);
410
411 return 0;
412}
413
414int
366check_http (void) 415check_http (void)
367{ 416{
368 int result = STATE_OK; 417 int result = STATE_OK;
369 int page_len = 0; 418 int page_len = 0;
370 int i; 419 int i;
371 char *force_host_header = NULL; 420 char *force_host_header = NULL;
421 struct curl_slist *host = NULL;
422 char addrstr[100];
423 char dnscache[DEFAULT_BUFFER_SIZE];
372 424
373 /* initialize curl */ 425 /* initialize curl */
374 if (curl_global_init (CURL_GLOBAL_DEFAULT) != CURLE_OK) 426 if (curl_global_init (CURL_GLOBAL_DEFAULT) != CURLE_OK)
@@ -383,6 +435,13 @@ check_http (void)
383 /* print everything on stdout like check_http would do */ 435 /* print everything on stdout like check_http would do */
384 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_STDERR, stdout), "CURLOPT_STDERR"); 436 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_STDERR, stdout), "CURLOPT_STDERR");
385 437
438 if (automatic_decompression)
439#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6)
440 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""), "CURLOPT_ACCEPT_ENCODING");
441#else
442 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_ENCODING, ""), "CURLOPT_ENCODING");
443#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */
444
386 /* initialize buffer for body of the answer */ 445 /* initialize buffer for body of the answer */
387 if (curlhelp_initwritebuffer(&body_buf) < 0) 446 if (curlhelp_initwritebuffer(&body_buf) < 0)
388 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n"); 447 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n");
@@ -404,9 +463,12 @@ check_http (void)
404 463
405 // fill dns resolve cache to make curl connect to the given server_address instead of the host_name, only required for ssl, because we use the host_name later on to make SNI happy 464 // fill dns resolve cache to make curl connect to the given server_address instead of the host_name, only required for ssl, because we use the host_name later on to make SNI happy
406 if(use_ssl && host_name != NULL) { 465 if(use_ssl && host_name != NULL) {
407 struct curl_slist *host = NULL; 466 if ( (res=lookup_host (server_address, addrstr, 100)) != 0) {
408 char dnscache[DEFAULT_BUFFER_SIZE]; 467 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"),
409 snprintf (dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, server_address); 468 server_address, res, gai_strerror (res));
469 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
470 }
471 snprintf (dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, addrstr);
410 host = curl_slist_append(NULL, dnscache); 472 host = curl_slist_append(NULL, dnscache);
411 curl_easy_setopt(curl, CURLOPT_RESOLVE, host); 473 curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
412 if (verbose>=1) 474 if (verbose>=1)
@@ -971,8 +1033,8 @@ char*
971uri_string (const UriTextRangeA range, char* buf, size_t buflen) 1033uri_string (const UriTextRangeA range, char* buf, size_t buflen)
972{ 1034{
973 if (!range.first) return "(null)"; 1035 if (!range.first) return "(null)";
974 strncpy (buf, range.first, max (buflen, range.afterLast - range.first)); 1036 strncpy (buf, range.first, max (buflen-1, range.afterLast - range.first));
975 buf[max (buflen, range.afterLast - range.first)] = '\0'; 1037 buf[max (buflen-1, range.afterLast - range.first)] = '\0';
976 buf[range.afterLast - range.first] = '\0'; 1038 buf[range.afterLast - range.first] = '\0';
977 return buf; 1039 return buf;
978} 1040}
@@ -1092,8 +1154,8 @@ redir (curlhelp_write_curlbuf* header_buf)
1092 !strncmp(server_address, new_host, MAX_IPV4_HOSTLENGTH) && 1154 !strncmp(server_address, new_host, MAX_IPV4_HOSTLENGTH) &&
1093 (host_name && !strncmp(host_name, new_host, MAX_IPV4_HOSTLENGTH)) && 1155 (host_name && !strncmp(host_name, new_host, MAX_IPV4_HOSTLENGTH)) &&
1094 !strcmp(server_url, new_url)) 1156 !strcmp(server_url, new_url))
1095 die (STATE_WARNING, 1157 die (STATE_CRITICAL,
1096 _("HTTP WARNING - redirection creates an infinite loop - %s://%s:%d%s%s\n"), 1158 _("HTTP CRITICAL - redirection creates an infinite loop - %s://%s:%d%s%s\n"),
1097 use_ssl ? "https" : "http", new_host, new_port, new_url, (display_html ? "</A>" : "")); 1159 use_ssl ? "https" : "http", new_host, new_port, new_url, (display_html ? "</A>" : ""));
1098 1160
1099 /* set new values for redirected request */ 1161 /* set new values for redirected request */
@@ -1149,7 +1211,8 @@ process_arguments (int argc, char **argv)
1149 INVERT_REGEX = CHAR_MAX + 1, 1211 INVERT_REGEX = CHAR_MAX + 1,
1150 SNI_OPTION, 1212 SNI_OPTION,
1151 CA_CERT_OPTION, 1213 CA_CERT_OPTION,
1152 HTTP_VERSION_OPTION 1214 HTTP_VERSION_OPTION,
1215 AUTOMATIC_DECOMPRESSION
1153 }; 1216 };
1154 1217
1155 int option = 0; 1218 int option = 0;
@@ -1192,6 +1255,7 @@ process_arguments (int argc, char **argv)
1192 {"extended-perfdata", no_argument, 0, 'E'}, 1255 {"extended-perfdata", no_argument, 0, 'E'},
1193 {"show-body", no_argument, 0, 'B'}, 1256 {"show-body", no_argument, 0, 'B'},
1194 {"http-version", required_argument, 0, HTTP_VERSION_OPTION}, 1257 {"http-version", required_argument, 0, HTTP_VERSION_OPTION},
1258 {"enable-automatic-decompression", no_argument, 0, AUTOMATIC_DECOMPRESSION},
1195 {0, 0, 0, 0} 1259 {0, 0, 0, 0}
1196 }; 1260 };
1197 1261
@@ -1583,6 +1647,9 @@ process_arguments (int argc, char **argv)
1583 exit (STATE_WARNING); 1647 exit (STATE_WARNING);
1584 } 1648 }
1585 break; 1649 break;
1650 case AUTOMATIC_DECOMPRESSION:
1651 automatic_decompression = TRUE;
1652 break;
1586 case '?': 1653 case '?':
1587 /* print short usage statement if args not parsable */ 1654 /* print short usage statement if args not parsable */
1588 usage5 (); 1655 usage5 ();
@@ -1793,6 +1860,8 @@ print_help (void)
1793 printf (" %s\n", "--http-version=VERSION"); 1860 printf (" %s\n", "--http-version=VERSION");
1794 printf (" %s\n", _("Connect via specific HTTP protocol.")); 1861 printf (" %s\n", _("Connect via specific HTTP protocol."));
1795 printf (" %s\n", _("1.0 = HTTP/1.0, 1.1 = HTTP/1.1, 2.0 = HTTP/2 (HTTP/2 will fail without -S)")); 1862 printf (" %s\n", _("1.0 = HTTP/1.0, 1.1 = HTTP/1.1, 2.0 = HTTP/2 (HTTP/2 will fail without -S)"));
1863 printf (" %s\n", "--enable-automatic-decompression");
1864 printf (" %s\n", _("Enable automatic decompression of body (CURLOPT_ACCEPT_ENCODING)."));
1796 printf ("\n"); 1865 printf ("\n");
1797 1866
1798 printf (UT_WARN_CRIT); 1867 printf (UT_WARN_CRIT);