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