[client] Added cipherdyne.com backup check in -R mode.
authorMichael Rash <mbr@cipherdyne.org>
Thu, 16 Aug 2012 02:49:29 +0000 (22:49 -0400)
committerMichael Rash <mbr@cipherdyne.org>
Thu, 16 Aug 2012 02:49:29 +0000 (22:49 -0400)
Added backup check against a cipherdyne.com 'myip' cgi instance in -R mode if
the normal check against cipherdyne.org fails.

ChangeLog
client/fwknop.c
client/fwknop_common.h
client/http_resolve_host.c

index 6bcdbd0..49e0f7b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -19,6 +19,8 @@ fwknop-2.0.2 (08//2012):
       remote webserver IP resolution mode (-R).  Previously IP resolution
       could fail if HTTP headers were transferred separately from the data
       (for whatever reason).  Jonathan Schulz submitted a patch for this.
+    - [client] Added backup check against a cipherdyne.com 'myip' cgi instance
+      in -R mode if the normal check against cipherdyne.org fails.
     - [server] Bug fix to implement FLUSH_IPT_AT_INIT and FLUSH_IPT_AT_EXIT
       functionality.  These are enabled by default, and now iptables rules
       added by fwknopd can be made persistant by setting these variables to
index 1d1f733..97192b6 100644 (file)
@@ -152,11 +152,13 @@ main(int argc, char **argv)
          * if this fails, consider it fatal.
         */
         if (options.resolve_ip_http)
+        {
             if(resolve_ip_http(&options) < 0)
             {
                 fko_destroy(ctx);
                 return(EXIT_FAILURE);
             }
+        }
 
         /* Set a message string by combining the allow IP and the
          * port/protocol.  The fwknopd server allows no port/protocol
index 5d7e8ef..bdbe5b9 100644 (file)
   *             for now.
 */
 #define HTTP_RESOLVE_HOST           "www.cipherdyne.org"
+#define HTTP_BACKUP_RESOLVE_HOST    "www.cipherdyne.com"
 #define HTTP_RESOLVE_URL            "/cgi-bin/myip"
 #define HTTP_MAX_REQUEST_LEN        2000
 #define HTTP_MAX_RESPONSE_LEN       2000
-#define HTTP_MAX_USER_AGENT_LEN     50
+#define HTTP_MAX_USER_AGENT_LEN     100
 #define MAX_HOSTNAME_LEN            70
 #define MAX_URL_HOST_LEN            256
 #define MAX_URL_PATH_LEN            1024
index a9b7be1..8312fbc 100644 (file)
@@ -52,90 +52,12 @@ struct url
 };
 
 static int
-parse_url(char *res_url, struct url* url)
-{
-    char *s_ndx, *e_ndx;
-    int  tlen, tlen_offset, port;
-
-    /* https is not supported.
-    */
-    if(strncasecmp(res_url, "https", 5) == 0)
-    {
-        fprintf(stderr, "https is not yet supported for http-resolve-ip.\n");
-        return(-1);
-    }
-
-    /* Strip off http:// portion if necessary
-    */
-    if(strncasecmp(res_url, "http://", 7) == 0)
-        s_ndx = res_url + 7;
-    else
-        s_ndx = res_url;
-
-    /* Look for a colon in case an alternate port was specified.
-    */
-    e_ndx = strchr(s_ndx, ':');
-    if(e_ndx != NULL)
-    {
-        port = atoi(e_ndx+1);
-        if(port < 1 || port > MAX_PORT)
-        {
-            fprintf(stderr, "resolve-url port value is invalid.\n");
-            return(-1);
-        }
-
-        sprintf(url->port, "%u", port);
-
-        /* Get the offset we need to skip the port portion when we
-         * extract the hostname part.
-        */
-        tlen_offset = strlen(url->port)+1;
-    }
-    else
-    {
-        strlcpy(url->port, "80", 3);
-        tlen_offset = 0;
-    }
-
-    e_ndx = strchr(s_ndx, '/');
-    if(e_ndx == NULL)
-        tlen = strlen(s_ndx)+1;
-    else
-        tlen = (e_ndx-s_ndx)+1;
-
-    tlen -= tlen_offset;
-
-    if(tlen > MAX_URL_HOST_LEN)
-    {
-        fprintf(stderr, "resolve-url hostname portion is too large.\n");
-        return(-1);
-    }
-    strlcpy(url->host, s_ndx, tlen);
-
-    if(e_ndx != NULL)
-    {
-        if(strlen(e_ndx) > MAX_URL_PATH_LEN)
-        {
-            fprintf(stderr, "resolve-url path portion is too large.\n");
-            return(-1);
-        }
-
-        strlcpy(url->path, e_ndx, MAX_URL_PATH_LEN);
-    }
-    else
-        *(url->path) = '\0';
-
-    return(0);
-}
-
-int
-resolve_ip_http(fko_cli_options_t *options)
+try_url(struct url *url, fko_cli_options_t *options)
 {
     int     sock, res, error, http_buf_len, i;
     int     bytes_read = 0, position = 0;
     int     o1, o2, o3, o4;
     struct  addrinfo *result, *rp, hints;
-    struct  url url;
     char    http_buf[HTTP_MAX_REQUEST_LEN];
     char    http_response[HTTP_MAX_RESPONSE_LEN] = {0};
     char   *ndx;
@@ -153,28 +75,15 @@ resolve_ip_http(fko_cli_options_t *options)
     }
 #endif
 
-    if(options->resolve_url != NULL)
-    {
-        if(parse_url(options->resolve_url, &url) < 0)
-        {
-            fprintf(stderr, "Error parsing resolve-url\n");
-            return(-1);
-        }
-    } else {
-        strlcpy(url.port, "80", 3);
-        strlcpy(url.host, HTTP_RESOLVE_HOST, MAX_URL_HOST_LEN);
-        strlcpy(url.path, HTTP_RESOLVE_URL, MAX_URL_PATH_LEN);
-    }
-
     /* Build our HTTP request to resolve the external IP (this is similar to
      * to contacting whatismyip.org, but using a different URL).
     */
     snprintf(http_buf, HTTP_MAX_REQUEST_LEN,
         "GET %s HTTP/1.0\r\nUser-Agent: %s\r\nAccept: */*\r\n"
         "Host: %s\r\nConnection: close\r\n\r\n",
-        url.path,
+        url->path,
         options->http_user_agent,
-        url.host
+        url->host
     );
 
     http_buf_len = strlen(http_buf);
@@ -185,7 +94,7 @@ resolve_ip_http(fko_cli_options_t *options)
     hints.ai_socktype = SOCK_STREAM;
     hints.ai_protocol = IPPROTO_TCP;
 
-    error = getaddrinfo(url.host, url.port, &hints, &result);
+    error = getaddrinfo(url->host, url->port, &hints, &result);
     if (error != 0)
     {
         fprintf(stderr, "error in getaddrinfo: %s\n", gai_strerror(error));
@@ -282,19 +191,135 @@ resolve_ip_http(fko_cli_options_t *options)
     {
         strlcpy(options->allow_ip_str, ndx, MAX_IPV4_STR_LEN);
 
+        if(options->verbose > 1)
+            printf("\nHTTP response: %s\n", http_response);
+
         if(options->verbose)
-            printf("Resolved external IP (via http://%s%s) as: %s\n",
-                    url.host,
-                    url.path,
+            printf("\n[+] Resolved external IP (via http://%s%s) as: %s\n",
+                    url->host,
+                    url->path,
                     options->allow_ip_str);
 
-        return(0);
+        return(1);
     }
     else
     {
-        fprintf(stderr, "Invalid IP (%s) in HTTP response.\n", ndx);
+        fprintf(stderr, "Invalid IP (%s) in HTTP response:\n\n%s\n",
+            ndx, http_response);
         return(-1);
     }
 }
 
+static int
+parse_url(char *res_url, struct url* url)
+{
+    char *s_ndx, *e_ndx;
+    int  tlen, tlen_offset, port;
+
+    /* https is not supported.
+    */
+    if(strncasecmp(res_url, "https", 5) == 0)
+    {
+        fprintf(stderr, "https is not yet supported for http-resolve-ip.\n");
+        return(-1);
+    }
+
+    /* Strip off http:// portion if necessary
+    */
+    if(strncasecmp(res_url, "http://", 7) == 0)
+        s_ndx = res_url + 7;
+    else
+        s_ndx = res_url;
+
+    /* Look for a colon in case an alternate port was specified.
+    */
+    e_ndx = strchr(s_ndx, ':');
+    if(e_ndx != NULL)
+    {
+        port = atoi(e_ndx+1);
+        if(port < 1 || port > MAX_PORT)
+        {
+            fprintf(stderr, "resolve-url port value is invalid.\n");
+            return(-1);
+        }
+
+        sprintf(url->port, "%u", port);
+
+        /* Get the offset we need to skip the port portion when we
+         * extract the hostname part.
+        */
+        tlen_offset = strlen(url->port)+1;
+    }
+    else
+    {
+        strlcpy(url->port, "80", 3);
+        tlen_offset = 0;
+    }
+
+    e_ndx = strchr(s_ndx, '/');
+    if(e_ndx == NULL)
+        tlen = strlen(s_ndx)+1;
+    else
+        tlen = (e_ndx-s_ndx)+1;
+
+    tlen -= tlen_offset;
+
+    if(tlen > MAX_URL_HOST_LEN)
+    {
+        fprintf(stderr, "resolve-url hostname portion is too large.\n");
+        return(-1);
+    }
+    strlcpy(url->host, s_ndx, tlen);
+
+    if(e_ndx != NULL)
+    {
+        if(strlen(e_ndx) > MAX_URL_PATH_LEN)
+        {
+            fprintf(stderr, "resolve-url path portion is too large.\n");
+            return(-1);
+        }
+
+        strlcpy(url->path, e_ndx, MAX_URL_PATH_LEN);
+    }
+    else
+        *(url->path) = '\0';
+
+    return(0);
+}
+
+int
+resolve_ip_http(fko_cli_options_t *options)
+{
+    int     res;
+    struct  url url;
+
+    if(options->resolve_url != NULL)
+    {
+        if(parse_url(options->resolve_url, &url) < 0)
+        {
+            fprintf(stderr, "Error parsing resolve-url\n");
+            return(-1);
+        }
+
+        res = try_url(&url, options);
+
+    } else {
+        strlcpy(url.port, "80", 3);
+        strlcpy(url.host, HTTP_RESOLVE_HOST, MAX_URL_HOST_LEN);
+        strlcpy(url.path, HTTP_RESOLVE_URL, MAX_URL_PATH_LEN);
+
+        res = try_url(&url, options);
+        if(res != 1)
+        {
+            /* try the backup url (just switches the host to cipherdyne.com)
+            */
+            strlcpy(url.host, HTTP_BACKUP_RESOLVE_HOST, MAX_URL_HOST_LEN);
+
+            sleep(2);
+            res = try_url(&url, options);
+        }
+    }
+    return(res);
+}
+
 /***EOF***/