[monitoring-plugins] check_curl: rewrite connect_to / host headers

Sven Nierlein git at monitoring-plugins.org
Thu Oct 25 10:40:16 CEST 2018


 Module: monitoring-plugins
 Branch: feature_check_curl
 Commit: 70d36a729e2bc0ecfb24751074663c21160f02f4
 Author: Sven Nierlein <sven at nierlein.de>
   Date: Thu Oct 25 10:29:48 2018 +0200
    URL: https://www.monitoring-plugins.org/repositories/monitoring-plugins/commit/?id=70d36a7

check_curl: rewrite connect_to / host headers

since CURLOPT_CONNECT_TO is only available in later curl versions, we do it the other way round now and
set the url from the address we want to connect to and then set the host header accordingly.

---

 plugins/check_curl.c   | 49 ++++++++++++++++++++++---------------------------
 plugins/t/check_curl.t | 14 +++++++++++++-
 2 files changed, 35 insertions(+), 28 deletions(-)

diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index 4d37891..7a516a9 100644
--- a/plugins/check_curl.c
+++ b/plugins/check_curl.c
@@ -365,25 +365,22 @@ check_http (void)
   handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, socket_timeout), "CURLOPT_CONNECTTIMEOUT");
   handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_TIMEOUT, socket_timeout), "CURLOPT_TIMEOUT");
 
-  /* compose URL: must be the host_name, only if not given take the IP address. */
-  if ((use_ssl == FALSE && virtual_port == HTTP_PORT) ||
-      (use_ssl == TRUE && virtual_port == HTTPS_PORT))
-    snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s%s", use_ssl ? "https" : "http",
-      host_name ? host_name : server_address, server_url);
-  else
-    snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", use_ssl ? "https" : "http",
-      host_name ? host_name : server_address, virtual_port, server_url);
+  /* compose URL: use the address we want to connect to, set Host: header later */
+  snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s",
+      use_ssl ? "https" : "http",
+      server_address,
+      server_port,
+      server_url
+  );
+
+  if (verbose>=1)
+    printf ("* curl CURLOPT_URL: %s\n", url);
   handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_URL, url), "CURLOPT_URL");
 
   /* cURL does certificate checking against the host name from the URL above
    * So we use CURLOPT_CONNECT_TO or CURLOPT_RESOLVE to handle differing
    * host names and/or ports */
-#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 49, 0)
-  snprintf (server_ip, DEFAULT_BUFFER_SIZE, "%s:%d:%s:%d", host_name ? host_name : server_address, virtual_port, server_address, server_port);
-  server_ips = curl_slist_append (server_ips, server_ip);
-  handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CONNECT_TO, server_ips), "CURLOPT_CONNECT_TO");
-
-#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 3)
+#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 3)
   if (host_name && strcmp (host_name, server_address)) {
     snprintf (server_ip, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, server_address);
     server_ips = curl_slist_append (server_ips, server_ip);
@@ -411,8 +408,17 @@ check_http (void)
       handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CUSTOMREQUEST, http_method), "CURLOPT_CUSTOMREQUEST");
   }
 
+  /* check if Host header is explicitly set in options */
+  if (http_opt_headers_count) {
+    for (i = 0; i < http_opt_headers_count ; i++) {
+      if (strncmp(http_opt_headers[i], "Host:", 5) == 0) {
+        force_host_header = http_opt_headers[i];
+      }
+    }
+  }
+
   /* set hostname (virtual hosts), not needed if CURLOPT_CONNECT_TO is used, but left in anyway */
-  if(host_name != NULL) {
+  if(host_name != NULL && force_host_header == NULL) {
     if((virtual_port != HTTP_PORT && !use_ssl) || (virtual_port != HTTPS_PORT && use_ssl)) {
       snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", host_name, virtual_port);
     } else {
@@ -425,22 +431,11 @@ check_http (void)
   snprintf (http_header, DEFAULT_BUFFER_SIZE, "Connection: close");
   header_list = curl_slist_append (header_list, http_header);
 
-  /* check if Host header is explicitly set in options */
-  if (http_opt_headers_count) {
-    for (i = 0; i < http_opt_headers_count ; i++) {
-      if (strncmp(http_opt_headers[i], "Host:", 5) == 0) {
-        force_host_header = http_opt_headers[i];
-      }
-    }
-  }
-
   /* attach additional headers supplied by the user */
   /* optionally send any other header tag */
   if (http_opt_headers_count) {
     for (i = 0; i < http_opt_headers_count ; i++) {
-      if (force_host_header != http_opt_headers[i]) {
-        header_list = curl_slist_append (header_list, http_opt_headers[i]);
-      }
+      header_list = curl_slist_append (header_list, http_opt_headers[i]);
     }
     /* This cannot be free'd here because a redirection will then try to access this and segfault */
     /* Covered in a testcase in tests/check_http.t */
diff --git a/plugins/t/check_curl.t b/plugins/t/check_curl.t
index e67fafb..050416c 100644
--- a/plugins/t/check_curl.t
+++ b/plugins/t/check_curl.t
@@ -9,7 +9,7 @@ use Test::More;
 use POSIX qw/mktime strftime/;
 use NPTest;
 
-plan tests => 49;
+plan tests => 57;
 
 my $successOutput = '/OK.*HTTP.*second/';
 
@@ -78,15 +78,27 @@ like( $res->output, "/cURL returned 6 - Couldn't resolve host name/", "Output OK
 # host header checks
 $res = NPTest->testCmd("./$plugin -v -H $host_tcp_http");
 like( $res->output, '/^Host: '.$host_tcp_http.'\s*$/ms', "Host Header OK" );
+like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
 
 $res = NPTest->testCmd("./$plugin -v -H $host_tcp_http -p 80");
 like( $res->output, '/^Host: '.$host_tcp_http.'\s*$/ms', "Host Header OK" );
+like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
 
 $res = NPTest->testCmd("./$plugin -v -H $host_tcp_http:8080 -p 80");
 like( $res->output, '/^Host: '.$host_tcp_http.':8080\s*$/ms', "Host Header OK" );
+like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
 
 $res = NPTest->testCmd("./$plugin -v -H $host_tcp_http:8080 -p 80");
 like( $res->output, '/^Host: '.$host_tcp_http.':8080\s*$/ms', "Host Header OK" );
+like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
+
+$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http:8080 -p 80 -k 'Host: testhost:8001'");
+like( $res->output, '/^Host: testhost:8001\s*$/ms', "Host Header OK" );
+like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
+
+$res = NPTest->testCmd("./$plugin -v -I $host_tcp_http -p 80 -k 'Host: testhost:8001'");
+like( $res->output, '/^Host: testhost:8001\s*$/ms', "Host Header OK" );
+like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
 
 SKIP: {
         skip "No internet access", 3 if $internet_access eq "no";



More information about the Commits mailing list