diff options
Diffstat (limited to 'plugins/check_curl.c')
| -rw-r--r-- | plugins/check_curl.c | 81 |
1 files changed, 57 insertions, 24 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c index fc704171..1dec8a2a 100644 --- a/plugins/check_curl.c +++ b/plugins/check_curl.c | |||
| @@ -69,10 +69,6 @@ const char *email = "devel@monitoring-plugins.org"; | |||
| 69 | #include <netdb.h> | 69 | #include <netdb.h> |
| 70 | 70 | ||
| 71 | enum { | 71 | enum { |
| 72 | MAX_IPV4_HOSTLENGTH = 255, | ||
| 73 | }; | ||
| 74 | |||
| 75 | enum { | ||
| 76 | REGS = 2, | 72 | REGS = 2, |
| 77 | }; | 73 | }; |
| 78 | 74 | ||
| @@ -96,16 +92,16 @@ typedef struct { | |||
| 96 | static check_curl_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); | 92 | static check_curl_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); |
| 97 | 93 | ||
| 98 | static mp_subcheck check_http(check_curl_config /*config*/, check_curl_working_state workingState, | 94 | static mp_subcheck check_http(check_curl_config /*config*/, check_curl_working_state workingState, |
| 99 | int redir_depth); | 95 | long redir_depth); |
| 100 | 96 | ||
| 101 | typedef struct { | 97 | typedef struct { |
| 102 | int redir_depth; | 98 | long redir_depth; |
| 103 | check_curl_working_state working_state; | 99 | check_curl_working_state working_state; |
| 104 | int error_code; | 100 | int error_code; |
| 105 | check_curl_global_state curl_state; | 101 | check_curl_global_state curl_state; |
| 106 | } redir_wrapper; | 102 | } redir_wrapper; |
| 107 | static redir_wrapper redir(curlhelp_write_curlbuf * /*header_buf*/, check_curl_config /*config*/, | 103 | static redir_wrapper redir(curlhelp_write_curlbuf * /*header_buf*/, check_curl_config /*config*/, |
| 108 | int redir_depth, check_curl_working_state working_state); | 104 | long redir_depth, check_curl_working_state working_state); |
| 109 | 105 | ||
| 110 | static void print_help(void); | 106 | static void print_help(void); |
| 111 | void print_usage(void); | 107 | void print_usage(void); |
| @@ -202,7 +198,7 @@ CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) { | |||
| 202 | #endif /* HAVE_SSL */ | 198 | #endif /* HAVE_SSL */ |
| 203 | 199 | ||
| 204 | mp_subcheck check_http(const check_curl_config config, check_curl_working_state workingState, | 200 | mp_subcheck check_http(const check_curl_config config, check_curl_working_state workingState, |
| 205 | int redir_depth) { | 201 | long redir_depth) { |
| 206 | 202 | ||
| 207 | // ======================= | 203 | // ======================= |
| 208 | // Initialisation for curl | 204 | // Initialisation for curl |
| @@ -445,19 +441,19 @@ mp_subcheck check_http(const check_curl_config config, check_curl_working_state | |||
| 445 | "CURLINFO_REDIRECT_COUNT"); | 441 | "CURLINFO_REDIRECT_COUNT"); |
| 446 | 442 | ||
| 447 | if (verbose >= 2) { | 443 | if (verbose >= 2) { |
| 448 | printf(_("* curl LIBINFO_REDIRECT_COUNT is %d\n"), redir_depth); | 444 | printf(_("* curl LIBINFO_REDIRECT_COUNT is %ld\n"), redir_depth); |
| 449 | } | 445 | } |
| 450 | 446 | ||
| 451 | mp_subcheck sc_redir_depth = mp_subcheck_init(); | 447 | mp_subcheck sc_redir_depth = mp_subcheck_init(); |
| 452 | if (redir_depth > config.max_depth) { | 448 | if (redir_depth > config.max_depth) { |
| 453 | xasprintf(&sc_redir_depth.output, | 449 | xasprintf(&sc_redir_depth.output, |
| 454 | "maximum redirection depth %d exceeded in libcurl", | 450 | "maximum redirection depth %ld exceeded in libcurl", |
| 455 | config.max_depth); | 451 | config.max_depth); |
| 456 | sc_redir_depth = mp_set_subcheck_state(sc_redir_depth, STATE_CRITICAL); | 452 | sc_redir_depth = mp_set_subcheck_state(sc_redir_depth, STATE_CRITICAL); |
| 457 | mp_add_subcheck_to_subcheck(&sc_result, sc_redir_depth); | 453 | mp_add_subcheck_to_subcheck(&sc_result, sc_redir_depth); |
| 458 | return sc_result; | 454 | return sc_result; |
| 459 | } | 455 | } |
| 460 | xasprintf(&sc_redir_depth.output, "redirection depth %d (of a maximum %d)", | 456 | xasprintf(&sc_redir_depth.output, "redirection depth %ld (of a maximum %ld)", |
| 461 | redir_depth, config.max_depth); | 457 | redir_depth, config.max_depth); |
| 462 | mp_add_subcheck_to_subcheck(&sc_result, sc_redir_depth); | 458 | mp_add_subcheck_to_subcheck(&sc_result, sc_redir_depth); |
| 463 | 459 | ||
| @@ -657,7 +653,7 @@ char *uri_string(const UriTextRangeA range, char *buf, size_t buflen) { | |||
| 657 | } | 653 | } |
| 658 | 654 | ||
| 659 | redir_wrapper redir(curlhelp_write_curlbuf *header_buf, const check_curl_config config, | 655 | redir_wrapper redir(curlhelp_write_curlbuf *header_buf, const check_curl_config config, |
| 660 | int redir_depth, check_curl_working_state working_state) { | 656 | long redir_depth, check_curl_working_state working_state) { |
| 661 | curlhelp_statusline status_line; | 657 | curlhelp_statusline status_line; |
| 662 | struct phr_header headers[255]; | 658 | struct phr_header headers[255]; |
| 663 | size_t msglen; | 659 | size_t msglen; |
| @@ -672,12 +668,17 @@ redir_wrapper redir(curlhelp_write_curlbuf *header_buf, const check_curl_config | |||
| 672 | 668 | ||
| 673 | char *location = get_header_value(headers, nof_headers, "location"); | 669 | char *location = get_header_value(headers, nof_headers, "location"); |
| 674 | 670 | ||
| 671 | if (location == NULL) { | ||
| 672 | // location header not found | ||
| 673 | die(STATE_UNKNOWN, "HTTP UNKNOWN - could not find \"location\" header\n"); | ||
| 674 | } | ||
| 675 | |||
| 675 | if (verbose >= 2) { | 676 | if (verbose >= 2) { |
| 676 | printf(_("* Seen redirect location %s\n"), location); | 677 | printf(_("* Seen redirect location %s\n"), location); |
| 677 | } | 678 | } |
| 678 | 679 | ||
| 679 | if (++redir_depth > config.max_depth) { | 680 | if (++redir_depth > config.max_depth) { |
| 680 | die(STATE_WARNING, _("HTTP WARNING - maximum redirection depth %d exceeded - %s\n"), | 681 | die(STATE_WARNING, _("HTTP WARNING - maximum redirection depth %ld exceeded - %s\n"), |
| 681 | config.max_depth, location); | 682 | config.max_depth, location); |
| 682 | } | 683 | } |
| 683 | 684 | ||
| @@ -760,7 +761,7 @@ redir_wrapper redir(curlhelp_write_curlbuf *header_buf, const check_curl_config | |||
| 760 | } | 761 | } |
| 761 | 762 | ||
| 762 | /* compose new path */ | 763 | /* compose new path */ |
| 763 | /* TODO: handle fragments and query part of URL */ | 764 | /* TODO: handle fragments of URL */ |
| 764 | char *new_url = (char *)calloc(1, DEFAULT_BUFFER_SIZE); | 765 | char *new_url = (char *)calloc(1, DEFAULT_BUFFER_SIZE); |
| 765 | if (uri.pathHead) { | 766 | if (uri.pathHead) { |
| 766 | for (UriPathSegmentA *pathSegment = uri.pathHead; pathSegment; | 767 | for (UriPathSegmentA *pathSegment = uri.pathHead; pathSegment; |
| @@ -771,6 +772,29 @@ redir_wrapper redir(curlhelp_write_curlbuf *header_buf, const check_curl_config | |||
| 771 | } | 772 | } |
| 772 | } | 773 | } |
| 773 | 774 | ||
| 775 | /* missing components have null,null in their UriTextRangeA | ||
| 776 | * add query parameters if they exist. | ||
| 777 | */ | ||
| 778 | if (uri.query.first && uri.query.afterLast) { | ||
| 779 | // Ensure we have space for '?' + query_str + '\0' ahead of time, instead of calling strncat | ||
| 780 | // twice | ||
| 781 | size_t current_len = strlen(new_url); | ||
| 782 | size_t remaining_space = DEFAULT_BUFFER_SIZE - current_len - 1; | ||
| 783 | |||
| 784 | const char *query_str = uri_string(uri.query, buf, DEFAULT_BUFFER_SIZE); | ||
| 785 | size_t query_str_len = strlen(query_str); | ||
| 786 | |||
| 787 | if (remaining_space >= query_str_len + 1) { | ||
| 788 | strcat(new_url, "?"); | ||
| 789 | strcat(new_url, query_str); | ||
| 790 | } else { | ||
| 791 | die(STATE_UNKNOWN, | ||
| 792 | _("HTTP UNKNOWN - No space to add query part of size %zu to the buffer, buffer has " | ||
| 793 | "remaining size %zu"), | ||
| 794 | query_str_len, current_len); | ||
| 795 | } | ||
| 796 | } | ||
| 797 | |||
| 774 | if (working_state.serverPort == new_port && | 798 | if (working_state.serverPort == new_port && |
| 775 | !strncmp(working_state.server_address, new_host, MAX_IPV4_HOSTLENGTH) && | 799 | !strncmp(working_state.server_address, new_host, MAX_IPV4_HOSTLENGTH) && |
| 776 | (working_state.host_name && | 800 | (working_state.host_name && |
| @@ -784,21 +808,21 @@ redir_wrapper redir(curlhelp_write_curlbuf *header_buf, const check_curl_config | |||
| 784 | /* set new values for redirected request */ | 808 | /* set new values for redirected request */ |
| 785 | 809 | ||
| 786 | if (!(config.followsticky & STICKY_HOST)) { | 810 | if (!(config.followsticky & STICKY_HOST)) { |
| 787 | free(working_state.server_address); | 811 | // free(working_state.server_address); |
| 788 | working_state.server_address = strndup(new_host, MAX_IPV4_HOSTLENGTH); | 812 | working_state.server_address = strndup(new_host, MAX_IPV4_HOSTLENGTH); |
| 789 | } | 813 | } |
| 790 | if (!(config.followsticky & STICKY_PORT)) { | 814 | if (!(config.followsticky & STICKY_PORT)) { |
| 791 | working_state.serverPort = (unsigned short)new_port; | 815 | working_state.serverPort = (unsigned short)new_port; |
| 792 | } | 816 | } |
| 793 | 817 | ||
| 794 | free(working_state.host_name); | 818 | // free(working_state.host_name); |
| 795 | working_state.host_name = strndup(new_host, MAX_IPV4_HOSTLENGTH); | 819 | working_state.host_name = strndup(new_host, MAX_IPV4_HOSTLENGTH); |
| 796 | 820 | ||
| 797 | /* reset virtual port */ | 821 | /* reset virtual port */ |
| 798 | working_state.virtualPort = working_state.serverPort; | 822 | working_state.virtualPort = working_state.serverPort; |
| 799 | 823 | ||
| 800 | free(new_host); | 824 | free(new_host); |
| 801 | free(working_state.server_url); | 825 | // free(working_state.server_url); |
| 802 | working_state.server_url = new_url; | 826 | working_state.server_url = new_url; |
| 803 | 827 | ||
| 804 | uriFreeUriMembersA(&uri); | 828 | uriFreeUriMembersA(&uri); |
| @@ -1399,7 +1423,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) { | |||
| 1399 | } | 1423 | } |
| 1400 | #endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) */ | 1424 | #endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) */ |
| 1401 | if (verbose >= 2) { | 1425 | if (verbose >= 2) { |
| 1402 | printf(_("* Set SSL/TLS version to %d\n"), result.config.curl_config.ssl_version); | 1426 | printf(_("* Set SSL/TLS version to %ld\n"), result.config.curl_config.ssl_version); |
| 1403 | } | 1427 | } |
| 1404 | if (!specify_port) { | 1428 | if (!specify_port) { |
| 1405 | result.config.initial_config.serverPort = HTTPS_PORT; | 1429 | result.config.initial_config.serverPort = HTTPS_PORT; |
| @@ -1480,7 +1504,9 @@ void print_help(void) { | |||
| 1480 | printf(" %s\n", _("Append a port to include it in the header (eg: example.com:5000)")); | 1504 | printf(" %s\n", _("Append a port to include it in the header (eg: example.com:5000)")); |
| 1481 | printf(" %s\n", "-I, --IP-address=ADDRESS"); | 1505 | printf(" %s\n", "-I, --IP-address=ADDRESS"); |
| 1482 | printf(" %s\n", | 1506 | printf(" %s\n", |
| 1483 | _("IP address or name (use numeric address if possible to bypass DNS lookup).")); | 1507 | "IP address or name (use numeric address if possible to bypass DNS lookup)."); |
| 1508 | printf(" %s\n", "This overwrites the network address of the target while leaving everything " | ||
| 1509 | "else (HTTP headers) as they are"); | ||
| 1484 | printf(" %s\n", "-p, --port=INTEGER"); | 1510 | printf(" %s\n", "-p, --port=INTEGER"); |
| 1485 | printf(" %s", _("Port number (default: ")); | 1511 | printf(" %s", _("Port number (default: ")); |
| 1486 | printf("%d)\n", HTTP_PORT); | 1512 | printf("%d)\n", HTTP_PORT); |
| @@ -1544,6 +1570,8 @@ void print_help(void) { | |||
| 1544 | printf(" %s\n", _("String to expect in the content")); | 1570 | printf(" %s\n", _("String to expect in the content")); |
| 1545 | printf(" %s\n", "-u, --url=PATH"); | 1571 | printf(" %s\n", "-u, --url=PATH"); |
| 1546 | printf(" %s\n", _("URL to GET or POST (default: /)")); | 1572 | printf(" %s\n", _("URL to GET or POST (default: /)")); |
| 1573 | printf(" %s\n", _("This is the part after the address in a URL, so for " | ||
| 1574 | "\"https://example.com/index.html\" it would be '-u /index.html'")); | ||
| 1547 | printf(" %s\n", "-P, --post=STRING"); | 1575 | printf(" %s\n", "-P, --post=STRING"); |
| 1548 | printf(" %s\n", _("URL decoded http POST data")); | 1576 | printf(" %s\n", _("URL decoded http POST data")); |
| 1549 | printf(" %s\n", | 1577 | printf(" %s\n", |
| @@ -1556,7 +1584,7 @@ void print_help(void) { | |||
| 1556 | printf(" %s\n", _("Warn if document is more than SECONDS old. the number can also be of")); | 1584 | printf(" %s\n", _("Warn if document is more than SECONDS old. the number can also be of")); |
| 1557 | printf(" %s\n", _("the form \"10m\" for minutes, \"10h\" for hours, or \"10d\" for days.")); | 1585 | printf(" %s\n", _("the form \"10m\" for minutes, \"10h\" for hours, or \"10d\" for days.")); |
| 1558 | printf(" %s\n", "-T, --content-type=STRING"); | 1586 | printf(" %s\n", "-T, --content-type=STRING"); |
| 1559 | printf(" %s\n", _("specify Content-Type header media type when POSTing\n")); | 1587 | printf(" %s\n", _("specify Content-Type header media type when POSTing")); |
| 1560 | printf(" %s\n", "-l, --linespan"); | 1588 | printf(" %s\n", "-l, --linespan"); |
| 1561 | printf(" %s\n", _("Allow regex to span newlines (must precede -r or -R)")); | 1589 | printf(" %s\n", _("Allow regex to span newlines (must precede -r or -R)")); |
| 1562 | printf(" %s\n", "-r, --regex, --ereg=STRING"); | 1590 | printf(" %s\n", "-r, --regex, --ereg=STRING"); |
| @@ -1644,6 +1672,8 @@ void print_help(void) { | |||
| 1644 | printf(" %s\n", _("certificate matches the hostname of the server, or if the certificate")); | 1672 | printf(" %s\n", _("certificate matches the hostname of the server, or if the certificate")); |
| 1645 | printf(" %s\n", _("has a valid chain of trust to one of the locally installed CAs.")); | 1673 | printf(" %s\n", _("has a valid chain of trust to one of the locally installed CAs.")); |
| 1646 | printf("\n"); | 1674 | printf("\n"); |
| 1675 | printf(" %s\n", _("To also verify certificates, please set --verify-cert.")); | ||
| 1676 | printf("\n"); | ||
| 1647 | printf("%s\n", _("Examples:")); | 1677 | printf("%s\n", _("Examples:")); |
| 1648 | printf(" %s\n\n", "CHECK CONTENT: check_curl -w 5 -c 10 --ssl -H www.verisign.com"); | 1678 | printf(" %s\n\n", "CHECK CONTENT: check_curl -w 5 -c 10 --ssl -H www.verisign.com"); |
| 1649 | printf(" %s\n", _("When the 'www.verisign.com' server returns its content within 5 seconds,")); | 1679 | printf(" %s\n", _("When the 'www.verisign.com' server returns its content within 5 seconds,")); |
| @@ -1653,16 +1683,18 @@ void print_help(void) { | |||
| 1653 | _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,")); | 1683 | _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,")); |
| 1654 | printf(" %s\n", _("a STATE_CRITICAL will be returned.")); | 1684 | printf(" %s\n", _("a STATE_CRITICAL will be returned.")); |
| 1655 | printf("\n"); | 1685 | printf("\n"); |
| 1656 | printf(" %s\n\n", "CHECK CERTIFICATE: check_curl -H www.verisign.com -C 14"); | 1686 | printf(" %s\n\n", "CHECK CERTIFICATE: check_curl -H www.verisign.com -C 14 -D"); |
| 1657 | printf(" %s\n", | 1687 | printf(" %s\n", |
| 1658 | _("When the certificate of 'www.verisign.com' is valid for more than 14 days,")); | 1688 | _("When the certificate of 'www.verisign.com' is valid for more than 14 days,")); |
| 1659 | printf(" %s\n", | 1689 | printf(" %s\n", |
| 1660 | _("a STATE_OK is returned. When the certificate is still valid, but for less than")); | 1690 | _("a STATE_OK is returned. When the certificate is still valid, but for less than")); |
| 1661 | printf(" %s\n", | 1691 | printf(" %s\n", |
| 1662 | _("14 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when")); | 1692 | _("14 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when")); |
| 1663 | printf(" %s\n\n", _("the certificate is expired.")); | 1693 | printf(" %s\n", _("the certificate is expired.")); |
| 1694 | printf("\n"); | ||
| 1695 | printf(" %s\n", _("The -D flag enforces a certificate validation beyond expiration time.")); | ||
| 1664 | printf("\n"); | 1696 | printf("\n"); |
| 1665 | printf(" %s\n\n", "CHECK CERTIFICATE: check_curl -H www.verisign.com -C 30,14"); | 1697 | printf(" %s\n\n", "CHECK CERTIFICATE: check_curl -H www.verisign.com -C 30,14 -D"); |
| 1666 | printf(" %s\n", | 1698 | printf(" %s\n", |
| 1667 | _("When the certificate of 'www.verisign.com' is valid for more than 30 days,")); | 1699 | _("When the certificate of 'www.verisign.com' is valid for more than 30 days,")); |
| 1668 | printf(" %s\n", | 1700 | printf(" %s\n", |
| @@ -1685,7 +1717,8 @@ void print_help(void) { | |||
| 1685 | printf(" %s\n", _("It is recommended to use an environment proxy like:")); | 1717 | printf(" %s\n", _("It is recommended to use an environment proxy like:")); |
| 1686 | printf(" %s\n", | 1718 | printf(" %s\n", |
| 1687 | _("https_proxy=http://192.168.100.35:3128 ./check_curl -H www.verisign.com -S")); | 1719 | _("https_proxy=http://192.168.100.35:3128 ./check_curl -H www.verisign.com -S")); |
| 1688 | printf(" %s\n", _("legacy proxy requests in check_http style still work:")); | 1720 | printf(" %s\n", _("legacy proxy requests in check_http style might still work, but are frowned " |
| 1721 | "upon, so DONT:")); | ||
| 1689 | printf(" %s\n", _("check_curl -I 192.168.100.35 -p 3128 -u https://www.verisign.com/ -S -j " | 1722 | printf(" %s\n", _("check_curl -I 192.168.100.35 -p 3128 -u https://www.verisign.com/ -S -j " |
| 1690 | "CONNECT -H www.verisign.com ")); | 1723 | "CONNECT -H www.verisign.com ")); |
| 1691 | printf(" %s\n", _("all these options are needed: -I <proxy> -p <proxy-port> -u <check-url> " | 1724 | printf(" %s\n", _("all these options are needed: -I <proxy> -p <proxy-port> -u <check-url> " |
