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.c155
1 files changed, 105 insertions, 50 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index d0871c48..d3bddacd 100644
--- a/plugins/check_curl.c
+++ b/plugins/check_curl.c
@@ -134,6 +134,7 @@ char regexp[MAX_RE_SIZE];
134int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE; 134int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE;
135int errcode; 135int errcode;
136bool invert_regex = false; 136bool invert_regex = false;
137int state_regex = STATE_CRITICAL;
137 138
138char *server_address = NULL; 139char *server_address = NULL;
139char *host_name = NULL; 140char *host_name = NULL;
@@ -213,6 +214,7 @@ char *client_privkey = NULL;
213char *ca_cert = NULL; 214char *ca_cert = NULL;
214bool verify_peer_and_host = false; 215bool verify_peer_and_host = false;
215bool is_openssl_callback = false; 216bool is_openssl_callback = false;
217bool add_sslctx_verify_fun = false;
216#if defined(HAVE_SSL) && defined(USE_OPENSSL) 218#if defined(HAVE_SSL) && defined(USE_OPENSSL)
217X509 *cert = NULL; 219X509 *cert = NULL;
218#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */ 220#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */
@@ -223,6 +225,7 @@ curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN;
223int curl_http_version = CURL_HTTP_VERSION_NONE; 225int curl_http_version = CURL_HTTP_VERSION_NONE;
224bool automatic_decompression = false; 226bool automatic_decompression = false;
225char *cookie_jar_file = NULL; 227char *cookie_jar_file = NULL;
228bool haproxy_protocol = false;
226 229
227bool process_arguments (int, char**); 230bool process_arguments (int, char**);
228void handle_curl_option_return_code (CURLcode res, const char* option); 231void handle_curl_option_return_code (CURLcode res, const char* option);
@@ -239,10 +242,10 @@ void print_help (void);
239void print_usage (void); 242void print_usage (void);
240void print_curl_version (void); 243void print_curl_version (void);
241int curlhelp_initwritebuffer (curlhelp_write_curlbuf*); 244int curlhelp_initwritebuffer (curlhelp_write_curlbuf*);
242int curlhelp_buffer_write_callback (void*, size_t , size_t , void*); 245size_t curlhelp_buffer_write_callback(void*, size_t , size_t , void*);
243void curlhelp_freewritebuffer (curlhelp_write_curlbuf*); 246void curlhelp_freewritebuffer (curlhelp_write_curlbuf*);
244int curlhelp_initreadbuffer (curlhelp_read_curlbuf *, const char *, size_t); 247int curlhelp_initreadbuffer (curlhelp_read_curlbuf *, const char *, size_t);
245int curlhelp_buffer_read_callback (void *, size_t , size_t , void *); 248size_t curlhelp_buffer_read_callback(void *, size_t , size_t , void *);
246void curlhelp_freereadbuffer (curlhelp_read_curlbuf *); 249void curlhelp_freereadbuffer (curlhelp_read_curlbuf *);
247curlhelp_ssl_library curlhelp_get_ssl_library (); 250curlhelp_ssl_library curlhelp_get_ssl_library ();
248const char* curlhelp_get_ssl_library_string (curlhelp_ssl_library); 251const char* curlhelp_get_ssl_library_string (curlhelp_ssl_library);
@@ -297,7 +300,7 @@ main (int argc, char **argv)
297 300
298int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) 301int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
299{ 302{
300 (void) preverify_ok; 303 (void) preverify_ok;
301 /* TODO: we get all certificates of the chain, so which ones 304 /* TODO: we get all certificates of the chain, so which ones
302 * should we test? 305 * should we test?
303 * TODO: is the last certificate always the server certificate? 306 * TODO: is the last certificate always the server certificate?
@@ -322,9 +325,18 @@ int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
322 325
323CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) 326CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm)
324{ 327{
325 (void) curl; // ignore unused parameter 328 (void) curl; // ignore unused parameter
326 (void) parm; // ignore unused parameter 329 (void) parm; // ignore unused parameter
327 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback); 330 if(add_sslctx_verify_fun) {
331 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback);
332 }
333
334 // workaround for issue:
335 // OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0
336 // see discussion https://github.com/openssl/openssl/discussions/22690
337#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
338 SSL_CTX_set_options(sslctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
339#endif
328 340
329 return CURLE_OK; 341 return CURLE_OK;
330} 342}
@@ -395,7 +407,7 @@ lookup_host (const char *host, char *buf, size_t buflen)
395 char addrstr[100]; 407 char addrstr[100];
396 size_t addrstr_len; 408 size_t addrstr_len;
397 int errcode; 409 int errcode;
398 void *ptr; 410 void *ptr = { 0 };
399 size_t buflen_remaining = buflen - 1; 411 size_t buflen_remaining = buflen - 1;
400 412
401 memset (&hints, 0, sizeof (hints)); 413 memset (&hints, 0, sizeof (hints));
@@ -466,6 +478,7 @@ int
466check_http (void) 478check_http (void)
467{ 479{
468 int result = STATE_OK; 480 int result = STATE_OK;
481 int result_ssl = STATE_OK;
469 int page_len = 0; 482 int page_len = 0;
470 int i; 483 int i;
471 char *force_host_header = NULL; 484 char *force_host_header = NULL;
@@ -485,7 +498,7 @@ check_http (void)
485 498
486 /* register cleanup function to shut down libcurl properly */ 499 /* register cleanup function to shut down libcurl properly */
487 atexit (cleanup); 500 atexit (cleanup);
488 501
489 if (verbose >= 1) 502 if (verbose >= 1)
490 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_VERBOSE, 1), "CURLOPT_VERBOSE"); 503 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_VERBOSE, 1), "CURLOPT_VERBOSE");
491 504
@@ -520,6 +533,11 @@ check_http (void)
520 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, socket_timeout), "CURLOPT_CONNECTTIMEOUT"); 533 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, socket_timeout), "CURLOPT_CONNECTTIMEOUT");
521 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_TIMEOUT, socket_timeout), "CURLOPT_TIMEOUT"); 534 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_TIMEOUT, socket_timeout), "CURLOPT_TIMEOUT");
522 535
536 /* enable haproxy protocol */
537 if (haproxy_protocol) {
538 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L), "CURLOPT_HAPROXYPROTOCOL");
539 }
540
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 541 // 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
524 if(use_ssl && host_name != NULL) { 542 if(use_ssl && host_name != NULL) {
525 if ( (res=lookup_host (server_address, addrstr, DEFAULT_BUFFER_SIZE/2)) != 0) { 543 if ( (res=lookup_host (server_address, addrstr, DEFAULT_BUFFER_SIZE/2)) != 0) {
@@ -670,9 +688,8 @@ check_http (void)
670 * OpenSSL-style libraries only!) */ 688 * OpenSSL-style libraries only!) */
671#ifdef USE_OPENSSL 689#ifdef USE_OPENSSL
672 /* libcurl and monitoring plugins built with OpenSSL, good */ 690 /* libcurl and monitoring plugins built with OpenSSL, good */
673 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); 691 add_sslctx_verify_fun = true;
674 is_openssl_callback = true; 692 is_openssl_callback = true;
675#else /* USE_OPENSSL */
676#endif /* USE_OPENSSL */ 693#endif /* USE_OPENSSL */
677 /* libcurl is built with OpenSSL, monitoring plugins, so falling 694 /* libcurl is built with OpenSSL, monitoring plugins, so falling
678 * back to manually extracting certificate information */ 695 * back to manually extracting certificate information */
@@ -705,12 +722,18 @@ check_http (void)
705#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ 722#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */
706 /* old libcurl, our only hope is OpenSSL, otherwise we are out of luck */ 723 /* old libcurl, our only hope is OpenSSL, otherwise we are out of luck */
707 if (ssl_library == CURLHELP_SSL_LIBRARY_OPENSSL || ssl_library == CURLHELP_SSL_LIBRARY_LIBRESSL) 724 if (ssl_library == CURLHELP_SSL_LIBRARY_OPENSSL || ssl_library == CURLHELP_SSL_LIBRARY_LIBRESSL)
708 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); 725 add_sslctx_verify_fun = true;
709 else 726 else
710 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (no CURLOPT_SSL_CTX_FUNCTION, no OpenSSL library or libcurl too old and has no CURLOPT_CERTINFO)\n"); 727 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (no CURLOPT_SSL_CTX_FUNCTION, no OpenSSL library or libcurl too old and has no CURLOPT_CERTINFO)\n");
711#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ 728#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */
712 } 729 }
713 730
731#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 10, 6) /* required for CURLOPT_SSL_CTX_FUNCTION */
732 // ssl ctx function is not available with all ssl backends
733 if (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, NULL) != CURLE_UNKNOWN_OPTION)
734 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION");
735#endif
736
714#endif /* LIBCURL_FEATURE_SSL */ 737#endif /* LIBCURL_FEATURE_SSL */
715 738
716 /* set default or user-given user agent identification */ 739 /* set default or user-given user agent identification */
@@ -805,7 +828,7 @@ check_http (void)
805 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_INFILESIZE, (curl_off_t)strlen (http_post_data)), "CURLOPT_INFILESIZE"); 828 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_INFILESIZE, (curl_off_t)strlen (http_post_data)), "CURLOPT_INFILESIZE");
806 } 829 }
807 } 830 }
808 831
809 /* cookie handling */ 832 /* cookie handling */
810 if (cookie_jar_file != NULL) { 833 if (cookie_jar_file != NULL) {
811 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_COOKIEJAR, cookie_jar_file), "CURLOPT_COOKIEJAR"); 834 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_COOKIEJAR, cookie_jar_file), "CURLOPT_COOKIEJAR");
@@ -845,9 +868,9 @@ check_http (void)
845 /* check certificate with OpenSSL functions, curl has been built against OpenSSL 868 /* check certificate with OpenSSL functions, curl has been built against OpenSSL
846 * and we actually have OpenSSL in the monitoring tools 869 * and we actually have OpenSSL in the monitoring tools
847 */ 870 */
848 result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); 871 result_ssl = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
849 if (!continue_after_check_cert) { 872 if (!continue_after_check_cert) {
850 return result; 873 return result_ssl;
851 } 874 }
852#else /* USE_OPENSSL */ 875#else /* USE_OPENSSL */
853 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n"); 876 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n");
@@ -891,17 +914,17 @@ GOT_FIRST_CERT:
891 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 914 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
892 } 915 }
893 BIO_free (cert_BIO); 916 BIO_free (cert_BIO);
894 result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); 917 result_ssl = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
895 if (!continue_after_check_cert) { 918 if (!continue_after_check_cert) {
896 return result; 919 return result_ssl;
897 } 920 }
898#else /* USE_OPENSSL */ 921#else /* USE_OPENSSL */
899 /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our disposal, 922 /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our disposal,
900 * so we use the libcurl CURLINFO data 923 * so we use the libcurl CURLINFO data
901 */ 924 */
902 result = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, days_till_exp_crit); 925 result_ssl = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, days_till_exp_crit);
903 if (!continue_after_check_cert) { 926 if (!continue_after_check_cert) {
904 return result; 927 return result_ssl;
905 } 928 }
906#endif /* USE_OPENSSL */ 929#endif /* USE_OPENSSL */
907 } else { 930 } else {
@@ -1127,7 +1150,7 @@ GOT_FIRST_CERT:
1127 strcpy(msg, tmp); 1150 strcpy(msg, tmp);
1128 1151
1129 } 1152 }
1130 result = STATE_CRITICAL; 1153 result = state_regex;
1131 } else { 1154 } else {
1132 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 1155 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
1133 1156
@@ -1167,9 +1190,9 @@ GOT_FIRST_CERT:
1167 else 1190 else
1168 msg[strlen(msg)-3] = '\0'; 1191 msg[strlen(msg)-3] = '\0';
1169 } 1192 }
1170 1193
1171 /* TODO: separate _() msg and status code: die (result, "HTTP %s: %s\n", state_text(result), msg); */ 1194 /* TODO: separate _() msg and status code: die (result, "HTTP %s: %s\n", state_text(result), msg); */
1172 die (result, "HTTP %s: %s %d %s%s%s - %d bytes in %.3f second response time %s|%s\n%s%s", 1195 die (max_state_alt(result, result_ssl), "HTTP %s: %s %d %s%s%s - %d bytes in %.3f second response time %s|%s\n%s%s",
1173 state_text(result), string_statuscode (status_line.http_major, status_line.http_minor), 1196 state_text(result), string_statuscode (status_line.http_major, status_line.http_minor),
1174 status_line.http_code, status_line.msg, 1197 status_line.http_code, status_line.msg,
1175 strlen(msg) > 0 ? " - " : "", 1198 strlen(msg) > 0 ? " - " : "",
@@ -1179,23 +1202,23 @@ GOT_FIRST_CERT:
1179 (show_body ? body_buf.buf : ""), 1202 (show_body ? body_buf.buf : ""),
1180 (show_body ? "\n" : "") ); 1203 (show_body ? "\n" : "") );
1181 1204
1182 return result; 1205 return max_state_alt(result, result_ssl);
1183} 1206}
1184 1207
1185int 1208int
1186uri_strcmp (const UriTextRangeA range, const char* s) 1209uri_strcmp (const UriTextRangeA range, const char* s)
1187{ 1210{
1188 if (!range.first) return -1; 1211 if (!range.first) return -1;
1189 if (range.afterLast - range.first < strlen (s)) return -1; 1212 if ( (size_t)(range.afterLast - range.first) < strlen (s) ) return -1;
1190 return strncmp (s, range.first, min( range.afterLast - range.first, strlen (s))); 1213 return strncmp (s, range.first, min( (size_t)(range.afterLast - range.first), strlen (s)));
1191} 1214}
1192 1215
1193char* 1216char*
1194uri_string (const UriTextRangeA range, char* buf, size_t buflen) 1217uri_string (const UriTextRangeA range, char* buf, size_t buflen)
1195{ 1218{
1196 if (!range.first) return "(null)"; 1219 if (!range.first) return "(null)";
1197 strncpy (buf, range.first, max (buflen-1, range.afterLast - range.first)); 1220 strncpy (buf, range.first, max (buflen-1, (size_t)(range.afterLast - range.first)));
1198 buf[max (buflen-1, range.afterLast - range.first)] = '\0'; 1221 buf[max (buflen-1, (size_t)(range.afterLast - range.first))] = '\0';
1199 buf[range.afterLast - range.first] = '\0'; 1222 buf[range.afterLast - range.first] = '\0';
1200 return buf; 1223 return buf;
1201} 1224}
@@ -1218,6 +1241,10 @@ redir (curlhelp_write_curlbuf* header_buf)
1218 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen, 1241 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
1219 headers, &nof_headers, 0); 1242 headers, &nof_headers, 0);
1220 1243
1244 if (res == -1) {
1245 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
1246 }
1247
1221 location = get_header_value (headers, nof_headers, "location"); 1248 location = get_header_value (headers, nof_headers, "location");
1222 1249
1223 if (verbose >= 2) 1250 if (verbose >= 2)
@@ -1274,10 +1301,12 @@ redir (curlhelp_write_curlbuf* header_buf)
1274 } 1301 }
1275 } 1302 }
1276 1303
1277 if (!uri_strcmp (uri.scheme, "https")) 1304 if (uri.scheme.first) {
1278 use_ssl = true; 1305 if (!uri_strcmp (uri.scheme, "https"))
1279 else 1306 use_ssl = true;
1280 use_ssl = false; 1307 else
1308 use_ssl = false;
1309 }
1281 1310
1282 /* we do a sloppy test here only, because uriparser would have failed 1311 /* we do a sloppy test here only, because uriparser would have failed
1283 * above, if the port would be invalid, we just check for MAX_PORT 1312 * above, if the port would be invalid, we just check for MAX_PORT
@@ -1295,10 +1324,13 @@ redir (curlhelp_write_curlbuf* header_buf)
1295 MAX_PORT, location, display_html ? "</A>" : ""); 1324 MAX_PORT, location, display_html ? "</A>" : "");
1296 1325
1297 /* by RFC 7231 relative URLs in Location should be taken relative to 1326 /* by RFC 7231 relative URLs in Location should be taken relative to
1298 * the original URL, so wy try to form a new absolute URL here 1327 * the original URL, so we try to form a new absolute URL here
1299 */ 1328 */
1300 if (!uri.scheme.first && !uri.hostText.first) { 1329 if (!uri.scheme.first && !uri.hostText.first) {
1301 new_host = strdup (host_name ? host_name : server_address); 1330 new_host = strdup (host_name ? host_name : server_address);
1331 new_port = server_port;
1332 if(use_ssl)
1333 uri_string (uri.scheme, "https", DEFAULT_BUFFER_SIZE);
1302 } else { 1334 } else {
1303 new_host = strdup (uri_string (uri.hostText, buf, DEFAULT_BUFFER_SIZE)); 1335 new_host = strdup (uri_string (uri.hostText, buf, DEFAULT_BUFFER_SIZE));
1304 } 1336 }
@@ -1380,7 +1412,9 @@ process_arguments (int argc, char **argv)
1380 CA_CERT_OPTION, 1412 CA_CERT_OPTION,
1381 HTTP_VERSION_OPTION, 1413 HTTP_VERSION_OPTION,
1382 AUTOMATIC_DECOMPRESSION, 1414 AUTOMATIC_DECOMPRESSION,
1383 COOKIE_JAR 1415 COOKIE_JAR,
1416 HAPROXY_PROTOCOL,
1417 STATE_REGEX
1384 }; 1418 };
1385 1419
1386 int option = 0; 1420 int option = 0;
@@ -1419,6 +1453,7 @@ process_arguments (int argc, char **argv)
1419 {"content-type", required_argument, 0, 'T'}, 1453 {"content-type", required_argument, 0, 'T'},
1420 {"pagesize", required_argument, 0, 'm'}, 1454 {"pagesize", required_argument, 0, 'm'},
1421 {"invert-regex", no_argument, NULL, INVERT_REGEX}, 1455 {"invert-regex", no_argument, NULL, INVERT_REGEX},
1456 {"state-regex", required_argument, 0, STATE_REGEX},
1422 {"use-ipv4", no_argument, 0, '4'}, 1457 {"use-ipv4", no_argument, 0, '4'},
1423 {"use-ipv6", no_argument, 0, '6'}, 1458 {"use-ipv6", no_argument, 0, '6'},
1424 {"extended-perfdata", no_argument, 0, 'E'}, 1459 {"extended-perfdata", no_argument, 0, 'E'},
@@ -1427,6 +1462,7 @@ process_arguments (int argc, char **argv)
1427 {"http-version", required_argument, 0, HTTP_VERSION_OPTION}, 1462 {"http-version", required_argument, 0, HTTP_VERSION_OPTION},
1428 {"enable-automatic-decompression", no_argument, 0, AUTOMATIC_DECOMPRESSION}, 1463 {"enable-automatic-decompression", no_argument, 0, AUTOMATIC_DECOMPRESSION},
1429 {"cookie-jar", required_argument, 0, COOKIE_JAR}, 1464 {"cookie-jar", required_argument, 0, COOKIE_JAR},
1465 {"haproxy-protocol", no_argument, 0, HAPROXY_PROTOCOL},
1430 {0, 0, 0, 0} 1466 {0, 0, 0, 0}
1431 }; 1467 };
1432 1468
@@ -1694,7 +1730,7 @@ process_arguments (int argc, char **argv)
1694 else { 1730 else {
1695 max_depth = atoi (optarg); 1731 max_depth = atoi (optarg);
1696 } 1732 }
1697 break; 1733 break;
1698 case 'f': /* onredirect */ 1734 case 'f': /* onredirect */
1699 if (!strcmp (optarg, "ok")) 1735 if (!strcmp (optarg, "ok"))
1700 onredirect = STATE_OK; 1736 onredirect = STATE_OK;
@@ -1753,6 +1789,13 @@ process_arguments (int argc, char **argv)
1753 case INVERT_REGEX: 1789 case INVERT_REGEX:
1754 invert_regex = true; 1790 invert_regex = true;
1755 break; 1791 break;
1792 case STATE_REGEX:
1793 if (!strcasecmp (optarg, "critical"))
1794 state_regex = STATE_CRITICAL;
1795 else if (!strcasecmp (optarg, "warning"))
1796 state_regex = STATE_WARNING;
1797 else usage2 (_("Invalid state-regex option"), optarg);
1798 break;
1756 case '4': 1799 case '4':
1757 address_family = AF_INET; 1800 address_family = AF_INET;
1758 break; 1801 break;
@@ -1837,6 +1880,9 @@ process_arguments (int argc, char **argv)
1837 case COOKIE_JAR: 1880 case COOKIE_JAR:
1838 cookie_jar_file = optarg; 1881 cookie_jar_file = optarg;
1839 break; 1882 break;
1883 case HAPROXY_PROTOCOL:
1884 haproxy_protocol = true;
1885 break;
1840 case '?': 1886 case '?':
1841 /* print short usage statement if args not parsable */ 1887 /* print short usage statement if args not parsable */
1842 usage5 (); 1888 usage5 ();
@@ -1977,8 +2023,11 @@ print_help (void)
1977 printf (" %s\n", _("Note: SNI is not supported in libcurl before 7.18.1")); 2023 printf (" %s\n", _("Note: SNI is not supported in libcurl before 7.18.1"));
1978#endif 2024#endif
1979 printf (" %s\n", "-C, --certificate=INTEGER[,INTEGER]"); 2025 printf (" %s\n", "-C, --certificate=INTEGER[,INTEGER]");
1980 printf (" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443")); 2026 printf (" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443."));
1981 printf (" %s\n", _("(when this option is used the URL is not checked by default. You can use")); 2027 printf (" %s\n", _("A STATE_WARNING is returned if the certificate has a validity less than the"));
2028 printf (" %s\n", _("first agument's value. If there is a second argument and the certificate's"));
2029 printf (" %s\n", _("validity is less than its value, a STATE_CRITICAL is returned."));
2030 printf (" %s\n", _("(When this option is used the URL is not checked by default. You can use"));
1982 printf (" %s\n", _(" --continue-after-certificate to override this behavior)")); 2031 printf (" %s\n", _(" --continue-after-certificate to override this behavior)"));
1983 printf (" %s\n", "--continue-after-certificate"); 2032 printf (" %s\n", "--continue-after-certificate");
1984 printf (" %s\n", _("Allows the HTTP check to continue after performing the certificate check.")); 2033 printf (" %s\n", _("Allows the HTTP check to continue after performing the certificate check."));
@@ -2007,7 +2056,7 @@ print_help (void)
2007 printf (" %s\n", "-u, --url=PATH"); 2056 printf (" %s\n", "-u, --url=PATH");
2008 printf (" %s\n", _("URL to GET or POST (default: /)")); 2057 printf (" %s\n", _("URL to GET or POST (default: /)"));
2009 printf (" %s\n", "-P, --post=STRING"); 2058 printf (" %s\n", "-P, --post=STRING");
2010 printf (" %s\n", _("URL encoded http POST data")); 2059 printf (" %s\n", _("URL decoded http POST data"));
2011 printf (" %s\n", "-j, --method=STRING (for example: HEAD, OPTIONS, TRACE, PUT, DELETE, CONNECT)"); 2060 printf (" %s\n", "-j, --method=STRING (for example: HEAD, OPTIONS, TRACE, PUT, DELETE, CONNECT)");
2012 printf (" %s\n", _("Set HTTP method.")); 2061 printf (" %s\n", _("Set HTTP method."));
2013 printf (" %s\n", "-N, --no-body"); 2062 printf (" %s\n", "-N, --no-body");
@@ -2025,7 +2074,10 @@ print_help (void)
2025 printf (" %s\n", "-R, --eregi=STRING"); 2074 printf (" %s\n", "-R, --eregi=STRING");
2026 printf (" %s\n", _("Search page for case-insensitive regex STRING")); 2075 printf (" %s\n", _("Search page for case-insensitive regex STRING"));
2027 printf (" %s\n", "--invert-regex"); 2076 printf (" %s\n", "--invert-regex");
2028 printf (" %s\n", _("Return CRITICAL if found, OK if not\n")); 2077 printf (" %s\n", _("Return STATE if found, OK if not (STATE is CRITICAL, per default)"));
2078 printf (" %s\n", _("can be changed with --state--regex)"));
2079 printf (" %s\n", "--state-regex=STATE");
2080 printf (" %s\n", _("Return STATE if regex is found, OK if not. STATE can be one of \"critical\",\"warning\""));
2029 printf (" %s\n", "-a, --authorization=AUTH_PAIR"); 2081 printf (" %s\n", "-a, --authorization=AUTH_PAIR");
2030 printf (" %s\n", _("Username:password on sites with basic authentication")); 2082 printf (" %s\n", _("Username:password on sites with basic authentication"));
2031 printf (" %s\n", "-b, --proxy-authorization=AUTH_PAIR"); 2083 printf (" %s\n", "-b, --proxy-authorization=AUTH_PAIR");
@@ -2056,7 +2108,9 @@ print_help (void)
2056 printf (" %s\n", _("1.0 = HTTP/1.0, 1.1 = HTTP/1.1, 2.0 = HTTP/2 (HTTP/2 will fail without -S)")); 2108 printf (" %s\n", _("1.0 = HTTP/1.0, 1.1 = HTTP/1.1, 2.0 = HTTP/2 (HTTP/2 will fail without -S)"));
2057 printf (" %s\n", "--enable-automatic-decompression"); 2109 printf (" %s\n", "--enable-automatic-decompression");
2058 printf (" %s\n", _("Enable automatic decompression of body (CURLOPT_ACCEPT_ENCODING).")); 2110 printf (" %s\n", _("Enable automatic decompression of body (CURLOPT_ACCEPT_ENCODING)."));
2059 printf (" %s\n", "---cookie-jar=FILE"); 2111 printf(" %s\n", "--haproxy-protocol");
2112 printf(" %s\n", _("Send HAProxy proxy protocol v1 header (CURLOPT_HAPROXYPROTOCOL)."));
2113 printf (" %s\n", "--cookie-jar=FILE");
2060 printf (" %s\n", _("Store cookies in the cookie jar and send them out when requested.")); 2114 printf (" %s\n", _("Store cookies in the cookie jar and send them out when requested."));
2061 printf ("\n"); 2115 printf ("\n");
2062 2116
@@ -2140,7 +2194,7 @@ print_usage (void)
2140 printf (" [-b proxy_auth] [-f <ok|warning|critical|follow|sticky|stickyport|curl>]\n"); 2194 printf (" [-b proxy_auth] [-f <ok|warning|critical|follow|sticky|stickyport|curl>]\n");
2141 printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n"); 2195 printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n");
2142 printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n"); 2196 printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n");
2143 printf (" [-A string] [-k string] [-S <version>] [--sni]\n"); 2197 printf (" [-A string] [-k string] [-S <version>] [--sni] [--haproxy-protocol]\n");
2144 printf (" [-T <content-type>] [-j method]\n"); 2198 printf (" [-T <content-type>] [-j method]\n");
2145 printf (" [--http-version=<version>] [--enable-automatic-decompression]\n"); 2199 printf (" [--http-version=<version>] [--enable-automatic-decompression]\n");
2146 printf (" [--cookie-jar=<cookie jar file>\n"); 2200 printf (" [--cookie-jar=<cookie jar file>\n");
@@ -2151,8 +2205,6 @@ print_usage (void)
2151 printf ("%s\n", _("In the first form, make an HTTP request.")); 2205 printf ("%s\n", _("In the first form, make an HTTP request."));
2152 printf ("%s\n\n", _("In the second form, connect to the server and check the TLS certificate.")); 2206 printf ("%s\n\n", _("In the second form, connect to the server and check the TLS certificate."));
2153#endif 2207#endif
2154 printf ("%s\n", _("WARNING: check_curl is experimental. Please use"));
2155 printf ("%s\n\n", _("check_http if you need a stable version."));
2156} 2208}
2157 2209
2158void 2210void
@@ -2171,8 +2223,7 @@ curlhelp_initwritebuffer (curlhelp_write_curlbuf *buf)
2171 return 0; 2223 return 0;
2172} 2224}
2173 2225
2174int 2226size_t curlhelp_buffer_write_callback (void *buffer, size_t size, size_t nmemb, void *stream)
2175curlhelp_buffer_write_callback (void *buffer, size_t size, size_t nmemb, void *stream)
2176{ 2227{
2177 curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream; 2228 curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream;
2178 2229
@@ -2192,8 +2243,7 @@ curlhelp_buffer_write_callback (void *buffer, size_t size, size_t nmemb, void *s
2192 return (int)(size * nmemb); 2243 return (int)(size * nmemb);
2193} 2244}
2194 2245
2195int 2246size_t curlhelp_buffer_read_callback(void *buffer, size_t size, size_t nmemb, void *stream)
2196curlhelp_buffer_read_callback (void *buffer, size_t size, size_t nmemb, void *stream)
2197{ 2247{
2198 curlhelp_read_curlbuf *buf = (curlhelp_read_curlbuf *)stream; 2248 curlhelp_read_curlbuf *buf = (curlhelp_read_curlbuf *)stream;
2199 2249
@@ -2366,8 +2416,7 @@ remove_newlines (char *s)
2366char * 2416char *
2367get_header_value (const struct phr_header* headers, const size_t nof_headers, const char* header) 2417get_header_value (const struct phr_header* headers, const size_t nof_headers, const char* header)
2368{ 2418{
2369 int i; 2419 for(size_t i = 0; i < nof_headers; i++ ) {
2370 for( i = 0; i < nof_headers; i++ ) {
2371 if(headers[i].name != NULL && strncasecmp( header, headers[i].name, max( headers[i].name_len, 4 ) ) == 0 ) { 2420 if(headers[i].name != NULL && strncasecmp( header, headers[i].name, max( headers[i].name_len, 4 ) ) == 0 ) {
2372 return strndup( headers[i].value, headers[i].value_len ); 2421 return strndup( headers[i].value, headers[i].value_len );
2373 } 2422 }
@@ -2390,6 +2439,10 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2390 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen, 2439 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
2391 headers, &nof_headers, 0); 2440 headers, &nof_headers, 0);
2392 2441
2442 if (res == -1) {
2443 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
2444 }
2445
2393 server_date = get_header_value (headers, nof_headers, "date"); 2446 server_date = get_header_value (headers, nof_headers, "date");
2394 document_date = get_header_value (headers, nof_headers, "last-modified"); 2447 document_date = get_header_value (headers, nof_headers, "last-modified");
2395 2448
@@ -2465,9 +2518,7 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2465int 2518int
2466get_content_length (const curlhelp_write_curlbuf* header_buf, const curlhelp_write_curlbuf* body_buf) 2519get_content_length (const curlhelp_write_curlbuf* header_buf, const curlhelp_write_curlbuf* body_buf)
2467{ 2520{
2468 const char *s; 2521 size_t content_length = 0;
2469 int content_length = 0;
2470 char *copy;
2471 struct phr_header headers[255]; 2522 struct phr_header headers[255];
2472 size_t nof_headers = 255; 2523 size_t nof_headers = 255;
2473 size_t msglen; 2524 size_t msglen;
@@ -2478,6 +2529,10 @@ get_content_length (const curlhelp_write_curlbuf* header_buf, const curlhelp_wri
2478 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen, 2529 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
2479 headers, &nof_headers, 0); 2530 headers, &nof_headers, 0);
2480 2531
2532 if (res == -1) {
2533 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
2534 }
2535
2481 content_length_s = get_header_value (headers, nof_headers, "content-length"); 2536 content_length_s = get_header_value (headers, nof_headers, "content-length");
2482 if (!content_length_s) { 2537 if (!content_length_s) {
2483 return header_buf->buflen + body_buf->buflen; 2538 return header_buf->buflen + body_buf->buflen;