summaryrefslogtreecommitdiffstats
path: root/plugins/check_curl.c
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2023-09-20 06:16:11 (GMT)
committerGitHub <noreply@github.com>2023-09-20 06:16:11 (GMT)
commita5ba424f85153b1ddaaf5e5269c82f0f049828d0 (patch)
treeb9c158930159f2ab1ea2eb45e9e19ccdd0fbb76b /plugins/check_curl.c
parenta99db0243baa5d208c5d500a9bde86b4619cec92 (diff)
parent220455a11e8f1dd3a86ac4725cf0c799c8e3b21b (diff)
downloadmonitoring-plugins-a5ba424f85153b1ddaaf5e5269c82f0f049828d0.tar.gz
Merge branch 'master' into masterrefs/pull/1637/head
Diffstat (limited to 'plugins/check_curl.c')
-rw-r--r--plugins/check_curl.c320
1 files changed, 228 insertions, 92 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index c37d45d..d0871c4 100644
--- a/plugins/check_curl.c
+++ b/plugins/check_curl.c
@@ -55,6 +55,7 @@ const char *email = "devel@monitoring-plugins.org";
55#include "uriparser/Uri.h" 55#include "uriparser/Uri.h"
56 56
57#include <arpa/inet.h> 57#include <arpa/inet.h>
58#include <netinet/in.h>
58 59
59#if defined(HAVE_SSL) && defined(USE_OPENSSL) 60#if defined(HAVE_SSL) && defined(USE_OPENSSL)
60#include <openssl/opensslv.h> 61#include <openssl/opensslv.h>
@@ -243,7 +244,7 @@ void curlhelp_freewritebuffer (curlhelp_write_curlbuf*);
243int curlhelp_initreadbuffer (curlhelp_read_curlbuf *, const char *, size_t); 244int curlhelp_initreadbuffer (curlhelp_read_curlbuf *, const char *, size_t);
244int curlhelp_buffer_read_callback (void *, size_t , size_t , void *); 245int curlhelp_buffer_read_callback (void *, size_t , size_t , void *);
245void curlhelp_freereadbuffer (curlhelp_read_curlbuf *); 246void curlhelp_freereadbuffer (curlhelp_read_curlbuf *);
246curlhelp_ssl_library curlhelp_get_ssl_library (CURL*); 247curlhelp_ssl_library curlhelp_get_ssl_library ();
247const char* curlhelp_get_ssl_library_string (curlhelp_ssl_library); 248const char* curlhelp_get_ssl_library_string (curlhelp_ssl_library);
248int net_noopenssl_check_certificate (cert_ptr_union*, int, int); 249int net_noopenssl_check_certificate (cert_ptr_union*, int, int);
249 250
@@ -296,6 +297,7 @@ main (int argc, char **argv)
296 297
297int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) 298int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
298{ 299{
300 (void) preverify_ok;
299 /* TODO: we get all certificates of the chain, so which ones 301 /* TODO: we get all certificates of the chain, so which ones
300 * should we test? 302 * should we test?
301 * TODO: is the last certificate always the server certificate? 303 * TODO: is the last certificate always the server certificate?
@@ -320,6 +322,8 @@ int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
320 322
321CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) 323CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm)
322{ 324{
325 (void) curl; // ignore unused parameter
326 (void) parm; // ignore unused parameter
323 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback); 327 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback);
324 328
325 return CURLE_OK; 329 return CURLE_OK;
@@ -374,8 +378,12 @@ void
374handle_curl_option_return_code (CURLcode res, const char* option) 378handle_curl_option_return_code (CURLcode res, const char* option)
375{ 379{
376 if (res != CURLE_OK) { 380 if (res != CURLE_OK) {
377 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Error while setting cURL option '%s': cURL returned %d - %s"), 381 snprintf (msg,
378 option, res, curl_easy_strerror(res)); 382 DEFAULT_BUFFER_SIZE,
383 _("Error while setting cURL option '%s': cURL returned %d - %s"),
384 option,
385 res,
386 curl_easy_strerror(res));
379 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 387 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
380 } 388 }
381} 389}
@@ -384,8 +392,11 @@ int
384lookup_host (const char *host, char *buf, size_t buflen) 392lookup_host (const char *host, char *buf, size_t buflen)
385{ 393{
386 struct addrinfo hints, *res, *result; 394 struct addrinfo hints, *res, *result;
395 char addrstr[100];
396 size_t addrstr_len;
387 int errcode; 397 int errcode;
388 void *ptr; 398 void *ptr;
399 size_t buflen_remaining = buflen - 1;
389 400
390 memset (&hints, 0, sizeof (hints)); 401 memset (&hints, 0, sizeof (hints));
391 hints.ai_family = address_family; 402 hints.ai_family = address_family;
@@ -395,26 +406,40 @@ lookup_host (const char *host, char *buf, size_t buflen)
395 errcode = getaddrinfo (host, NULL, &hints, &result); 406 errcode = getaddrinfo (host, NULL, &hints, &result);
396 if (errcode != 0) 407 if (errcode != 0)
397 return errcode; 408 return errcode;
398 409
410 strcpy(buf, "");
399 res = result; 411 res = result;
400 412
401 while (res) { 413 while (res) {
402 inet_ntop (res->ai_family, res->ai_addr->sa_data, buf, buflen); 414 switch (res->ai_family) {
403 switch (res->ai_family) { 415 case AF_INET:
404 case AF_INET: 416 ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr;
405 ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr; 417 break;
406 break; 418 case AF_INET6:
407 case AF_INET6: 419 ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
408 ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; 420 break;
409 break;
410 } 421 }
411 inet_ntop (res->ai_family, ptr, buf, buflen); 422
412 if (verbose >= 1) 423 inet_ntop (res->ai_family, ptr, addrstr, 100);
424 if (verbose >= 1) {
413 printf ("* getaddrinfo IPv%d address: %s\n", 425 printf ("* getaddrinfo IPv%d address: %s\n",
414 res->ai_family == PF_INET6 ? 6 : 4, buf); 426 res->ai_family == PF_INET6 ? 6 : 4, addrstr);
427 }
428
429 // Append all IPs to buf as a comma-separated string
430 addrstr_len = strlen(addrstr);
431 if (buflen_remaining > addrstr_len + 1) {
432 if (buf[0] != '\0') {
433 strncat(buf, ",", buflen_remaining);
434 buflen_remaining -= 1;
435 }
436 strncat(buf, addrstr, buflen_remaining);
437 buflen_remaining -= addrstr_len;
438 }
439
415 res = res->ai_next; 440 res = res->ai_next;
416 } 441 }
417 442
418 freeaddrinfo(result); 443 freeaddrinfo(result);
419 444
420 return 0; 445 return 0;
@@ -445,7 +470,7 @@ check_http (void)
445 int i; 470 int i;
446 char *force_host_header = NULL; 471 char *force_host_header = NULL;
447 struct curl_slist *host = NULL; 472 struct curl_slist *host = NULL;
448 char addrstr[100]; 473 char addrstr[DEFAULT_BUFFER_SIZE/2];
449 char dnscache[DEFAULT_BUFFER_SIZE]; 474 char dnscache[DEFAULT_BUFFER_SIZE];
450 475
451 /* initialize curl */ 476 /* initialize curl */
@@ -497,10 +522,14 @@ check_http (void)
497 522
498 // 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 523 // 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
499 if(use_ssl && host_name != NULL) { 524 if(use_ssl && host_name != NULL) {
500 if ( (res=lookup_host (server_address, addrstr, 100)) != 0) { 525 if ( (res=lookup_host (server_address, addrstr, DEFAULT_BUFFER_SIZE/2)) != 0) {
501 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"), 526 snprintf (msg,
502 server_address, res, gai_strerror (res)); 527 DEFAULT_BUFFER_SIZE,
503 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 528 _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"),
529 server_address,
530 res,
531 gai_strerror (res));
532 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
504 } 533 }
505 snprintf (dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, addrstr); 534 snprintf (dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, addrstr);
506 host = curl_slist_append(NULL, dnscache); 535 host = curl_slist_append(NULL, dnscache);
@@ -524,7 +553,7 @@ check_http (void)
524 /* compose URL: use the address we want to connect to, set Host: header later */ 553 /* compose URL: use the address we want to connect to, set Host: header later */
525 snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", 554 snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s",
526 use_ssl ? "https" : "http", 555 use_ssl ? "https" : "http",
527 use_ssl & host_name != NULL ? host_name : server_address, 556 ( use_ssl & ( host_name != NULL ) ) ? host_name : server_address,
528 server_port, 557 server_port,
529 server_url 558 server_url
530 ); 559 );
@@ -600,7 +629,7 @@ check_http (void)
600 629
601#ifdef LIBCURL_FEATURE_SSL 630#ifdef LIBCURL_FEATURE_SSL
602 631
603 /* set SSL version, warn about unsecure or unsupported versions */ 632 /* set SSL version, warn about insecure or unsupported versions */
604 if (use_ssl) { 633 if (use_ssl) {
605 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLVERSION, ssl_version), "CURLOPT_SSLVERSION"); 634 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLVERSION, ssl_version), "CURLOPT_SSLVERSION");
606 } 635 }
@@ -628,7 +657,7 @@ check_http (void)
628 } 657 }
629 658
630 /* detect SSL library used by libcurl */ 659 /* detect SSL library used by libcurl */
631 ssl_library = curlhelp_get_ssl_library (curl); 660 ssl_library = curlhelp_get_ssl_library ();
632 661
633 /* try hard to get a stack of certificates to verify against */ 662 /* try hard to get a stack of certificates to verify against */
634 if (check_cert) { 663 if (check_cert) {
@@ -792,12 +821,19 @@ check_http (void)
792 /* free header and server IP resolve lists, we don't need it anymore */ 821 /* free header and server IP resolve lists, we don't need it anymore */
793 curl_slist_free_all (header_list); header_list = NULL; 822 curl_slist_free_all (header_list); header_list = NULL;
794 curl_slist_free_all (server_ips); server_ips = NULL; 823 curl_slist_free_all (server_ips); server_ips = NULL;
824 if (host) {
825 curl_slist_free_all (host); host = NULL;
826 }
795 827
796 /* Curl errors, result in critical Nagios state */ 828 /* Curl errors, result in critical Nagios state */
797 if (res != CURLE_OK) { 829 if (res != CURLE_OK) {
798 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"), 830 snprintf (msg,
799 server_port, res, errbuf[0] ? errbuf : curl_easy_strerror(res)); 831 DEFAULT_BUFFER_SIZE,
800 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 832 _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"),
833 server_port,
834 res,
835 errbuf[0] ? errbuf : curl_easy_strerror(res));
836 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
801 } 837 }
802 838
803 /* certificate checks */ 839 /* certificate checks */
@@ -840,15 +876,19 @@ check_http (void)
840 } 876 }
841GOT_FIRST_CERT: 877GOT_FIRST_CERT:
842 if (!raw_cert) { 878 if (!raw_cert) {
843 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Cannot retrieve certificates from CERTINFO information - certificate data was empty")); 879 snprintf (msg,
844 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 880 DEFAULT_BUFFER_SIZE,
881 _("Cannot retrieve certificates from CERTINFO information - certificate data was empty"));
882 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
845 } 883 }
846 BIO* cert_BIO = BIO_new (BIO_s_mem()); 884 BIO* cert_BIO = BIO_new (BIO_s_mem());
847 BIO_write (cert_BIO, raw_cert, strlen(raw_cert)); 885 BIO_write (cert_BIO, raw_cert, strlen(raw_cert));
848 cert = PEM_read_bio_X509 (cert_BIO, NULL, NULL, NULL); 886 cert = PEM_read_bio_X509 (cert_BIO, NULL, NULL, NULL);
849 if (!cert) { 887 if (!cert) {
850 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Cannot read certificate from CERTINFO information - BIO error")); 888 snprintf (msg,
851 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 889 DEFAULT_BUFFER_SIZE,
890 _("Cannot read certificate from CERTINFO information - BIO error"));
891 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
852 } 892 }
853 BIO_free (cert_BIO); 893 BIO_free (cert_BIO);
854 result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); 894 result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
@@ -865,9 +905,12 @@ GOT_FIRST_CERT:
865 } 905 }
866#endif /* USE_OPENSSL */ 906#endif /* USE_OPENSSL */
867 } else { 907 } else {
868 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Cannot retrieve certificates - cURL returned %d - %s"), 908 snprintf (msg,
869 res, curl_easy_strerror(res)); 909 DEFAULT_BUFFER_SIZE,
870 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 910 _("Cannot retrieve certificates - cURL returned %d - %s"),
911 res,
912 curl_easy_strerror(res));
913 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
871 } 914 }
872 } 915 }
873 } 916 }
@@ -906,8 +949,11 @@ GOT_FIRST_CERT:
906 949
907 /* get status line of answer, check sanity of HTTP code */ 950 /* get status line of answer, check sanity of HTTP code */
908 if (curlhelp_parse_statusline (header_buf.buf, &status_line) < 0) { 951 if (curlhelp_parse_statusline (header_buf.buf, &status_line) < 0) {
909 snprintf (msg, DEFAULT_BUFFER_SIZE, "Unparsable status line in %.3g seconds response time|%s\n", 952 snprintf (msg,
910 total_time, perfstring); 953 DEFAULT_BUFFER_SIZE,
954 "Unparsable status line in %.3g seconds response time|%s\n",
955 total_time,
956 perfstring);
911 /* we cannot know the major/minor version here for sure as we cannot parse the first line */ 957 /* we cannot know the major/minor version here for sure as we cannot parse the first line */
912 die (STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", code, msg); 958 die (STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", code, msg);
913 } 959 }
@@ -927,9 +973,16 @@ GOT_FIRST_CERT:
927 /* make sure the status line matches the response we are looking for */ 973 /* make sure the status line matches the response we are looking for */
928 if (!expected_statuscode(status_line.first_line, server_expect)) { 974 if (!expected_statuscode(status_line.first_line, server_expect)) {
929 if (server_port == HTTP_PORT) 975 if (server_port == HTTP_PORT)
930 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"), status_line.first_line); 976 snprintf(msg,
977 DEFAULT_BUFFER_SIZE,
978 _("Invalid HTTP response received from host: %s\n"),
979 status_line.first_line);
931 else 980 else
932 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: %s\n"), server_port, status_line.first_line); 981 snprintf(msg,
982 DEFAULT_BUFFER_SIZE,
983 _("Invalid HTTP response received from host on port %d: %s\n"),
984 server_port,
985 status_line.first_line);
933 die (STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg, 986 die (STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg,
934 show_body ? "\n" : "", 987 show_body ? "\n" : "",
935 show_body ? body_buf.buf : ""); 988 show_body ? body_buf.buf : "");
@@ -965,7 +1018,7 @@ GOT_FIRST_CERT:
965 } 1018 }
966 } else { 1019 } else {
967 /* this is a specific code in the command line to 1020 /* this is a specific code in the command line to
968 * be returned when a redirection is encoutered 1021 * be returned when a redirection is encountered
969 */ 1022 */
970 } 1023 }
971 result = max_state_alt (onredirect, result); 1024 result = max_state_alt (onredirect, result);
@@ -1002,23 +1055,55 @@ GOT_FIRST_CERT:
1002 1055
1003 if (strlen (header_expect)) { 1056 if (strlen (header_expect)) {
1004 if (!strstr (header_buf.buf, header_expect)) { 1057 if (!strstr (header_buf.buf, header_expect)) {
1058
1005 strncpy(&output_header_search[0],header_expect,sizeof(output_header_search)); 1059 strncpy(&output_header_search[0],header_expect,sizeof(output_header_search));
1060
1006 if(output_header_search[sizeof(output_header_search)-1]!='\0') { 1061 if(output_header_search[sizeof(output_header_search)-1]!='\0') {
1007 bcopy("...",&output_header_search[sizeof(output_header_search)-4],4); 1062 bcopy("...",&output_header_search[sizeof(output_header_search)-4],4);
1008 } 1063 }
1009 snprintf (msg, DEFAULT_BUFFER_SIZE, _("%sheader '%s' not found on '%s://%s:%d%s', "), msg, output_header_search, use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url); 1064
1010 result = STATE_CRITICAL; 1065 char tmp[DEFAULT_BUFFER_SIZE];
1066
1067 snprintf (tmp,
1068 DEFAULT_BUFFER_SIZE,
1069 _("%sheader '%s' not found on '%s://%s:%d%s', "),
1070 msg,
1071 output_header_search,
1072 use_ssl ? "https" : "http",
1073 host_name ? host_name : server_address,
1074 server_port,
1075 server_url);
1076
1077 strcpy(msg, tmp);
1078
1079 result = STATE_CRITICAL;
1011 } 1080 }
1012 } 1081 }
1013 1082
1014 if (strlen (string_expect)) { 1083 if (strlen (string_expect)) {
1015 if (!strstr (body_buf.buf, string_expect)) { 1084 if (!strstr (body_buf.buf, string_expect)) {
1085
1016 strncpy(&output_string_search[0],string_expect,sizeof(output_string_search)); 1086 strncpy(&output_string_search[0],string_expect,sizeof(output_string_search));
1087
1017 if(output_string_search[sizeof(output_string_search)-1]!='\0') { 1088 if(output_string_search[sizeof(output_string_search)-1]!='\0') {
1018 bcopy("...",&output_string_search[sizeof(output_string_search)-4],4); 1089 bcopy("...",&output_string_search[sizeof(output_string_search)-4],4);
1019 } 1090 }
1020 snprintf (msg, DEFAULT_BUFFER_SIZE, _("%sstring '%s' not found on '%s://%s:%d%s', "), msg, output_string_search, use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url); 1091
1021 result = STATE_CRITICAL; 1092 char tmp[DEFAULT_BUFFER_SIZE];
1093
1094 snprintf (tmp,
1095 DEFAULT_BUFFER_SIZE,
1096 _("%sstring '%s' not found on '%s://%s:%d%s', "),
1097 msg,
1098 output_string_search,
1099 use_ssl ? "https" : "http",
1100 host_name ? host_name : server_address,
1101 server_port,
1102 server_url);
1103
1104 strcpy(msg, tmp);
1105
1106 result = STATE_CRITICAL;
1022 } 1107 }
1023 } 1108 }
1024 1109
@@ -1029,27 +1114,48 @@ GOT_FIRST_CERT:
1029 result = max_state_alt(STATE_OK, result); 1114 result = max_state_alt(STATE_OK, result);
1030 } 1115 }
1031 else if ((errcode == REG_NOMATCH && !invert_regex) || (errcode == 0 && invert_regex)) { 1116 else if ((errcode == REG_NOMATCH && !invert_regex) || (errcode == 0 && invert_regex)) {
1032 if (!invert_regex) 1117 if (!invert_regex) {
1033 snprintf (msg, DEFAULT_BUFFER_SIZE, _("%spattern not found, "), msg); 1118 char tmp[DEFAULT_BUFFER_SIZE];
1034 else 1119
1035 snprintf (msg, DEFAULT_BUFFER_SIZE, _("%spattern found, "), msg); 1120 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spattern not found, "), msg);
1036 result = STATE_CRITICAL; 1121 strcpy(msg, tmp);
1037 } 1122
1038 else { 1123 } else {
1039 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 1124 char tmp[DEFAULT_BUFFER_SIZE];
1040 snprintf (msg, DEFAULT_BUFFER_SIZE, _("%sExecute Error: %s, "), msg, errbuf); 1125
1041 result = STATE_UNKNOWN; 1126 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spattern found, "), msg);
1042 } 1127 strcpy(msg, tmp);
1128
1129 }
1130 result = STATE_CRITICAL;
1131 } else {
1132 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
1133
1134 char tmp[DEFAULT_BUFFER_SIZE];
1135
1136 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sExecute Error: %s, "), msg, errbuf);
1137 strcpy(msg, tmp);
1138 result = STATE_UNKNOWN;
1139 }
1043 } 1140 }
1044 1141
1045 /* make sure the page is of an appropriate size */ 1142 /* make sure the page is of an appropriate size */
1046 if ((max_page_len > 0) && (page_len > max_page_len)) { 1143 if ((max_page_len > 0) && (page_len > max_page_len)) {
1047 snprintf (msg, DEFAULT_BUFFER_SIZE, _("%spage size %d too large, "), msg, page_len); 1144 char tmp[DEFAULT_BUFFER_SIZE];
1048 result = max_state_alt(STATE_WARNING, result); 1145
1049 } else if ((min_page_len > 0) && (page_len < min_page_len)) { 1146 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spage size %d too large, "), msg, page_len);
1050 snprintf (msg, DEFAULT_BUFFER_SIZE, _("%spage size %d too small, "), msg, page_len); 1147
1051 result = max_state_alt(STATE_WARNING, result); 1148 strcpy(msg, tmp);
1052 } 1149
1150 result = max_state_alt(STATE_WARNING, result);
1151
1152 } else if ((min_page_len > 0) && (page_len < min_page_len)) {
1153 char tmp[DEFAULT_BUFFER_SIZE];
1154
1155 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spage size %d too small, "), msg, page_len);
1156 strcpy(msg, tmp);
1157 result = max_state_alt(STATE_WARNING, result);
1158 }
1053 1159
1054 /* -w, -c: check warning and critical level */ 1160 /* -w, -c: check warning and critical level */
1055 result = max_state_alt(get_status(total_time, thlds), result); 1161 result = max_state_alt(get_status(total_time, thlds), result);
@@ -1633,6 +1739,7 @@ process_arguments (int argc, char **argv)
1633 break; 1739 break;
1634 case 'R': /* regex */ 1740 case 'R': /* regex */
1635 cflags |= REG_ICASE; 1741 cflags |= REG_ICASE;
1742 // fall through
1636 case 'r': /* regex */ 1743 case 'r': /* regex */
1637 strncpy (regexp, optarg, MAX_RE_SIZE - 1); 1744 strncpy (regexp, optarg, MAX_RE_SIZE - 1);
1638 regexp[MAX_RE_SIZE - 1] = 0; 1745 regexp[MAX_RE_SIZE - 1] = 0;
@@ -2030,7 +2137,7 @@ print_usage (void)
2030 printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname); 2137 printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname);
2031 printf (" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate file>] [-D]\n"); 2138 printf (" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate file>] [-D]\n");
2032 printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-a auth]\n"); 2139 printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-a auth]\n");
2033 printf (" [-b proxy_auth] [-f <ok|warning|critcal|follow|sticky|stickyport|curl>]\n"); 2140 printf (" [-b proxy_auth] [-f <ok|warning|critical|follow|sticky|stickyport|curl>]\n");
2034 printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n"); 2141 printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n");
2035 printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n"); 2142 printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n");
2036 printf (" [-A string] [-k string] [-S <version>] [--sni]\n"); 2143 printf (" [-A string] [-k string] [-S <version>] [--sni]\n");
@@ -2196,11 +2303,10 @@ curlhelp_parse_statusline (const char *buf, curlhelp_statusline *status_line)
2196 if( strchr( p, '.' ) != NULL ) { 2303 if( strchr( p, '.' ) != NULL ) {
2197 2304
2198 /* HTTP 1.x case */ 2305 /* HTTP 1.x case */
2199 char *ppp; 2306 strtok( p, "." );
2200 ppp = strtok( p, "." );
2201 status_line->http_major = (int)strtol( p, &pp, 10 ); 2307 status_line->http_major = (int)strtol( p, &pp, 10 );
2202 if( *pp != '\0' ) { free( first_line_buf ); return -1; } 2308 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2203 ppp = strtok( NULL, " " ); 2309 strtok( NULL, " " );
2204 status_line->http_minor = (int)strtol( p, &pp, 10 ); 2310 status_line->http_minor = (int)strtol( p, &pp, 10 );
2205 if( *pp != '\0' ) { free( first_line_buf ); return -1; } 2311 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2206 p += 4; /* 1.x SP */ 2312 p += 4; /* 1.x SP */
@@ -2287,37 +2393,67 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2287 server_date = get_header_value (headers, nof_headers, "date"); 2393 server_date = get_header_value (headers, nof_headers, "date");
2288 document_date = get_header_value (headers, nof_headers, "last-modified"); 2394 document_date = get_header_value (headers, nof_headers, "last-modified");
2289 2395
2290 if (!server_date || !*server_date) { 2396 if (!server_date || !*server_date) {
2291 snprintf (*msg, DEFAULT_BUFFER_SIZE, _("%sServer date unknown, "), *msg); 2397 char tmp[DEFAULT_BUFFER_SIZE];
2292 date_result = max_state_alt(STATE_UNKNOWN, date_result); 2398
2293 } else if (!document_date || !*document_date) { 2399 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sServer date unknown, "), *msg);
2294 snprintf (*msg, DEFAULT_BUFFER_SIZE, _("%sDocument modification date unknown, "), *msg); 2400 strcpy(*msg, tmp);
2295 date_result = max_state_alt(STATE_CRITICAL, date_result); 2401
2402 date_result = max_state_alt(STATE_UNKNOWN, date_result);
2403
2404 } else if (!document_date || !*document_date) {
2405 char tmp[DEFAULT_BUFFER_SIZE];
2406
2407 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sDocument modification date unknown, "), *msg);
2408 strcpy(*msg, tmp);
2409
2410 date_result = max_state_alt(STATE_CRITICAL, date_result);
2411
2296 } else { 2412 } else {
2297 time_t srv_data = curl_getdate (server_date, NULL); 2413 time_t srv_data = curl_getdate (server_date, NULL);
2298 time_t doc_data = curl_getdate (document_date, NULL); 2414 time_t doc_data = curl_getdate (document_date, NULL);
2299 if (verbose >= 2) 2415 if (verbose >= 2)
2300 printf ("* server date: '%s' (%d), doc_date: '%s' (%d)\n", server_date, (int)srv_data, document_date, (int)doc_data); 2416 printf ("* server date: '%s' (%d), doc_date: '%s' (%d)\n", server_date, (int)srv_data, document_date, (int)doc_data);
2301 if (srv_data <= 0) { 2417 if (srv_data <= 0) {
2302 snprintf (*msg, DEFAULT_BUFFER_SIZE, _("%sServer date \"%100s\" unparsable, "), *msg, server_date); 2418 char tmp[DEFAULT_BUFFER_SIZE];
2303 date_result = max_state_alt(STATE_CRITICAL, date_result); 2419
2304 } else if (doc_data <= 0) { 2420 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sServer date \"%100s\" unparsable, "), *msg, server_date);
2305 snprintf (*msg, DEFAULT_BUFFER_SIZE, _("%sDocument date \"%100s\" unparsable, "), *msg, document_date); 2421 strcpy(*msg, tmp);
2306 date_result = max_state_alt(STATE_CRITICAL, date_result); 2422
2307 } else if (doc_data > srv_data + 30) { 2423 date_result = max_state_alt(STATE_CRITICAL, date_result);
2308 snprintf (*msg, DEFAULT_BUFFER_SIZE, _("%sDocument is %d seconds in the future, "), *msg, (int)doc_data - (int)srv_data); 2424 } else if (doc_data <= 0) {
2309 date_result = max_state_alt(STATE_CRITICAL, date_result); 2425 char tmp[DEFAULT_BUFFER_SIZE];
2310 } else if (doc_data < srv_data - maximum_age) { 2426
2311 int n = (srv_data - doc_data); 2427 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sDocument date \"%100s\" unparsable, "), *msg, document_date);
2312 if (n > (60 * 60 * 24 * 2)) { 2428 strcpy(*msg, tmp);
2313 snprintf (*msg, DEFAULT_BUFFER_SIZE, _("%sLast modified %.1f days ago, "), *msg, ((float) n) / (60 * 60 * 24)); 2429
2314 date_result = max_state_alt(STATE_CRITICAL, date_result); 2430 date_result = max_state_alt(STATE_CRITICAL, date_result);
2315 } else { 2431 } else if (doc_data > srv_data + 30) {
2316 snprintf (*msg, DEFAULT_BUFFER_SIZE, _("%sLast modified %d:%02d:%02d ago, "), *msg, n / (60 * 60), (n / 60) % 60, n % 60); 2432 char tmp[DEFAULT_BUFFER_SIZE];
2317 date_result = max_state_alt(STATE_CRITICAL, date_result); 2433
2318 } 2434 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sDocument is %d seconds in the future, "), *msg, (int)doc_data - (int)srv_data);
2319 } 2435 strcpy(*msg, tmp);
2320 } 2436
2437 date_result = max_state_alt(STATE_CRITICAL, date_result);
2438 } else if (doc_data < srv_data - maximum_age) {
2439 int n = (srv_data - doc_data);
2440 if (n > (60 * 60 * 24 * 2)) {
2441 char tmp[DEFAULT_BUFFER_SIZE];
2442
2443 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sLast modified %.1f days ago, "), *msg, ((float) n) / (60 * 60 * 24));
2444 strcpy(*msg, tmp);
2445
2446 date_result = max_state_alt(STATE_CRITICAL, date_result);
2447 } else {
2448 char tmp[DEFAULT_BUFFER_SIZE];
2449
2450 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sLast modified %d:%02d:%02d ago, "), *msg, n / (60 * 60), (n / 60) % 60, n % 60);
2451 strcpy(*msg, tmp);
2452
2453 date_result = max_state_alt(STATE_CRITICAL, date_result);
2454 }
2455 }
2456 }
2321 2457
2322 if (server_date) free (server_date); 2458 if (server_date) free (server_date);
2323 if (document_date) free (document_date); 2459 if (document_date) free (document_date);
@@ -2359,7 +2495,7 @@ get_content_length (const curlhelp_write_curlbuf* header_buf, const curlhelp_wri
2359 2495
2360/* TODO: is there a better way in libcurl to check for the SSL library? */ 2496/* TODO: is there a better way in libcurl to check for the SSL library? */
2361curlhelp_ssl_library 2497curlhelp_ssl_library
2362curlhelp_get_ssl_library (CURL* curl) 2498curlhelp_get_ssl_library ()
2363{ 2499{
2364 curl_version_info_data* version_data; 2500 curl_version_info_data* version_data;
2365 char *ssl_version; 2501 char *ssl_version;