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