1 /******************************************************************************
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 ******************************************************************************/
18 /* splint -I. -I../../plugins -I../../lib/ -I/usr/kerberos/include/ ../../plugins/check_http.c */
20 const char *progname = "check_http";
21 const char *revision = "$Revision$";
22 const char *copyright = "1999-2001";
23 const char *email = "nagiosplug-devel@lists.sourceforge.net";
25 #include "common.h"
26 #include "netutils.h"
27 #include "utils.h"
29 #define HTTP_EXPECT "HTTP/1."
30 enum {
31 MAX_IPV4_HOSTLENGTH = 255,
32 HTTP_PORT = 80,
33 HTTPS_PORT = 443
34 };
36 #ifdef HAVE_SSL_H
37 #include <rsa.h>
38 #include <crypto.h>
39 #include <x509.h>
40 #include <pem.h>
41 #include <ssl.h>
42 #include <err.h>
43 #include <rand.h>
44 #else
45 # ifdef HAVE_OPENSSL_SSL_H
46 # include <openssl/rsa.h>
47 # include <openssl/crypto.h>
48 # include <openssl/x509.h>
49 # include <openssl/pem.h>
50 # include <openssl/ssl.h>
51 # include <openssl/err.h>
52 # include <openssl/rand.h>
53 # endif
54 #endif
56 #ifdef HAVE_SSL
57 int check_cert = FALSE;
58 int days_till_exp;
59 char *randbuff;
60 SSL_CTX *ctx;
61 SSL *ssl;
62 X509 *server_cert;
63 int connect_SSL (void);
64 int check_certificate (X509 **);
65 #endif
66 int no_body = FALSE;
67 int maximum_age = -1;
69 #ifdef HAVE_REGEX_H
70 enum {
71 REGS = 2,
72 MAX_RE_SIZE = 256
73 };
74 #include <regex.h>
75 regex_t preg;
76 regmatch_t pmatch[REGS];
77 char regexp[MAX_RE_SIZE];
78 char errbuf[MAX_INPUT_BUFFER];
79 int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE;
80 int errcode;
81 #endif
83 struct timeval tv;
85 #define HTTP_URL "/"
86 #define CRLF "\r\n"
88 char timestamp[17] = "";
89 int specify_port = FALSE;
90 int server_port = HTTP_PORT;
91 char server_port_text[6] = "";
92 char server_type[6] = "http";
93 char *server_address;
94 char *host_name;
95 char *server_url;
96 char *user_agent;
97 int server_url_length;
98 int server_expect_yn = 0;
99 char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT;
100 char string_expect[MAX_INPUT_BUFFER] = "";
101 double warning_time = 0;
102 int check_warning_time = FALSE;
103 double critical_time = 0;
104 int check_critical_time = FALSE;
105 char user_auth[MAX_INPUT_BUFFER] = "";
106 int display_html = FALSE;
107 int onredirect = STATE_OK;
108 int use_ssl = FALSE;
109 int verbose = FALSE;
110 int sd;
111 int min_page_len = 0;
112 int redir_depth = 0;
113 int max_depth = 15;
114 char *http_method;
115 char *http_post_data;
116 char *http_content_type;
117 char buffer[MAX_INPUT_BUFFER];
119 int process_arguments (int, char **);
120 static char *base64 (const char *bin, size_t len);
121 int check_http (void);
122 void redir (char *pos, char *status_line);
123 int server_type_check(const char *type);
124 int server_port_check(int ssl_flag);
125 char *perfd_time (double microsec);
126 char *perfd_size (int page_len);
127 int my_recv (void);
128 int my_close (void);
129 void print_help (void);
130 void print_usage (void);
132 int
133 main (int argc, char **argv)
134 {
135 int result = STATE_UNKNOWN;
137 /* Set default URL. Must be malloced for subsequent realloc if --onredirect=follow */
138 server_url = strdup(HTTP_URL);
139 server_url_length = strlen(server_url);
140 asprintf (&user_agent, "User-Agent: check_http/%s (nagios-plugins %s)",
141 clean_revstring (revision), VERSION);
143 if (process_arguments (argc, argv) == ERROR)
144 usage (_("check_http: could not parse arguments\n"));
146 if (strstr (timestamp, ":")) {
147 if (strstr (server_url, "?"))
148 asprintf (&server_url, "%s&%s", server_url, timestamp);
149 else
150 asprintf (&server_url, "%s?%s", server_url, timestamp);
151 }
153 if (display_html == TRUE)
154 printf ("<A HREF=\"http://%s:%d%s\" target=\"_blank\">",
155 host_name, 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 #ifdef HAVE_SSL
163 if (use_ssl && check_cert == TRUE) {
164 if (connect_SSL () != OK)
165 die (STATE_CRITICAL, _("HTTP CRITICAL - Could not make SSL connection\n"));
166 if ((server_cert = SSL_get_peer_certificate (ssl)) != NULL) {
167 result = check_certificate (&server_cert);
168 X509_free (server_cert);
169 }
170 else {
171 printf (_("ERROR: Cannot retrieve server certificate.\n"));
172 result = STATE_CRITICAL;
173 }
174 SSL_shutdown (ssl);
175 SSL_free (ssl);
176 SSL_CTX_free (ctx);
177 close (sd);
178 }
179 else {
180 result = check_http ();
181 }
182 #else
183 result = check_http ();
184 #endif
185 return result;
186 }
187 \f
190 /* process command-line arguments */
191 int
192 process_arguments (int argc, char **argv)
193 {
194 int c = 1;
196 int option = 0;
197 static struct option longopts[] = {
198 STD_LONG_OPTS,
199 {"file",required_argument,0,'F'},
200 {"link", no_argument, 0, 'L'},
201 {"nohtml", no_argument, 0, 'n'},
202 {"ssl", no_argument, 0, 'S'},
203 {"verbose", no_argument, 0, 'v'},
204 {"post", required_argument, 0, 'P'},
205 {"IP-address", required_argument, 0, 'I'},
206 {"url", required_argument, 0, 'u'},
207 {"string", required_argument, 0, 's'},
208 {"regex", required_argument, 0, 'r'},
209 {"ereg", required_argument, 0, 'r'},
210 {"eregi", required_argument, 0, 'R'},
211 {"linespan", no_argument, 0, 'l'},
212 {"onredirect", required_argument, 0, 'f'},
213 {"certificate", required_argument, 0, 'C'},
214 {"no-body", no_argument, 0, 'N'},
215 {"max-age", required_argument, 0, 'M'},
216 {"content-type", required_argument, 0, 'T'},
217 {"min", required_argument, 0, 'm'},
218 {"use-ipv4", no_argument, 0, '4'},
219 {"use-ipv6", no_argument, 0, '6'},
220 {0, 0, 0, 0}
221 };
223 if (argc < 2)
224 return ERROR;
226 for (c = 1; c < argc; c++) {
227 if (strcmp ("-to", argv[c]) == 0)
228 strcpy (argv[c], "-t");
229 if (strcmp ("-hn", argv[c]) == 0)
230 strcpy (argv[c], "-H");
231 if (strcmp ("-wt", argv[c]) == 0)
232 strcpy (argv[c], "-w");
233 if (strcmp ("-ct", argv[c]) == 0)
234 strcpy (argv[c], "-c");
235 if (strcmp ("-nohtml", argv[c]) == 0)
236 strcpy (argv[c], "-n");
237 }
239 while (1) {
240 c = getopt_long (argc, argv, "Vvh46t:c:w:H:P:T:I:a:e:p:s:R:r:u:f:C:nlLSm:M:N", longopts, &option);
241 if (c == -1 || c == EOF)
242 break;
244 switch (c) {
245 case '?': /* usage */
246 usage3 (_("unknown argument"), optopt);
247 break;
248 case 'h': /* help */
249 print_help ();
250 exit (STATE_OK);
251 break;
252 case 'V': /* version */
253 print_revision (progname, revision);
254 exit (STATE_OK);
255 break;
256 case 't': /* timeout period */
257 if (!is_intnonneg (optarg))
258 usage2 (_("timeout interval must be a non-negative integer"), optarg);
259 else
260 socket_timeout = atoi (optarg);
261 break;
262 case 'c': /* critical time threshold */
263 if (!is_nonnegative (optarg))
264 usage2 (_("invalid critical threshold"), optarg);
265 else {
266 critical_time = strtod (optarg, NULL);
267 check_critical_time = TRUE;
268 }
269 break;
270 case 'w': /* warning time threshold */
271 if (!is_nonnegative (optarg))
272 usage2 (_("invalid warning threshold"), optarg);
273 else {
274 warning_time = strtod (optarg, NULL);
275 check_warning_time = TRUE;
276 }
277 break;
278 case 'L': /* show html link */
279 display_html = TRUE;
280 break;
281 case 'n': /* do not show html link */
282 display_html = FALSE;
283 break;
284 case 'S': /* use SSL */
285 #ifndef HAVE_SSL
286 usage (_("check_http: invalid option - SSL is not available\n"));
287 #endif
288 use_ssl = TRUE;
289 if (specify_port == FALSE)
290 server_port = HTTPS_PORT;
291 break;
292 case 'C': /* Check SSL cert validity */
293 #ifdef HAVE_SSL
294 if (!is_intnonneg (optarg))
295 usage2 (_("invalid certificate expiration period"), optarg);
296 else {
297 days_till_exp = atoi (optarg);
298 check_cert = TRUE;
299 }
300 #else
301 usage (_("check_http: invalid option - SSL is not available\n"));
302 #endif
303 break;
304 case 'f': /* onredirect */
305 if (!strcmp (optarg, "follow"))
306 onredirect = STATE_DEPENDENT;
307 if (!strcmp (optarg, "unknown"))
308 onredirect = STATE_UNKNOWN;
309 if (!strcmp (optarg, "ok"))
310 onredirect = STATE_OK;
311 if (!strcmp (optarg, "warning"))
312 onredirect = STATE_WARNING;
313 if (!strcmp (optarg, "critical"))
314 onredirect = STATE_CRITICAL;
315 if (verbose)
316 printf(_("option f:%d \n"), onredirect);
317 break;
318 /* Note: H, I, and u must be malloc'd or will fail on redirects */
319 case 'H': /* Host Name (virtual host) */
320 host_name = strdup (optarg);
321 break;
322 case 'I': /* Server IP-address */
323 server_address = strdup (optarg);
324 break;
325 case 'u': /* URL path */
326 server_url = strdup (optarg);
327 server_url_length = strlen (server_url);
328 break;
329 case 'p': /* Server port */
330 if (!is_intnonneg (optarg))
331 usage2 (_("invalid port number"), optarg);
332 else {
333 server_port = atoi (optarg);
334 specify_port = TRUE;
335 }
336 break;
337 case 'a': /* authorization info */
338 strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1);
339 user_auth[MAX_INPUT_BUFFER - 1] = 0;
340 break;
341 case 'P': /* HTTP POST data in URL encoded format */
342 if (http_method || http_post_data) break;
343 http_method = strdup("POST");
344 http_post_data = strdup (optarg);
345 break;
346 case 's': /* string or substring */
347 strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1);
348 string_expect[MAX_INPUT_BUFFER - 1] = 0;
349 break;
350 case 'e': /* string or substring */
351 strncpy (server_expect, optarg, MAX_INPUT_BUFFER - 1);
352 server_expect[MAX_INPUT_BUFFER - 1] = 0;
353 server_expect_yn = 1;
354 break;
355 case 'T': /* Content-type */
356 asprintf (&http_content_type, "%s", optarg);
357 break;
358 #ifndef HAVE_REGEX_H
359 case 'l': /* linespan */
360 case 'r': /* linespan */
361 case 'R': /* linespan */
362 usage (_("check_http: call for regex which was not a compiled option\n"));
363 break;
364 #else
365 case 'l': /* linespan */
366 cflags &= ~REG_NEWLINE;
367 break;
368 case 'R': /* regex */
369 cflags |= REG_ICASE;
370 case 'r': /* regex */
371 strncpy (regexp, optarg, MAX_RE_SIZE - 1);
372 regexp[MAX_RE_SIZE - 1] = 0;
373 errcode = regcomp (&preg, regexp, cflags);
374 if (errcode != 0) {
375 (void) regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
376 printf (_("Could Not Compile Regular Expression: %s"), errbuf);
377 return ERROR;
378 }
379 break;
380 #endif
381 case '4':
382 address_family = AF_INET;
383 break;
384 case '6':
385 #ifdef USE_IPV6
386 address_family = AF_INET6;
387 #else
388 usage (_("IPv6 support not available\n"));
389 #endif
390 break;
391 case 'v': /* verbose */
392 verbose = TRUE;
393 break;
394 case 'm': /* min_page_length */
395 min_page_len = atoi (optarg);
396 break;
397 case 'N': /* no-body */
398 no_body = TRUE;
399 break;
400 case 'M': /* max-age */
401 {
402 int L = strlen(optarg);
403 if (L && optarg[L-1] == 'm')
404 maximum_age = atoi (optarg) * 60;
405 else if (L && optarg[L-1] == 'h')
406 maximum_age = atoi (optarg) * 60 * 60;
407 else if (L && optarg[L-1] == 'd')
408 maximum_age = atoi (optarg) * 60 * 60 * 24;
409 else if (L && (optarg[L-1] == 's' ||
410 isdigit (optarg[L-1])))
411 maximum_age = atoi (optarg);
412 else {
413 fprintf (stderr, "unparsable max-age: %s\n", optarg);
414 exit (1);
415 }
416 }
417 break;
418 }
419 }
421 c = optind;
423 if (server_address == NULL && c < argc)
424 server_address = strdup (argv[c++]);
426 if (host_name == NULL && c < argc)
427 host_name = strdup (argv[c++]);
429 if (server_address == NULL) {
430 if (host_name == NULL)
431 usage (_("check_http: you must specify a server address or host name\n"));
432 else
433 server_address = strdup (host_name);
434 }
436 if (check_critical_time && critical_time>(double)socket_timeout)
437 socket_timeout = (int)critical_time + 1;
439 if (http_method == NULL)
440 http_method = strdup ("GET");
442 return TRUE;
443 }
444 \f
447 /* written by lauri alanko */
448 static char *
449 base64 (const char *bin, size_t len)
450 {
452 char *buf = (char *) malloc ((len + 2) / 3 * 4 + 1);
453 size_t i = 0, j = 0;
455 char BASE64_END = '=';
456 char base64_table[64];
457 strncpy (base64_table, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", 64);
459 while (j < len - 2) {
460 buf[i++] = base64_table[bin[j] >> 2];
461 buf[i++] = base64_table[((bin[j] & 3) << 4) | (bin[j + 1] >> 4)];
462 buf[i++] = base64_table[((bin[j + 1] & 15) << 2) | (bin[j + 2] >> 6)];
463 buf[i++] = base64_table[bin[j + 2] & 63];
464 j += 3;
465 }
467 switch (len - j) {
468 case 1:
469 buf[i++] = base64_table[bin[j] >> 2];
470 buf[i++] = base64_table[(bin[j] & 3) << 4];
471 buf[i++] = BASE64_END;
472 buf[i++] = BASE64_END;
473 break;
474 case 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];
478 buf[i++] = BASE64_END;
479 break;
480 case 0:
481 break;
482 }
484 buf[i] = '\0';
485 return buf;
486 }
487 \f
492 /* Returns 1 if we're done processing the document body; 0 to keep going */
493 static int
494 document_headers_done (char *full_page)
495 {
496 const char *body, *s;
497 const char *end;
499 for (body = full_page; *body; body++) {
500 if (!strncmp (body, "\n\n", 2) || !strncmp (body, "\n\r\n", 3))
501 break;
502 }
504 if (!*body)
505 return 0; /* haven't read end of headers yet */
507 full_page[body - full_page] = 0;
508 return 1;
509 }
511 static time_t
512 parse_time_string (const char *string)
513 {
514 struct tm tm;
515 time_t t;
516 memset (&tm, 0, sizeof(tm));
518 /* Like this: Tue, 25 Dec 2001 02:59:03 GMT */
520 if (isupper (string[0]) && /* Tue */
521 islower (string[1]) &&
522 islower (string[2]) &&
523 ',' == string[3] &&
524 ' ' == string[4] &&
525 (isdigit(string[5]) || string[5] == ' ') && /* 25 */
526 isdigit (string[6]) &&
527 ' ' == string[7] &&
528 isupper (string[8]) && /* Dec */
529 islower (string[9]) &&
530 islower (string[10]) &&
531 ' ' == string[11] &&
532 isdigit (string[12]) && /* 2001 */
533 isdigit (string[13]) &&
534 isdigit (string[14]) &&
535 isdigit (string[15]) &&
536 ' ' == string[16] &&
537 isdigit (string[17]) && /* 02: */
538 isdigit (string[18]) &&
539 ':' == string[19] &&
540 isdigit (string[20]) && /* 59: */
541 isdigit (string[21]) &&
542 ':' == string[22] &&
543 isdigit (string[23]) && /* 03 */
544 isdigit (string[24]) &&
545 ' ' == string[25] &&
546 'G' == string[26] && /* GMT */
547 'M' == string[27] && /* GMT */
548 'T' == string[28]) {
550 tm.tm_sec = 10 * (string[23]-'0') + (string[24]-'0');
551 tm.tm_min = 10 * (string[20]-'0') + (string[21]-'0');
552 tm.tm_hour = 10 * (string[17]-'0') + (string[18]-'0');
553 tm.tm_mday = 10 * (string[5] == ' ' ? 0 : string[5]-'0') + (string[6]-'0');
554 tm.tm_mon = (!strncmp (string+8, "Jan", 3) ? 0 :
555 !strncmp (string+8, "Feb", 3) ? 1 :
556 !strncmp (string+8, "Mar", 3) ? 2 :
557 !strncmp (string+8, "Apr", 3) ? 3 :
558 !strncmp (string+8, "May", 3) ? 4 :
559 !strncmp (string+8, "Jun", 3) ? 5 :
560 !strncmp (string+8, "Jul", 3) ? 6 :
561 !strncmp (string+8, "Aug", 3) ? 7 :
562 !strncmp (string+8, "Sep", 3) ? 8 :
563 !strncmp (string+8, "Oct", 3) ? 9 :
564 !strncmp (string+8, "Nov", 3) ? 10 :
565 !strncmp (string+8, "Dec", 3) ? 11 :
566 -1);
567 tm.tm_year = ((1000 * (string[12]-'0') +
568 100 * (string[13]-'0') +
569 10 * (string[14]-'0') +
570 (string[15]-'0'))
571 - 1900);
573 tm.tm_isdst = 0; /* GMT is never in DST, right? */
575 if (tm.tm_mon < 0 || tm.tm_mday < 1 || tm.tm_mday > 31)
576 return 0;
578 /*
579 This is actually wrong: we need to subtract the local timezone
580 offset from GMT from this value. But, that's ok in this usage,
581 because we only comparing these two GMT dates against each other,
582 so it doesn't matter what time zone we parse them in.
583 */
585 t = mktime (&tm);
586 if (t == (time_t) -1) t = 0;
588 if (verbose) {
589 const char *s = string;
590 while (*s && *s != '\r' && *s != '\n')
591 fputc (*s++, stdout);
592 printf (" ==> %lu\n", (unsigned long) t);
593 }
595 return t;
597 } else {
598 return 0;
599 }
600 }
603 static void
604 check_document_dates (const char *headers)
605 {
606 const char *s;
607 char *server_date = 0;
608 char *document_date = 0;
610 s = headers;
611 while (*s) {
612 const char *field = s;
613 const char *value = 0;
615 /* Find the end of the header field */
616 while (*s && !isspace(*s) && *s != ':')
617 s++;
619 /* Remember the header value, if any. */
620 if (*s == ':')
621 value = ++s;
623 /* Skip to the end of the header, including continuation lines. */
624 while (*s && !(*s == '\n' && (s[1] != ' ' && s[1] != '\t')))
625 s++;
626 s++;
628 /* Process this header. */
629 if (value && value > field+2) {
630 char *ff = (char *) malloc (value-field);
631 char *ss = ff;
632 while (field < value-1)
633 *ss++ = tolower(*field++);
634 *ss++ = 0;
636 if (!strcmp (ff, "date") || !strcmp (ff, "last-modified")) {
637 const char *e;
638 while (*value && isspace (*value))
639 value++;
640 for (e = value; *e && *e != '\r' && *e != '\n'; e++)
641 ;
642 ss = (char *) malloc (e - value + 1);
643 strncpy (ss, value, e - value);
644 ss[e - value] = 0;
645 if (!strcmp (ff, "date")) {
646 if (server_date) free (server_date);
647 server_date = ss;
648 } else {
649 if (document_date) free (document_date);
650 document_date = ss;
651 }
652 }
653 free (ff);
654 }
655 }
657 /* Done parsing the body. Now check the dates we (hopefully) parsed. */
658 if (!server_date || !*server_date) {
659 die (STATE_UNKNOWN, _("Server date unknown\n"));
660 } else if (!document_date || !*document_date) {
661 die (STATE_CRITICAL, _("Document modification date unknown\n"));
662 } else {
663 time_t sd = parse_time_string (server_date);
664 time_t dd = parse_time_string (document_date);
666 if (sd <= 0) {
667 die (STATE_CRITICAL, _("CRITICAL - Server date \"%100s\" unparsable"), server_date);
668 } else if (dd <= 0) {
669 die (STATE_CRITICAL, _("CRITICAL - Document date \"%100s\" unparsable"), document_date);
670 } else if (dd > sd + 30) {
671 die (STATE_CRITICAL, _("CRITICAL - Document is %d seconds in the future\n"), dd - sd);
672 } else if (dd < sd - maximum_age) {
673 int n = (sd - dd);
674 if (n > (60 * 60 * 24 * 2))
675 die (STATE_CRITICAL,
676 _("CRITICAL - Last modified %.1f days ago\n"),
677 ((float) n) / (60 * 60 * 24));
678 else
679 die (STATE_CRITICAL,
680 _("CRITICAL - Last modified %d:%02d:%02d ago\n"),
681 n / (60 * 60), (n / 60) % 60, n % 60);
682 }
684 free (server_date);
685 free (document_date);
686 }
687 }
691 int
692 check_http (void)
693 {
694 char *msg;
695 char *status_line;
696 char *status_code;
697 char *header;
698 char *page;
699 char *auth;
700 int http_status;
701 int i = 0;
702 size_t pagesize = 0;
703 char *full_page;
704 char *buf;
705 char *pos;
706 long microsec;
707 double elapsed_time;
708 int page_len = 0;
709 #ifdef HAVE_SSL
710 int sslerr;
711 #endif
713 /* try to connect to the host at the given port number */
714 #ifdef HAVE_SSL
715 if (use_ssl == TRUE) {
717 if (connect_SSL () != OK) {
718 die (STATE_CRITICAL, _("Unable to open TCP socket\n"));
719 }
721 if ((server_cert = SSL_get_peer_certificate (ssl)) != NULL) {
722 X509_free (server_cert);
723 }
724 else {
725 printf (_("ERROR: Cannot retrieve server certificate.\n"));
726 return STATE_CRITICAL;
727 }
729 }
730 else {
731 #endif
732 if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK)
733 die (STATE_CRITICAL, _("Unable to open TCP socket\n"));
734 #ifdef HAVE_SSL
735 }
736 #endif
738 asprintf (&buf, "%s %s HTTP/1.0\r\n%s\r\n", http_method, server_url, user_agent);
740 /* optionally send the host header info */
741 if (host_name)
742 asprintf (&buf, "%sHost: %s\r\n", buf, host_name);
744 /* optionally send the authentication info */
745 if (strlen(user_auth)) {
746 auth = base64 (user_auth, strlen (user_auth));
747 asprintf (&buf, "%sAuthorization: Basic %s\r\n", buf, auth);
748 }
750 /* either send http POST data */
751 if (http_post_data) {
752 if (http_content_type) {
753 asprintf (&buf, "%sContent-Type: %s\r\n", buf, http_content_type);
754 } else {
755 asprintf (&buf, "%sContent-Type: application/x-www-form-urlencoded\r\n", buf);
756 }
757 asprintf (&buf, "%sContent-Length: %i\r\n\r\n", buf, strlen (http_post_data));
758 asprintf (&buf, "%s%s%s", buf, http_post_data, CRLF);
759 }
760 else {
761 /* or just a newline so the server knows we're done with the request */
762 asprintf (&buf, "%s%s", buf, CRLF);
763 }
765 if (verbose)
766 printf ("%s\n", buf);
768 #ifdef HAVE_SSL
769 if (use_ssl == TRUE) {
770 if (SSL_write (ssl, buf, (int)strlen(buf)) == -1) {
771 ERR_print_errors_fp (stderr);
772 return STATE_CRITICAL;
773 }
774 }
775 else {
776 #endif
777 send (sd, buf, strlen (buf), 0);
778 #ifdef HAVE_SSL
779 }
780 #endif
782 /* fetch the page */
783 full_page = strdup("");
784 while ((i = my_recv ()) > 0) {
785 buffer[i] = '\0';
786 asprintf (&full_page, "%s%s", full_page, buffer);
787 pagesize += i;
789 if (no_body && document_headers_done (full_page)) {
790 i = 0;
791 break;
792 }
793 }
795 if (i < 0 && errno != ECONNRESET) {
796 #ifdef HAVE_SSL
797 if (use_ssl) {
798 sslerr=SSL_get_error(ssl, i);
799 if ( sslerr == SSL_ERROR_SSL ) {
800 die (STATE_WARNING, _("Client Certificate Required\n"));
801 } else {
802 die (STATE_CRITICAL, _("Error in recv()\n"));
803 }
804 }
805 else {
806 #endif
807 die (STATE_CRITICAL, _("Error in recv()\n"));
808 #ifdef HAVE_SSL
809 }
810 #endif
811 }
813 /* return a CRITICAL status if we couldn't read any data */
814 if (pagesize == (size_t) 0)
815 die (STATE_CRITICAL, _("No data received %s\n"), timestamp);
817 /* close the connection */
818 my_close ();
820 /* reset the alarm */
821 alarm (0);
823 /* leave full_page untouched so we can free it later */
824 page = full_page;
826 if (verbose)
827 printf ("%s://%s:%d%s is %d characters\n", server_type, server_address, server_port, server_url, pagesize);
829 /* find status line and null-terminate it */
830 status_line = page;
831 page += (size_t) strcspn (page, "\r\n");
832 pos = page;
833 page += (size_t) strspn (page, "\r\n");
834 status_line[strcspn(status_line, "\r\n")] = 0;
835 strip (status_line);
836 if (verbose)
837 printf ("STATUS: %s\n", status_line);
839 /* find header info and null-terminate it */
840 header = page;
841 while (strcspn (page, "\r\n") > 0) {
842 page += (size_t) strcspn (page, "\r\n");
843 pos = page;
844 if ((strspn (page, "\r") == 1 && strspn (page, "\r\n") >= 2) ||
845 (strspn (page, "\n") == 1 && strspn (page, "\r\n") >= 2))
846 page += (size_t) 2;
847 else
848 page += (size_t) 1;
849 }
850 page += (size_t) strspn (page, "\r\n");
851 header[pos - header] = 0;
852 if (verbose)
853 printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header,
854 (no_body ? " [[ skipped ]]" : page));
856 /* make sure the status line matches the response we are looking for */
857 if (!strstr (status_line, server_expect)) {
858 if (server_port == HTTP_PORT)
859 asprintf (&msg,
860 _("Invalid HTTP response received from host\n"));
861 else
862 asprintf (&msg,
863 _("Invalid HTTP response received from host on port %d\n"),
864 server_port);
865 die (STATE_CRITICAL, "%s", msg);
866 }
868 /* Exit here if server_expect was set by user and not default */
869 if ( server_expect_yn ) {
870 asprintf (&msg,
871 _("HTTP OK: Status line output matched \"%s\"\n"),
872 server_expect);
873 if (verbose)
874 printf ("%s\n",msg);
875 }
876 else {
877 /* Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF */
878 /* HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT */
879 /* Status-Code = 3 DIGITS */
881 status_code = strchr (status_line, ' ') + sizeof (char);
882 if (strspn (status_code, "1234567890") != 3)
883 die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status Line (%s)\n"), status_line);
885 http_status = atoi (status_code);
887 /* check the return code */
889 if (http_status >= 600 || http_status < 100)
890 die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%s)\n"), status_line);
892 /* server errors result in a critical state */
893 else if (http_status >= 500)
894 die (STATE_CRITICAL, _("HTTP CRITICAL: %s\n"), status_line);
896 /* client errors result in a warning state */
897 else if (http_status >= 400)
898 die (STATE_WARNING, _("HTTP WARNING: %s\n"), status_line);
900 /* check redirected page if specified */
901 else if (http_status >= 300) {
903 if (onredirect == STATE_DEPENDENT)
904 redir (header, status_line);
905 else if (onredirect == STATE_UNKNOWN)
906 printf (_("UNKNOWN"));
907 else if (onredirect == STATE_OK)
908 printf (_("OK"));
909 else if (onredirect == STATE_WARNING)
910 printf (_("WARNING"));
911 else if (onredirect == STATE_CRITICAL)
912 printf (_("CRITICAL"));
913 microsec = deltime (tv);
914 elapsed_time = (double)microsec / 1.0e6;
915 die (onredirect,
916 _(" - %s - %.3f second response time %s%s|%s %s\n"),
917 status_line, elapsed_time, timestamp,
918 (display_html ? "</A>" : ""),
919 perfd_time (elapsed_time), perfd_size (pagesize));
920 } /* end if (http_status >= 300) */
922 } /* end else (server_expect_yn) */
924 if (maximum_age >= 0) {
925 check_document_dates (header);
926 }
928 /* check elapsed time */
929 microsec = deltime (tv);
930 elapsed_time = (double)microsec / 1.0e6;
931 asprintf (&msg,
932 _("HTTP problem: %s - %.3f second response time %s%s|%s %s\n"),
933 status_line, elapsed_time, timestamp,
934 (display_html ? "</A>" : ""),
935 perfd_time (elapsed_time), perfd_size (pagesize));
936 if (check_critical_time == TRUE && elapsed_time > critical_time)
937 die (STATE_CRITICAL, "%s", msg);
938 if (check_warning_time == TRUE && elapsed_time > warning_time)
939 die (STATE_WARNING, "%s", msg);
941 /* Page and Header content checks go here */
942 /* these checks should be last */
944 if (strlen (string_expect)) {
945 if (strstr (page, string_expect)) {
946 printf (_("HTTP OK %s - %.3f second response time %s%s|%s %s\n"),
947 status_line, elapsed_time,
948 timestamp, (display_html ? "</A>" : ""),
949 perfd_time (elapsed_time), perfd_size (pagesize));
950 exit (STATE_OK);
951 }
952 else {
953 printf (_("CRITICAL - string not found%s|%s %s\n"),
954 (display_html ? "</A>" : ""),
955 perfd_time (elapsed_time), perfd_size (pagesize));
956 exit (STATE_CRITICAL);
957 }
958 }
959 #ifdef HAVE_REGEX_H
960 if (strlen (regexp)) {
961 errcode = regexec (&preg, page, REGS, pmatch, 0);
962 if (errcode == 0) {
963 printf (_("HTTP OK %s - %.3f second response time %s%s|%s %s\n"),
964 status_line, elapsed_time,
965 timestamp, (display_html ? "</A>" : ""),
966 perfd_time (elapsed_time), perfd_size (pagesize));
967 exit (STATE_OK);
968 }
969 else {
970 if (errcode == REG_NOMATCH) {
971 printf (_("CRITICAL - pattern not found%s|%s %s\n"),
972 (display_html ? "</A>" : ""),
973 perfd_time (elapsed_time), perfd_size (pagesize));
974 exit (STATE_CRITICAL);
975 }
976 else {
977 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
978 printf (_("CRITICAL - Execute Error: %s\n"), errbuf);
979 exit (STATE_CRITICAL);
980 }
981 }
982 }
983 #endif
985 /* make sure the page is of an appropriate size */
986 page_len = strlen (page);
987 if ((min_page_len > 0) && (page_len < min_page_len)) {
988 printf (_("HTTP WARNING: page size %d too small%s|%s\n"),
989 page_len, (display_html ? "</A>" : ""), perfd_size (page_len) );
990 exit (STATE_WARNING);
991 }
992 /* We only get here if all tests have been passed */
993 asprintf (&msg, _("HTTP OK %s - %d bytes in %.3f seconds %s%s|%s %s\n"),
994 status_line, page_len, elapsed_time,
995 timestamp, (display_html ? "</A>" : ""),
996 perfd_time (elapsed_time), perfd_size (page_len));
997 die (STATE_OK, "%s", msg);
998 return STATE_UNKNOWN;
999 }
1004 /* per RFC 2396 */
1005 #define HDR_LOCATION "%*[Ll]%*[Oo]%*[Cc]%*[Aa]%*[Tt]%*[Ii]%*[Oo]%*[Nn]: "
1006 #define URI_HTTP "%[HTPShtps]://"
1007 #define URI_HOST "%[-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
1008 #define URI_PORT ":%[0123456789]"
1009 #define URI_PATH "%[-_.!~*'();/?:@&=+$,%#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
1010 #define HD1 URI_HTTP URI_HOST URI_PORT URI_PATH
1011 #define HD2 URI_HTTP URI_HOST URI_PATH
1012 #define HD3 URI_HTTP URI_HOST URI_PORT
1013 #define HD4 URI_HTTP URI_HOST
1014 #define HD5 URI_PATH
1016 void
1017 redir (char *pos, char *status_line)
1018 {
1019 int i = 0;
1020 char *x;
1021 char xx[2];
1022 char type[6];
1023 char *addr;
1024 char port[6];
1025 char *url;
1027 addr = malloc (MAX_IPV4_HOSTLENGTH + 1);
1028 if (addr == NULL)
1029 die (STATE_UNKNOWN, _("ERROR: could not allocate addr\n"));
1031 url = malloc (strcspn (pos, "\r\n"));
1032 if (url == NULL)
1033 die (STATE_UNKNOWN, _("ERROR: could not allocate url\n"));
1035 while (pos) {
1037 if (sscanf (pos, "%[Ll]%*[Oo]%*[Cc]%*[Aa]%*[Tt]%*[Ii]%*[Oo]%*[Nn]:%n", xx, &i) < 1) {
1039 pos += (size_t) strcspn (pos, "\r\n");
1040 pos += (size_t) strspn (pos, "\r\n");
1041 if (strlen(pos) == 0)
1042 die (STATE_UNKNOWN,
1043 _("UNKNOWN - Could not find redirect location - %s%s\n"),
1044 status_line, (display_html ? "</A>" : ""));
1045 continue;
1046 }
1048 pos += i;
1049 pos += strspn (pos, " \t\r\n");
1051 url = realloc (url, strcspn (pos, "\r\n"));
1052 if (url == NULL)
1053 die (STATE_UNKNOWN, _("ERROR: could not allocate url\n"));
1055 /* URI_HTTP, URI_HOST, URI_PORT, URI_PATH */
1056 if (sscanf (pos, HD1, type, addr, port, url) == 4) {
1057 use_ssl = server_type_check (type);
1058 i = atoi (port);
1059 }
1061 /* URI_HTTP URI_HOST URI_PATH */
1062 else if (sscanf (pos, HD2, type, addr, url) == 3 ) {
1063 use_ssl = server_type_check (type);
1064 i = server_port_check (use_ssl);
1065 }
1067 /* URI_HTTP URI_HOST URI_PORT */
1068 else if(sscanf (pos, HD3, type, addr, port) == 3) {
1069 strcpy (url, HTTP_URL);
1070 use_ssl = server_type_check (type);
1071 i = atoi (port);
1072 }
1074 /* URI_HTTP URI_HOST */
1075 else if(sscanf (pos, HD4, type, addr) == 2) {
1076 strcpy (url, HTTP_URL);
1077 use_ssl = server_type_check (type);
1078 i = server_port_check (use_ssl);
1079 }
1081 /* URI_PATH */
1082 else if (sscanf (pos, HD5, url) == 1) {
1083 /* relative url */
1084 if ((url[0] != '/')) {
1085 if ((x = strrchr(server_url, '/')))
1086 *x = '\0';
1087 asprintf (&url, "%s/%s", server_url, url);
1088 }
1089 i = server_port;
1090 strcpy (type, server_type);
1091 strcpy (addr, host_name);
1092 }
1094 else {
1095 die (STATE_UNKNOWN,
1096 _("UNKNOWN - Could not parse redirect location - %s%s\n"),
1097 pos, (display_html ? "</A>" : ""));
1098 }
1100 break;
1102 } /* end while (pos) */
1104 if (++redir_depth > max_depth)
1105 die (STATE_WARNING,
1106 _("WARNING - maximum redirection depth %d exceeded - %s://%s:%d%s%s\n"),
1107 max_depth, type, addr, i, url, (display_html ? "</A>" : ""));
1109 if (server_port==i &&
1110 !strcmp(server_address, addr) &&
1111 (host_name && !strcmp(host_name, addr)) &&
1112 !strcmp(server_url, url))
1113 die (STATE_WARNING,
1114 _("WARNING - redirection creates an infinite loop - %s://%s:%d%s%s\n"),
1115 type, addr, i, url, (display_html ? "</A>" : ""));
1117 server_port = i;
1118 strcpy (server_type, type);
1120 free (host_name);
1121 host_name = strdup (addr);
1123 free (server_address);
1124 server_address = strdup (addr);
1126 free (server_url);
1127 server_url = strdup (url);
1129 check_http ();
1130 }
1134 int
1135 server_type_check (const char *type)
1136 {
1137 if (strcmp (type, "https"))
1138 return FALSE;
1139 else
1140 return TRUE;
1141 }
1143 int
1144 server_port_check (int ssl_flag)
1145 {
1146 if (ssl_flag)
1147 return HTTPS_PORT;
1148 else
1149 return HTTP_PORT;
1150 }
1154 #ifdef HAVE_SSL
1155 int connect_SSL (void)
1156 {
1157 SSL_METHOD *meth;
1159 asprintf (&randbuff, "%s", "qwertyuiopasdfghjklqwertyuiopasdfghjkl");
1160 RAND_seed (randbuff, (int)strlen(randbuff));
1161 if (verbose)
1162 printf(_("SSL seeding: %s\n"), (RAND_status()==1 ? _("OK") : _("Failed")) );
1164 /* Initialize SSL context */
1165 SSLeay_add_ssl_algorithms ();
1166 meth = SSLv23_client_method ();
1167 SSL_load_error_strings ();
1168 if ((ctx = SSL_CTX_new (meth)) == NULL) {
1169 printf (_("CRITICAL - Cannot create SSL context.\n"));
1170 return STATE_CRITICAL;
1171 }
1173 /* Initialize alarm signal handling */
1174 signal (SIGALRM, socket_timeout_alarm_handler);
1176 /* Set socket timeout */
1177 alarm (socket_timeout);
1179 /* Save start time */
1180 gettimeofday (&tv, NULL);
1182 /* Make TCP connection */
1183 if (my_tcp_connect (server_address, server_port, &sd) == STATE_OK) {
1184 /* Do the SSL handshake */
1185 if ((ssl = SSL_new (ctx)) != NULL) {
1186 SSL_set_cipher_list(ssl, "ALL");
1187 SSL_set_fd (ssl, sd);
1188 if (SSL_connect (ssl) != -1)
1189 return OK;
1190 ERR_print_errors_fp (stderr);
1191 }
1192 else {
1193 printf (_("CRITICAL - Cannot initiate SSL handshake.\n"));
1194 }
1195 SSL_free (ssl);
1196 }
1198 SSL_CTX_free (ctx);
1199 close (sd);
1201 return STATE_CRITICAL;
1202 }
1203 #endif
1205 #ifdef HAVE_SSL
1206 int
1207 check_certificate (X509 ** certificate)
1208 {
1209 ASN1_STRING *tm;
1210 int offset;
1211 struct tm stamp;
1212 int days_left;
1215 /* Retrieve timestamp of certificate */
1216 tm = X509_get_notAfter (*certificate);
1218 /* Generate tm structure to process timestamp */
1219 if (tm->type == V_ASN1_UTCTIME) {
1220 if (tm->length < 10) {
1221 printf (_("CRITICAL - Wrong time format in certificate.\n"));
1222 return STATE_CRITICAL;
1223 }
1224 else {
1225 stamp.tm_year = (tm->data[0] - '0') * 10 + (tm->data[1] - '0');
1226 if (stamp.tm_year < 50)
1227 stamp.tm_year += 100;
1228 offset = 0;
1229 }
1230 }
1231 else {
1232 if (tm->length < 12) {
1233 printf (_("CRITICAL - Wrong time format in certificate.\n"));
1234 return STATE_CRITICAL;
1235 }
1236 else {
1237 stamp.tm_year =
1238 (tm->data[0] - '0') * 1000 + (tm->data[1] - '0') * 100 +
1239 (tm->data[2] - '0') * 10 + (tm->data[3] - '0');
1240 stamp.tm_year -= 1900;
1241 offset = 2;
1242 }
1243 }
1244 stamp.tm_mon =
1245 (tm->data[2 + offset] - '0') * 10 + (tm->data[3 + offset] - '0') - 1;
1246 stamp.tm_mday =
1247 (tm->data[4 + offset] - '0') * 10 + (tm->data[5 + offset] - '0');
1248 stamp.tm_hour =
1249 (tm->data[6 + offset] - '0') * 10 + (tm->data[7 + offset] - '0');
1250 stamp.tm_min =
1251 (tm->data[8 + offset] - '0') * 10 + (tm->data[9 + offset] - '0');
1252 stamp.tm_sec = 0;
1253 stamp.tm_isdst = -1;
1255 days_left = (mktime (&stamp) - time (NULL)) / 86400;
1256 snprintf
1257 (timestamp, 17, "%02d/%02d/%04d %02d:%02d",
1258 stamp.tm_mon + 1,
1259 stamp.tm_mday, stamp.tm_year + 1900, stamp.tm_hour, stamp.tm_min);
1261 if (days_left > 0 && days_left <= days_till_exp) {
1262 printf (_("WARNING - Certificate expires in %d day(s) (%s).\n"), days_left, timestamp);
1263 return STATE_WARNING;
1264 }
1265 if (days_left < 0) {
1266 printf (_("CRITICAL - Certificate expired on %s.\n"), timestamp);
1267 return STATE_CRITICAL;
1268 }
1270 if (days_left == 0) {
1271 printf (_("WARNING - Certificate expires today (%s).\n"), timestamp);
1272 return STATE_WARNING;
1273 }
1275 printf (_("OK - Certificate will expire on %s.\n"), timestamp);
1277 return STATE_OK;
1278 }
1279 #endif
1280 \f
1283 char *perfd_time (double elapsed_time)
1284 {
1285 return fperfdata ("time", elapsed_time, "s",
1286 check_warning_time, warning_time,
1287 check_critical_time, critical_time,
1288 TRUE, 0, FALSE, 0);
1289 }
1292 char *perfd_size (int page_len)
1293 {
1294 return perfdata ("size", page_len, "B",
1295 (min_page_len>0?TRUE:FALSE), min_page_len,
1296 (min_page_len>0?TRUE:FALSE), 0,
1297 TRUE, 0, FALSE, 0);
1298 }
1301 int
1302 my_recv (void)
1303 {
1304 int i;
1305 #ifdef HAVE_SSL
1306 if (use_ssl) {
1307 i = SSL_read (ssl, buffer, MAX_INPUT_BUFFER - 1);
1308 }
1309 else {
1310 i = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
1311 }
1312 #else
1313 i = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
1314 #endif
1315 return i;
1316 }
1319 int
1320 my_close (void)
1321 {
1322 #ifdef HAVE_SSL
1323 if (use_ssl == TRUE) {
1324 SSL_shutdown (ssl);
1325 SSL_free (ssl);
1326 SSL_CTX_free (ctx);
1327 return 0;
1328 }
1329 else {
1330 #endif
1331 return close (sd);
1332 #ifdef HAVE_SSL
1333 }
1334 #endif
1335 }
1341 \f
1342 void
1343 print_help (void)
1344 {
1345 print_revision (progname, revision);
1347 printf (_("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"));
1348 printf (_(COPYRIGHT), copyright, email);
1350 printf (_("\
1351 This plugin tests the HTTP service on the specified host. It can test\n\
1352 normal (http) and secure (https) servers, follow redirects, search for\n\
1353 strings and regular expressions, check connection times, and report on\n\
1354 certificate expiration times.\n"));
1356 print_usage ();
1358 printf (_("NOTE: One or both of -H and -I must be specified\n"));
1360 printf (_(UT_HELP_VRSN));
1362 printf (_("\
1363 -H, --hostname=ADDRESS\n\
1364 Host name argument for servers using host headers (virtual host)\n\
1365 -I, --IP-address=ADDRESS\n\
1366 IP address or name (use numeric address if possible to bypass DNS lookup).\n\
1367 -p, --port=INTEGER\n\
1368 Port number (default: %d)\n"), HTTP_PORT);
1370 printf (_(UT_IPv46));
1372 #ifdef HAVE_SSL
1373 printf (_("\
1374 -S, --ssl\n\
1375 Connect via SSL\n\
1376 -C, --certificate=INTEGER\n\
1377 Minimum number of days a certificate has to be valid.\n\
1378 (when this option is used the url is not checked.)\n"));
1379 #endif
1381 printf (_("\
1382 -e, --expect=STRING\n\
1383 String to expect in first (status) line of server response (default: %s)\n\
1384 If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)\n\
1385 -s, --string=STRING\n\
1386 String to expect in the content\n\
1387 -u, --url=PATH\n\
1388 URL to GET or POST (default: /)\n\
1389 -P, --post=STRING\n\
1390 URL encoded http POST data\n\
1391 -N, --no-body\n\
1392 Don't wait for document body: stop reading after headers.\n\
1393 (Note that this still does an HTTP GET or POST, not a HEAD.)\n\
1394 -M, --max-age=SECONDS\n\
1395 Warn if document is more than SECONDS old. the number can also be of \n\
1396 the form \"10m\" for minutes, \"10h\" for hours, or \"10d\" for days.\n\
1397 -T, --content-type=STRING\n\
1398 specify Content-Type header media type when POSTing\n"), HTTP_EXPECT);
1400 #ifdef HAVE_REGEX_H
1401 printf (_("\
1402 -l, --linespan\n\
1403 Allow regex to span newlines (must precede -r or -R)\n\
1404 -r, --regex, --ereg=STRING\n\
1405 Search page for regex STRING\n\
1406 -R, --eregi=STRING\n\
1407 Search page for case-insensitive regex STRING\n"));
1408 #endif
1410 printf (_("\
1411 -a, --authorization=AUTH_PAIR\n\
1412 Username:password on sites with basic authentication\n\
1413 -L, --link=URL\n\
1414 Wrap output in HTML link (obsoleted by urlize)\n\
1415 -f, --onredirect=<ok|warning|critical|follow>\n\
1416 How to handle redirected pages\n\
1417 -m, --min=INTEGER\n\
1418 Minimum page size required (bytes)\n"));
1420 printf (_(UT_WARN_CRIT));
1422 printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
1424 printf (_(UT_VERBOSE));
1426 printf (_("\
1427 This plugin will attempt to open an HTTP connection with the host. Successful\n\
1428 connects return STATE_OK, refusals and timeouts return STATE_CRITICAL, other\n\
1429 errors return STATE_UNKNOWN. Successful connects, but incorrect reponse\n\
1430 messages from the host result in STATE_WARNING return values. If you are\n\
1431 checking a virtual server that uses 'host headers' you must supply the FQDN\n\
1432 (fully qualified domain name) as the [host_name] argument.\n"));
1434 #ifdef HAVE_SSL
1435 printf (_("\n\
1436 This plugin can also check whether an SSL enabled web server is able to\n\
1437 serve content (optionally within a specified time) or whether the X509 \n\
1438 certificate is still valid for the specified number of days.\n"));
1439 printf (_("\n\
1440 CHECK CONTENT: check_http -w 5 -c 10 --ssl www.verisign.com\n\n\
1441 When the 'www.verisign.com' server returns its content within 5 seconds, a\n\
1442 STATE_OK will be returned. When the server returns its content but exceeds\n\
1443 the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,\n\
1444 a STATE_CRITICAL will be returned.\n\n"));
1446 printf (_("\
1447 CHECK CERTIFICATE: check_http www.verisign.com -C 14\n\n\
1448 When the certificate of 'www.verisign.com' is valid for more than 14 days, a\n\
1449 STATE_OK is returned. When the certificate is still valid, but for less than\n\
1450 14 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when\n\
1451 the certificate is expired.\n"));
1452 #endif
1454 printf (_(UT_SUPPORT));
1456 }
1461 void
1462 print_usage (void)
1463 {
1464 printf (_("\
1465 Usage: %s (-H <vhost> | -I <IP-address>) [-u <uri>] [-p <port>]\n\
1466 [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L]\n\
1467 [-a auth] [-f <ok | warn | critcal | follow>] [-e <expect>]\n\
1468 [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n\
1469 [-P string] [-m min_pg_size] [-4|-6] [-N] [-M <age>]\n"), progname);
1470 printf (_(UT_HLP_VRS), progname, progname);
1471 }