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