diff options
Diffstat (limited to 'plugins/check_curl.c')
| -rw-r--r-- | plugins/check_curl.c | 184 |
1 files changed, 158 insertions, 26 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c index 2d69b310..14cc8463 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 | ||
| 118 | enum { | 124 | enum { |
| 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" |
| 123 | regex_t preg; | 129 | regex_t preg; |
| @@ -145,6 +151,7 @@ thresholds *thlds; | |||
| 145 | char user_agent[DEFAULT_BUFFER_SIZE]; | 151 | char user_agent[DEFAULT_BUFFER_SIZE]; |
| 146 | int verbose = 0; | 152 | int verbose = 0; |
| 147 | int show_extended_perfdata = FALSE; | 153 | int show_extended_perfdata = FALSE; |
| 154 | int show_body = FALSE; | ||
| 148 | int min_page_len = 0; | 155 | int min_page_len = 0; |
| 149 | int max_page_len = 0; | 156 | int max_page_len = 0; |
| 150 | int redir_depth = 0; | 157 | int redir_depth = 0; |
| @@ -195,6 +202,7 @@ int ssl_version = CURL_SSLVERSION_DEFAULT; | |||
| 195 | char *client_cert = NULL; | 202 | char *client_cert = NULL; |
| 196 | char *client_privkey = NULL; | 203 | char *client_privkey = NULL; |
| 197 | char *ca_cert = NULL; | 204 | char *ca_cert = NULL; |
| 205 | int verify_peer_and_host = FALSE; | ||
| 198 | int is_openssl_callback = FALSE; | 206 | int is_openssl_callback = FALSE; |
| 199 | #if defined(HAVE_SSL) && defined(USE_OPENSSL) | 207 | #if defined(HAVE_SSL) && defined(USE_OPENSSL) |
| 200 | X509 *cert = NULL; | 208 | X509 *cert = NULL; |
| @@ -204,6 +212,7 @@ int maximum_age = -1; | |||
| 204 | int address_family = AF_UNSPEC; | 212 | int address_family = AF_UNSPEC; |
| 205 | curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN; | 213 | curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN; |
| 206 | int curl_http_version = CURL_HTTP_VERSION_NONE; | 214 | int curl_http_version = CURL_HTTP_VERSION_NONE; |
| 215 | int automatic_decompression = FALSE; | ||
| 207 | 216 | ||
| 208 | int process_arguments (int, char**); | 217 | int process_arguments (int, char**); |
| 209 | void handle_curl_option_return_code (CURLcode res, const char* option); | 218 | void 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" */ | ||
| 323 | static 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' */ |
| 300 | static int | 345 | static int |
| 301 | expected_statuscode (const char *reply, const char *statuscodes) | 346 | expected_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 | ||
| 329 | int | 374 | int |
| 375 | lookup_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 | |||
| 414 | int | ||
| 330 | check_http (void) | 415 | check_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* | |||
| 928 | uri_string (const UriTextRangeA range, char* buf, size_t buflen) | 1033 | uri_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 | } |
