From 6b28ae739b1ca9f20519f7522b52d055ce3a0902 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 10 Sep 2013 11:09:22 +0200 Subject: check_http: Support HTTP CONNECT method Add the -Y/--http-connect[=] option which tells check_http to use the HTTP CONNECT method for tunneling an HTTPS connection through a proxy server. This is a modified version of a patch provided by Mark Frost in SourceForge tracker item #2975393, updated for the current check_http code. Changes include: - Let the new --http-connect option imply --ssl. - Allow for specifying the server port the proxy should connect to. diff --git a/NEWS b/NEWS index 6c01776..17acce2 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,7 @@ This file documents the major additions and syntax changes between releases. New switch -E/--extended-perfdata for check_http to print additional performance data (Sebastian Nohn) New check_http -d option to specify a string to expect within the response headers New check_http -J/-K options for client certificate authentication support + New check_http -Y/--http-connect[=] option for tunneling SSL connections through proxies Add support for executing queries to check_pgsql Let check_pgsql accept a UNIX socket directory as hostname New check_pgsql -o option to specify additional connection parameters diff --git a/THANKS.in b/THANKS.in index 6118143..a6caa46 100644 --- a/THANKS.in +++ b/THANKS.in @@ -286,3 +286,4 @@ Fabio Rueda Gabriele Tozzi Sebastian Nohn Emmanuel Dreyfus +Mark Frost diff --git a/plugins/check_http.c b/plugins/check_http.c index c44bb3a..43c37e0 100644 --- a/plugins/check_http.c +++ b/plugins/check_http.c @@ -118,6 +118,8 @@ int use_ssl = FALSE; int use_sni = FALSE; int verbose = FALSE; int show_extended_perfdata = FALSE; +int http_connect = FALSE; +int connect_port = HTTPS_PORT; int sd; int min_page_len = 0; int max_page_len = 0; @@ -133,6 +135,7 @@ char *client_privkey = NULL; int process_arguments (int, char **); int check_http (void); void redir (char *pos, char *status_line); +int http_connect_through_proxy (char *host_name, int port, char *user_agent, int sd); int server_type_check(const char *type); int server_port_check(int ssl_flag); char *perfd_time (double microsec); @@ -209,6 +212,7 @@ process_arguments (int argc, char **argv) {"nohtml", no_argument, 0, 'n'}, {"ssl", optional_argument, 0, 'S'}, {"sni", no_argument, 0, SNI_OPTION}, + {"http-connect", optional_argument, 0, 'Y'}, {"post", required_argument, 0, 'P'}, {"method", required_argument, 0, 'j'}, {"IP-address", required_argument, 0, 'I'}, @@ -257,7 +261,7 @@ process_arguments (int argc, char **argv) } while (1) { - c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:d:e:p:s:R:r:u:f:C:J:K:nlLS::m:M:N:E", longopts, &option); + c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:Y::T:I:a:b:d:e:p:s:R:r:u:f:C:J:K:nlLS::m:M:N:E", longopts, &option); if (c == -1 || c == EOF) break; @@ -336,6 +340,13 @@ process_arguments (int argc, char **argv) client_privkey = optarg; goto enable_ssl; #endif + case 'Y': /* Use HTTP CONNECT */ +#ifdef HAVE_SSL + if (optarg != NULL && ((connect_port = atoi (optarg)) < 1 || connect_port > 65535)) + usage2 (_("Invalid HTTP CONNECT port number"), optarg); + http_connect = TRUE; + goto enable_ssl; +#endif case 'S': /* use SSL */ #ifdef HAVE_SSL enable_ssl: @@ -879,6 +890,8 @@ check_http (void) elapsed_time_connect = (double)microsec_connect / 1.0e6; if (use_ssl == TRUE) { gettimeofday (&tv_temp, NULL); + if (http_connect == TRUE && http_connect_through_proxy (host_name, connect_port, user_agent, sd) != STATE_OK) + die (STATE_CRITICAL, _("HTTP CRITICAL - Unable to open proxy tunnel TCP socket\n")); result = np_net_ssl_init_with_hostname_version_and_cert(sd, (use_sni ? host_name : NULL), ssl_version, client_cert, client_privkey); if (result != STATE_OK) return result; @@ -1369,6 +1382,41 @@ redir (char *pos, char *status_line) check_http (); } +/* start the HTTP CONNECT method exchange with a proxy host */ +int +http_connect_through_proxy (char *host_name, int port, char *user_agent, int sd) +{ + int result; + char *send_buffer=NULL; + char recv_buffer[MAX_INPUT_BUFFER]; + char *status_line; + char *status_code; + int http_status; + + asprintf( &send_buffer, "CONNECT %s:%d HTTP/1.0\r\nUser-agent: %s\r\n\r\n", host_name, port, user_agent); + + result = STATE_OK; + result = send_tcp_request (sd, send_buffer, recv_buffer, sizeof(recv_buffer)); + if (result != STATE_OK) + return result; + + status_line = recv_buffer; + status_line[strcspn(status_line, "\r\n")] = 0; + strip (status_line); + if (verbose) + printf ("HTTP_CONNECT STATUS: %s\n", status_line); + + status_code = strchr (status_line, ' ') + sizeof (char); + if (strspn (status_code, "1234567890") != 3) + die (STATE_CRITICAL, _("HTTP CRITICAL: HTTP_CONNECT Returns Invalid Status Line (%s)\n"), status_line); + + http_status = atoi (status_code); + + if (http_status != 200) + die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid HTTP Connect Proxy Status (%s)\n"), status_line); + + return STATE_OK; +} int server_type_check (const char *type) @@ -1479,6 +1527,10 @@ print_help (void) printf (" %s\n", "-K, --private-key=FILE"); printf (" %s\n", _("Name of file containing the private key (PEM format)")); printf (" %s\n", _("matching the client certificate")); + printf (" %s\n", "-Y, --http-connect=PORT"); + printf (" %s\n", _("Connect to a proxy using the HTTP CONNECT method (SSL tunnel).")); + printf (" %s\n", _("Implies -S. The optional PORT number specifies the port on the server the")); + printf (" %s\n\n", _("proxy should connect to (default: 443).")); #endif printf (" %s\n", "-e, --expect=STRING"); @@ -1589,7 +1641,7 @@ print_usage (void) { printf ("%s\n", _("Usage:")); printf (" %s -H | -I [-u ] [-p ]\n",progname); - printf (" [-J ] [-K ]\n"); + printf (" [-J ] [-K ] [-Y ]\n"); printf (" [-w ] [-c ] [-t ] [-L] [-E] [-a auth]\n"); printf (" [-b proxy_auth] [-f ]\n"); printf (" [-e ] [-d string] [-s string] [-l] [-r | -R ]\n"); -- cgit v0.10-9-g596f