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.c81
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
71enum { 71enum {
72 MAX_IPV4_HOSTLENGTH = 255,
73};
74
75enum {
76 REGS = 2, 72 REGS = 2,
77}; 73};
78 74
@@ -96,16 +92,16 @@ typedef struct {
96static check_curl_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); 92static check_curl_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
97 93
98static mp_subcheck check_http(check_curl_config /*config*/, check_curl_working_state workingState, 94static mp_subcheck check_http(check_curl_config /*config*/, check_curl_working_state workingState,
99 int redir_depth); 95 long redir_depth);
100 96
101typedef struct { 97typedef 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;
107static redir_wrapper redir(curlhelp_write_curlbuf * /*header_buf*/, check_curl_config /*config*/, 103static 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
110static void print_help(void); 106static void print_help(void);
111void print_usage(void); 107void 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
204mp_subcheck check_http(const check_curl_config config, check_curl_working_state workingState, 200mp_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
659redir_wrapper redir(curlhelp_write_curlbuf *header_buf, const check_curl_config config, 655redir_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> "