1 /*****************************************************************************
3 * Nagios check_http plugin
6 * Copyright (c) 1999-2013 Nagios Plugins Development Team
10 * This file contains the check_http plugin
12 * This plugin tests the HTTP service on the specified host. It can test
13 * normal (http) and secure (https) servers, follow redirects, search for
14 * strings and regular expressions, check connection times, and report on
15 * certificate expiration times.
18 * This program is free software: you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation, either version 3 of the License, or
21 * (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32 *****************************************************************************/
34 /* splint -I. -I../../plugins -I../../lib/ -I/usr/kerberos/include/ ../../plugins/check_http.c */
36 const char *progname
= "check_http";
37 const char *copyright
= "1999-2013";
38 const char *email
= "nagiosplug-devel@lists.sourceforge.net";
50 #define HTTP_EXPECT "HTTP/1."
52 MAX_IPV4_HOSTLENGTH
= 255,
59 int check_cert
= FALSE
;
61 int days_till_exp_warn
, days_till_exp_crit
;
64 # define my_recv(buf, len) ((use_ssl) ? np_net_ssl_read(buf, len) : read(sd, buf, len))
65 # define my_send(buf, len) ((use_ssl) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0))
66 #else /* ifndef HAVE_SSL */
67 # define my_recv(buf, len) read(sd, buf, len)
68 # define my_send(buf, len) send(sd, buf, len, 0)
79 regmatch_t pmatch
[REGS
];
80 char regexp
[MAX_RE_SIZE
];
81 char errbuf
[MAX_INPUT_BUFFER
];
82 int cflags
= REG_NOSUB
| REG_EXTENDED
| REG_NEWLINE
;
87 struct timeval tv_temp
;
92 int specify_port
= FALSE
;
93 int server_port
= HTTP_PORT
;
94 char server_port_text
[6] = "";
95 char server_type
[6] = "http";
100 int server_url_length
;
101 int server_expect_yn
= 0;
102 char server_expect
[MAX_INPUT_BUFFER
] = HTTP_EXPECT
;
103 char string_expect
[MAX_INPUT_BUFFER
] = "";
104 char output_string_search
[30] = "";
105 char *warning_thresholds
= NULL
;
106 char *critical_thresholds
= NULL
;
108 char user_auth
[MAX_INPUT_BUFFER
] = "";
109 char proxy_auth
[MAX_INPUT_BUFFER
] = "";
110 int display_html
= FALSE
;
111 char **http_opt_headers
;
112 int http_opt_headers_count
= 0;
113 int onredirect
= STATE_OK
;
114 int followsticky
= STICKY_NONE
;
118 int show_extended_perfdata
= FALSE
;
120 int min_page_len
= 0;
121 int max_page_len
= 0;
125 char *http_post_data
;
126 char *http_content_type
;
127 char buffer
[MAX_INPUT_BUFFER
];
129 int process_arguments (int, char **);
130 int check_http (void);
131 void redir (char *pos
, char *status_line
);
132 int server_type_check(const char *type
);
133 int server_port_check(int ssl_flag
);
134 char *perfd_time (double microsec
);
135 char *perfd_time_connect (double microsec
);
136 char *perfd_time_ssl (double microsec
);
137 char *perfd_time_firstbyte (double microsec
);
138 char *perfd_time_headers (double microsec
);
139 char *perfd_time_transfer (double microsec
);
140 char *perfd_size (int page_len
);
141 void print_help (void);
142 void print_usage (void);
145 main (int argc
, char **argv
)
147 int result
= STATE_UNKNOWN
;
149 setlocale (LC_ALL
, "");
150 bindtextdomain (PACKAGE
, LOCALEDIR
);
151 textdomain (PACKAGE
);
153 /* Set default URL. Must be malloced for subsequent realloc if --onredirect=follow */
154 server_url
= strdup(HTTP_URL
);
155 server_url_length
= strlen(server_url
);
156 xasprintf (&user_agent
, "User-Agent: check_http/v%s (nagios-plugins %s)",
157 NP_VERSION
, VERSION
);
159 /* Parse extra opts if any */
160 argv
=np_extra_opts (&argc
, argv
, progname
);
162 if (process_arguments (argc
, argv
) == ERROR
)
163 usage4 (_("Could not parse arguments"));
165 if (display_html
== TRUE
)
166 printf ("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">",
167 use_ssl
? "https" : "http", host_name
? host_name
: server_address
,
168 server_port
, server_url
);
170 /* initialize alarm signal handling, set socket timeout, start timer */
171 (void) signal (SIGALRM
, socket_timeout_alarm_handler
);
172 (void) alarm (socket_timeout
);
173 gettimeofday (&tv
, NULL
);
175 result
= check_http ();
181 /* process command-line arguments */
183 process_arguments (int argc
, char **argv
)
190 INVERT_REGEX
= CHAR_MAX
+ 1,
195 static struct option longopts
[] = {
197 {"link", no_argument
, 0, 'L'},
198 {"nohtml", no_argument
, 0, 'n'},
199 {"ssl", optional_argument
, 0, 'S'},
200 {"sni", no_argument
, 0, SNI_OPTION
},
201 {"post", required_argument
, 0, 'P'},
202 {"method", required_argument
, 0, 'j'},
203 {"IP-address", required_argument
, 0, 'I'},
204 {"url", required_argument
, 0, 'u'},
205 {"port", required_argument
, 0, 'p'},
206 {"authorization", required_argument
, 0, 'a'},
207 {"proxy_authorization", required_argument
, 0, 'b'},
208 {"string", required_argument
, 0, 's'},
209 {"expect", required_argument
, 0, 'e'},
210 {"regex", required_argument
, 0, 'r'},
211 {"ereg", required_argument
, 0, 'r'},
212 {"eregi", required_argument
, 0, 'R'},
213 {"linespan", no_argument
, 0, 'l'},
214 {"onredirect", required_argument
, 0, 'f'},
215 {"certificate", required_argument
, 0, 'C'},
216 {"useragent", required_argument
, 0, 'A'},
217 {"header", required_argument
, 0, 'k'},
218 {"no-body", no_argument
, 0, 'N'},
219 {"max-age", required_argument
, 0, 'M'},
220 {"content-type", required_argument
, 0, 'T'},
221 {"pagesize", required_argument
, 0, 'm'},
222 {"invert-regex", no_argument
, NULL
, INVERT_REGEX
},
223 {"use-ipv4", no_argument
, 0, '4'},
224 {"use-ipv6", no_argument
, 0, '6'},
225 {"extended-perfdata", no_argument
, 0, 'E'},
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");
246 c
= getopt_long (argc
, argv
, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:e:p:s:R:r:u:f:C:nlLS::m:M:N:E", longopts
, &option
);
247 if (c
== -1 || c
== EOF
)
251 case '?': /* usage */
258 case 'V': /* version */
259 print_revision (progname
, NP_VERSION
);
262 case 't': /* timeout period */
263 if (!is_intnonneg (optarg
))
264 usage2 (_("Timeout interval must be a positive integer"), optarg
);
266 socket_timeout
= atoi (optarg
);
268 case 'c': /* critical time threshold */
269 critical_thresholds
= optarg
;
271 case 'w': /* warning time threshold */
272 warning_thresholds
= optarg
;
274 case 'A': /* User Agent String */
275 xasprintf (&user_agent
, "User-Agent: %s", optarg
);
277 case 'k': /* Additional headers */
278 if (http_opt_headers_count
== 0)
279 http_opt_headers
= malloc (sizeof (char *) * (++http_opt_headers_count
));
281 http_opt_headers
= realloc (http_opt_headers
, sizeof (char *) * (++http_opt_headers_count
));
282 http_opt_headers
[http_opt_headers_count
- 1] = optarg
;
283 /* xasprintf (&http_opt_headers, "%s", optarg); */
285 case 'L': /* show html link */
288 case 'n': /* do not show html link */
289 display_html
= FALSE
;
291 case 'C': /* Check SSL cert validity */
293 if ((temp
=strchr(optarg
,','))!=NULL
) {
295 if (!is_intnonneg (optarg
))
296 usage2 (_("Invalid certificate expiration period"), optarg
);
297 days_till_exp_warn
= atoi(optarg
);
300 if (!is_intnonneg (temp
))
301 usage2 (_("Invalid certificate expiration period"), temp
);
302 days_till_exp_crit
= atoi (temp
);
305 days_till_exp_crit
=0;
306 if (!is_intnonneg (optarg
))
307 usage2 (_("Invalid certificate expiration period"), optarg
);
308 days_till_exp_warn
= atoi (optarg
);
311 /* Fall through to -S option */
313 case 'S': /* use SSL */
316 if (optarg
== NULL
|| c
!= 'S')
319 ssl_version
= atoi(optarg
);
320 if (ssl_version
< 1 || ssl_version
> 3)
321 usage4 (_("Invalid option - Valid values for SSL Version are 1 (TLSv1), 2 (SSLv2) or 3 (SSLv3)"));
323 if (specify_port
== FALSE
)
324 server_port
= HTTPS_PORT
;
326 usage4 (_("Invalid option - SSL is not available"));
332 case 'f': /* onredirect */
333 if (!strcmp (optarg
, "stickyport"))
334 onredirect
= STATE_DEPENDENT
, followsticky
= STICKY_HOST
|STICKY_PORT
;
335 else if (!strcmp (optarg
, "sticky"))
336 onredirect
= STATE_DEPENDENT
, followsticky
= STICKY_HOST
;
337 else if (!strcmp (optarg
, "follow"))
338 onredirect
= STATE_DEPENDENT
, followsticky
= STICKY_NONE
;
339 else if (!strcmp (optarg
, "unknown"))
340 onredirect
= STATE_UNKNOWN
;
341 else if (!strcmp (optarg
, "ok"))
342 onredirect
= STATE_OK
;
343 else if (!strcmp (optarg
, "warning"))
344 onredirect
= STATE_WARNING
;
345 else if (!strcmp (optarg
, "critical"))
346 onredirect
= STATE_CRITICAL
;
347 else usage2 (_("Invalid onredirect option"), optarg
);
349 printf(_("option f:%d \n"), onredirect
);
351 /* Note: H, I, and u must be malloc'd or will fail on redirects */
352 case 'H': /* Host Name (virtual host) */
353 host_name
= strdup (optarg
);
354 if (host_name
[0] == '[') {
355 if ((p
= strstr (host_name
, "]:")) != NULL
) /* [IPv6]:port */
356 server_port
= atoi (p
+ 2);
357 } else if ((p
= strchr (host_name
, ':')) != NULL
358 && strchr (++p
, ':') == NULL
) /* IPv4:port or host:port */
359 server_port
= atoi (p
);
361 case 'I': /* Server IP-address */
362 server_address
= strdup (optarg
);
364 case 'u': /* URL path */
365 server_url
= strdup (optarg
);
366 server_url_length
= strlen (server_url
);
368 case 'p': /* Server port */
369 if (!is_intnonneg (optarg
))
370 usage2 (_("Invalid port number"), optarg
);
372 server_port
= atoi (optarg
);
376 case 'a': /* authorization info */
377 strncpy (user_auth
, optarg
, MAX_INPUT_BUFFER
- 1);
378 user_auth
[MAX_INPUT_BUFFER
- 1] = 0;
380 case 'b': /* proxy-authorization info */
381 strncpy (proxy_auth
, optarg
, MAX_INPUT_BUFFER
- 1);
382 proxy_auth
[MAX_INPUT_BUFFER
- 1] = 0;
384 case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */
385 if (! http_post_data
)
386 http_post_data
= strdup (optarg
);
388 http_method
= strdup("POST");
390 case 'j': /* Set HTTP method */
393 http_method
= strdup (optarg
);
395 case 's': /* string or substring */
396 strncpy (string_expect
, optarg
, MAX_INPUT_BUFFER
- 1);
397 string_expect
[MAX_INPUT_BUFFER
- 1] = 0;
399 case 'e': /* string or substring */
400 strncpy (server_expect
, optarg
, MAX_INPUT_BUFFER
- 1);
401 server_expect
[MAX_INPUT_BUFFER
- 1] = 0;
402 server_expect_yn
= 1;
404 case 'T': /* Content-type */
405 xasprintf (&http_content_type
, "%s", optarg
);
407 case 'l': /* linespan */
408 cflags
&= ~REG_NEWLINE
;
410 case 'R': /* regex */
412 case 'r': /* regex */
413 strncpy (regexp
, optarg
, MAX_RE_SIZE
- 1);
414 regexp
[MAX_RE_SIZE
- 1] = 0;
415 errcode
= regcomp (&preg
, regexp
, cflags
);
417 (void) regerror (errcode
, &preg
, errbuf
, MAX_INPUT_BUFFER
);
418 printf (_("Could Not Compile Regular Expression: %s"), errbuf
);
426 address_family
= AF_INET
;
430 address_family
= AF_INET6
;
432 usage4 (_("IPv6 support not available"));
435 case 'v': /* verbose */
438 case 'm': /* min_page_length */
441 if (strchr(optarg
, ':') != (char *)NULL
) {
442 /* range, so get two values, min:max */
443 tmp
= strtok(optarg
, ":");
445 printf("Bad format: try \"-m min:max\"\n");
446 exit (STATE_WARNING
);
448 min_page_len
= atoi(tmp
);
450 tmp
= strtok(NULL
, ":");
452 printf("Bad format: try \"-m min:max\"\n");
453 exit (STATE_WARNING
);
455 max_page_len
= atoi(tmp
);
457 min_page_len
= atoi (optarg
);
460 case 'N': /* no-body */
463 case 'M': /* max-age */
465 int L
= strlen(optarg
);
466 if (L
&& optarg
[L
-1] == 'm')
467 maximum_age
= atoi (optarg
) * 60;
468 else if (L
&& optarg
[L
-1] == 'h')
469 maximum_age
= atoi (optarg
) * 60 * 60;
470 else if (L
&& optarg
[L
-1] == 'd')
471 maximum_age
= atoi (optarg
) * 60 * 60 * 24;
472 else if (L
&& (optarg
[L
-1] == 's' ||
473 isdigit (optarg
[L
-1])))
474 maximum_age
= atoi (optarg
);
476 fprintf (stderr
, "unparsable max-age: %s\n", optarg
);
477 exit (STATE_WARNING
);
481 case 'E': /* show extended perfdata */
482 show_extended_perfdata
= TRUE
;
489 if (server_address
== NULL
&& c
< argc
)
490 server_address
= strdup (argv
[c
++]);
492 if (host_name
== NULL
&& c
< argc
)
493 host_name
= strdup (argv
[c
++]);
495 if (server_address
== NULL
) {
496 if (host_name
== NULL
)
497 usage4 (_("You must specify a server address or host name"));
499 server_address
= strdup (host_name
);
502 set_thresholds(&thlds
, warning_thresholds
, critical_thresholds
);
504 if (critical_thresholds
&& thlds
->critical
->end
>(double)socket_timeout
)
505 socket_timeout
= (int)thlds
->critical
->end
+ 1;
507 if (http_method
== NULL
)
508 http_method
= strdup ("GET");
515 /* Returns 1 if we're done processing the document body; 0 to keep going */
517 document_headers_done (char *full_page
)
521 for (body
= full_page
; *body
; body
++) {
522 if (!strncmp (body
, "\n\n", 2) || !strncmp (body
, "\n\r\n", 3))
527 return 0; /* haven't read end of headers yet */
529 full_page
[body
- full_page
] = 0;
534 parse_time_string (const char *string
)
538 memset (&tm
, 0, sizeof(tm
));
540 /* Like this: Tue, 25 Dec 2001 02:59:03 GMT */
542 if (isupper (string
[0]) && /* Tue */
543 islower (string
[1]) &&
544 islower (string
[2]) &&
547 (isdigit(string
[5]) || string
[5] == ' ') && /* 25 */
548 isdigit (string
[6]) &&
550 isupper (string
[8]) && /* Dec */
551 islower (string
[9]) &&
552 islower (string
[10]) &&
554 isdigit (string
[12]) && /* 2001 */
555 isdigit (string
[13]) &&
556 isdigit (string
[14]) &&
557 isdigit (string
[15]) &&
559 isdigit (string
[17]) && /* 02: */
560 isdigit (string
[18]) &&
562 isdigit (string
[20]) && /* 59: */
563 isdigit (string
[21]) &&
565 isdigit (string
[23]) && /* 03 */
566 isdigit (string
[24]) &&
568 'G' == string
[26] && /* GMT */
569 'M' == string
[27] && /* GMT */
572 tm
.tm_sec
= 10 * (string
[23]-'0') + (string
[24]-'0');
573 tm
.tm_min
= 10 * (string
[20]-'0') + (string
[21]-'0');
574 tm
.tm_hour
= 10 * (string
[17]-'0') + (string
[18]-'0');
575 tm
.tm_mday
= 10 * (string
[5] == ' ' ? 0 : string
[5]-'0') + (string
[6]-'0');
576 tm
.tm_mon
= (!strncmp (string
+8, "Jan", 3) ? 0 :
577 !strncmp (string
+8, "Feb", 3) ? 1 :
578 !strncmp (string
+8, "Mar", 3) ? 2 :
579 !strncmp (string
+8, "Apr", 3) ? 3 :
580 !strncmp (string
+8, "May", 3) ? 4 :
581 !strncmp (string
+8, "Jun", 3) ? 5 :
582 !strncmp (string
+8, "Jul", 3) ? 6 :
583 !strncmp (string
+8, "Aug", 3) ? 7 :
584 !strncmp (string
+8, "Sep", 3) ? 8 :
585 !strncmp (string
+8, "Oct", 3) ? 9 :
586 !strncmp (string
+8, "Nov", 3) ? 10 :
587 !strncmp (string
+8, "Dec", 3) ? 11 :
589 tm
.tm_year
= ((1000 * (string
[12]-'0') +
590 100 * (string
[13]-'0') +
591 10 * (string
[14]-'0') +
595 tm
.tm_isdst
= 0; /* GMT is never in DST, right? */
597 if (tm
.tm_mon
< 0 || tm
.tm_mday
< 1 || tm
.tm_mday
> 31)
601 This is actually wrong: we need to subtract the local timezone
602 offset from GMT from this value. But, that's ok in this usage,
603 because we only comparing these two GMT dates against each other,
604 so it doesn't matter what time zone we parse them in.
608 if (t
== (time_t) -1) t
= 0;
611 const char *s
= string
;
612 while (*s
&& *s
!= '\r' && *s
!= '\n')
613 fputc (*s
++, stdout
);
614 printf (" ==> %lu\n", (unsigned long) t
);
624 /* Checks if the server 'reply' is one of the expected 'statuscodes' */
626 expected_statuscode (const char *reply
, const char *statuscodes
)
628 char *expected
, *code
;
631 if ((expected
= strdup (statuscodes
)) == NULL
)
632 die (STATE_UNKNOWN
, _("HTTP UNKNOWN - Memory allocation error\n"));
634 for (code
= strtok (expected
, ","); code
!= NULL
; code
= strtok (NULL
, ","))
635 if (strstr (reply
, code
) != NULL
) {
645 check_document_dates (const char *headers
, char **msg
)
648 char *server_date
= 0;
649 char *document_date
= 0;
650 int date_result
= STATE_OK
;
654 const char *field
= s
;
655 const char *value
= 0;
657 /* Find the end of the header field */
658 while (*s
&& !isspace(*s
) && *s
!= ':')
661 /* Remember the header value, if any. */
665 /* Skip to the end of the header, including continuation lines. */
666 while (*s
&& !(*s
== '\n' && (s
[1] != ' ' && s
[1] != '\t')))
669 /* Avoid stepping over end-of-string marker */
673 /* Process this header. */
674 if (value
&& value
> field
+2) {
675 char *ff
= (char *) malloc (value
-field
);
677 while (field
< value
-1)
678 *ss
++ = tolower(*field
++);
681 if (!strcmp (ff
, "date") || !strcmp (ff
, "last-modified")) {
683 while (*value
&& isspace (*value
))
685 for (e
= value
; *e
&& *e
!= '\r' && *e
!= '\n'; e
++)
687 ss
= (char *) malloc (e
- value
+ 1);
688 strncpy (ss
, value
, e
- value
);
690 if (!strcmp (ff
, "date")) {
691 if (server_date
) free (server_date
);
694 if (document_date
) free (document_date
);
702 /* Done parsing the body. Now check the dates we (hopefully) parsed. */
703 if (!server_date
|| !*server_date
) {
704 xasprintf (msg
, _("%sServer date unknown, "), *msg
);
705 date_result
= max_state_alt(STATE_UNKNOWN
, date_result
);
706 } else if (!document_date
|| !*document_date
) {
707 xasprintf (msg
, _("%sDocument modification date unknown, "), *msg
);
708 date_result
= max_state_alt(STATE_CRITICAL
, date_result
);
710 time_t srv_data
= parse_time_string (server_date
);
711 time_t doc_data
= parse_time_string (document_date
);
714 xasprintf (msg
, _("%sServer date \"%100s\" unparsable, "), *msg
, server_date
);
715 date_result
= max_state_alt(STATE_CRITICAL
, date_result
);
716 } else if (doc_data
<= 0) {
717 xasprintf (msg
, _("%sDocument date \"%100s\" unparsable, "), *msg
, document_date
);
718 date_result
= max_state_alt(STATE_CRITICAL
, date_result
);
719 } else if (doc_data
> srv_data
+ 30) {
720 xasprintf (msg
, _("%sDocument is %d seconds in the future, "), *msg
, (int)doc_data
- (int)srv_data
);
721 date_result
= max_state_alt(STATE_CRITICAL
, date_result
);
722 } else if (doc_data
< srv_data
- maximum_age
) {
723 int n
= (srv_data
- doc_data
);
724 if (n
> (60 * 60 * 24 * 2)) {
725 xasprintf (msg
, _("%sLast modified %.1f days ago, "), *msg
, ((float) n
) / (60 * 60 * 24));
726 date_result
= max_state_alt(STATE_CRITICAL
, date_result
);
728 xasprintf (msg
, _("%sLast modified %d:%02d:%02d ago, "), *msg
, n
/ (60 * 60), (n
/ 60) % 60, n
% 60);
729 date_result
= max_state_alt(STATE_CRITICAL
, date_result
);
733 free (document_date
);
739 get_content_length (const char *headers
)
742 int content_length
= 0;
746 const char *field
= s
;
747 const char *value
= 0;
749 /* Find the end of the header field */
750 while (*s
&& !isspace(*s
) && *s
!= ':')
753 /* Remember the header value, if any. */
757 /* Skip to the end of the header, including continuation lines. */
758 while (*s
&& !(*s
== '\n' && (s
[1] != ' ' && s
[1] != '\t')))
761 /* Avoid stepping over end-of-string marker */
765 /* Process this header. */
766 if (value
&& value
> field
+2) {
767 char *ff
= (char *) malloc (value
-field
);
769 while (field
< value
-1)
770 *ss
++ = tolower(*field
++);
773 if (!strcmp (ff
, "content-length")) {
775 while (*value
&& isspace (*value
))
777 for (e
= value
; *e
&& *e
!= '\r' && *e
!= '\n'; e
++)
779 ss
= (char *) malloc (e
- value
+ 1);
780 strncpy (ss
, value
, e
- value
);
782 content_length
= atoi(ss
);
788 return (content_length
);
792 prepend_slash (char *path
)
799 if ((newpath
= malloc (strlen(path
) + 2)) == NULL
)
800 die (STATE_UNKNOWN
, _("HTTP UNKNOWN - Memory allocation error\n"));
802 strcpy (newpath
+ 1, path
);
825 long microsec_connect
;
826 double elapsed_time_connect
;
828 double elapsed_time_ssl
;
829 long microsec_firstbyte
;
830 double elapsed_time_firstbyte
;
831 long microsec_headers
;
832 double elapsed_time_headers
;
833 long microsec_transfer
;
834 double elapsed_time_transfer
;
836 int result
= STATE_OK
;
838 /* try to connect to the host at the given port number */
839 gettimeofday (&tv_temp
, NULL
);
840 if (my_tcp_connect (server_address
, server_port
, &sd
) != STATE_OK
)
841 die (STATE_CRITICAL
, _("HTTP CRITICAL - Unable to open TCP socket\n"));
842 microsec_connect
= deltime (tv_temp
);
844 elapsed_time_connect
= (double)microsec_connect
/ 1.0e6
;
845 if (use_ssl
== TRUE
) {
846 gettimeofday (&tv_temp
, NULL
);
847 result
= np_net_ssl_init_with_hostname_and_version(sd
, (use_sni
? host_name
: NULL
), ssl_version
);
848 if (result
!= STATE_OK
)
850 microsec_ssl
= deltime (tv_temp
);
851 elapsed_time_ssl
= (double)microsec_ssl
/ 1.0e6
;
852 if (check_cert
== TRUE
) {
853 result
= np_net_ssl_check_cert(days_till_exp_warn
, days_till_exp_crit
);
854 np_net_ssl_cleanup();
859 #endif /* HAVE_SSL */
861 xasprintf (&buf
, "%s %s %s\r\n%s\r\n", http_method
, server_url
, host_name
? "HTTP/1.1" : "HTTP/1.0", user_agent
);
863 /* tell HTTP/1.1 servers not to keep the connection alive */
864 xasprintf (&buf
, "%sConnection: close\r\n", buf
);
866 /* optionally send the host header info */
869 * Specify the port only if we're using a non-default port (see RFC 2616,
870 * 14.23). Some server applications/configurations cause trouble if the
871 * (default) port is explicitly specified in the "Host:" header line.
873 if ((use_ssl
== FALSE
&& server_port
== HTTP_PORT
) ||
874 (use_ssl
== TRUE
&& server_port
== HTTPS_PORT
))
875 xasprintf (&buf
, "%sHost: %s\r\n", buf
, host_name
);
877 xasprintf (&buf
, "%sHost: %s:%d\r\n", buf
, host_name
, server_port
);
880 /* optionally send any other header tag */
881 if (http_opt_headers_count
) {
882 for (i
= 0; i
< http_opt_headers_count
; i
++) {
883 xasprintf (&buf
, "%s%s\r\n", buf
, http_opt_headers
[i
]);
885 /* This cannot be free'd here because a redirection will then try to access this and segfault */
886 /* Covered in a testcase in tests/check_http.t */
887 /* free(http_opt_headers); */
890 /* optionally send the authentication info */
891 if (strlen(user_auth
)) {
892 base64_encode_alloc (user_auth
, strlen (user_auth
), &auth
);
893 xasprintf (&buf
, "%sAuthorization: Basic %s\r\n", buf
, auth
);
896 /* optionally send the proxy authentication info */
897 if (strlen(proxy_auth
)) {
898 base64_encode_alloc (proxy_auth
, strlen (proxy_auth
), &auth
);
899 xasprintf (&buf
, "%sProxy-Authorization: Basic %s\r\n", buf
, auth
);
902 /* either send http POST data (any data, not only POST)*/
903 if (http_post_data
) {
904 if (http_content_type
) {
905 xasprintf (&buf
, "%sContent-Type: %s\r\n", buf
, http_content_type
);
907 xasprintf (&buf
, "%sContent-Type: application/x-www-form-urlencoded\r\n", buf
);
910 xasprintf (&buf
, "%sContent-Length: %i\r\n\r\n", buf
, (int)strlen (http_post_data
));
911 xasprintf (&buf
, "%s%s%s", buf
, http_post_data
, CRLF
);
914 /* or just a newline so the server knows we're done with the request */
915 xasprintf (&buf
, "%s%s", buf
, CRLF
);
918 if (verbose
) printf ("%s\n", buf
);
919 gettimeofday (&tv_temp
, NULL
);
920 my_send (buf
, strlen (buf
));
921 microsec_headers
= deltime (tv_temp
);
922 elapsed_time_headers
= (double)microsec_headers
/ 1.0e6
;
925 full_page
= strdup("");
926 gettimeofday (&tv_temp
, NULL
);
927 while ((i
= my_recv (buffer
, MAX_INPUT_BUFFER
-1)) > 0) {
928 if ((i
>= 1) && (elapsed_time_firstbyte
<= 0.000001)) {
929 microsec_firstbyte
= deltime (tv_temp
);
930 elapsed_time_firstbyte
= (double)microsec_firstbyte
/ 1.0e6
;
933 xasprintf (&full_page_new
, "%s%s", full_page
, buffer
);
935 full_page
= full_page_new
;
938 if (no_body
&& document_headers_done (full_page
)) {
943 microsec_transfer
= deltime (tv_temp
);
944 elapsed_time_transfer
= (double)microsec_transfer
/ 1.0e6
;
946 if (i
< 0 && errno
!= ECONNRESET
) {
950 sslerr=SSL_get_error(ssl, i);
951 if ( sslerr == SSL_ERROR_SSL ) {
952 die (STATE_WARNING, _("HTTP WARNING - Client Certificate Required\n"));
954 die (STATE_CRITICAL, _("HTTP CRITICAL - Error on receive\n"));
960 die (STATE_CRITICAL
, _("HTTP CRITICAL - Error on receive\n"));
968 /* return a CRITICAL status if we couldn't read any data */
969 if (pagesize
== (size_t) 0)
970 die (STATE_CRITICAL
, _("HTTP CRITICAL - No data received from host\n"));
972 /* close the connection */
974 np_net_ssl_cleanup();
978 /* Save check time */
979 microsec
= deltime (tv
);
980 elapsed_time
= (double)microsec
/ 1.0e6
;
982 /* leave full_page untouched so we can free it later */
986 printf ("%s://%s:%d%s is %d characters\n",
987 use_ssl
? "https" : "http", server_address
,
988 server_port
, server_url
, (int)pagesize
);
990 /* find status line and null-terminate it */
992 page
+= (size_t) strcspn (page
, "\r\n");
994 page
+= (size_t) strspn (page
, "\r\n");
995 status_line
[strcspn(status_line
, "\r\n")] = 0;
998 printf ("STATUS: %s\n", status_line
);
1000 /* find header info and null-terminate it */
1002 while (strcspn (page
, "\r\n") > 0) {
1003 page
+= (size_t) strcspn (page
, "\r\n");
1005 if ((strspn (page
, "\r") == 1 && strspn (page
, "\r\n") >= 2) ||
1006 (strspn (page
, "\n") == 1 && strspn (page
, "\r\n") >= 2))
1011 page
+= (size_t) strspn (page
, "\r\n");
1012 header
[pos
- header
] = 0;
1014 printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header
,
1015 (no_body
? " [[ skipped ]]" : page
));
1017 /* make sure the status line matches the response we are looking for */
1018 if (!expected_statuscode (status_line
, server_expect
)) {
1019 if (server_port
== HTTP_PORT
)
1021 _("Invalid HTTP response received from host: %s\n"),
1025 _("Invalid HTTP response received from host on port %d: %s\n"),
1026 server_port
, status_line
);
1027 die (STATE_CRITICAL
, "HTTP CRITICAL - %s", msg
);
1030 /* Bypass normal status line check if server_expect was set by user and not default */
1031 /* NOTE: After this if/else block msg *MUST* be an asprintf-allocated string */
1032 if ( server_expect_yn
) {
1034 _("Status line output matched \"%s\" - "), server_expect
);
1036 printf ("%s\n",msg
);
1039 /* Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF */
1040 /* HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT */
1041 /* Status-Code = 3 DIGITS */
1043 status_code
= strchr (status_line
, ' ') + sizeof (char);
1044 if (strspn (status_code
, "1234567890") != 3)
1045 die (STATE_CRITICAL
, _("HTTP CRITICAL: Invalid Status Line (%s)\n"), status_line
);
1047 http_status
= atoi (status_code
);
1049 /* check the return code */
1051 if (http_status
>= 600 || http_status
< 100) {
1052 die (STATE_CRITICAL
, _("HTTP CRITICAL: Invalid Status (%s)\n"), status_line
);
1054 /* server errors result in a critical state */
1055 else if (http_status
>= 500) {
1056 xasprintf (&msg
, _("%s - "), status_line
);
1057 result
= STATE_CRITICAL
;
1059 /* client errors result in a warning state */
1060 else if (http_status
>= 400) {
1061 xasprintf (&msg
, _("%s - "), status_line
);
1062 result
= max_state_alt(STATE_WARNING
, result
);
1064 /* check redirected page if specified */
1065 else if (http_status
>= 300) {
1067 if (onredirect
== STATE_DEPENDENT
)
1068 redir (header
, status_line
);
1070 result
= max_state_alt(onredirect
, result
);
1071 xasprintf (&msg
, _("%s - "), status_line
);
1072 } /* end if (http_status >= 300) */
1074 /* Print OK status anyway */
1075 xasprintf (&msg
, _("%s - "), status_line
);
1078 } /* end else (server_expect_yn) */
1080 /* reset the alarm - must be called *after* redir or we'll never die on redirects! */
1083 if (maximum_age
>= 0) {
1084 result
= max_state_alt(check_document_dates(header
, &msg
), result
);
1087 /* Page and Header content checks go here */
1089 if (strlen (string_expect
)) {
1090 if (!strstr (page
, string_expect
)) {
1091 strncpy(&output_string_search
[0],string_expect
,sizeof(output_string_search
));
1092 if(output_string_search
[sizeof(output_string_search
)-1]!='\0') {
1093 bcopy("...",&output_string_search
[sizeof(output_string_search
)-4],4);
1095 xasprintf (&msg
, _("%sstring '%s' not found on '%s://%s:%d%s', "), msg
, output_string_search
, use_ssl
? "https" : "http", host_name
? host_name
: server_address
, server_port
, server_url
);
1096 result
= STATE_CRITICAL
;
1100 if (strlen (regexp
)) {
1101 errcode
= regexec (&preg
, page
, REGS
, pmatch
, 0);
1102 if ((errcode
== 0 && invert_regex
== 0) || (errcode
== REG_NOMATCH
&& invert_regex
== 1)) {
1103 /* OK - No-op to avoid changing the logic around it */
1104 result
= max_state_alt(STATE_OK
, result
);
1106 else if ((errcode
== REG_NOMATCH
&& invert_regex
== 0) || (errcode
== 0 && invert_regex
== 1)) {
1107 if (invert_regex
== 0)
1108 xasprintf (&msg
, _("%spattern not found, "), msg
);
1110 xasprintf (&msg
, _("%spattern found, "), msg
);
1111 result
= STATE_CRITICAL
;
1114 /* FIXME: Shouldn't that be UNKNOWN? */
1115 regerror (errcode
, &preg
, errbuf
, MAX_INPUT_BUFFER
);
1116 xasprintf (&msg
, _("%sExecute Error: %s, "), msg
, errbuf
);
1117 result
= STATE_CRITICAL
;
1121 /* make sure the page is of an appropriate size */
1122 /* page_len = get_content_length(header); */
1123 /* FIXME: Will this work with -N ? IMHO we should use
1124 * get_content_length(header) and always check if it's different than the
1127 /* FIXME: IIRC pagesize returns headers - shouldn't we make
1128 * it == get_content_length(header) ??
1130 page_len
= pagesize
;
1131 if ((max_page_len
> 0) && (page_len
> max_page_len
)) {
1132 xasprintf (&msg
, _("%spage size %d too large, "), msg
, page_len
);
1133 result
= max_state_alt(STATE_WARNING
, result
);
1134 } else if ((min_page_len
> 0) && (page_len
< min_page_len
)) {
1135 xasprintf (&msg
, _("%spage size %d too small, "), msg
, page_len
);
1136 result
= max_state_alt(STATE_WARNING
, result
);
1139 /* Cut-off trailing characters */
1140 if(msg
[strlen(msg
)-2] == ',')
1141 msg
[strlen(msg
)-2] = '\0';
1143 msg
[strlen(msg
)-3] = '\0';
1145 /* check elapsed time */
1146 if (show_extended_perfdata
)
1148 _("%s - %d bytes in %.3f second response time %s|%s %s %s %s %s %s %s"),
1149 msg
, page_len
, elapsed_time
,
1150 (display_html
? "</A>" : ""),
1151 perfd_time (elapsed_time
),
1152 perfd_size (page_len
),
1153 perfd_time_connect (elapsed_time_connect
),
1154 use_ssl
== TRUE
? perfd_time_ssl (elapsed_time_ssl
) : "",
1155 perfd_time_headers (elapsed_time_headers
),
1156 perfd_time_firstbyte (elapsed_time_firstbyte
),
1157 perfd_time_transfer (elapsed_time_transfer
));
1160 _("%s - %d bytes in %.3f second response time %s|%s %s"),
1161 msg
, page_len
, elapsed_time
,
1162 (display_html
? "</A>" : ""),
1163 perfd_time (elapsed_time
),
1164 perfd_size (page_len
));
1166 result
= max_state_alt(get_status(elapsed_time
, thlds
), result
);
1168 die (result
, "HTTP %s: %s\n", state_text(result
), msg
);
1170 return STATE_UNKNOWN
;
1176 #define URI_HTTP "%5[HTPShtps]"
1177 #define URI_HOST "%255[-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
1178 #define URI_PORT "%6d" /* MAX_PORT's width is 5 chars, 6 to detect overflow */
1179 #define URI_PATH "%[-_.!~*'();/?:@&=+$,%#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
1180 #define HD1 URI_HTTP "://" URI_HOST ":" URI_PORT "/" URI_PATH
1181 #define HD2 URI_HTTP "://" URI_HOST "/" URI_PATH
1182 #define HD3 URI_HTTP "://" URI_HOST ":" URI_PORT
1183 #define HD4 URI_HTTP "://" URI_HOST
1184 #define HD5 URI_PATH
1187 redir (char *pos
, char *status_line
)
1196 addr
= malloc (MAX_IPV4_HOSTLENGTH
+ 1);
1198 die (STATE_UNKNOWN
, _("HTTP UNKNOWN - Could not allocate addr\n"));
1200 url
= malloc (strcspn (pos
, "\r\n"));
1202 die (STATE_UNKNOWN
, _("HTTP UNKNOWN - Could not allocate URL\n"));
1205 sscanf (pos
, "%1[Ll]%*1[Oo]%*1[Cc]%*1[Aa]%*1[Tt]%*1[Ii]%*1[Oo]%*1[Nn]:%n", xx
, &i
);
1207 pos
+= (size_t) strcspn (pos
, "\r\n");
1208 pos
+= (size_t) strspn (pos
, "\r\n");
1209 if (strlen(pos
) == 0)
1211 _("HTTP UNKNOWN - Could not find redirect location - %s%s\n"),
1212 status_line
, (display_html
? "</A>" : ""));
1217 pos
+= strspn (pos
, " \t");
1220 * RFC 2616 (4.2): ``Header fields can be extended over multiple lines by
1221 * preceding each extra line with at least one SP or HT.''
1223 for (; (i
= strspn (pos
, "\r\n")); pos
+= i
) {
1225 if (!(i
= strspn (pos
, " \t"))) {
1226 die (STATE_UNKNOWN
, _("HTTP UNKNOWN - Empty redirect location%s\n"),
1227 display_html
? "</A>" : "");
1231 url
= realloc (url
, strcspn (pos
, "\r\n") + 1);
1233 die (STATE_UNKNOWN
, _("HTTP UNKNOWN - Could not allocate URL\n"));
1235 /* URI_HTTP, URI_HOST, URI_PORT, URI_PATH */
1236 if (sscanf (pos
, HD1
, type
, addr
, &i
, url
) == 4) {
1237 url
= prepend_slash (url
);
1238 use_ssl
= server_type_check (type
);
1241 /* URI_HTTP URI_HOST URI_PATH */
1242 else if (sscanf (pos
, HD2
, type
, addr
, url
) == 3 ) {
1243 url
= prepend_slash (url
);
1244 use_ssl
= server_type_check (type
);
1245 i
= server_port_check (use_ssl
);
1248 /* URI_HTTP URI_HOST URI_PORT */
1249 else if (sscanf (pos
, HD3
, type
, addr
, &i
) == 3) {
1250 strcpy (url
, HTTP_URL
);
1251 use_ssl
= server_type_check (type
);
1254 /* URI_HTTP URI_HOST */
1255 else if (sscanf (pos
, HD4
, type
, addr
) == 2) {
1256 strcpy (url
, HTTP_URL
);
1257 use_ssl
= server_type_check (type
);
1258 i
= server_port_check (use_ssl
);
1262 else if (sscanf (pos
, HD5
, url
) == 1) {
1264 if ((url
[0] != '/')) {
1265 if ((x
= strrchr(server_url
, '/')))
1267 xasprintf (&url
, "%s/%s", server_url
, url
);
1270 strcpy (type
, server_type
);
1271 strcpy (addr
, host_name
? host_name
: server_address
);
1276 _("HTTP UNKNOWN - Could not parse redirect location - %s%s\n"),
1277 pos
, (display_html
? "</A>" : ""));
1282 } /* end while (pos) */
1284 if (++redir_depth
> max_depth
)
1286 _("HTTP WARNING - maximum redirection depth %d exceeded - %s://%s:%d%s%s\n"),
1287 max_depth
, type
, addr
, i
, url
, (display_html
? "</A>" : ""));
1289 if (server_port
==i
&&
1290 !strcmp(server_address
, addr
) &&
1291 (host_name
&& !strcmp(host_name
, addr
)) &&
1292 !strcmp(server_url
, url
))
1294 _("HTTP WARNING - redirection creates an infinite loop - %s://%s:%d%s%s\n"),
1295 type
, addr
, i
, url
, (display_html
? "</A>" : ""));
1297 strcpy (server_type
, type
);
1300 host_name
= strdup (addr
);
1302 if (!(followsticky
& STICKY_HOST
)) {
1303 free (server_address
);
1304 server_address
= strdup (addr
);
1306 if (!(followsticky
& STICKY_PORT
)) {
1313 if (server_port
> MAX_PORT
)
1315 _("HTTP UNKNOWN - Redirection to port above %d - %s://%s:%d%s%s\n"),
1316 MAX_PORT
, server_type
, server_address
, server_port
, server_url
,
1317 display_html
? "</A>" : "");
1320 printf (_("Redirection to %s://%s:%d%s\n"), server_type
,
1321 host_name
? host_name
: server_address
, server_port
, server_url
);
1328 server_type_check (const char *type
)
1330 if (strcmp (type
, "https"))
1337 server_port_check (int ssl_flag
)
1345 char *perfd_time (double elapsed_time
)
1347 return fperfdata ("time", elapsed_time
, "s",
1348 thlds
->warning
?TRUE
:FALSE
, thlds
->warning
?thlds
->warning
->end
:0,
1349 thlds
->critical
?TRUE
:FALSE
, thlds
->critical
?thlds
->critical
->end
:0,
1353 char *perfd_time_connect (double elapsed_time_connect
)
1355 return fperfdata ("time_connect", elapsed_time_connect
, "s", FALSE
, 0, FALSE
, 0, FALSE
, 0, FALSE
, 0);
1358 char *perfd_time_ssl (double elapsed_time_ssl
)
1360 return fperfdata ("time_ssl", elapsed_time_ssl
, "s", FALSE
, 0, FALSE
, 0, FALSE
, 0, FALSE
, 0);
1363 char *perfd_time_headers (double elapsed_time_headers
)
1365 return fperfdata ("time_headers", elapsed_time_headers
, "s", FALSE
, 0, FALSE
, 0, FALSE
, 0, FALSE
, 0);
1368 char *perfd_time_firstbyte (double elapsed_time_firstbyte
)
1370 return fperfdata ("time_firstbyte", elapsed_time_firstbyte
, "s", FALSE
, 0, FALSE
, 0, FALSE
, 0, FALSE
, 0);
1373 char *perfd_time_transfer (double elapsed_time_transfer
)
1375 return fperfdata ("time_transfer", elapsed_time_transfer
, "s", FALSE
, 0, FALSE
, 0, FALSE
, 0, FALSE
, 0);
1378 char *perfd_size (int page_len
)
1380 return perfdata ("size", page_len
, "B",
1381 (min_page_len
>0?TRUE
:FALSE
), min_page_len
,
1382 (min_page_len
>0?TRUE
:FALSE
), 0,
1389 print_revision (progname
, NP_VERSION
);
1391 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
1392 printf (COPYRIGHT
, copyright
, email
);
1394 printf ("%s\n", _("This plugin tests the HTTP service on the specified host. It can test"));
1395 printf ("%s\n", _("normal (http) and secure (https) servers, follow redirects, search for"));
1396 printf ("%s\n", _("strings and regular expressions, check connection times, and report on"));
1397 printf ("%s\n", _("certificate expiration times."));
1403 printf (_("NOTE: One or both of -H and -I must be specified"));
1407 printf (UT_HELP_VRSN
);
1408 printf (UT_EXTRA_OPTS
);
1410 printf (" %s\n", "-H, --hostname=ADDRESS");
1411 printf (" %s\n", _("Host name argument for servers using host headers (virtual host)"));
1412 printf (" %s\n", _("Append a port to include it in the header (eg: example.com:5000)"));
1413 printf (" %s\n", "-I, --IP-address=ADDRESS");
1414 printf (" %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup)."));
1415 printf (" %s\n", "-p, --port=INTEGER");
1416 printf (" %s", _("Port number (default: "));
1417 printf ("%d)\n", HTTP_PORT
);
1422 printf (" %s\n", "-S, --ssl=VERSION");
1423 printf (" %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents"));
1424 printf (" %s\n", _("auto-negotiation (1 = TLSv1, 2 = SSLv2, 3 = SSLv3)."));
1425 printf (" %s\n", "--sni");
1426 printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)"));
1427 printf (" %s\n", "-C, --certificate=INTEGER[,INTEGER]");
1428 printf (" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443"));
1429 printf (" %s\n", _("(when this option is used the URL is not checked.)\n"));
1432 printf (" %s\n", "-e, --expect=STRING");
1433 printf (" %s\n", _("Comma-delimited list of strings, at least one of them is expected in"));
1434 printf (" %s", _("the first (status) line of the server response (default: "));
1435 printf ("%s)\n", HTTP_EXPECT
);
1436 printf (" %s\n", _("If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)"));
1437 printf (" %s\n", "-s, --string=STRING");
1438 printf (" %s\n", _("String to expect in the content"));
1439 printf (" %s\n", "-u, --url=PATH");
1440 printf (" %s\n", _("URL to GET or POST (default: /)"));
1441 printf (" %s\n", "-P, --post=STRING");
1442 printf (" %s\n", _("URL encoded http POST data"));
1443 printf (" %s\n", "-j, --method=STRING (for example: HEAD, OPTIONS, TRACE, PUT, DELETE)");
1444 printf (" %s\n", _("Set HTTP method."));
1445 printf (" %s\n", "-N, --no-body");
1446 printf (" %s\n", _("Don't wait for document body: stop reading after headers."));
1447 printf (" %s\n", _("(Note that this still does an HTTP GET or POST, not a HEAD.)"));
1448 printf (" %s\n", "-M, --max-age=SECONDS");
1449 printf (" %s\n", _("Warn if document is more than SECONDS old. the number can also be of"));
1450 printf (" %s\n", _("the form \"10m\" for minutes, \"10h\" for hours, or \"10d\" for days."));
1451 printf (" %s\n", "-T, --content-type=STRING");
1452 printf (" %s\n", _("specify Content-Type header media type when POSTing\n"));
1454 printf (" %s\n", "-l, --linespan");
1455 printf (" %s\n", _("Allow regex to span newlines (must precede -r or -R)"));
1456 printf (" %s\n", "-r, --regex, --ereg=STRING");
1457 printf (" %s\n", _("Search page for regex STRING"));
1458 printf (" %s\n", "-R, --eregi=STRING");
1459 printf (" %s\n", _("Search page for case-insensitive regex STRING"));
1460 printf (" %s\n", "--invert-regex");
1461 printf (" %s\n", _("Return CRITICAL if found, OK if not\n"));
1463 printf (" %s\n", "-a, --authorization=AUTH_PAIR");
1464 printf (" %s\n", _("Username:password on sites with basic authentication"));
1465 printf (" %s\n", "-b, --proxy-authorization=AUTH_PAIR");
1466 printf (" %s\n", _("Username:password on proxy-servers with basic authentication"));
1467 printf (" %s\n", "-A, --useragent=STRING");
1468 printf (" %s\n", _("String to be sent in http header as \"User Agent\""));
1469 printf (" %s\n", "-k, --header=STRING");
1470 printf (" %s\n", _("Any other tags to be sent in http header. Use multiple times for additional headers"));
1471 printf (" %s\n", "-L, --link");
1472 printf (" %s\n", _("Wrap output in HTML link (obsoleted by urlize)"));
1473 printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport>");
1474 printf (" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the"));
1475 printf (" %s\n", _("specified IP address. stickyport also ensures port stays the same."));
1476 printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>");
1477 printf (" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)"));
1479 printf (UT_WARN_CRIT
);
1481 printf (UT_TIMEOUT
, DEFAULT_SOCKET_TIMEOUT
);
1483 printf (UT_VERBOSE
);
1486 printf ("%s\n", _("Notes:"));
1487 printf (" %s\n", _("This plugin will attempt to open an HTTP connection with the host."));
1488 printf (" %s\n", _("Successful connects return STATE_OK, refusals and timeouts return STATE_CRITICAL"));
1489 printf (" %s\n", _("other errors return STATE_UNKNOWN. Successful connects, but incorrect reponse"));
1490 printf (" %s\n", _("messages from the host result in STATE_WARNING return values. If you are"));
1491 printf (" %s\n", _("checking a virtual server that uses 'host headers' you must supply the FQDN"));
1492 printf (" %s\n", _("(fully qualified domain name) as the [host_name] argument."));
1496 printf (" %s\n", _("This plugin can also check whether an SSL enabled web server is able to"));
1497 printf (" %s\n", _("serve content (optionally within a specified time) or whether the X509 "));
1498 printf (" %s\n", _("certificate is still valid for the specified number of days."));
1500 printf (" %s\n", _("Please note that this plugin does not check if the presented server"));
1501 printf (" %s\n", _("certificate matches the hostname of the server, or if the certificate"));
1502 printf (" %s\n", _("has a valid chain of trust to one of the locally installed CAs."));
1504 printf ("%s\n", _("Examples:"));
1505 printf (" %s\n\n", "CHECK CONTENT: check_http -w 5 -c 10 --ssl -H www.verisign.com");
1506 printf (" %s\n", _("When the 'www.verisign.com' server returns its content within 5 seconds,"));
1507 printf (" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds"));
1508 printf (" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,"));
1509 printf (" %s\n", _("a STATE_CRITICAL will be returned."));
1511 printf (" %s\n\n", "CHECK CERTIFICATE: check_http -H www.verisign.com -C 14");
1512 printf (" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 14 days,"));
1513 printf (" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than"));
1514 printf (" %s\n", _("14 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when"));
1515 printf (" %s\n", _("the certificate is expired."));
1517 printf (" %s\n\n", "CHECK CERTIFICATE: check_http -H www.verisign.com -C 30,14");
1518 printf (" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 30 days,"));
1519 printf (" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than"));
1520 printf (" %s\n", _("30 days, but more than 14 days, a STATE_WARNING is returned."));
1521 printf (" %s\n", _("A STATE_CRITICAL will be returned when certificate expires in less than 14 days"));
1525 printf (UT_SUPPORT
);
1534 printf ("%s\n", _("Usage:"));
1535 printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname
);
1536 printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-a auth]\n");
1537 printf (" [-b proxy_auth] [-f <ok|warning|critcal|follow|sticky|stickyport>]\n");
1538 printf (" [-e <expect>] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n");
1539 printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n");
1540 printf (" [-A string] [-k string] [-S <version>] [--sni] [-C <warn_age>[,<crit_age>]]\n");
1541 printf (" [-T <content-type>] [-j method]\n");