Code

Adding missing function calls needed for i18n (only for plugins already in POTFILES.in)
[nagiosplug.git] / plugins / check_http.c
1 /******************************************************************************
2 *
3 * Nagios check_http plugin
4 *
5 * License: GPL
6 * Copyright (c) 1999-2006 nagios-plugins team
7 *
8 * Last Modified: $Date$
9 *
10 * Description:
11 *
12 * This file contains the check_http plugin
13 *
14 *  This plugin tests the HTTP service on the specified host. It can test
15 *  normal (http) and secure (https) servers, follow redirects, search for
16 *  strings and regular expressions, check connection times, and report on
17 *  certificate expiration times.
18 *
19 *
20 * License Information:
21 *
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30 * GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
36  $Id$
37  
38 ******************************************************************************/
39 /* splint -I. -I../../plugins -I../../lib/ -I/usr/kerberos/include/ ../../plugins/check_http.c */
41 const char *progname = "check_http";
42 const char *revision = "$Revision$";
43 const char *copyright = "1999-2006";
44 const char *email = "nagiosplug-devel@lists.sourceforge.net";
46 #include <ctype.h>
48 #include "common.h"
49 #include "netutils.h"
50 #include "utils.h"
51 #include "base64.h"
53 #define INPUT_DELIMITER ";"
55 #define HTTP_EXPECT "HTTP/1."
56 enum {
57   MAX_IPV4_HOSTLENGTH = 255,
58   HTTP_PORT = 80,
59   HTTPS_PORT = 443,
60   MAX_PORT = 65535
61 };
63 #ifdef HAVE_SSL
64 int check_cert = FALSE;
65 int days_till_exp;
66 char *randbuff;
67 X509 *server_cert;
68 #  define my_recv(buf, len) ((use_ssl) ? np_net_ssl_read(buf, len) : read(sd, buf, len))
69 #  define my_send(buf, len) ((use_ssl) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0))
70 #else /* ifndef HAVE_SSL */
71 #  define my_recv(buf, len) read(sd, buf, len)
72 #  define my_send(buf, len) send(sd, buf, len, 0)
73 #endif /* HAVE_SSL */
74 int no_body = FALSE;
75 int maximum_age = -1;
77 enum {
78   REGS = 2,
79   MAX_RE_SIZE = 256
80 };
81 #include "regex.h"
82 regex_t preg;
83 regmatch_t pmatch[REGS];
84 char regexp[MAX_RE_SIZE];
85 char errbuf[MAX_INPUT_BUFFER];
86 int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE;
87 int errcode;
88 int invert_regex = 0;
90 struct timeval tv;
92 #define HTTP_URL "/"
93 #define CRLF "\r\n"
95 int specify_port = FALSE;
96 int server_port = HTTP_PORT;
97 char server_port_text[6] = "";
98 char server_type[6] = "http";
99 char *server_address;
100 char *host_name;
101 char *server_url;
102 char *user_agent;
103 int server_url_length;
104 int server_expect_yn = 0;
105 char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT;
106 char string_expect[MAX_INPUT_BUFFER] = "";
107 double warning_time = 0;
108 int check_warning_time = FALSE;
109 double critical_time = 0;
110 int check_critical_time = FALSE;
111 char user_auth[MAX_INPUT_BUFFER] = "";
112 int display_html = FALSE;
113 char **http_opt_headers;
114 int http_opt_headers_count = 0;
115 int onredirect = STATE_OK;
116 int use_ssl = FALSE;
117 int verbose = FALSE;
118 int sd;
119 int min_page_len = 0;
120 int max_page_len = 0;
121 int redir_depth = 0;
122 int max_depth = 15;
123 char *http_method;
124 char *http_post_data;
125 char *http_content_type;
126 char buffer[MAX_INPUT_BUFFER];
128 int process_arguments (int, char **);
129 int check_http (void);
130 void redir (char *pos, char *status_line);
131 int server_type_check(const char *type);
132 int server_port_check(int ssl_flag);
133 char *perfd_time (double microsec);
134 char *perfd_size (int page_len);
135 void print_help (void);
136 void print_usage (void);
138 int
139 main (int argc, char **argv)
141   int result = STATE_UNKNOWN;
143         setlocale (LC_ALL, "");
144         bindtextdomain (PACKAGE, LOCALEDIR);
145         textdomain (PACKAGE);
147   /* Set default URL. Must be malloced for subsequent realloc if --onredirect=follow */
148   server_url = strdup(HTTP_URL);
149   server_url_length = strlen(server_url);
150   asprintf (&user_agent, "User-Agent: check_http/%s (nagios-plugins %s)",
151             clean_revstring (revision), VERSION);
153   if (process_arguments (argc, argv) == ERROR)
154     usage4 (_("Could not parse arguments"));
156   if (display_html == TRUE)
157     printf ("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">", 
158       use_ssl ? "https" : "http", host_name ? host_name : server_address,
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   result = check_http ();
167   return result;
172 /* process command-line arguments */
173 int
174 process_arguments (int argc, char **argv)
176   int c = 1;
178   enum {
179     INVERT_REGEX = CHAR_MAX + 1
180   };
182   int option = 0;
183   static struct option longopts[] = {
184     STD_LONG_OPTS,
185     {"link", no_argument, 0, 'L'},
186     {"nohtml", no_argument, 0, 'n'},
187     {"ssl", no_argument, 0, 'S'},
188     {"post", required_argument, 0, 'P'},
189     {"IP-address", required_argument, 0, 'I'},
190     {"url", required_argument, 0, 'u'},
191     {"port", required_argument, 0, 'p'},
192     {"authorization", required_argument, 0, 'a'},
193     {"string", required_argument, 0, 's'},
194     {"expect", required_argument, 0, 'e'},
195     {"regex", required_argument, 0, 'r'},
196     {"ereg", required_argument, 0, 'r'},
197     {"eregi", required_argument, 0, 'R'},
198     {"linespan", no_argument, 0, 'l'},
199     {"onredirect", required_argument, 0, 'f'},
200     {"certificate", required_argument, 0, 'C'},
201     {"useragent", required_argument, 0, 'A'},
202     {"header", required_argument, 0, 'k'},
203     {"no-body", no_argument, 0, 'N'},
204     {"max-age", required_argument, 0, 'M'},
205     {"content-type", required_argument, 0, 'T'},
206     {"pagesize", required_argument, 0, 'm'},
207     {"invert-regex", no_argument, NULL, INVERT_REGEX},
208     {"use-ipv4", no_argument, 0, '4'},
209     {"use-ipv6", no_argument, 0, '6'},
210     {0, 0, 0, 0}
211   };
213   if (argc < 2)
214     return ERROR;
216   for (c = 1; c < argc; c++) {
217     if (strcmp ("-to", argv[c]) == 0)
218       strcpy (argv[c], "-t");
219     if (strcmp ("-hn", argv[c]) == 0)
220       strcpy (argv[c], "-H");
221     if (strcmp ("-wt", argv[c]) == 0)
222       strcpy (argv[c], "-w");
223     if (strcmp ("-ct", argv[c]) == 0)
224       strcpy (argv[c], "-c");
225     if (strcmp ("-nohtml", argv[c]) == 0)
226       strcpy (argv[c], "-n");
227   }
229   while (1) {
230     c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:T:I:a:e:p:s:R:r:u:f:C:nlLSm:M:N", longopts, &option);
231     if (c == -1 || c == EOF)
232       break;
234     switch (c) {
235     case '?': /* usage */
236       usage5 ();
237       break;
238     case 'h': /* help */
239       print_help ();
240       exit (STATE_OK);
241       break;
242     case 'V': /* version */
243       print_revision (progname, revision);
244       exit (STATE_OK);
245       break;
246     case 't': /* timeout period */
247       if (!is_intnonneg (optarg))
248         usage2 (_("Timeout interval must be a positive integer"), optarg);
249       else
250         socket_timeout = atoi (optarg);
251       break;
252     case 'c': /* critical time threshold */
253       if (!is_nonnegative (optarg))
254         usage2 (_("Critical threshold must be integer"), optarg);
255       else {
256         critical_time = strtod (optarg, NULL);
257         check_critical_time = TRUE;
258       }
259       break;
260     case 'w': /* warning time threshold */
261       if (!is_nonnegative (optarg))
262         usage2 (_("Warning threshold must be integer"), optarg);
263       else {
264         warning_time = strtod (optarg, NULL);
265         check_warning_time = TRUE;
266       }
267       break;
268     case 'A': /* User Agent String */
269       asprintf (&user_agent, "User-Agent: %s", optarg);
270       break;
271     case 'k': /* Additional headers */
272       if (http_opt_headers_count == 0)
273         http_opt_headers = malloc (sizeof (char *) * (++http_opt_headers_count));
274       else
275         http_opt_headers = realloc (http_opt_headers, sizeof (char *) * (++http_opt_headers_count));
276       http_opt_headers[http_opt_headers_count - 1] = optarg;
277       /* asprintf (&http_opt_headers, "%s", optarg); */
278       break;
279     case 'L': /* show html link */
280       display_html = TRUE;
281       break;
282     case 'n': /* do not show html link */
283       display_html = FALSE;
284       break;
285     case 'C': /* Check SSL cert validity */
286 #ifdef HAVE_SSL
287       if (!is_intnonneg (optarg))
288         usage2 (_("Invalid certificate expiration period"), optarg);
289       else {
290         days_till_exp = atoi (optarg);
291         check_cert = TRUE;
292       }
293      /* Fall through to -S option */
294 #endif
295     case 'S': /* use SSL */
296 #ifndef HAVE_SSL
297       usage4 (_("Invalid option - SSL is not available"));
298 #endif
299       use_ssl = TRUE;
300       if (specify_port == FALSE)
301         server_port = HTTPS_PORT;
302       break;
303     case 'f': /* onredirect */
304       if (!strcmp (optarg, "follow"))
305         onredirect = STATE_DEPENDENT;
306       if (!strcmp (optarg, "unknown"))
307         onredirect = STATE_UNKNOWN;
308       if (!strcmp (optarg, "ok"))
309         onredirect = STATE_OK;
310       if (!strcmp (optarg, "warning"))
311         onredirect = STATE_WARNING;
312       if (!strcmp (optarg, "critical"))
313         onredirect = STATE_CRITICAL;
314       if (verbose)
315         printf(_("option f:%d \n"), onredirect);  
316       break;
317     /* Note: H, I, and u must be malloc'd or will fail on redirects */
318     case 'H': /* Host Name (virtual host) */
319       host_name = strdup (optarg);
320       if (strstr (optarg, ":"))
321         sscanf (optarg, "%*[^:]:%d", &server_port);
322       break;
323     case 'I': /* Server IP-address */
324       server_address = strdup (optarg);
325       break;
326     case 'u': /* URL path */
327       server_url = strdup (optarg);
328       server_url_length = strlen (server_url);
329       break;
330     case 'p': /* Server port */
331       if (!is_intnonneg (optarg))
332         usage2 (_("Invalid port number"), optarg);
333       else {
334         server_port = atoi (optarg);
335         specify_port = TRUE;
336       }
337       break;
338     case 'a': /* authorization info */
339       strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1);
340       user_auth[MAX_INPUT_BUFFER - 1] = 0;
341       break;
342     case 'P': /* HTTP POST data in URL encoded format */
343       if (http_method || http_post_data) break;
344       http_method = strdup("POST");
345       http_post_data = strdup (optarg);
346       break;
347     case 's': /* string or substring */
348       strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1);
349       string_expect[MAX_INPUT_BUFFER - 1] = 0;
350       break;
351     case 'e': /* string or substring */
352       strncpy (server_expect, optarg, MAX_INPUT_BUFFER - 1);
353       server_expect[MAX_INPUT_BUFFER - 1] = 0;
354       server_expect_yn = 1;
355       break;
356     case 'T': /* Content-type */
357       asprintf (&http_content_type, "%s", optarg);
358       break;
359     case 'l': /* linespan */
360       cflags &= ~REG_NEWLINE;
361       break;
362     case 'R': /* regex */
363       cflags |= REG_ICASE;
364     case 'r': /* regex */
365       strncpy (regexp, optarg, MAX_RE_SIZE - 1);
366       regexp[MAX_RE_SIZE - 1] = 0;
367       errcode = regcomp (&preg, regexp, cflags);
368       if (errcode != 0) {
369         (void) regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
370         printf (_("Could Not Compile Regular Expression: %s"), errbuf);
371         return ERROR;
372       }
373       break;
374     case INVERT_REGEX:
375       invert_regex = 1;
376       break;
377     case '4':
378       address_family = AF_INET;
379       break;
380     case '6':
381 #ifdef USE_IPV6
382       address_family = AF_INET6;
383 #else
384       usage4 (_("IPv6 support not available"));
385 #endif
386       break;
387     case 'v': /* verbose */
388       verbose = TRUE;
389       break;
390     case 'm': /* min_page_length */
391       {
392       char *tmp;
393       if (strchr(optarg, ':') != (char *)NULL) {
394         /* range, so get two values, min:max */
395         tmp = strtok(optarg, ":");
396         if (tmp == NULL) {
397           printf("Bad format: try \"-m min:max\"\n");
398           exit (STATE_WARNING);
399         } else
400           min_page_len = atoi(tmp);
402         tmp = strtok(NULL, ":");
403         if (tmp == NULL) {
404           printf("Bad format: try \"-m min:max\"\n");
405           exit (STATE_WARNING);
406         } else
407           max_page_len = atoi(tmp);
408       } else 
409         min_page_len = atoi (optarg);
410       break;
411       }
412     case 'N': /* no-body */
413       no_body = TRUE;
414       break;
415     case 'M': /* max-age */
416                   {
417                     int L = strlen(optarg);
418                     if (L && optarg[L-1] == 'm')
419                       maximum_age = atoi (optarg) * 60;
420                     else if (L && optarg[L-1] == 'h')
421                       maximum_age = atoi (optarg) * 60 * 60;
422                     else if (L && optarg[L-1] == 'd')
423                       maximum_age = atoi (optarg) * 60 * 60 * 24;
424                     else if (L && (optarg[L-1] == 's' ||
425                                    isdigit (optarg[L-1])))
426                       maximum_age = atoi (optarg);
427                     else {
428                       fprintf (stderr, "unparsable max-age: %s\n", optarg);
429                       exit (STATE_WARNING);
430                     }
431                   }
432                   break;
433     }
434   }
436   c = optind;
438   if (server_address == NULL && c < argc)
439     server_address = strdup (argv[c++]);
441   if (host_name == NULL && c < argc)
442     host_name = strdup (argv[c++]);
444   if (server_address == NULL) {
445     if (host_name == NULL)
446       usage4 (_("You must specify a server address or host name"));
447     else
448       server_address = strdup (host_name);
449   }
451   if (check_critical_time && critical_time>(double)socket_timeout)
452     socket_timeout = (int)critical_time + 1;
454   if (http_method == NULL)
455     http_method = strdup ("GET");
457   return TRUE;
462 /* Returns 1 if we're done processing the document body; 0 to keep going */
463 static int
464 document_headers_done (char *full_page)
466   const char *body;
468   for (body = full_page; *body; body++) {
469     if (!strncmp (body, "\n\n", 2) || !strncmp (body, "\n\r\n", 3))
470       break;
471   }
473   if (!*body)
474     return 0;  /* haven't read end of headers yet */
476   full_page[body - full_page] = 0;
477   return 1;
480 static time_t
481 parse_time_string (const char *string)
483   struct tm tm;
484   time_t t;
485   memset (&tm, 0, sizeof(tm));
487   /* Like this: Tue, 25 Dec 2001 02:59:03 GMT */
489   if (isupper (string[0])  &&  /* Tue */
490     islower (string[1])  &&
491     islower (string[2])  &&
492     ',' ==   string[3]   &&
493     ' ' ==   string[4]   &&
494     (isdigit(string[5]) || string[5] == ' ') &&   /* 25 */
495     isdigit (string[6])  &&
496     ' ' ==   string[7]   &&
497     isupper (string[8])  &&  /* Dec */
498     islower (string[9])  &&
499     islower (string[10]) &&
500     ' ' ==   string[11]  &&
501     isdigit (string[12]) &&  /* 2001 */
502     isdigit (string[13]) &&
503     isdigit (string[14]) &&
504     isdigit (string[15]) &&
505     ' ' ==   string[16]  &&
506     isdigit (string[17]) &&  /* 02: */
507     isdigit (string[18]) &&
508     ':' ==   string[19]  &&
509     isdigit (string[20]) &&  /* 59: */
510     isdigit (string[21]) &&
511     ':' ==   string[22]  &&
512     isdigit (string[23]) &&  /* 03 */
513     isdigit (string[24]) &&
514     ' ' ==   string[25]  &&
515     'G' ==   string[26]  &&  /* GMT */
516     'M' ==   string[27]  &&  /* GMT */
517     'T' ==   string[28]) {
519     tm.tm_sec  = 10 * (string[23]-'0') + (string[24]-'0');
520     tm.tm_min  = 10 * (string[20]-'0') + (string[21]-'0');
521     tm.tm_hour = 10 * (string[17]-'0') + (string[18]-'0');
522     tm.tm_mday = 10 * (string[5] == ' ' ? 0 : string[5]-'0') + (string[6]-'0');
523     tm.tm_mon = (!strncmp (string+8, "Jan", 3) ? 0 :
524       !strncmp (string+8, "Feb", 3) ? 1 :
525       !strncmp (string+8, "Mar", 3) ? 2 :
526       !strncmp (string+8, "Apr", 3) ? 3 :
527       !strncmp (string+8, "May", 3) ? 4 :
528       !strncmp (string+8, "Jun", 3) ? 5 :
529       !strncmp (string+8, "Jul", 3) ? 6 :
530       !strncmp (string+8, "Aug", 3) ? 7 :
531       !strncmp (string+8, "Sep", 3) ? 8 :
532       !strncmp (string+8, "Oct", 3) ? 9 :
533       !strncmp (string+8, "Nov", 3) ? 10 :
534       !strncmp (string+8, "Dec", 3) ? 11 :
535       -1);
536     tm.tm_year = ((1000 * (string[12]-'0') +
537       100 * (string[13]-'0') +
538       10 * (string[14]-'0') +
539       (string[15]-'0'))
540       - 1900);
542     tm.tm_isdst = 0;  /* GMT is never in DST, right? */
544     if (tm.tm_mon < 0 || tm.tm_mday < 1 || tm.tm_mday > 31)
545       return 0;
547     /* 
548     This is actually wrong: we need to subtract the local timezone
549     offset from GMT from this value.  But, that's ok in this usage,
550     because we only comparing these two GMT dates against each other,
551     so it doesn't matter what time zone we parse them in.
552     */
554     t = mktime (&tm);
555     if (t == (time_t) -1) t = 0;
557     if (verbose) {
558       const char *s = string;
559       while (*s && *s != '\r' && *s != '\n')
560       fputc (*s++, stdout);
561       printf (" ==> %lu\n", (unsigned long) t);
562     }
564     return t;
566   } else {
567     return 0;
568   }
573 static void
574 check_document_dates (const char *headers)
576   const char *s;
577   char *server_date = 0;
578   char *document_date = 0;
580   s = headers;
581   while (*s) {
582     const char *field = s;
583     const char *value = 0;
585     /* Find the end of the header field */
586     while (*s && !isspace(*s) && *s != ':')
587       s++;
589     /* Remember the header value, if any. */
590     if (*s == ':')
591       value = ++s;
593     /* Skip to the end of the header, including continuation lines. */
594     while (*s && !(*s == '\n' && (s[1] != ' ' && s[1] != '\t')))
595       s++;
596     s++;
598     /* Process this header. */
599     if (value && value > field+2) {
600       char *ff = (char *) malloc (value-field);
601       char *ss = ff;
602       while (field < value-1)
603         *ss++ = tolower(*field++);
604       *ss++ = 0;
606       if (!strcmp (ff, "date") || !strcmp (ff, "last-modified")) {
607         const char *e;
608         while (*value && isspace (*value))
609           value++;
610         for (e = value; *e && *e != '\r' && *e != '\n'; e++)
611           ;
612         ss = (char *) malloc (e - value + 1);
613         strncpy (ss, value, e - value);
614         ss[e - value] = 0;
615         if (!strcmp (ff, "date")) {
616           if (server_date) free (server_date);
617           server_date = ss;
618         } else {
619           if (document_date) free (document_date);
620           document_date = ss;
621         }
622       }
623       free (ff);
624     }
625   }
627   /* Done parsing the body.  Now check the dates we (hopefully) parsed.  */
628   if (!server_date || !*server_date) {
629     die (STATE_UNKNOWN, _("HTTP UNKNOWN - Server date unknown\n"));
630   } else if (!document_date || !*document_date) {
631     die (STATE_CRITICAL, _("HTTP CRITICAL - Document modification date unknown\n"));
632   } else {
633     time_t srv_data = parse_time_string (server_date);
634     time_t doc_data = parse_time_string (document_date);
636     if (srv_data <= 0) {
637       die (STATE_CRITICAL, _("HTTP CRITICAL - Server date \"%100s\" unparsable"), server_date);
638     } else if (doc_data <= 0) {
639       die (STATE_CRITICAL, _("HTTP CRITICAL - Document date \"%100s\" unparsable"), document_date);
640     } else if (doc_data > srv_data + 30) {
641       die (STATE_CRITICAL, _("HTTP CRITICAL - Document is %d seconds in the future\n"), (int)doc_data - (int)srv_data);
642     } else if (doc_data < srv_data - maximum_age) {
643     int n = (srv_data - doc_data);
644     if (n > (60 * 60 * 24 * 2))
645       die (STATE_CRITICAL,
646         _("HTTP CRITICAL - Last modified %.1f days ago\n"),
647         ((float) n) / (60 * 60 * 24));
648   else
649     die (STATE_CRITICAL,
650         _("HTTP CRITICAL - Last modified %d:%02d:%02d ago\n"),
651         n / (60 * 60), (n / 60) % 60, n % 60);
652     }
654     free (server_date);
655     free (document_date);
656   }
659 int
660 get_content_length (const char *headers)
662   const char *s;
663   int content_length = 0;
665   s = headers;
666   while (*s) {
667     const char *field = s;
668     const char *value = 0;
670     /* Find the end of the header field */
671     while (*s && !isspace(*s) && *s != ':')
672       s++;
674     /* Remember the header value, if any. */
675     if (*s == ':')
676       value = ++s;
678     /* Skip to the end of the header, including continuation lines. */
679     while (*s && !(*s == '\n' && (s[1] != ' ' && s[1] != '\t')))
680       s++;
681     s++;
683     /* Process this header. */
684     if (value && value > field+2) {
685       char *ff = (char *) malloc (value-field);
686       char *ss = ff;
687       while (field < value-1)
688         *ss++ = tolower(*field++);
689       *ss++ = 0;
691       if (!strcmp (ff, "content-length")) {
692         const char *e;
693         while (*value && isspace (*value))
694           value++;
695         for (e = value; *e && *e != '\r' && *e != '\n'; e++)
696           ;
697         ss = (char *) malloc (e - value + 1);
698         strncpy (ss, value, e - value);
699         ss[e - value] = 0;
700         content_length = atoi(ss);
701         free (ss);
702       }
703       free (ff);
704     }
705   }
706   return (content_length);
709 int
710 check_http (void)
712   char *msg;
713   char *status_line;
714   char *status_code;
715   char *header;
716   char *page;
717   char *auth;
718   int http_status;
719   int i = 0;
720   size_t pagesize = 0;
721   char *full_page;
722   char *buf;
723   char *pos;
724   long microsec;
725   double elapsed_time;
726   int page_len = 0;
727   int result = STATE_UNKNOWN;
729   /* try to connect to the host at the given port number */
730   if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK)
731     die (STATE_CRITICAL, _("HTTP CRITICAL - Unable to open TCP socket\n"));
732 #ifdef HAVE_SSL
733   if (use_ssl == TRUE) {
734     np_net_ssl_init(sd);
735     if (check_cert == TRUE) {
736       result = np_net_ssl_check_cert(days_till_exp);
737       np_net_ssl_cleanup();
738       if(sd) close(sd);
739       return result;
740     }
741   }
742 #endif /* HAVE_SSL */
744   asprintf (&buf, "%s %s HTTP/1.0\r\n%s\r\n", http_method, server_url, user_agent);
746   /* tell HTTP/1.1 servers not to keep the connection alive */
747   asprintf (&buf, "%sConnection: close\r\n", buf);
749   /* optionally send the host header info */
750   if (host_name)
751     asprintf (&buf, "%sHost: %s\r\n", buf, host_name);
753   /* optionally send any other header tag */
754   if (http_opt_headers_count) {
755     for (i = 0; i < http_opt_headers_count ; i++) {
756       for ((pos = strtok(http_opt_headers[i], INPUT_DELIMITER)); pos; (pos = strtok(NULL, INPUT_DELIMITER)))
757         asprintf (&buf, "%s%s\r\n", buf, pos);
758     }
759     free(http_opt_headers);
760   }
762   /* optionally send the authentication info */
763   if (strlen(user_auth)) {
764     auth = base64 (user_auth, strlen (user_auth));
765     asprintf (&buf, "%sAuthorization: Basic %s\r\n", buf, auth);
766   }
768   /* either send http POST data */
769   if (http_post_data) {
770     if (http_content_type) {
771       asprintf (&buf, "%sContent-Type: %s\r\n", buf, http_content_type);
772     } else {
773       asprintf (&buf, "%sContent-Type: application/x-www-form-urlencoded\r\n", buf);
774     }
775     
776     asprintf (&buf, "%sContent-Length: %i\r\n\r\n", buf, (int)strlen (http_post_data));
777     asprintf (&buf, "%s%s%s", buf, http_post_data, CRLF);
778   }
779   else {
780     /* or just a newline so the server knows we're done with the request */
781     asprintf (&buf, "%s%s", buf, CRLF);
782   }
784   if (verbose) printf ("%s\n", buf);
785   my_send (buf, strlen (buf));
787   /* fetch the page */
788   full_page = strdup("");
789   while ((i = my_recv (buffer, MAX_INPUT_BUFFER-1)) > 0) {
790     buffer[i] = '\0';
791     asprintf (&full_page, "%s%s", full_page, buffer);
792     pagesize += i;
794                 if (no_body && document_headers_done (full_page)) {
795                   i = 0;
796                   break;
797                 }
798   }
800   if (i < 0 && errno != ECONNRESET) {
801 #ifdef HAVE_SSL
802     /*
803     if (use_ssl) {
804       sslerr=SSL_get_error(ssl, i);
805       if ( sslerr == SSL_ERROR_SSL ) {
806         die (STATE_WARNING, _("HTTP WARNING - Client Certificate Required\n"));
807       } else {
808         die (STATE_CRITICAL, _("HTTP CRITICAL - Error on receive\n"));
809       }
810     }
811     else {
812     */
813 #endif
814       die (STATE_CRITICAL, _("HTTP CRITICAL - Error on receive\n"));
815 #ifdef HAVE_SSL
816       /* XXX
817     }
818     */
819 #endif
820   }
822   /* return a CRITICAL status if we couldn't read any data */
823   if (pagesize == (size_t) 0)
824     die (STATE_CRITICAL, _("HTTP CRITICAL - No data received from host\n"));
826   /* close the connection */
827 #ifdef HAVE_SSL
828   np_net_ssl_cleanup();
829 #endif
830   if(sd) close(sd);
832   /* reset the alarm */
833   alarm (0);
835   /* leave full_page untouched so we can free it later */
836   page = full_page;
838   if (verbose)
839     printf ("%s://%s:%d%s is %d characters\n",
840       use_ssl ? "https" : "http", server_address,
841       server_port, server_url, (int)pagesize);
843   /* find status line and null-terminate it */
844   status_line = page;
845   page += (size_t) strcspn (page, "\r\n");
846   pos = page;
847   page += (size_t) strspn (page, "\r\n");
848   status_line[strcspn(status_line, "\r\n")] = 0;
849   strip (status_line);
850   if (verbose)
851     printf ("STATUS: %s\n", status_line);
853   /* find header info and null-terminate it */
854   header = page;
855   while (strcspn (page, "\r\n") > 0) {
856     page += (size_t) strcspn (page, "\r\n");
857     pos = page;
858     if ((strspn (page, "\r") == 1 && strspn (page, "\r\n") >= 2) ||
859         (strspn (page, "\n") == 1 && strspn (page, "\r\n") >= 2))
860       page += (size_t) 2;
861     else
862       page += (size_t) 1;
863   }
864   page += (size_t) strspn (page, "\r\n");
865   header[pos - header] = 0;
866   if (verbose)
867     printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header,
868                 (no_body ? "  [[ skipped ]]" : page));
870   /* make sure the status line matches the response we are looking for */
871   if (!strstr (status_line, server_expect)) {
872     if (server_port == HTTP_PORT)
873       asprintf (&msg,
874                 _("Invalid HTTP response received from host\n"));
875     else
876       asprintf (&msg,
877                 _("Invalid HTTP response received from host on port %d\n"),
878                 server_port);
879     die (STATE_CRITICAL, "HTTP CRITICAL - %s", msg);
880   }
882   /* Exit here if server_expect was set by user and not default */
883   if ( server_expect_yn  )  {
884     asprintf (&msg,
885               _("HTTP OK: Status line output matched \"%s\"\n"),
886               server_expect);
887     if (verbose)
888       printf ("%s\n",msg);
889   }
890   else {
891     /* Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF */
892     /* HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT */
893     /* Status-Code = 3 DIGITS */
895     status_code = strchr (status_line, ' ') + sizeof (char);
896     if (strspn (status_code, "1234567890") != 3)
897       die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status Line (%s)\n"), status_line);
899     http_status = atoi (status_code);
901     /* check the return code */
903     if (http_status >= 600 || http_status < 100)
904       die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%s)\n"), status_line);
906     /* server errors result in a critical state */
907     else if (http_status >= 500)
908       die (STATE_CRITICAL, _("HTTP CRITICAL: %s\n"), status_line);
910     /* client errors result in a warning state */
911     else if (http_status >= 400)
912       die (STATE_WARNING, _("HTTP WARNING: %s\n"), status_line);
914     /* check redirected page if specified */
915     else if (http_status >= 300) {
917       if (onredirect == STATE_DEPENDENT)
918         redir (header, status_line);
919       else if (onredirect == STATE_UNKNOWN)
920         printf (_("HTTP UNKNOWN"));
921       else if (onredirect == STATE_OK)
922         printf (_("HTTP OK"));
923       else if (onredirect == STATE_WARNING)
924         printf (_("HTTP WARNING"));
925       else if (onredirect == STATE_CRITICAL)
926         printf (_("HTTP CRITICAL"));
927       microsec = deltime (tv);
928       elapsed_time = (double)microsec / 1.0e6;
929       die (onredirect,
930            _(" - %s - %.3f second response time %s|%s %s\n"),
931            status_line, elapsed_time, 
932            (display_html ? "</A>" : ""),
933            perfd_time (elapsed_time), perfd_size (pagesize));
934     } /* end if (http_status >= 300) */
936   } /* end else (server_expect_yn)  */
937     
938         if (maximum_age >= 0) {
939           check_document_dates (header);
940         }
942   /* check elapsed time */
943   microsec = deltime (tv);
944   elapsed_time = (double)microsec / 1.0e6;
945   asprintf (&msg,
946             _(" - %s - %.3f second response time %s|%s %s\n"),
947             status_line, elapsed_time, 
948             (display_html ? "</A>" : ""),
949             perfd_time (elapsed_time), perfd_size (pagesize));
950   if (check_critical_time == TRUE && elapsed_time > critical_time)
951     die (STATE_CRITICAL, "HTTP %s: %s", _("CRITICAL"), msg);
952   if (check_warning_time == TRUE && elapsed_time > warning_time)
953     die (STATE_WARNING, "HTTP %s: %s", _("WARNING"), msg);
955   /* Page and Header content checks go here */
956   /* these checks should be last */
958   if (strlen (string_expect)) {
959     if (strstr (page, string_expect)) {
960       printf (_("HTTP OK %s - %.3f second response time %s|%s %s\n"),
961               status_line, elapsed_time,
962               (display_html ? "</A>" : ""),
963               perfd_time (elapsed_time), perfd_size (pagesize));
964       exit (STATE_OK);
965     }
966     else {
967       printf (_("HTTP CRITICAL - string not found%s|%s %s\n"),
968               (display_html ? "</A>" : ""),
969               perfd_time (elapsed_time), perfd_size (pagesize));
970       exit (STATE_CRITICAL);
971     }
972   }
974   if (strlen (regexp)) {
975     errcode = regexec (&preg, page, REGS, pmatch, 0);
976     if ((errcode == 0 && invert_regex == 0) || (errcode == REG_NOMATCH && invert_regex == 1)) {
977       printf (_("HTTP OK %s - %.3f second response time %s|%s %s\n"),
978               status_line, elapsed_time,
979               (display_html ? "</A>" : ""),
980               perfd_time (elapsed_time), perfd_size (pagesize));
981       exit (STATE_OK);
982     }
983     else if ((errcode == REG_NOMATCH && invert_regex == 0) || (errcode == 0 && invert_regex == 1)) {
984       if (invert_regex == 0) 
985         msg = strdup(_("pattern not found"));
986       else 
987         msg = strdup(_("pattern found"));
988       printf (("%s - %s%s|%s %s\n"),
989         _("HTTP CRITICAL"),
990         msg,
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 (_("HTTP CRITICAL - Execute Error: %s\n"), errbuf);
998       exit (STATE_CRITICAL);
999     }
1000   }
1002   /* make sure the page is of an appropriate size */
1003   /* page_len = get_content_length(header); */
1004   page_len = pagesize;
1005   if ((max_page_len > 0) && (page_len > max_page_len)) {
1006     printf (_("HTTP WARNING: page size %d too large%s|%s\n"),
1007       page_len, (display_html ? "</A>" : ""), perfd_size (page_len) );
1008     exit (STATE_WARNING);
1009   } else if ((min_page_len > 0) && (page_len < min_page_len)) {
1010     printf (_("HTTP WARNING: page size %d too small%s|%s\n"),
1011       page_len, (display_html ? "</A>" : ""), perfd_size (page_len) );
1012     exit (STATE_WARNING);
1013   }
1014   /* We only get here if all tests have been passed */
1015   asprintf (&msg, _("HTTP OK %s - %d bytes in %.3f seconds %s|%s %s\n"),
1016             status_line, page_len, elapsed_time,
1017             (display_html ? "</A>" : ""),
1018             perfd_time (elapsed_time), perfd_size (page_len));
1019   die (STATE_OK, "%s", msg);
1020   return STATE_UNKNOWN;
1025 /* per RFC 2396 */
1026 #define URI_HTTP "%5[HTPShtps]"
1027 #define URI_HOST "%255[-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
1028 #define URI_PORT "%6d" /* MAX_PORT's width is 5 chars, 6 to detect overflow */
1029 #define URI_PATH "%[-_.!~*'();/?:@&=+$,%#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
1030 #define HD1 URI_HTTP "://" URI_HOST ":" URI_PORT "/" URI_PATH
1031 #define HD2 URI_HTTP "://" URI_HOST "/" URI_PATH
1032 #define HD3 URI_HTTP "://" URI_HOST ":" URI_PORT
1033 #define HD4 URI_HTTP "://" URI_HOST
1034 #define HD5 URI_PATH
1036 void
1037 redir (char *pos, char *status_line)
1039   int i = 0;
1040   char *x;
1041   char xx[2];
1042   char type[6];
1043   char *addr;
1044   char *url;
1046   addr = malloc (MAX_IPV4_HOSTLENGTH + 1);
1047   if (addr == NULL)
1048     die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate addr\n"));
1049   
1050   url = malloc (strcspn (pos, "\r\n"));
1051   if (url == NULL)
1052     die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate url\n"));
1054   while (pos) {
1055     sscanf (pos, "%1[Ll]%*1[Oo]%*1[Cc]%*1[Aa]%*1[Tt]%*1[Ii]%*1[Oo]%*1[Nn]:%n", xx, &i);
1056     if (i == 0) {
1057       pos += (size_t) strcspn (pos, "\r\n");
1058       pos += (size_t) strspn (pos, "\r\n");
1059       if (strlen(pos) == 0) 
1060         die (STATE_UNKNOWN,
1061              _("HTTP UNKNOWN - Could not find redirect location - %s%s\n"),
1062              status_line, (display_html ? "</A>" : ""));
1063       continue;
1064     }
1066     pos += i;
1067     pos += strspn (pos, " \t");
1069     /*
1070      * RFC 2616 (4.2):  ``Header fields can be extended over multiple lines by
1071      * preceding each extra line with at least one SP or HT.''
1072      */
1073     for (; (i = strspn (pos, "\r\n")); pos += i) {
1074       pos += i;
1075       if (!(i = strspn (pos, " \t"))) {
1076         die (STATE_UNKNOWN, _("HTTP UNKNOWN - Empty redirect location%s\n"),
1077              display_html ? "</A>" : "");
1078       }
1079     }
1081     url = realloc (url, strcspn (pos, "\r\n") + 1);
1082     if (url == NULL)
1083       die (STATE_UNKNOWN, _("HTTP UNKNOWN - could not allocate url\n"));
1085     /* URI_HTTP, URI_HOST, URI_PORT, URI_PATH */
1086     if (sscanf (pos, HD1, type, addr, &i, url) == 4)
1087       use_ssl = server_type_check (type);
1089     /* URI_HTTP URI_HOST URI_PATH */
1090     else if (sscanf (pos, HD2, type, addr, url) == 3 ) { 
1091       use_ssl = server_type_check (type);
1092       i = server_port_check (use_ssl);
1093     }
1095     /* URI_HTTP URI_HOST URI_PORT */
1096     else if(sscanf (pos, HD3, type, addr, &i) == 3) {
1097       strcpy (url, HTTP_URL);
1098       use_ssl = server_type_check (type);
1099     }
1101     /* URI_HTTP URI_HOST */
1102     else if(sscanf (pos, HD4, type, addr) == 2) {
1103       strcpy (url, HTTP_URL);
1104       use_ssl = server_type_check (type);
1105       i = server_port_check (use_ssl);
1106     }
1108     /* URI_PATH */
1109     else if (sscanf (pos, HD5, url) == 1) {
1110       /* relative url */
1111       if ((url[0] != '/')) {
1112         if ((x = strrchr(server_url, '/')))
1113           *x = '\0';
1114         asprintf (&url, "%s/%s", server_url, url);
1115       }
1116       i = server_port;
1117       strcpy (type, server_type);
1118       strcpy (addr, host_name ? host_name : server_address);
1119     }           
1121     else {
1122       die (STATE_UNKNOWN,
1123            _("HTTP UNKNOWN - Could not parse redirect location - %s%s\n"),
1124            pos, (display_html ? "</A>" : ""));
1125     }
1127     break;
1129   } /* end while (pos) */
1131   if (++redir_depth > max_depth)
1132     die (STATE_WARNING,
1133          _("HTTP WARNING - maximum redirection depth %d exceeded - %s://%s:%d%s%s\n"),
1134          max_depth, type, addr, i, url, (display_html ? "</A>" : ""));
1136   if (server_port==i &&
1137       !strcmp(server_address, addr) &&
1138       (host_name && !strcmp(host_name, addr)) &&
1139       !strcmp(server_url, url))
1140     die (STATE_WARNING,
1141          _("HTTP WARNING - redirection creates an infinite loop - %s://%s:%d%s%s\n"),
1142          type, addr, i, url, (display_html ? "</A>" : ""));
1144   strcpy (server_type, type);
1146   free (host_name);
1147   host_name = strdup (addr);
1149   free (server_address);
1150   server_address = strdup (addr);
1152   free (server_url);
1153   if ((url[0] == '/'))
1154     server_url = strdup (url);
1155   else if (asprintf(&server_url, "/%s", url) == -1)
1156     die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate server_url%s\n"),
1157          display_html ? "</A>" : "");
1158   free(url);
1160   if ((server_port = i) > MAX_PORT)
1161     die (STATE_UNKNOWN,
1162          _("HTTP UNKNOWN - Redirection to port above %d - %s://%s:%d%s%s\n"),
1163          MAX_PORT, server_type, server_address, server_port, server_url,
1164          display_html ? "</A>" : "");
1166   if (verbose)
1167     printf (_("Redirection to %s://%s:%d%s\n"), server_type,
1168             host_name ? host_name : server_address, server_port, server_url);
1170   check_http ();
1175 int
1176 server_type_check (const char *type)
1178   if (strcmp (type, "https"))
1179     return FALSE;
1180   else
1181     return TRUE;
1184 int
1185 server_port_check (int ssl_flag)
1187   if (ssl_flag)
1188     return HTTPS_PORT;
1189   else
1190     return HTTP_PORT;
1193 char *perfd_time (double elapsed_time)
1195   return fperfdata ("time", elapsed_time, "s",
1196             check_warning_time, warning_time,
1197             check_critical_time, critical_time,
1198                    TRUE, 0, FALSE, 0);
1203 char *perfd_size (int page_len)
1205   return perfdata ("size", page_len, "B",
1206             (min_page_len>0?TRUE:FALSE), min_page_len,
1207             (min_page_len>0?TRUE:FALSE), 0,
1208             TRUE, 0, FALSE, 0);
1211 void
1212 print_help (void)
1214   print_revision (progname, revision);
1216   printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
1217   printf (COPYRIGHT, copyright, email);
1219   printf ("%s\n", _("This plugin tests the HTTP service on the specified host. It can test"));
1220   printf ("%s\n", _("normal (http) and secure (https) servers, follow redirects, search for"));
1221   printf ("%s\n", _("strings and regular expressions, check connection times, and report on"));
1222   printf ("%s\n", _("certificate expiration times."));
1224   printf ("\n\n");
1226   print_usage ();
1228   printf (_("NOTE: One or both of -H and -I must be specified"));
1230   printf ("\n");
1232   printf (_(UT_HELP_VRSN));
1234   printf (" %s\n", "-H, --hostname=ADDRESS");
1235   printf ("    %s\n", _("Host name argument for servers using host headers (virtual host)"));
1236   printf ("    %s\n", _("Append a port to include it in the header (eg: example.com:5000)"));
1237   printf (" %s\n", "-I, --IP-address=ADDRESS");
1238   printf ("    %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup)."));
1239   printf (" %s\n", "-p, --port=INTEGER");
1240   printf (" %s", _("Port number (default: "));
1241   printf ("%d)\n", HTTP_PORT);
1243   printf (_(UT_IPv46));
1245 #ifdef HAVE_SSL
1246   printf (" %s\n", "-S, --ssl");
1247   printf ("   %s\n", _("Connect via SSL. Port defaults to 443"));
1248   printf (" %s\n", "-C, --certificate=INTEGER");
1249   printf ("   %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443"));
1250   printf ("   %s\n", _("(when this option is used the url is not checked.)\n"));
1251 #endif
1253   printf (" %s\n", "-e, --expect=STRING");
1254   printf ("    %s\n", _("String to expect in first (status) line of server response (default: "));
1255   printf ("%s)\n", HTTP_EXPECT);
1256   printf ("    %s\n", _("If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)"));
1257   printf (" %s\n", "-s, --string=STRING");
1258   printf ("    %s\n", _("String to expect in the content"));
1259   printf (" %s\n", "-u, --url=PATH");
1260   printf ("    %s\n", _("URL to GET or POST (default: /)"));
1261   printf (" %s\n", "-P, --post=STRING");
1262   printf ("    %s\n", _("URL encoded http POST data"));
1263   printf (" %s\n", "-N, --no-body");
1264   printf ("    %s\n", _("Don't wait for document body: stop reading after headers."));
1265   printf ("    %s\n", _("(Note that this still does an HTTP GET or POST, not a HEAD.)"));
1266   printf (" %s\n", "-M, --max-age=SECONDS");
1267   printf ("    %s\n", _("Warn if document is more than SECONDS old. the number can also be of"));
1268   printf ("    %s\n", _("the form \"10m\" for minutes, \"10h\" for hours, or \"10d\" for days."));
1269   printf (" %s\n", "-T, --content-type=STRING");
1270   printf ("    %s\n", _("specify Content-Type header media type when POSTing\n"));
1272   printf (" %s\n", "-l, --linespan");
1273   printf ("    %s\n", _("Allow regex to span newlines (must precede -r or -R)"));
1274   printf (" %s\n", "-r, --regex, --ereg=STRING");
1275   printf ("    %s\n", _("Search page for regex STRING"));
1276   printf (" %s\n", "-R, --eregi=STRING");
1277   printf ("    %s\n", _("Search page for case-insensitive regex STRING"));
1278   printf (" %s\n", "--invert-regex");
1279   printf ("    %s\n", _("Return CRITICAL if found, OK if not\n"));
1281   printf (" %s\n", "-a, --authorization=AUTH_PAIR");
1282   printf ("    %s\n", _("Username:password on sites with basic authentication"));
1283   printf (" %s\n", "-A, --useragent=STRING");
1284   printf ("    %s\n", _("String to be sent in http header as \"User Agent\""));
1285   printf (" %s\n", "-k, --header=STRING");
1286   printf ("    %s\n", _(" Any other tags to be sent in http header. Use multiple times for additional headers"));
1287   printf (" %s\n", "-L, --link");
1288   printf ("    %s\n", _("Wrap output in HTML link (obsoleted by urlize)"));
1289   printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow>");
1290   printf ("    %s\n", _("How to handle redirected pages"));
1291   printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>");
1292   printf ("    %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)"));
1294   printf (_(UT_WARN_CRIT));
1296   printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
1298   printf (_(UT_VERBOSE));
1300   printf (_("Notes:"));
1301   printf (" %s\n", _("This plugin will attempt to open an HTTP connection with the host."));
1302   printf (" %s\n", _("Successful connects return STATE_OK, refusals and timeouts return STATE_CRITICAL"));
1303   printf (" %s\n", _("other errors return STATE_UNKNOWN.  Successful connects, but incorrect reponse"));
1304   printf (" %s\n", _("messages from the host result in STATE_WARNING return values.  If you are"));
1305   printf (" %s\n", _("checking a virtual server that uses 'host headers' you must supply the FQDN"));
1306   printf (" %s\n", _("(fully qualified domain name) as the [host_name] argument."));
1308 #ifdef HAVE_SSL
1309   printf (" %s\n", _("This plugin can also check whether an SSL enabled web server is able to"));
1310   printf (" %s\n", _("serve content (optionally within a specified time) or whether the X509 "));
1311   printf (" %s\n", _("certificate is still valid for the specified number of days."));
1312   printf (_("Examples:"));
1313   printf (" %s\n\n", "CHECK CONTENT: check_http -w 5 -c 10 --ssl -H www.verisign.com");
1314   printf (" %s\n", _("When the 'www.verisign.com' server returns its content within 5 seconds,"));
1315   printf (" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds"));
1316   printf (" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,"));
1317   printf (" %s\n\n", _("a STATE_CRITICAL will be returned."));
1319   printf (" %s\n\n", "CHECK CERTIFICATE: check_http -H www.verisign.com -C 14");
1320   printf (" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 14 days,"));
1321   printf (" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than"));
1322   printf (" %s\n", _("14 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when"));
1323   printf (" %s\n\n", _("the certificate is expired."));
1324 #endif
1326   printf (_(UT_SUPPORT));
1332 void
1333 print_usage (void)
1335   printf (_("Usage:"));
1336   printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname);
1337   printf ("       [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L]\n");
1338   printf ("       [-a auth] [-f <ok | warn | critcal | follow>] [-e <expect>]\n");
1339   printf ("       [-s string] [-l] [-r <regex> | -R <case-insensitive regex>] [-P string]\n");
1340   printf ("       [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>] [-A string]\n");
1341   printf ("       [-k string] [-S] [-C <age>] [-T <content-type>]\n");