summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/check_curl.c4416
1 files changed, 2156 insertions, 2260 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index d3bddac..8936110 100644
--- a/plugins/check_curl.c
+++ b/plugins/check_curl.c
@@ -1,37 +1,37 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_curl plugin 3 * Monitoring check_curl plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2019 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2019 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_curl plugin 10 * This file contains the check_curl plugin
11* 11 *
12* This plugin tests the HTTP service on the specified host. It can test 12 * This plugin tests the HTTP service on the specified host. It can test
13* normal (http) and secure (https) servers, follow redirects, search for 13 * normal (http) and secure (https) servers, follow redirects, search for
14* strings and regular expressions, check connection times, and report on 14 * strings and regular expressions, check connection times, and report on
15* certificate expiration times. 15 * certificate expiration times.
16* 16 *
17* This plugin uses functions from the curl library, see 17 * This plugin uses functions from the curl library, see
18* http://curl.haxx.se 18 * http://curl.haxx.se
19* 19 *
20* This program is free software: you can redistribute it and/or modify 20 * This program is free software: you can redistribute it and/or modify
21* it under the terms of the GNU General Public License as published by 21 * it under the terms of the GNU General Public License as published by
22* the Free Software Foundation, either version 3 of the License, or 22 * the Free Software Foundation, either version 3 of the License, or
23* (at your option) any later version. 23 * (at your option) any later version.
24* 24 *
25* This program is distributed in the hope that it will be useful, 25 * This program is distributed in the hope that it will be useful,
26* but WITHOUT ANY WARRANTY; without even the implied warranty of 26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28* GNU General Public License for more details. 28 * GNU General Public License for more details.
29* 29 *
30* You should have received a copy of the GNU General Public License 30 * You should have received a copy of the GNU General Public License
31* along with this program. If not, see <http://www.gnu.org/licenses/>. 31 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32* 32 *
33* 33 *
34*****************************************************************************/ 34 *****************************************************************************/
35const char *progname = "check_curl"; 35const char *progname = "check_curl";
36 36
37const char *copyright = "2006-2019"; 37const char *copyright = "2006-2019";
@@ -44,7 +44,7 @@ const char *email = "devel@monitoring-plugins.org";
44#include "utils.h" 44#include "utils.h"
45 45
46#ifndef LIBCURL_PROTOCOL_HTTP 46#ifndef LIBCURL_PROTOCOL_HTTP
47#error libcurl compiled without HTTP support, compiling check_curl plugin does not makes a lot of sense 47# error libcurl compiled without HTTP support, compiling check_curl plugin does not makes a lot of sense
48#endif 48#endif
49 49
50#include "curl/curl.h" 50#include "curl/curl.h"
@@ -58,7 +58,7 @@ const char *email = "devel@monitoring-plugins.org";
58#include <netinet/in.h> 58#include <netinet/in.h>
59 59
60#if defined(HAVE_SSL) && defined(USE_OPENSSL) 60#if defined(HAVE_SSL) && defined(USE_OPENSSL)
61#include <openssl/opensslv.h> 61# include <openssl/opensslv.h>
62#endif 62#endif
63 63
64#include <netdb.h> 64#include <netdb.h>
@@ -66,66 +66,66 @@ const char *email = "devel@monitoring-plugins.org";
66#define MAKE_LIBCURL_VERSION(major, minor, patch) ((major)*0x10000 + (minor)*0x100 + (patch)) 66#define MAKE_LIBCURL_VERSION(major, minor, patch) ((major)*0x10000 + (minor)*0x100 + (patch))
67 67
68#define DEFAULT_BUFFER_SIZE 2048 68#define DEFAULT_BUFFER_SIZE 2048
69#define DEFAULT_SERVER_URL "/" 69#define DEFAULT_SERVER_URL "/"
70#define HTTP_EXPECT "HTTP/" 70#define HTTP_EXPECT "HTTP/"
71#define INET_ADDR_MAX_SIZE INET6_ADDRSTRLEN 71#define INET_ADDR_MAX_SIZE INET6_ADDRSTRLEN
72enum { 72enum {
73 MAX_IPV4_HOSTLENGTH = 255, 73 MAX_IPV4_HOSTLENGTH = 255,
74 HTTP_PORT = 80, 74 HTTP_PORT = 80,
75 HTTPS_PORT = 443, 75 HTTPS_PORT = 443,
76 MAX_PORT = 65535, 76 MAX_PORT = 65535,
77 DEFAULT_MAX_REDIRS = 15 77 DEFAULT_MAX_REDIRS = 15
78}; 78};
79 79
80enum { 80enum {
81 STICKY_NONE = 0, 81 STICKY_NONE = 0,
82 STICKY_HOST = 1, 82 STICKY_HOST = 1,
83 STICKY_PORT = 2 83 STICKY_PORT = 2
84}; 84};
85 85
86enum { 86enum {
87 FOLLOW_HTTP_CURL = 0, 87 FOLLOW_HTTP_CURL = 0,
88 FOLLOW_LIBCURL = 1 88 FOLLOW_LIBCURL = 1
89}; 89};
90 90
91/* for buffers for header and body */ 91/* for buffers for header and body */
92typedef struct { 92typedef struct {
93 char *buf; 93 char *buf;
94 size_t buflen; 94 size_t buflen;
95 size_t bufsize; 95 size_t bufsize;
96} curlhelp_write_curlbuf; 96} curlhelp_write_curlbuf;
97 97
98/* for buffering the data sent in PUT */ 98/* for buffering the data sent in PUT */
99typedef struct { 99typedef struct {
100 char *buf; 100 char *buf;
101 size_t buflen; 101 size_t buflen;
102 off_t pos; 102 off_t pos;
103} curlhelp_read_curlbuf; 103} curlhelp_read_curlbuf;
104 104
105/* for parsing the HTTP status line */ 105/* for parsing the HTTP status line */
106typedef struct { 106typedef struct {
107 int http_major; /* major version of the protocol, always 1 (HTTP/0.9 107 int http_major; /* major version of the protocol, always 1 (HTTP/0.9
108 * never reached the big internet most likely) */ 108 * never reached the big internet most likely) */
109 int http_minor; /* minor version of the protocol, usually 0 or 1 */ 109 int http_minor; /* minor version of the protocol, usually 0 or 1 */
110 int http_code; /* HTTP return code as in RFC 2145 */ 110 int http_code; /* HTTP return code as in RFC 2145 */
111 int http_subcode; /* Microsoft IIS extension, HTTP subcodes, see 111 int http_subcode; /* Microsoft IIS extension, HTTP subcodes, see
112 * http://support.microsoft.com/kb/318380/en-us */ 112 * http://support.microsoft.com/kb/318380/en-us */
113 const char *msg; /* the human readable message */ 113 const char *msg; /* the human readable message */
114 char *first_line; /* a copy of the first line */ 114 char *first_line; /* a copy of the first line */
115} curlhelp_statusline; 115} curlhelp_statusline;
116 116
117/* to know the underlying SSL library used by libcurl */ 117/* to know the underlying SSL library used by libcurl */
118typedef enum curlhelp_ssl_library { 118typedef enum curlhelp_ssl_library {
119 CURLHELP_SSL_LIBRARY_UNKNOWN, 119 CURLHELP_SSL_LIBRARY_UNKNOWN,
120 CURLHELP_SSL_LIBRARY_OPENSSL, 120 CURLHELP_SSL_LIBRARY_OPENSSL,
121 CURLHELP_SSL_LIBRARY_LIBRESSL, 121 CURLHELP_SSL_LIBRARY_LIBRESSL,
122 CURLHELP_SSL_LIBRARY_GNUTLS, 122 CURLHELP_SSL_LIBRARY_GNUTLS,
123 CURLHELP_SSL_LIBRARY_NSS 123 CURLHELP_SSL_LIBRARY_NSS
124} curlhelp_ssl_library; 124} curlhelp_ssl_library;
125 125
126enum { 126enum {
127 REGS = 2, 127 REGS = 2,
128 MAX_RE_SIZE = 1024 128 MAX_RE_SIZE = 1024
129}; 129};
130#include "regex.h" 130#include "regex.h"
131regex_t preg; 131regex_t preg;
@@ -204,8 +204,8 @@ bool use_sni = true;
204bool check_cert = false; 204bool check_cert = false;
205bool continue_after_check_cert = false; 205bool continue_after_check_cert = false;
206typedef union { 206typedef union {
207 struct curl_slist* to_info; 207 struct curl_slist *to_info;
208 struct curl_certinfo* to_certinfo; 208 struct curl_certinfo *to_certinfo;
209} cert_ptr_union; 209} cert_ptr_union;
210cert_ptr_union cert_ptr; 210cert_ptr_union cert_ptr;
211int ssl_version = CURL_SSLVERSION_DEFAULT; 211int ssl_version = CURL_SSLVERSION_DEFAULT;
@@ -227,946 +227,889 @@ bool automatic_decompression = false;
227char *cookie_jar_file = NULL; 227char *cookie_jar_file = NULL;
228bool haproxy_protocol = false; 228bool haproxy_protocol = false;
229 229
230bool process_arguments (int, char**); 230bool process_arguments(int, char **);
231void handle_curl_option_return_code (CURLcode res, const char* option); 231void handle_curl_option_return_code(CURLcode res, const char *option);
232int check_http (void); 232int check_http(void);
233void redir (curlhelp_write_curlbuf*); 233void redir(curlhelp_write_curlbuf *);
234char *perfd_time (double microsec); 234char *perfd_time(double microsec);
235char *perfd_time_connect (double microsec); 235char *perfd_time_connect(double microsec);
236char *perfd_time_ssl (double microsec); 236char *perfd_time_ssl(double microsec);
237char *perfd_time_firstbyte (double microsec); 237char *perfd_time_firstbyte(double microsec);
238char *perfd_time_headers (double microsec); 238char *perfd_time_headers(double microsec);
239char *perfd_time_transfer (double microsec); 239char *perfd_time_transfer(double microsec);
240char *perfd_size (int page_len); 240char *perfd_size(int page_len);
241void print_help (void); 241void print_help(void);
242void print_usage (void); 242void print_usage(void);
243void print_curl_version (void); 243void print_curl_version(void);
244int curlhelp_initwritebuffer (curlhelp_write_curlbuf*); 244int curlhelp_initwritebuffer(curlhelp_write_curlbuf *);
245size_t curlhelp_buffer_write_callback(void*, size_t , size_t , void*); 245size_t curlhelp_buffer_write_callback(void *, size_t, size_t, void *);
246void curlhelp_freewritebuffer (curlhelp_write_curlbuf*); 246void curlhelp_freewritebuffer(curlhelp_write_curlbuf *);
247int curlhelp_initreadbuffer (curlhelp_read_curlbuf *, const char *, size_t); 247int curlhelp_initreadbuffer(curlhelp_read_curlbuf *, const char *, size_t);
248size_t curlhelp_buffer_read_callback(void *, size_t , size_t , void *); 248size_t curlhelp_buffer_read_callback(void *, size_t, size_t, void *);
249void curlhelp_freereadbuffer (curlhelp_read_curlbuf *); 249void curlhelp_freereadbuffer(curlhelp_read_curlbuf *);
250curlhelp_ssl_library curlhelp_get_ssl_library (); 250curlhelp_ssl_library curlhelp_get_ssl_library();
251const char* curlhelp_get_ssl_library_string (curlhelp_ssl_library); 251const char *curlhelp_get_ssl_library_string(curlhelp_ssl_library);
252int net_noopenssl_check_certificate (cert_ptr_union*, int, int); 252int net_noopenssl_check_certificate(cert_ptr_union *, int, int);
253 253
254int curlhelp_parse_statusline (const char*, curlhelp_statusline *); 254int curlhelp_parse_statusline(const char *, curlhelp_statusline *);
255void curlhelp_free_statusline (curlhelp_statusline *); 255void curlhelp_free_statusline(curlhelp_statusline *);
256char *get_header_value (const struct phr_header* headers, const size_t nof_headers, const char* header); 256char *get_header_value(const struct phr_header *headers, const size_t nof_headers, const char *header);
257int check_document_dates (const curlhelp_write_curlbuf *, char (*msg)[DEFAULT_BUFFER_SIZE]); 257int check_document_dates(const curlhelp_write_curlbuf *, char (*msg)[DEFAULT_BUFFER_SIZE]);
258int get_content_length (const curlhelp_write_curlbuf* header_buf, const curlhelp_write_curlbuf* body_buf); 258int get_content_length(const curlhelp_write_curlbuf *header_buf, const curlhelp_write_curlbuf *body_buf);
259 259
260#if defined(HAVE_SSL) && defined(USE_OPENSSL) 260#if defined(HAVE_SSL) && defined(USE_OPENSSL)
261int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int days_till_exp_crit); 261int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int days_till_exp_crit);
262#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */ 262#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */
263 263
264void remove_newlines (char *); 264void remove_newlines(char *);
265void test_file (char *); 265void test_file(char *);
266 266
267int 267int main(int argc, char **argv) {
268main (int argc, char **argv) 268 int result = STATE_UNKNOWN;
269{
270 int result = STATE_UNKNOWN;
271 269
272 setlocale (LC_ALL, ""); 270 setlocale(LC_ALL, "");
273 bindtextdomain (PACKAGE, LOCALEDIR); 271 bindtextdomain(PACKAGE, LOCALEDIR);
274 textdomain (PACKAGE); 272 textdomain(PACKAGE);
275 273
276 /* Parse extra opts if any */ 274 /* Parse extra opts if any */
277 argv = np_extra_opts (&argc, argv, progname); 275 argv = np_extra_opts(&argc, argv, progname);
278 276
279 /* set defaults */ 277 /* set defaults */
280 snprintf( user_agent, DEFAULT_BUFFER_SIZE, "%s/v%s (monitoring-plugins %s, %s)", 278 snprintf(user_agent, DEFAULT_BUFFER_SIZE, "%s/v%s (monitoring-plugins %s, %s)", progname, NP_VERSION, VERSION, curl_version());
281 progname, NP_VERSION, VERSION, curl_version());
282 279
283 /* parse arguments */ 280 /* parse arguments */
284 if (process_arguments (argc, argv) == false) 281 if (process_arguments(argc, argv) == false)
285 usage4 (_("Could not parse arguments")); 282 usage4(_("Could not parse arguments"));
286 283
287 if (display_html) 284 if (display_html)
288 printf ("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">", 285 printf("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">", use_ssl ? "https" : "http", host_name ? host_name : server_address,
289 use_ssl ? "https" : "http", 286 virtual_port ? virtual_port : server_port, server_url);
290 host_name ? host_name : server_address,
291 virtual_port ? virtual_port : server_port,
292 server_url);
293 287
294 result = check_http (); 288 result = check_http();
295 return result; 289 return result;
296} 290}
297 291
298#ifdef HAVE_SSL 292#ifdef HAVE_SSL
299#ifdef USE_OPENSSL 293# ifdef USE_OPENSSL
300 294
301int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) 295int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) {
302{ 296 (void)preverify_ok;
303 (void) preverify_ok; 297 /* TODO: we get all certificates of the chain, so which ones
304 /* TODO: we get all certificates of the chain, so which ones 298 * should we test?
305 * should we test? 299 * TODO: is the last certificate always the server certificate?
306 * TODO: is the last certificate always the server certificate? 300 */
307 */ 301 cert = X509_STORE_CTX_get_current_cert(x509_ctx);
308 cert = X509_STORE_CTX_get_current_cert(x509_ctx); 302# if OPENSSL_VERSION_NUMBER >= 0x10100000L
309#if OPENSSL_VERSION_NUMBER >= 0x10100000L 303 X509_up_ref(cert);
310 X509_up_ref(cert); 304# endif
311#endif 305 if (verbose >= 2) {
312 if (verbose>=2) { 306 puts("* SSL verify callback with certificate:");
313 puts("* SSL verify callback with certificate:"); 307 X509_NAME *subject, *issuer;
314 X509_NAME *subject, *issuer; 308 printf("* issuer:\n");
315 printf("* issuer:\n"); 309 issuer = X509_get_issuer_name(cert);
316 issuer = X509_get_issuer_name( cert ); 310 X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE);
317 X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE); 311 printf("* curl verify_callback:\n* subject:\n");
318 printf("* curl verify_callback:\n* subject:\n"); 312 subject = X509_get_subject_name(cert);
319 subject = X509_get_subject_name( cert ); 313 X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE);
320 X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE); 314 puts("");
321 puts(""); 315 }
322 } 316 return 1;
323 return 1;
324} 317}
325 318
326CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) 319CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) {
327{ 320 (void)curl; // ignore unused parameter
328 (void) curl; // ignore unused parameter 321 (void)parm; // ignore unused parameter
329 (void) parm; // ignore unused parameter 322 if (add_sslctx_verify_fun) {
330 if(add_sslctx_verify_fun) { 323 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback);
331 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback); 324 }
332 } 325
333 326 // workaround for issue:
334 // workaround for issue: 327 // OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0
335 // OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0 328 // see discussion https://github.com/openssl/openssl/discussions/22690
336 // see discussion https://github.com/openssl/openssl/discussions/22690 329# ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
337#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF 330 SSL_CTX_set_options(sslctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
338 SSL_CTX_set_options(sslctx, SSL_OP_IGNORE_UNEXPECTED_EOF); 331# endif
339#endif
340 332
341 return CURLE_OK; 333 return CURLE_OK;
342} 334}
343 335
344#endif /* USE_OPENSSL */ 336# endif /* USE_OPENSSL */
345#endif /* HAVE_SSL */ 337#endif /* HAVE_SSL */
346 338
347/* returns a string "HTTP/1.x" or "HTTP/2" */ 339/* returns a string "HTTP/1.x" or "HTTP/2" */
348static char *string_statuscode (int major, int minor) 340static char *string_statuscode(int major, int minor) {
349{ 341 static char buf[10];
350 static char buf[10]; 342
351 343 switch (major) {
352 switch (major) { 344 case 1:
353 case 1: 345 snprintf(buf, sizeof(buf), "HTTP/%d.%d", major, minor);
354 snprintf (buf, sizeof (buf), "HTTP/%d.%d", major, minor); 346 break;
355 break; 347 case 2:
356 case 2: 348 case 3:
357 case 3: 349 snprintf(buf, sizeof(buf), "HTTP/%d", major);
358 snprintf (buf, sizeof (buf), "HTTP/%d", major); 350 break;
359 break; 351 default:
360 default: 352 /* assuming here HTTP/N with N>=4 */
361 /* assuming here HTTP/N with N>=4 */ 353 snprintf(buf, sizeof(buf), "HTTP/%d", major);
362 snprintf (buf, sizeof (buf), "HTTP/%d", major); 354 break;
363 break; 355 }
364 } 356
365 357 return buf;
366 return buf;
367} 358}
368 359
369/* Checks if the server 'reply' is one of the expected 'statuscodes' */ 360/* Checks if the server 'reply' is one of the expected 'statuscodes' */
370static int 361static int expected_statuscode(const char *reply, const char *statuscodes) {
371expected_statuscode (const char *reply, const char *statuscodes) 362 char *expected, *code;
372{ 363 int result = 0;
373 char *expected, *code; 364
374 int result = 0; 365 if ((expected = strdup(statuscodes)) == NULL)
375 366 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n"));
376 if ((expected = strdup (statuscodes)) == NULL) 367
377 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n")); 368 for (code = strtok(expected, ","); code != NULL; code = strtok(NULL, ","))
378 369 if (strstr(reply, code) != NULL) {
379 for (code = strtok (expected, ","); code != NULL; code = strtok (NULL, ",")) 370 result = 1;
380 if (strstr (reply, code) != NULL) { 371 break;
381 result = 1; 372 }
382 break; 373
383 } 374 free(expected);
384 375 return result;
385 free (expected);
386 return result;
387} 376}
388 377
389void 378void handle_curl_option_return_code(CURLcode res, const char *option) {
390handle_curl_option_return_code (CURLcode res, const char* option) 379 if (res != CURLE_OK) {
391{ 380 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Error while setting cURL option '%s': cURL returned %d - %s"), option, res,
392 if (res != CURLE_OK) { 381 curl_easy_strerror(res));
393 snprintf (msg, 382 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
394 DEFAULT_BUFFER_SIZE, 383 }
395 _("Error while setting cURL option '%s': cURL returned %d - %s"),
396 option,
397 res,
398 curl_easy_strerror(res));
399 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
400 }
401} 384}
402 385
403int 386int lookup_host(const char *host, char *buf, size_t buflen) {
404lookup_host (const char *host, char *buf, size_t buflen) 387 struct addrinfo hints, *res, *result;
405{ 388 char addrstr[100];
406 struct addrinfo hints, *res, *result; 389 size_t addrstr_len;
407 char addrstr[100]; 390 int errcode;
408 size_t addrstr_len; 391 void *ptr = {0};
409 int errcode; 392 size_t buflen_remaining = buflen - 1;
410 void *ptr = { 0 }; 393
411 size_t buflen_remaining = buflen - 1; 394 memset(&hints, 0, sizeof(hints));
412 395 hints.ai_family = address_family;
413 memset (&hints, 0, sizeof (hints)); 396 hints.ai_socktype = SOCK_STREAM;
414 hints.ai_family = address_family; 397 hints.ai_flags |= AI_CANONNAME;
415 hints.ai_socktype = SOCK_STREAM; 398
416 hints.ai_flags |= AI_CANONNAME; 399 errcode = getaddrinfo(host, NULL, &hints, &result);
417 400 if (errcode != 0)
418 errcode = getaddrinfo (host, NULL, &hints, &result); 401 return errcode;
419 if (errcode != 0) 402
420 return errcode; 403 strcpy(buf, "");
421 404 res = result;
422 strcpy(buf, ""); 405
423 res = result; 406 while (res) {
424 407 switch (res->ai_family) {
425 while (res) { 408 case AF_INET:
426 switch (res->ai_family) { 409 ptr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
427 case AF_INET: 410 break;
428 ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr; 411 case AF_INET6:
429 break; 412 ptr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
430 case AF_INET6: 413 break;
431 ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; 414 }
432 break; 415
433 } 416 inet_ntop(res->ai_family, ptr, addrstr, 100);
434 417 if (verbose >= 1) {
435 inet_ntop (res->ai_family, ptr, addrstr, 100); 418 printf("* getaddrinfo IPv%d address: %s\n", res->ai_family == PF_INET6 ? 6 : 4, addrstr);
436 if (verbose >= 1) { 419 }
437 printf ("* getaddrinfo IPv%d address: %s\n", 420
438 res->ai_family == PF_INET6 ? 6 : 4, addrstr); 421 // Append all IPs to buf as a comma-separated string
439 } 422 addrstr_len = strlen(addrstr);
440 423 if (buflen_remaining > addrstr_len + 1) {
441 // Append all IPs to buf as a comma-separated string 424 if (buf[0] != '\0') {
442 addrstr_len = strlen(addrstr); 425 strncat(buf, ",", buflen_remaining);
443 if (buflen_remaining > addrstr_len + 1) { 426 buflen_remaining -= 1;
444 if (buf[0] != '\0') { 427 }
445 strncat(buf, ",", buflen_remaining); 428 strncat(buf, addrstr, buflen_remaining);
446 buflen_remaining -= 1; 429 buflen_remaining -= addrstr_len;
447 } 430 }
448 strncat(buf, addrstr, buflen_remaining); 431
449 buflen_remaining -= addrstr_len; 432 res = res->ai_next;
450 } 433 }
451 434
452 res = res->ai_next; 435 freeaddrinfo(result);
453 } 436
454 437 return 0;
455 freeaddrinfo(result);
456
457 return 0;
458} 438}
459 439
460static void 440static void cleanup(void) {
461cleanup (void) 441 if (status_line_initialized)
462{ 442 curlhelp_free_statusline(&status_line);
463 if (status_line_initialized) curlhelp_free_statusline(&status_line); 443 status_line_initialized = false;
464 status_line_initialized = false; 444 if (curl_easy_initialized)
465 if (curl_easy_initialized) curl_easy_cleanup (curl); 445 curl_easy_cleanup(curl);
466 curl_easy_initialized = false; 446 curl_easy_initialized = false;
467 if (curl_global_initialized) curl_global_cleanup (); 447 if (curl_global_initialized)
468 curl_global_initialized = false; 448 curl_global_cleanup();
469 if (body_buf_initialized) curlhelp_freewritebuffer (&body_buf); 449 curl_global_initialized = false;
470 body_buf_initialized = false; 450 if (body_buf_initialized)
471 if (header_buf_initialized) curlhelp_freewritebuffer (&header_buf); 451 curlhelp_freewritebuffer(&body_buf);
472 header_buf_initialized = false; 452 body_buf_initialized = false;
473 if (put_buf_initialized) curlhelp_freereadbuffer (&put_buf); 453 if (header_buf_initialized)
474 put_buf_initialized = false; 454 curlhelp_freewritebuffer(&header_buf);
455 header_buf_initialized = false;
456 if (put_buf_initialized)
457 curlhelp_freereadbuffer(&put_buf);
458 put_buf_initialized = false;
475} 459}
476 460
477int 461int check_http(void) {
478check_http (void) 462 int result = STATE_OK;
479{ 463 int result_ssl = STATE_OK;
480 int result = STATE_OK; 464 int page_len = 0;
481 int result_ssl = STATE_OK; 465 int i;
482 int page_len = 0; 466 char *force_host_header = NULL;
483 int i; 467 struct curl_slist *host = NULL;
484 char *force_host_header = NULL; 468 char addrstr[DEFAULT_BUFFER_SIZE / 2];
485 struct curl_slist *host = NULL; 469 char dnscache[DEFAULT_BUFFER_SIZE];
486 char addrstr[DEFAULT_BUFFER_SIZE/2]; 470
487 char dnscache[DEFAULT_BUFFER_SIZE]; 471 /* initialize curl */
488 472 if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK)
489 /* initialize curl */ 473 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n");
490 if (curl_global_init (CURL_GLOBAL_DEFAULT) != CURLE_OK) 474 curl_global_initialized = true;
491 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n"); 475
492 curl_global_initialized = true; 476 if ((curl = curl_easy_init()) == NULL) {
493 477 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n");
494 if ((curl = curl_easy_init()) == NULL) { 478 }
495 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n"); 479 curl_easy_initialized = true;
496 } 480
497 curl_easy_initialized = true; 481 /* register cleanup function to shut down libcurl properly */
498 482 atexit(cleanup);
499 /* register cleanup function to shut down libcurl properly */ 483
500 atexit (cleanup); 484 if (verbose >= 1)
501 485 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_VERBOSE, 1), "CURLOPT_VERBOSE");
502 if (verbose >= 1) 486
503 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_VERBOSE, 1), "CURLOPT_VERBOSE"); 487 /* print everything on stdout like check_http would do */
504 488 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_STDERR, stdout), "CURLOPT_STDERR");
505 /* print everything on stdout like check_http would do */ 489
506 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_STDERR, stdout), "CURLOPT_STDERR"); 490 if (automatic_decompression)
507
508 if (automatic_decompression)
509#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) 491#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6)
510 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""), "CURLOPT_ACCEPT_ENCODING"); 492 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""), "CURLOPT_ACCEPT_ENCODING");
511#else 493#else
512 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_ENCODING, ""), "CURLOPT_ENCODING"); 494 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ENCODING, ""), "CURLOPT_ENCODING");
513#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */ 495#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */
514 496
515 /* initialize buffer for body of the answer */ 497 /* initialize buffer for body of the answer */
516 if (curlhelp_initwritebuffer(&body_buf) < 0) 498 if (curlhelp_initwritebuffer(&body_buf) < 0)
517 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n"); 499 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n");
518 body_buf_initialized = true; 500 body_buf_initialized = true;
519 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback), "CURLOPT_WRITEFUNCTION"); 501 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback),
520 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)&body_buf), "CURLOPT_WRITEDATA"); 502 "CURLOPT_WRITEFUNCTION");
521 503 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&body_buf), "CURLOPT_WRITEDATA");
522 /* initialize buffer for header of the answer */ 504
523 if (curlhelp_initwritebuffer( &header_buf ) < 0) 505 /* initialize buffer for header of the answer */
524 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n" ); 506 if (curlhelp_initwritebuffer(&header_buf) < 0)
525 header_buf_initialized = true; 507 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n");
526 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback), "CURLOPT_HEADERFUNCTION"); 508 header_buf_initialized = true;
527 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEHEADER, (void *)&header_buf), "CURLOPT_WRITEHEADER"); 509 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback),
528 510 "CURLOPT_HEADERFUNCTION");
529 /* set the error buffer */ 511 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEHEADER, (void *)&header_buf), "CURLOPT_WRITEHEADER");
530 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, errbuf), "CURLOPT_ERRORBUFFER"); 512
531 513 /* set the error buffer */
532 /* set timeouts */ 514 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf), "CURLOPT_ERRORBUFFER");
533 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, socket_timeout), "CURLOPT_CONNECTTIMEOUT"); 515
534 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_TIMEOUT, socket_timeout), "CURLOPT_TIMEOUT"); 516 /* set timeouts */
535 517 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, socket_timeout), "CURLOPT_CONNECTTIMEOUT");
536 /* enable haproxy protocol */ 518 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_TIMEOUT, socket_timeout), "CURLOPT_TIMEOUT");
537 if (haproxy_protocol) { 519
538 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L), "CURLOPT_HAPROXYPROTOCOL"); 520 /* enable haproxy protocol */
539 } 521 if (haproxy_protocol) {
540 522 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L), "CURLOPT_HAPROXYPROTOCOL");
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 523 }
542 if(use_ssl && host_name != NULL) { 524
543 if ( (res=lookup_host (server_address, addrstr, DEFAULT_BUFFER_SIZE/2)) != 0) { 525 // fill dns resolve cache to make curl connect to the given server_address instead of the host_name, only required for ssl, because we
544 snprintf (msg, 526 // use the host_name later on to make SNI happy
545 DEFAULT_BUFFER_SIZE, 527 if (use_ssl && host_name != NULL) {
546 _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"), 528 if ((res = lookup_host(server_address, addrstr, DEFAULT_BUFFER_SIZE / 2)) != 0) {
547 server_address, 529 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"), server_address, res,
548 res, 530 gai_strerror(res));
549 gai_strerror (res)); 531 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
550 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 532 }
551 } 533 snprintf(dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, addrstr);
552 snprintf (dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, addrstr); 534 host = curl_slist_append(NULL, dnscache);
553 host = curl_slist_append(NULL, dnscache); 535 curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
554 curl_easy_setopt(curl, CURLOPT_RESOLVE, host); 536 if (verbose >= 1)
555 if (verbose>=1) 537 printf("* curl CURLOPT_RESOLVE: %s\n", dnscache);
556 printf ("* curl CURLOPT_RESOLVE: %s\n", dnscache); 538 }
557 } 539
558 540 // If server_address is an IPv6 address it must be surround by square brackets
559 // If server_address is an IPv6 address it must be surround by square brackets 541 struct in6_addr tmp_in_addr;
560 struct in6_addr tmp_in_addr; 542 if (inet_pton(AF_INET6, server_address, &tmp_in_addr) == 1) {
561 if (inet_pton(AF_INET6, server_address, &tmp_in_addr) == 1) { 543 char *new_server_address = malloc(strlen(server_address) + 3);
562 char *new_server_address = malloc(strlen(server_address) + 3); 544 if (new_server_address == NULL) {
563 if (new_server_address == NULL) { 545 die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n");
564 die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n"); 546 }
565 } 547 snprintf(new_server_address, strlen(server_address) + 3, "[%s]", server_address);
566 snprintf(new_server_address, strlen(server_address)+3, "[%s]", server_address); 548 free(server_address);
567 free(server_address); 549 server_address = new_server_address;
568 server_address = new_server_address; 550 }
569 } 551
570 552 /* compose URL: use the address we want to connect to, set Host: header later */
571 /* compose URL: use the address we want to connect to, set Host: header later */ 553 snprintf(url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", use_ssl ? "https" : "http",
572 snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", 554 (use_ssl & (host_name != NULL)) ? host_name : server_address, server_port, server_url);
573 use_ssl ? "https" : "http", 555
574 ( use_ssl & ( host_name != NULL ) ) ? host_name : server_address, 556 if (verbose >= 1)
575 server_port, 557 printf("* curl CURLOPT_URL: %s\n", url);
576 server_url 558 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_URL, url), "CURLOPT_URL");
577 ); 559
578 560 /* extract proxy information for legacy proxy https requests */
579 if (verbose>=1) 561 if (!strcmp(http_method, "CONNECT") || strstr(server_url, "http") == server_url) {
580 printf ("* curl CURLOPT_URL: %s\n", url); 562 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_PROXY, server_address), "CURLOPT_PROXY");
581 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_URL, url), "CURLOPT_URL"); 563 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_PROXYPORT, (long)server_port), "CURLOPT_PROXYPORT");
582 564 if (verbose >= 2)
583 /* extract proxy information for legacy proxy https requests */ 565 printf("* curl CURLOPT_PROXY: %s:%d\n", server_address, server_port);
584 if (!strcmp(http_method, "CONNECT") || strstr(server_url, "http") == server_url) { 566 http_method = "GET";
585 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_PROXY, server_address), "CURLOPT_PROXY"); 567 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_URL, server_url), "CURLOPT_URL");
586 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_PROXYPORT, (long)server_port), "CURLOPT_PROXYPORT"); 568 }
587 if (verbose>=2) 569
588 printf ("* curl CURLOPT_PROXY: %s:%d\n", server_address, server_port); 570 /* disable body for HEAD request */
589 http_method = "GET"; 571 if (http_method && !strcmp(http_method, "HEAD")) {
590 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_URL, server_url), "CURLOPT_URL"); 572 no_body = true;
591 } 573 }
592 574
593 /* disable body for HEAD request */ 575 /* set HTTP protocol version */
594 if (http_method && !strcmp (http_method, "HEAD" )) { 576 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, curl_http_version), "CURLOPT_HTTP_VERSION");
595 no_body = true; 577
596 } 578 /* set HTTP method */
597 579 if (http_method) {
598 /* set HTTP protocol version */ 580 if (!strcmp(http_method, "POST"))
599 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_HTTP_VERSION, curl_http_version), "CURLOPT_HTTP_VERSION"); 581 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_POST, 1), "CURLOPT_POST");
600 582 else if (!strcmp(http_method, "PUT"))
601 /* set HTTP method */ 583 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_UPLOAD, 1), "CURLOPT_UPLOAD");
602 if (http_method) { 584 else
603 if (!strcmp(http_method, "POST")) 585 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_method), "CURLOPT_CUSTOMREQUEST");
604 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_POST, 1), "CURLOPT_POST"); 586 }
605 else if (!strcmp(http_method, "PUT")) 587
606 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_UPLOAD, 1), "CURLOPT_UPLOAD"); 588 /* check if Host header is explicitly set in options */
607 else 589 if (http_opt_headers_count) {
608 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CUSTOMREQUEST, http_method), "CURLOPT_CUSTOMREQUEST"); 590 for (i = 0; i < http_opt_headers_count; i++) {
609 } 591 if (strncmp(http_opt_headers[i], "Host:", 5) == 0) {
610 592 force_host_header = http_opt_headers[i];
611 /* check if Host header is explicitly set in options */ 593 }
612 if (http_opt_headers_count) { 594 }
613 for (i = 0; i < http_opt_headers_count ; i++) { 595 }
614 if (strncmp(http_opt_headers[i], "Host:", 5) == 0) { 596
615 force_host_header = http_opt_headers[i]; 597 /* set hostname (virtual hosts), not needed if CURLOPT_CONNECT_TO is used, but left in anyway */
616 } 598 if (host_name != NULL && force_host_header == NULL) {
617 } 599 if ((virtual_port != HTTP_PORT && !use_ssl) || (virtual_port != HTTPS_PORT && use_ssl)) {
618 } 600 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", host_name, virtual_port);
619 601 } else {
620 /* set hostname (virtual hosts), not needed if CURLOPT_CONNECT_TO is used, but left in anyway */ 602 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s", host_name);
621 if(host_name != NULL && force_host_header == NULL) { 603 }
622 if((virtual_port != HTTP_PORT && !use_ssl) || (virtual_port != HTTPS_PORT && use_ssl)) { 604 header_list = curl_slist_append(header_list, http_header);
623 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", host_name, virtual_port); 605 }
624 } else { 606
625 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s", host_name); 607 /* always close connection, be nice to servers */
626 } 608 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Connection: close");
627 header_list = curl_slist_append (header_list, http_header); 609 header_list = curl_slist_append(header_list, http_header);
628 } 610
629 611 /* attach additional headers supplied by the user */
630 /* always close connection, be nice to servers */ 612 /* optionally send any other header tag */
631 snprintf (http_header, DEFAULT_BUFFER_SIZE, "Connection: close"); 613 if (http_opt_headers_count) {
632 header_list = curl_slist_append (header_list, http_header); 614 for (i = 0; i < http_opt_headers_count; i++) {
633 615 header_list = curl_slist_append(header_list, http_opt_headers[i]);
634 /* attach additional headers supplied by the user */ 616 }
635 /* optionally send any other header tag */ 617 /* This cannot be free'd here because a redirection will then try to access this and segfault */
636 if (http_opt_headers_count) { 618 /* Covered in a testcase in tests/check_http.t */
637 for (i = 0; i < http_opt_headers_count ; i++) { 619 /* free(http_opt_headers); */
638 header_list = curl_slist_append (header_list, http_opt_headers[i]); 620 }
639 } 621
640 /* This cannot be free'd here because a redirection will then try to access this and segfault */ 622 /* set HTTP headers */
641 /* Covered in a testcase in tests/check_http.t */ 623 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list), "CURLOPT_HTTPHEADER");
642 /* free(http_opt_headers); */
643 }
644
645 /* set HTTP headers */
646 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_HTTPHEADER, header_list ), "CURLOPT_HTTPHEADER");
647 624
648#ifdef LIBCURL_FEATURE_SSL 625#ifdef LIBCURL_FEATURE_SSL
649 626
650 /* set SSL version, warn about insecure or unsupported versions */ 627 /* set SSL version, warn about insecure or unsupported versions */
651 if (use_ssl) { 628 if (use_ssl) {
652 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLVERSION, ssl_version), "CURLOPT_SSLVERSION"); 629 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSLVERSION, ssl_version), "CURLOPT_SSLVERSION");
653 } 630 }
654 631
655 /* client certificate and key to present to server (SSL) */ 632 /* client certificate and key to present to server (SSL) */
656 if (client_cert) 633 if (client_cert)
657 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLCERT, client_cert), "CURLOPT_SSLCERT"); 634 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSLCERT, client_cert), "CURLOPT_SSLCERT");
658 if (client_privkey) 635 if (client_privkey)
659 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLKEY, client_privkey), "CURLOPT_SSLKEY"); 636 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSLKEY, client_privkey), "CURLOPT_SSLKEY");
660 if (ca_cert) { 637 if (ca_cert) {
661 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CAINFO, ca_cert), "CURLOPT_CAINFO"); 638 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CAINFO, ca_cert), "CURLOPT_CAINFO");
662 } 639 }
663 if (ca_cert || verify_peer_and_host) { 640 if (ca_cert || verify_peer_and_host) {
664 /* per default if we have a CA verify both the peer and the 641 /* per default if we have a CA verify both the peer and the
665 * hostname in the certificate, can be switched off later */ 642 * hostname in the certificate, can be switched off later */
666 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 1), "CURLOPT_SSL_VERIFYPEER"); 643 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1), "CURLOPT_SSL_VERIFYPEER");
667 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYHOST, 2), "CURLOPT_SSL_VERIFYHOST"); 644 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2), "CURLOPT_SSL_VERIFYHOST");
668 } else { 645 } else {
669 /* backward-compatible behaviour, be tolerant in checks 646 /* backward-compatible behaviour, be tolerant in checks
670 * TODO: depending on more options have aspects we want 647 * TODO: depending on more options have aspects we want
671 * to be less tolerant about ssl verfications 648 * to be less tolerant about ssl verfications
672 */ 649 */
673 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0), "CURLOPT_SSL_VERIFYPEER"); 650 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0), "CURLOPT_SSL_VERIFYPEER");
674 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0), "CURLOPT_SSL_VERIFYHOST"); 651 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0), "CURLOPT_SSL_VERIFYHOST");
675 } 652 }
676 653
677 /* detect SSL library used by libcurl */ 654 /* detect SSL library used by libcurl */
678 ssl_library = curlhelp_get_ssl_library (); 655 ssl_library = curlhelp_get_ssl_library();
679 656
680 /* try hard to get a stack of certificates to verify against */ 657 /* try hard to get a stack of certificates to verify against */
681 if (check_cert) { 658 if (check_cert) {
682#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) 659# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1)
683 /* inform curl to report back certificates */ 660 /* inform curl to report back certificates */
684 switch (ssl_library) { 661 switch (ssl_library) {
685 case CURLHELP_SSL_LIBRARY_OPENSSL: 662 case CURLHELP_SSL_LIBRARY_OPENSSL:
686 case CURLHELP_SSL_LIBRARY_LIBRESSL: 663 case CURLHELP_SSL_LIBRARY_LIBRESSL:
687 /* set callback to extract certificate with OpenSSL context function (works with 664 /* set callback to extract certificate with OpenSSL context function (works with
688 * OpenSSL-style libraries only!) */ 665 * OpenSSL-style libraries only!) */
689#ifdef USE_OPENSSL 666# ifdef USE_OPENSSL
690 /* libcurl and monitoring plugins built with OpenSSL, good */ 667 /* libcurl and monitoring plugins built with OpenSSL, good */
691 add_sslctx_verify_fun = true; 668 add_sslctx_verify_fun = true;
692 is_openssl_callback = true; 669 is_openssl_callback = true;
693#endif /* USE_OPENSSL */ 670# endif /* USE_OPENSSL */
694 /* libcurl is built with OpenSSL, monitoring plugins, so falling 671 /* libcurl is built with OpenSSL, monitoring plugins, so falling
695 * back to manually extracting certificate information */ 672 * back to manually extracting certificate information */
696 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 673 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
697 break; 674 break;
698 675
699 case CURLHELP_SSL_LIBRARY_NSS: 676 case CURLHELP_SSL_LIBRARY_NSS:
700#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 677# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
701 /* NSS: support for CERTINFO is implemented since 7.34.0 */ 678 /* NSS: support for CERTINFO is implemented since 7.34.0 */
702 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 679 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
703#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 680# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
704 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n", curlhelp_get_ssl_library_string (ssl_library)); 681 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n",
705#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 682 curlhelp_get_ssl_library_string(ssl_library));
706 break; 683# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
707 684 break;
708 case CURLHELP_SSL_LIBRARY_GNUTLS: 685
709#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) 686 case CURLHELP_SSL_LIBRARY_GNUTLS:
710 /* GnuTLS: support for CERTINFO is implemented since 7.42.0 */ 687# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0)
711 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 688 /* GnuTLS: support for CERTINFO is implemented since 7.42.0 */
712#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */ 689 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
713 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n", curlhelp_get_ssl_library_string (ssl_library)); 690# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */
714#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */ 691 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n",
715 break; 692 curlhelp_get_ssl_library_string(ssl_library));
716 693# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */
717 case CURLHELP_SSL_LIBRARY_UNKNOWN: 694 break;
718 default: 695
719 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (unknown SSL library '%s', must implement first)\n", curlhelp_get_ssl_library_string (ssl_library)); 696 case CURLHELP_SSL_LIBRARY_UNKNOWN:
720 break; 697 default:
721 } 698 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (unknown SSL library '%s', must implement first)\n",
722#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ 699 curlhelp_get_ssl_library_string(ssl_library));
723 /* old libcurl, our only hope is OpenSSL, otherwise we are out of luck */ 700 break;
724 if (ssl_library == CURLHELP_SSL_LIBRARY_OPENSSL || ssl_library == CURLHELP_SSL_LIBRARY_LIBRESSL) 701 }
725 add_sslctx_verify_fun = true; 702# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */
726 else 703 /* old libcurl, our only hope is OpenSSL, otherwise we are out of luck */
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"); 704 if (ssl_library == CURLHELP_SSL_LIBRARY_OPENSSL || ssl_library == CURLHELP_SSL_LIBRARY_LIBRESSL)
728#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ 705 add_sslctx_verify_fun = true;
729 } 706 else
730 707 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (no CURLOPT_SSL_CTX_FUNCTION, no OpenSSL library or libcurl "
731#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 10, 6) /* required for CURLOPT_SSL_CTX_FUNCTION */ 708 "too old and has no CURLOPT_CERTINFO)\n");
732 // ssl ctx function is not available with all ssl backends 709# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */
733 if (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, NULL) != CURLE_UNKNOWN_OPTION) 710 }
734 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); 711
735#endif 712# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 10, 6) /* required for CURLOPT_SSL_CTX_FUNCTION */
713 // ssl ctx function is not available with all ssl backends
714 if (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, NULL) != CURLE_UNKNOWN_OPTION)
715 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION");
716# endif
736 717
737#endif /* LIBCURL_FEATURE_SSL */ 718#endif /* LIBCURL_FEATURE_SSL */
738 719
739 /* set default or user-given user agent identification */ 720 /* set default or user-given user agent identification */
740 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_USERAGENT, user_agent), "CURLOPT_USERAGENT"); 721 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_USERAGENT, user_agent), "CURLOPT_USERAGENT");
741 722
742 /* proxy-authentication */ 723 /* proxy-authentication */
743 if (strcmp(proxy_auth, "")) 724 if (strcmp(proxy_auth, ""))
744 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_PROXYUSERPWD, proxy_auth), "CURLOPT_PROXYUSERPWD"); 725 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxy_auth), "CURLOPT_PROXYUSERPWD");
745 726
746 /* authentication */ 727 /* authentication */
747 if (strcmp(user_auth, "")) 728 if (strcmp(user_auth, ""))
748 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_USERPWD, user_auth), "CURLOPT_USERPWD"); 729 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_USERPWD, user_auth), "CURLOPT_USERPWD");
749 730
750 /* TODO: parameter auth method, bitfield of following methods: 731 /* TODO: parameter auth method, bitfield of following methods:
751 * CURLAUTH_BASIC (default) 732 * CURLAUTH_BASIC (default)
752 * CURLAUTH_DIGEST 733 * CURLAUTH_DIGEST
753 * CURLAUTH_DIGEST_IE 734 * CURLAUTH_DIGEST_IE
754 * CURLAUTH_NEGOTIATE 735 * CURLAUTH_NEGOTIATE
755 * CURLAUTH_NTLM 736 * CURLAUTH_NTLM
756 * CURLAUTH_NTLM_WB 737 * CURLAUTH_NTLM_WB
757 * 738 *
758 * convenience tokens for typical sets of methods: 739 * convenience tokens for typical sets of methods:
759 * CURLAUTH_ANYSAFE: most secure, without BASIC 740 * CURLAUTH_ANYSAFE: most secure, without BASIC
760 * or CURLAUTH_ANY: most secure, even BASIC if necessary 741 * or CURLAUTH_ANY: most secure, even BASIC if necessary
761 * 742 *
762 * handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_DIGEST ), "CURLOPT_HTTPAUTH"); 743 * handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_DIGEST ), "CURLOPT_HTTPAUTH");
763 */ 744 */
764 745
765 /* handle redirections */ 746 /* handle redirections */
766 if (onredirect == STATE_DEPENDENT) { 747 if (onredirect == STATE_DEPENDENT) {
767 if( followmethod == FOLLOW_LIBCURL ) { 748 if (followmethod == FOLLOW_LIBCURL) {
768 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1), "CURLOPT_FOLLOWLOCATION"); 749 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1), "CURLOPT_FOLLOWLOCATION");
769 750
770 /* default -1 is infinite, not good, could lead to zombie plugins! 751 /* default -1 is infinite, not good, could lead to zombie plugins!
771 Setting it to one bigger than maximal limit to handle errors nicely below 752 Setting it to one bigger than maximal limit to handle errors nicely below
772 */ 753 */
773 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_MAXREDIRS, max_depth+1), "CURLOPT_MAXREDIRS"); 754 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_MAXREDIRS, max_depth + 1), "CURLOPT_MAXREDIRS");
774 755
775 /* for now allow only http and https (we are a http(s) check plugin in the end) */ 756 /* for now allow only http and https (we are a http(s) check plugin in the end) */
776#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 85, 0) 757#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 85, 0)
777 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https"), "CURLOPT_REDIR_PROTOCOLS_STR"); 758 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https"),
759 "CURLOPT_REDIR_PROTOCOLS_STR");
778#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4) 760#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4)
779 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS), "CURLOPT_REDIRECT_PROTOCOLS"); 761 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS),
762 "CURLOPT_REDIRECT_PROTOCOLS");
780#endif 763#endif
781 764
782 /* TODO: handle the following aspects of redirection, make them 765 /* TODO: handle the following aspects of redirection, make them
783 * command line options too later: 766 * command line options too later:
784 CURLOPT_POSTREDIR: method switch 767 CURLOPT_POSTREDIR: method switch
785 CURLINFO_REDIRECT_URL: custom redirect option 768 CURLINFO_REDIRECT_URL: custom redirect option
786 CURLOPT_REDIRECT_PROTOCOLS: allow people to step outside safe protocols 769 CURLOPT_REDIRECT_PROTOCOLS: allow people to step outside safe protocols
787 CURLINFO_REDIRECT_COUNT: get the number of redirects, print it, maybe a range option here is nice like for expected page size? 770 CURLINFO_REDIRECT_COUNT: get the number of redirects, print it, maybe a range option here is nice like for expected page size?
788 */ 771 */
789 } else { 772 } else {
790 /* old style redirection is handled below */ 773 /* old style redirection is handled below */
791 } 774 }
792 } 775 }
793 776
794 /* no-body */ 777 /* no-body */
795 if (no_body) 778 if (no_body)
796 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_NOBODY, 1), "CURLOPT_NOBODY"); 779 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_NOBODY, 1), "CURLOPT_NOBODY");
797 780
798 /* IPv4 or IPv6 forced DNS resolution */ 781 /* IPv4 or IPv6 forced DNS resolution */
799 if (address_family == AF_UNSPEC) 782 if (address_family == AF_UNSPEC)
800 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER), "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_WHATEVER)"); 783 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER),
801 else if (address_family == AF_INET) 784 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_WHATEVER)");
802 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4), "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)"); 785 else if (address_family == AF_INET)
803#if defined (USE_IPV6) && defined (LIBCURL_FEATURE_IPV6) 786 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4),
804 else if (address_family == AF_INET6) 787 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)");
805 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6), "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V6)"); 788#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6)
789 else if (address_family == AF_INET6)
790 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6),
791 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V6)");
806#endif 792#endif
807 793
808 /* either send http POST data (any data, not only POST)*/ 794 /* either send http POST data (any data, not only POST)*/
809 if (!strcmp(http_method, "POST") ||!strcmp(http_method, "PUT")) { 795 if (!strcmp(http_method, "POST") || !strcmp(http_method, "PUT")) {
810 /* set content of payload for POST and PUT */ 796 /* set content of payload for POST and PUT */
811 if (http_content_type) { 797 if (http_content_type) {
812 snprintf (http_header, DEFAULT_BUFFER_SIZE, "Content-Type: %s", http_content_type); 798 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Content-Type: %s", http_content_type);
813 header_list = curl_slist_append (header_list, http_header); 799 header_list = curl_slist_append(header_list, http_header);
814 } 800 }
815 /* NULL indicates "HTTP Continue" in libcurl, provide an empty string 801 /* NULL indicates "HTTP Continue" in libcurl, provide an empty string
816 * in case of no POST/PUT data */ 802 * in case of no POST/PUT data */
817 if (!http_post_data) 803 if (!http_post_data)
818 http_post_data = ""; 804 http_post_data = "";
819 if (!strcmp(http_method, "POST")) { 805 if (!strcmp(http_method, "POST")) {
820 /* POST method, set payload with CURLOPT_POSTFIELDS */ 806 /* POST method, set payload with CURLOPT_POSTFIELDS */
821 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_POSTFIELDS, http_post_data), "CURLOPT_POSTFIELDS"); 807 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_POSTFIELDS, http_post_data), "CURLOPT_POSTFIELDS");
822 } else if (!strcmp(http_method, "PUT")) { 808 } else if (!strcmp(http_method, "PUT")) {
823 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_READFUNCTION, (curl_read_callback)curlhelp_buffer_read_callback), "CURLOPT_READFUNCTION"); 809 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_READFUNCTION, (curl_read_callback)curlhelp_buffer_read_callback),
824 if (curlhelp_initreadbuffer (&put_buf, http_post_data, strlen (http_post_data)) < 0) 810 "CURLOPT_READFUNCTION");
825 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating read buffer for PUT\n"); 811 if (curlhelp_initreadbuffer(&put_buf, http_post_data, strlen(http_post_data)) < 0)
826 put_buf_initialized = true; 812 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating read buffer for PUT\n");
827 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_READDATA, (void *)&put_buf), "CURLOPT_READDATA"); 813 put_buf_initialized = true;
828 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_INFILESIZE, (curl_off_t)strlen (http_post_data)), "CURLOPT_INFILESIZE"); 814 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_READDATA, (void *)&put_buf), "CURLOPT_READDATA");
829 } 815 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_INFILESIZE, (curl_off_t)strlen(http_post_data)),
830 } 816 "CURLOPT_INFILESIZE");
831 817 }
832 /* cookie handling */ 818 }
833 if (cookie_jar_file != NULL) { 819
834 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_COOKIEJAR, cookie_jar_file), "CURLOPT_COOKIEJAR"); 820 /* cookie handling */
835 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_COOKIEFILE, cookie_jar_file), "CURLOPT_COOKIEFILE"); 821 if (cookie_jar_file != NULL) {
836 } 822 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookie_jar_file), "CURLOPT_COOKIEJAR");
837 823 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookie_jar_file), "CURLOPT_COOKIEFILE");
838 /* do the request */ 824 }
839 res = curl_easy_perform(curl); 825
840 826 /* do the request */
841 if (verbose>=2 && http_post_data) 827 res = curl_easy_perform(curl);
842 printf ("**** REQUEST CONTENT ****\n%s\n", http_post_data); 828
843 829 if (verbose >= 2 && http_post_data)
844 /* free header and server IP resolve lists, we don't need it anymore */ 830 printf("**** REQUEST CONTENT ****\n%s\n", http_post_data);
845 curl_slist_free_all (header_list); header_list = NULL; 831
846 curl_slist_free_all (server_ips); server_ips = NULL; 832 /* free header and server IP resolve lists, we don't need it anymore */
847 if (host) { 833 curl_slist_free_all(header_list);
848 curl_slist_free_all (host); host = NULL; 834 header_list = NULL;
849 } 835 curl_slist_free_all(server_ips);
850 836 server_ips = NULL;
851 /* Curl errors, result in critical Nagios state */ 837 if (host) {
852 if (res != CURLE_OK) { 838 curl_slist_free_all(host);
853 snprintf (msg, 839 host = NULL;
854 DEFAULT_BUFFER_SIZE, 840 }
855 _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"), 841
856 server_port, 842 /* Curl errors, result in critical Nagios state */
857 res, 843 if (res != CURLE_OK) {
858 errbuf[0] ? errbuf : curl_easy_strerror(res)); 844 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"), server_port,
859 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 845 res, errbuf[0] ? errbuf : curl_easy_strerror(res));
860 } 846 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
861 847 }
862 /* certificate checks */ 848
849 /* certificate checks */
863#ifdef LIBCURL_FEATURE_SSL 850#ifdef LIBCURL_FEATURE_SSL
864 if (use_ssl) { 851 if (use_ssl) {
865 if (check_cert) { 852 if (check_cert) {
866 if (is_openssl_callback) { 853 if (is_openssl_callback) {
867#ifdef USE_OPENSSL 854# ifdef USE_OPENSSL
868 /* check certificate with OpenSSL functions, curl has been built against OpenSSL 855 /* check certificate with OpenSSL functions, curl has been built against OpenSSL
869 * and we actually have OpenSSL in the monitoring tools 856 * and we actually have OpenSSL in the monitoring tools
870 */ 857 */
871 result_ssl = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); 858 result_ssl = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
872 if (!continue_after_check_cert) { 859 if (!continue_after_check_cert) {
873 return result_ssl; 860 return result_ssl;
874 } 861 }
875#else /* USE_OPENSSL */ 862# else /* USE_OPENSSL */
876 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n"); 863 die(STATE_CRITICAL,
877#endif /* USE_OPENSSL */ 864 "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n");
878 } else { 865# endif /* USE_OPENSSL */
879 int i; 866 } else {
880 struct curl_slist *slist; 867 int i;
881 868 struct curl_slist *slist;
882 cert_ptr.to_info = NULL; 869
883 res = curl_easy_getinfo (curl, CURLINFO_CERTINFO, &cert_ptr.to_info); 870 cert_ptr.to_info = NULL;
884 if (!res && cert_ptr.to_info) { 871 res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &cert_ptr.to_info);
885#ifdef USE_OPENSSL 872 if (!res && cert_ptr.to_info) {
886 /* We have no OpenSSL in libcurl, but we can use OpenSSL for X509 cert parsing 873# ifdef USE_OPENSSL
887 * We only check the first certificate and assume it's the one of the server 874 /* We have no OpenSSL in libcurl, but we can use OpenSSL for X509 cert parsing
888 */ 875 * We only check the first certificate and assume it's the one of the server
889 const char* raw_cert = NULL; 876 */
890 for (i = 0; i < cert_ptr.to_certinfo->num_of_certs; i++) { 877 const char *raw_cert = NULL;
891 for (slist = cert_ptr.to_certinfo->certinfo[i]; slist; slist = slist->next) { 878 for (i = 0; i < cert_ptr.to_certinfo->num_of_certs; i++) {
892 if (verbose >= 2) 879 for (slist = cert_ptr.to_certinfo->certinfo[i]; slist; slist = slist->next) {
893 printf ("%d ** %s\n", i, slist->data); 880 if (verbose >= 2)
894 if (strncmp (slist->data, "Cert:", 5) == 0) { 881 printf("%d ** %s\n", i, slist->data);
895 raw_cert = &slist->data[5]; 882 if (strncmp(slist->data, "Cert:", 5) == 0) {
896 goto GOT_FIRST_CERT; 883 raw_cert = &slist->data[5];
897 } 884 goto GOT_FIRST_CERT;
898 } 885 }
899 } 886 }
900GOT_FIRST_CERT: 887 }
901 if (!raw_cert) { 888 GOT_FIRST_CERT:
902 snprintf (msg, 889 if (!raw_cert) {
903 DEFAULT_BUFFER_SIZE, 890 snprintf(msg, DEFAULT_BUFFER_SIZE,
904 _("Cannot retrieve certificates from CERTINFO information - certificate data was empty")); 891 _("Cannot retrieve certificates from CERTINFO information - certificate data was empty"));
905 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 892 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
906 } 893 }
907 BIO* cert_BIO = BIO_new (BIO_s_mem()); 894 BIO *cert_BIO = BIO_new(BIO_s_mem());
908 BIO_write (cert_BIO, raw_cert, strlen(raw_cert)); 895 BIO_write(cert_BIO, raw_cert, strlen(raw_cert));
909 cert = PEM_read_bio_X509 (cert_BIO, NULL, NULL, NULL); 896 cert = PEM_read_bio_X509(cert_BIO, NULL, NULL, NULL);
910 if (!cert) { 897 if (!cert) {
911 snprintf (msg, 898 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Cannot read certificate from CERTINFO information - BIO error"));
912 DEFAULT_BUFFER_SIZE, 899 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
913 _("Cannot read certificate from CERTINFO information - BIO error")); 900 }
914 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 901 BIO_free(cert_BIO);
915 } 902 result_ssl = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
916 BIO_free (cert_BIO); 903 if (!continue_after_check_cert) {
917 result_ssl = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); 904 return result_ssl;
918 if (!continue_after_check_cert) { 905 }
919 return result_ssl; 906# else /* USE_OPENSSL */
920 } 907 /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our disposal,
921#else /* USE_OPENSSL */ 908 * so we use the libcurl CURLINFO data
922 /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our disposal, 909 */
923 * so we use the libcurl CURLINFO data 910 result_ssl = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, days_till_exp_crit);
924 */ 911 if (!continue_after_check_cert) {
925 result_ssl = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, days_till_exp_crit); 912 return result_ssl;
926 if (!continue_after_check_cert) { 913 }
927 return result_ssl; 914# endif /* USE_OPENSSL */
928 } 915 } else {
929#endif /* USE_OPENSSL */ 916 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Cannot retrieve certificates - cURL returned %d - %s"), res,
930 } else { 917 curl_easy_strerror(res));
931 snprintf (msg, 918 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
932 DEFAULT_BUFFER_SIZE, 919 }
933 _("Cannot retrieve certificates - cURL returned %d - %s"), 920 }
934 res, 921 }
935 curl_easy_strerror(res)); 922 }
936 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
937 }
938 }
939 }
940 }
941#endif /* LIBCURL_FEATURE_SSL */ 923#endif /* LIBCURL_FEATURE_SSL */
942 924
943 /* we got the data and we executed the request in a given time, so we can append 925 /* we got the data and we executed the request in a given time, so we can append
944 * performance data to the answer always 926 * performance data to the answer always
945 */ 927 */
946 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_TOTAL_TIME, &total_time), "CURLINFO_TOTAL_TIME"); 928 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total_time), "CURLINFO_TOTAL_TIME");
947 page_len = get_content_length(&header_buf, &body_buf); 929 page_len = get_content_length(&header_buf, &body_buf);
948 if(show_extended_perfdata) { 930 if (show_extended_perfdata) {
949 handle_curl_option_return_code (curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &time_connect), "CURLINFO_CONNECT_TIME"); 931 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &time_connect), "CURLINFO_CONNECT_TIME");
950 handle_curl_option_return_code (curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, &time_appconnect), "CURLINFO_APPCONNECT_TIME"); 932 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, &time_appconnect), "CURLINFO_APPCONNECT_TIME");
951 handle_curl_option_return_code (curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &time_headers), "CURLINFO_PRETRANSFER_TIME"); 933 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &time_headers), "CURLINFO_PRETRANSFER_TIME");
952 handle_curl_option_return_code (curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &time_firstbyte), "CURLINFO_STARTTRANSFER_TIME"); 934 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &time_firstbyte),
953 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s %s %s %s %s %s", 935 "CURLINFO_STARTTRANSFER_TIME");
954 perfd_time(total_time), 936 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s %s %s %s %s %s", perfd_time(total_time), perfd_size(page_len),
955 perfd_size(page_len), 937 perfd_time_connect(time_connect), use_ssl ? perfd_time_ssl(time_appconnect - time_connect) : "",
956 perfd_time_connect(time_connect), 938 perfd_time_headers(time_headers - time_appconnect), perfd_time_firstbyte(time_firstbyte - time_headers),
957 use_ssl ? perfd_time_ssl (time_appconnect-time_connect) : "", 939 perfd_time_transfer(total_time - time_firstbyte));
958 perfd_time_headers(time_headers - time_appconnect), 940 } else {
959 perfd_time_firstbyte(time_firstbyte - time_headers), 941 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s", perfd_time(total_time), perfd_size(page_len));
960 perfd_time_transfer(total_time-time_firstbyte) 942 }
961 );
962 } else {
963 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s",
964 perfd_time(total_time),
965 perfd_size(page_len)
966 );
967 }
968
969 /* return a CRITICAL status if we couldn't read any data */
970 if (strlen(header_buf.buf) == 0 && strlen(body_buf.buf) == 0)
971 die (STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n"));
972
973 /* get status line of answer, check sanity of HTTP code */
974 if (curlhelp_parse_statusline (header_buf.buf, &status_line) < 0) {
975 snprintf (msg,
976 DEFAULT_BUFFER_SIZE,
977 "Unparsable status line in %.3g seconds response time|%s\n",
978 total_time,
979 perfstring);
980 /* we cannot know the major/minor version here for sure as we cannot parse the first line */
981 die (STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", code, msg);
982 }
983 status_line_initialized = true;
984
985 /* get result code from cURL */
986 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &code), "CURLINFO_RESPONSE_CODE");
987 if (verbose>=2)
988 printf ("* curl CURLINFO_RESPONSE_CODE is %ld\n", code);
989
990 /* print status line, header, body if verbose */
991 if (verbose >= 2) {
992 printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header_buf.buf,
993 (no_body ? " [[ skipped ]]" : body_buf.buf));
994 }
995
996 /* make sure the status line matches the response we are looking for */
997 if (!expected_statuscode(status_line.first_line, server_expect)) {
998 if (server_port == HTTP_PORT)
999 snprintf(msg,
1000 DEFAULT_BUFFER_SIZE,
1001 _("Invalid HTTP response received from host: %s\n"),
1002 status_line.first_line);
1003 else
1004 snprintf(msg,
1005 DEFAULT_BUFFER_SIZE,
1006 _("Invalid HTTP response received from host on port %d: %s\n"),
1007 server_port,
1008 status_line.first_line);
1009 die (STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg,
1010 show_body ? "\n" : "",
1011 show_body ? body_buf.buf : "");
1012 }
1013
1014 if( server_expect_yn ) {
1015 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Status line output matched \"%s\" - "), server_expect);
1016 if (verbose)
1017 printf ("%s\n",msg);
1018 result = STATE_OK;
1019 }
1020 else {
1021 /* illegal return codes result in a critical state */
1022 if (code >= 600 || code < 100) {
1023 die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"), status_line.http_code, status_line.msg);
1024 /* server errors result in a critical state */
1025 } else if (code >= 500) {
1026 result = STATE_CRITICAL;
1027 /* client errors result in a warning state */
1028 } else if (code >= 400) {
1029 result = STATE_WARNING;
1030 /* check redirected page if specified */
1031 } else if (code >= 300) {
1032 if (onredirect == STATE_DEPENDENT) {
1033 if( followmethod == FOLLOW_LIBCURL ) {
1034 code = status_line.http_code;
1035 } else {
1036 /* old check_http style redirection, if we come
1037 * back here, we are in the same status as with
1038 * the libcurl method
1039 */
1040 redir (&header_buf);
1041 }
1042 } else {
1043 /* this is a specific code in the command line to
1044 * be returned when a redirection is encountered
1045 */
1046 }
1047 result = max_state_alt (onredirect, result);
1048 /* all other codes are considered ok */
1049 } else {
1050 result = STATE_OK;
1051 }
1052 }
1053
1054 /* libcurl redirection internally, handle error states here */
1055 if( followmethod == FOLLOW_LIBCURL ) {
1056 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_REDIRECT_COUNT, &redir_depth), "CURLINFO_REDIRECT_COUNT");
1057 if (verbose >= 2)
1058 printf(_("* curl LIBINFO_REDIRECT_COUNT is %d\n"), redir_depth);
1059 if (redir_depth > max_depth) {
1060 snprintf (msg, DEFAULT_BUFFER_SIZE, "maximum redirection depth %d exceeded in libcurl",
1061 max_depth);
1062 die (STATE_WARNING, "HTTP WARNING - %s", msg);
1063 }
1064 }
1065
1066 /* check status codes, set exit status accordingly */
1067 if( status_line.http_code != code ) {
1068 die (STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"),
1069 string_statuscode (status_line.http_major, status_line.http_minor),
1070 status_line.http_code, status_line.msg, code);
1071 }
1072
1073 if (maximum_age >= 0) {
1074 result = max_state_alt(check_document_dates(&header_buf, &msg), result);
1075 }
1076
1077 /* Page and Header content checks go here */
1078
1079 if (strlen (header_expect)) {
1080 if (!strstr (header_buf.buf, header_expect)) {
1081
1082 strncpy(&output_header_search[0],header_expect,sizeof(output_header_search));
1083
1084 if(output_header_search[sizeof(output_header_search)-1]!='\0') {
1085 bcopy("...",&output_header_search[sizeof(output_header_search)-4],4);
1086 }
1087 943
1088 char tmp[DEFAULT_BUFFER_SIZE]; 944 /* return a CRITICAL status if we couldn't read any data */
945 if (strlen(header_buf.buf) == 0 && strlen(body_buf.buf) == 0)
946 die(STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n"));
1089 947
1090 snprintf (tmp, 948 /* get status line of answer, check sanity of HTTP code */
1091 DEFAULT_BUFFER_SIZE, 949 if (curlhelp_parse_statusline(header_buf.buf, &status_line) < 0) {
1092 _("%sheader '%s' not found on '%s://%s:%d%s', "), 950 snprintf(msg, DEFAULT_BUFFER_SIZE, "Unparsable status line in %.3g seconds response time|%s\n", total_time, perfstring);
1093 msg, 951 /* we cannot know the major/minor version here for sure as we cannot parse the first line */
1094 output_header_search, 952 die(STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", code, msg);
1095 use_ssl ? "https" : "http", 953 }
1096 host_name ? host_name : server_address, 954 status_line_initialized = true;
1097 server_port,
1098 server_url);
1099 955
1100 strcpy(msg, tmp); 956 /* get result code from cURL */
957 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code), "CURLINFO_RESPONSE_CODE");
958 if (verbose >= 2)
959 printf("* curl CURLINFO_RESPONSE_CODE is %ld\n", code);
960
961 /* print status line, header, body if verbose */
962 if (verbose >= 2) {
963 printf("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header_buf.buf, (no_body ? " [[ skipped ]]" : body_buf.buf));
964 }
965
966 /* make sure the status line matches the response we are looking for */
967 if (!expected_statuscode(status_line.first_line, server_expect)) {
968 if (server_port == HTTP_PORT)
969 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"), status_line.first_line);
970 else
971 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: %s\n"), server_port,
972 status_line.first_line);
973 die(STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg, show_body ? "\n" : "", show_body ? body_buf.buf : "");
974 }
975
976 if (server_expect_yn) {
977 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Status line output matched \"%s\" - "), server_expect);
978 if (verbose)
979 printf("%s\n", msg);
980 result = STATE_OK;
981 } else {
982 /* illegal return codes result in a critical state */
983 if (code >= 600 || code < 100) {
984 die(STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"), status_line.http_code, status_line.msg);
985 /* server errors result in a critical state */
986 } else if (code >= 500) {
987 result = STATE_CRITICAL;
988 /* client errors result in a warning state */
989 } else if (code >= 400) {
990 result = STATE_WARNING;
991 /* check redirected page if specified */
992 } else if (code >= 300) {
993 if (onredirect == STATE_DEPENDENT) {
994 if (followmethod == FOLLOW_LIBCURL) {
995 code = status_line.http_code;
996 } else {
997 /* old check_http style redirection, if we come
998 * back here, we are in the same status as with
999 * the libcurl method
1000 */
1001 redir(&header_buf);
1002 }
1003 } else {
1004 /* this is a specific code in the command line to
1005 * be returned when a redirection is encountered
1006 */
1007 }
1008 result = max_state_alt(onredirect, result);
1009 /* all other codes are considered ok */
1010 } else {
1011 result = STATE_OK;
1012 }
1013 }
1101 1014
1102 result = STATE_CRITICAL; 1015 /* libcurl redirection internally, handle error states here */
1103 } 1016 if (followmethod == FOLLOW_LIBCURL) {
1104 } 1017 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &redir_depth), "CURLINFO_REDIRECT_COUNT");
1018 if (verbose >= 2)
1019 printf(_("* curl LIBINFO_REDIRECT_COUNT is %d\n"), redir_depth);
1020 if (redir_depth > max_depth) {
1021 snprintf(msg, DEFAULT_BUFFER_SIZE, "maximum redirection depth %d exceeded in libcurl", max_depth);
1022 die(STATE_WARNING, "HTTP WARNING - %s", msg);
1023 }
1024 }
1105 1025
1106 if (strlen (string_expect)) { 1026 /* check status codes, set exit status accordingly */
1107 if (!strstr (body_buf.buf, string_expect)) { 1027 if (status_line.http_code != code) {
1028 die(STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"),
1029 string_statuscode(status_line.http_major, status_line.http_minor), status_line.http_code, status_line.msg, code);
1030 }
1108 1031
1109 strncpy(&output_string_search[0],string_expect,sizeof(output_string_search)); 1032 if (maximum_age >= 0) {
1033 result = max_state_alt(check_document_dates(&header_buf, &msg), result);
1034 }
1110 1035
1111 if(output_string_search[sizeof(output_string_search)-1]!='\0') { 1036 /* Page and Header content checks go here */
1112 bcopy("...",&output_string_search[sizeof(output_string_search)-4],4); 1037
1113 } 1038 if (strlen(header_expect)) {
1039 if (!strstr(header_buf.buf, header_expect)) {
1040
1041 strncpy(&output_header_search[0], header_expect, sizeof(output_header_search));
1042
1043 if (output_header_search[sizeof(output_header_search) - 1] != '\0') {
1044 bcopy("...", &output_header_search[sizeof(output_header_search) - 4], 4);
1045 }
1114 1046
1115 char tmp[DEFAULT_BUFFER_SIZE]; 1047 char tmp[DEFAULT_BUFFER_SIZE];
1116 1048
1117 snprintf (tmp, 1049 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sheader '%s' not found on '%s://%s:%d%s', "), msg, output_header_search,
1118 DEFAULT_BUFFER_SIZE, 1050 use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url);
1119 _("%sstring '%s' not found on '%s://%s:%d%s', "),
1120 msg,
1121 output_string_search,
1122 use_ssl ? "https" : "http",
1123 host_name ? host_name : server_address,
1124 server_port,
1125 server_url);
1126 1051
1127 strcpy(msg, tmp); 1052 strcpy(msg, tmp);
1128 1053
1129 result = STATE_CRITICAL; 1054 result = STATE_CRITICAL;
1130 } 1055 }
1131 } 1056 }
1132 1057
1133 if (strlen (regexp)) { 1058 if (strlen(string_expect)) {
1134 errcode = regexec (&preg, body_buf.buf, REGS, pmatch, 0); 1059 if (!strstr(body_buf.buf, string_expect)) {
1135 if ((errcode == 0 && !invert_regex) || (errcode == REG_NOMATCH && invert_regex)) { 1060
1136 /* OK - No-op to avoid changing the logic around it */ 1061 strncpy(&output_string_search[0], string_expect, sizeof(output_string_search));
1137 result = max_state_alt(STATE_OK, result); 1062
1138 } 1063 if (output_string_search[sizeof(output_string_search) - 1] != '\0') {
1139 else if ((errcode == REG_NOMATCH && !invert_regex) || (errcode == 0 && invert_regex)) { 1064 bcopy("...", &output_string_search[sizeof(output_string_search) - 4], 4);
1065 }
1066
1067 char tmp[DEFAULT_BUFFER_SIZE];
1068
1069 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sstring '%s' not found on '%s://%s:%d%s', "), msg, output_string_search,
1070 use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url);
1071
1072 strcpy(msg, tmp);
1073
1074 result = STATE_CRITICAL;
1075 }
1076 }
1077
1078 if (strlen(regexp)) {
1079 errcode = regexec(&preg, body_buf.buf, REGS, pmatch, 0);
1080 if ((errcode == 0 && !invert_regex) || (errcode == REG_NOMATCH && invert_regex)) {
1081 /* OK - No-op to avoid changing the logic around it */
1082 result = max_state_alt(STATE_OK, result);
1083 } else if ((errcode == REG_NOMATCH && !invert_regex) || (errcode == 0 && invert_regex)) {
1140 if (!invert_regex) { 1084 if (!invert_regex) {
1141 char tmp[DEFAULT_BUFFER_SIZE]; 1085 char tmp[DEFAULT_BUFFER_SIZE];
1142 1086
1143 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spattern not found, "), msg); 1087 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spattern not found, "), msg);
1144 strcpy(msg, tmp); 1088 strcpy(msg, tmp);
1145 1089
1146 } else { 1090 } else {
1147 char tmp[DEFAULT_BUFFER_SIZE]; 1091 char tmp[DEFAULT_BUFFER_SIZE];
1148 1092
1149 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spattern found, "), msg); 1093 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spattern found, "), msg);
1150 strcpy(msg, tmp); 1094 strcpy(msg, tmp);
1151
1152 } 1095 }
1153 result = state_regex; 1096 result = state_regex;
1154 } else { 1097 } else {
1155 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 1098 regerror(errcode, &preg, errbuf, MAX_INPUT_BUFFER);
1156 1099
1157 char tmp[DEFAULT_BUFFER_SIZE]; 1100 char tmp[DEFAULT_BUFFER_SIZE];
1158 1101
1159 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sExecute Error: %s, "), msg, errbuf); 1102 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sExecute Error: %s, "), msg, errbuf);
1160 strcpy(msg, tmp); 1103 strcpy(msg, tmp);
1161 result = STATE_UNKNOWN; 1104 result = STATE_UNKNOWN;
1162 } 1105 }
1163 } 1106 }
1164 1107
1165 /* make sure the page is of an appropriate size */ 1108 /* make sure the page is of an appropriate size */
1166 if ((max_page_len > 0) && (page_len > max_page_len)) { 1109 if ((max_page_len > 0) && (page_len > max_page_len)) {
1167 char tmp[DEFAULT_BUFFER_SIZE]; 1110 char tmp[DEFAULT_BUFFER_SIZE];
1168 1111
1169 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spage size %d too large, "), msg, page_len); 1112 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spage size %d too large, "), msg, page_len);
1170 1113
1171 strcpy(msg, tmp); 1114 strcpy(msg, tmp);
1172 1115
@@ -1175,1281 +1118,1239 @@ GOT_FIRST_CERT:
1175 } else if ((min_page_len > 0) && (page_len < min_page_len)) { 1118 } else if ((min_page_len > 0) && (page_len < min_page_len)) {
1176 char tmp[DEFAULT_BUFFER_SIZE]; 1119 char tmp[DEFAULT_BUFFER_SIZE];
1177 1120
1178 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spage size %d too small, "), msg, page_len); 1121 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spage size %d too small, "), msg, page_len);
1179 strcpy(msg, tmp); 1122 strcpy(msg, tmp);
1180 result = max_state_alt(STATE_WARNING, result); 1123 result = max_state_alt(STATE_WARNING, result);
1181 } 1124 }
1182 1125
1183 /* -w, -c: check warning and critical level */ 1126 /* -w, -c: check warning and critical level */
1184 result = max_state_alt(get_status(total_time, thlds), result); 1127 result = max_state_alt(get_status(total_time, thlds), result);
1185 1128
1186 /* Cut-off trailing characters */ 1129 /* Cut-off trailing characters */
1187 if (strlen(msg) >= 2) { 1130 if (strlen(msg) >= 2) {
1188 if(msg[strlen(msg)-2] == ',') 1131 if (msg[strlen(msg) - 2] == ',')
1189 msg[strlen(msg)-2] = '\0'; 1132 msg[strlen(msg) - 2] = '\0';
1190 else 1133 else
1191 msg[strlen(msg)-3] = '\0'; 1134 msg[strlen(msg) - 3] = '\0';
1192 } 1135 }
1193 1136
1194 /* TODO: separate _() msg and status code: die (result, "HTTP %s: %s\n", state_text(result), msg); */ 1137 /* TODO: separate _() msg and status code: die (result, "HTTP %s: %s\n", state_text(result), msg); */
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", 1138 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", state_text(result),
1196 state_text(result), string_statuscode (status_line.http_major, status_line.http_minor), 1139 string_statuscode(status_line.http_major, status_line.http_minor), status_line.http_code, status_line.msg,
1197 status_line.http_code, status_line.msg, 1140 strlen(msg) > 0 ? " - " : "", msg, page_len, total_time, (display_html ? "</A>" : ""), perfstring, (show_body ? body_buf.buf : ""),
1198 strlen(msg) > 0 ? " - " : "", 1141 (show_body ? "\n" : ""));
1199 msg, page_len, total_time, 1142
1200 (display_html ? "</A>" : ""), 1143 return max_state_alt(result, result_ssl);
1201 perfstring,
1202 (show_body ? body_buf.buf : ""),
1203 (show_body ? "\n" : "") );
1204
1205 return max_state_alt(result, result_ssl);
1206} 1144}
1207 1145
1208int 1146int uri_strcmp(const UriTextRangeA range, const char *s) {
1209uri_strcmp (const UriTextRangeA range, const char* s) 1147 if (!range.first)
1210{ 1148 return -1;
1211 if (!range.first) return -1; 1149 if ((size_t)(range.afterLast - range.first) < strlen(s))
1212 if ( (size_t)(range.afterLast - range.first) < strlen (s) ) return -1; 1150 return -1;
1213 return strncmp (s, range.first, min( (size_t)(range.afterLast - range.first), strlen (s))); 1151 return strncmp(s, range.first, min((size_t)(range.afterLast - range.first), strlen(s)));
1214} 1152}
1215 1153
1216char* 1154char *uri_string(const UriTextRangeA range, char *buf, size_t buflen) {
1217uri_string (const UriTextRangeA range, char* buf, size_t buflen) 1155 if (!range.first)
1218{ 1156 return "(null)";
1219 if (!range.first) return "(null)"; 1157 strncpy(buf, range.first, max(buflen - 1, (size_t)(range.afterLast - range.first)));
1220 strncpy (buf, range.first, max (buflen-1, (size_t)(range.afterLast - range.first))); 1158 buf[max(buflen - 1, (size_t)(range.afterLast - range.first))] = '\0';
1221 buf[max (buflen-1, (size_t)(range.afterLast - range.first))] = '\0'; 1159 buf[range.afterLast - range.first] = '\0';
1222 buf[range.afterLast - range.first] = '\0'; 1160 return buf;
1223 return buf;
1224} 1161}
1225 1162
1226void 1163void redir(curlhelp_write_curlbuf *header_buf) {
1227redir (curlhelp_write_curlbuf* header_buf) 1164 char *location = NULL;
1228{ 1165 curlhelp_statusline status_line;
1229 char *location = NULL; 1166 struct phr_header headers[255];
1230 curlhelp_statusline status_line; 1167 size_t nof_headers = 255;
1231 struct phr_header headers[255]; 1168 size_t msglen;
1232 size_t nof_headers = 255; 1169 char buf[DEFAULT_BUFFER_SIZE];
1233 size_t msglen; 1170 char ipstr[INET_ADDR_MAX_SIZE];
1234 char buf[DEFAULT_BUFFER_SIZE]; 1171 int new_port;
1235 char ipstr[INET_ADDR_MAX_SIZE]; 1172 char *new_host;
1236 int new_port; 1173 char *new_url;
1237 char *new_host; 1174
1238 char *new_url; 1175 int res = phr_parse_response(header_buf->buf, header_buf->buflen, &status_line.http_major, &status_line.http_minor,
1239 1176 &status_line.http_code, &status_line.msg, &msglen, headers, &nof_headers, 0);
1240 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
1241 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
1242 headers, &nof_headers, 0);
1243 1177
1244 if (res == -1) { 1178 if (res == -1) {
1245 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n")); 1179 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
1246 } 1180 }
1247 1181
1248 location = get_header_value (headers, nof_headers, "location"); 1182 location = get_header_value(headers, nof_headers, "location");
1249 1183
1250 if (verbose >= 2) 1184 if (verbose >= 2)
1251 printf(_("* Seen redirect location %s\n"), location); 1185 printf(_("* Seen redirect location %s\n"), location);
1252 1186
1253 if (++redir_depth > max_depth) 1187 if (++redir_depth > max_depth)
1254 die (STATE_WARNING, 1188 die(STATE_WARNING, _("HTTP WARNING - maximum redirection depth %d exceeded - %s%s\n"), max_depth, location,
1255 _("HTTP WARNING - maximum redirection depth %d exceeded - %s%s\n"), 1189 (display_html ? "</A>" : ""));
1256 max_depth, location, (display_html ? "</A>" : "")); 1190
1257 1191 UriParserStateA state;
1258 UriParserStateA state; 1192 UriUriA uri;
1259 UriUriA uri; 1193 state.uri = &uri;
1260 state.uri = &uri; 1194 if (uriParseUriA(&state, location) != URI_SUCCESS) {
1261 if (uriParseUriA (&state, location) != URI_SUCCESS) { 1195 if (state.errorCode == URI_ERROR_SYNTAX) {
1262 if (state.errorCode == URI_ERROR_SYNTAX) { 1196 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Could not parse redirect location '%s'%s\n"), location, (display_html ? "</A>" : ""));
1263 die (STATE_UNKNOWN, 1197 } else if (state.errorCode == URI_ERROR_MALLOC) {
1264 _("HTTP UNKNOWN - Could not parse redirect location '%s'%s\n"), 1198 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n"));
1265 location, (display_html ? "</A>" : "")); 1199 }
1266 } else if (state.errorCode == URI_ERROR_MALLOC) { 1200 }
1267 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n")); 1201
1268 } 1202 if (verbose >= 2) {
1269 } 1203 printf(_("** scheme: %s\n"), uri_string(uri.scheme, buf, DEFAULT_BUFFER_SIZE));
1270 1204 printf(_("** host: %s\n"), uri_string(uri.hostText, buf, DEFAULT_BUFFER_SIZE));
1271 if (verbose >= 2) { 1205 printf(_("** port: %s\n"), uri_string(uri.portText, buf, DEFAULT_BUFFER_SIZE));
1272 printf (_("** scheme: %s\n"), 1206 if (uri.hostData.ip4) {
1273 uri_string (uri.scheme, buf, DEFAULT_BUFFER_SIZE)); 1207 inet_ntop(AF_INET, uri.hostData.ip4->data, ipstr, sizeof(ipstr));
1274 printf (_("** host: %s\n"), 1208 printf(_("** IPv4: %s\n"), ipstr);
1275 uri_string (uri.hostText, buf, DEFAULT_BUFFER_SIZE)); 1209 }
1276 printf (_("** port: %s\n"), 1210 if (uri.hostData.ip6) {
1277 uri_string (uri.portText, buf, DEFAULT_BUFFER_SIZE)); 1211 inet_ntop(AF_INET, uri.hostData.ip6->data, ipstr, sizeof(ipstr));
1278 if (uri.hostData.ip4) { 1212 printf(_("** IPv6: %s\n"), ipstr);
1279 inet_ntop (AF_INET, uri.hostData.ip4->data, ipstr, sizeof (ipstr)); 1213 }
1280 printf (_("** IPv4: %s\n"), ipstr); 1214 if (uri.pathHead) {
1281 } 1215 printf(_("** path: "));
1282 if (uri.hostData.ip6) { 1216 const UriPathSegmentA *p = uri.pathHead;
1283 inet_ntop (AF_INET, uri.hostData.ip6->data, ipstr, sizeof (ipstr)); 1217 for (; p; p = p->next) {
1284 printf (_("** IPv6: %s\n"), ipstr); 1218 printf("/%s", uri_string(p->text, buf, DEFAULT_BUFFER_SIZE));
1285 } 1219 }
1286 if (uri.pathHead) { 1220 puts("");
1287 printf (_("** path: ")); 1221 }
1288 const UriPathSegmentA* p = uri.pathHead; 1222 if (uri.query.first) {
1289 for (; p; p = p->next) { 1223 printf(_("** query: %s\n"), uri_string(uri.query, buf, DEFAULT_BUFFER_SIZE));
1290 printf ("/%s", uri_string (p->text, buf, DEFAULT_BUFFER_SIZE)); 1224 }
1291 } 1225 if (uri.fragment.first) {
1292 puts (""); 1226 printf(_("** fragment: %s\n"), uri_string(uri.fragment, buf, DEFAULT_BUFFER_SIZE));
1293 } 1227 }
1294 if (uri.query.first) { 1228 }
1295 printf (_("** query: %s\n"), 1229
1296 uri_string (uri.query, buf, DEFAULT_BUFFER_SIZE)); 1230 if (uri.scheme.first) {
1297 } 1231 if (!uri_strcmp(uri.scheme, "https"))
1298 if (uri.fragment.first) { 1232 use_ssl = true;
1299 printf (_("** fragment: %s\n"), 1233 else
1300 uri_string (uri.fragment, buf, DEFAULT_BUFFER_SIZE)); 1234 use_ssl = false;
1301 } 1235 }
1302 } 1236
1303 1237 /* we do a sloppy test here only, because uriparser would have failed
1304 if (uri.scheme.first) { 1238 * above, if the port would be invalid, we just check for MAX_PORT
1305 if (!uri_strcmp (uri.scheme, "https")) 1239 */
1306 use_ssl = true; 1240 if (uri.portText.first) {
1307 else 1241 new_port = atoi(uri_string(uri.portText, buf, DEFAULT_BUFFER_SIZE));
1308 use_ssl = false; 1242 } else {
1309 } 1243 new_port = HTTP_PORT;
1310 1244 if (use_ssl)
1311 /* we do a sloppy test here only, because uriparser would have failed 1245 new_port = HTTPS_PORT;
1312 * above, if the port would be invalid, we just check for MAX_PORT 1246 }
1313 */ 1247 if (new_port > MAX_PORT)
1314 if (uri.portText.first) { 1248 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Redirection to port above %d - %s%s\n"), MAX_PORT, location, display_html ? "</A>" : "");
1315 new_port = atoi (uri_string (uri.portText, buf, DEFAULT_BUFFER_SIZE)); 1249
1316 } else { 1250 /* by RFC 7231 relative URLs in Location should be taken relative to
1317 new_port = HTTP_PORT; 1251 * the original URL, so we try to form a new absolute URL here
1318 if (use_ssl) 1252 */
1319 new_port = HTTPS_PORT; 1253 if (!uri.scheme.first && !uri.hostText.first) {
1320 } 1254 new_host = strdup(host_name ? host_name : server_address);
1321 if (new_port > MAX_PORT) 1255 new_port = server_port;
1322 die (STATE_UNKNOWN, 1256 if (use_ssl)
1323 _("HTTP UNKNOWN - Redirection to port above %d - %s%s\n"), 1257 uri_string(uri.scheme, "https", DEFAULT_BUFFER_SIZE);
1324 MAX_PORT, location, display_html ? "</A>" : ""); 1258 } else {
1325 1259 new_host = strdup(uri_string(uri.hostText, buf, DEFAULT_BUFFER_SIZE));
1326 /* by RFC 7231 relative URLs in Location should be taken relative to 1260 }
1327 * the original URL, so we try to form a new absolute URL here 1261
1328 */ 1262 /* compose new path */
1329 if (!uri.scheme.first && !uri.hostText.first) { 1263 /* TODO: handle fragments and query part of URL */
1330 new_host = strdup (host_name ? host_name : server_address); 1264 new_url = (char *)calloc(1, DEFAULT_BUFFER_SIZE);
1331 new_port = server_port; 1265 if (uri.pathHead) {
1332 if(use_ssl) 1266 const UriPathSegmentA *p = uri.pathHead;
1333 uri_string (uri.scheme, "https", DEFAULT_BUFFER_SIZE); 1267 for (; p; p = p->next) {
1334 } else { 1268 strncat(new_url, "/", DEFAULT_BUFFER_SIZE);
1335 new_host = strdup (uri_string (uri.hostText, buf, DEFAULT_BUFFER_SIZE)); 1269 strncat(new_url, uri_string(p->text, buf, DEFAULT_BUFFER_SIZE), DEFAULT_BUFFER_SIZE - 1);
1336 } 1270 }
1337 1271 }
1338 /* compose new path */ 1272
1339 /* TODO: handle fragments and query part of URL */ 1273 if (server_port == new_port && !strncmp(server_address, new_host, MAX_IPV4_HOSTLENGTH) &&
1340 new_url = (char *)calloc( 1, DEFAULT_BUFFER_SIZE); 1274 (host_name && !strncmp(host_name, new_host, MAX_IPV4_HOSTLENGTH)) && !strcmp(server_url, new_url))
1341 if (uri.pathHead) { 1275 die(STATE_CRITICAL, _("HTTP CRITICAL - redirection creates an infinite loop - %s://%s:%d%s%s\n"), use_ssl ? "https" : "http",
1342 const UriPathSegmentA* p = uri.pathHead; 1276 new_host, new_port, new_url, (display_html ? "</A>" : ""));
1343 for (; p; p = p->next) { 1277
1344 strncat (new_url, "/", DEFAULT_BUFFER_SIZE); 1278 /* set new values for redirected request */
1345 strncat (new_url, uri_string (p->text, buf, DEFAULT_BUFFER_SIZE), DEFAULT_BUFFER_SIZE-1); 1279
1346 } 1280 if (!(followsticky & STICKY_HOST)) {
1347 } 1281 free(server_address);
1348 1282 server_address = strndup(new_host, MAX_IPV4_HOSTLENGTH);
1349 if (server_port==new_port && 1283 }
1350 !strncmp(server_address, new_host, MAX_IPV4_HOSTLENGTH) && 1284 if (!(followsticky & STICKY_PORT)) {
1351 (host_name && !strncmp(host_name, new_host, MAX_IPV4_HOSTLENGTH)) && 1285 server_port = (unsigned short)new_port;
1352 !strcmp(server_url, new_url)) 1286 }
1353 die (STATE_CRITICAL, 1287
1354 _("HTTP CRITICAL - redirection creates an infinite loop - %s://%s:%d%s%s\n"), 1288 free(host_name);
1355 use_ssl ? "https" : "http", new_host, new_port, new_url, (display_html ? "</A>" : "")); 1289 host_name = strndup(new_host, MAX_IPV4_HOSTLENGTH);
1356 1290
1357 /* set new values for redirected request */ 1291 /* reset virtual port */
1358 1292 virtual_port = server_port;
1359 if (!(followsticky & STICKY_HOST)) { 1293
1360 free (server_address); 1294 free(new_host);
1361 server_address = strndup (new_host, MAX_IPV4_HOSTLENGTH); 1295 free(server_url);
1362 } 1296 server_url = new_url;
1363 if (!(followsticky & STICKY_PORT)) { 1297
1364 server_port = (unsigned short)new_port; 1298 uriFreeUriMembersA(&uri);
1365 } 1299
1366 1300 if (verbose)
1367 free (host_name); 1301 printf(_("Redirection to %s://%s:%d%s\n"), use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port,
1368 host_name = strndup (new_host, MAX_IPV4_HOSTLENGTH); 1302 server_url);
1369 1303
1370 /* reset virtual port */ 1304 /* TODO: the hash component MUST be taken from the original URL and
1371 virtual_port = server_port; 1305 * attached to the URL in Location
1372 1306 */
1373 free(new_host); 1307
1374 free (server_url); 1308 cleanup();
1375 server_url = new_url; 1309 check_http();
1376
1377 uriFreeUriMembersA (&uri);
1378
1379 if (verbose)
1380 printf (_("Redirection to %s://%s:%d%s\n"), use_ssl ? "https" : "http",
1381 host_name ? host_name : server_address, server_port, server_url);
1382
1383 /* TODO: the hash component MUST be taken from the original URL and
1384 * attached to the URL in Location
1385 */
1386
1387 cleanup ();
1388 check_http ();
1389} 1310}
1390 1311
1391/* check whether a file exists */ 1312/* check whether a file exists */
1392void 1313void test_file(char *path) {
1393test_file (char *path) 1314 if (access(path, R_OK) == 0)
1394{ 1315 return;
1395 if (access(path, R_OK) == 0) 1316 usage2(_("file does not exist or is not readable"), path);
1396 return;
1397 usage2 (_("file does not exist or is not readable"), path);
1398} 1317}
1399 1318
1400bool 1319bool process_arguments(int argc, char **argv) {
1401process_arguments (int argc, char **argv) 1320 char *p;
1402{ 1321 int c = 1;
1403 char *p; 1322 char *temp;
1404 int c = 1; 1323
1405 char *temp; 1324 enum {
1406 1325 INVERT_REGEX = CHAR_MAX + 1,
1407 enum { 1326 SNI_OPTION,
1408 INVERT_REGEX = CHAR_MAX + 1, 1327 MAX_REDIRS_OPTION,
1409 SNI_OPTION, 1328 CONTINUE_AFTER_CHECK_CERT,
1410 MAX_REDIRS_OPTION, 1329 CA_CERT_OPTION,
1411 CONTINUE_AFTER_CHECK_CERT, 1330 HTTP_VERSION_OPTION,
1412 CA_CERT_OPTION, 1331 AUTOMATIC_DECOMPRESSION,
1413 HTTP_VERSION_OPTION, 1332 COOKIE_JAR,
1414 AUTOMATIC_DECOMPRESSION, 1333 HAPROXY_PROTOCOL,
1415 COOKIE_JAR, 1334 STATE_REGEX
1416 HAPROXY_PROTOCOL, 1335 };
1417 STATE_REGEX 1336
1418 }; 1337 int option = 0;
1419 1338 int got_plus = 0;
1420 int option = 0; 1339 static struct option longopts[] = {STD_LONG_OPTS,
1421 int got_plus = 0; 1340 {"link", no_argument, 0, 'L'},
1422 static struct option longopts[] = { 1341 {"nohtml", no_argument, 0, 'n'},
1423 STD_LONG_OPTS, 1342 {"ssl", optional_argument, 0, 'S'},
1424 {"link", no_argument, 0, 'L'}, 1343 {"sni", no_argument, 0, SNI_OPTION},
1425 {"nohtml", no_argument, 0, 'n'}, 1344 {"post", required_argument, 0, 'P'},
1426 {"ssl", optional_argument, 0, 'S'}, 1345 {"method", required_argument, 0, 'j'},
1427 {"sni", no_argument, 0, SNI_OPTION}, 1346 {"IP-address", required_argument, 0, 'I'},
1428 {"post", required_argument, 0, 'P'}, 1347 {"url", required_argument, 0, 'u'},
1429 {"method", required_argument, 0, 'j'}, 1348 {"port", required_argument, 0, 'p'},
1430 {"IP-address", required_argument, 0, 'I'}, 1349 {"authorization", required_argument, 0, 'a'},
1431 {"url", required_argument, 0, 'u'}, 1350 {"proxy-authorization", required_argument, 0, 'b'},
1432 {"port", required_argument, 0, 'p'}, 1351 {"header-string", required_argument, 0, 'd'},
1433 {"authorization", required_argument, 0, 'a'}, 1352 {"string", required_argument, 0, 's'},
1434 {"proxy-authorization", required_argument, 0, 'b'}, 1353 {"expect", required_argument, 0, 'e'},
1435 {"header-string", required_argument, 0, 'd'}, 1354 {"regex", required_argument, 0, 'r'},
1436 {"string", required_argument, 0, 's'}, 1355 {"ereg", required_argument, 0, 'r'},
1437 {"expect", required_argument, 0, 'e'}, 1356 {"eregi", required_argument, 0, 'R'},
1438 {"regex", required_argument, 0, 'r'}, 1357 {"linespan", no_argument, 0, 'l'},
1439 {"ereg", required_argument, 0, 'r'}, 1358 {"onredirect", required_argument, 0, 'f'},
1440 {"eregi", required_argument, 0, 'R'}, 1359 {"certificate", required_argument, 0, 'C'},
1441 {"linespan", no_argument, 0, 'l'}, 1360 {"client-cert", required_argument, 0, 'J'},
1442 {"onredirect", required_argument, 0, 'f'}, 1361 {"private-key", required_argument, 0, 'K'},
1443 {"certificate", required_argument, 0, 'C'}, 1362 {"ca-cert", required_argument, 0, CA_CERT_OPTION},
1444 {"client-cert", required_argument, 0, 'J'}, 1363 {"verify-cert", no_argument, 0, 'D'},
1445 {"private-key", required_argument, 0, 'K'}, 1364 {"continue-after-certificate", no_argument, 0, CONTINUE_AFTER_CHECK_CERT},
1446 {"ca-cert", required_argument, 0, CA_CERT_OPTION}, 1365 {"useragent", required_argument, 0, 'A'},
1447 {"verify-cert", no_argument, 0, 'D'}, 1366 {"header", required_argument, 0, 'k'},
1448 {"continue-after-certificate", no_argument, 0, CONTINUE_AFTER_CHECK_CERT}, 1367 {"no-body", no_argument, 0, 'N'},
1449 {"useragent", required_argument, 0, 'A'}, 1368 {"max-age", required_argument, 0, 'M'},
1450 {"header", required_argument, 0, 'k'}, 1369 {"content-type", required_argument, 0, 'T'},
1451 {"no-body", no_argument, 0, 'N'}, 1370 {"pagesize", required_argument, 0, 'm'},
1452 {"max-age", required_argument, 0, 'M'}, 1371 {"invert-regex", no_argument, NULL, INVERT_REGEX},
1453 {"content-type", required_argument, 0, 'T'}, 1372 {"state-regex", required_argument, 0, STATE_REGEX},
1454 {"pagesize", required_argument, 0, 'm'}, 1373 {"use-ipv4", no_argument, 0, '4'},
1455 {"invert-regex", no_argument, NULL, INVERT_REGEX}, 1374 {"use-ipv6", no_argument, 0, '6'},
1456 {"state-regex", required_argument, 0, STATE_REGEX}, 1375 {"extended-perfdata", no_argument, 0, 'E'},
1457 {"use-ipv4", no_argument, 0, '4'}, 1376 {"show-body", no_argument, 0, 'B'},
1458 {"use-ipv6", no_argument, 0, '6'}, 1377 {"max-redirs", required_argument, 0, MAX_REDIRS_OPTION},
1459 {"extended-perfdata", no_argument, 0, 'E'}, 1378 {"http-version", required_argument, 0, HTTP_VERSION_OPTION},
1460 {"show-body", no_argument, 0, 'B'}, 1379 {"enable-automatic-decompression", no_argument, 0, AUTOMATIC_DECOMPRESSION},
1461 {"max-redirs", required_argument, 0, MAX_REDIRS_OPTION}, 1380 {"cookie-jar", required_argument, 0, COOKIE_JAR},
1462 {"http-version", required_argument, 0, HTTP_VERSION_OPTION}, 1381 {"haproxy-protocol", no_argument, 0, HAPROXY_PROTOCOL},
1463 {"enable-automatic-decompression", no_argument, 0, AUTOMATIC_DECOMPRESSION}, 1382 {0, 0, 0, 0}};
1464 {"cookie-jar", required_argument, 0, COOKIE_JAR}, 1383
1465 {"haproxy-protocol", no_argument, 0, HAPROXY_PROTOCOL}, 1384 if (argc < 2)
1466 {0, 0, 0, 0} 1385 return false;
1467 }; 1386
1468 1387 /* support check_http compatible arguments */
1469 if (argc < 2) 1388 for (c = 1; c < argc; c++) {
1470 return false; 1389 if (strcmp("-to", argv[c]) == 0)
1471 1390 strcpy(argv[c], "-t");
1472 /* support check_http compatible arguments */ 1391 if (strcmp("-hn", argv[c]) == 0)
1473 for (c = 1; c < argc; c++) { 1392 strcpy(argv[c], "-H");
1474 if (strcmp ("-to", argv[c]) == 0) 1393 if (strcmp("-wt", argv[c]) == 0)
1475 strcpy (argv[c], "-t"); 1394 strcpy(argv[c], "-w");
1476 if (strcmp ("-hn", argv[c]) == 0) 1395 if (strcmp("-ct", argv[c]) == 0)
1477 strcpy (argv[c], "-H"); 1396 strcpy(argv[c], "-c");
1478 if (strcmp ("-wt", argv[c]) == 0) 1397 if (strcmp("-nohtml", argv[c]) == 0)
1479 strcpy (argv[c], "-w"); 1398 strcpy(argv[c], "-n");
1480 if (strcmp ("-ct", argv[c]) == 0) 1399 }
1481 strcpy (argv[c], "-c"); 1400
1482 if (strcmp ("-nohtml", argv[c]) == 0) 1401 server_url = strdup(DEFAULT_SERVER_URL);
1483 strcpy (argv[c], "-n"); 1402
1484 } 1403 while (1) {
1485 1404 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);
1486 server_url = strdup(DEFAULT_SERVER_URL); 1405 if (c == -1 || c == EOF || c == 1)
1487 1406 break;
1488 while (1) { 1407
1489 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); 1408 switch (c) {
1490 if (c == -1 || c == EOF || c == 1) 1409 case 'h':
1491 break; 1410 print_help();
1492 1411 exit(STATE_UNKNOWN);
1493 switch (c) { 1412 break;
1494 case 'h': 1413 case 'V':
1495 print_help(); 1414 print_revision(progname, NP_VERSION);
1496 exit(STATE_UNKNOWN); 1415 print_curl_version();
1497 break; 1416 exit(STATE_UNKNOWN);
1498 case 'V': 1417 break;
1499 print_revision(progname, NP_VERSION); 1418 case 'v':
1500 print_curl_version(); 1419 verbose++;
1501 exit(STATE_UNKNOWN); 1420 break;
1502 break; 1421 case 't': /* timeout period */
1503 case 'v': 1422 if (!is_intnonneg(optarg))
1504 verbose++; 1423 usage2(_("Timeout interval must be a positive integer"), optarg);
1505 break; 1424 else
1506 case 't': /* timeout period */ 1425 socket_timeout = (int)strtol(optarg, NULL, 10);
1507 if (!is_intnonneg (optarg)) 1426 break;
1508 usage2 (_("Timeout interval must be a positive integer"), optarg); 1427 case 'c': /* critical time threshold */
1509 else 1428 critical_thresholds = optarg;
1510 socket_timeout = (int)strtol (optarg, NULL, 10); 1429 break;
1511 break; 1430 case 'w': /* warning time threshold */
1512 case 'c': /* critical time threshold */ 1431 warning_thresholds = optarg;
1513 critical_thresholds = optarg; 1432 break;
1514 break; 1433 case 'H': /* virtual host */
1515 case 'w': /* warning time threshold */ 1434 host_name = strdup(optarg);
1516 warning_thresholds = optarg; 1435 if (host_name[0] == '[') {
1517 break; 1436 if ((p = strstr(host_name, "]:")) != NULL) { /* [IPv6]:port */
1518 case 'H': /* virtual host */ 1437 virtual_port = atoi(p + 2);
1519 host_name = strdup (optarg); 1438 /* cut off the port */
1520 if (host_name[0] == '[') { 1439 host_name_length = strlen(host_name) - strlen(p) - 1;
1521 if ((p = strstr (host_name, "]:")) != NULL) { /* [IPv6]:port */ 1440 free(host_name);
1522 virtual_port = atoi (p + 2); 1441 host_name = strndup(optarg, host_name_length);
1523 /* cut off the port */ 1442 }
1524 host_name_length = strlen (host_name) - strlen (p) - 1; 1443 } else if ((p = strchr(host_name, ':')) != NULL && strchr(++p, ':') == NULL) { /* IPv4:port or host:port */
1525 free (host_name); 1444 virtual_port = atoi(p);
1526 host_name = strndup (optarg, host_name_length); 1445 /* cut off the port */
1527 } 1446 host_name_length = strlen(host_name) - strlen(p) - 1;
1528 } else if ((p = strchr (host_name, ':')) != NULL 1447 free(host_name);
1529 && strchr (++p, ':') == NULL) { /* IPv4:port or host:port */ 1448 host_name = strndup(optarg, host_name_length);
1530 virtual_port = atoi (p); 1449 }
1531 /* cut off the port */ 1450 break;
1532 host_name_length = strlen (host_name) - strlen (p) - 1; 1451 case 'I': /* internet address */
1533 free (host_name); 1452 server_address = strdup(optarg);
1534 host_name = strndup (optarg, host_name_length); 1453 break;
1535 } 1454 case 'u': /* URL path */
1536 break; 1455 server_url = strdup(optarg);
1537 case 'I': /* internet address */ 1456 break;
1538 server_address = strdup (optarg); 1457 case 'p': /* Server port */
1539 break; 1458 if (!is_intnonneg(optarg))
1540 case 'u': /* URL path */ 1459 usage2(_("Invalid port number, expecting a non-negative number"), optarg);
1541 server_url = strdup (optarg); 1460 else {
1542 break; 1461 if (strtol(optarg, NULL, 10) > MAX_PORT)
1543 case 'p': /* Server port */ 1462 usage2(_("Invalid port number, supplied port number is too big"), optarg);
1544 if (!is_intnonneg (optarg)) 1463 server_port = (unsigned short)strtol(optarg, NULL, 10);
1545 usage2 (_("Invalid port number, expecting a non-negative number"), optarg); 1464 specify_port = true;
1546 else { 1465 }
1547 if( strtol(optarg, NULL, 10) > MAX_PORT) 1466 break;
1548 usage2 (_("Invalid port number, supplied port number is too big"), optarg); 1467 case 'a': /* authorization info */
1549 server_port = (unsigned short)strtol(optarg, NULL, 10); 1468 strncpy(user_auth, optarg, MAX_INPUT_BUFFER - 1);
1550 specify_port = true; 1469 user_auth[MAX_INPUT_BUFFER - 1] = 0;
1551 } 1470 break;
1552 break; 1471 case 'b': /* proxy-authorization info */
1553 case 'a': /* authorization info */ 1472 strncpy(proxy_auth, optarg, MAX_INPUT_BUFFER - 1);
1554 strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1); 1473 proxy_auth[MAX_INPUT_BUFFER - 1] = 0;
1555 user_auth[MAX_INPUT_BUFFER - 1] = 0; 1474 break;
1556 break; 1475 case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */
1557 case 'b': /* proxy-authorization info */ 1476 if (!http_post_data)
1558 strncpy (proxy_auth, optarg, MAX_INPUT_BUFFER - 1); 1477 http_post_data = strdup(optarg);
1559 proxy_auth[MAX_INPUT_BUFFER - 1] = 0; 1478 if (!http_method)
1560 break; 1479 http_method = strdup("POST");
1561 case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */ 1480 break;
1562 if (! http_post_data) 1481 case 'j': /* Set HTTP method */
1563 http_post_data = strdup (optarg); 1482 if (http_method)
1564 if (! http_method) 1483 free(http_method);
1565 http_method = strdup("POST"); 1484 http_method = strdup(optarg);
1566 break; 1485 break;
1567 case 'j': /* Set HTTP method */ 1486 case 'A': /* useragent */
1568 if (http_method) 1487 strncpy(user_agent, optarg, DEFAULT_BUFFER_SIZE);
1569 free(http_method); 1488 user_agent[DEFAULT_BUFFER_SIZE - 1] = '\0';
1570 http_method = strdup (optarg); 1489 break;
1571 break; 1490 case 'k': /* Additional headers */
1572 case 'A': /* useragent */ 1491 if (http_opt_headers_count == 0)
1573 strncpy (user_agent, optarg, DEFAULT_BUFFER_SIZE); 1492 http_opt_headers = malloc(sizeof(char *) * (++http_opt_headers_count));
1574 user_agent[DEFAULT_BUFFER_SIZE-1] = '\0'; 1493 else
1575 break; 1494 http_opt_headers = realloc(http_opt_headers, sizeof(char *) * (++http_opt_headers_count));
1576 case 'k': /* Additional headers */ 1495 http_opt_headers[http_opt_headers_count - 1] = optarg;
1577 if (http_opt_headers_count == 0) 1496 break;
1578 http_opt_headers = malloc (sizeof (char *) * (++http_opt_headers_count)); 1497 case 'L': /* show html link */
1579 else 1498 display_html = true;
1580 http_opt_headers = realloc (http_opt_headers, sizeof (char *) * (++http_opt_headers_count)); 1499 break;
1581 http_opt_headers[http_opt_headers_count - 1] = optarg; 1500 case 'n': /* do not show html link */
1582 break; 1501 display_html = false;
1583 case 'L': /* show html link */ 1502 break;
1584 display_html = true; 1503 case 'C': /* Check SSL cert validity */
1585 break;
1586 case 'n': /* do not show html link */
1587 display_html = false;
1588 break;
1589 case 'C': /* Check SSL cert validity */
1590#ifdef LIBCURL_FEATURE_SSL 1504#ifdef LIBCURL_FEATURE_SSL
1591 if ((temp=strchr(optarg,','))!=NULL) { 1505 if ((temp = strchr(optarg, ',')) != NULL) {
1592 *temp='\0'; 1506 *temp = '\0';
1593 if (!is_intnonneg (optarg)) 1507 if (!is_intnonneg(optarg))
1594 usage2 (_("Invalid certificate expiration period"), optarg); 1508 usage2(_("Invalid certificate expiration period"), optarg);
1595 days_till_exp_warn = atoi(optarg); 1509 days_till_exp_warn = atoi(optarg);
1596 *temp=','; 1510 *temp = ',';
1597 temp++; 1511 temp++;
1598 if (!is_intnonneg (temp)) 1512 if (!is_intnonneg(temp))
1599 usage2 (_("Invalid certificate expiration period"), temp); 1513 usage2(_("Invalid certificate expiration period"), temp);
1600 days_till_exp_crit = atoi (temp); 1514 days_till_exp_crit = atoi(temp);
1601 } 1515 } else {
1602 else { 1516 days_till_exp_crit = 0;
1603 days_till_exp_crit=0; 1517 if (!is_intnonneg(optarg))
1604 if (!is_intnonneg (optarg)) 1518 usage2(_("Invalid certificate expiration period"), optarg);
1605 usage2 (_("Invalid certificate expiration period"), optarg); 1519 days_till_exp_warn = atoi(optarg);
1606 days_till_exp_warn = atoi (optarg); 1520 }
1607 } 1521 check_cert = true;
1608 check_cert = true; 1522 goto enable_ssl;
1609 goto enable_ssl;
1610#endif 1523#endif
1611 case CONTINUE_AFTER_CHECK_CERT: /* don't stop after the certificate is checked */ 1524 case CONTINUE_AFTER_CHECK_CERT: /* don't stop after the certificate is checked */
1612#ifdef HAVE_SSL 1525#ifdef HAVE_SSL
1613 continue_after_check_cert = true; 1526 continue_after_check_cert = true;
1614 break; 1527 break;
1615#endif 1528#endif
1616 case 'J': /* use client certificate */ 1529 case 'J': /* use client certificate */
1617#ifdef LIBCURL_FEATURE_SSL 1530#ifdef LIBCURL_FEATURE_SSL
1618 test_file(optarg); 1531 test_file(optarg);
1619 client_cert = optarg; 1532 client_cert = optarg;
1620 goto enable_ssl; 1533 goto enable_ssl;
1621#endif 1534#endif
1622 case 'K': /* use client private key */ 1535 case 'K': /* use client private key */
1623#ifdef LIBCURL_FEATURE_SSL 1536#ifdef LIBCURL_FEATURE_SSL
1624 test_file(optarg); 1537 test_file(optarg);
1625 client_privkey = optarg; 1538 client_privkey = optarg;
1626 goto enable_ssl; 1539 goto enable_ssl;
1627#endif 1540#endif
1628#ifdef LIBCURL_FEATURE_SSL 1541#ifdef LIBCURL_FEATURE_SSL
1629 case CA_CERT_OPTION: /* use CA chain file */ 1542 case CA_CERT_OPTION: /* use CA chain file */
1630 test_file(optarg); 1543 test_file(optarg);
1631 ca_cert = optarg; 1544 ca_cert = optarg;
1632 goto enable_ssl; 1545 goto enable_ssl;
1633#endif 1546#endif
1634#ifdef LIBCURL_FEATURE_SSL 1547#ifdef LIBCURL_FEATURE_SSL
1635 case 'D': /* verify peer certificate & host */ 1548 case 'D': /* verify peer certificate & host */
1636 verify_peer_and_host = true; 1549 verify_peer_and_host = true;
1637 break; 1550 break;
1638#endif 1551#endif
1639 case 'S': /* use SSL */ 1552 case 'S': /* use SSL */
1640#ifdef LIBCURL_FEATURE_SSL 1553#ifdef LIBCURL_FEATURE_SSL
1641 enable_ssl: 1554 enable_ssl:
1642 use_ssl = true; 1555 use_ssl = true;
1643 /* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default. 1556 /* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default.
1644 * Only set if it's non-zero. This helps when we include multiple 1557 * Only set if it's non-zero. This helps when we include multiple
1645 * parameters, like -S and -C combinations */ 1558 * parameters, like -S and -C combinations */
1646 ssl_version = CURL_SSLVERSION_DEFAULT; 1559 ssl_version = CURL_SSLVERSION_DEFAULT;
1647 if (c=='S' && optarg != NULL) { 1560 if (c == 'S' && optarg != NULL) {
1648 char *plus_ptr = strchr(optarg, '+'); 1561 char *plus_ptr = strchr(optarg, '+');
1649 if (plus_ptr) { 1562 if (plus_ptr) {
1650 got_plus = 1; 1563 got_plus = 1;
1651 *plus_ptr = '\0'; 1564 *plus_ptr = '\0';
1652 } 1565 }
1653 1566
1654 if (optarg[0] == '2') 1567 if (optarg[0] == '2')
1655 ssl_version = CURL_SSLVERSION_SSLv2; 1568 ssl_version = CURL_SSLVERSION_SSLv2;
1656 else if (optarg[0] == '3') 1569 else if (optarg[0] == '3')
1657 ssl_version = CURL_SSLVERSION_SSLv3; 1570 ssl_version = CURL_SSLVERSION_SSLv3;
1658 else if (!strcmp (optarg, "1") || !strcmp (optarg, "1.0")) 1571 else if (!strcmp(optarg, "1") || !strcmp(optarg, "1.0"))
1659#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1572# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1660 ssl_version = CURL_SSLVERSION_TLSv1_0; 1573 ssl_version = CURL_SSLVERSION_TLSv1_0;
1661#else 1574# else
1662 ssl_version = CURL_SSLVERSION_DEFAULT; 1575 ssl_version = CURL_SSLVERSION_DEFAULT;
1663#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1576# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1664 else if (!strcmp (optarg, "1.1")) 1577 else if (!strcmp(optarg, "1.1"))
1665#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1578# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1666 ssl_version = CURL_SSLVERSION_TLSv1_1; 1579 ssl_version = CURL_SSLVERSION_TLSv1_1;
1667#else 1580# else
1668 ssl_version = CURL_SSLVERSION_DEFAULT; 1581 ssl_version = CURL_SSLVERSION_DEFAULT;
1669#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1582# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1670 else if (!strcmp (optarg, "1.2")) 1583 else if (!strcmp(optarg, "1.2"))
1671#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1584# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1672 ssl_version = CURL_SSLVERSION_TLSv1_2; 1585 ssl_version = CURL_SSLVERSION_TLSv1_2;
1673#else 1586# else
1674 ssl_version = CURL_SSLVERSION_DEFAULT; 1587 ssl_version = CURL_SSLVERSION_DEFAULT;
1675#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1588# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1676 else if (!strcmp (optarg, "1.3")) 1589 else if (!strcmp(optarg, "1.3"))
1677#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) 1590# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0)
1678 ssl_version = CURL_SSLVERSION_TLSv1_3; 1591 ssl_version = CURL_SSLVERSION_TLSv1_3;
1679#else 1592# else
1680 ssl_version = CURL_SSLVERSION_DEFAULT; 1593 ssl_version = CURL_SSLVERSION_DEFAULT;
1681#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */ 1594# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */
1682 else 1595 else
1683 usage4 (_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2, 1.3 (with optional '+' suffix)")); 1596 usage4(_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2, 1.3 (with optional '+' suffix)"));
1684 } 1597 }
1685#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) 1598# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0)
1686 if (got_plus) { 1599 if (got_plus) {
1687 switch (ssl_version) { 1600 switch (ssl_version) {
1688 case CURL_SSLVERSION_TLSv1_3: 1601 case CURL_SSLVERSION_TLSv1_3:
1689 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3; 1602 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3;
1690 break; 1603 break;
1691 case CURL_SSLVERSION_TLSv1_2: 1604 case CURL_SSLVERSION_TLSv1_2:
1692 case CURL_SSLVERSION_TLSv1_1: 1605 case CURL_SSLVERSION_TLSv1_1:
1693 case CURL_SSLVERSION_TLSv1_0: 1606 case CURL_SSLVERSION_TLSv1_0:
1694 ssl_version |= CURL_SSLVERSION_MAX_DEFAULT; 1607 ssl_version |= CURL_SSLVERSION_MAX_DEFAULT;
1695 break; 1608 break;
1696 } 1609 }
1697 } else { 1610 } else {
1698 switch (ssl_version) { 1611 switch (ssl_version) {
1699 case CURL_SSLVERSION_TLSv1_3: 1612 case CURL_SSLVERSION_TLSv1_3:
1700 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3; 1613 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3;
1701 break; 1614 break;
1702 case CURL_SSLVERSION_TLSv1_2: 1615 case CURL_SSLVERSION_TLSv1_2:
1703 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_2; 1616 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_2;
1704 break; 1617 break;
1705 case CURL_SSLVERSION_TLSv1_1: 1618 case CURL_SSLVERSION_TLSv1_1:
1706 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_1; 1619 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_1;
1707 break; 1620 break;
1708 case CURL_SSLVERSION_TLSv1_0: 1621 case CURL_SSLVERSION_TLSv1_0:
1709 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_0; 1622 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_0;
1710 break; 1623 break;
1711 } 1624 }
1712 } 1625 }
1713#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) */ 1626# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) */
1714 if (verbose >= 2) 1627 if (verbose >= 2)
1715 printf(_("* Set SSL/TLS version to %d\n"), ssl_version); 1628 printf(_("* Set SSL/TLS version to %d\n"), ssl_version);
1716 if (!specify_port) 1629 if (!specify_port)
1717 server_port = HTTPS_PORT; 1630 server_port = HTTPS_PORT;
1718 break; 1631 break;
1719#else /* LIBCURL_FEATURE_SSL */ 1632#else /* LIBCURL_FEATURE_SSL */
1720 /* -C -J and -K fall through to here without SSL */ 1633 /* -C -J and -K fall through to here without SSL */
1721 usage4 (_("Invalid option - SSL is not available")); 1634 usage4(_("Invalid option - SSL is not available"));
1722 break; 1635 break;
1723 case SNI_OPTION: /* --sni is parsed, but ignored, the default is true with libcurl */ 1636 case SNI_OPTION: /* --sni is parsed, but ignored, the default is true with libcurl */
1724 use_sni = true; 1637 use_sni = true;
1725 break; 1638 break;
1726#endif /* LIBCURL_FEATURE_SSL */ 1639#endif /* LIBCURL_FEATURE_SSL */
1727 case MAX_REDIRS_OPTION: 1640 case MAX_REDIRS_OPTION:
1728 if (!is_intnonneg (optarg)) 1641 if (!is_intnonneg(optarg))
1729 usage2 (_("Invalid max_redirs count"), optarg); 1642 usage2(_("Invalid max_redirs count"), optarg);
1730 else { 1643 else {
1731 max_depth = atoi (optarg); 1644 max_depth = atoi(optarg);
1732 } 1645 }
1733 break; 1646 break;
1734 case 'f': /* onredirect */ 1647 case 'f': /* onredirect */
1735 if (!strcmp (optarg, "ok")) 1648 if (!strcmp(optarg, "ok"))
1736 onredirect = STATE_OK; 1649 onredirect = STATE_OK;
1737 else if (!strcmp (optarg, "warning")) 1650 else if (!strcmp(optarg, "warning"))
1738 onredirect = STATE_WARNING; 1651 onredirect = STATE_WARNING;
1739 else if (!strcmp (optarg, "critical")) 1652 else if (!strcmp(optarg, "critical"))
1740 onredirect = STATE_CRITICAL; 1653 onredirect = STATE_CRITICAL;
1741 else if (!strcmp (optarg, "unknown")) 1654 else if (!strcmp(optarg, "unknown"))
1742 onredirect = STATE_UNKNOWN; 1655 onredirect = STATE_UNKNOWN;
1743 else if (!strcmp (optarg, "follow")) 1656 else if (!strcmp(optarg, "follow"))
1744 onredirect = STATE_DEPENDENT; 1657 onredirect = STATE_DEPENDENT;
1745 else if (!strcmp (optarg, "stickyport")) 1658 else if (!strcmp(optarg, "stickyport"))
1746 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_HOST|STICKY_PORT; 1659 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_HOST | STICKY_PORT;
1747 else if (!strcmp (optarg, "sticky")) 1660 else if (!strcmp(optarg, "sticky"))
1748 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_HOST; 1661 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_HOST;
1749 else if (!strcmp (optarg, "follow")) 1662 else if (!strcmp(optarg, "follow"))
1750 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_NONE; 1663 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_NONE;
1751 else if (!strcmp (optarg, "curl")) 1664 else if (!strcmp(optarg, "curl"))
1752 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_LIBCURL; 1665 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_LIBCURL;
1753 else usage2 (_("Invalid onredirect option"), optarg); 1666 else
1754 if (verbose >= 2) 1667 usage2(_("Invalid onredirect option"), optarg);
1755 printf(_("* Following redirects set to %s\n"), state_text(onredirect)); 1668 if (verbose >= 2)
1756 break; 1669 printf(_("* Following redirects set to %s\n"), state_text(onredirect));
1757 case 'd': /* string or substring */ 1670 break;
1758 strncpy (header_expect, optarg, MAX_INPUT_BUFFER - 1); 1671 case 'd': /* string or substring */
1759 header_expect[MAX_INPUT_BUFFER - 1] = 0; 1672 strncpy(header_expect, optarg, MAX_INPUT_BUFFER - 1);
1760 break; 1673 header_expect[MAX_INPUT_BUFFER - 1] = 0;
1761 case 's': /* string or substring */ 1674 break;
1762 strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1); 1675 case 's': /* string or substring */
1763 string_expect[MAX_INPUT_BUFFER - 1] = 0; 1676 strncpy(string_expect, optarg, MAX_INPUT_BUFFER - 1);
1764 break; 1677 string_expect[MAX_INPUT_BUFFER - 1] = 0;
1765 case 'e': /* string or substring */ 1678 break;
1766 strncpy (server_expect, optarg, MAX_INPUT_BUFFER - 1); 1679 case 'e': /* string or substring */
1767 server_expect[MAX_INPUT_BUFFER - 1] = 0; 1680 strncpy(server_expect, optarg, MAX_INPUT_BUFFER - 1);
1768 server_expect_yn = 1; 1681 server_expect[MAX_INPUT_BUFFER - 1] = 0;
1769 break; 1682 server_expect_yn = 1;
1770 case 'T': /* Content-type */ 1683 break;
1771 http_content_type = strdup (optarg); 1684 case 'T': /* Content-type */
1772 break; 1685 http_content_type = strdup(optarg);
1773 case 'l': /* linespan */ 1686 break;
1774 cflags &= ~REG_NEWLINE; 1687 case 'l': /* linespan */
1775 break; 1688 cflags &= ~REG_NEWLINE;
1776 case 'R': /* regex */ 1689 break;
1777 cflags |= REG_ICASE; 1690 case 'R': /* regex */
1691 cflags |= REG_ICASE;
1778 // fall through 1692 // fall through
1779 case 'r': /* regex */ 1693 case 'r': /* regex */
1780 strncpy (regexp, optarg, MAX_RE_SIZE - 1); 1694 strncpy(regexp, optarg, MAX_RE_SIZE - 1);
1781 regexp[MAX_RE_SIZE - 1] = 0; 1695 regexp[MAX_RE_SIZE - 1] = 0;
1782 errcode = regcomp (&preg, regexp, cflags); 1696 errcode = regcomp(&preg, regexp, cflags);
1783 if (errcode != 0) { 1697 if (errcode != 0) {
1784 (void) regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 1698 (void)regerror(errcode, &preg, errbuf, MAX_INPUT_BUFFER);
1785 printf (_("Could Not Compile Regular Expression: %s"), errbuf); 1699 printf(_("Could Not Compile Regular Expression: %s"), errbuf);
1786 return false; 1700 return false;
1787 } 1701 }
1788 break; 1702 break;
1789 case INVERT_REGEX: 1703 case INVERT_REGEX:
1790 invert_regex = true; 1704 invert_regex = true;
1791 break; 1705 break;
1792 case STATE_REGEX: 1706 case STATE_REGEX:
1793 if (!strcasecmp (optarg, "critical")) 1707 if (!strcasecmp(optarg, "critical"))
1794 state_regex = STATE_CRITICAL; 1708 state_regex = STATE_CRITICAL;
1795 else if (!strcasecmp (optarg, "warning")) 1709 else if (!strcasecmp(optarg, "warning"))
1796 state_regex = STATE_WARNING; 1710 state_regex = STATE_WARNING;
1797 else usage2 (_("Invalid state-regex option"), optarg); 1711 else
1798 break; 1712 usage2(_("Invalid state-regex option"), optarg);
1799 case '4': 1713 break;
1800 address_family = AF_INET; 1714 case '4':
1801 break; 1715 address_family = AF_INET;
1802 case '6': 1716 break;
1803#if defined (USE_IPV6) && defined (LIBCURL_FEATURE_IPV6) 1717 case '6':
1804 address_family = AF_INET6; 1718#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6)
1719 address_family = AF_INET6;
1805#else 1720#else
1806 usage4 (_("IPv6 support not available")); 1721 usage4(_("IPv6 support not available"));
1807#endif 1722#endif
1808 break; 1723 break;
1809 case 'm': /* min_page_length */ 1724 case 'm': /* min_page_length */
1810 { 1725 {
1811 char *tmp; 1726 char *tmp;
1812 if (strchr(optarg, ':') != (char *)NULL) { 1727 if (strchr(optarg, ':') != (char *)NULL) {
1813 /* range, so get two values, min:max */ 1728 /* range, so get two values, min:max */
1814 tmp = strtok(optarg, ":"); 1729 tmp = strtok(optarg, ":");
1815 if (tmp == NULL) { 1730 if (tmp == NULL) {
1816 printf("Bad format: try \"-m min:max\"\n"); 1731 printf("Bad format: try \"-m min:max\"\n");
1817 exit (STATE_WARNING); 1732 exit(STATE_WARNING);
1818 } else 1733 } else
1819 min_page_len = atoi(tmp); 1734 min_page_len = atoi(tmp);
1820 1735
1821 tmp = strtok(NULL, ":"); 1736 tmp = strtok(NULL, ":");
1822 if (tmp == NULL) { 1737 if (tmp == NULL) {
1823 printf("Bad format: try \"-m min:max\"\n"); 1738 printf("Bad format: try \"-m min:max\"\n");
1824 exit (STATE_WARNING); 1739 exit(STATE_WARNING);
1825 } else 1740 } else
1826 max_page_len = atoi(tmp); 1741 max_page_len = atoi(tmp);
1827 } else 1742 } else
1828 min_page_len = atoi (optarg); 1743 min_page_len = atoi(optarg);
1829 break; 1744 break;
1830 } 1745 }
1831 case 'N': /* no-body */ 1746 case 'N': /* no-body */
1832 no_body = true; 1747 no_body = true;
1833 break; 1748 break;
1834 case 'M': /* max-age */ 1749 case 'M': /* max-age */
1835 { 1750 {
1836 int L = strlen(optarg); 1751 int L = strlen(optarg);
1837 if (L && optarg[L-1] == 'm') 1752 if (L && optarg[L - 1] == 'm')
1838 maximum_age = atoi (optarg) * 60; 1753 maximum_age = atoi(optarg) * 60;
1839 else if (L && optarg[L-1] == 'h') 1754 else if (L && optarg[L - 1] == 'h')
1840 maximum_age = atoi (optarg) * 60 * 60; 1755 maximum_age = atoi(optarg) * 60 * 60;
1841 else if (L && optarg[L-1] == 'd') 1756 else if (L && optarg[L - 1] == 'd')
1842 maximum_age = atoi (optarg) * 60 * 60 * 24; 1757 maximum_age = atoi(optarg) * 60 * 60 * 24;
1843 else if (L && (optarg[L-1] == 's' || 1758 else if (L && (optarg[L - 1] == 's' || isdigit(optarg[L - 1])))
1844 isdigit (optarg[L-1]))) 1759 maximum_age = atoi(optarg);
1845 maximum_age = atoi (optarg); 1760 else {
1846 else { 1761 fprintf(stderr, "unparsable max-age: %s\n", optarg);
1847 fprintf (stderr, "unparsable max-age: %s\n", optarg); 1762 exit(STATE_WARNING);
1848 exit (STATE_WARNING); 1763 }
1849 } 1764 if (verbose >= 2)
1850 if (verbose >= 2) 1765 printf("* Maximal age of document set to %d seconds\n", maximum_age);
1851 printf ("* Maximal age of document set to %d seconds\n", maximum_age); 1766 } break;
1852 } 1767 case 'E': /* show extended perfdata */
1853 break; 1768 show_extended_perfdata = true;
1854 case 'E': /* show extended perfdata */ 1769 break;
1855 show_extended_perfdata = true; 1770 case 'B': /* print body content after status line */
1856 break; 1771 show_body = true;
1857 case 'B': /* print body content after status line */ 1772 break;
1858 show_body = true; 1773 case HTTP_VERSION_OPTION:
1859 break; 1774 curl_http_version = CURL_HTTP_VERSION_NONE;
1860 case HTTP_VERSION_OPTION: 1775 if (strcmp(optarg, "1.0") == 0) {
1861 curl_http_version = CURL_HTTP_VERSION_NONE; 1776 curl_http_version = CURL_HTTP_VERSION_1_0;
1862 if (strcmp (optarg, "1.0") == 0) { 1777 } else if (strcmp(optarg, "1.1") == 0) {
1863 curl_http_version = CURL_HTTP_VERSION_1_0; 1778 curl_http_version = CURL_HTTP_VERSION_1_1;
1864 } else if (strcmp (optarg, "1.1") == 0) { 1779 } else if ((strcmp(optarg, "2.0") == 0) || (strcmp(optarg, "2") == 0)) {
1865 curl_http_version = CURL_HTTP_VERSION_1_1;
1866 } else if ((strcmp (optarg, "2.0") == 0) || (strcmp (optarg, "2") == 0)) {
1867#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) 1780#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0)
1868 curl_http_version = CURL_HTTP_VERSION_2_0; 1781 curl_http_version = CURL_HTTP_VERSION_2_0;
1869#else 1782#else
1870 curl_http_version = CURL_HTTP_VERSION_NONE; 1783 curl_http_version = CURL_HTTP_VERSION_NONE;
1871#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) */ 1784#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) */
1872 } else { 1785 } else {
1873 fprintf (stderr, "unknown http-version parameter: %s\n", optarg); 1786 fprintf(stderr, "unknown http-version parameter: %s\n", optarg);
1874 exit (STATE_WARNING); 1787 exit(STATE_WARNING);
1875 } 1788 }
1876 break; 1789 break;
1877 case AUTOMATIC_DECOMPRESSION: 1790 case AUTOMATIC_DECOMPRESSION:
1878 automatic_decompression = true; 1791 automatic_decompression = true;
1879 break; 1792 break;
1880 case COOKIE_JAR: 1793 case COOKIE_JAR:
1881 cookie_jar_file = optarg; 1794 cookie_jar_file = optarg;
1882 break; 1795 break;
1883 case HAPROXY_PROTOCOL: 1796 case HAPROXY_PROTOCOL:
1884 haproxy_protocol = true; 1797 haproxy_protocol = true;
1885 break; 1798 break;
1886 case '?': 1799 case '?':
1887 /* print short usage statement if args not parsable */ 1800 /* print short usage statement if args not parsable */
1888 usage5 (); 1801 usage5();
1889 break; 1802 break;
1890 } 1803 }
1891 } 1804 }
1892 1805
1893 c = optind; 1806 c = optind;
1894 1807
1895 if (server_address == NULL && c < argc) 1808 if (server_address == NULL && c < argc)
1896 server_address = strdup (argv[c++]); 1809 server_address = strdup(argv[c++]);
1897 1810
1898 if (host_name == NULL && c < argc) 1811 if (host_name == NULL && c < argc)
1899 host_name = strdup (argv[c++]); 1812 host_name = strdup(argv[c++]);
1900 1813
1901 if (server_address == NULL) { 1814 if (server_address == NULL) {
1902 if (host_name == NULL) 1815 if (host_name == NULL)
1903 usage4 (_("You must specify a server address or host name")); 1816 usage4(_("You must specify a server address or host name"));
1904 else 1817 else
1905 server_address = strdup (host_name); 1818 server_address = strdup(host_name);
1906 } 1819 }
1907 1820
1908 set_thresholds(&thlds, warning_thresholds, critical_thresholds); 1821 set_thresholds(&thlds, warning_thresholds, critical_thresholds);
1909 1822
1910 if (critical_thresholds && thlds->critical->end>(double)socket_timeout) 1823 if (critical_thresholds && thlds->critical->end > (double)socket_timeout)
1911 socket_timeout = (int)thlds->critical->end + 1; 1824 socket_timeout = (int)thlds->critical->end + 1;
1912 if (verbose >= 2) 1825 if (verbose >= 2)
1913 printf ("* Socket timeout set to %ld seconds\n", socket_timeout); 1826 printf("* Socket timeout set to %ld seconds\n", socket_timeout);
1914 1827
1915 if (http_method == NULL) 1828 if (http_method == NULL)
1916 http_method = strdup ("GET"); 1829 http_method = strdup("GET");
1917 1830
1918 if (client_cert && !client_privkey) 1831 if (client_cert && !client_privkey)
1919 usage4 (_("If you use a client certificate you must also specify a private key file")); 1832 usage4(_("If you use a client certificate you must also specify a private key file"));
1920 1833
1921 if (virtual_port == 0) 1834 if (virtual_port == 0)
1922 virtual_port = server_port; 1835 virtual_port = server_port;
1923 else { 1836 else {
1924 if ((use_ssl && server_port == HTTPS_PORT) || (!use_ssl && server_port == HTTP_PORT)) 1837 if ((use_ssl && server_port == HTTPS_PORT) || (!use_ssl && server_port == HTTP_PORT))
1925 if(!specify_port) 1838 if (!specify_port)
1926 server_port = virtual_port; 1839 server_port = virtual_port;
1927 } 1840 }
1928 1841
1929 return true; 1842 return true;
1930} 1843}
1931 1844
1932char *perfd_time (double elapsed_time) 1845char *perfd_time(double elapsed_time) {
1933{ 1846 return fperfdata("time", elapsed_time, "s", thlds->warning ? true : false, thlds->warning ? thlds->warning->end : 0,
1934 return fperfdata ("time", elapsed_time, "s", 1847 thlds->critical ? true : false, thlds->critical ? thlds->critical->end : 0, true, 0, true, socket_timeout);
1935 thlds->warning?true:false, thlds->warning?thlds->warning->end:0,
1936 thlds->critical?true:false, thlds->critical?thlds->critical->end:0,
1937 true, 0, true, socket_timeout);
1938} 1848}
1939 1849
1940char *perfd_time_connect (double elapsed_time_connect) 1850char *perfd_time_connect(double elapsed_time_connect) {
1941{ 1851 return fperfdata("time_connect", elapsed_time_connect, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1942 return fperfdata ("time_connect", elapsed_time_connect, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1943} 1852}
1944 1853
1945char *perfd_time_ssl (double elapsed_time_ssl) 1854char *perfd_time_ssl(double elapsed_time_ssl) {
1946{ 1855 return fperfdata("time_ssl", elapsed_time_ssl, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1947 return fperfdata ("time_ssl", elapsed_time_ssl, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1948} 1856}
1949 1857
1950char *perfd_time_headers (double elapsed_time_headers) 1858char *perfd_time_headers(double elapsed_time_headers) {
1951{ 1859 return fperfdata("time_headers", elapsed_time_headers, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1952 return fperfdata ("time_headers", elapsed_time_headers, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1953} 1860}
1954 1861
1955char *perfd_time_firstbyte (double elapsed_time_firstbyte) 1862char *perfd_time_firstbyte(double elapsed_time_firstbyte) {
1956{ 1863 return fperfdata("time_firstbyte", elapsed_time_firstbyte, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1957 return fperfdata ("time_firstbyte", elapsed_time_firstbyte, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1958} 1864}
1959 1865
1960char *perfd_time_transfer (double elapsed_time_transfer) 1866char *perfd_time_transfer(double elapsed_time_transfer) {
1961{ 1867 return fperfdata("time_transfer", elapsed_time_transfer, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1962 return fperfdata ("time_transfer", elapsed_time_transfer, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1963} 1868}
1964 1869
1965char *perfd_size (int page_len) 1870char *perfd_size(int page_len) {
1966{ 1871 return perfdata("size", page_len, "B", (min_page_len > 0 ? true : false), min_page_len, (min_page_len > 0 ? true : false), 0, true, 0,
1967 return perfdata ("size", page_len, "B", 1872 false, 0);
1968 (min_page_len>0?true:false), min_page_len,
1969 (min_page_len>0?true:false), 0,
1970 true, 0, false, 0);
1971} 1873}
1972 1874
1973void 1875void print_help(void) {
1974print_help (void) 1876 print_revision(progname, NP_VERSION);
1975{
1976 print_revision (progname, NP_VERSION);
1977 1877
1978 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 1878 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
1979 printf (COPYRIGHT, copyright, email); 1879 printf(COPYRIGHT, copyright, email);
1980 1880
1981 printf ("%s\n", _("This plugin tests the HTTP service on the specified host. It can test")); 1881 printf("%s\n", _("This plugin tests the HTTP service on the specified host. It can test"));
1982 printf ("%s\n", _("normal (http) and secure (https) servers, follow redirects, search for")); 1882 printf("%s\n", _("normal (http) and secure (https) servers, follow redirects, search for"));
1983 printf ("%s\n", _("strings and regular expressions, check connection times, and report on")); 1883 printf("%s\n", _("strings and regular expressions, check connection times, and report on"));
1984 printf ("%s\n", _("certificate expiration times.")); 1884 printf("%s\n", _("certificate expiration times."));
1985 printf ("\n"); 1885 printf("\n");
1986 printf ("%s\n", _("It makes use of libcurl to do so. It tries to be as compatible to check_http")); 1886 printf("%s\n", _("It makes use of libcurl to do so. It tries to be as compatible to check_http"));
1987 printf ("%s\n", _("as possible.")); 1887 printf("%s\n", _("as possible."));
1988 1888
1989 printf ("\n\n"); 1889 printf("\n\n");
1990 1890
1991 print_usage (); 1891 print_usage();
1992 1892
1993 printf (_("NOTE: One or both of -H and -I must be specified")); 1893 printf(_("NOTE: One or both of -H and -I must be specified"));
1994 1894
1995 printf ("\n"); 1895 printf("\n");
1996 1896
1997 printf (UT_HELP_VRSN); 1897 printf(UT_HELP_VRSN);
1998 printf (UT_EXTRA_OPTS); 1898 printf(UT_EXTRA_OPTS);
1999 1899
2000 printf (" %s\n", "-H, --hostname=ADDRESS"); 1900 printf(" %s\n", "-H, --hostname=ADDRESS");
2001 printf (" %s\n", _("Host name argument for servers using host headers (virtual host)")); 1901 printf(" %s\n", _("Host name argument for servers using host headers (virtual host)"));
2002 printf (" %s\n", _("Append a port to include it in the header (eg: example.com:5000)")); 1902 printf(" %s\n", _("Append a port to include it in the header (eg: example.com:5000)"));
2003 printf (" %s\n", "-I, --IP-address=ADDRESS"); 1903 printf(" %s\n", "-I, --IP-address=ADDRESS");
2004 printf (" %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup).")); 1904 printf(" %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup)."));
2005 printf (" %s\n", "-p, --port=INTEGER"); 1905 printf(" %s\n", "-p, --port=INTEGER");
2006 printf (" %s", _("Port number (default: ")); 1906 printf(" %s", _("Port number (default: "));
2007 printf ("%d)\n", HTTP_PORT); 1907 printf("%d)\n", HTTP_PORT);
2008 1908
2009 printf (UT_IPv46); 1909 printf(UT_IPv46);
2010 1910
2011#ifdef LIBCURL_FEATURE_SSL 1911#ifdef LIBCURL_FEATURE_SSL
2012 printf (" %s\n", "-S, --ssl=VERSION[+]"); 1912 printf(" %s\n", "-S, --ssl=VERSION[+]");
2013 printf (" %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents")); 1913 printf(" %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents"));
2014 printf (" %s\n", _("auto-negotiation (2 = SSLv2, 3 = SSLv3, 1 = TLSv1, 1.1 = TLSv1.1,")); 1914 printf(" %s\n", _("auto-negotiation (2 = SSLv2, 3 = SSLv3, 1 = TLSv1, 1.1 = TLSv1.1,"));
2015 printf (" %s\n", _("1.2 = TLSv1.2, 1.3 = TLSv1.3). With a '+' suffix, newer versions are also accepted.")); 1915 printf(" %s\n", _("1.2 = TLSv1.2, 1.3 = TLSv1.3). With a '+' suffix, newer versions are also accepted."));
2016 printf (" %s\n", _("Note: SSLv2 and SSLv3 are deprecated and are usually disabled in libcurl")); 1916 printf(" %s\n", _("Note: SSLv2 and SSLv3 are deprecated and are usually disabled in libcurl"));
2017 printf (" %s\n", "--sni"); 1917 printf(" %s\n", "--sni");
2018 printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)")); 1918 printf(" %s\n", _("Enable SSL/TLS hostname extension support (SNI)"));
2019#if LIBCURL_VERSION_NUM >= 0x071801 1919# if LIBCURL_VERSION_NUM >= 0x071801
2020 printf (" %s\n", _("Note: --sni is the default in libcurl as SSLv2 and SSLV3 are deprecated and")); 1920 printf(" %s\n", _("Note: --sni is the default in libcurl as SSLv2 and SSLV3 are deprecated and"));
2021 printf (" %s\n", _(" SNI only really works since TLSv1.0")); 1921 printf(" %s\n", _(" SNI only really works since TLSv1.0"));
2022#else 1922# else
2023 printf (" %s\n", _("Note: SNI is not supported in libcurl before 7.18.1")); 1923 printf(" %s\n", _("Note: SNI is not supported in libcurl before 7.18.1"));
2024#endif 1924# endif
2025 printf (" %s\n", "-C, --certificate=INTEGER[,INTEGER]"); 1925 printf(" %s\n", "-C, --certificate=INTEGER[,INTEGER]");
2026 printf (" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443.")); 1926 printf(" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443."));
2027 printf (" %s\n", _("A STATE_WARNING is returned if the certificate has a validity less than the")); 1927 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")); 1928 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.")); 1929 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")); 1930 printf(" %s\n", _("(When this option is used the URL is not checked by default. You can use"));
2031 printf (" %s\n", _(" --continue-after-certificate to override this behavior)")); 1931 printf(" %s\n", _(" --continue-after-certificate to override this behavior)"));
2032 printf (" %s\n", "--continue-after-certificate"); 1932 printf(" %s\n", "--continue-after-certificate");
2033 printf (" %s\n", _("Allows the HTTP check to continue after performing the certificate check.")); 1933 printf(" %s\n", _("Allows the HTTP check to continue after performing the certificate check."));
2034 printf (" %s\n", _("Does nothing unless -C is used.")); 1934 printf(" %s\n", _("Does nothing unless -C is used."));
2035 printf (" %s\n", "-J, --client-cert=FILE"); 1935 printf(" %s\n", "-J, --client-cert=FILE");
2036 printf (" %s\n", _("Name of file that contains the client certificate (PEM format)")); 1936 printf(" %s\n", _("Name of file that contains the client certificate (PEM format)"));
2037 printf (" %s\n", _("to be used in establishing the SSL session")); 1937 printf(" %s\n", _("to be used in establishing the SSL session"));
2038 printf (" %s\n", "-K, --private-key=FILE"); 1938 printf(" %s\n", "-K, --private-key=FILE");
2039 printf (" %s\n", _("Name of file containing the private key (PEM format)")); 1939 printf(" %s\n", _("Name of file containing the private key (PEM format)"));
2040 printf (" %s\n", _("matching the client certificate")); 1940 printf(" %s\n", _("matching the client certificate"));
2041 printf (" %s\n", "--ca-cert=FILE"); 1941 printf(" %s\n", "--ca-cert=FILE");
2042 printf (" %s\n", _("CA certificate file to verify peer against")); 1942 printf(" %s\n", _("CA certificate file to verify peer against"));
2043 printf (" %s\n", "-D, --verify-cert"); 1943 printf(" %s\n", "-D, --verify-cert");
2044 printf (" %s\n", _("Verify the peer's SSL certificate and hostname")); 1944 printf(" %s\n", _("Verify the peer's SSL certificate and hostname"));
2045#endif 1945#endif
2046 1946
2047 printf (" %s\n", "-e, --expect=STRING"); 1947 printf(" %s\n", "-e, --expect=STRING");
2048 printf (" %s\n", _("Comma-delimited list of strings, at least one of them is expected in")); 1948 printf(" %s\n", _("Comma-delimited list of strings, at least one of them is expected in"));
2049 printf (" %s", _("the first (status) line of the server response (default: ")); 1949 printf(" %s", _("the first (status) line of the server response (default: "));
2050 printf ("%s)\n", HTTP_EXPECT); 1950 printf("%s)\n", HTTP_EXPECT);
2051 printf (" %s\n", _("If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)")); 1951 printf(" %s\n", _("If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)"));
2052 printf (" %s\n", "-d, --header-string=STRING"); 1952 printf(" %s\n", "-d, --header-string=STRING");
2053 printf (" %s\n", _("String to expect in the response headers")); 1953 printf(" %s\n", _("String to expect in the response headers"));
2054 printf (" %s\n", "-s, --string=STRING"); 1954 printf(" %s\n", "-s, --string=STRING");
2055 printf (" %s\n", _("String to expect in the content")); 1955 printf(" %s\n", _("String to expect in the content"));
2056 printf (" %s\n", "-u, --url=PATH"); 1956 printf(" %s\n", "-u, --url=PATH");
2057 printf (" %s\n", _("URL to GET or POST (default: /)")); 1957 printf(" %s\n", _("URL to GET or POST (default: /)"));
2058 printf (" %s\n", "-P, --post=STRING"); 1958 printf(" %s\n", "-P, --post=STRING");
2059 printf (" %s\n", _("URL decoded http POST data")); 1959 printf(" %s\n", _("URL decoded http POST data"));
2060 printf (" %s\n", "-j, --method=STRING (for example: HEAD, OPTIONS, TRACE, PUT, DELETE, CONNECT)"); 1960 printf(" %s\n", "-j, --method=STRING (for example: HEAD, OPTIONS, TRACE, PUT, DELETE, CONNECT)");
2061 printf (" %s\n", _("Set HTTP method.")); 1961 printf(" %s\n", _("Set HTTP method."));
2062 printf (" %s\n", "-N, --no-body"); 1962 printf(" %s\n", "-N, --no-body");
2063 printf (" %s\n", _("Don't wait for document body: stop reading after headers.")); 1963 printf(" %s\n", _("Don't wait for document body: stop reading after headers."));
2064 printf (" %s\n", _("(Note that this still does an HTTP GET or POST, not a HEAD.)")); 1964 printf(" %s\n", _("(Note that this still does an HTTP GET or POST, not a HEAD.)"));
2065 printf (" %s\n", "-M, --max-age=SECONDS"); 1965 printf(" %s\n", "-M, --max-age=SECONDS");
2066 printf (" %s\n", _("Warn if document is more than SECONDS old. the number can also be of")); 1966 printf(" %s\n", _("Warn if document is more than SECONDS old. the number can also be of"));
2067 printf (" %s\n", _("the form \"10m\" for minutes, \"10h\" for hours, or \"10d\" for days.")); 1967 printf(" %s\n", _("the form \"10m\" for minutes, \"10h\" for hours, or \"10d\" for days."));
2068 printf (" %s\n", "-T, --content-type=STRING"); 1968 printf(" %s\n", "-T, --content-type=STRING");
2069 printf (" %s\n", _("specify Content-Type header media type when POSTing\n")); 1969 printf(" %s\n", _("specify Content-Type header media type when POSTing\n"));
2070 printf (" %s\n", "-l, --linespan"); 1970 printf(" %s\n", "-l, --linespan");
2071 printf (" %s\n", _("Allow regex to span newlines (must precede -r or -R)")); 1971 printf(" %s\n", _("Allow regex to span newlines (must precede -r or -R)"));
2072 printf (" %s\n", "-r, --regex, --ereg=STRING"); 1972 printf(" %s\n", "-r, --regex, --ereg=STRING");
2073 printf (" %s\n", _("Search page for regex STRING")); 1973 printf(" %s\n", _("Search page for regex STRING"));
2074 printf (" %s\n", "-R, --eregi=STRING"); 1974 printf(" %s\n", "-R, --eregi=STRING");
2075 printf (" %s\n", _("Search page for case-insensitive regex STRING")); 1975 printf(" %s\n", _("Search page for case-insensitive regex STRING"));
2076 printf (" %s\n", "--invert-regex"); 1976 printf(" %s\n", "--invert-regex");
2077 printf (" %s\n", _("Return STATE if found, OK if not (STATE is CRITICAL, per default)")); 1977 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)")); 1978 printf(" %s\n", _("can be changed with --state--regex)"));
2079 printf (" %s\n", "--state-regex=STATE"); 1979 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\"")); 1980 printf(" %s\n", _("Return STATE if regex is found, OK if not. STATE can be one of \"critical\",\"warning\""));
2081 printf (" %s\n", "-a, --authorization=AUTH_PAIR"); 1981 printf(" %s\n", "-a, --authorization=AUTH_PAIR");
2082 printf (" %s\n", _("Username:password on sites with basic authentication")); 1982 printf(" %s\n", _("Username:password on sites with basic authentication"));
2083 printf (" %s\n", "-b, --proxy-authorization=AUTH_PAIR"); 1983 printf(" %s\n", "-b, --proxy-authorization=AUTH_PAIR");
2084 printf (" %s\n", _("Username:password on proxy-servers with basic authentication")); 1984 printf(" %s\n", _("Username:password on proxy-servers with basic authentication"));
2085 printf (" %s\n", "-A, --useragent=STRING"); 1985 printf(" %s\n", "-A, --useragent=STRING");
2086 printf (" %s\n", _("String to be sent in http header as \"User Agent\"")); 1986 printf(" %s\n", _("String to be sent in http header as \"User Agent\""));
2087 printf (" %s\n", "-k, --header=STRING"); 1987 printf(" %s\n", "-k, --header=STRING");
2088 printf (" %s\n", _("Any other tags to be sent in http header. Use multiple times for additional headers")); 1988 printf(" %s\n", _("Any other tags to be sent in http header. Use multiple times for additional headers"));
2089 printf (" %s\n", "-E, --extended-perfdata"); 1989 printf(" %s\n", "-E, --extended-perfdata");
2090 printf (" %s\n", _("Print additional performance data")); 1990 printf(" %s\n", _("Print additional performance data"));
2091 printf (" %s\n", "-B, --show-body"); 1991 printf(" %s\n", "-B, --show-body");
2092 printf (" %s\n", _("Print body content below status line")); 1992 printf(" %s\n", _("Print body content below status line"));
2093 printf (" %s\n", "-L, --link"); 1993 printf(" %s\n", "-L, --link");
2094 printf (" %s\n", _("Wrap output in HTML link (obsoleted by urlize)")); 1994 printf(" %s\n", _("Wrap output in HTML link (obsoleted by urlize)"));
2095 printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport|curl>"); 1995 printf(" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport|curl>");
2096 printf (" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the")); 1996 printf(" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the"));
2097 printf (" %s\n", _("specified IP address. stickyport also ensures port stays the same.")); 1997 printf(" %s\n", _("specified IP address. stickyport also ensures port stays the same."));
2098 printf (" %s\n", _("follow uses the old redirection algorithm of check_http.")); 1998 printf(" %s\n", _("follow uses the old redirection algorithm of check_http."));
2099 printf (" %s\n", _("curl uses CURL_FOLLOWLOCATION built into libcurl.")); 1999 printf(" %s\n", _("curl uses CURL_FOLLOWLOCATION built into libcurl."));
2100 printf (" %s\n", "--max-redirs=INTEGER"); 2000 printf(" %s\n", "--max-redirs=INTEGER");
2101 printf (" %s", _("Maximal number of redirects (default: ")); 2001 printf(" %s", _("Maximal number of redirects (default: "));
2102 printf ("%d)\n", DEFAULT_MAX_REDIRS); 2002 printf("%d)\n", DEFAULT_MAX_REDIRS);
2103 printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>"); 2003 printf(" %s\n", "-m, --pagesize=INTEGER<:INTEGER>");
2104 printf (" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)")); 2004 printf(" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)"));
2105 printf ("\n"); 2005 printf("\n");
2106 printf (" %s\n", "--http-version=VERSION"); 2006 printf(" %s\n", "--http-version=VERSION");
2107 printf (" %s\n", _("Connect via specific HTTP protocol.")); 2007 printf(" %s\n", _("Connect via specific HTTP protocol."));
2108 printf (" %s\n", _("1.0 = HTTP/1.0, 1.1 = HTTP/1.1, 2.0 = HTTP/2 (HTTP/2 will fail without -S)")); 2008 printf(" %s\n", _("1.0 = HTTP/1.0, 1.1 = HTTP/1.1, 2.0 = HTTP/2 (HTTP/2 will fail without -S)"));
2109 printf (" %s\n", "--enable-automatic-decompression"); 2009 printf(" %s\n", "--enable-automatic-decompression");
2110 printf (" %s\n", _("Enable automatic decompression of body (CURLOPT_ACCEPT_ENCODING).")); 2010 printf(" %s\n", _("Enable automatic decompression of body (CURLOPT_ACCEPT_ENCODING)."));
2111 printf(" %s\n", "--haproxy-protocol"); 2011 printf(" %s\n", "--haproxy-protocol");
2112 printf(" %s\n", _("Send HAProxy proxy protocol v1 header (CURLOPT_HAPROXYPROTOCOL).")); 2012 printf(" %s\n", _("Send HAProxy proxy protocol v1 header (CURLOPT_HAPROXYPROTOCOL)."));
2113 printf (" %s\n", "--cookie-jar=FILE"); 2013 printf(" %s\n", "--cookie-jar=FILE");
2114 printf (" %s\n", _("Store cookies in the cookie jar and send them out when requested.")); 2014 printf(" %s\n", _("Store cookies in the cookie jar and send them out when requested."));
2115 printf ("\n"); 2015 printf("\n");
2116 2016
2117 printf (UT_WARN_CRIT); 2017 printf(UT_WARN_CRIT);
2118 2018
2119 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 2019 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
2120 2020
2121 printf (UT_VERBOSE); 2021 printf(UT_VERBOSE);
2122 2022
2123 printf ("\n"); 2023 printf("\n");
2124 printf ("%s\n", _("Notes:")); 2024 printf("%s\n", _("Notes:"));
2125 printf (" %s\n", _("This plugin will attempt to open an HTTP connection with the host.")); 2025 printf(" %s\n", _("This plugin will attempt to open an HTTP connection with the host."));
2126 printf (" %s\n", _("Successful connects return STATE_OK, refusals and timeouts return STATE_CRITICAL")); 2026 printf(" %s\n", _("Successful connects return STATE_OK, refusals and timeouts return STATE_CRITICAL"));
2127 printf (" %s\n", _("other errors return STATE_UNKNOWN. Successful connects, but incorrect response")); 2027 printf(" %s\n", _("other errors return STATE_UNKNOWN. Successful connects, but incorrect response"));
2128 printf (" %s\n", _("messages from the host result in STATE_WARNING return values. If you are")); 2028 printf(" %s\n", _("messages from the host result in STATE_WARNING return values. If you are"));
2129 printf (" %s\n", _("checking a virtual server that uses 'host headers' you must supply the FQDN")); 2029 printf(" %s\n", _("checking a virtual server that uses 'host headers' you must supply the FQDN"));
2130 printf (" %s\n", _("(fully qualified domain name) as the [host_name] argument.")); 2030 printf(" %s\n", _("(fully qualified domain name) as the [host_name] argument."));
2131 2031
2132#ifdef LIBCURL_FEATURE_SSL 2032#ifdef LIBCURL_FEATURE_SSL
2133 printf ("\n"); 2033 printf("\n");
2134 printf (" %s\n", _("This plugin can also check whether an SSL enabled web server is able to")); 2034 printf(" %s\n", _("This plugin can also check whether an SSL enabled web server is able to"));
2135 printf (" %s\n", _("serve content (optionally within a specified time) or whether the X509 ")); 2035 printf(" %s\n", _("serve content (optionally within a specified time) or whether the X509 "));
2136 printf (" %s\n", _("certificate is still valid for the specified number of days.")); 2036 printf(" %s\n", _("certificate is still valid for the specified number of days."));
2137 printf ("\n"); 2037 printf("\n");
2138 printf (" %s\n", _("Please note that this plugin does not check if the presented server")); 2038 printf(" %s\n", _("Please note that this plugin does not check if the presented server"));
2139 printf (" %s\n", _("certificate matches the hostname of the server, or if the certificate")); 2039 printf(" %s\n", _("certificate matches the hostname of the server, or if the certificate"));
2140 printf (" %s\n", _("has a valid chain of trust to one of the locally installed CAs.")); 2040 printf(" %s\n", _("has a valid chain of trust to one of the locally installed CAs."));
2141 printf ("\n"); 2041 printf("\n");
2142 printf ("%s\n", _("Examples:")); 2042 printf("%s\n", _("Examples:"));
2143 printf (" %s\n\n", "CHECK CONTENT: check_curl -w 5 -c 10 --ssl -H www.verisign.com"); 2043 printf(" %s\n\n", "CHECK CONTENT: check_curl -w 5 -c 10 --ssl -H www.verisign.com");
2144 printf (" %s\n", _("When the 'www.verisign.com' server returns its content within 5 seconds,")); 2044 printf(" %s\n", _("When the 'www.verisign.com' server returns its content within 5 seconds,"));
2145 printf (" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds")); 2045 printf(" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds"));
2146 printf (" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,")); 2046 printf(" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,"));
2147 printf (" %s\n", _("a STATE_CRITICAL will be returned.")); 2047 printf(" %s\n", _("a STATE_CRITICAL will be returned."));
2148 printf ("\n"); 2048 printf("\n");
2149 printf (" %s\n\n", "CHECK CERTIFICATE: check_curl -H www.verisign.com -C 14"); 2049 printf(" %s\n\n", "CHECK CERTIFICATE: check_curl -H www.verisign.com -C 14");
2150 printf (" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 14 days,")); 2050 printf(" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 14 days,"));
2151 printf (" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than")); 2051 printf(" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than"));
2152 printf (" %s\n", _("14 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when")); 2052 printf(" %s\n", _("14 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when"));
2153 printf (" %s\n\n", _("the certificate is expired.")); 2053 printf(" %s\n\n", _("the certificate is expired."));
2154 printf ("\n"); 2054 printf("\n");
2155 printf (" %s\n\n", "CHECK CERTIFICATE: check_curl -H www.verisign.com -C 30,14"); 2055 printf(" %s\n\n", "CHECK CERTIFICATE: check_curl -H www.verisign.com -C 30,14");
2156 printf (" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 30 days,")); 2056 printf(" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 30 days,"));
2157 printf (" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than")); 2057 printf(" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than"));
2158 printf (" %s\n", _("30 days, but more than 14 days, a STATE_WARNING is returned.")); 2058 printf(" %s\n", _("30 days, but more than 14 days, a STATE_WARNING is returned."));
2159 printf (" %s\n", _("A STATE_CRITICAL will be returned when certificate expires in less than 14 days")); 2059 printf(" %s\n", _("A STATE_CRITICAL will be returned when certificate expires in less than 14 days"));
2160#endif 2060#endif
2161 2061
2162 printf ("\n %s\n", "CHECK WEBSERVER CONTENT VIA PROXY:"); 2062 printf("\n %s\n", "CHECK WEBSERVER CONTENT VIA PROXY:");
2163 printf (" %s\n", _("It is recommended to use an environment proxy like:")); 2063 printf(" %s\n", _("It is recommended to use an environment proxy like:"));
2164 printf (" %s\n", _("http_proxy=http://192.168.100.35:3128 ./check_curl -H www.monitoring-plugins.org")); 2064 printf(" %s\n", _("http_proxy=http://192.168.100.35:3128 ./check_curl -H www.monitoring-plugins.org"));
2165 printf (" %s\n", _("legacy proxy requests in check_http style still work:")); 2065 printf(" %s\n", _("legacy proxy requests in check_http style still work:"));
2166 printf (" %s\n", _("check_curl -I 192.168.100.35 -p 3128 -u http://www.monitoring-plugins.org/ -H www.monitoring-plugins.org")); 2066 printf(" %s\n", _("check_curl -I 192.168.100.35 -p 3128 -u http://www.monitoring-plugins.org/ -H www.monitoring-plugins.org"));
2167 2067
2168#ifdef LIBCURL_FEATURE_SSL 2068#ifdef LIBCURL_FEATURE_SSL
2169 printf ("\n %s\n", "CHECK SSL WEBSERVER CONTENT VIA PROXY USING HTTP 1.1 CONNECT: "); 2069 printf("\n %s\n", "CHECK SSL WEBSERVER CONTENT VIA PROXY USING HTTP 1.1 CONNECT: ");
2170 printf (" %s\n", _("It is recommended to use an environment proxy like:")); 2070 printf(" %s\n", _("It is recommended to use an environment proxy like:"));
2171 printf (" %s\n", _("https_proxy=http://192.168.100.35:3128 ./check_curl -H www.verisign.com -S")); 2071 printf(" %s\n", _("https_proxy=http://192.168.100.35:3128 ./check_curl -H www.verisign.com -S"));
2172 printf (" %s\n", _("legacy proxy requests in check_http style still work:")); 2072 printf(" %s\n", _("legacy proxy requests in check_http style still work:"));
2173 printf (" %s\n", _("check_curl -I 192.168.100.35 -p 3128 -u https://www.verisign.com/ -S -j CONNECT -H www.verisign.com ")); 2073 printf(" %s\n", _("check_curl -I 192.168.100.35 -p 3128 -u https://www.verisign.com/ -S -j CONNECT -H www.verisign.com "));
2174 printf (" %s\n", _("all these options are needed: -I <proxy> -p <proxy-port> -u <check-url> -S(sl) -j CONNECT -H <webserver>")); 2074 printf(" %s\n", _("all these options are needed: -I <proxy> -p <proxy-port> -u <check-url> -S(sl) -j CONNECT -H <webserver>"));
2175 printf (" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds")); 2075 printf(" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds"));
2176 printf (" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,")); 2076 printf(" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,"));
2177 printf (" %s\n", _("a STATE_CRITICAL will be returned.")); 2077 printf(" %s\n", _("a STATE_CRITICAL will be returned."));
2178 2078
2179#endif 2079#endif
2180 2080
2181 printf (UT_SUPPORT); 2081 printf(UT_SUPPORT);
2182
2183} 2082}
2184 2083
2185 2084void print_usage(void) {
2186 2085 printf("%s\n", _("Usage:"));
2187void 2086 printf(" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n", progname);
2188print_usage (void) 2087 printf(" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate file>] [-D]\n");
2189{ 2088 printf(" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-a auth]\n");
2190 printf ("%s\n", _("Usage:")); 2089 printf(" [-b proxy_auth] [-f <ok|warning|critical|follow|sticky|stickyport|curl>]\n");
2191 printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname); 2090 printf(" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n");
2192 printf (" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate file>] [-D]\n"); 2091 printf(" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n");
2193 printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-a auth]\n"); 2092 printf(" [-A string] [-k string] [-S <version>] [--sni] [--haproxy-protocol]\n");
2194 printf (" [-b proxy_auth] [-f <ok|warning|critical|follow|sticky|stickyport|curl>]\n"); 2093 printf(" [-T <content-type>] [-j method]\n");
2195 printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n"); 2094 printf(" [--http-version=<version>] [--enable-automatic-decompression]\n");
2196 printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n"); 2095 printf(" [--cookie-jar=<cookie jar file>\n");
2197 printf (" [-A string] [-k string] [-S <version>] [--sni] [--haproxy-protocol]\n"); 2096 printf(" %s -H <vhost> | -I <IP-address> -C <warn_age>[,<crit_age>]\n", progname);
2198 printf (" [-T <content-type>] [-j method]\n"); 2097 printf(" [-p <port>] [-t <timeout>] [-4|-6] [--sni]\n");
2199 printf (" [--http-version=<version>] [--enable-automatic-decompression]\n"); 2098 printf("\n");
2200 printf (" [--cookie-jar=<cookie jar file>\n");
2201 printf (" %s -H <vhost> | -I <IP-address> -C <warn_age>[,<crit_age>]\n",progname);
2202 printf (" [-p <port>] [-t <timeout>] [-4|-6] [--sni]\n");
2203 printf ("\n");
2204#ifdef LIBCURL_FEATURE_SSL 2099#ifdef LIBCURL_FEATURE_SSL
2205 printf ("%s\n", _("In the first form, make an HTTP request.")); 2100 printf("%s\n", _("In the first form, make an HTTP request."));
2206 printf ("%s\n\n", _("In the second form, connect to the server and check the TLS certificate.")); 2101 printf("%s\n\n", _("In the second form, connect to the server and check the TLS certificate."));
2207#endif 2102#endif
2208} 2103}
2209 2104
2210void 2105void print_curl_version(void) { printf("%s\n", curl_version()); }
2211print_curl_version (void)
2212{
2213 printf( "%s\n", curl_version());
2214}
2215 2106
2216int 2107int curlhelp_initwritebuffer(curlhelp_write_curlbuf *buf) {
2217curlhelp_initwritebuffer (curlhelp_write_curlbuf *buf) 2108 buf->bufsize = DEFAULT_BUFFER_SIZE;
2218{ 2109 buf->buflen = 0;
2219 buf->bufsize = DEFAULT_BUFFER_SIZE; 2110 buf->buf = (char *)malloc((size_t)buf->bufsize);
2220 buf->buflen = 0; 2111 if (buf->buf == NULL)
2221 buf->buf = (char *)malloc ((size_t)buf->bufsize); 2112 return -1;
2222 if (buf->buf == NULL) return -1; 2113 return 0;
2223 return 0;
2224} 2114}
2225 2115
2226size_t curlhelp_buffer_write_callback (void *buffer, size_t size, size_t nmemb, void *stream) 2116size_t curlhelp_buffer_write_callback(void *buffer, size_t size, size_t nmemb, void *stream) {
2227{ 2117 curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream;
2228 curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream;
2229 2118
2230 while (buf->bufsize < buf->buflen + size * nmemb + 1) { 2119 while (buf->bufsize < buf->buflen + size * nmemb + 1) {
2231 buf->bufsize = buf->bufsize * 2; 2120 buf->bufsize = buf->bufsize * 2;
2232 buf->buf = (char *)realloc (buf->buf, buf->bufsize); 2121 buf->buf = (char *)realloc(buf->buf, buf->bufsize);
2233 if (buf->buf == NULL) { 2122 if (buf->buf == NULL) {
2234 fprintf(stderr, "malloc failed (%d) %s\n", errno, strerror(errno)); 2123 fprintf(stderr, "malloc failed (%d) %s\n", errno, strerror(errno));
2235 return -1; 2124 return -1;
2236 } 2125 }
2237 } 2126 }
2238 2127
2239 memcpy (buf->buf + buf->buflen, buffer, size * nmemb); 2128 memcpy(buf->buf + buf->buflen, buffer, size * nmemb);
2240 buf->buflen += size * nmemb; 2129 buf->buflen += size * nmemb;
2241 buf->buf[buf->buflen] = '\0'; 2130 buf->buf[buf->buflen] = '\0';
2242 2131
2243 return (int)(size * nmemb); 2132 return (int)(size * nmemb);
2244} 2133}
2245 2134
2246size_t curlhelp_buffer_read_callback(void *buffer, size_t size, size_t nmemb, void *stream) 2135size_t curlhelp_buffer_read_callback(void *buffer, size_t size, size_t nmemb, void *stream) {
2247{ 2136 curlhelp_read_curlbuf *buf = (curlhelp_read_curlbuf *)stream;
2248 curlhelp_read_curlbuf *buf = (curlhelp_read_curlbuf *)stream;
2249 2137
2250 size_t n = min (nmemb * size, buf->buflen - buf->pos); 2138 size_t n = min(nmemb * size, buf->buflen - buf->pos);
2251 2139
2252 memcpy (buffer, buf->buf + buf->pos, n); 2140 memcpy(buffer, buf->buf + buf->pos, n);
2253 buf->pos += n; 2141 buf->pos += n;
2254 2142
2255 return (int)n; 2143 return (int)n;
2256} 2144}
2257 2145
2258void 2146void curlhelp_freewritebuffer(curlhelp_write_curlbuf *buf) {
2259curlhelp_freewritebuffer (curlhelp_write_curlbuf *buf) 2147 free(buf->buf);
2260{ 2148 buf->buf = NULL;
2261 free (buf->buf);
2262 buf->buf = NULL;
2263} 2149}
2264 2150
2265int 2151int curlhelp_initreadbuffer(curlhelp_read_curlbuf *buf, const char *data, size_t datalen) {
2266curlhelp_initreadbuffer (curlhelp_read_curlbuf *buf, const char *data, size_t datalen) 2152 buf->buflen = datalen;
2267{ 2153 buf->buf = (char *)malloc((size_t)buf->buflen);
2268 buf->buflen = datalen; 2154 if (buf->buf == NULL)
2269 buf->buf = (char *)malloc ((size_t)buf->buflen); 2155 return -1;
2270 if (buf->buf == NULL) return -1; 2156 memcpy(buf->buf, data, datalen);
2271 memcpy (buf->buf, data, datalen); 2157 buf->pos = 0;
2272 buf->pos = 0; 2158 return 0;
2273 return 0;
2274} 2159}
2275 2160
2276void 2161void curlhelp_freereadbuffer(curlhelp_read_curlbuf *buf) {
2277curlhelp_freereadbuffer (curlhelp_read_curlbuf *buf) 2162 free(buf->buf);
2278{ 2163 buf->buf = NULL;
2279 free (buf->buf);
2280 buf->buf = NULL;
2281} 2164}
2282 2165
2283/* TODO: where to put this, it's actually part of sstrings2 (logically)? 2166/* TODO: where to put this, it's actually part of sstrings2 (logically)?
2284 */ 2167 */
2285const char* 2168const char *strrstr2(const char *haystack, const char *needle) {
2286strrstr2(const char *haystack, const char *needle) 2169 int counter;
2287{ 2170 size_t len;
2288 int counter; 2171 const char *prev_pos;
2289 size_t len; 2172 const char *pos;
2290 const char *prev_pos; 2173
2291 const char *pos; 2174 if (haystack == NULL || needle == NULL)
2292 2175 return NULL;
2293 if (haystack == NULL || needle == NULL) 2176
2294 return NULL; 2177 if (haystack[0] == '\0' || needle[0] == '\0')
2295 2178 return NULL;
2296 if (haystack[0] == '\0' || needle[0] == '\0') 2179
2297 return NULL; 2180 counter = 0;
2298 2181 prev_pos = NULL;
2299 counter = 0; 2182 pos = haystack;
2300 prev_pos = NULL; 2183 len = strlen(needle);
2301 pos = haystack; 2184 for (;;) {
2302 len = strlen (needle); 2185 pos = strstr(pos, needle);
2303 for (;;) { 2186 if (pos == NULL) {
2304 pos = strstr (pos, needle); 2187 if (counter == 0)
2305 if (pos == NULL) { 2188 return NULL;
2306 if (counter == 0) 2189 else
2307 return NULL; 2190 return prev_pos;
2308 else 2191 }
2309 return prev_pos; 2192 counter++;
2310 } 2193 prev_pos = pos;
2311 counter++; 2194 pos += len;
2312 prev_pos = pos; 2195 if (*pos == '\0')
2313 pos += len; 2196 return prev_pos;
2314 if (*pos == '\0') return prev_pos; 2197 }
2315 }
2316} 2198}
2317 2199
2318int 2200int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line) {
2319curlhelp_parse_statusline (const char *buf, curlhelp_statusline *status_line) 2201 char *first_line_end;
2320{ 2202 char *p;
2321 char *first_line_end; 2203 size_t first_line_len;
2322 char *p; 2204 char *pp;
2323 size_t first_line_len; 2205 const char *start;
2324 char *pp; 2206 char *first_line_buf;
2325 const char *start; 2207
2326 char *first_line_buf; 2208 /* find last start of a new header */
2327 2209 start = strrstr2(buf, "\r\nHTTP/");
2328 /* find last start of a new header */ 2210 if (start != NULL) {
2329 start = strrstr2 (buf, "\r\nHTTP/"); 2211 start += 2;
2330 if (start != NULL) { 2212 buf = start;
2331 start += 2; 2213 }
2332 buf = start; 2214
2333 } 2215 first_line_end = strstr(buf, "\r\n");
2334 2216 if (first_line_end == NULL)
2335 first_line_end = strstr(buf, "\r\n"); 2217 return -1;
2336 if (first_line_end == NULL) return -1; 2218
2337 2219 first_line_len = (size_t)(first_line_end - buf);
2338 first_line_len = (size_t)(first_line_end - buf); 2220 status_line->first_line = (char *)malloc(first_line_len + 1);
2339 status_line->first_line = (char *)malloc (first_line_len + 1); 2221 if (status_line->first_line == NULL)
2340 if (status_line->first_line == NULL) return -1; 2222 return -1;
2341 memcpy (status_line->first_line, buf, first_line_len); 2223 memcpy(status_line->first_line, buf, first_line_len);
2342 status_line->first_line[first_line_len] = '\0'; 2224 status_line->first_line[first_line_len] = '\0';
2343 first_line_buf = strdup( status_line->first_line ); 2225 first_line_buf = strdup(status_line->first_line);
2344 2226
2345 /* protocol and version: "HTTP/x.x" SP or "HTTP/2" SP */ 2227 /* protocol and version: "HTTP/x.x" SP or "HTTP/2" SP */
2346 2228
2347 p = strtok(first_line_buf, "/"); 2229 p = strtok(first_line_buf, "/");
2348 if( p == NULL ) { free( first_line_buf ); return -1; } 2230 if (p == NULL) {
2349 if( strcmp( p, "HTTP" ) != 0 ) { free( first_line_buf ); return -1; } 2231 free(first_line_buf);
2350 2232 return -1;
2351 p = strtok( NULL, " " ); 2233 }
2352 if( p == NULL ) { free( first_line_buf ); return -1; } 2234 if (strcmp(p, "HTTP") != 0) {
2353 if( strchr( p, '.' ) != NULL ) { 2235 free(first_line_buf);
2354 2236 return -1;
2355 /* HTTP 1.x case */ 2237 }
2356 strtok( p, "." ); 2238
2357 status_line->http_major = (int)strtol( p, &pp, 10 ); 2239 p = strtok(NULL, " ");
2358 if( *pp != '\0' ) { free( first_line_buf ); return -1; } 2240 if (p == NULL) {
2359 strtok( NULL, " " ); 2241 free(first_line_buf);
2360 status_line->http_minor = (int)strtol( p, &pp, 10 ); 2242 return -1;
2361 if( *pp != '\0' ) { free( first_line_buf ); return -1; } 2243 }
2362 p += 4; /* 1.x SP */ 2244 if (strchr(p, '.') != NULL) {
2363 } else { 2245
2364 /* HTTP 2 case */ 2246 /* HTTP 1.x case */
2365 status_line->http_major = (int)strtol( p, &pp, 10 ); 2247 strtok(p, ".");
2366 status_line->http_minor = 0; 2248 status_line->http_major = (int)strtol(p, &pp, 10);
2367 p += 2; /* 2 SP */ 2249 if (*pp != '\0') {
2368 } 2250 free(first_line_buf);
2369 2251 return -1;
2370 /* status code: "404" or "404.1", then SP */ 2252 }
2371 2253 strtok(NULL, " ");
2372 p = strtok( p, " " ); 2254 status_line->http_minor = (int)strtol(p, &pp, 10);
2373 if( p == NULL ) { free( first_line_buf ); return -1; } 2255 if (*pp != '\0') {
2374 if( strchr( p, '.' ) != NULL ) { 2256 free(first_line_buf);
2375 char *ppp; 2257 return -1;
2376 ppp = strtok( p, "." ); 2258 }
2377 status_line->http_code = (int)strtol( ppp, &pp, 10 ); 2259 p += 4; /* 1.x SP */
2378 if( *pp != '\0' ) { free( first_line_buf ); return -1; } 2260 } else {
2379 ppp = strtok( NULL, "" ); 2261 /* HTTP 2 case */
2380 status_line->http_subcode = (int)strtol( ppp, &pp, 10 ); 2262 status_line->http_major = (int)strtol(p, &pp, 10);
2381 if( *pp != '\0' ) { free( first_line_buf ); return -1; } 2263 status_line->http_minor = 0;
2382 p += 6; /* 400.1 SP */ 2264 p += 2; /* 2 SP */
2383 } else { 2265 }
2384 status_line->http_code = (int)strtol( p, &pp, 10 );
2385 status_line->http_subcode = -1;
2386 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2387 p += 4; /* 400 SP */
2388 }
2389
2390 /* Human readable message: "Not Found" CRLF */
2391
2392 p = strtok( p, "" );
2393 if( p == NULL ) { status_line->msg = ""; return 0; }
2394 status_line->msg = status_line->first_line + ( p - first_line_buf );
2395 free( first_line_buf );
2396
2397 return 0;
2398}
2399 2266
2400void 2267 /* status code: "404" or "404.1", then SP */
2401curlhelp_free_statusline (curlhelp_statusline *status_line) 2268
2402{ 2269 p = strtok(p, " ");
2403 free (status_line->first_line); 2270 if (p == NULL) {
2271 free(first_line_buf);
2272 return -1;
2273 }
2274 if (strchr(p, '.') != NULL) {
2275 char *ppp;
2276 ppp = strtok(p, ".");
2277 status_line->http_code = (int)strtol(ppp, &pp, 10);
2278 if (*pp != '\0') {
2279 free(first_line_buf);
2280 return -1;
2281 }
2282 ppp = strtok(NULL, "");
2283 status_line->http_subcode = (int)strtol(ppp, &pp, 10);
2284 if (*pp != '\0') {
2285 free(first_line_buf);
2286 return -1;
2287 }
2288 p += 6; /* 400.1 SP */
2289 } else {
2290 status_line->http_code = (int)strtol(p, &pp, 10);
2291 status_line->http_subcode = -1;
2292 if (*pp != '\0') {
2293 free(first_line_buf);
2294 return -1;
2295 }
2296 p += 4; /* 400 SP */
2297 }
2298
2299 /* Human readable message: "Not Found" CRLF */
2300
2301 p = strtok(p, "");
2302 if (p == NULL) {
2303 status_line->msg = "";
2304 return 0;
2305 }
2306 status_line->msg = status_line->first_line + (p - first_line_buf);
2307 free(first_line_buf);
2308
2309 return 0;
2404} 2310}
2405 2311
2406void 2312void curlhelp_free_statusline(curlhelp_statusline *status_line) { free(status_line->first_line); }
2407remove_newlines (char *s)
2408{
2409 char *p;
2410 2313
2411 for (p = s; *p != '\0'; p++) 2314void remove_newlines(char *s) {
2412 if (*p == '\r' || *p == '\n') 2315 char *p;
2413 *p = ' '; 2316
2317 for (p = s; *p != '\0'; p++)
2318 if (*p == '\r' || *p == '\n')
2319 *p = ' ';
2414} 2320}
2415 2321
2416char * 2322char *get_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) 2323 for (size_t i = 0; i < nof_headers; i++) {
2418{ 2324 if (headers[i].name != NULL && strncasecmp(header, headers[i].name, max(headers[i].name_len, 4)) == 0) {
2419 for(size_t i = 0; i < nof_headers; i++ ) { 2325 return strndup(headers[i].value, headers[i].value_len);
2420 if(headers[i].name != NULL && strncasecmp( header, headers[i].name, max( headers[i].name_len, 4 ) ) == 0 ) { 2326 }
2421 return strndup( headers[i].value, headers[i].value_len ); 2327 }
2422 } 2328 return NULL;
2423 }
2424 return NULL;
2425} 2329}
2426 2330
2427int 2331int check_document_dates(const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFAULT_BUFFER_SIZE]) {
2428check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFAULT_BUFFER_SIZE]) 2332 char *server_date = NULL;
2429{ 2333 char *document_date = NULL;
2430 char *server_date = NULL; 2334 int date_result = STATE_OK;
2431 char *document_date = NULL; 2335 curlhelp_statusline status_line;
2432 int date_result = STATE_OK; 2336 struct phr_header headers[255];
2433 curlhelp_statusline status_line; 2337 size_t nof_headers = 255;
2434 struct phr_header headers[255]; 2338 size_t msglen;
2435 size_t nof_headers = 255; 2339
2436 size_t msglen; 2340 int res = phr_parse_response(header_buf->buf, header_buf->buflen, &status_line.http_major, &status_line.http_minor,
2437 2341 &status_line.http_code, &status_line.msg, &msglen, headers, &nof_headers, 0);
2438 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
2439 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
2440 headers, &nof_headers, 0);
2441 2342
2442 if (res == -1) { 2343 if (res == -1) {
2443 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n")); 2344 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
2444 } 2345 }
2445 2346
2446 server_date = get_header_value (headers, nof_headers, "date"); 2347 server_date = get_header_value(headers, nof_headers, "date");
2447 document_date = get_header_value (headers, nof_headers, "last-modified"); 2348 document_date = get_header_value(headers, nof_headers, "last-modified");
2448 2349
2449 if (!server_date || !*server_date) { 2350 if (!server_date || !*server_date) {
2450 char tmp[DEFAULT_BUFFER_SIZE]; 2351 char tmp[DEFAULT_BUFFER_SIZE];
2451 2352
2452 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sServer date unknown, "), *msg); 2353 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sServer date unknown, "), *msg);
2453 strcpy(*msg, tmp); 2354 strcpy(*msg, tmp);
2454 2355
2455 date_result = max_state_alt(STATE_UNKNOWN, date_result); 2356 date_result = max_state_alt(STATE_UNKNOWN, date_result);
@@ -2457,34 +2358,34 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2457 } else if (!document_date || !*document_date) { 2358 } else if (!document_date || !*document_date) {
2458 char tmp[DEFAULT_BUFFER_SIZE]; 2359 char tmp[DEFAULT_BUFFER_SIZE];
2459 2360
2460 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sDocument modification date unknown, "), *msg); 2361 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sDocument modification date unknown, "), *msg);
2461 strcpy(*msg, tmp); 2362 strcpy(*msg, tmp);
2462 2363
2463 date_result = max_state_alt(STATE_CRITICAL, date_result); 2364 date_result = max_state_alt(STATE_CRITICAL, date_result);
2464 2365
2465 } else { 2366 } else {
2466 time_t srv_data = curl_getdate (server_date, NULL); 2367 time_t srv_data = curl_getdate(server_date, NULL);
2467 time_t doc_data = curl_getdate (document_date, NULL); 2368 time_t doc_data = curl_getdate(document_date, NULL);
2468 if (verbose >= 2) 2369 if (verbose >= 2)
2469 printf ("* server date: '%s' (%d), doc_date: '%s' (%d)\n", server_date, (int)srv_data, document_date, (int)doc_data); 2370 printf("* server date: '%s' (%d), doc_date: '%s' (%d)\n", server_date, (int)srv_data, document_date, (int)doc_data);
2470 if (srv_data <= 0) { 2371 if (srv_data <= 0) {
2471 char tmp[DEFAULT_BUFFER_SIZE]; 2372 char tmp[DEFAULT_BUFFER_SIZE];
2472 2373
2473 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sServer date \"%100s\" unparsable, "), *msg, server_date); 2374 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sServer date \"%100s\" unparsable, "), *msg, server_date);
2474 strcpy(*msg, tmp); 2375 strcpy(*msg, tmp);
2475 2376
2476 date_result = max_state_alt(STATE_CRITICAL, date_result); 2377 date_result = max_state_alt(STATE_CRITICAL, date_result);
2477 } else if (doc_data <= 0) { 2378 } else if (doc_data <= 0) {
2478 char tmp[DEFAULT_BUFFER_SIZE]; 2379 char tmp[DEFAULT_BUFFER_SIZE];
2479 2380
2480 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sDocument date \"%100s\" unparsable, "), *msg, document_date); 2381 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sDocument date \"%100s\" unparsable, "), *msg, document_date);
2481 strcpy(*msg, tmp); 2382 strcpy(*msg, tmp);
2482 2383
2483 date_result = max_state_alt(STATE_CRITICAL, date_result); 2384 date_result = max_state_alt(STATE_CRITICAL, date_result);
2484 } else if (doc_data > srv_data + 30) { 2385 } else if (doc_data > srv_data + 30) {
2485 char tmp[DEFAULT_BUFFER_SIZE]; 2386 char tmp[DEFAULT_BUFFER_SIZE];
2486 2387
2487 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sDocument is %d seconds in the future, "), *msg, (int)doc_data - (int)srv_data); 2388 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sDocument is %d seconds in the future, "), *msg, (int)doc_data - (int)srv_data);
2488 strcpy(*msg, tmp); 2389 strcpy(*msg, tmp);
2489 2390
2490 date_result = max_state_alt(STATE_CRITICAL, date_result); 2391 date_result = max_state_alt(STATE_CRITICAL, date_result);
@@ -2493,14 +2394,14 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2493 if (n > (60 * 60 * 24 * 2)) { 2394 if (n > (60 * 60 * 24 * 2)) {
2494 char tmp[DEFAULT_BUFFER_SIZE]; 2395 char tmp[DEFAULT_BUFFER_SIZE];
2495 2396
2496 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sLast modified %.1f days ago, "), *msg, ((float) n) / (60 * 60 * 24)); 2397 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sLast modified %.1f days ago, "), *msg, ((float)n) / (60 * 60 * 24));
2497 strcpy(*msg, tmp); 2398 strcpy(*msg, tmp);
2498 2399
2499 date_result = max_state_alt(STATE_CRITICAL, date_result); 2400 date_result = max_state_alt(STATE_CRITICAL, date_result);
2500 } else { 2401 } else {
2501 char tmp[DEFAULT_BUFFER_SIZE]; 2402 char tmp[DEFAULT_BUFFER_SIZE];
2502 2403
2503 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sLast modified %d:%02d:%02d ago, "), *msg, n / (60 * 60), (n / 60) % 60, n % 60); 2404 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sLast modified %d:%02d:%02d ago, "), *msg, n / (60 * 60), (n / 60) % 60, n % 60);
2504 strcpy(*msg, tmp); 2405 strcpy(*msg, tmp);
2505 2406
2506 date_result = max_state_alt(STATE_CRITICAL, date_result); 2407 date_result = max_state_alt(STATE_CRITICAL, date_result);
@@ -2508,132 +2409,128 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2508 } 2409 }
2509 } 2410 }
2510 2411
2511 if (server_date) free (server_date); 2412 if (server_date)
2512 if (document_date) free (document_date); 2413 free(server_date);
2414 if (document_date)
2415 free(document_date);
2513 2416
2514 return date_result; 2417 return date_result;
2515} 2418}
2516 2419
2420int get_content_length(const curlhelp_write_curlbuf *header_buf, const curlhelp_write_curlbuf *body_buf) {
2421 size_t content_length = 0;
2422 struct phr_header headers[255];
2423 size_t nof_headers = 255;
2424 size_t msglen;
2425 char *content_length_s = NULL;
2426 curlhelp_statusline status_line;
2517 2427
2518int 2428 int res = phr_parse_response(header_buf->buf, header_buf->buflen, &status_line.http_major, &status_line.http_minor,
2519get_content_length (const curlhelp_write_curlbuf* header_buf, const curlhelp_write_curlbuf* body_buf) 2429 &status_line.http_code, &status_line.msg, &msglen, headers, &nof_headers, 0);
2520{
2521 size_t content_length = 0;
2522 struct phr_header headers[255];
2523 size_t nof_headers = 255;
2524 size_t msglen;
2525 char *content_length_s = NULL;
2526 curlhelp_statusline status_line;
2527
2528 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
2529 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
2530 headers, &nof_headers, 0);
2531 2430
2532 if (res == -1) { 2431 if (res == -1) {
2533 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n")); 2432 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
2534 } 2433 }
2535 2434
2536 content_length_s = get_header_value (headers, nof_headers, "content-length"); 2435 content_length_s = get_header_value(headers, nof_headers, "content-length");
2537 if (!content_length_s) { 2436 if (!content_length_s) {
2538 return header_buf->buflen + body_buf->buflen; 2437 return header_buf->buflen + body_buf->buflen;
2539 } 2438 }
2540 content_length_s += strspn (content_length_s, " \t"); 2439 content_length_s += strspn(content_length_s, " \t");
2541 content_length = atoi (content_length_s); 2440 content_length = atoi(content_length_s);
2542 if (content_length != body_buf->buflen) { 2441 if (content_length != body_buf->buflen) {
2543 /* TODO: should we warn if the actual and the reported body length don't match? */ 2442 /* TODO: should we warn if the actual and the reported body length don't match? */
2544 } 2443 }
2545 2444
2546 if (content_length_s) free (content_length_s); 2445 if (content_length_s)
2446 free(content_length_s);
2547 2447
2548 return header_buf->buflen + body_buf->buflen; 2448 return header_buf->buflen + body_buf->buflen;
2549} 2449}
2550 2450
2551/* TODO: is there a better way in libcurl to check for the SSL library? */ 2451/* TODO: is there a better way in libcurl to check for the SSL library? */
2552curlhelp_ssl_library 2452curlhelp_ssl_library curlhelp_get_ssl_library() {
2553curlhelp_get_ssl_library () 2453 curl_version_info_data *version_data;
2554{ 2454 char *ssl_version;
2555 curl_version_info_data* version_data; 2455 char *library;
2556 char *ssl_version; 2456 curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN;
2557 char *library; 2457
2558 curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN; 2458 version_data = curl_version_info(CURLVERSION_NOW);
2559 2459 if (version_data == NULL)
2560 version_data = curl_version_info (CURLVERSION_NOW); 2460 return CURLHELP_SSL_LIBRARY_UNKNOWN;
2561 if (version_data == NULL) return CURLHELP_SSL_LIBRARY_UNKNOWN; 2461
2562 2462 ssl_version = strdup(version_data->ssl_version);
2563 ssl_version = strdup (version_data->ssl_version); 2463 if (ssl_version == NULL)
2564 if (ssl_version == NULL ) return CURLHELP_SSL_LIBRARY_UNKNOWN; 2464 return CURLHELP_SSL_LIBRARY_UNKNOWN;
2565 2465
2566 library = strtok (ssl_version, "/"); 2466 library = strtok(ssl_version, "/");
2567 if (library == NULL) return CURLHELP_SSL_LIBRARY_UNKNOWN; 2467 if (library == NULL)
2568 2468 return CURLHELP_SSL_LIBRARY_UNKNOWN;
2569 if (strcmp (library, "OpenSSL") == 0) 2469
2570 ssl_library = CURLHELP_SSL_LIBRARY_OPENSSL; 2470 if (strcmp(library, "OpenSSL") == 0)
2571 else if (strcmp (library, "LibreSSL") == 0) 2471 ssl_library = CURLHELP_SSL_LIBRARY_OPENSSL;
2572 ssl_library = CURLHELP_SSL_LIBRARY_LIBRESSL; 2472 else if (strcmp(library, "LibreSSL") == 0)
2573 else if (strcmp (library, "GnuTLS") == 0) 2473 ssl_library = CURLHELP_SSL_LIBRARY_LIBRESSL;
2574 ssl_library = CURLHELP_SSL_LIBRARY_GNUTLS; 2474 else if (strcmp(library, "GnuTLS") == 0)
2575 else if (strcmp (library, "NSS") == 0) 2475 ssl_library = CURLHELP_SSL_LIBRARY_GNUTLS;
2576 ssl_library = CURLHELP_SSL_LIBRARY_NSS; 2476 else if (strcmp(library, "NSS") == 0)
2577 2477 ssl_library = CURLHELP_SSL_LIBRARY_NSS;
2578 if (verbose >= 2) 2478
2579 printf ("* SSL library string is : %s %s (%d)\n", version_data->ssl_version, library, ssl_library); 2479 if (verbose >= 2)
2580 2480 printf("* SSL library string is : %s %s (%d)\n", version_data->ssl_version, library, ssl_library);
2581 free (ssl_version); 2481
2582 2482 free(ssl_version);
2583 return ssl_library; 2483
2484 return ssl_library;
2584} 2485}
2585 2486
2586const char* 2487const char *curlhelp_get_ssl_library_string(curlhelp_ssl_library ssl_library) {
2587curlhelp_get_ssl_library_string (curlhelp_ssl_library ssl_library) 2488 switch (ssl_library) {
2588{ 2489 case CURLHELP_SSL_LIBRARY_OPENSSL:
2589 switch (ssl_library) { 2490 return "OpenSSL";
2590 case CURLHELP_SSL_LIBRARY_OPENSSL: 2491 case CURLHELP_SSL_LIBRARY_LIBRESSL:
2591 return "OpenSSL"; 2492 return "LibreSSL";
2592 case CURLHELP_SSL_LIBRARY_LIBRESSL: 2493 case CURLHELP_SSL_LIBRARY_GNUTLS:
2593 return "LibreSSL"; 2494 return "GnuTLS";
2594 case CURLHELP_SSL_LIBRARY_GNUTLS: 2495 case CURLHELP_SSL_LIBRARY_NSS:
2595 return "GnuTLS"; 2496 return "NSS";
2596 case CURLHELP_SSL_LIBRARY_NSS: 2497 case CURLHELP_SSL_LIBRARY_UNKNOWN:
2597 return "NSS"; 2498 default:
2598 case CURLHELP_SSL_LIBRARY_UNKNOWN: 2499 return "unknown";
2599 default: 2500 }
2600 return "unknown";
2601 }
2602} 2501}
2603 2502
2604#ifdef LIBCURL_FEATURE_SSL 2503#ifdef LIBCURL_FEATURE_SSL
2605#ifndef USE_OPENSSL 2504# ifndef USE_OPENSSL
2606time_t 2505time_t parse_cert_date(const char *s) {
2607parse_cert_date (const char *s) 2506 struct tm tm;
2608{ 2507 time_t date;
2609 struct tm tm; 2508 char *res;
2610 time_t date; 2509
2611 char *res; 2510 if (!s)
2612 2511 return -1;
2613 if (!s) return -1; 2512
2614 2513 /* Jan 17 14:25:12 2020 GMT */
2615 /* Jan 17 14:25:12 2020 GMT */ 2514 res = strptime(s, "%Y-%m-%d %H:%M:%S GMT", &tm);
2616 res = strptime (s, "%Y-%m-%d %H:%M:%S GMT", &tm); 2515 /* Sep 11 12:00:00 2020 GMT */
2617 /* Sep 11 12:00:00 2020 GMT */ 2516 if (res == NULL)
2618 if (res == NULL) strptime (s, "%Y %m %d %H:%M:%S GMT", &tm); 2517 strptime(s, "%Y %m %d %H:%M:%S GMT", &tm);
2619 date = mktime (&tm); 2518 date = mktime(&tm);
2620 2519
2621 return date; 2520 return date;
2622} 2521}
2623 2522
2624/* TODO: this needs cleanup in the sslutils.c, maybe we the #else case to 2523/* TODO: this needs cleanup in the sslutils.c, maybe we the #else case to
2625 * OpenSSL could be this function 2524 * OpenSSL could be this function
2626 */ 2525 */
2627int 2526int net_noopenssl_check_certificate(cert_ptr_union *cert_ptr, int days_till_exp_warn, int days_till_exp_crit) {
2628net_noopenssl_check_certificate (cert_ptr_union* cert_ptr, int days_till_exp_warn, int days_till_exp_crit) 2527 int i;
2629{ 2528 struct curl_slist *slist;
2630 int i; 2529 int cname_found = 0;
2631 struct curl_slist* slist; 2530 char *start_date_str = NULL;
2632 int cname_found = 0; 2531 char *end_date_str = NULL;
2633 char* start_date_str = NULL; 2532 time_t start_date;
2634 char* end_date_str = NULL; 2533 time_t end_date;
2635 time_t start_date;
2636 time_t end_date;
2637 char *tz; 2534 char *tz;
2638 float time_left; 2535 float time_left;
2639 int days_left; 2536 int days_left;
@@ -2641,66 +2538,64 @@ net_noopenssl_check_certificate (cert_ptr_union* cert_ptr, int days_till_exp_war
2641 char timestamp[50] = ""; 2538 char timestamp[50] = "";
2642 int status = STATE_UNKNOWN; 2539 int status = STATE_UNKNOWN;
2643 2540
2644 if (verbose >= 2) 2541 if (verbose >= 2)
2645 printf ("**** REQUEST CERTIFICATES ****\n"); 2542 printf("**** REQUEST CERTIFICATES ****\n");
2646 2543
2647 for (i = 0; i < cert_ptr->to_certinfo->num_of_certs; i++) { 2544 for (i = 0; i < cert_ptr->to_certinfo->num_of_certs; i++) {
2648 for (slist = cert_ptr->to_certinfo->certinfo[i]; slist; slist = slist->next) { 2545 for (slist = cert_ptr->to_certinfo->certinfo[i]; slist; slist = slist->next) {
2649 /* find first common name in subject, 2546 /* find first common name in subject,
2650 * TODO: check alternative subjects for 2547 * TODO: check alternative subjects for
2651 * TODO: have a decent parser here and not a hack 2548 * TODO: have a decent parser here and not a hack
2652 * multi-host certificate, check wildcards 2549 * multi-host certificate, check wildcards
2653 */ 2550 */
2654 if (strncasecmp (slist->data, "Subject:", 8) == 0) { 2551 if (strncasecmp(slist->data, "Subject:", 8) == 0) {
2655 int d = 3; 2552 int d = 3;
2656 char* p = strstr (slist->data, "CN="); 2553 char *p = strstr(slist->data, "CN=");
2657 if (p == NULL) { 2554 if (p == NULL) {
2658 d = 5; 2555 d = 5;
2659 p = strstr (slist->data, "CN = "); 2556 p = strstr(slist->data, "CN = ");
2660 } 2557 }
2661 if (p != NULL) { 2558 if (p != NULL) {
2662 if (strncmp (host_name, p+d, strlen (host_name)) == 0) { 2559 if (strncmp(host_name, p + d, strlen(host_name)) == 0) {
2663 cname_found = 1; 2560 cname_found = 1;
2664 } 2561 }
2665 } 2562 }
2666 } else if (strncasecmp (slist->data, "Start Date:", 11) == 0) { 2563 } else if (strncasecmp(slist->data, "Start Date:", 11) == 0) {
2667 start_date_str = &slist->data[11]; 2564 start_date_str = &slist->data[11];
2668 } else if (strncasecmp (slist->data, "Expire Date:", 12) == 0) { 2565 } else if (strncasecmp(slist->data, "Expire Date:", 12) == 0) {
2669 end_date_str = &slist->data[12]; 2566 end_date_str = &slist->data[12];
2670 } else if (strncasecmp (slist->data, "Cert:", 5) == 0) { 2567 } else if (strncasecmp(slist->data, "Cert:", 5) == 0) {
2671 goto HAVE_FIRST_CERT; 2568 goto HAVE_FIRST_CERT;
2672 } 2569 }
2673 if (verbose >= 2) 2570 if (verbose >= 2)
2674 printf ("%d ** %s\n", i, slist->data); 2571 printf("%d ** %s\n", i, slist->data);
2675 } 2572 }
2676 } 2573 }
2677HAVE_FIRST_CERT: 2574HAVE_FIRST_CERT:
2678 2575
2679 if (verbose >= 2) 2576 if (verbose >= 2)
2680 printf ("**** REQUEST CERTIFICATES ****\n"); 2577 printf("**** REQUEST CERTIFICATES ****\n");
2681 2578
2682 if (!cname_found) { 2579 if (!cname_found) {
2683 printf("%s\n",_("CRITICAL - Cannot retrieve certificate subject.")); 2580 printf("%s\n", _("CRITICAL - Cannot retrieve certificate subject."));
2684 return STATE_CRITICAL; 2581 return STATE_CRITICAL;
2685 } 2582 }
2686 2583
2687 start_date = parse_cert_date (start_date_str); 2584 start_date = parse_cert_date(start_date_str);
2688 if (start_date <= 0) { 2585 if (start_date <= 0) {
2689 snprintf (msg, DEFAULT_BUFFER_SIZE, _("WARNING - Unparsable 'Start Date' in certificate: '%s'"), 2586 snprintf(msg, DEFAULT_BUFFER_SIZE, _("WARNING - Unparsable 'Start Date' in certificate: '%s'"), start_date_str);
2690 start_date_str); 2587 puts(msg);
2691 puts (msg); 2588 return STATE_WARNING;
2692 return STATE_WARNING; 2589 }
2693 } 2590
2694 2591 end_date = parse_cert_date(end_date_str);
2695 end_date = parse_cert_date (end_date_str); 2592 if (end_date <= 0) {
2696 if (end_date <= 0) { 2593 snprintf(msg, DEFAULT_BUFFER_SIZE, _("WARNING - Unparsable 'Expire Date' in certificate: '%s'"), start_date_str);
2697 snprintf (msg, DEFAULT_BUFFER_SIZE, _("WARNING - Unparsable 'Expire Date' in certificate: '%s'"), 2594 puts(msg);
2698 start_date_str); 2595 return STATE_WARNING;
2699 puts (msg); 2596 }
2700 return STATE_WARNING; 2597
2701 } 2598 time_left = difftime(end_date, time(NULL));
2702
2703 time_left = difftime (end_date, time(NULL));
2704 days_left = time_left / 86400; 2599 days_left = time_left / 86400;
2705 tz = getenv("TZ"); 2600 tz = getenv("TZ");
2706 setenv("TZ", "GMT", 1); 2601 setenv("TZ", "GMT", 1);
@@ -2713,30 +2608,31 @@ HAVE_FIRST_CERT:
2713 tzset(); 2608 tzset();
2714 2609
2715 if (days_left > 0 && days_left <= days_till_exp_warn) { 2610 if (days_left > 0 && days_left <= days_till_exp_warn) {
2716 printf (_("%s - Certificate '%s' expires in %d day(s) (%s).\n"), (days_left>days_till_exp_crit)?"WARNING":"CRITICAL", host_name, days_left, timestamp); 2611 printf(_("%s - Certificate '%s' expires in %d day(s) (%s).\n"), (days_left > days_till_exp_crit) ? "WARNING" : "CRITICAL",
2612 host_name, days_left, timestamp);
2717 if (days_left > days_till_exp_crit) 2613 if (days_left > days_till_exp_crit)
2718 status = STATE_WARNING; 2614 status = STATE_WARNING;
2719 else 2615 else
2720 status = STATE_CRITICAL; 2616 status = STATE_CRITICAL;
2721 } else if (days_left == 0 && time_left > 0) { 2617 } else if (days_left == 0 && time_left > 0) {
2722 if (time_left >= 3600) 2618 if (time_left >= 3600)
2723 time_remaining = (int) time_left / 3600; 2619 time_remaining = (int)time_left / 3600;
2724 else 2620 else
2725 time_remaining = (int) time_left / 60; 2621 time_remaining = (int)time_left / 60;
2726 2622
2727 printf (_("%s - Certificate '%s' expires in %u %s (%s)\n"), 2623 printf(_("%s - Certificate '%s' expires in %u %s (%s)\n"), (days_left > days_till_exp_crit) ? "WARNING" : "CRITICAL", host_name,
2728 (days_left>days_till_exp_crit) ? "WARNING" : "CRITICAL", host_name, time_remaining, 2624 time_remaining, time_left >= 3600 ? "hours" : "minutes", timestamp);
2729 time_left >= 3600 ? "hours" : "minutes", timestamp);
2730 2625
2731 if ( days_left > days_till_exp_crit) 2626 if (days_left > days_till_exp_crit)
2732 status = STATE_WARNING; 2627 status = STATE_WARNING;
2733 else 2628 else
2734 status = STATE_CRITICAL; 2629 status = STATE_CRITICAL;
2735 } else if (time_left < 0) { 2630 } else if (time_left < 0) {
2736 printf(_("CRITICAL - Certificate '%s' expired on %s.\n"), host_name, timestamp); 2631 printf(_("CRITICAL - Certificate '%s' expired on %s.\n"), host_name, timestamp);
2737 status=STATE_CRITICAL; 2632 status = STATE_CRITICAL;
2738 } else if (days_left == 0) { 2633 } else if (days_left == 0) {
2739 printf (_("%s - Certificate '%s' just expired (%s).\n"), (days_left>days_till_exp_crit)?"WARNING":"CRITICAL", host_name, timestamp); 2634 printf(_("%s - Certificate '%s' just expired (%s).\n"), (days_left > days_till_exp_crit) ? "WARNING" : "CRITICAL", host_name,
2635 timestamp);
2740 if (days_left > days_till_exp_crit) 2636 if (days_left > days_till_exp_crit)
2741 status = STATE_WARNING; 2637 status = STATE_WARNING;
2742 else 2638 else
@@ -2747,5 +2643,5 @@ HAVE_FIRST_CERT:
2747 } 2643 }
2748 return status; 2644 return status;
2749} 2645}
2750#endif /* USE_OPENSSL */ 2646# endif /* USE_OPENSSL */
2751#endif /* LIBCURL_FEATURE_SSL */ 2647#endif /* LIBCURL_FEATURE_SSL */