0275402110a536925801eae69eb957796c8e4eeb
1 /*****************************************************************************
2 *
3 * Nagios check_http plugin
4 *
5 * License: GPL
6 * Copyright (c) 1999-2008 Nagios Plugins Development Team
7 *
8 * Last Modified: $Date$
9 *
10 * Description:
11 *
12 * This file contains the check_http plugin
13 *
14 * This plugin tests the HTTP service on the specified host. It can test
15 * normal (http) and secure (https) servers, follow redirects, search for
16 * strings and regular expressions, check connection times, and report on
17 * certificate expiration times.
18 *
19 *
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
22 * the Free Software Foundation, either version 3 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
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/>.
32 *
33 * $Id$
34 *
35 *****************************************************************************/
37 /* splint -I. -I../../plugins -I../../lib/ -I/usr/kerberos/include/ ../../plugins/check_http.c */
39 const char *progname = "check_http";
40 const char *revision = "$Revision$";
41 const char *copyright = "1999-2008";
42 const char *email = "nagiosplug-devel@lists.sourceforge.net";
44 #include <ctype.h>
46 #include "common.h"
47 #include "netutils.h"
48 #include "utils.h"
49 #include "base64.h"
51 #define INPUT_DELIMITER ";"
53 #define HTTP_EXPECT "HTTP/1."
54 enum {
55 MAX_IPV4_HOSTLENGTH = 255,
56 HTTP_PORT = 80,
57 HTTPS_PORT = 443,
58 MAX_PORT = 65535
59 };
61 #ifdef HAVE_SSL
62 int check_cert = FALSE;
63 int days_till_exp;
64 char *randbuff;
65 X509 *server_cert;
66 # define my_recv(buf, len) ((use_ssl) ? np_net_ssl_read(buf, len) : read(sd, buf, len))
67 # define my_send(buf, len) ((use_ssl) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0))
68 #else /* ifndef HAVE_SSL */
69 # define my_recv(buf, len) read(sd, buf, len)
70 # define my_send(buf, len) send(sd, buf, len, 0)
71 #endif /* HAVE_SSL */
72 int no_body = FALSE;
73 int maximum_age = -1;
75 enum {
76 REGS = 2,
77 MAX_RE_SIZE = 256
78 };
79 #include "regex.h"
80 regex_t preg;
81 regmatch_t pmatch[REGS];
82 char regexp[MAX_RE_SIZE];
83 char errbuf[MAX_INPUT_BUFFER];
84 int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE;
85 int errcode;
86 int invert_regex = 0;
88 struct timeval tv;
90 #define HTTP_URL "/"
91 #define CRLF "\r\n"
93 int specify_port = FALSE;
94 int server_port = HTTP_PORT;
95 char server_port_text[6] = "";
96 char server_type[6] = "http";
97 char *server_address;
98 char *host_name;
99 char *server_url;
100 char *user_agent;
101 int server_url_length;
102 int server_expect_yn = 0;
103 char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT;
104 char string_expect[MAX_INPUT_BUFFER] = "";
105 double warning_time = 0;
106 int check_warning_time = FALSE;
107 double critical_time = 0;
108 int check_critical_time = FALSE;
109 char user_auth[MAX_INPUT_BUFFER] = "";
110 int display_html = FALSE;
111 char **http_opt_headers;
112 int http_opt_headers_count = 0;
113 int onredirect = STATE_OK;
114 int use_ssl = FALSE;
115 int verbose = FALSE;
116 int sd;
117 int min_page_len = 0;
118 int max_page_len = 0;
119 int redir_depth = 0;
120 int max_depth = 15;
121 char *http_method;
122 char *http_post_data;
123 char *http_content_type;
124 char buffer[MAX_INPUT_BUFFER];
126 int process_arguments (int, char **);
127 int check_http (void);
128 void redir (char *pos, char *status_line);
129 int server_type_check(const char *type);
130 int server_port_check(int ssl_flag);
131 char *perfd_time (double microsec);
132 char *perfd_size (int page_len);
133 void print_help (void);
134 void print_usage (void);
136 int
137 main (int argc, char **argv)
138 {
139 int result = STATE_UNKNOWN;
141 setlocale (LC_ALL, "");
142 bindtextdomain (PACKAGE, LOCALEDIR);
143 textdomain (PACKAGE);
145 /* Set default URL. Must be malloced for subsequent realloc if --onredirect=follow */
146 server_url = strdup(HTTP_URL);
147 server_url_length = strlen(server_url);
148 asprintf (&user_agent, "User-Agent: check_http/%s (nagios-plugins %s)",
149 clean_revstring (revision), VERSION);
151 if (process_arguments (argc, argv) == ERROR)
152 usage4 (_("Could not parse arguments"));
154 if (display_html == TRUE)
155 printf ("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">",
156 use_ssl ? "https" : "http", host_name ? host_name : server_address,
157 server_port, server_url);
159 /* initialize alarm signal handling, set socket timeout, start timer */
160 (void) signal (SIGALRM, socket_timeout_alarm_handler);
161 (void) alarm (socket_timeout);
162 gettimeofday (&tv, NULL);
164 result = check_http ();
165 return result;
166 }
170 /* process command-line arguments */
171 int
172 process_arguments (int argc, char **argv)
173 {
174 int c = 1;
175 char *p;
177 enum {
178 INVERT_REGEX = CHAR_MAX + 1
179 };
181 int option = 0;
182 static struct option longopts[] = {
183 STD_LONG_OPTS,
184 {"link", no_argument, 0, 'L'},
185 {"nohtml", no_argument, 0, 'n'},
186 {"ssl", no_argument, 0, 'S'},
187 {"post", required_argument, 0, 'P'},
188 {"IP-address", required_argument, 0, 'I'},
189 {"url", required_argument, 0, 'u'},
190 {"port", required_argument, 0, 'p'},
191 {"authorization", required_argument, 0, 'a'},
192 {"string", required_argument, 0, 's'},
193 {"expect", required_argument, 0, 'e'},
194 {"regex", required_argument, 0, 'r'},
195 {"ereg", required_argument, 0, 'r'},
196 {"eregi", required_argument, 0, 'R'},
197 {"linespan", no_argument, 0, 'l'},
198 {"onredirect", required_argument, 0, 'f'},
199 {"certificate", required_argument, 0, 'C'},
200 {"useragent", required_argument, 0, 'A'},
201 {"header", required_argument, 0, 'k'},
202 {"no-body", no_argument, 0, 'N'},
203 {"max-age", required_argument, 0, 'M'},
204 {"content-type", required_argument, 0, 'T'},
205 {"pagesize", required_argument, 0, 'm'},
206 {"invert-regex", no_argument, NULL, INVERT_REGEX},
207 {"use-ipv4", no_argument, 0, '4'},
208 {"use-ipv6", no_argument, 0, '6'},
209 {0, 0, 0, 0}
210 };
212 if (argc < 2)
213 return ERROR;
215 for (c = 1; c < argc; c++) {
216 if (strcmp ("-to", argv[c]) == 0)
217 strcpy (argv[c], "-t");
218 if (strcmp ("-hn", argv[c]) == 0)
219 strcpy (argv[c], "-H");
220 if (strcmp ("-wt", argv[c]) == 0)
221 strcpy (argv[c], "-w");
222 if (strcmp ("-ct", argv[c]) == 0)
223 strcpy (argv[c], "-c");
224 if (strcmp ("-nohtml", argv[c]) == 0)
225 strcpy (argv[c], "-n");
226 }
228 while (1) {
229 c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:T:I:a:e:p:s:R:r:u:f:C:nlLSm:M:N", longopts, &option);
230 if (c == -1 || c == EOF)
231 break;
233 switch (c) {
234 case '?': /* usage */
235 usage5 ();
236 break;
237 case 'h': /* help */
238 print_help ();
239 exit (STATE_OK);
240 break;
241 case 'V': /* version */
242 print_revision (progname, revision);
243 exit (STATE_OK);
244 break;
245 case 't': /* timeout period */
246 if (!is_intnonneg (optarg))
247 usage2 (_("Timeout interval must be a positive integer"), optarg);
248 else
249 socket_timeout = atoi (optarg);
250 break;
251 case 'c': /* critical time threshold */
252 if (!is_nonnegative (optarg))
253 usage2 (_("Critical threshold must be integer"), optarg);
254 else {
255 critical_time = strtod (optarg, NULL);
256 check_critical_time = TRUE;
257 }
258 break;
259 case 'w': /* warning time threshold */
260 if (!is_nonnegative (optarg))
261 usage2 (_("Warning threshold must be integer"), optarg);
262 else {
263 warning_time = strtod (optarg, NULL);
264 check_warning_time = TRUE;
265 }
266 break;
267 case 'A': /* User Agent String */
268 asprintf (&user_agent, "User-Agent: %s", optarg);
269 break;
270 case 'k': /* Additional headers */
271 if (http_opt_headers_count == 0)
272 http_opt_headers = malloc (sizeof (char *) * (++http_opt_headers_count));
273 else
274 http_opt_headers = realloc (http_opt_headers, sizeof (char *) * (++http_opt_headers_count));
275 http_opt_headers[http_opt_headers_count - 1] = optarg;
276 /* asprintf (&http_opt_headers, "%s", optarg); */
277 break;
278 case 'L': /* show html link */
279 display_html = TRUE;
280 break;
281 case 'n': /* do not show html link */
282 display_html = FALSE;
283 break;
284 case 'C': /* Check SSL cert validity */
285 #ifdef HAVE_SSL
286 if (!is_intnonneg (optarg))
287 usage2 (_("Invalid certificate expiration period"), optarg);
288 else {
289 days_till_exp = atoi (optarg);
290 check_cert = TRUE;
291 }
292 /* Fall through to -S option */
293 #endif
294 case 'S': /* use SSL */
295 #ifndef HAVE_SSL
296 usage4 (_("Invalid option - SSL is not available"));
297 #endif
298 use_ssl = TRUE;
299 if (specify_port == FALSE)
300 server_port = HTTPS_PORT;
301 break;
302 case 'f': /* onredirect */
303 if (!strcmp (optarg, "follow"))
304 onredirect = STATE_DEPENDENT;
305 if (!strcmp (optarg, "unknown"))
306 onredirect = STATE_UNKNOWN;
307 if (!strcmp (optarg, "ok"))
308 onredirect = STATE_OK;
309 if (!strcmp (optarg, "warning"))
310 onredirect = STATE_WARNING;
311 if (!strcmp (optarg, "critical"))
312 onredirect = STATE_CRITICAL;
313 if (verbose)
314 printf(_("option f:%d \n"), onredirect);
315 break;
316 /* Note: H, I, and u must be malloc'd or will fail on redirects */
317 case 'H': /* Host Name (virtual host) */
318 host_name = strdup (optarg);
319 if (host_name[0] == '[') {
320 if ((p = strstr (host_name, "]:")) != NULL) /* [IPv6]:port */
321 server_port = atoi (p + 2);
322 } else if ((p = strchr (host_name, ':')) != NULL
323 && strchr (++p, ':') == NULL) /* IPv4:port or host:port */
324 server_port = atoi (p);
325 break;
326 case 'I': /* Server IP-address */
327 server_address = strdup (optarg);
328 break;
329 case 'u': /* URL path */
330 server_url = strdup (optarg);
331 server_url_length = strlen (server_url);
332 break;
333 case 'p': /* Server port */
334 if (!is_intnonneg (optarg))
335 usage2 (_("Invalid port number"), optarg);
336 else {
337 server_port = atoi (optarg);
338 specify_port = TRUE;
339 }
340 break;
341 case 'a': /* authorization info */
342 strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1);
343 user_auth[MAX_INPUT_BUFFER - 1] = 0;
344 break;
345 case 'P': /* HTTP POST data in URL encoded format */
346 if (http_method || http_post_data) break;
347 http_method = strdup("POST");
348 http_post_data = strdup (optarg);
349 break;
350 case 's': /* string or substring */
351 strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1);
352 string_expect[MAX_INPUT_BUFFER - 1] = 0;
353 break;
354 case 'e': /* string or substring */
355 strncpy (server_expect, optarg, MAX_INPUT_BUFFER - 1);
356 server_expect[MAX_INPUT_BUFFER - 1] = 0;
357 server_expect_yn = 1;
358 break;
359 case 'T': /* Content-type */
360 asprintf (&http_content_type, "%s", optarg);
361 break;
362 case 'l': /* linespan */
363 cflags &= ~REG_NEWLINE;
364 break;
365 case 'R': /* regex */
366 cflags |= REG_ICASE;
367 case 'r': /* regex */
368 strncpy (regexp, optarg, MAX_RE_SIZE - 1);
369 regexp[MAX_RE_SIZE - 1] = 0;
370 errcode = regcomp (&preg, regexp, cflags);
371 if (errcode != 0) {
372 (void) regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
373 printf (_("Could Not Compile Regular Expression: %s"), errbuf);
374 return ERROR;
375 }
376 break;
377 case INVERT_REGEX:
378 invert_regex = 1;
379 break;
380 case '4':
381 address_family = AF_INET;
382 break;
383 case '6':
384 #ifdef USE_IPV6
385 address_family = AF_INET6;
386 #else
387 usage4 (_("IPv6 support not available"));
388 #endif
389 break;
390 case 'v': /* verbose */
391 verbose = TRUE;
392 break;
393 case 'm': /* min_page_length */
394 {
395 char *tmp;
396 if (strchr(optarg, ':') != (char *)NULL) {
397 /* range, so get two values, min:max */
398 tmp = strtok(optarg, ":");
399 if (tmp == NULL) {
400 printf("Bad format: try \"-m min:max\"\n");
401 exit (STATE_WARNING);
402 } else
403 min_page_len = atoi(tmp);
405 tmp = strtok(NULL, ":");
406 if (tmp == NULL) {
407 printf("Bad format: try \"-m min:max\"\n");
408 exit (STATE_WARNING);
409 } else
410 max_page_len = atoi(tmp);
411 } else
412 min_page_len = atoi (optarg);
413 break;
414 }
415 case 'N': /* no-body */
416 no_body = TRUE;
417 break;
418 case 'M': /* max-age */
419 {
420 int L = strlen(optarg);
421 if (L && optarg[L-1] == 'm')
422 maximum_age = atoi (optarg) * 60;
423 else if (L && optarg[L-1] == 'h')
424 maximum_age = atoi (optarg) * 60 * 60;
425 else if (L && optarg[L-1] == 'd')
426 maximum_age = atoi (optarg) * 60 * 60 * 24;
427 else if (L && (optarg[L-1] == 's' ||
428 isdigit (optarg[L-1])))
429 maximum_age = atoi (optarg);
430 else {
431 fprintf (stderr, "unparsable max-age: %s\n", optarg);
432 exit (STATE_WARNING);
433 }
434 }
435 break;
436 }
437 }
439 c = optind;
441 if (server_address == NULL && c < argc)
442 server_address = strdup (argv[c++]);
444 if (host_name == NULL && c < argc)
445 host_name = strdup (argv[c++]);
447 if (server_address == NULL) {
448 if (host_name == NULL)
449 usage4 (_("You must specify a server address or host name"));
450 else
451 server_address = strdup (host_name);
452 }
454 if (check_critical_time && critical_time>(double)socket_timeout)
455 socket_timeout = (int)critical_time + 1;
457 if (http_method == NULL)
458 http_method = strdup ("GET");
460 return TRUE;
461 }
465 /* Returns 1 if we're done processing the document body; 0 to keep going */
466 static int
467 document_headers_done (char *full_page)
468 {
469 const char *body;
471 for (body = full_page; *body; body++) {
472 if (!strncmp (body, "\n\n", 2) || !strncmp (body, "\n\r\n", 3))
473 break;
474 }
476 if (!*body)
477 return 0; /* haven't read end of headers yet */
479 full_page[body - full_page] = 0;
480 return 1;
481 }
483 static time_t
484 parse_time_string (const char *string)
485 {
486 struct tm tm;
487 time_t t;
488 memset (&tm, 0, sizeof(tm));
490 /* Like this: Tue, 25 Dec 2001 02:59:03 GMT */
492 if (isupper (string[0]) && /* Tue */
493 islower (string[1]) &&
494 islower (string[2]) &&
495 ',' == string[3] &&
496 ' ' == string[4] &&
497 (isdigit(string[5]) || string[5] == ' ') && /* 25 */
498 isdigit (string[6]) &&
499 ' ' == string[7] &&
500 isupper (string[8]) && /* Dec */
501 islower (string[9]) &&
502 islower (string[10]) &&
503 ' ' == string[11] &&
504 isdigit (string[12]) && /* 2001 */
505 isdigit (string[13]) &&
506 isdigit (string[14]) &&
507 isdigit (string[15]) &&
508 ' ' == string[16] &&
509 isdigit (string[17]) && /* 02: */
510 isdigit (string[18]) &&
511 ':' == string[19] &&
512 isdigit (string[20]) && /* 59: */
513 isdigit (string[21]) &&
514 ':' == string[22] &&
515 isdigit (string[23]) && /* 03 */
516 isdigit (string[24]) &&
517 ' ' == string[25] &&
518 'G' == string[26] && /* GMT */
519 'M' == string[27] && /* GMT */
520 'T' == string[28]) {
522 tm.tm_sec = 10 * (string[23]-'0') + (string[24]-'0');
523 tm.tm_min = 10 * (string[20]-'0') + (string[21]-'0');
524 tm.tm_hour = 10 * (string[17]-'0') + (string[18]-'0');
525 tm.tm_mday = 10 * (string[5] == ' ' ? 0 : string[5]-'0') + (string[6]-'0');
526 tm.tm_mon = (!strncmp (string+8, "Jan", 3) ? 0 :
527 !strncmp (string+8, "Feb", 3) ? 1 :
528 !strncmp (string+8, "Mar", 3) ? 2 :
529 !strncmp (string+8, "Apr", 3) ? 3 :
530 !strncmp (string+8, "May", 3) ? 4 :
531 !strncmp (string+8, "Jun", 3) ? 5 :
532 !strncmp (string+8, "Jul", 3) ? 6 :
533 !strncmp (string+8, "Aug", 3) ? 7 :
534 !strncmp (string+8, "Sep", 3) ? 8 :
535 !strncmp (string+8, "Oct", 3) ? 9 :
536 !strncmp (string+8, "Nov", 3) ? 10 :
537 !strncmp (string+8, "Dec", 3) ? 11 :
538 -1);
539 tm.tm_year = ((1000 * (string[12]-'0') +
540 100 * (string[13]-'0') +
541 10 * (string[14]-'0') +
542 (string[15]-'0'))
543 - 1900);
545 tm.tm_isdst = 0; /* GMT is never in DST, right? */
547 if (tm.tm_mon < 0 || tm.tm_mday < 1 || tm.tm_mday > 31)
548 return 0;
550 /*
551 This is actually wrong: we need to subtract the local timezone
552 offset from GMT from this value. But, that's ok in this usage,
553 because we only comparing these two GMT dates against each other,
554 so it doesn't matter what time zone we parse them in.
555 */
557 t = mktime (&tm);
558 if (t == (time_t) -1) t = 0;
560 if (verbose) {
561 const char *s = string;
562 while (*s && *s != '\r' && *s != '\n')
563 fputc (*s++, stdout);
564 printf (" ==> %lu\n", (unsigned long) t);
565 }
567 return t;
569 } else {
570 return 0;
571 }
572 }
576 static void
577 check_document_dates (const char *headers)
578 {
579 const char *s;
580 char *server_date = 0;
581 char *document_date = 0;
583 s = headers;
584 while (*s) {
585 const char *field = s;
586 const char *value = 0;
588 /* Find the end of the header field */
589 while (*s && !isspace(*s) && *s != ':')
590 s++;
592 /* Remember the header value, if any. */
593 if (*s == ':')
594 value = ++s;
596 /* Skip to the end of the header, including continuation lines. */
597 while (*s && !(*s == '\n' && (s[1] != ' ' && s[1] != '\t')))
598 s++;
599 s++;
601 /* Process this header. */
602 if (value && value > field+2) {
603 char *ff = (char *) malloc (value-field);
604 char *ss = ff;
605 while (field < value-1)
606 *ss++ = tolower(*field++);
607 *ss++ = 0;
609 if (!strcmp (ff, "date") || !strcmp (ff, "last-modified")) {
610 const char *e;
611 while (*value && isspace (*value))
612 value++;
613 for (e = value; *e && *e != '\r' && *e != '\n'; e++)
614 ;
615 ss = (char *) malloc (e - value + 1);
616 strncpy (ss, value, e - value);
617 ss[e - value] = 0;
618 if (!strcmp (ff, "date")) {
619 if (server_date) free (server_date);
620 server_date = ss;
621 } else {
622 if (document_date) free (document_date);
623 document_date = ss;
624 }
625 }
626 free (ff);
627 }
628 }
630 /* Done parsing the body. Now check the dates we (hopefully) parsed. */
631 if (!server_date || !*server_date) {
632 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Server date unknown\n"));
633 } else if (!document_date || !*document_date) {
634 die (STATE_CRITICAL, _("HTTP CRITICAL - Document modification date unknown\n"));
635 } else {
636 time_t srv_data = parse_time_string (server_date);
637 time_t doc_data = parse_time_string (document_date);
639 if (srv_data <= 0) {
640 die (STATE_CRITICAL, _("HTTP CRITICAL - Server date \"%100s\" unparsable"), server_date);
641 } else if (doc_data <= 0) {
642 die (STATE_CRITICAL, _("HTTP CRITICAL - Document date \"%100s\" unparsable"), document_date);
643 } else if (doc_data > srv_data + 30) {
644 die (STATE_CRITICAL, _("HTTP CRITICAL - Document is %d seconds in the future\n"), (int)doc_data - (int)srv_data);
645 } else if (doc_data < srv_data - maximum_age) {
646 int n = (srv_data - doc_data);
647 if (n > (60 * 60 * 24 * 2))
648 die (STATE_CRITICAL,
649 _("HTTP CRITICAL - Last modified %.1f days ago\n"),
650 ((float) n) / (60 * 60 * 24));
651 else
652 die (STATE_CRITICAL,
653 _("HTTP CRITICAL - Last modified %d:%02d:%02d ago\n"),
654 n / (60 * 60), (n / 60) % 60, n % 60);
655 }
657 free (server_date);
658 free (document_date);
659 }
660 }
662 int
663 get_content_length (const char *headers)
664 {
665 const char *s;
666 int content_length = 0;
668 s = headers;
669 while (*s) {
670 const char *field = s;
671 const char *value = 0;
673 /* Find the end of the header field */
674 while (*s && !isspace(*s) && *s != ':')
675 s++;
677 /* Remember the header value, if any. */
678 if (*s == ':')
679 value = ++s;
681 /* Skip to the end of the header, including continuation lines. */
682 while (*s && !(*s == '\n' && (s[1] != ' ' && s[1] != '\t')))
683 s++;
684 s++;
686 /* Process this header. */
687 if (value && value > field+2) {
688 char *ff = (char *) malloc (value-field);
689 char *ss = ff;
690 while (field < value-1)
691 *ss++ = tolower(*field++);
692 *ss++ = 0;
694 if (!strcmp (ff, "content-length")) {
695 const char *e;
696 while (*value && isspace (*value))
697 value++;
698 for (e = value; *e && *e != '\r' && *e != '\n'; e++)
699 ;
700 ss = (char *) malloc (e - value + 1);
701 strncpy (ss, value, e - value);
702 ss[e - value] = 0;
703 content_length = atoi(ss);
704 free (ss);
705 }
706 free (ff);
707 }
708 }
709 return (content_length);
710 }
712 int
713 check_http (void)
714 {
715 char *msg;
716 char *status_line;
717 char *status_code;
718 char *header;
719 char *page;
720 char *auth;
721 int http_status;
722 int i = 0;
723 size_t pagesize = 0;
724 char *full_page;
725 char *buf;
726 char *pos;
727 long microsec;
728 double elapsed_time;
729 int page_len = 0;
730 int result = STATE_UNKNOWN;
732 /* try to connect to the host at the given port number */
733 if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK)
734 die (STATE_CRITICAL, _("HTTP CRITICAL - Unable to open TCP socket\n"));
735 #ifdef HAVE_SSL
736 if (use_ssl == TRUE) {
737 np_net_ssl_init(sd);
738 if (check_cert == TRUE) {
739 result = np_net_ssl_check_cert(days_till_exp);
740 np_net_ssl_cleanup();
741 if(sd) close(sd);
742 return result;
743 }
744 }
745 #endif /* HAVE_SSL */
747 asprintf (&buf, "%s %s HTTP/1.0\r\n%s\r\n", http_method, server_url, user_agent);
749 /* tell HTTP/1.1 servers not to keep the connection alive */
750 asprintf (&buf, "%sConnection: close\r\n", buf);
752 /* optionally send the host header info */
753 if (host_name)
754 asprintf (&buf, "%sHost: %s\r\n", buf, host_name);
756 /* optionally send any other header tag */
757 if (http_opt_headers_count) {
758 for (i = 0; i < http_opt_headers_count ; i++) {
759 for ((pos = strtok(http_opt_headers[i], INPUT_DELIMITER)); pos; (pos = strtok(NULL, INPUT_DELIMITER)))
760 asprintf (&buf, "%s%s\r\n", buf, pos);
761 }
762 free(http_opt_headers);
763 }
765 /* optionally send the authentication info */
766 if (strlen(user_auth)) {
767 auth = base64 (user_auth, strlen (user_auth));
768 asprintf (&buf, "%sAuthorization: Basic %s\r\n", buf, auth);
769 }
771 /* either send http POST data */
772 if (http_post_data) {
773 if (http_content_type) {
774 asprintf (&buf, "%sContent-Type: %s\r\n", buf, http_content_type);
775 } else {
776 asprintf (&buf, "%sContent-Type: application/x-www-form-urlencoded\r\n", buf);
777 }
779 asprintf (&buf, "%sContent-Length: %i\r\n\r\n", buf, (int)strlen (http_post_data));
780 asprintf (&buf, "%s%s%s", buf, http_post_data, CRLF);
781 }
782 else {
783 /* or just a newline so the server knows we're done with the request */
784 asprintf (&buf, "%s%s", buf, CRLF);
785 }
787 if (verbose) printf ("%s\n", buf);
788 my_send (buf, strlen (buf));
790 /* fetch the page */
791 full_page = strdup("");
792 while ((i = my_recv (buffer, MAX_INPUT_BUFFER-1)) > 0) {
793 buffer[i] = '\0';
794 asprintf (&full_page, "%s%s", full_page, buffer);
795 pagesize += i;
797 if (no_body && document_headers_done (full_page)) {
798 i = 0;
799 break;
800 }
801 }
803 if (i < 0 && errno != ECONNRESET) {
804 #ifdef HAVE_SSL
805 /*
806 if (use_ssl) {
807 sslerr=SSL_get_error(ssl, i);
808 if ( sslerr == SSL_ERROR_SSL ) {
809 die (STATE_WARNING, _("HTTP WARNING - Client Certificate Required\n"));
810 } else {
811 die (STATE_CRITICAL, _("HTTP CRITICAL - Error on receive\n"));
812 }
813 }
814 else {
815 */
816 #endif
817 die (STATE_CRITICAL, _("HTTP CRITICAL - Error on receive\n"));
818 #ifdef HAVE_SSL
819 /* XXX
820 }
821 */
822 #endif
823 }
825 /* return a CRITICAL status if we couldn't read any data */
826 if (pagesize == (size_t) 0)
827 die (STATE_CRITICAL, _("HTTP CRITICAL - No data received from host\n"));
829 /* close the connection */
830 #ifdef HAVE_SSL
831 np_net_ssl_cleanup();
832 #endif
833 if(sd) close(sd);
835 /* reset the alarm */
836 alarm (0);
838 /* leave full_page untouched so we can free it later */
839 page = full_page;
841 if (verbose)
842 printf ("%s://%s:%d%s is %d characters\n",
843 use_ssl ? "https" : "http", server_address,
844 server_port, server_url, (int)pagesize);
846 /* find status line and null-terminate it */
847 status_line = page;
848 page += (size_t) strcspn (page, "\r\n");
849 pos = page;
850 page += (size_t) strspn (page, "\r\n");
851 status_line[strcspn(status_line, "\r\n")] = 0;
852 strip (status_line);
853 if (verbose)
854 printf ("STATUS: %s\n", status_line);
856 /* find header info and null-terminate it */
857 header = page;
858 while (strcspn (page, "\r\n") > 0) {
859 page += (size_t) strcspn (page, "\r\n");
860 pos = page;
861 if ((strspn (page, "\r") == 1 && strspn (page, "\r\n") >= 2) ||
862 (strspn (page, "\n") == 1 && strspn (page, "\r\n") >= 2))
863 page += (size_t) 2;
864 else
865 page += (size_t) 1;
866 }
867 page += (size_t) strspn (page, "\r\n");
868 header[pos - header] = 0;
869 if (verbose)
870 printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header,
871 (no_body ? " [[ skipped ]]" : page));
873 /* make sure the status line matches the response we are looking for */
874 if (!strstr (status_line, server_expect)) {
875 if (server_port == HTTP_PORT)
876 asprintf (&msg,
877 _("Invalid HTTP response received from host\n"));
878 else
879 asprintf (&msg,
880 _("Invalid HTTP response received from host on port %d\n"),
881 server_port);
882 die (STATE_CRITICAL, "HTTP CRITICAL - %s", msg);
883 }
885 /* Exit here if server_expect was set by user and not default */
886 if ( server_expect_yn ) {
887 asprintf (&msg,
888 _("HTTP OK: Status line output matched \"%s\"\n"),
889 server_expect);
890 if (verbose)
891 printf ("%s\n",msg);
892 }
893 else {
894 /* Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF */
895 /* HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT */
896 /* Status-Code = 3 DIGITS */
898 status_code = strchr (status_line, ' ') + sizeof (char);
899 if (strspn (status_code, "1234567890") != 3)
900 die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status Line (%s)\n"), status_line);
902 http_status = atoi (status_code);
904 /* check the return code */
906 if (http_status >= 600 || http_status < 100)
907 die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%s)\n"), status_line);
909 /* server errors result in a critical state */
910 else if (http_status >= 500)
911 die (STATE_CRITICAL, _("HTTP CRITICAL: %s\n"), status_line);
913 /* client errors result in a warning state */
914 else if (http_status >= 400)
915 die (STATE_WARNING, _("HTTP WARNING: %s\n"), status_line);
917 /* check redirected page if specified */
918 else if (http_status >= 300) {
920 if (onredirect == STATE_DEPENDENT)
921 redir (header, status_line);
922 else if (onredirect == STATE_UNKNOWN)
923 printf (_("HTTP UNKNOWN"));
924 else if (onredirect == STATE_OK)
925 printf (_("HTTP OK"));
926 else if (onredirect == STATE_WARNING)
927 printf (_("HTTP WARNING"));
928 else if (onredirect == STATE_CRITICAL)
929 printf (_("HTTP CRITICAL"));
930 microsec = deltime (tv);
931 elapsed_time = (double)microsec / 1.0e6;
932 die (onredirect,
933 _(" - %s - %.3f second response time %s|%s %s\n"),
934 status_line, elapsed_time,
935 (display_html ? "</A>" : ""),
936 perfd_time (elapsed_time), perfd_size (pagesize));
937 } /* end if (http_status >= 300) */
939 } /* end else (server_expect_yn) */
941 if (maximum_age >= 0) {
942 check_document_dates (header);
943 }
945 /* check elapsed time */
946 microsec = deltime (tv);
947 elapsed_time = (double)microsec / 1.0e6;
948 asprintf (&msg,
949 _(" - %s - %.3f second response time %s|%s %s\n"),
950 status_line, elapsed_time,
951 (display_html ? "</A>" : ""),
952 perfd_time (elapsed_time), perfd_size (pagesize));
953 if (check_critical_time == TRUE && elapsed_time > critical_time)
954 die (STATE_CRITICAL, "HTTP %s: %s", _("CRITICAL"), msg);
955 if (check_warning_time == TRUE && elapsed_time > warning_time)
956 die (STATE_WARNING, "HTTP %s: %s", _("WARNING"), msg);
958 /* Page and Header content checks go here */
959 /* these checks should be last */
961 if (strlen (string_expect)) {
962 if (strstr (page, string_expect)) {
963 printf (_("HTTP OK %s - %.3f second response time %s|%s %s\n"),
964 status_line, elapsed_time,
965 (display_html ? "</A>" : ""),
966 perfd_time (elapsed_time), perfd_size (pagesize));
967 exit (STATE_OK);
968 }
969 else {
970 printf (_("HTTP CRITICAL - string not found%s|%s %s\n"),
971 (display_html ? "</A>" : ""),
972 perfd_time (elapsed_time), perfd_size (pagesize));
973 exit (STATE_CRITICAL);
974 }
975 }
977 if (strlen (regexp)) {
978 errcode = regexec (&preg, page, REGS, pmatch, 0);
979 if ((errcode == 0 && invert_regex == 0) || (errcode == REG_NOMATCH && invert_regex == 1)) {
980 printf (_("HTTP OK %s - %.3f second response time %s|%s %s\n"),
981 status_line, elapsed_time,
982 (display_html ? "</A>" : ""),
983 perfd_time (elapsed_time), perfd_size (pagesize));
984 exit (STATE_OK);
985 }
986 else if ((errcode == REG_NOMATCH && invert_regex == 0) || (errcode == 0 && invert_regex == 1)) {
987 if (invert_regex == 0)
988 msg = strdup(_("pattern not found"));
989 else
990 msg = strdup(_("pattern found"));
991 printf (("%s - %s%s|%s %s\n"),
992 _("HTTP CRITICAL"),
993 msg,
994 (display_html ? "</A>" : ""),
995 perfd_time (elapsed_time), perfd_size (pagesize));
996 exit (STATE_CRITICAL);
997 }
998 else {
999 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
1000 printf (_("HTTP CRITICAL - Execute Error: %s\n"), errbuf);
1001 exit (STATE_CRITICAL);
1002 }
1003 }
1005 /* make sure the page is of an appropriate size */
1006 /* page_len = get_content_length(header); */
1007 page_len = pagesize;
1008 if ((max_page_len > 0) && (page_len > max_page_len)) {
1009 printf (_("HTTP WARNING: page size %d too large%s|%s\n"),
1010 page_len, (display_html ? "</A>" : ""), perfd_size (page_len) );
1011 exit (STATE_WARNING);
1012 } else if ((min_page_len > 0) && (page_len < min_page_len)) {
1013 printf (_("HTTP WARNING: page size %d too small%s|%s\n"),
1014 page_len, (display_html ? "</A>" : ""), perfd_size (page_len) );
1015 exit (STATE_WARNING);
1016 }
1017 /* We only get here if all tests have been passed */
1018 asprintf (&msg, _("HTTP OK %s - %d bytes in %.3f seconds %s|%s %s\n"),
1019 status_line, page_len, elapsed_time,
1020 (display_html ? "</A>" : ""),
1021 perfd_time (elapsed_time), perfd_size (page_len));
1022 die (STATE_OK, "%s", msg);
1023 return STATE_UNKNOWN;
1024 }
1028 /* per RFC 2396 */
1029 #define URI_HTTP "%5[HTPShtps]"
1030 #define URI_HOST "%255[-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
1031 #define URI_PORT "%6d" /* MAX_PORT's width is 5 chars, 6 to detect overflow */
1032 #define URI_PATH "%[-_.!~*'();/?:@&=+$,%#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
1033 #define HD1 URI_HTTP "://" URI_HOST ":" URI_PORT "/" URI_PATH
1034 #define HD2 URI_HTTP "://" URI_HOST "/" URI_PATH
1035 #define HD3 URI_HTTP "://" URI_HOST ":" URI_PORT
1036 #define HD4 URI_HTTP "://" URI_HOST
1037 #define HD5 URI_PATH
1039 void
1040 redir (char *pos, char *status_line)
1041 {
1042 int i = 0;
1043 char *x;
1044 char xx[2];
1045 char type[6];
1046 char *addr;
1047 char *url;
1049 addr = malloc (MAX_IPV4_HOSTLENGTH + 1);
1050 if (addr == NULL)
1051 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate addr\n"));
1053 url = malloc (strcspn (pos, "\r\n"));
1054 if (url == NULL)
1055 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate url\n"));
1057 while (pos) {
1058 sscanf (pos, "%1[Ll]%*1[Oo]%*1[Cc]%*1[Aa]%*1[Tt]%*1[Ii]%*1[Oo]%*1[Nn]:%n", xx, &i);
1059 if (i == 0) {
1060 pos += (size_t) strcspn (pos, "\r\n");
1061 pos += (size_t) strspn (pos, "\r\n");
1062 if (strlen(pos) == 0)
1063 die (STATE_UNKNOWN,
1064 _("HTTP UNKNOWN - Could not find redirect location - %s%s\n"),
1065 status_line, (display_html ? "</A>" : ""));
1066 continue;
1067 }
1069 pos += i;
1070 pos += strspn (pos, " \t");
1072 /*
1073 * RFC 2616 (4.2): ``Header fields can be extended over multiple lines by
1074 * preceding each extra line with at least one SP or HT.''
1075 */
1076 for (; (i = strspn (pos, "\r\n")); pos += i) {
1077 pos += i;
1078 if (!(i = strspn (pos, " \t"))) {
1079 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Empty redirect location%s\n"),
1080 display_html ? "</A>" : "");
1081 }
1082 }
1084 url = realloc (url, strcspn (pos, "\r\n") + 1);
1085 if (url == NULL)
1086 die (STATE_UNKNOWN, _("HTTP UNKNOWN - could not allocate url\n"));
1088 /* URI_HTTP, URI_HOST, URI_PORT, URI_PATH */
1089 if (sscanf (pos, HD1, type, addr, &i, url) == 4)
1090 use_ssl = server_type_check (type);
1092 /* URI_HTTP URI_HOST URI_PATH */
1093 else if (sscanf (pos, HD2, type, addr, url) == 3 ) {
1094 use_ssl = server_type_check (type);
1095 i = server_port_check (use_ssl);
1096 }
1098 /* URI_HTTP URI_HOST URI_PORT */
1099 else if(sscanf (pos, HD3, type, addr, &i) == 3) {
1100 strcpy (url, HTTP_URL);
1101 use_ssl = server_type_check (type);
1102 }
1104 /* URI_HTTP URI_HOST */
1105 else if(sscanf (pos, HD4, type, addr) == 2) {
1106 strcpy (url, HTTP_URL);
1107 use_ssl = server_type_check (type);
1108 i = server_port_check (use_ssl);
1109 }
1111 /* URI_PATH */
1112 else if (sscanf (pos, HD5, url) == 1) {
1113 /* relative url */
1114 if ((url[0] != '/')) {
1115 if ((x = strrchr(server_url, '/')))
1116 *x = '\0';
1117 asprintf (&url, "%s/%s", server_url, url);
1118 }
1119 i = server_port;
1120 strcpy (type, server_type);
1121 strcpy (addr, host_name ? host_name : server_address);
1122 }
1124 else {
1125 die (STATE_UNKNOWN,
1126 _("HTTP UNKNOWN - Could not parse redirect location - %s%s\n"),
1127 pos, (display_html ? "</A>" : ""));
1128 }
1130 break;
1132 } /* end while (pos) */
1134 if (++redir_depth > max_depth)
1135 die (STATE_WARNING,
1136 _("HTTP WARNING - maximum redirection depth %d exceeded - %s://%s:%d%s%s\n"),
1137 max_depth, type, addr, i, url, (display_html ? "</A>" : ""));
1139 if (server_port==i &&
1140 !strcmp(server_address, addr) &&
1141 (host_name && !strcmp(host_name, addr)) &&
1142 !strcmp(server_url, url))
1143 die (STATE_WARNING,
1144 _("HTTP WARNING - redirection creates an infinite loop - %s://%s:%d%s%s\n"),
1145 type, addr, i, url, (display_html ? "</A>" : ""));
1147 strcpy (server_type, type);
1149 free (host_name);
1150 host_name = strdup (addr);
1152 free (server_address);
1153 server_address = strdup (addr);
1155 free (server_url);
1156 if ((url[0] == '/'))
1157 server_url = strdup (url);
1158 else if (asprintf(&server_url, "/%s", url) == -1)
1159 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate server_url%s\n"),
1160 display_html ? "</A>" : "");
1161 free(url);
1163 if ((server_port = i) > MAX_PORT)
1164 die (STATE_UNKNOWN,
1165 _("HTTP UNKNOWN - Redirection to port above %d - %s://%s:%d%s%s\n"),
1166 MAX_PORT, server_type, server_address, server_port, server_url,
1167 display_html ? "</A>" : "");
1169 if (verbose)
1170 printf (_("Redirection to %s://%s:%d%s\n"), server_type,
1171 host_name ? host_name : server_address, server_port, server_url);
1173 check_http ();
1174 }
1178 int
1179 server_type_check (const char *type)
1180 {
1181 if (strcmp (type, "https"))
1182 return FALSE;
1183 else
1184 return TRUE;
1185 }
1187 int
1188 server_port_check (int ssl_flag)
1189 {
1190 if (ssl_flag)
1191 return HTTPS_PORT;
1192 else
1193 return HTTP_PORT;
1194 }
1196 char *perfd_time (double elapsed_time)
1197 {
1198 return fperfdata ("time", elapsed_time, "s",
1199 check_warning_time, warning_time,
1200 check_critical_time, critical_time,
1201 TRUE, 0, FALSE, 0);
1202 }
1206 char *perfd_size (int page_len)
1207 {
1208 return perfdata ("size", page_len, "B",
1209 (min_page_len>0?TRUE:FALSE), min_page_len,
1210 (min_page_len>0?TRUE:FALSE), 0,
1211 TRUE, 0, FALSE, 0);
1212 }
1214 void
1215 print_help (void)
1216 {
1217 print_revision (progname, revision);
1219 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
1220 printf (COPYRIGHT, copyright, email);
1222 printf ("%s\n", _("This plugin tests the HTTP service on the specified host. It can test"));
1223 printf ("%s\n", _("normal (http) and secure (https) servers, follow redirects, search for"));
1224 printf ("%s\n", _("strings and regular expressions, check connection times, and report on"));
1225 printf ("%s\n", _("certificate expiration times."));
1227 printf ("\n\n");
1229 print_usage ();
1231 printf (_("NOTE: One or both of -H and -I must be specified"));
1233 printf ("\n");
1235 printf (_(UT_HELP_VRSN));
1237 printf (" %s\n", "-H, --hostname=ADDRESS");
1238 printf (" %s\n", _("Host name argument for servers using host headers (virtual host)"));
1239 printf (" %s\n", _("Append a port to include it in the header (eg: example.com:5000)"));
1240 printf (" %s\n", "-I, --IP-address=ADDRESS");
1241 printf (" %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup)."));
1242 printf (" %s\n", "-p, --port=INTEGER");
1243 printf (" %s", _("Port number (default: "));
1244 printf ("%d)\n", HTTP_PORT);
1246 printf (_(UT_IPv46));
1248 #ifdef HAVE_SSL
1249 printf (" %s\n", "-S, --ssl");
1250 printf (" %s\n", _("Connect via SSL. Port defaults to 443"));
1251 printf (" %s\n", "-C, --certificate=INTEGER");
1252 printf (" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443"));
1253 printf (" %s\n", _("(when this option is used the url is not checked.)\n"));
1254 #endif
1256 printf (" %s\n", "-e, --expect=STRING");
1257 printf (" %s\n", _("String to expect in first (status) line of server response (default: "));
1258 printf ("%s)\n", HTTP_EXPECT);
1259 printf (" %s\n", _("If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)"));
1260 printf (" %s\n", "-s, --string=STRING");
1261 printf (" %s\n", _("String to expect in the content"));
1262 printf (" %s\n", "-u, --url=PATH");
1263 printf (" %s\n", _("URL to GET or POST (default: /)"));
1264 printf (" %s\n", "-P, --post=STRING");
1265 printf (" %s\n", _("URL encoded http POST data"));
1266 printf (" %s\n", "-N, --no-body");
1267 printf (" %s\n", _("Don't wait for document body: stop reading after headers."));
1268 printf (" %s\n", _("(Note that this still does an HTTP GET or POST, not a HEAD.)"));
1269 printf (" %s\n", "-M, --max-age=SECONDS");
1270 printf (" %s\n", _("Warn if document is more than SECONDS old. the number can also be of"));
1271 printf (" %s\n", _("the form \"10m\" for minutes, \"10h\" for hours, or \"10d\" for days."));
1272 printf (" %s\n", "-T, --content-type=STRING");
1273 printf (" %s\n", _("specify Content-Type header media type when POSTing\n"));
1275 printf (" %s\n", "-l, --linespan");
1276 printf (" %s\n", _("Allow regex to span newlines (must precede -r or -R)"));
1277 printf (" %s\n", "-r, --regex, --ereg=STRING");
1278 printf (" %s\n", _("Search page for regex STRING"));
1279 printf (" %s\n", "-R, --eregi=STRING");
1280 printf (" %s\n", _("Search page for case-insensitive regex STRING"));
1281 printf (" %s\n", "--invert-regex");
1282 printf (" %s\n", _("Return CRITICAL if found, OK if not\n"));
1284 printf (" %s\n", "-a, --authorization=AUTH_PAIR");
1285 printf (" %s\n", _("Username:password on sites with basic authentication"));
1286 printf (" %s\n", "-A, --useragent=STRING");
1287 printf (" %s\n", _("String to be sent in http header as \"User Agent\""));
1288 printf (" %s\n", "-k, --header=STRING");
1289 printf (" %s\n", _(" Any other tags to be sent in http header. Use multiple times for additional headers"));
1290 printf (" %s\n", "-L, --link");
1291 printf (" %s\n", _("Wrap output in HTML link (obsoleted by urlize)"));
1292 printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow>");
1293 printf (" %s\n", _("How to handle redirected pages"));
1294 printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>");
1295 printf (" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)"));
1297 printf (_(UT_WARN_CRIT));
1299 printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
1301 printf (_(UT_VERBOSE));
1303 printf (_("Notes:"));
1304 printf (" %s\n", _("This plugin will attempt to open an HTTP connection with the host."));
1305 printf (" %s\n", _("Successful connects return STATE_OK, refusals and timeouts return STATE_CRITICAL"));
1306 printf (" %s\n", _("other errors return STATE_UNKNOWN. Successful connects, but incorrect reponse"));
1307 printf (" %s\n", _("messages from the host result in STATE_WARNING return values. If you are"));
1308 printf (" %s\n", _("checking a virtual server that uses 'host headers' you must supply the FQDN"));
1309 printf (" %s\n", _("(fully qualified domain name) as the [host_name] argument."));
1311 #ifdef HAVE_SSL
1312 printf (" %s\n", _("This plugin can also check whether an SSL enabled web server is able to"));
1313 printf (" %s\n", _("serve content (optionally within a specified time) or whether the X509 "));
1314 printf (" %s\n", _("certificate is still valid for the specified number of days."));
1315 printf (_("Examples:"));
1316 printf (" %s\n\n", "CHECK CONTENT: check_http -w 5 -c 10 --ssl -H www.verisign.com");
1317 printf (" %s\n", _("When the 'www.verisign.com' server returns its content within 5 seconds,"));
1318 printf (" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds"));
1319 printf (" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,"));
1320 printf (" %s\n\n", _("a STATE_CRITICAL will be returned."));
1322 printf (" %s\n\n", "CHECK CERTIFICATE: check_http -H www.verisign.com -C 14");
1323 printf (" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 14 days,"));
1324 printf (" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than"));
1325 printf (" %s\n", _("14 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when"));
1326 printf (" %s\n\n", _("the certificate is expired."));
1327 #endif
1329 printf (_(UT_SUPPORT));
1331 }
1335 void
1336 print_usage (void)
1337 {
1338 printf (_("Usage:"));
1339 printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname);
1340 printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L]\n");
1341 printf (" [-a auth] [-f <ok | warn | critcal | follow>] [-e <expect>]\n");
1342 printf (" [-s string] [-l] [-r <regex> | -R <case-insensitive regex>] [-P string]\n");
1343 printf (" [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>] [-A string]\n");
1344 printf (" [-k string] [-S] [-C <age>] [-T <content-type>]\n");
1345 }