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