Prep for 1.4.10
[monitoring-plugins.git] / plugins / check_http.c
blobb371cd6413267e6ccc556386869afe67390e8934
1 /******************************************************************************
3 * Nagios check_http plugin
5 * License: GPL
6 * Copyright (c) 1999-2006 nagios-plugins team
8 * Last Modified: $Date$
10 * Description:
12 * This file contains the check_http plugin
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.
20 * License Information:
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.
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.
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"
52 #define INPUT_DELIMITER ";"
54 #define HTTP_EXPECT "HTTP/1."
55 enum {
56 MAX_IPV4_HOSTLENGTH = 255,
57 HTTP_PORT = 80,
58 HTTPS_PORT = 443,
59 MAX_PORT = 65535
62 #ifdef HAVE_SSL
63 int check_cert = FALSE;
64 int days_till_exp;
65 char *randbuff;
66 X509 *server_cert;
67 # define my_recv(buf, len) ((use_ssl) ? np_net_ssl_read(buf, len) : read(sd, buf, len))
68 # define my_send(buf, len) ((use_ssl) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0))
69 #else /* ifndef HAVE_SSL */
70 # define my_recv(buf, len) read(sd, buf, len)
71 # define my_send(buf, len) send(sd, buf, len, 0)
72 #endif /* HAVE_SSL */
73 int no_body = FALSE;
74 int maximum_age = -1;
76 enum {
77 REGS = 2,
78 MAX_RE_SIZE = 256
80 #include "regex.h"
81 regex_t preg;
82 regmatch_t pmatch[REGS];
83 char regexp[MAX_RE_SIZE];
84 char errbuf[MAX_INPUT_BUFFER];
85 int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE;
86 int errcode;
87 int invert_regex = 0;
89 struct timeval tv;
91 #define HTTP_URL "/"
92 #define CRLF "\r\n"
94 int specify_port = FALSE;
95 int server_port = HTTP_PORT;
96 char server_port_text[6] = "";
97 char server_type[6] = "http";
98 char *server_address;
99 char *host_name;
100 char *server_url;
101 char *user_agent;
102 int server_url_length;
103 int server_expect_yn = 0;
104 char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT;
105 char string_expect[MAX_INPUT_BUFFER] = "";
106 double warning_time = 0;
107 int check_warning_time = FALSE;
108 double critical_time = 0;
109 int check_critical_time = FALSE;
110 char user_auth[MAX_INPUT_BUFFER] = "";
111 int display_html = FALSE;
112 char **http_opt_headers;
113 int http_opt_headers_count = 0;
114 int onredirect = STATE_OK;
115 int use_ssl = FALSE;
116 int verbose = FALSE;
117 int sd;
118 int min_page_len = 0;
119 int max_page_len = 0;
120 int redir_depth = 0;
121 int max_depth = 15;
122 char *http_method;
123 char *http_post_data;
124 char *http_content_type;
125 char buffer[MAX_INPUT_BUFFER];
127 int process_arguments (int, char **);
128 static char *base64 (const char *bin, size_t len);
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);
139 main (int argc, char **argv)
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", 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;
168 /* process command-line arguments */
170 process_arguments (int argc, char **argv)
172 int c = 1;
174 enum {
175 INVERT_REGEX = CHAR_MAX + 1
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}
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");
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;
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;
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;
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;
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;
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 */
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;
408 case 'N': /* no-body */
409 no_body = TRUE;
410 break;
411 case 'M': /* max-age */
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);
428 break;
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);
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;
458 /* written by lauri alanko */
459 static char *
460 base64 (const char *bin, size_t len)
463 char *buf = (char *) malloc ((len + 2) / 3 * 4 + 1);
464 size_t i = 0, j = 0;
466 char BASE64_END = '=';
467 char base64_table[64];
468 strncpy (base64_table, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", 64);
470 while (j < len - 2) {
471 buf[i++] = base64_table[bin[j] >> 2];
472 buf[i++] = base64_table[((bin[j] & 3) << 4) | (bin[j + 1] >> 4)];
473 buf[i++] = base64_table[((bin[j + 1] & 15) << 2) | (bin[j + 2] >> 6)];
474 buf[i++] = base64_table[bin[j + 2] & 63];
475 j += 3;
478 switch (len - j) {
479 case 1:
480 buf[i++] = base64_table[bin[j] >> 2];
481 buf[i++] = base64_table[(bin[j] & 3) << 4];
482 buf[i++] = BASE64_END;
483 buf[i++] = BASE64_END;
484 break;
485 case 2:
486 buf[i++] = base64_table[bin[j] >> 2];
487 buf[i++] = base64_table[((bin[j] & 3) << 4) | (bin[j + 1] >> 4)];
488 buf[i++] = base64_table[(bin[j + 1] & 15) << 2];
489 buf[i++] = BASE64_END;
490 break;
491 case 0:
492 break;
495 buf[i] = '\0';
496 return buf;
501 /* Returns 1 if we're done processing the document body; 0 to keep going */
502 static int
503 document_headers_done (char *full_page)
505 const char *body;
507 for (body = full_page; *body; body++) {
508 if (!strncmp (body, "\n\n", 2) || !strncmp (body, "\n\r\n", 3))
509 break;
512 if (!*body)
513 return 0; /* haven't read end of headers yet */
515 full_page[body - full_page] = 0;
516 return 1;
519 static time_t
520 parse_time_string (const char *string)
522 struct tm tm;
523 time_t t;
524 memset (&tm, 0, sizeof(tm));
526 /* Like this: Tue, 25 Dec 2001 02:59:03 GMT */
528 if (isupper (string[0]) && /* Tue */
529 islower (string[1]) &&
530 islower (string[2]) &&
531 ',' == string[3] &&
532 ' ' == string[4] &&
533 (isdigit(string[5]) || string[5] == ' ') && /* 25 */
534 isdigit (string[6]) &&
535 ' ' == string[7] &&
536 isupper (string[8]) && /* Dec */
537 islower (string[9]) &&
538 islower (string[10]) &&
539 ' ' == string[11] &&
540 isdigit (string[12]) && /* 2001 */
541 isdigit (string[13]) &&
542 isdigit (string[14]) &&
543 isdigit (string[15]) &&
544 ' ' == string[16] &&
545 isdigit (string[17]) && /* 02: */
546 isdigit (string[18]) &&
547 ':' == string[19] &&
548 isdigit (string[20]) && /* 59: */
549 isdigit (string[21]) &&
550 ':' == string[22] &&
551 isdigit (string[23]) && /* 03 */
552 isdigit (string[24]) &&
553 ' ' == string[25] &&
554 'G' == string[26] && /* GMT */
555 'M' == string[27] && /* GMT */
556 'T' == string[28]) {
558 tm.tm_sec = 10 * (string[23]-'0') + (string[24]-'0');
559 tm.tm_min = 10 * (string[20]-'0') + (string[21]-'0');
560 tm.tm_hour = 10 * (string[17]-'0') + (string[18]-'0');
561 tm.tm_mday = 10 * (string[5] == ' ' ? 0 : string[5]-'0') + (string[6]-'0');
562 tm.tm_mon = (!strncmp (string+8, "Jan", 3) ? 0 :
563 !strncmp (string+8, "Feb", 3) ? 1 :
564 !strncmp (string+8, "Mar", 3) ? 2 :
565 !strncmp (string+8, "Apr", 3) ? 3 :
566 !strncmp (string+8, "May", 3) ? 4 :
567 !strncmp (string+8, "Jun", 3) ? 5 :
568 !strncmp (string+8, "Jul", 3) ? 6 :
569 !strncmp (string+8, "Aug", 3) ? 7 :
570 !strncmp (string+8, "Sep", 3) ? 8 :
571 !strncmp (string+8, "Oct", 3) ? 9 :
572 !strncmp (string+8, "Nov", 3) ? 10 :
573 !strncmp (string+8, "Dec", 3) ? 11 :
574 -1);
575 tm.tm_year = ((1000 * (string[12]-'0') +
576 100 * (string[13]-'0') +
577 10 * (string[14]-'0') +
578 (string[15]-'0'))
579 - 1900);
581 tm.tm_isdst = 0; /* GMT is never in DST, right? */
583 if (tm.tm_mon < 0 || tm.tm_mday < 1 || tm.tm_mday > 31)
584 return 0;
587 This is actually wrong: we need to subtract the local timezone
588 offset from GMT from this value. But, that's ok in this usage,
589 because we only comparing these two GMT dates against each other,
590 so it doesn't matter what time zone we parse them in.
593 t = mktime (&tm);
594 if (t == (time_t) -1) t = 0;
596 if (verbose) {
597 const char *s = string;
598 while (*s && *s != '\r' && *s != '\n')
599 fputc (*s++, stdout);
600 printf (" ==> %lu\n", (unsigned long) t);
603 return t;
605 } else {
606 return 0;
612 static void
613 check_document_dates (const char *headers)
615 const char *s;
616 char *server_date = 0;
617 char *document_date = 0;
619 s = headers;
620 while (*s) {
621 const char *field = s;
622 const char *value = 0;
624 /* Find the end of the header field */
625 while (*s && !isspace(*s) && *s != ':')
626 s++;
628 /* Remember the header value, if any. */
629 if (*s == ':')
630 value = ++s;
632 /* Skip to the end of the header, including continuation lines. */
633 while (*s && !(*s == '\n' && (s[1] != ' ' && s[1] != '\t')))
634 s++;
635 s++;
637 /* Process this header. */
638 if (value && value > field+2) {
639 char *ff = (char *) malloc (value-field);
640 char *ss = ff;
641 while (field < value-1)
642 *ss++ = tolower(*field++);
643 *ss++ = 0;
645 if (!strcmp (ff, "date") || !strcmp (ff, "last-modified")) {
646 const char *e;
647 while (*value && isspace (*value))
648 value++;
649 for (e = value; *e && *e != '\r' && *e != '\n'; e++)
651 ss = (char *) malloc (e - value + 1);
652 strncpy (ss, value, e - value);
653 ss[e - value] = 0;
654 if (!strcmp (ff, "date")) {
655 if (server_date) free (server_date);
656 server_date = ss;
657 } else {
658 if (document_date) free (document_date);
659 document_date = ss;
662 free (ff);
666 /* Done parsing the body. Now check the dates we (hopefully) parsed. */
667 if (!server_date || !*server_date) {
668 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Server date unknown\n"));
669 } else if (!document_date || !*document_date) {
670 die (STATE_CRITICAL, _("HTTP CRITICAL - Document modification date unknown\n"));
671 } else {
672 time_t srv_data = parse_time_string (server_date);
673 time_t doc_data = parse_time_string (document_date);
675 if (srv_data <= 0) {
676 die (STATE_CRITICAL, _("HTTP CRITICAL - Server date \"%100s\" unparsable"), server_date);
677 } else if (doc_data <= 0) {
678 die (STATE_CRITICAL, _("HTTP CRITICAL - Document date \"%100s\" unparsable"), document_date);
679 } else if (doc_data > srv_data + 30) {
680 die (STATE_CRITICAL, _("HTTP CRITICAL - Document is %d seconds in the future\n"), (int)doc_data - (int)srv_data);
681 } else if (doc_data < srv_data - maximum_age) {
682 int n = (srv_data - doc_data);
683 if (n > (60 * 60 * 24 * 2))
684 die (STATE_CRITICAL,
685 _("HTTP CRITICAL - Last modified %.1f days ago\n"),
686 ((float) n) / (60 * 60 * 24));
687 else
688 die (STATE_CRITICAL,
689 _("HTTP CRITICAL - Last modified %d:%02d:%02d ago\n"),
690 n / (60 * 60), (n / 60) % 60, n % 60);
693 free (server_date);
694 free (document_date);
699 get_content_length (const char *headers)
701 const char *s;
702 int content_length = 0;
704 s = headers;
705 while (*s) {
706 const char *field = s;
707 const char *value = 0;
709 /* Find the end of the header field */
710 while (*s && !isspace(*s) && *s != ':')
711 s++;
713 /* Remember the header value, if any. */
714 if (*s == ':')
715 value = ++s;
717 /* Skip to the end of the header, including continuation lines. */
718 while (*s && !(*s == '\n' && (s[1] != ' ' && s[1] != '\t')))
719 s++;
720 s++;
722 /* Process this header. */
723 if (value && value > field+2) {
724 char *ff = (char *) malloc (value-field);
725 char *ss = ff;
726 while (field < value-1)
727 *ss++ = tolower(*field++);
728 *ss++ = 0;
730 if (!strcmp (ff, "content-length")) {
731 const char *e;
732 while (*value && isspace (*value))
733 value++;
734 for (e = value; *e && *e != '\r' && *e != '\n'; e++)
736 ss = (char *) malloc (e - value + 1);
737 strncpy (ss, value, e - value);
738 ss[e - value] = 0;
739 content_length = atoi(ss);
740 free (ss);
742 free (ff);
745 return (content_length);
749 check_http (void)
751 char *msg;
752 char *status_line;
753 char *status_code;
754 char *header;
755 char *page;
756 char *auth;
757 int http_status;
758 int i = 0;
759 size_t pagesize = 0;
760 char *full_page;
761 char *buf;
762 char *pos;
763 long microsec;
764 double elapsed_time;
765 int page_len = 0;
766 int result = STATE_UNKNOWN;
768 /* try to connect to the host at the given port number */
769 if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK)
770 die (STATE_CRITICAL, _("HTTP CRITICAL - Unable to open TCP socket\n"));
771 #ifdef HAVE_SSL
772 if (use_ssl == TRUE) {
773 np_net_ssl_init(sd);
774 if (check_cert == TRUE) {
775 result = np_net_ssl_check_cert(days_till_exp);
776 np_net_ssl_cleanup();
777 if(sd) close(sd);
778 return result;
781 #endif /* HAVE_SSL */
783 asprintf (&buf, "%s %s HTTP/1.0\r\n%s\r\n", http_method, server_url, user_agent);
785 /* tell HTTP/1.1 servers not to keep the connection alive */
786 asprintf (&buf, "%sConnection: close\r\n", buf);
788 /* optionally send the host header info */
789 if (host_name)
790 asprintf (&buf, "%sHost: %s\r\n", buf, host_name);
792 /* optionally send any other header tag */
793 if (http_opt_headers_count) {
794 for (i = 0; i < http_opt_headers_count ; i++) {
795 for ((pos = strtok(http_opt_headers[i], INPUT_DELIMITER)); pos; (pos = strtok(NULL, INPUT_DELIMITER)))
796 asprintf (&buf, "%s%s\r\n", buf, pos);
798 free(http_opt_headers);
801 /* optionally send the authentication info */
802 if (strlen(user_auth)) {
803 auth = base64 (user_auth, strlen (user_auth));
804 asprintf (&buf, "%sAuthorization: Basic %s\r\n", buf, auth);
807 /* either send http POST data */
808 if (http_post_data) {
809 if (http_content_type) {
810 asprintf (&buf, "%sContent-Type: %s\r\n", buf, http_content_type);
811 } else {
812 asprintf (&buf, "%sContent-Type: application/x-www-form-urlencoded\r\n", buf);
815 asprintf (&buf, "%sContent-Length: %i\r\n\r\n", buf, (int)strlen (http_post_data));
816 asprintf (&buf, "%s%s%s", buf, http_post_data, CRLF);
818 else {
819 /* or just a newline so the server knows we're done with the request */
820 asprintf (&buf, "%s%s", buf, CRLF);
823 if (verbose) printf ("%s\n", buf);
824 my_send (buf, strlen (buf));
826 /* fetch the page */
827 full_page = strdup("");
828 while ((i = my_recv (buffer, MAX_INPUT_BUFFER-1)) > 0) {
829 buffer[i] = '\0';
830 asprintf (&full_page, "%s%s", full_page, buffer);
831 pagesize += i;
833 if (no_body && document_headers_done (full_page)) {
834 i = 0;
835 break;
839 if (i < 0 && errno != ECONNRESET) {
840 #ifdef HAVE_SSL
842 if (use_ssl) {
843 sslerr=SSL_get_error(ssl, i);
844 if ( sslerr == SSL_ERROR_SSL ) {
845 die (STATE_WARNING, _("HTTP WARNING - Client Certificate Required\n"));
846 } else {
847 die (STATE_CRITICAL, _("HTTP CRITICAL - Error on receive\n"));
850 else {
852 #endif
853 die (STATE_CRITICAL, _("HTTP CRITICAL - Error on receive\n"));
854 #ifdef HAVE_SSL
855 /* XXX
858 #endif
861 /* return a CRITICAL status if we couldn't read any data */
862 if (pagesize == (size_t) 0)
863 die (STATE_CRITICAL, _("HTTP CRITICAL - No data received from host\n"));
865 /* close the connection */
866 #ifdef HAVE_SSL
867 np_net_ssl_cleanup();
868 #endif
869 if(sd) close(sd);
871 /* reset the alarm */
872 alarm (0);
874 /* leave full_page untouched so we can free it later */
875 page = full_page;
877 if (verbose)
878 printf ("%s://%s:%d%s is %d characters\n",
879 use_ssl ? "https" : "http", server_address,
880 server_port, server_url, (int)pagesize);
882 /* find status line and null-terminate it */
883 status_line = page;
884 page += (size_t) strcspn (page, "\r\n");
885 pos = page;
886 page += (size_t) strspn (page, "\r\n");
887 status_line[strcspn(status_line, "\r\n")] = 0;
888 strip (status_line);
889 if (verbose)
890 printf ("STATUS: %s\n", status_line);
892 /* find header info and null-terminate it */
893 header = page;
894 while (strcspn (page, "\r\n") > 0) {
895 page += (size_t) strcspn (page, "\r\n");
896 pos = page;
897 if ((strspn (page, "\r") == 1 && strspn (page, "\r\n") >= 2) ||
898 (strspn (page, "\n") == 1 && strspn (page, "\r\n") >= 2))
899 page += (size_t) 2;
900 else
901 page += (size_t) 1;
903 page += (size_t) strspn (page, "\r\n");
904 header[pos - header] = 0;
905 if (verbose)
906 printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header,
907 (no_body ? " [[ skipped ]]" : page));
909 /* make sure the status line matches the response we are looking for */
910 if (!strstr (status_line, server_expect)) {
911 if (server_port == HTTP_PORT)
912 asprintf (&msg,
913 _("Invalid HTTP response received from host\n"));
914 else
915 asprintf (&msg,
916 _("Invalid HTTP response received from host on port %d\n"),
917 server_port);
918 die (STATE_CRITICAL, "HTTP CRITICAL - %s", msg);
921 /* Exit here if server_expect was set by user and not default */
922 if ( server_expect_yn ) {
923 asprintf (&msg,
924 _("HTTP OK: Status line output matched \"%s\"\n"),
925 server_expect);
926 if (verbose)
927 printf ("%s\n",msg);
929 else {
930 /* Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF */
931 /* HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT */
932 /* Status-Code = 3 DIGITS */
934 status_code = strchr (status_line, ' ') + sizeof (char);
935 if (strspn (status_code, "1234567890") != 3)
936 die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status Line (%s)\n"), status_line);
938 http_status = atoi (status_code);
940 /* check the return code */
942 if (http_status >= 600 || http_status < 100)
943 die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%s)\n"), status_line);
945 /* server errors result in a critical state */
946 else if (http_status >= 500)
947 die (STATE_CRITICAL, _("HTTP CRITICAL: %s\n"), status_line);
949 /* client errors result in a warning state */
950 else if (http_status >= 400)
951 die (STATE_WARNING, _("HTTP WARNING: %s\n"), status_line);
953 /* check redirected page if specified */
954 else if (http_status >= 300) {
956 if (onredirect == STATE_DEPENDENT)
957 redir (header, status_line);
958 else if (onredirect == STATE_UNKNOWN)
959 printf (_("HTTP UNKNOWN"));
960 else if (onredirect == STATE_OK)
961 printf (_("HTTP OK"));
962 else if (onredirect == STATE_WARNING)
963 printf (_("HTTP WARNING"));
964 else if (onredirect == STATE_CRITICAL)
965 printf (_("HTTP CRITICAL"));
966 microsec = deltime (tv);
967 elapsed_time = (double)microsec / 1.0e6;
968 die (onredirect,
969 _(" - %s - %.3f second response time %s|%s %s\n"),
970 status_line, elapsed_time,
971 (display_html ? "</A>" : ""),
972 perfd_time (elapsed_time), perfd_size (pagesize));
973 } /* end if (http_status >= 300) */
975 } /* end else (server_expect_yn) */
977 if (maximum_age >= 0) {
978 check_document_dates (header);
981 /* check elapsed time */
982 microsec = deltime (tv);
983 elapsed_time = (double)microsec / 1.0e6;
984 asprintf (&msg,
985 _("HTTP WARNING: %s - %.3f second response time %s|%s %s\n"),
986 status_line, elapsed_time,
987 (display_html ? "</A>" : ""),
988 perfd_time (elapsed_time), perfd_size (pagesize));
989 if (check_critical_time == TRUE && elapsed_time > critical_time)
990 die (STATE_CRITICAL, "%s", msg);
991 if (check_warning_time == TRUE && elapsed_time > warning_time)
992 die (STATE_WARNING, "%s", msg);
994 /* Page and Header content checks go here */
995 /* these checks should be last */
997 if (strlen (string_expect)) {
998 if (strstr (page, string_expect)) {
999 printf (_("HTTP OK %s - %.3f second response time %s|%s %s\n"),
1000 status_line, elapsed_time,
1001 (display_html ? "</A>" : ""),
1002 perfd_time (elapsed_time), perfd_size (pagesize));
1003 exit (STATE_OK);
1005 else {
1006 printf (_("HTTP CRITICAL - string not found%s|%s %s\n"),
1007 (display_html ? "</A>" : ""),
1008 perfd_time (elapsed_time), perfd_size (pagesize));
1009 exit (STATE_CRITICAL);
1013 if (strlen (regexp)) {
1014 errcode = regexec (&preg, page, REGS, pmatch, 0);
1015 if ((errcode == 0 && invert_regex == 0) || (errcode == REG_NOMATCH && invert_regex == 1)) {
1016 printf (_("HTTP OK %s - %.3f second response time %s|%s %s\n"),
1017 status_line, elapsed_time,
1018 (display_html ? "</A>" : ""),
1019 perfd_time (elapsed_time), perfd_size (pagesize));
1020 exit (STATE_OK);
1022 else if ((errcode == REG_NOMATCH && invert_regex == 0) || (errcode == 0 && invert_regex == 1)) {
1023 if (invert_regex == 0)
1024 msg = strdup(_("pattern not found"));
1025 else
1026 msg = strdup(_("pattern found"));
1027 printf (("%s - %s%s|%s %s\n"),
1028 _("HTTP CRITICAL"),
1029 msg,
1030 (display_html ? "</A>" : ""),
1031 perfd_time (elapsed_time), perfd_size (pagesize));
1032 exit (STATE_CRITICAL);
1034 else {
1035 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
1036 printf (_("HTTP CRITICAL - Execute Error: %s\n"), errbuf);
1037 exit (STATE_CRITICAL);
1041 /* make sure the page is of an appropriate size */
1042 /* page_len = get_content_length(header); */
1043 page_len = pagesize;
1044 if ((max_page_len > 0) && (page_len > max_page_len)) {
1045 printf (_("HTTP WARNING: page size %d too large%s|%s\n"),
1046 page_len, (display_html ? "</A>" : ""), perfd_size (page_len) );
1047 exit (STATE_WARNING);
1048 } else if ((min_page_len > 0) && (page_len < min_page_len)) {
1049 printf (_("HTTP WARNING: page size %d too small%s|%s\n"),
1050 page_len, (display_html ? "</A>" : ""), perfd_size (page_len) );
1051 exit (STATE_WARNING);
1053 /* We only get here if all tests have been passed */
1054 asprintf (&msg, _("HTTP OK %s - %d bytes in %.3f seconds %s|%s %s\n"),
1055 status_line, page_len, elapsed_time,
1056 (display_html ? "</A>" : ""),
1057 perfd_time (elapsed_time), perfd_size (page_len));
1058 die (STATE_OK, "%s", msg);
1059 return STATE_UNKNOWN;
1064 /* per RFC 2396 */
1065 #define HDR_LOCATION "%*[Ll]%*[Oo]%*[Cc]%*[Aa]%*[Tt]%*[Ii]%*[Oo]%*[Nn]: "
1066 #define URI_HTTP "%5[HTPShtps]"
1067 #define URI_HOST "%255[-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
1068 #define URI_PORT "%6d" /* MAX_PORT's width is 5 chars, 6 to detect overflow */
1069 #define URI_PATH "%[-_.!~*'();/?:@&=+$,%#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
1070 #define HD1 URI_HTTP "://" URI_HOST ":" URI_PORT "/" URI_PATH
1071 #define HD2 URI_HTTP "://" URI_HOST "/" URI_PATH
1072 #define HD3 URI_HTTP "://" URI_HOST ":" URI_PORT
1073 #define HD4 URI_HTTP "://" URI_HOST
1074 #define HD5 URI_PATH
1076 void
1077 redir (char *pos, char *status_line)
1079 int i = 0;
1080 char *x;
1081 char xx[2];
1082 char type[6];
1083 char *addr;
1084 char *url;
1086 addr = malloc (MAX_IPV4_HOSTLENGTH + 1);
1087 if (addr == NULL)
1088 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate addr\n"));
1090 url = malloc (strcspn (pos, "\r\n"));
1091 if (url == NULL)
1092 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate url\n"));
1094 while (pos) {
1095 sscanf (pos, "%[Ll]%*[Oo]%*[Cc]%*[Aa]%*[Tt]%*[Ii]%*[Oo]%*[Nn]:%n", xx, &i);
1096 if (i == 0) {
1097 pos += (size_t) strcspn (pos, "\r\n");
1098 pos += (size_t) strspn (pos, "\r\n");
1099 if (strlen(pos) == 0)
1100 die (STATE_UNKNOWN,
1101 _("HTTP UNKNOWN - Could not find redirect location - %s%s\n"),
1102 status_line, (display_html ? "</A>" : ""));
1103 continue;
1106 pos += i;
1107 pos += strspn (pos, " \t");
1110 * RFC 2616 (4.2): ``Header fields can be extended over multiple lines by
1111 * preceding each extra line with at least one SP or HT.''
1113 for (; (i = strspn (pos, "\r\n")); pos += i) {
1114 pos += i;
1115 if (!(i = strspn (pos, " \t"))) {
1116 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Empty redirect location%s\n"),
1117 display_html ? "</A>" : "");
1121 url = realloc (url, strcspn (pos, "\r\n") + 1);
1122 if (url == NULL)
1123 die (STATE_UNKNOWN, _("HTTP UNKNOWN - could not allocate url\n"));
1125 /* URI_HTTP, URI_HOST, URI_PORT, URI_PATH */
1126 if (sscanf (pos, HD1, type, addr, &i, url) == 4)
1127 use_ssl = server_type_check (type);
1129 /* URI_HTTP URI_HOST URI_PATH */
1130 else if (sscanf (pos, HD2, type, addr, url) == 3 ) {
1131 use_ssl = server_type_check (type);
1132 i = server_port_check (use_ssl);
1135 /* URI_HTTP URI_HOST URI_PORT */
1136 else if(sscanf (pos, HD3, type, addr, &i) == 3) {
1137 strcpy (url, HTTP_URL);
1138 use_ssl = server_type_check (type);
1141 /* URI_HTTP URI_HOST */
1142 else if(sscanf (pos, HD4, type, addr) == 2) {
1143 strcpy (url, HTTP_URL);
1144 use_ssl = server_type_check (type);
1145 i = server_port_check (use_ssl);
1148 /* URI_PATH */
1149 else if (sscanf (pos, HD5, url) == 1) {
1150 /* relative url */
1151 if ((url[0] != '/')) {
1152 if ((x = strrchr(server_url, '/')))
1153 *x = '\0';
1154 asprintf (&url, "%s/%s", server_url, url);
1156 i = server_port;
1157 strcpy (type, server_type);
1158 strcpy (addr, server_address);
1161 else {
1162 die (STATE_UNKNOWN,
1163 _("HTTP UNKNOWN - Could not parse redirect location - %s%s\n"),
1164 pos, (display_html ? "</A>" : ""));
1167 break;
1169 } /* end while (pos) */
1171 if (++redir_depth > max_depth)
1172 die (STATE_WARNING,
1173 _("HTTP WARNING - maximum redirection depth %d exceeded - %s://%s:%d%s%s\n"),
1174 max_depth, type, addr, i, url, (display_html ? "</A>" : ""));
1176 if (server_port==i &&
1177 !strcmp(server_address, addr) &&
1178 (host_name && !strcmp(host_name, addr)) &&
1179 !strcmp(server_url, url))
1180 die (STATE_WARNING,
1181 _("HTTP WARNING - redirection creates an infinite loop - %s://%s:%d%s%s\n"),
1182 type, addr, i, url, (display_html ? "</A>" : ""));
1184 strcpy (server_type, type);
1186 free (host_name);
1187 host_name = strdup (addr);
1189 free (server_address);
1190 server_address = strdup (addr);
1192 free (server_url);
1193 if ((url[0] == '/'))
1194 server_url = strdup (url);
1195 else if (asprintf(&server_url, "/%s", url) == -1)
1196 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate server_url%s\n"),
1197 display_html ? "</A>" : "");
1198 free(url);
1200 if ((server_port = i) > MAX_PORT)
1201 die (STATE_UNKNOWN,
1202 _("HTTP UNKNOWN - Redirection to port above %d - %s://%s:%d%s%s\n"),
1203 MAX_PORT, server_type, server_address, server_port, server_url,
1204 display_html ? "</A>" : "");
1206 if (verbose)
1207 printf (_("Redirection to %s://%s:%d%s\n"), server_type, server_address,
1208 server_port, server_url);
1210 check_http ();
1216 server_type_check (const char *type)
1218 if (strcmp (type, "https"))
1219 return FALSE;
1220 else
1221 return TRUE;
1225 server_port_check (int ssl_flag)
1227 if (ssl_flag)
1228 return HTTPS_PORT;
1229 else
1230 return HTTP_PORT;
1233 char *perfd_time (double elapsed_time)
1235 return fperfdata ("time", elapsed_time, "s",
1236 check_warning_time, warning_time,
1237 check_critical_time, critical_time,
1238 TRUE, 0, FALSE, 0);
1243 char *perfd_size (int page_len)
1245 return perfdata ("size", page_len, "B",
1246 (min_page_len>0?TRUE:FALSE), min_page_len,
1247 (min_page_len>0?TRUE:FALSE), 0,
1248 TRUE, 0, FALSE, 0);
1251 void
1252 print_help (void)
1254 print_revision (progname, revision);
1256 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
1257 printf (COPYRIGHT, copyright, email);
1259 printf ("%s\n", _("This plugin tests the HTTP service on the specified host. It can test"));
1260 printf ("%s\n", _("normal (http) and secure (https) servers, follow redirects, search for"));
1261 printf ("%s\n", _("strings and regular expressions, check connection times, and report on"));
1262 printf ("%s\n", _("certificate expiration times."));
1264 printf ("\n\n");
1266 print_usage ();
1268 printf (_("NOTE: One or both of -H and -I must be specified"));
1270 printf ("\n");
1272 printf (_(UT_HELP_VRSN));
1274 printf (" %s\n", "-H, --hostname=ADDRESS");
1275 printf (" %s\n", _("Host name argument for servers using host headers (virtual host)"));
1276 printf (" %s\n", _("Append a port to include it in the header (eg: example.com:5000)"));
1277 printf (" %s\n", "-I, --IP-address=ADDRESS");
1278 printf (" %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup)."));
1279 printf (" %s\n", "-p, --port=INTEGER");
1280 printf (" %s", _("Port number (default: "));
1281 printf ("%d)\n", HTTP_PORT);
1283 printf (_(UT_IPv46));
1285 #ifdef HAVE_SSL
1286 printf (" %s\n", "-S, --ssl");
1287 printf (" %s\n", _("Connect via SSL. Port defaults to 443"));
1288 printf (" %s\n", "-C, --certificate=INTEGER");
1289 printf (" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443"));
1290 printf (" %s\n", _("(when this option is used the url is not checked.)\n"));
1291 #endif
1293 printf (" %s\n", "-e, --expect=STRING");
1294 printf (" %s\n", _("String to expect in first (status) line of server response (default: "));
1295 printf ("%s)\n", HTTP_EXPECT);
1296 printf (" %s\n", _("If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)"));
1297 printf (" %s\n", "-s, --string=STRING");
1298 printf (" %s\n", _("String to expect in the content"));
1299 printf (" %s\n", "-u, --url=PATH");
1300 printf (" %s\n", _("URL to GET or POST (default: /)"));
1301 printf (" %s\n", "-P, --post=STRING");
1302 printf (" %s\n", _("URL encoded http POST data"));
1303 printf (" %s\n", "-N, --no-body");
1304 printf (" %s\n", _("Don't wait for document body: stop reading after headers."));
1305 printf (" %s\n", _("(Note that this still does an HTTP GET or POST, not a HEAD.)"));
1306 printf (" %s\n", "-M, --max-age=SECONDS");
1307 printf (" %s\n", _("Warn if document is more than SECONDS old. the number can also be of"));
1308 printf (" %s\n", _("the form \"10m\" for minutes, \"10h\" for hours, or \"10d\" for days."));
1309 printf (" %s\n", "-T, --content-type=STRING");
1310 printf (" %s\n", _("specify Content-Type header media type when POSTing\n"));
1312 printf (" %s\n", "-l, --linespan");
1313 printf (" %s\n", _("Allow regex to span newlines (must precede -r or -R)"));
1314 printf (" %s\n", "-r, --regex, --ereg=STRING");
1315 printf (" %s\n", _("Search page for regex STRING"));
1316 printf (" %s\n", "-R, --eregi=STRING");
1317 printf (" %s\n", _("Search page for case-insensitive regex STRING"));
1318 printf (" %s\n", "--invert-regex");
1319 printf (" %s\n", _("Return CRITICAL if found, OK if not\n"));
1321 printf (" %s\n", "-a, --authorization=AUTH_PAIR");
1322 printf (" %s\n", _("Username:password on sites with basic authentication"));
1323 printf (" %s\n", "-A, --useragent=STRING");
1324 printf (" %s\n", _("String to be sent in http header as \"User Agent\""));
1325 printf (" %s\n", "-k, --header=STRING");
1326 printf (" %s\n", _(" Any other tags to be sent in http header. Use multiple times for additional headers"));
1327 printf (" %s\n", "-L, --link");
1328 printf (" %s\n", _("Wrap output in HTML link (obsoleted by urlize)"));
1329 printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow>");
1330 printf (" %s\n", _("How to handle redirected pages"));
1331 printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>");
1332 printf (" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)"));
1334 printf (_(UT_WARN_CRIT));
1336 printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
1338 printf (_(UT_VERBOSE));
1340 printf (_("Notes:"));
1341 printf (" %s\n", _("This plugin will attempt to open an HTTP connection with the host."));
1342 printf (" %s\n", _("Successful connects return STATE_OK, refusals and timeouts return STATE_CRITICAL"));
1343 printf (" %s\n", _("other errors return STATE_UNKNOWN. Successful connects, but incorrect reponse"));
1344 printf (" %s\n", _("messages from the host result in STATE_WARNING return values. If you are"));
1345 printf (" %s\n", _("checking a virtual server that uses 'host headers' you must supply the FQDN"));
1346 printf (" %s\n", _("(fully qualified domain name) as the [host_name] argument."));
1348 #ifdef HAVE_SSL
1349 printf (" %s\n", _("This plugin can also check whether an SSL enabled web server is able to"));
1350 printf (" %s\n", _("serve content (optionally within a specified time) or whether the X509 "));
1351 printf (" %s\n", _("certificate is still valid for the specified number of days."));
1352 printf (_("Examples:"));
1353 printf (" %s\n\n", "CHECK CONTENT: check_http -w 5 -c 10 --ssl -H www.verisign.com");
1354 printf (" %s\n", _("When the 'www.verisign.com' server returns its content within 5 seconds,"));
1355 printf (" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds"));
1356 printf (" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,"));
1357 printf (" %s\n\n", _("a STATE_CRITICAL will be returned."));
1359 printf (" %s\n\n", "CHECK CERTIFICATE: check_http -H www.verisign.com -C 14");
1360 printf (" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 14 days,"));
1361 printf (" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than"));
1362 printf (" %s\n", _("14 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when"));
1363 printf (" %s\n\n", _("the certificate is expired."));
1364 #endif
1366 printf (_(UT_SUPPORT));
1372 void
1373 print_usage (void)
1375 printf (_("Usage:"));
1376 printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname);
1377 printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L]\n");
1378 printf (" [-a auth] [-f <ok | warn | critcal | follow>] [-e <expect>]\n");
1379 printf (" [-s string] [-l] [-r <regex> | -R <case-insensitive regex>] [-P string]\n");
1380 printf (" [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>] [-A string]\n");
1381 printf (" [-k string] [-S] [-C <age>] [-T <content-type>]\n");