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