Code

- bindtextdomain for gettext, a few other smale cleanups here and there
[nagiosplug.git] / plugins / check_http.c
index 27127d6af63e8bafd7097a9b146a39251555aa1b..3ec9e4992211ce2fe3a6b7368f4533dd3b691a77 100644 (file)
@@ -79,11 +79,6 @@ int errcode;
 
 struct timeval tv;
 
-#define server_type_check(server_type) \
-(strcmp (server_type, "https") ? FALSE : TRUE)
-
-#define server_port_check(use_ssl) (use_ssl ? HTTPS_PORT : HTTP_PORT)
-
 #define HTTP_URL "/"
 #define CRLF "\r\n"
 
@@ -110,13 +105,18 @@ int use_ssl = FALSE;
 int verbose = FALSE;
 int sd;
 int min_page_len = 0;
+int redir_depth = 0;
+int max_depth = 15;
 char *http_method;
 char *http_post_data;
 char buffer[MAX_INPUT_BUFFER];
 
 int process_arguments (int, char **);
-static char *base64 (char *bin, size_t len);
+static char *base64 (const char *bin, size_t len);
 int check_http (void);
+int redir (char *pos, char *status_line);
+int server_type_check(const char *type);
+int server_port_check(int ssl_flag);
 int my_recv (void);
 int my_close (void);
 void print_help (void);
@@ -304,13 +304,13 @@ process_arguments (int argc, char **argv)
                        break;
                /* Note: H, I, and u must be malloc'd or will fail on redirects */
                case 'H': /* Host Name (virtual host) */
-                       host_name = optarg;
+                       host_name = strdup (optarg);
                        break;
                case 'I': /* Server IP-address */
-                       server_address = optarg;
+                       server_address = strdup (optarg);
                        break;
                case 'u': /* URL path */
-                       asprintf (&server_url, "%s", optarg);
+                       server_url = strdup (optarg);
                        server_url_length = strlen (server_url);
                        break;
                case 'p': /* Server port */
@@ -328,7 +328,7 @@ process_arguments (int argc, char **argv)
                case 'P': /* HTTP POST data in URL encoded format */
                        if (http_method || http_post_data) break;
                        http_method = strdup("POST");
-                       http_post_data = optarg;
+                       http_post_data = strdup (optarg);
                        break;
                case 's': /* string or substring */
                        strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1);
@@ -387,7 +387,7 @@ process_arguments (int argc, char **argv)
                server_address = strdup (argv[c++]);
 
        if (host_name == NULL && c < argc)
-               asprintf (&host_name, "%s", argv[c++]);
+               host_name = strdup (argv[c++]);
 
        if (server_address == NULL) {
                if (host_name == NULL)
@@ -409,7 +409,7 @@ process_arguments (int argc, char **argv)
 
 /* written by lauri alanko */
 static char *
-base64 (char *bin, size_t len)
+base64 (const char *bin, size_t len)
 {
 
        char *buf = (char *) malloc ((len + 2) / 3 * 4 + 1);
@@ -450,17 +450,7 @@ base64 (char *bin, size_t len)
 \f
 
 
-/* per RFC 2396 */
-#define HDR_LOCATION "%*[Ll]%*[Oo]%*[Cc]%*[Aa]%*[Tt]%*[Ii]%*[Oo]%*[Nn]: "
-#define URI_HTTP "%[HTPShtps]://"
-#define URI_HOST "%[-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
-#define URI_PORT ":%[0123456789]"
-#define URI_PATH "%[-_.!~*'();/?:@&=+$,%#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
-#define HD1 HDR_LOCATION URI_HTTP URI_HOST URI_PORT URI_PATH
-#define HD2 HDR_LOCATION URI_HTTP URI_HOST URI_PATH
-#define HD3 HDR_LOCATION URI_HTTP URI_HOST URI_PORT
-#define HD4 HDR_LOCATION URI_HTTP URI_HOST
-#define HD5 HDR_LOCATION URI_PATH
+
 
 int
 check_http (void)
@@ -475,8 +465,6 @@ check_http (void)
        char *full_page;
        char *buf;
        char *pos;
-       char *x;
-       char *orig_url;
        long microsec;
        double elapsed_time;
        int page_len = 0;
@@ -489,7 +477,7 @@ check_http (void)
        if (use_ssl == TRUE) {
 
                if (connect_SSL () != OK) {
-                       die (STATE_CRITICAL, _("Unable to open TCP socket"));
+                       die (STATE_CRITICAL, _("Unable to open TCP socket\n"));
                }
 
                if ((server_cert = SSL_get_peer_certificate (ssl)) != NULL) {
@@ -504,7 +492,7 @@ check_http (void)
        else {
 #endif
                if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK)
-                       die (STATE_CRITICAL, _("Unable to open TCP socket"));
+                       die (STATE_CRITICAL, _("Unable to open TCP socket\n"));
 #ifdef HAVE_SSL
        }
 #endif
@@ -565,12 +553,12 @@ check_http (void)
                        if ( sslerr == SSL_ERROR_SSL ) {
                                die (STATE_WARNING, _("Client Certificate Required\n"));
                        } else {
-                               die (STATE_CRITICAL, _("Error in recv()"));
+                               die (STATE_CRITICAL, _("Error in recv()\n"));
                        }
                }
                else {
 #endif
-                       die (STATE_CRITICAL, _("Error in recv()"));
+                       die (STATE_CRITICAL, _("Error in recv()\n"));
 #ifdef HAVE_SSL
                }
 #endif
@@ -578,7 +566,7 @@ check_http (void)
 
        /* return a CRITICAL status if we couldn't read any data */
        if (pagesize == (size_t) 0)
-               die (STATE_CRITICAL, _("No data received %s"), timestamp);
+               die (STATE_CRITICAL, _("No data received %s\n"), timestamp);
 
        /* close the connection */
        my_close ();
@@ -590,7 +578,7 @@ check_http (void)
        page = full_page;
 
        if (verbose)
-               printf ("Page is %d characters\n", pagesize);
+               printf ("%s://%s:%d%s is %d characters\n", server_type, server_address, server_port, server_url, pagesize);
 
        /* find status line and null-terminate it */
        status_line = page;
@@ -643,92 +631,33 @@ check_http (void)
 
                /* check the return code */
                /* server errors result in a critical state */
-               if (strstr (status_line, "500") ||
-                 strstr (status_line, "501") ||
-               strstr (status_line, "502") ||
-                   strstr (status_line, "503")) {
-                       die (STATE_CRITICAL, _("HTTP CRITICAL: %s\n"), status_line);
+               if (strstr (status_line, "500") || strstr (status_line, "501") ||
+                   strstr (status_line, "502") || strstr (status_line, "503") ||
+                   strstr (status_line, "504") || strstr (status_line, "505")) {
+                       die (STATE_CRITICAL, _("HTTP CRITICAL: %s\n"), status_line);
                }
 
                /* client errors result in a warning state */
-               if (strstr (status_line, "400") ||
-                 strstr (status_line, "401") ||
-               strstr (status_line, "402") ||
-                   strstr (status_line, "403") ||
-                   strstr (status_line, "404")) {
+               if (strstr (status_line, "400") || strstr (status_line, "401") ||
+                   strstr (status_line, "402") || strstr (status_line, "403") ||
+                   strstr (status_line, "404") || strstr (status_line, "405") ||
+                   strstr (status_line, "406") || strstr (status_line, "407") ||
+                   strstr (status_line, "408") || strstr (status_line, "409") ||
+                   strstr (status_line, "410") || strstr (status_line, "411") ||
+                   strstr (status_line, "412") || strstr (status_line, "413") ||
+                   strstr (status_line, "414") || strstr (status_line, "415") ||
+                   strstr (status_line, "416") || strstr (status_line, "417")) {
                        die (STATE_WARNING, _("HTTP WARNING: %s\n"), status_line);
                }
 
                /* check redirected page if specified */
-               if (strstr (status_line, "300") ||
-                 strstr (status_line, "301") ||
-               strstr (status_line, "302") ||
-                   strstr (status_line, "303") ||
-                   strstr (status_line, "304")) {
-                       if (onredirect == STATE_DEPENDENT) {
-
-                               asprintf (&orig_url, "%s", server_url);
-                               pos = header;
-                               while (pos) {
-                                       server_address = realloc (server_address, MAX_IPV4_HOSTLENGTH + 1);
-                                       if (server_address == NULL)
-                                               die (STATE_UNKNOWN,_("ERROR: could not allocate server_address"));
-                                       if (strcspn (pos, "\r\n") > (size_t)server_url_length) {
-                                               server_url = realloc (server_url, strcspn (pos, "\r\n"));
-                                               if (server_url == NULL)
-                                                       die (STATE_UNKNOWN, _("ERROR: could not allocate server_url"));
-                                               server_url_length = strcspn (pos, "\r\n");
-                                       }
-                                       /* HDR_LOCATION, URI_HTTP, URI_HOST, URI_PORT, URI_PATH */
-                                       if (sscanf (pos, HD1, server_type, server_address, server_port_text, server_url) == 4) {
-                                               if (host_name != NULL) free(host_name);
-                                               host_name = strdup(server_address);
-                                               use_ssl = server_type_check (server_type);
-                                               server_port = atoi (server_port_text);
-                                               check_http ();
-                                       }
-                                       /* HDR_LOCATION URI_HTTP URI_HOST URI_PATH */
-                                       else if (sscanf (pos, HD2, server_type, server_address, server_url) == 3 ) { 
-                                               if (host_name != NULL) free(host_name);
-                                               host_name = strdup(server_address);
-                                               use_ssl = server_type_check (server_type);
-                                               server_port = server_port_check (use_ssl);
-                                               check_http ();
-                                       }
-                                       /* HDR_LOCATION URI_HTTP URI_HOST URI_PORT */
-                                       else if(sscanf (pos, HD3, server_type, server_address, server_port_text) == 3) {
-                                               if (host_name != NULL) free(host_name);
-                                               host_name = strdup(server_address);
-                                               strcpy (server_url, "/");
-                                               use_ssl = server_type_check (server_type);
-                                               server_port = atoi (server_port_text);
-                                               check_http ();
-                                       }
-                                       /* HDR_LOCATION URI_HTTP URI_HOST */
-                                       else if(sscanf (pos, HD4, server_type, server_address) == 2) {
-                                               if (host_name != NULL) free(host_name);
-                                               host_name = strdup(server_address);
-                                               strcpy (server_url, "/");
-                                               use_ssl = server_type_check (server_type);
-                                               server_port = server_port_check (use_ssl);
-                                               check_http ();
-                                       }
-                                       /* HDR_LOCATION URI_PATH */
-                                       else if (sscanf (pos, HD5, server_url) == 1) {
-                                               if ((server_url[0] != '/') && (x = strrchr(orig_url, '/'))) {
-                                                       *x = '\0';
-                                                       asprintf (&server_url, "%s/%s", orig_url, server_url);
-                                               }
-                                               check_http ();
-                                       }                                       
-                                       pos += (size_t) strcspn (pos, "\r\n");
-                                       pos += (size_t) strspn (pos, "\r\n");
-                               } /* end while (pos) */
-                               printf (_("UNKNOWN - Could not find redirect location - %s%s"),
-                                       status_line, (display_html ? "</A>" : ""));
-                               exit (STATE_UNKNOWN);
-                       } /* end if (onredirect == STATE_DEPENDENT) */
-                       
+               if (strstr (status_line, "300") || strstr (status_line, "301") ||
+                   strstr (status_line, "302") || strstr (status_line, "303") ||
+                   strstr (status_line, "304") || strstr (status_line, "305") ||
+                   strstr (status_line, "306")) {
+
+                       if (onredirect == STATE_DEPENDENT)
+                               redir (header, status_line);
                        else if (onredirect == STATE_UNKNOWN)
                                printf (_("UNKNOWN"));
                        else if (onredirect == STATE_OK)
@@ -817,6 +746,149 @@ check_http (void)
 
 
 
+
+/* per RFC 2396 */
+#define HDR_LOCATION "%*[Ll]%*[Oo]%*[Cc]%*[Aa]%*[Tt]%*[Ii]%*[Oo]%*[Nn]: "
+#define URI_HTTP "%[HTPShtps]://"
+#define URI_HOST "%[-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
+#define URI_PORT ":%[0123456789]"
+#define URI_PATH "%[-_.!~*'();/?:@&=+$,%#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
+#define HD1 URI_HTTP URI_HOST URI_PORT URI_PATH
+#define HD2 URI_HTTP URI_HOST URI_PATH
+#define HD3 URI_HTTP URI_HOST URI_PORT
+#define HD4 URI_HTTP URI_HOST
+#define HD5 URI_PATH
+
+int
+redir (char *pos, char *status_line)
+{
+       int i = 0;
+       char *x;
+       char xx[2];
+       char type[6];
+       char *addr;
+       char port[6];
+       char *url;
+
+       addr = malloc (MAX_IPV4_HOSTLENGTH + 1);
+       if (addr == NULL)
+               die (STATE_UNKNOWN, _("ERROR: could not allocate addr\n"));
+       
+       url = malloc (strcspn (pos, "\r\n"));
+       if (url == NULL)
+               die (STATE_UNKNOWN, _("ERROR: could not allocate url\n"));
+
+       while (pos) {
+
+               if (sscanf (pos, "%[Ll]%*[Oo]%*[Cc]%*[Aa]%*[Tt]%*[Ii]%*[Oo]%*[Nn]:%n", xx, &i) > 0) {
+
+                       pos += i;
+                       pos += strspn (pos, " \t\r\n");
+
+                       /* URI_HTTP, URI_HOST, URI_PORT, URI_PATH */
+                       if (sscanf (pos, HD1, type, addr, port, url) == 4) {
+                               use_ssl = server_type_check (type);
+                               i = atoi (port);
+                       }
+
+                       /* URI_HTTP URI_HOST URI_PATH */
+                       else if (sscanf (pos, HD2, type, addr, url) == 3 ) { 
+                               use_ssl = server_type_check (type);
+                               i = server_port_check (use_ssl);
+                       }
+
+                       /* URI_HTTP URI_HOST URI_PORT */
+                       else if(sscanf (pos, HD3, type, addr, port) == 3) {
+                               strcpy (url, HTTP_URL);
+                               use_ssl = server_type_check (type);
+                               i = atoi (port);
+                       }
+
+                       /* URI_HTTP URI_HOST */
+                       else if(sscanf (pos, HD4, type, addr) == 2) {
+                               strcpy (url, HTTP_URL);
+                               use_ssl = server_type_check (type);
+                               i = server_port_check (use_ssl);
+                       }
+
+                       /* URI_PATH */
+                       else if (sscanf (pos, HD5, url) == 1) {
+                               /* relative url */
+                               if ((url[0] != '/')) {
+                                       if ((x = strrchr(url, '/')))
+                                               *x = '\0';
+                                       asprintf (&server_url, "%s/%s", server_url, url);
+                               }
+                               i = server_port;
+                               strcpy (type, server_type);
+                               strcpy (addr, host_name);
+                       }                                       
+
+                       else {
+                               die (STATE_UNKNOWN,
+                                                _("UNKNOWN - Could not parse redirect location - %s%s\n"),
+                                                pos, (display_html ? "</A>" : ""));
+                       }
+
+                       break;
+
+               } else {
+
+                       pos += (size_t) strcspn (pos, "\r\n");
+                       pos += (size_t) strspn (pos, "\r\n");
+                       if (strlen(pos) == 0) 
+                               die (STATE_UNKNOWN,
+                                                _("UNKNOWN - Could not find redirect location - %s%s\n"),
+                                                status_line, (display_html ? "</A>" : ""));
+
+               }
+
+       } /* end while (pos) */
+
+       if (++redir_depth > max_depth)
+               die (STATE_WARNING,
+                    _("WARNING - maximum redirection depth %d exceeded - %s://%s:%d%s%s\n"),
+                    max_depth, type, addr, i, url, (display_html ? "</A>" : ""));
+
+       if (server_port==i &&
+           !strcmp(server_address, addr) &&
+           (host_name && !strcmp(host_name, addr)) &&
+           !strcmp(server_url, url))
+               die (STATE_WARNING,
+                    _("WARNING - redirection creates an infinite loop - %s://%s:%d%s%s\n"),
+                    type, addr, i, url, (display_html ? "</A>" : ""));
+
+       server_port = i;
+       strcpy (server_type, type);
+       asprintf (&host_name, "%s", addr);
+       asprintf (&server_address, "%s", addr);
+       asprintf (&server_url, "%s", url);
+
+       return check_http ();
+}
+
+
+
+int
+server_type_check (const char *type)
+{
+       if (strcmp (type, "https"))
+               return FALSE;
+       else
+               return TRUE;
+}
+
+int
+server_port_check (int ssl_flag)
+{
+       if (ssl_flag)
+               return HTTPS_PORT;
+       else
+               return HTTP_PORT;
+}
+
+
+
 #ifdef HAVE_SSL
 int connect_SSL (void)
 {
@@ -920,7 +992,7 @@ check_certificate (X509 ** certificate)
 
        days_left = (mktime (&stamp) - time (NULL)) / 86400;
        snprintf
-               (timestamp, 16, "%02d/%02d/%04d %02d:%02d",
+               (timestamp, 17, "%02d/%02d/%04d %02d:%02d",
                 stamp.tm_mon + 1,
                 stamp.tm_mday, stamp.tm_year + 1900, stamp.tm_hour, stamp.tm_min);