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.c441
1 files changed, 333 insertions, 108 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index 2d69b310..c37d45d9 100644
--- a/plugins/check_curl.c
+++ b/plugins/check_curl.c
@@ -37,6 +37,7 @@ const char *progname = "check_curl";
37const char *copyright = "2006-2019"; 37const char *copyright = "2006-2019";
38const char *email = "devel@monitoring-plugins.org"; 38const char *email = "devel@monitoring-plugins.org";
39 39
40#include <stdbool.h>
40#include <ctype.h> 41#include <ctype.h>
41 42
42#include "common.h" 43#include "common.h"
@@ -55,18 +56,24 @@ const char *email = "devel@monitoring-plugins.org";
55 56
56#include <arpa/inet.h> 57#include <arpa/inet.h>
57 58
59#if defined(HAVE_SSL) && defined(USE_OPENSSL)
60#include <openssl/opensslv.h>
61#endif
62
63#include <netdb.h>
64
58#define MAKE_LIBCURL_VERSION(major, minor, patch) ((major)*0x10000 + (minor)*0x100 + (patch)) 65#define MAKE_LIBCURL_VERSION(major, minor, patch) ((major)*0x10000 + (minor)*0x100 + (patch))
59 66
60#define DEFAULT_BUFFER_SIZE 2048 67#define DEFAULT_BUFFER_SIZE 2048
61#define DEFAULT_SERVER_URL "/" 68#define DEFAULT_SERVER_URL "/"
62#define HTTP_EXPECT "HTTP/" 69#define HTTP_EXPECT "HTTP/"
63#define DEFAULT_MAX_REDIRS 15
64#define INET_ADDR_MAX_SIZE INET6_ADDRSTRLEN 70#define INET_ADDR_MAX_SIZE INET6_ADDRSTRLEN
65enum { 71enum {
66 MAX_IPV4_HOSTLENGTH = 255, 72 MAX_IPV4_HOSTLENGTH = 255,
67 HTTP_PORT = 80, 73 HTTP_PORT = 80,
68 HTTPS_PORT = 443, 74 HTTPS_PORT = 443,
69 MAX_PORT = 65535 75 MAX_PORT = 65535,
76 DEFAULT_MAX_REDIRS = 15
70}; 77};
71 78
72enum { 79enum {
@@ -117,7 +124,7 @@ typedef enum curlhelp_ssl_library {
117 124
118enum { 125enum {
119 REGS = 2, 126 REGS = 2,
120 MAX_RE_SIZE = 256 127 MAX_RE_SIZE = 1024
121}; 128};
122#include "regex.h" 129#include "regex.h"
123regex_t preg; 130regex_t preg;
@@ -125,14 +132,14 @@ regmatch_t pmatch[REGS];
125char regexp[MAX_RE_SIZE]; 132char regexp[MAX_RE_SIZE];
126int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE; 133int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE;
127int errcode; 134int errcode;
128int invert_regex = 0; 135bool invert_regex = false;
129 136
130char *server_address = NULL; 137char *server_address = NULL;
131char *host_name = NULL; 138char *host_name = NULL;
132char *server_url = 0; 139char *server_url = 0;
133char server_ip[DEFAULT_BUFFER_SIZE]; 140char server_ip[DEFAULT_BUFFER_SIZE];
134struct curl_slist *server_ips = NULL; 141struct curl_slist *server_ips = NULL;
135int specify_port = FALSE; 142bool specify_port = false;
136unsigned short server_port = HTTP_PORT; 143unsigned short server_port = HTTP_PORT;
137unsigned short virtual_port = 0; 144unsigned short virtual_port = 0;
138int host_name_length; 145int host_name_length;
@@ -144,7 +151,8 @@ int days_till_exp_warn, days_till_exp_crit;
144thresholds *thlds; 151thresholds *thlds;
145char user_agent[DEFAULT_BUFFER_SIZE]; 152char user_agent[DEFAULT_BUFFER_SIZE];
146int verbose = 0; 153int verbose = 0;
147int show_extended_perfdata = FALSE; 154bool show_extended_perfdata = false;
155bool show_body = false;
148int min_page_len = 0; 156int min_page_len = 0;
149int max_page_len = 0; 157int max_page_len = 0;
150int redir_depth = 0; 158int redir_depth = 0;
@@ -153,10 +161,16 @@ char *http_method = NULL;
153char *http_post_data = NULL; 161char *http_post_data = NULL;
154char *http_content_type = NULL; 162char *http_content_type = NULL;
155CURL *curl; 163CURL *curl;
164bool curl_global_initialized = false;
165bool curl_easy_initialized = false;
156struct curl_slist *header_list = NULL; 166struct curl_slist *header_list = NULL;
167bool body_buf_initialized = false;
157curlhelp_write_curlbuf body_buf; 168curlhelp_write_curlbuf body_buf;
169bool header_buf_initialized = false;
158curlhelp_write_curlbuf header_buf; 170curlhelp_write_curlbuf header_buf;
171bool status_line_initialized = false;
159curlhelp_statusline status_line; 172curlhelp_statusline status_line;
173bool put_buf_initialized = false;
160curlhelp_read_curlbuf put_buf; 174curlhelp_read_curlbuf put_buf;
161char http_header[DEFAULT_BUFFER_SIZE]; 175char http_header[DEFAULT_BUFFER_SIZE];
162long code; 176long code;
@@ -166,7 +180,7 @@ double time_connect;
166double time_appconnect; 180double time_appconnect;
167double time_headers; 181double time_headers;
168double time_firstbyte; 182double time_firstbyte;
169char errbuf[CURL_ERROR_SIZE+1]; 183char errbuf[MAX_INPUT_BUFFER];
170CURLcode res; 184CURLcode res;
171char url[DEFAULT_BUFFER_SIZE]; 185char url[DEFAULT_BUFFER_SIZE];
172char msg[DEFAULT_BUFFER_SIZE]; 186char msg[DEFAULT_BUFFER_SIZE];
@@ -179,13 +193,14 @@ char user_auth[MAX_INPUT_BUFFER] = "";
179char proxy_auth[MAX_INPUT_BUFFER] = ""; 193char proxy_auth[MAX_INPUT_BUFFER] = "";
180char **http_opt_headers; 194char **http_opt_headers;
181int http_opt_headers_count = 0; 195int http_opt_headers_count = 0;
182int display_html = FALSE; 196bool display_html = false;
183int onredirect = STATE_OK; 197int onredirect = STATE_OK;
184int followmethod = FOLLOW_HTTP_CURL; 198int followmethod = FOLLOW_HTTP_CURL;
185int followsticky = STICKY_NONE; 199int followsticky = STICKY_NONE;
186int use_ssl = FALSE; 200bool use_ssl = false;
187int use_sni = TRUE; 201bool use_sni = true;
188int check_cert = FALSE; 202bool check_cert = false;
203bool continue_after_check_cert = false;
189typedef union { 204typedef union {
190 struct curl_slist* to_info; 205 struct curl_slist* to_info;
191 struct curl_certinfo* to_certinfo; 206 struct curl_certinfo* to_certinfo;
@@ -195,17 +210,20 @@ int ssl_version = CURL_SSLVERSION_DEFAULT;
195char *client_cert = NULL; 210char *client_cert = NULL;
196char *client_privkey = NULL; 211char *client_privkey = NULL;
197char *ca_cert = NULL; 212char *ca_cert = NULL;
198int is_openssl_callback = FALSE; 213bool verify_peer_and_host = false;
214bool is_openssl_callback = false;
199#if defined(HAVE_SSL) && defined(USE_OPENSSL) 215#if defined(HAVE_SSL) && defined(USE_OPENSSL)
200X509 *cert = NULL; 216X509 *cert = NULL;
201#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */ 217#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */
202int no_body = FALSE; 218bool no_body = false;
203int maximum_age = -1; 219int maximum_age = -1;
204int address_family = AF_UNSPEC; 220int address_family = AF_UNSPEC;
205curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN; 221curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN;
206int curl_http_version = CURL_HTTP_VERSION_NONE; 222int curl_http_version = CURL_HTTP_VERSION_NONE;
223bool automatic_decompression = false;
224char *cookie_jar_file = NULL;
207 225
208int process_arguments (int, char**); 226bool process_arguments (int, char**);
209void handle_curl_option_return_code (CURLcode res, const char* option); 227void handle_curl_option_return_code (CURLcode res, const char* option);
210int check_http (void); 228int check_http (void);
211void redir (curlhelp_write_curlbuf*); 229void redir (curlhelp_write_curlbuf*);
@@ -259,10 +277,10 @@ main (int argc, char **argv)
259 progname, NP_VERSION, VERSION, curl_version()); 277 progname, NP_VERSION, VERSION, curl_version());
260 278
261 /* parse arguments */ 279 /* parse arguments */
262 if (process_arguments (argc, argv) == ERROR) 280 if (process_arguments (argc, argv) == false)
263 usage4 (_("Could not parse arguments")); 281 usage4 (_("Could not parse arguments"));
264 282
265 if (display_html == TRUE) 283 if (display_html)
266 printf ("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">", 284 printf ("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">",
267 use_ssl ? "https" : "http", 285 use_ssl ? "https" : "http",
268 host_name ? host_name : server_address, 286 host_name ? host_name : server_address,
@@ -283,6 +301,20 @@ int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
283 * TODO: is the last certificate always the server certificate? 301 * TODO: is the last certificate always the server certificate?
284 */ 302 */
285 cert = X509_STORE_CTX_get_current_cert(x509_ctx); 303 cert = X509_STORE_CTX_get_current_cert(x509_ctx);
304#if OPENSSL_VERSION_NUMBER >= 0x10100000L
305 X509_up_ref(cert);
306#endif
307 if (verbose>=2) {
308 puts("* SSL verify callback with certificate:");
309 X509_NAME *subject, *issuer;
310 printf("* issuer:\n");
311 issuer = X509_get_issuer_name( cert );
312 X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE);
313 printf("* curl verify_callback:\n* subject:\n");
314 subject = X509_get_subject_name( cert );
315 X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE);
316 puts("");
317 }
286 return 1; 318 return 1;
287} 319}
288 320
@@ -296,6 +328,28 @@ CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm)
296#endif /* USE_OPENSSL */ 328#endif /* USE_OPENSSL */
297#endif /* HAVE_SSL */ 329#endif /* HAVE_SSL */
298 330
331/* returns a string "HTTP/1.x" or "HTTP/2" */
332static char *string_statuscode (int major, int minor)
333{
334 static char buf[10];
335
336 switch (major) {
337 case 1:
338 snprintf (buf, sizeof (buf), "HTTP/%d.%d", major, minor);
339 break;
340 case 2:
341 case 3:
342 snprintf (buf, sizeof (buf), "HTTP/%d", major);
343 break;
344 default:
345 /* assuming here HTTP/N with N>=4 */
346 snprintf (buf, sizeof (buf), "HTTP/%d", major);
347 break;
348 }
349
350 return buf;
351}
352
299/* Checks if the server 'reply' is one of the expected 'statuscodes' */ 353/* Checks if the server 'reply' is one of the expected 'statuscodes' */
300static int 354static int
301expected_statuscode (const char *reply, const char *statuscodes) 355expected_statuscode (const char *reply, const char *statuscodes)
@@ -327,35 +381,110 @@ handle_curl_option_return_code (CURLcode res, const char* option)
327} 381}
328 382
329int 383int
384lookup_host (const char *host, char *buf, size_t buflen)
385{
386 struct addrinfo hints, *res, *result;
387 int errcode;
388 void *ptr;
389
390 memset (&hints, 0, sizeof (hints));
391 hints.ai_family = address_family;
392 hints.ai_socktype = SOCK_STREAM;
393 hints.ai_flags |= AI_CANONNAME;
394
395 errcode = getaddrinfo (host, NULL, &hints, &result);
396 if (errcode != 0)
397 return errcode;
398
399 res = result;
400
401 while (res) {
402 inet_ntop (res->ai_family, res->ai_addr->sa_data, buf, buflen);
403 switch (res->ai_family) {
404 case AF_INET:
405 ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr;
406 break;
407 case AF_INET6:
408 ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
409 break;
410 }
411 inet_ntop (res->ai_family, ptr, buf, buflen);
412 if (verbose >= 1)
413 printf ("* getaddrinfo IPv%d address: %s\n",
414 res->ai_family == PF_INET6 ? 6 : 4, buf);
415 res = res->ai_next;
416 }
417
418 freeaddrinfo(result);
419
420 return 0;
421}
422
423static void
424cleanup (void)
425{
426 if (status_line_initialized) curlhelp_free_statusline(&status_line);
427 status_line_initialized = false;
428 if (curl_easy_initialized) curl_easy_cleanup (curl);
429 curl_easy_initialized = false;
430 if (curl_global_initialized) curl_global_cleanup ();
431 curl_global_initialized = false;
432 if (body_buf_initialized) curlhelp_freewritebuffer (&body_buf);
433 body_buf_initialized = false;
434 if (header_buf_initialized) curlhelp_freewritebuffer (&header_buf);
435 header_buf_initialized = false;
436 if (put_buf_initialized) curlhelp_freereadbuffer (&put_buf);
437 put_buf_initialized = false;
438}
439
440int
330check_http (void) 441check_http (void)
331{ 442{
332 int result = STATE_OK; 443 int result = STATE_OK;
333 int page_len = 0; 444 int page_len = 0;
334 int i; 445 int i;
335 char *force_host_header = NULL; 446 char *force_host_header = NULL;
447 struct curl_slist *host = NULL;
448 char addrstr[100];
449 char dnscache[DEFAULT_BUFFER_SIZE];
336 450
337 /* initialize curl */ 451 /* initialize curl */
338 if (curl_global_init (CURL_GLOBAL_DEFAULT) != CURLE_OK) 452 if (curl_global_init (CURL_GLOBAL_DEFAULT) != CURLE_OK)
339 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n"); 453 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n");
454 curl_global_initialized = true;
340 455
341 if ((curl = curl_easy_init()) == NULL) 456 if ((curl = curl_easy_init()) == NULL) {
342 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n"); 457 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n");
458 }
459 curl_easy_initialized = true;
343 460
461 /* register cleanup function to shut down libcurl properly */
462 atexit (cleanup);
463
344 if (verbose >= 1) 464 if (verbose >= 1)
345 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_VERBOSE, TRUE), "CURLOPT_VERBOSE"); 465 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_VERBOSE, 1), "CURLOPT_VERBOSE");
346 466
347 /* print everything on stdout like check_http would do */ 467 /* print everything on stdout like check_http would do */
348 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_STDERR, stdout), "CURLOPT_STDERR"); 468 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_STDERR, stdout), "CURLOPT_STDERR");
349 469
470 if (automatic_decompression)
471#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6)
472 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""), "CURLOPT_ACCEPT_ENCODING");
473#else
474 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_ENCODING, ""), "CURLOPT_ENCODING");
475#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */
476
350 /* initialize buffer for body of the answer */ 477 /* initialize buffer for body of the answer */
351 if (curlhelp_initwritebuffer(&body_buf) < 0) 478 if (curlhelp_initwritebuffer(&body_buf) < 0)
352 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n"); 479 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n");
480 body_buf_initialized = true;
353 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback), "CURLOPT_WRITEFUNCTION"); 481 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback), "CURLOPT_WRITEFUNCTION");
354 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)&body_buf), "CURLOPT_WRITEDATA"); 482 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)&body_buf), "CURLOPT_WRITEDATA");
355 483
356 /* initialize buffer for header of the answer */ 484 /* initialize buffer for header of the answer */
357 if (curlhelp_initwritebuffer( &header_buf ) < 0) 485 if (curlhelp_initwritebuffer( &header_buf ) < 0)
358 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n" ); 486 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n" );
487 header_buf_initialized = true;
359 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback), "CURLOPT_HEADERFUNCTION"); 488 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback), "CURLOPT_HEADERFUNCTION");
360 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEHEADER, (void *)&header_buf), "CURLOPT_WRITEHEADER"); 489 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEHEADER, (void *)&header_buf), "CURLOPT_WRITEHEADER");
361 490
@@ -368,15 +497,30 @@ check_http (void)
368 497
369 // fill dns resolve cache to make curl connect to the given server_address instead of the host_name, only required for ssl, because we use the host_name later on to make SNI happy 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
370 if(use_ssl && host_name != NULL) { 499 if(use_ssl && host_name != NULL) {
371 struct curl_slist *host = NULL; 500 if ( (res=lookup_host (server_address, addrstr, 100)) != 0) {
372 char dnscache[DEFAULT_BUFFER_SIZE]; 501 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"),
373 snprintf (dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, server_address); 502 server_address, res, gai_strerror (res));
503 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
504 }
505 snprintf (dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, addrstr);
374 host = curl_slist_append(NULL, dnscache); 506 host = curl_slist_append(NULL, dnscache);
375 curl_easy_setopt(curl, CURLOPT_RESOLVE, host); 507 curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
376 if (verbose>=1) 508 if (verbose>=1)
377 printf ("* curl CURLOPT_RESOLVE: %s\n", dnscache); 509 printf ("* curl CURLOPT_RESOLVE: %s\n", dnscache);
378 } 510 }
379 511
512 // If server_address is an IPv6 address it must be surround by square brackets
513 struct in6_addr tmp_in_addr;
514 if (inet_pton(AF_INET6, server_address, &tmp_in_addr) == 1) {
515 char *new_server_address = malloc(strlen(server_address) + 3);
516 if (new_server_address == NULL) {
517 die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n");
518 }
519 snprintf(new_server_address, strlen(server_address)+3, "[%s]", server_address);
520 free(server_address);
521 server_address = new_server_address;
522 }
523
380 /* compose URL: use the address we want to connect to, set Host: header later */ 524 /* compose URL: use the address we want to connect to, set Host: header later */
381 snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", 525 snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s",
382 use_ssl ? "https" : "http", 526 use_ssl ? "https" : "http",
@@ -401,7 +545,7 @@ check_http (void)
401 545
402 /* disable body for HEAD request */ 546 /* disable body for HEAD request */
403 if (http_method && !strcmp (http_method, "HEAD" )) { 547 if (http_method && !strcmp (http_method, "HEAD" )) {
404 no_body = TRUE; 548 no_body = true;
405 } 549 }
406 550
407 /* set HTTP protocol version */ 551 /* set HTTP protocol version */
@@ -467,9 +611,11 @@ check_http (void)
467 if (client_privkey) 611 if (client_privkey)
468 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLKEY, client_privkey), "CURLOPT_SSLKEY"); 612 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLKEY, client_privkey), "CURLOPT_SSLKEY");
469 if (ca_cert) { 613 if (ca_cert) {
614 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CAINFO, ca_cert), "CURLOPT_CAINFO");
615 }
616 if (ca_cert || verify_peer_and_host) {
470 /* per default if we have a CA verify both the peer and the 617 /* per default if we have a CA verify both the peer and the
471 * hostname in the certificate, can be switched off later */ 618 * hostname in the certificate, can be switched off later */
472 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CAINFO, ca_cert), "CURLOPT_CAINFO");
473 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 1), "CURLOPT_SSL_VERIFYPEER"); 619 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 1), "CURLOPT_SSL_VERIFYPEER");
474 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYHOST, 2), "CURLOPT_SSL_VERIFYHOST"); 620 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYHOST, 2), "CURLOPT_SSL_VERIFYHOST");
475 } else { 621 } else {
@@ -496,7 +642,7 @@ check_http (void)
496#ifdef USE_OPENSSL 642#ifdef USE_OPENSSL
497 /* libcurl and monitoring plugins built with OpenSSL, good */ 643 /* libcurl and monitoring plugins built with OpenSSL, good */
498 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); 644 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION");
499 is_openssl_callback = TRUE; 645 is_openssl_callback = true;
500#else /* USE_OPENSSL */ 646#else /* USE_OPENSSL */
501#endif /* USE_OPENSSL */ 647#endif /* USE_OPENSSL */
502 /* libcurl is built with OpenSSL, monitoring plugins, so falling 648 /* libcurl is built with OpenSSL, monitoring plugins, so falling
@@ -575,9 +721,11 @@ check_http (void)
575 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_MAXREDIRS, max_depth+1), "CURLOPT_MAXREDIRS"); 721 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_MAXREDIRS, max_depth+1), "CURLOPT_MAXREDIRS");
576 722
577 /* for now allow only http and https (we are a http(s) check plugin in the end) */ 723 /* for now allow only http and https (we are a http(s) check plugin in the end) */
578#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4) 724#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 85, 0)
725 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https"), "CURLOPT_REDIR_PROTOCOLS_STR");
726#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4)
579 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS), "CURLOPT_REDIRECT_PROTOCOLS"); 727 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS), "CURLOPT_REDIRECT_PROTOCOLS");
580#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4) */ 728#endif
581 729
582 /* TODO: handle the following aspects of redirection, make them 730 /* TODO: handle the following aspects of redirection, make them
583 * command line options too later: 731 * command line options too later:
@@ -621,11 +769,19 @@ check_http (void)
621 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_POSTFIELDS, http_post_data), "CURLOPT_POSTFIELDS"); 769 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_POSTFIELDS, http_post_data), "CURLOPT_POSTFIELDS");
622 } else if (!strcmp(http_method, "PUT")) { 770 } else if (!strcmp(http_method, "PUT")) {
623 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_READFUNCTION, (curl_read_callback)curlhelp_buffer_read_callback), "CURLOPT_READFUNCTION"); 771 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_READFUNCTION, (curl_read_callback)curlhelp_buffer_read_callback), "CURLOPT_READFUNCTION");
624 curlhelp_initreadbuffer (&put_buf, http_post_data, strlen (http_post_data)); 772 if (curlhelp_initreadbuffer (&put_buf, http_post_data, strlen (http_post_data)) < 0)
773 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating read buffer for PUT\n");
774 put_buf_initialized = true;
625 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_READDATA, (void *)&put_buf), "CURLOPT_READDATA"); 775 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_READDATA, (void *)&put_buf), "CURLOPT_READDATA");
626 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_INFILESIZE, (curl_off_t)strlen (http_post_data)), "CURLOPT_INFILESIZE"); 776 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_INFILESIZE, (curl_off_t)strlen (http_post_data)), "CURLOPT_INFILESIZE");
627 } 777 }
628 } 778 }
779
780 /* cookie handling */
781 if (cookie_jar_file != NULL) {
782 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_COOKIEJAR, cookie_jar_file), "CURLOPT_COOKIEJAR");
783 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_COOKIEFILE, cookie_jar_file), "CURLOPT_COOKIEFILE");
784 }
629 785
630 /* do the request */ 786 /* do the request */
631 res = curl_easy_perform(curl); 787 res = curl_easy_perform(curl);
@@ -640,21 +796,23 @@ check_http (void)
640 /* Curl errors, result in critical Nagios state */ 796 /* Curl errors, result in critical Nagios state */
641 if (res != CURLE_OK) { 797 if (res != CURLE_OK) {
642 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"), 798 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"),
643 server_port, res, curl_easy_strerror(res)); 799 server_port, res, errbuf[0] ? errbuf : curl_easy_strerror(res));
644 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 800 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
645 } 801 }
646 802
647 /* certificate checks */ 803 /* certificate checks */
648#ifdef LIBCURL_FEATURE_SSL 804#ifdef LIBCURL_FEATURE_SSL
649 if (use_ssl == TRUE) { 805 if (use_ssl) {
650 if (check_cert == TRUE) { 806 if (check_cert) {
651 if (is_openssl_callback) { 807 if (is_openssl_callback) {
652#ifdef USE_OPENSSL 808#ifdef USE_OPENSSL
653 /* check certificate with OpenSSL functions, curl has been built against OpenSSL 809 /* check certificate with OpenSSL functions, curl has been built against OpenSSL
654 * and we actually have OpenSSL in the monitoring tools 810 * and we actually have OpenSSL in the monitoring tools
655 */ 811 */
656 result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); 812 result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
657 return result; 813 if (!continue_after_check_cert) {
814 return result;
815 }
658#else /* USE_OPENSSL */ 816#else /* USE_OPENSSL */
659 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n"); 817 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n");
660#endif /* USE_OPENSSL */ 818#endif /* USE_OPENSSL */
@@ -694,13 +852,17 @@ GOT_FIRST_CERT:
694 } 852 }
695 BIO_free (cert_BIO); 853 BIO_free (cert_BIO);
696 result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); 854 result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
697 return result; 855 if (!continue_after_check_cert) {
856 return result;
857 }
698#else /* USE_OPENSSL */ 858#else /* USE_OPENSSL */
699 /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our disposal, 859 /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our disposal,
700 * so we use the libcurl CURLINFO data 860 * so we use the libcurl CURLINFO data
701 */ 861 */
702 result = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, days_till_exp_crit); 862 result = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, days_till_exp_crit);
703 return result; 863 if (!continue_after_check_cert) {
864 return result;
865 }
704#endif /* USE_OPENSSL */ 866#endif /* USE_OPENSSL */
705 } else { 867 } else {
706 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Cannot retrieve certificates - cURL returned %d - %s"), 868 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Cannot retrieve certificates - cURL returned %d - %s"),
@@ -726,7 +888,7 @@ GOT_FIRST_CERT:
726 perfd_time(total_time), 888 perfd_time(total_time),
727 perfd_size(page_len), 889 perfd_size(page_len),
728 perfd_time_connect(time_connect), 890 perfd_time_connect(time_connect),
729 use_ssl == TRUE ? perfd_time_ssl (time_appconnect-time_connect) : "", 891 use_ssl ? perfd_time_ssl (time_appconnect-time_connect) : "",
730 perfd_time_headers(time_headers - time_appconnect), 892 perfd_time_headers(time_headers - time_appconnect),
731 perfd_time_firstbyte(time_firstbyte - time_headers), 893 perfd_time_firstbyte(time_firstbyte - time_headers),
732 perfd_time_transfer(total_time-time_firstbyte) 894 perfd_time_transfer(total_time-time_firstbyte)
@@ -746,8 +908,10 @@ GOT_FIRST_CERT:
746 if (curlhelp_parse_statusline (header_buf.buf, &status_line) < 0) { 908 if (curlhelp_parse_statusline (header_buf.buf, &status_line) < 0) {
747 snprintf (msg, DEFAULT_BUFFER_SIZE, "Unparsable status line in %.3g seconds response time|%s\n", 909 snprintf (msg, DEFAULT_BUFFER_SIZE, "Unparsable status line in %.3g seconds response time|%s\n",
748 total_time, perfstring); 910 total_time, perfstring);
749 die (STATE_CRITICAL, "HTTP CRITICAL HTTP/1.x %ld unknown - %s", code, msg); 911 /* 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);
750 } 913 }
914 status_line_initialized = true;
751 915
752 /* get result code from cURL */ 916 /* get result code from cURL */
753 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &code), "CURLINFO_RESPONSE_CODE"); 917 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &code), "CURLINFO_RESPONSE_CODE");
@@ -766,7 +930,9 @@ GOT_FIRST_CERT:
766 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"), status_line.first_line); 930 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"), status_line.first_line);
767 else 931 else
768 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: %s\n"), server_port, status_line.first_line); 932 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: %s\n"), server_port, status_line.first_line);
769 die (STATE_CRITICAL, "HTTP CRITICAL - %s", msg); 933 die (STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg,
934 show_body ? "\n" : "",
935 show_body ? body_buf.buf : "");
770 } 936 }
771 937
772 if( server_expect_yn ) { 938 if( server_expect_yn ) {
@@ -823,8 +989,8 @@ GOT_FIRST_CERT:
823 989
824 /* check status codes, set exit status accordingly */ 990 /* check status codes, set exit status accordingly */
825 if( status_line.http_code != code ) { 991 if( status_line.http_code != code ) {
826 die (STATE_CRITICAL, _("HTTP CRITICAL HTTP/%d.%d %d %s - different HTTP codes (cUrl has %ld)\n"), 992 die (STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"),
827 status_line.http_major, status_line.http_minor, 993 string_statuscode (status_line.http_major, status_line.http_minor),
828 status_line.http_code, status_line.msg, code); 994 status_line.http_code, status_line.msg, code);
829 } 995 }
830 996
@@ -858,12 +1024,12 @@ GOT_FIRST_CERT:
858 1024
859 if (strlen (regexp)) { 1025 if (strlen (regexp)) {
860 errcode = regexec (&preg, body_buf.buf, REGS, pmatch, 0); 1026 errcode = regexec (&preg, body_buf.buf, REGS, pmatch, 0);
861 if ((errcode == 0 && invert_regex == 0) || (errcode == REG_NOMATCH && invert_regex == 1)) { 1027 if ((errcode == 0 && !invert_regex) || (errcode == REG_NOMATCH && invert_regex)) {
862 /* OK - No-op to avoid changing the logic around it */ 1028 /* OK - No-op to avoid changing the logic around it */
863 result = max_state_alt(STATE_OK, result); 1029 result = max_state_alt(STATE_OK, result);
864 } 1030 }
865 else if ((errcode == REG_NOMATCH && invert_regex == 0) || (errcode == 0 && invert_regex == 1)) { 1031 else if ((errcode == REG_NOMATCH && !invert_regex) || (errcode == 0 && invert_regex)) {
866 if (invert_regex == 0) 1032 if (!invert_regex)
867 snprintf (msg, DEFAULT_BUFFER_SIZE, _("%spattern not found, "), msg); 1033 snprintf (msg, DEFAULT_BUFFER_SIZE, _("%spattern not found, "), msg);
868 else 1034 else
869 snprintf (msg, DEFAULT_BUFFER_SIZE, _("%spattern found, "), msg); 1035 snprintf (msg, DEFAULT_BUFFER_SIZE, _("%spattern found, "), msg);
@@ -889,29 +1055,23 @@ GOT_FIRST_CERT:
889 result = max_state_alt(get_status(total_time, thlds), result); 1055 result = max_state_alt(get_status(total_time, thlds), result);
890 1056
891 /* Cut-off trailing characters */ 1057 /* Cut-off trailing characters */
892 if(msg[strlen(msg)-2] == ',') 1058 if (strlen(msg) >= 2) {
893 msg[strlen(msg)-2] = '\0'; 1059 if(msg[strlen(msg)-2] == ',')
894 else 1060 msg[strlen(msg)-2] = '\0';
895 msg[strlen(msg)-3] = '\0'; 1061 else
896 1062 msg[strlen(msg)-3] = '\0';
1063 }
1064
897 /* TODO: separate _() msg and status code: die (result, "HTTP %s: %s\n", state_text(result), msg); */ 1065 /* TODO: separate _() msg and status code: die (result, "HTTP %s: %s\n", state_text(result), msg); */
898 die (result, "HTTP %s: HTTP/%d.%d %d %s%s%s - %d bytes in %.3f second response time %s|%s\n", 1066 die (result, "HTTP %s: %s %d %s%s%s - %d bytes in %.3f second response time %s|%s\n%s%s",
899 state_text(result), status_line.http_major, status_line.http_minor, 1067 state_text(result), string_statuscode (status_line.http_major, status_line.http_minor),
900 status_line.http_code, status_line.msg, 1068 status_line.http_code, status_line.msg,
901 strlen(msg) > 0 ? " - " : "", 1069 strlen(msg) > 0 ? " - " : "",
902 msg, page_len, total_time, 1070 msg, page_len, total_time,
903 (display_html ? "</A>" : ""), 1071 (display_html ? "</A>" : ""),
904 perfstring); 1072 perfstring,
905 1073 (show_body ? body_buf.buf : ""),
906 /* proper cleanup after die? */ 1074 (show_body ? "\n" : "") );
907 curlhelp_free_statusline(&status_line);
908 curl_easy_cleanup (curl);
909 curl_global_cleanup ();
910 curlhelp_freewritebuffer (&body_buf);
911 curlhelp_freewritebuffer (&header_buf);
912 if (!strcmp (http_method, "PUT")) {
913 curlhelp_freereadbuffer (&put_buf);
914 }
915 1075
916 return result; 1076 return result;
917} 1077}
@@ -928,8 +1088,8 @@ char*
928uri_string (const UriTextRangeA range, char* buf, size_t buflen) 1088uri_string (const UriTextRangeA range, char* buf, size_t buflen)
929{ 1089{
930 if (!range.first) return "(null)"; 1090 if (!range.first) return "(null)";
931 strncpy (buf, range.first, max (buflen, range.afterLast - range.first)); 1091 strncpy (buf, range.first, max (buflen-1, range.afterLast - range.first));
932 buf[max (buflen, range.afterLast - range.first)] = '\0'; 1092 buf[max (buflen-1, range.afterLast - range.first)] = '\0';
933 buf[range.afterLast - range.first] = '\0'; 1093 buf[range.afterLast - range.first] = '\0';
934 return buf; 1094 return buf;
935} 1095}
@@ -949,7 +1109,7 @@ redir (curlhelp_write_curlbuf* header_buf)
949 char *new_url; 1109 char *new_url;
950 1110
951 int res = phr_parse_response (header_buf->buf, header_buf->buflen, 1111 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
952 &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen, 1112 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
953 headers, &nof_headers, 0); 1113 headers, &nof_headers, 0);
954 1114
955 location = get_header_value (headers, nof_headers, "location"); 1115 location = get_header_value (headers, nof_headers, "location");
@@ -1008,7 +1168,10 @@ redir (curlhelp_write_curlbuf* header_buf)
1008 } 1168 }
1009 } 1169 }
1010 1170
1011 use_ssl = !uri_strcmp (uri.scheme, "https"); 1171 if (!uri_strcmp (uri.scheme, "https"))
1172 use_ssl = true;
1173 else
1174 use_ssl = false;
1012 1175
1013 /* we do a sloppy test here only, because uriparser would have failed 1176 /* we do a sloppy test here only, because uriparser would have failed
1014 * above, if the port would be invalid, we just check for MAX_PORT 1177 * above, if the port would be invalid, we just check for MAX_PORT
@@ -1041,7 +1204,7 @@ redir (curlhelp_write_curlbuf* header_buf)
1041 const UriPathSegmentA* p = uri.pathHead; 1204 const UriPathSegmentA* p = uri.pathHead;
1042 for (; p; p = p->next) { 1205 for (; p; p = p->next) {
1043 strncat (new_url, "/", DEFAULT_BUFFER_SIZE); 1206 strncat (new_url, "/", DEFAULT_BUFFER_SIZE);
1044 strncat (new_url, uri_string (p->text, buf, DEFAULT_BUFFER_SIZE), DEFAULT_BUFFER_SIZE); 1207 strncat (new_url, uri_string (p->text, buf, DEFAULT_BUFFER_SIZE), DEFAULT_BUFFER_SIZE-1);
1045 } 1208 }
1046 } 1209 }
1047 1210
@@ -1049,8 +1212,8 @@ redir (curlhelp_write_curlbuf* header_buf)
1049 !strncmp(server_address, new_host, MAX_IPV4_HOSTLENGTH) && 1212 !strncmp(server_address, new_host, MAX_IPV4_HOSTLENGTH) &&
1050 (host_name && !strncmp(host_name, new_host, MAX_IPV4_HOSTLENGTH)) && 1213 (host_name && !strncmp(host_name, new_host, MAX_IPV4_HOSTLENGTH)) &&
1051 !strcmp(server_url, new_url)) 1214 !strcmp(server_url, new_url))
1052 die (STATE_WARNING, 1215 die (STATE_CRITICAL,
1053 _("HTTP WARNING - redirection creates an infinite loop - %s://%s:%d%s%s\n"), 1216 _("HTTP CRITICAL - redirection creates an infinite loop - %s://%s:%d%s%s\n"),
1054 use_ssl ? "https" : "http", new_host, new_port, new_url, (display_html ? "</A>" : "")); 1217 use_ssl ? "https" : "http", new_host, new_port, new_url, (display_html ? "</A>" : ""));
1055 1218
1056 /* set new values for redirected request */ 1219 /* set new values for redirected request */
@@ -1083,6 +1246,7 @@ redir (curlhelp_write_curlbuf* header_buf)
1083 * attached to the URL in Location 1246 * attached to the URL in Location
1084 */ 1247 */
1085 1248
1249 cleanup ();
1086 check_http (); 1250 check_http ();
1087} 1251}
1088 1252
@@ -1095,7 +1259,7 @@ test_file (char *path)
1095 usage2 (_("file does not exist or is not readable"), path); 1259 usage2 (_("file does not exist or is not readable"), path);
1096} 1260}
1097 1261
1098int 1262bool
1099process_arguments (int argc, char **argv) 1263process_arguments (int argc, char **argv)
1100{ 1264{
1101 char *p; 1265 char *p;
@@ -1105,8 +1269,12 @@ process_arguments (int argc, char **argv)
1105 enum { 1269 enum {
1106 INVERT_REGEX = CHAR_MAX + 1, 1270 INVERT_REGEX = CHAR_MAX + 1,
1107 SNI_OPTION, 1271 SNI_OPTION,
1272 MAX_REDIRS_OPTION,
1273 CONTINUE_AFTER_CHECK_CERT,
1108 CA_CERT_OPTION, 1274 CA_CERT_OPTION,
1109 HTTP_VERSION_OPTION 1275 HTTP_VERSION_OPTION,
1276 AUTOMATIC_DECOMPRESSION,
1277 COOKIE_JAR
1110 }; 1278 };
1111 1279
1112 int option = 0; 1280 int option = 0;
@@ -1136,6 +1304,8 @@ process_arguments (int argc, char **argv)
1136 {"client-cert", required_argument, 0, 'J'}, 1304 {"client-cert", required_argument, 0, 'J'},
1137 {"private-key", required_argument, 0, 'K'}, 1305 {"private-key", required_argument, 0, 'K'},
1138 {"ca-cert", required_argument, 0, CA_CERT_OPTION}, 1306 {"ca-cert", required_argument, 0, CA_CERT_OPTION},
1307 {"verify-cert", no_argument, 0, 'D'},
1308 {"continue-after-certificate", no_argument, 0, CONTINUE_AFTER_CHECK_CERT},
1139 {"useragent", required_argument, 0, 'A'}, 1309 {"useragent", required_argument, 0, 'A'},
1140 {"header", required_argument, 0, 'k'}, 1310 {"header", required_argument, 0, 'k'},
1141 {"no-body", no_argument, 0, 'N'}, 1311 {"no-body", no_argument, 0, 'N'},
@@ -1146,12 +1316,16 @@ process_arguments (int argc, char **argv)
1146 {"use-ipv4", no_argument, 0, '4'}, 1316 {"use-ipv4", no_argument, 0, '4'},
1147 {"use-ipv6", no_argument, 0, '6'}, 1317 {"use-ipv6", no_argument, 0, '6'},
1148 {"extended-perfdata", no_argument, 0, 'E'}, 1318 {"extended-perfdata", no_argument, 0, 'E'},
1319 {"show-body", no_argument, 0, 'B'},
1320 {"max-redirs", required_argument, 0, MAX_REDIRS_OPTION},
1149 {"http-version", required_argument, 0, HTTP_VERSION_OPTION}, 1321 {"http-version", required_argument, 0, HTTP_VERSION_OPTION},
1322 {"enable-automatic-decompression", no_argument, 0, AUTOMATIC_DECOMPRESSION},
1323 {"cookie-jar", required_argument, 0, COOKIE_JAR},
1150 {0, 0, 0, 0} 1324 {0, 0, 0, 0}
1151 }; 1325 };
1152 1326
1153 if (argc < 2) 1327 if (argc < 2)
1154 return ERROR; 1328 return false;
1155 1329
1156 /* support check_http compatible arguments */ 1330 /* support check_http compatible arguments */
1157 for (c = 1; c < argc; c++) { 1331 for (c = 1; c < argc; c++) {
@@ -1170,7 +1344,7 @@ process_arguments (int argc, char **argv)
1170 server_url = strdup(DEFAULT_SERVER_URL); 1344 server_url = strdup(DEFAULT_SERVER_URL);
1171 1345
1172 while (1) { 1346 while (1) {
1173 c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:d:e:p:s:R:r:u:f:C:J:K:nlLS::m:M:NE", longopts, &option); 1347 c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:d:e:p:s:R:r:u:f:C:J:K:DnlLS::m:M:NEB", longopts, &option);
1174 if (c == -1 || c == EOF || c == 1) 1348 if (c == -1 || c == EOF || c == 1)
1175 break; 1349 break;
1176 1350
@@ -1231,7 +1405,7 @@ process_arguments (int argc, char **argv)
1231 if( strtol(optarg, NULL, 10) > MAX_PORT) 1405 if( strtol(optarg, NULL, 10) > MAX_PORT)
1232 usage2 (_("Invalid port number, supplied port number is too big"), optarg); 1406 usage2 (_("Invalid port number, supplied port number is too big"), optarg);
1233 server_port = (unsigned short)strtol(optarg, NULL, 10); 1407 server_port = (unsigned short)strtol(optarg, NULL, 10);
1234 specify_port = TRUE; 1408 specify_port = true;
1235 } 1409 }
1236 break; 1410 break;
1237 case 'a': /* authorization info */ 1411 case 'a': /* authorization info */
@@ -1265,10 +1439,10 @@ process_arguments (int argc, char **argv)
1265 http_opt_headers[http_opt_headers_count - 1] = optarg; 1439 http_opt_headers[http_opt_headers_count - 1] = optarg;
1266 break; 1440 break;
1267 case 'L': /* show html link */ 1441 case 'L': /* show html link */
1268 display_html = TRUE; 1442 display_html = true;
1269 break; 1443 break;
1270 case 'n': /* do not show html link */ 1444 case 'n': /* do not show html link */
1271 display_html = FALSE; 1445 display_html = false;
1272 break; 1446 break;
1273 case 'C': /* Check SSL cert validity */ 1447 case 'C': /* Check SSL cert validity */
1274#ifdef LIBCURL_FEATURE_SSL 1448#ifdef LIBCURL_FEATURE_SSL
@@ -1289,9 +1463,14 @@ process_arguments (int argc, char **argv)
1289 usage2 (_("Invalid certificate expiration period"), optarg); 1463 usage2 (_("Invalid certificate expiration period"), optarg);
1290 days_till_exp_warn = atoi (optarg); 1464 days_till_exp_warn = atoi (optarg);
1291 } 1465 }
1292 check_cert = TRUE; 1466 check_cert = true;
1293 goto enable_ssl; 1467 goto enable_ssl;
1294#endif 1468#endif
1469 case CONTINUE_AFTER_CHECK_CERT: /* don't stop after the certificate is checked */
1470#ifdef HAVE_SSL
1471 continue_after_check_cert = true;
1472 break;
1473#endif
1295 case 'J': /* use client certificate */ 1474 case 'J': /* use client certificate */
1296#ifdef LIBCURL_FEATURE_SSL 1475#ifdef LIBCURL_FEATURE_SSL
1297 test_file(optarg); 1476 test_file(optarg);
@@ -1310,10 +1489,15 @@ process_arguments (int argc, char **argv)
1310 ca_cert = optarg; 1489 ca_cert = optarg;
1311 goto enable_ssl; 1490 goto enable_ssl;
1312#endif 1491#endif
1492#ifdef LIBCURL_FEATURE_SSL
1493 case 'D': /* verify peer certificate & host */
1494 verify_peer_and_host = true;
1495 break;
1496#endif
1313 case 'S': /* use SSL */ 1497 case 'S': /* use SSL */
1314#ifdef LIBCURL_FEATURE_SSL 1498#ifdef LIBCURL_FEATURE_SSL
1315 enable_ssl: 1499 enable_ssl:
1316 use_ssl = TRUE; 1500 use_ssl = true;
1317 /* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default. 1501 /* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default.
1318 * Only set if it's non-zero. This helps when we include multiple 1502 * Only set if it's non-zero. This helps when we include multiple
1319 * parameters, like -S and -C combinations */ 1503 * parameters, like -S and -C combinations */
@@ -1354,7 +1538,7 @@ process_arguments (int argc, char **argv)
1354 ssl_version = CURL_SSLVERSION_DEFAULT; 1538 ssl_version = CURL_SSLVERSION_DEFAULT;
1355#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */ 1539#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */
1356 else 1540 else
1357 usage4 (_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2 (with optional '+' suffix)")); 1541 usage4 (_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2, 1.3 (with optional '+' suffix)"));
1358 } 1542 }
1359#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) 1543#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0)
1360 if (got_plus) { 1544 if (got_plus) {
@@ -1387,17 +1571,24 @@ process_arguments (int argc, char **argv)
1387#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) */ 1571#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) */
1388 if (verbose >= 2) 1572 if (verbose >= 2)
1389 printf(_("* Set SSL/TLS version to %d\n"), ssl_version); 1573 printf(_("* Set SSL/TLS version to %d\n"), ssl_version);
1390 if (specify_port == FALSE) 1574 if (!specify_port)
1391 server_port = HTTPS_PORT; 1575 server_port = HTTPS_PORT;
1392 break; 1576 break;
1393#else /* LIBCURL_FEATURE_SSL */ 1577#else /* LIBCURL_FEATURE_SSL */
1394 /* -C -J and -K fall through to here without SSL */ 1578 /* -C -J and -K fall through to here without SSL */
1395 usage4 (_("Invalid option - SSL is not available")); 1579 usage4 (_("Invalid option - SSL is not available"));
1396 break; 1580 break;
1397 case SNI_OPTION: /* --sni is parsed, but ignored, the default is TRUE with libcurl */ 1581 case SNI_OPTION: /* --sni is parsed, but ignored, the default is true with libcurl */
1398 use_sni = TRUE; 1582 use_sni = true;
1399 break; 1583 break;
1400#endif /* LIBCURL_FEATURE_SSL */ 1584#endif /* LIBCURL_FEATURE_SSL */
1585 case MAX_REDIRS_OPTION:
1586 if (!is_intnonneg (optarg))
1587 usage2 (_("Invalid max_redirs count"), optarg);
1588 else {
1589 max_depth = atoi (optarg);
1590 }
1591 break;
1401 case 'f': /* onredirect */ 1592 case 'f': /* onredirect */
1402 if (!strcmp (optarg, "ok")) 1593 if (!strcmp (optarg, "ok"))
1403 onredirect = STATE_OK; 1594 onredirect = STATE_OK;
@@ -1449,11 +1640,11 @@ process_arguments (int argc, char **argv)
1449 if (errcode != 0) { 1640 if (errcode != 0) {
1450 (void) regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 1641 (void) regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
1451 printf (_("Could Not Compile Regular Expression: %s"), errbuf); 1642 printf (_("Could Not Compile Regular Expression: %s"), errbuf);
1452 return ERROR; 1643 return false;
1453 } 1644 }
1454 break; 1645 break;
1455 case INVERT_REGEX: 1646 case INVERT_REGEX:
1456 invert_regex = 1; 1647 invert_regex = true;
1457 break; 1648 break;
1458 case '4': 1649 case '4':
1459 address_family = AF_INET; 1650 address_family = AF_INET;
@@ -1488,7 +1679,7 @@ process_arguments (int argc, char **argv)
1488 break; 1679 break;
1489 } 1680 }
1490 case 'N': /* no-body */ 1681 case 'N': /* no-body */
1491 no_body = TRUE; 1682 no_body = true;
1492 break; 1683 break;
1493 case 'M': /* max-age */ 1684 case 'M': /* max-age */
1494 { 1685 {
@@ -1511,7 +1702,10 @@ process_arguments (int argc, char **argv)
1511 } 1702 }
1512 break; 1703 break;
1513 case 'E': /* show extended perfdata */ 1704 case 'E': /* show extended perfdata */
1514 show_extended_perfdata = TRUE; 1705 show_extended_perfdata = true;
1706 break;
1707 case 'B': /* print body content after status line */
1708 show_body = true;
1515 break; 1709 break;
1516 case HTTP_VERSION_OPTION: 1710 case HTTP_VERSION_OPTION:
1517 curl_http_version = CURL_HTTP_VERSION_NONE; 1711 curl_http_version = CURL_HTTP_VERSION_NONE;
@@ -1526,10 +1720,16 @@ process_arguments (int argc, char **argv)
1526 curl_http_version = CURL_HTTP_VERSION_NONE; 1720 curl_http_version = CURL_HTTP_VERSION_NONE;
1527#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) */ 1721#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) */
1528 } else { 1722 } else {
1529 fprintf (stderr, "unkown http-version parameter: %s\n", optarg); 1723 fprintf (stderr, "unknown http-version parameter: %s\n", optarg);
1530 exit (STATE_WARNING); 1724 exit (STATE_WARNING);
1531 } 1725 }
1532 break; 1726 break;
1727 case AUTOMATIC_DECOMPRESSION:
1728 automatic_decompression = true;
1729 break;
1730 case COOKIE_JAR:
1731 cookie_jar_file = optarg;
1732 break;
1533 case '?': 1733 case '?':
1534 /* print short usage statement if args not parsable */ 1734 /* print short usage statement if args not parsable */
1535 usage5 (); 1735 usage5 ();
@@ -1569,52 +1769,52 @@ process_arguments (int argc, char **argv)
1569 virtual_port = server_port; 1769 virtual_port = server_port;
1570 else { 1770 else {
1571 if ((use_ssl && server_port == HTTPS_PORT) || (!use_ssl && server_port == HTTP_PORT)) 1771 if ((use_ssl && server_port == HTTPS_PORT) || (!use_ssl && server_port == HTTP_PORT))
1572 if(specify_port == FALSE) 1772 if(!specify_port)
1573 server_port = virtual_port; 1773 server_port = virtual_port;
1574 } 1774 }
1575 1775
1576 return TRUE; 1776 return true;
1577} 1777}
1578 1778
1579char *perfd_time (double elapsed_time) 1779char *perfd_time (double elapsed_time)
1580{ 1780{
1581 return fperfdata ("time", elapsed_time, "s", 1781 return fperfdata ("time", elapsed_time, "s",
1582 thlds->warning?TRUE:FALSE, thlds->warning?thlds->warning->end:0, 1782 thlds->warning?true:false, thlds->warning?thlds->warning->end:0,
1583 thlds->critical?TRUE:FALSE, thlds->critical?thlds->critical->end:0, 1783 thlds->critical?true:false, thlds->critical?thlds->critical->end:0,
1584 TRUE, 0, TRUE, socket_timeout); 1784 true, 0, true, socket_timeout);
1585} 1785}
1586 1786
1587char *perfd_time_connect (double elapsed_time_connect) 1787char *perfd_time_connect (double elapsed_time_connect)
1588{ 1788{
1589 return fperfdata ("time_connect", elapsed_time_connect, "s", FALSE, 0, FALSE, 0, FALSE, 0, TRUE, socket_timeout); 1789 return fperfdata ("time_connect", elapsed_time_connect, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1590} 1790}
1591 1791
1592char *perfd_time_ssl (double elapsed_time_ssl) 1792char *perfd_time_ssl (double elapsed_time_ssl)
1593{ 1793{
1594 return fperfdata ("time_ssl", elapsed_time_ssl, "s", FALSE, 0, FALSE, 0, FALSE, 0, TRUE, socket_timeout); 1794 return fperfdata ("time_ssl", elapsed_time_ssl, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1595} 1795}
1596 1796
1597char *perfd_time_headers (double elapsed_time_headers) 1797char *perfd_time_headers (double elapsed_time_headers)
1598{ 1798{
1599 return fperfdata ("time_headers", elapsed_time_headers, "s", FALSE, 0, FALSE, 0, FALSE, 0, TRUE, socket_timeout); 1799 return fperfdata ("time_headers", elapsed_time_headers, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1600} 1800}
1601 1801
1602char *perfd_time_firstbyte (double elapsed_time_firstbyte) 1802char *perfd_time_firstbyte (double elapsed_time_firstbyte)
1603{ 1803{
1604 return fperfdata ("time_firstbyte", elapsed_time_firstbyte, "s", FALSE, 0, FALSE, 0, FALSE, 0, TRUE, socket_timeout); 1804 return fperfdata ("time_firstbyte", elapsed_time_firstbyte, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1605} 1805}
1606 1806
1607char *perfd_time_transfer (double elapsed_time_transfer) 1807char *perfd_time_transfer (double elapsed_time_transfer)
1608{ 1808{
1609 return fperfdata ("time_transfer", elapsed_time_transfer, "s", FALSE, 0, FALSE, 0, FALSE, 0, TRUE, socket_timeout); 1809 return fperfdata ("time_transfer", elapsed_time_transfer, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1610} 1810}
1611 1811
1612char *perfd_size (int page_len) 1812char *perfd_size (int page_len)
1613{ 1813{
1614 return perfdata ("size", page_len, "B", 1814 return perfdata ("size", page_len, "B",
1615 (min_page_len>0?TRUE:FALSE), min_page_len, 1815 (min_page_len>0?true:false), min_page_len,
1616 (min_page_len>0?TRUE:FALSE), 0, 1816 (min_page_len>0?true:false), 0,
1617 TRUE, 0, FALSE, 0); 1817 true, 0, false, 0);
1618} 1818}
1619 1819
1620void 1820void
@@ -1659,7 +1859,7 @@ print_help (void)
1659 printf (" %s\n", "-S, --ssl=VERSION[+]"); 1859 printf (" %s\n", "-S, --ssl=VERSION[+]");
1660 printf (" %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents")); 1860 printf (" %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents"));
1661 printf (" %s\n", _("auto-negotiation (2 = SSLv2, 3 = SSLv3, 1 = TLSv1, 1.1 = TLSv1.1,")); 1861 printf (" %s\n", _("auto-negotiation (2 = SSLv2, 3 = SSLv3, 1 = TLSv1, 1.1 = TLSv1.1,"));
1662 printf (" %s\n", _("1.2 = TLSv1.2). With a '+' suffix, newer versions are also accepted.")); 1862 printf (" %s\n", _("1.2 = TLSv1.2, 1.3 = TLSv1.3). With a '+' suffix, newer versions are also accepted."));
1663 printf (" %s\n", _("Note: SSLv2 and SSLv3 are deprecated and are usually disabled in libcurl")); 1863 printf (" %s\n", _("Note: SSLv2 and SSLv3 are deprecated and are usually disabled in libcurl"));
1664 printf (" %s\n", "--sni"); 1864 printf (" %s\n", "--sni");
1665 printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)")); 1865 printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)"));
@@ -1671,7 +1871,11 @@ print_help (void)
1671#endif 1871#endif
1672 printf (" %s\n", "-C, --certificate=INTEGER[,INTEGER]"); 1872 printf (" %s\n", "-C, --certificate=INTEGER[,INTEGER]");
1673 printf (" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443")); 1873 printf (" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443"));
1674 printf (" %s\n", _("(when this option is used the URL is not checked.)")); 1874 printf (" %s\n", _("(when this option is used the URL is not checked by default. You can use"));
1875 printf (" %s\n", _(" --continue-after-certificate to override this behavior)"));
1876 printf (" %s\n", "--continue-after-certificate");
1877 printf (" %s\n", _("Allows the HTTP check to continue after performing the certificate check."));
1878 printf (" %s\n", _("Does nothing unless -C is used."));
1675 printf (" %s\n", "-J, --client-cert=FILE"); 1879 printf (" %s\n", "-J, --client-cert=FILE");
1676 printf (" %s\n", _("Name of file that contains the client certificate (PEM format)")); 1880 printf (" %s\n", _("Name of file that contains the client certificate (PEM format)"));
1677 printf (" %s\n", _("to be used in establishing the SSL session")); 1881 printf (" %s\n", _("to be used in establishing the SSL session"));
@@ -1680,6 +1884,8 @@ print_help (void)
1680 printf (" %s\n", _("matching the client certificate")); 1884 printf (" %s\n", _("matching the client certificate"));
1681 printf (" %s\n", "--ca-cert=FILE"); 1885 printf (" %s\n", "--ca-cert=FILE");
1682 printf (" %s\n", _("CA certificate file to verify peer against")); 1886 printf (" %s\n", _("CA certificate file to verify peer against"));
1887 printf (" %s\n", "-D, --verify-cert");
1888 printf (" %s\n", _("Verify the peer's SSL certificate and hostname"));
1683#endif 1889#endif
1684 1890
1685 printf (" %s\n", "-e, --expect=STRING"); 1891 printf (" %s\n", "-e, --expect=STRING");
@@ -1723,6 +1929,8 @@ print_help (void)
1723 printf (" %s\n", _("Any other tags to be sent in http header. Use multiple times for additional headers")); 1929 printf (" %s\n", _("Any other tags to be sent in http header. Use multiple times for additional headers"));
1724 printf (" %s\n", "-E, --extended-perfdata"); 1930 printf (" %s\n", "-E, --extended-perfdata");
1725 printf (" %s\n", _("Print additional performance data")); 1931 printf (" %s\n", _("Print additional performance data"));
1932 printf (" %s\n", "-B, --show-body");
1933 printf (" %s\n", _("Print body content below status line"));
1726 printf (" %s\n", "-L, --link"); 1934 printf (" %s\n", "-L, --link");
1727 printf (" %s\n", _("Wrap output in HTML link (obsoleted by urlize)")); 1935 printf (" %s\n", _("Wrap output in HTML link (obsoleted by urlize)"));
1728 printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport|curl>"); 1936 printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport|curl>");
@@ -1730,12 +1938,19 @@ print_help (void)
1730 printf (" %s\n", _("specified IP address. stickyport also ensures port stays the same.")); 1938 printf (" %s\n", _("specified IP address. stickyport also ensures port stays the same."));
1731 printf (" %s\n", _("follow uses the old redirection algorithm of check_http.")); 1939 printf (" %s\n", _("follow uses the old redirection algorithm of check_http."));
1732 printf (" %s\n", _("curl uses CURL_FOLLOWLOCATION built into libcurl.")); 1940 printf (" %s\n", _("curl uses CURL_FOLLOWLOCATION built into libcurl."));
1941 printf (" %s\n", "--max-redirs=INTEGER");
1942 printf (" %s", _("Maximal number of redirects (default: "));
1943 printf ("%d)\n", DEFAULT_MAX_REDIRS);
1733 printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>"); 1944 printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>");
1734 printf (" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)")); 1945 printf (" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)"));
1735 printf ("\n"); 1946 printf ("\n");
1736 printf (" %s\n", "--http-version=VERSION"); 1947 printf (" %s\n", "--http-version=VERSION");
1737 printf (" %s\n", _("Connect via specific HTTP protocol.")); 1948 printf (" %s\n", _("Connect via specific HTTP protocol."));
1738 printf (" %s\n", _("1.0 = HTTP/1.0, 1.1 = HTTP/1.1, 2.0 = HTTP/2 (HTTP/2 will fail without -S)")); 1949 printf (" %s\n", _("1.0 = HTTP/1.0, 1.1 = HTTP/1.1, 2.0 = HTTP/2 (HTTP/2 will fail without -S)"));
1950 printf (" %s\n", "--enable-automatic-decompression");
1951 printf (" %s\n", _("Enable automatic decompression of body (CURLOPT_ACCEPT_ENCODING)."));
1952 printf (" %s\n", "---cookie-jar=FILE");
1953 printf (" %s\n", _("Store cookies in the cookie jar and send them out when requested."));
1739 printf ("\n"); 1954 printf ("\n");
1740 1955
1741 printf (UT_WARN_CRIT); 1956 printf (UT_WARN_CRIT);
@@ -1813,15 +2028,22 @@ print_usage (void)
1813{ 2028{
1814 printf ("%s\n", _("Usage:")); 2029 printf ("%s\n", _("Usage:"));
1815 printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname); 2030 printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname);
1816 printf (" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate file>]\n"); 2031 printf (" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate file>] [-D]\n");
1817 printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-a auth]\n"); 2032 printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-a auth]\n");
1818 printf (" [-b proxy_auth] [-f <ok|warning|critcal|follow|sticky|stickyport|curl>]\n"); 2033 printf (" [-b proxy_auth] [-f <ok|warning|critcal|follow|sticky|stickyport|curl>]\n");
1819 printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n"); 2034 printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n");
1820 printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n"); 2035 printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n");
1821 printf (" [-A string] [-k string] [-S <version>] [--sni] [-C <warn_age>[,<crit_age>]]\n"); 2036 printf (" [-A string] [-k string] [-S <version>] [--sni]\n");
1822 printf (" [-T <content-type>] [-j method]\n"); 2037 printf (" [-T <content-type>] [-j method]\n");
1823 printf (" [--http-version=<version>]\n"); 2038 printf (" [--http-version=<version>] [--enable-automatic-decompression]\n");
2039 printf (" [--cookie-jar=<cookie jar file>\n");
2040 printf (" %s -H <vhost> | -I <IP-address> -C <warn_age>[,<crit_age>]\n",progname);
2041 printf (" [-p <port>] [-t <timeout>] [-4|-6] [--sni]\n");
1824 printf ("\n"); 2042 printf ("\n");
2043#ifdef LIBCURL_FEATURE_SSL
2044 printf ("%s\n", _("In the first form, make an HTTP request."));
2045 printf ("%s\n\n", _("In the second form, connect to the server and check the TLS certificate."));
2046#endif
1825 printf ("%s\n", _("WARNING: check_curl is experimental. Please use")); 2047 printf ("%s\n", _("WARNING: check_curl is experimental. Please use"));
1826 printf ("%s\n\n", _("check_http if you need a stable version.")); 2048 printf ("%s\n\n", _("check_http if you need a stable version."));
1827} 2049}
@@ -1848,9 +2070,12 @@ curlhelp_buffer_write_callback (void *buffer, size_t size, size_t nmemb, void *s
1848 curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream; 2070 curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream;
1849 2071
1850 while (buf->bufsize < buf->buflen + size * nmemb + 1) { 2072 while (buf->bufsize < buf->buflen + size * nmemb + 1) {
1851 buf->bufsize *= buf->bufsize * 2; 2073 buf->bufsize = buf->bufsize * 2;
1852 buf->buf = (char *)realloc (buf->buf, buf->bufsize); 2074 buf->buf = (char *)realloc (buf->buf, buf->bufsize);
1853 if (buf->buf == NULL) return -1; 2075 if (buf->buf == NULL) {
2076 fprintf(stderr, "malloc failed (%d) %s\n", errno, strerror(errno));
2077 return -1;
2078 }
1854 } 2079 }
1855 2080
1856 memcpy (buf->buf + buf->buflen, buffer, size * nmemb); 2081 memcpy (buf->buf + buf->buflen, buffer, size * nmemb);
@@ -1944,7 +2169,7 @@ curlhelp_parse_statusline (const char *buf, curlhelp_statusline *status_line)
1944 char *first_line_buf; 2169 char *first_line_buf;
1945 2170
1946 /* find last start of a new header */ 2171 /* find last start of a new header */
1947 start = strrstr2 (buf, "\r\nHTTP"); 2172 start = strrstr2 (buf, "\r\nHTTP/");
1948 if (start != NULL) { 2173 if (start != NULL) {
1949 start += 2; 2174 start += 2;
1950 buf = start; 2175 buf = start;
@@ -2037,7 +2262,7 @@ get_header_value (const struct phr_header* headers, const size_t nof_headers, co
2037{ 2262{
2038 int i; 2263 int i;
2039 for( i = 0; i < nof_headers; i++ ) { 2264 for( i = 0; i < nof_headers; i++ ) {
2040 if( strncasecmp( header, headers[i].name, max( headers[i].name_len, 4 ) ) == 0 ) { 2265 if(headers[i].name != NULL && strncasecmp( header, headers[i].name, max( headers[i].name_len, 4 ) ) == 0 ) {
2041 return strndup( headers[i].value, headers[i].value_len ); 2266 return strndup( headers[i].value, headers[i].value_len );
2042 } 2267 }
2043 } 2268 }
@@ -2056,7 +2281,7 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2056 size_t msglen; 2281 size_t msglen;
2057 2282
2058 int res = phr_parse_response (header_buf->buf, header_buf->buflen, 2283 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
2059 &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen, 2284 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
2060 headers, &nof_headers, 0); 2285 headers, &nof_headers, 0);
2061 2286
2062 server_date = get_header_value (headers, nof_headers, "date"); 2287 server_date = get_header_value (headers, nof_headers, "date");
@@ -2114,7 +2339,7 @@ get_content_length (const curlhelp_write_curlbuf* header_buf, const curlhelp_wri
2114 curlhelp_statusline status_line; 2339 curlhelp_statusline status_line;
2115 2340
2116 int res = phr_parse_response (header_buf->buf, header_buf->buflen, 2341 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
2117 &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen, 2342 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
2118 headers, &nof_headers, 0); 2343 headers, &nof_headers, 0);
2119 2344
2120 content_length_s = get_header_value (headers, nof_headers, "content-length"); 2345 content_length_s = get_header_value (headers, nof_headers, "content-length");