summaryrefslogtreecommitdiffstats
path: root/plugins/check_curl.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_curl.c')
-rw-r--r--plugins/check_curl.c184
1 files changed, 158 insertions, 26 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index 2d69b31..14cc846 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
@@ -117,7 +123,7 @@ typedef enum curlhelp_ssl_library {
117 123
118enum { 124enum {
119 REGS = 2, 125 REGS = 2,
120 MAX_RE_SIZE = 256 126 MAX_RE_SIZE = 1024
121}; 127};
122#include "regex.h" 128#include "regex.h"
123regex_t preg; 129regex_t preg;
@@ -145,6 +151,7 @@ thresholds *thlds;
145char user_agent[DEFAULT_BUFFER_SIZE]; 151char user_agent[DEFAULT_BUFFER_SIZE];
146int verbose = 0; 152int verbose = 0;
147int show_extended_perfdata = FALSE; 153int show_extended_perfdata = FALSE;
154int show_body = FALSE;
148int min_page_len = 0; 155int min_page_len = 0;
149int max_page_len = 0; 156int max_page_len = 0;
150int redir_depth = 0; 157int redir_depth = 0;
@@ -195,6 +202,7 @@ int ssl_version = CURL_SSLVERSION_DEFAULT;
195char *client_cert = NULL; 202char *client_cert = NULL;
196char *client_privkey = NULL; 203char *client_privkey = NULL;
197char *ca_cert = NULL; 204char *ca_cert = NULL;
205int verify_peer_and_host = FALSE;
198int is_openssl_callback = FALSE; 206int is_openssl_callback = FALSE;
199#if defined(HAVE_SSL) && defined(USE_OPENSSL) 207#if defined(HAVE_SSL) && defined(USE_OPENSSL)
200X509 *cert = NULL; 208X509 *cert = NULL;
@@ -204,6 +212,7 @@ int maximum_age = -1;
204int address_family = AF_UNSPEC; 212int address_family = AF_UNSPEC;
205curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN; 213curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN;
206int curl_http_version = CURL_HTTP_VERSION_NONE; 214int curl_http_version = CURL_HTTP_VERSION_NONE;
215int automatic_decompression = FALSE;
207 216
208int process_arguments (int, char**); 217int process_arguments (int, char**);
209void handle_curl_option_return_code (CURLcode res, const char* option); 218void handle_curl_option_return_code (CURLcode res, const char* option);
@@ -283,6 +292,20 @@ int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
283 * TODO: is the last certificate always the server certificate? 292 * TODO: is the last certificate always the server certificate?
284 */ 293 */
285 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
296 X509_up_ref(cert);
297#endif
298 if (verbose>=2) {
299 puts("* SSL verify callback with certificate:");
300 X509_NAME *subject, *issuer;
301 printf("* issuer:\n");
302 issuer = X509_get_issuer_name( cert );
303 X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE);
304 printf("* curl verify_callback:\n* subject:\n");
305 subject = X509_get_subject_name( cert );
306 X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE);
307 puts("");
308 }
286 return 1; 309 return 1;
287} 310}
288 311
@@ -296,6 +319,28 @@ CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm)
296#endif /* USE_OPENSSL */ 319#endif /* USE_OPENSSL */
297#endif /* HAVE_SSL */ 320#endif /* HAVE_SSL */
298 321
322/* returns a string "HTTP/1.x" or "HTTP/2" */
323static char *string_statuscode (int major, int minor)
324{
325 static char buf[10];
326
327 switch (major) {
328 case 1:
329 snprintf (buf, sizeof (buf), "HTTP/%d.%d", major, minor);
330 break;
331 case 2:
332 case 3:
333 snprintf (buf, sizeof (buf), "HTTP/%d", major);
334 break;
335 default:
336 /* assuming here HTTP/N with N>=4 */
337 snprintf (buf, sizeof (buf), "HTTP/%d", major);
338 break;
339 }
340
341 return buf;
342}
343
299/* Checks if the server 'reply' is one of the expected 'statuscodes' */ 344/* Checks if the server 'reply' is one of the expected 'statuscodes' */
300static int 345static int
301expected_statuscode (const char *reply, const char *statuscodes) 346expected_statuscode (const char *reply, const char *statuscodes)
@@ -327,12 +372,55 @@ handle_curl_option_return_code (CURLcode res, const char* option)
327} 372}
328 373
329int 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
330check_http (void) 415check_http (void)
331{ 416{
332 int result = STATE_OK; 417 int result = STATE_OK;
333 int page_len = 0; 418 int page_len = 0;
334 int i; 419 int i;
335 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];
336 424
337 /* initialize curl */ 425 /* initialize curl */
338 if (curl_global_init (CURL_GLOBAL_DEFAULT) != CURLE_OK) 426 if (curl_global_init (CURL_GLOBAL_DEFAULT) != CURLE_OK)
@@ -347,6 +435,13 @@ check_http (void)
347 /* print everything on stdout like check_http would do */ 435 /* print everything on stdout like check_http would do */
348 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");
349 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
350 /* initialize buffer for body of the answer */ 445 /* initialize buffer for body of the answer */
351 if (curlhelp_initwritebuffer(&body_buf) < 0) 446 if (curlhelp_initwritebuffer(&body_buf) < 0)
352 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");
@@ -368,9 +463,12 @@ check_http (void)
368 463
369 // 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
370 if(use_ssl && host_name != NULL) { 465 if(use_ssl && host_name != NULL) {
371 struct curl_slist *host = NULL; 466 if ( (res=lookup_host (server_address, addrstr, 100)) != 0) {
372 char dnscache[DEFAULT_BUFFER_SIZE]; 467 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"),
373 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);
374 host = curl_slist_append(NULL, dnscache); 472 host = curl_slist_append(NULL, dnscache);
375 curl_easy_setopt(curl, CURLOPT_RESOLVE, host); 473 curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
376 if (verbose>=1) 474 if (verbose>=1)
@@ -467,9 +565,11 @@ check_http (void)
467 if (client_privkey) 565 if (client_privkey)
468 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLKEY, client_privkey), "CURLOPT_SSLKEY"); 566 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLKEY, client_privkey), "CURLOPT_SSLKEY");
469 if (ca_cert) { 567 if (ca_cert) {
568 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CAINFO, ca_cert), "CURLOPT_CAINFO");
569 }
570 if (ca_cert || verify_peer_and_host) {
470 /* per default if we have a CA verify both the peer and the 571 /* per default if we have a CA verify both the peer and the
471 * hostname in the certificate, can be switched off later */ 572 * hostname in the certificate, can be switched off later */
472 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CAINFO, ca_cert), "CURLOPT_CAINFO");
473 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 1), "CURLOPT_SSL_VERIFYPEER"); 573 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 1), "CURLOPT_SSL_VERIFYPEER");
474 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYHOST, 2), "CURLOPT_SSL_VERIFYHOST"); 574 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYHOST, 2), "CURLOPT_SSL_VERIFYHOST");
475 } else { 575 } else {
@@ -640,7 +740,7 @@ check_http (void)
640 /* Curl errors, result in critical Nagios state */ 740 /* Curl errors, result in critical Nagios state */
641 if (res != CURLE_OK) { 741 if (res != CURLE_OK) {
642 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"), 742 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"),
643 server_port, res, curl_easy_strerror(res)); 743 server_port, res, errbuf[0] ? errbuf : curl_easy_strerror(res));
644 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 744 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
645 } 745 }
646 746
@@ -746,7 +846,8 @@ GOT_FIRST_CERT:
746 if (curlhelp_parse_statusline (header_buf.buf, &status_line) < 0) { 846 if (curlhelp_parse_statusline (header_buf.buf, &status_line) < 0) {
747 snprintf (msg, DEFAULT_BUFFER_SIZE, "Unparsable status line in %.3g seconds response time|%s\n", 847 snprintf (msg, DEFAULT_BUFFER_SIZE, "Unparsable status line in %.3g seconds response time|%s\n",
748 total_time, perfstring); 848 total_time, perfstring);
749 die (STATE_CRITICAL, "HTTP CRITICAL HTTP/1.x %ld unknown - %s", code, msg); 849 /* we cannot know the major/minor version here for sure as we cannot parse the first line */
850 die (STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", code, msg);
750 } 851 }
751 852
752 /* get result code from cURL */ 853 /* get result code from cURL */
@@ -766,7 +867,9 @@ GOT_FIRST_CERT:
766 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"), status_line.first_line); 867 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"), status_line.first_line);
767 else 868 else
768 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: %s\n"), server_port, status_line.first_line); 869 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: %s\n"), server_port, status_line.first_line);
769 die (STATE_CRITICAL, "HTTP CRITICAL - %s", msg); 870 die (STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg,
871 show_body ? "\n" : "",
872 show_body ? body_buf.buf : "");
770 } 873 }
771 874
772 if( server_expect_yn ) { 875 if( server_expect_yn ) {
@@ -823,8 +926,8 @@ GOT_FIRST_CERT:
823 926
824 /* check status codes, set exit status accordingly */ 927 /* check status codes, set exit status accordingly */
825 if( status_line.http_code != code ) { 928 if( status_line.http_code != code ) {
826 die (STATE_CRITICAL, _("HTTP CRITICAL HTTP/%d.%d %d %s - different HTTP codes (cUrl has %ld)\n"), 929 die (STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"),
827 status_line.http_major, status_line.http_minor, 930 string_statuscode (status_line.http_major, status_line.http_minor),
828 status_line.http_code, status_line.msg, code); 931 status_line.http_code, status_line.msg, code);
829 } 932 }
830 933
@@ -895,13 +998,15 @@ GOT_FIRST_CERT:
895 msg[strlen(msg)-3] = '\0'; 998 msg[strlen(msg)-3] = '\0';
896 999
897 /* TODO: separate _() msg and status code: die (result, "HTTP %s: %s\n", state_text(result), msg); */ 1000 /* TODO: separate _() msg and status code: die (result, "HTTP %s: %s\n", state_text(result), msg); */
898 die (result, "HTTP %s: HTTP/%d.%d %d %s%s%s - %d bytes in %.3f second response time %s|%s\n", 1001 die (result, "HTTP %s: %s %d %s%s%s - %d bytes in %.3f second response time %s|%s\n%s%s",
899 state_text(result), status_line.http_major, status_line.http_minor, 1002 state_text(result), string_statuscode (status_line.http_major, status_line.http_minor),
900 status_line.http_code, status_line.msg, 1003 status_line.http_code, status_line.msg,
901 strlen(msg) > 0 ? " - " : "", 1004 strlen(msg) > 0 ? " - " : "",
902 msg, page_len, total_time, 1005 msg, page_len, total_time,
903 (display_html ? "</A>" : ""), 1006 (display_html ? "</A>" : ""),
904 perfstring); 1007 perfstring,
1008 (show_body ? body_buf.buf : ""),
1009 (show_body ? "\n" : "") );
905 1010
906 /* proper cleanup after die? */ 1011 /* proper cleanup after die? */
907 curlhelp_free_statusline(&status_line); 1012 curlhelp_free_statusline(&status_line);
@@ -928,8 +1033,8 @@ char*
928uri_string (const UriTextRangeA range, char* buf, size_t buflen) 1033uri_string (const UriTextRangeA range, char* buf, size_t buflen)
929{ 1034{
930 if (!range.first) return "(null)"; 1035 if (!range.first) return "(null)";
931 strncpy (buf, range.first, max (buflen, range.afterLast - range.first)); 1036 strncpy (buf, range.first, max (buflen-1, range.afterLast - range.first));
932 buf[max (buflen, range.afterLast - range.first)] = '\0'; 1037 buf[max (buflen-1, range.afterLast - range.first)] = '\0';
933 buf[range.afterLast - range.first] = '\0'; 1038 buf[range.afterLast - range.first] = '\0';
934 return buf; 1039 return buf;
935} 1040}
@@ -1041,7 +1146,7 @@ redir (curlhelp_write_curlbuf* header_buf)
1041 const UriPathSegmentA* p = uri.pathHead; 1146 const UriPathSegmentA* p = uri.pathHead;
1042 for (; p; p = p->next) { 1147 for (; p; p = p->next) {
1043 strncat (new_url, "/", DEFAULT_BUFFER_SIZE); 1148 strncat (new_url, "/", DEFAULT_BUFFER_SIZE);
1044 strncat (new_url, uri_string (p->text, buf, DEFAULT_BUFFER_SIZE), DEFAULT_BUFFER_SIZE); 1149 strncat (new_url, uri_string (p->text, buf, DEFAULT_BUFFER_SIZE), DEFAULT_BUFFER_SIZE-1);
1045 } 1150 }
1046 } 1151 }
1047 1152
@@ -1049,8 +1154,8 @@ redir (curlhelp_write_curlbuf* header_buf)
1049 !strncmp(server_address, new_host, MAX_IPV4_HOSTLENGTH) && 1154 !strncmp(server_address, new_host, MAX_IPV4_HOSTLENGTH) &&
1050 (host_name && !strncmp(host_name, new_host, MAX_IPV4_HOSTLENGTH)) && 1155 (host_name && !strncmp(host_name, new_host, MAX_IPV4_HOSTLENGTH)) &&
1051 !strcmp(server_url, new_url)) 1156 !strcmp(server_url, new_url))
1052 die (STATE_WARNING, 1157 die (STATE_CRITICAL,
1053 _("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"),
1054 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>" : ""));
1055 1160
1056 /* set new values for redirected request */ 1161 /* set new values for redirected request */
@@ -1106,7 +1211,8 @@ process_arguments (int argc, char **argv)
1106 INVERT_REGEX = CHAR_MAX + 1, 1211 INVERT_REGEX = CHAR_MAX + 1,
1107 SNI_OPTION, 1212 SNI_OPTION,
1108 CA_CERT_OPTION, 1213 CA_CERT_OPTION,
1109 HTTP_VERSION_OPTION 1214 HTTP_VERSION_OPTION,
1215 AUTOMATIC_DECOMPRESSION
1110 }; 1216 };
1111 1217
1112 int option = 0; 1218 int option = 0;
@@ -1136,6 +1242,7 @@ process_arguments (int argc, char **argv)
1136 {"client-cert", required_argument, 0, 'J'}, 1242 {"client-cert", required_argument, 0, 'J'},
1137 {"private-key", required_argument, 0, 'K'}, 1243 {"private-key", required_argument, 0, 'K'},
1138 {"ca-cert", required_argument, 0, CA_CERT_OPTION}, 1244 {"ca-cert", required_argument, 0, CA_CERT_OPTION},
1245 {"verify-cert", no_argument, 0, 'D'},
1139 {"useragent", required_argument, 0, 'A'}, 1246 {"useragent", required_argument, 0, 'A'},
1140 {"header", required_argument, 0, 'k'}, 1247 {"header", required_argument, 0, 'k'},
1141 {"no-body", no_argument, 0, 'N'}, 1248 {"no-body", no_argument, 0, 'N'},
@@ -1146,7 +1253,9 @@ process_arguments (int argc, char **argv)
1146 {"use-ipv4", no_argument, 0, '4'}, 1253 {"use-ipv4", no_argument, 0, '4'},
1147 {"use-ipv6", no_argument, 0, '6'}, 1254 {"use-ipv6", no_argument, 0, '6'},
1148 {"extended-perfdata", no_argument, 0, 'E'}, 1255 {"extended-perfdata", no_argument, 0, 'E'},
1256 {"show-body", no_argument, 0, 'B'},
1149 {"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},
1150 {0, 0, 0, 0} 1259 {0, 0, 0, 0}
1151 }; 1260 };
1152 1261
@@ -1170,7 +1279,7 @@ process_arguments (int argc, char **argv)
1170 server_url = strdup(DEFAULT_SERVER_URL); 1279 server_url = strdup(DEFAULT_SERVER_URL);
1171 1280
1172 while (1) { 1281 while (1) {
1173 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); 1282 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);
1174 if (c == -1 || c == EOF || c == 1) 1283 if (c == -1 || c == EOF || c == 1)
1175 break; 1284 break;
1176 1285
@@ -1310,6 +1419,11 @@ process_arguments (int argc, char **argv)
1310 ca_cert = optarg; 1419 ca_cert = optarg;
1311 goto enable_ssl; 1420 goto enable_ssl;
1312#endif 1421#endif
1422#ifdef LIBCURL_FEATURE_SSL
1423 case 'D': /* verify peer certificate & host */
1424 verify_peer_and_host = TRUE;
1425 break;
1426#endif
1313 case 'S': /* use SSL */ 1427 case 'S': /* use SSL */
1314#ifdef LIBCURL_FEATURE_SSL 1428#ifdef LIBCURL_FEATURE_SSL
1315 enable_ssl: 1429 enable_ssl:
@@ -1354,7 +1468,7 @@ process_arguments (int argc, char **argv)
1354 ssl_version = CURL_SSLVERSION_DEFAULT; 1468 ssl_version = CURL_SSLVERSION_DEFAULT;
1355#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */ 1469#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */
1356 else 1470 else
1357 usage4 (_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2 (with optional '+' suffix)")); 1471 usage4 (_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2, 1.3 (with optional '+' suffix)"));
1358 } 1472 }
1359#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) 1473#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0)
1360 if (got_plus) { 1474 if (got_plus) {
@@ -1513,6 +1627,9 @@ process_arguments (int argc, char **argv)
1513 case 'E': /* show extended perfdata */ 1627 case 'E': /* show extended perfdata */
1514 show_extended_perfdata = TRUE; 1628 show_extended_perfdata = TRUE;
1515 break; 1629 break;
1630 case 'B': /* print body content after status line */
1631 show_body = TRUE;
1632 break;
1516 case HTTP_VERSION_OPTION: 1633 case HTTP_VERSION_OPTION:
1517 curl_http_version = CURL_HTTP_VERSION_NONE; 1634 curl_http_version = CURL_HTTP_VERSION_NONE;
1518 if (strcmp (optarg, "1.0") == 0) { 1635 if (strcmp (optarg, "1.0") == 0) {
@@ -1530,6 +1647,9 @@ process_arguments (int argc, char **argv)
1530 exit (STATE_WARNING); 1647 exit (STATE_WARNING);
1531 } 1648 }
1532 break; 1649 break;
1650 case AUTOMATIC_DECOMPRESSION:
1651 automatic_decompression = TRUE;
1652 break;
1533 case '?': 1653 case '?':
1534 /* print short usage statement if args not parsable */ 1654 /* print short usage statement if args not parsable */
1535 usage5 (); 1655 usage5 ();
@@ -1659,7 +1779,7 @@ print_help (void)
1659 printf (" %s\n", "-S, --ssl=VERSION[+]"); 1779 printf (" %s\n", "-S, --ssl=VERSION[+]");
1660 printf (" %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents")); 1780 printf (" %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents"));
1661 printf (" %s\n", _("auto-negotiation (2 = SSLv2, 3 = SSLv3, 1 = TLSv1, 1.1 = TLSv1.1,")); 1781 printf (" %s\n", _("auto-negotiation (2 = SSLv2, 3 = SSLv3, 1 = TLSv1, 1.1 = TLSv1.1,"));
1662 printf (" %s\n", _("1.2 = TLSv1.2). With a '+' suffix, newer versions are also accepted.")); 1782 printf (" %s\n", _("1.2 = TLSv1.2, 1.3 = TLSv1.3). With a '+' suffix, newer versions are also accepted."));
1663 printf (" %s\n", _("Note: SSLv2 and SSLv3 are deprecated and are usually disabled in libcurl")); 1783 printf (" %s\n", _("Note: SSLv2 and SSLv3 are deprecated and are usually disabled in libcurl"));
1664 printf (" %s\n", "--sni"); 1784 printf (" %s\n", "--sni");
1665 printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)")); 1785 printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)"));
@@ -1680,6 +1800,8 @@ print_help (void)
1680 printf (" %s\n", _("matching the client certificate")); 1800 printf (" %s\n", _("matching the client certificate"));
1681 printf (" %s\n", "--ca-cert=FILE"); 1801 printf (" %s\n", "--ca-cert=FILE");
1682 printf (" %s\n", _("CA certificate file to verify peer against")); 1802 printf (" %s\n", _("CA certificate file to verify peer against"));
1803 printf (" %s\n", "-D, --verify-cert");
1804 printf (" %s\n", _("Verify the peer's SSL certificate and hostname"));
1683#endif 1805#endif
1684 1806
1685 printf (" %s\n", "-e, --expect=STRING"); 1807 printf (" %s\n", "-e, --expect=STRING");
@@ -1723,6 +1845,8 @@ print_help (void)
1723 printf (" %s\n", _("Any other tags to be sent in http header. Use multiple times for additional headers")); 1845 printf (" %s\n", _("Any other tags to be sent in http header. Use multiple times for additional headers"));
1724 printf (" %s\n", "-E, --extended-perfdata"); 1846 printf (" %s\n", "-E, --extended-perfdata");
1725 printf (" %s\n", _("Print additional performance data")); 1847 printf (" %s\n", _("Print additional performance data"));
1848 printf (" %s\n", "-B, --show-body");
1849 printf (" %s\n", _("Print body content below status line"));
1726 printf (" %s\n", "-L, --link"); 1850 printf (" %s\n", "-L, --link");
1727 printf (" %s\n", _("Wrap output in HTML link (obsoleted by urlize)")); 1851 printf (" %s\n", _("Wrap output in HTML link (obsoleted by urlize)"));
1728 printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport|curl>"); 1852 printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport|curl>");
@@ -1736,6 +1860,8 @@ print_help (void)
1736 printf (" %s\n", "--http-version=VERSION"); 1860 printf (" %s\n", "--http-version=VERSION");
1737 printf (" %s\n", _("Connect via specific HTTP protocol.")); 1861 printf (" %s\n", _("Connect via specific HTTP protocol."));
1738 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)."));
1739 printf ("\n"); 1865 printf ("\n");
1740 1866
1741 printf (UT_WARN_CRIT); 1867 printf (UT_WARN_CRIT);
@@ -1813,15 +1939,21 @@ print_usage (void)
1813{ 1939{
1814 printf ("%s\n", _("Usage:")); 1940 printf ("%s\n", _("Usage:"));
1815 printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname); 1941 printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname);
1816 printf (" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate file>]\n"); 1942 printf (" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate file>] [-D]\n");
1817 printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-a auth]\n"); 1943 printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-a auth]\n");
1818 printf (" [-b proxy_auth] [-f <ok|warning|critcal|follow|sticky|stickyport|curl>]\n"); 1944 printf (" [-b proxy_auth] [-f <ok|warning|critcal|follow|sticky|stickyport|curl>]\n");
1819 printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n"); 1945 printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n");
1820 printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n"); 1946 printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n");
1821 printf (" [-A string] [-k string] [-S <version>] [--sni] [-C <warn_age>[,<crit_age>]]\n"); 1947 printf (" [-A string] [-k string] [-S <version>] [--sni]\n");
1822 printf (" [-T <content-type>] [-j method]\n"); 1948 printf (" [-T <content-type>] [-j method]\n");
1823 printf (" [--http-version=<version>]\n"); 1949 printf (" [--http-version=<version>]\n");
1950 printf (" %s -H <vhost> | -I <IP-address> -C <warn_age>[,<crit_age>]\n",progname);
1951 printf (" [-p <port>] [-t <timeout>] [-4|-6] [--sni]\n");
1824 printf ("\n"); 1952 printf ("\n");
1953#ifdef LIBCURL_FEATURE_SSL
1954 printf ("%s\n", _("In the first form, make an HTTP request."));
1955 printf ("%s\n\n", _("In the second form, connect to the server and check the TLS certificate."));
1956#endif
1825 printf ("%s\n", _("WARNING: check_curl is experimental. Please use")); 1957 printf ("%s\n", _("WARNING: check_curl is experimental. Please use"));
1826 printf ("%s\n\n", _("check_http if you need a stable version.")); 1958 printf ("%s\n\n", _("check_http if you need a stable version."));
1827} 1959}
@@ -1944,7 +2076,7 @@ curlhelp_parse_statusline (const char *buf, curlhelp_statusline *status_line)
1944 char *first_line_buf; 2076 char *first_line_buf;
1945 2077
1946 /* find last start of a new header */ 2078 /* find last start of a new header */
1947 start = strrstr2 (buf, "\r\nHTTP"); 2079 start = strrstr2 (buf, "\r\nHTTP/");
1948 if (start != NULL) { 2080 if (start != NULL) {
1949 start += 2; 2081 start += 2;
1950 buf = start; 2082 buf = start;
@@ -2037,7 +2169,7 @@ get_header_value (const struct phr_header* headers, const size_t nof_headers, co
2037{ 2169{
2038 int i; 2170 int i;
2039 for( i = 0; i < nof_headers; i++ ) { 2171 for( i = 0; i < nof_headers; i++ ) {
2040 if( strncasecmp( header, headers[i].name, max( headers[i].name_len, 4 ) ) == 0 ) { 2172 if(headers[i].name != NULL && strncasecmp( header, headers[i].name, max( headers[i].name_len, 4 ) ) == 0 ) {
2041 return strndup( headers[i].value, headers[i].value_len ); 2173 return strndup( headers[i].value, headers[i].value_len );
2042 } 2174 }
2043 } 2175 }