]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Added --remote-random-hostname option.
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Sat, 22 Aug 2009 18:29:20 +0000 (18:29 +0000)
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Sat, 22 Aug 2009 18:29:20 +0000 (18:29 +0000)
git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@4843 e7ae566f-a301-0410-adde-c780ea21d3b5

misc.c
misc.h
options.c
socket.c
socket.h
version.m4

diff --git a/misc.c b/misc.c
index d9735bc114f3b9133070b8a9d410d8fe401dada9..33e676213d14d6af04ede5b0a9acc3a1905df779 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -1186,6 +1186,44 @@ create_temp_filename (const char *directory, const char *prefix, struct gc_arena
   return gen_path (directory, BSTR (&fname), gc);
 }
 
+/*
+ * Add a random string to first DNS label of hostname to prevent DNS caching.
+ * For example, foo.bar.gov would be modified to <random-chars>.foo.bar.gov.
+ * Of course, this requires explicit support in the DNS server.
+ */
+const char *
+hostname_randomize(const char *hostname, struct gc_arena *gc)
+{
+  const int n_rnd_bytes = 6;
+
+  char *hst = string_alloc(hostname, gc);
+  char *dot = strchr(hst, '.');
+
+  if (dot)
+    {
+      uint8_t rnd_bytes[n_rnd_bytes];
+      const char *rnd_str;
+      struct buffer hname = alloc_buf_gc (strlen(hostname)+sizeof(rnd_bytes)*2+4, gc);
+
+      *dot++ = '\0';
+      prng_bytes (rnd_bytes, sizeof (rnd_bytes));
+      rnd_str = format_hex_ex (rnd_bytes, sizeof (rnd_bytes), 40, 0, NULL, gc);
+      buf_printf(&hname, "%s-0x%s.%s", hst, rnd_str, dot);
+      return BSTR(&hname);
+    }
+  else
+    return hostname;
+}
+
+#else
+
+const char *
+hostname_randomize(const char *hostname, struct gc_arena *gc)
+{
+  msg (M_WARN, "WARNING: hostname randomization disabled when crypto support is not compiled");
+  return hostname;
+}
+
 #endif
 
 /*
diff --git a/misc.h b/misc.h
index 8bc1e8f848c90140df28d1d57a7f0d117186892f..bf51e897ae9fc91a1a6cb7f0c20b37ee5b4a13fd 100644 (file)
--- a/misc.h
+++ b/misc.h
@@ -230,6 +230,9 @@ bool delete_file (const char *filename);
 /* return true if pathname is absolute */
 bool absolute_pathname (const char *pathname);
 
+/* prepend a random prefix to hostname (need USE_CRYPTO) */
+const char *hostname_randomize(const char *hostname, struct gc_arena *gc);
+
 /*
  * Get and store a username/password
  */
index a83c6a2e1018c4b70a3404627a2bba4c5e997ebd..eba311b8685a9ab47462402d123fb188d9a77757 100644 (file)
--- a/options.c
+++ b/options.c
@@ -90,6 +90,7 @@ static const char usage_message[] =
   "--local host    : Local host name or ip address. Implies --bind.\n"
   "--remote host [port] : Remote host name or ip address.\n"
   "--remote-random : If multiple --remote options specified, choose one randomly.\n"
+  "--remote-random-hostname : Add a random string to remote DNS name.\n"
   "--mode m        : Major mode, m = 'p2p' (default, point-to-point) or 'server'.\n"
   "--proto p       : Use protocol p for communicating with peer.\n"
   "                  p = udp (default), tcp-server, or tcp-client\n"
@@ -4420,15 +4421,27 @@ add_option (struct options *options,
        }
       options->routes->flags |= RG_ENABLE;
     }
+  else if (streq (p[0], "remote-random-hostname"))
+    {
+      VERIFY_PERMISSION (OPT_P_GENERAL);
+      options->sockflags |= SF_HOST_RANDOMIZE;
+    }
   else if (streq (p[0], "setenv") && p[1])
     {
       VERIFY_PERMISSION (OPT_P_GENERAL);
-      if (streq (p[1], "FORWARD_COMPATIBLE") && p[2] && streq (p[2], "1"))
+      if (streq (p[1], "REMOTE_RANDOM_HOSTNAME"))
+       {
+         options->sockflags |= SF_HOST_RANDOMIZE;
+       }
+      else
        {
-         options->forward_compatible = true;
-         msglevel_fc = msglevel_forward_compatible (options, msglevel);
+         if (streq (p[1], "FORWARD_COMPATIBLE") && p[2] && streq (p[2], "1"))
+           {
+             options->forward_compatible = true;
+             msglevel_fc = msglevel_forward_compatible (options, msglevel);
+           }
+         setenv_str (es, p[1], p[2] ? p[2] : "");
        }
-      setenv_str (es, p[1], p[2] ? p[2] : "");
     }
   else if (streq (p[0], "setenv-safe") && p[1])
     {
index f3407bb6473678b2fb8f93951e0394439f8696df..fecc39837b0353cfa31564518ee034bdb625185f 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -32,6 +32,7 @@
 #include "plugin.h"
 #include "ps.h"
 #include "manage.h"
+#include "misc.h"
 
 #include "memdbg.h"
 
@@ -42,6 +43,19 @@ const int proto_overhead[] = { /* indexed by PROTO_x */
   IPv4_TCP_HEADER_SIZE
 };
 
+/*
+ * Convert sockflags/getaddr_flags into getaddr_flags
+ */
+static unsigned int
+sf2gaf(const unsigned int getaddr_flags,
+       const unsigned int sockflags)
+{
+  if (sockflags & SF_HOST_RANDOMIZE)
+    return getaddr_flags | GETADDR_RANDOMIZE;
+  else
+    return getaddr_flags;
+}
+
 /*
  * Functions related to the translation of DNS names to IP addresses.
  */
@@ -79,6 +93,10 @@ getaddr (unsigned int flags,
   int status;
   int sigrec = 0;
   int msglevel = (flags & GETADDR_FATAL) ? M_FATAL : D_RESOLVE_ERRORS;
+  struct gc_arena gc = gc_new ();
+
+  if (flags & GETADDR_RANDOMIZE)
+    hostname = hostname_randomize(hostname, &gc);
 
   if (flags & GETADDR_MSG_VIRT_OUT)
     msglevel |= M_MSG_VIRT_OUT;
@@ -225,6 +243,7 @@ getaddr (unsigned int flags,
       msg (level, "RESOLVE: signal received during DNS resolution attempt");
     }
 
+  gc_free (&gc);
   return (flags & GETADDR_HOST_ORDER) ? ntohl (ia.s_addr) : ia.s_addr;
 }
 
@@ -359,12 +378,13 @@ mac_addr_safe (const char *mac_addr)
 static void
 update_remote (const char* host,
               struct openvpn_sockaddr *addr,
-              bool *changed)
+              bool *changed,
+              const unsigned int sockflags)
 {
   if (host && addr)
     {
       const in_addr_t new_addr = getaddr (
-                                         GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE,
+                                         sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sockflags),
                                          host,
                                          1,
                                          NULL,
@@ -728,7 +748,7 @@ socket_listen_accept (socket_descriptor_t sd,
 
       if (socket_defined (new_sd))
        {
-         update_remote (remote_dynamic, &remote_verify, remote_changed);
+         update_remote (remote_dynamic, &remote_verify, remote_changed, 0);
          if (addr_defined (&remote_verify)
              && !addr_match (&remote_verify, &act->dest))
            {
@@ -858,6 +878,7 @@ socket_connect (socket_descriptor_t *sd,
                const int connect_retry_seconds,
                const int connect_timeout,
                const int connect_retry_max,
+               const unsigned int sockflags,
                volatile int *signal_received)
 {
   struct gc_arena gc = gc_new ();
@@ -919,7 +940,7 @@ socket_connect (socket_descriptor_t *sd,
       *sd = create_socket_tcp ();
       if (bind_local)
         socket_bind (*sd, local, "TCP Client");
-      update_remote (remote_dynamic, remote, remote_changed);
+      update_remote (remote_dynamic, remote, remote_changed, sockflags);
     }
 
   msg (M_INFO, "TCP connection established with %s", 
@@ -1023,7 +1044,7 @@ resolve_remote (struct link_socket *sock,
 
          if (sock->remote_host)
            {
-             unsigned int flags = GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE;
+             unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags);
              int retry = 0;
              bool status = false;
 
@@ -1384,6 +1405,7 @@ link_socket_init_phase2 (struct link_socket *sock,
                            sock->connect_retry_seconds,
                            sock->connect_timeout,
                            sock->connect_retry_max,
+                           sock->sockflags,
                            signal_received);
 
            if (*signal_received)
@@ -1432,6 +1454,7 @@ link_socket_init_phase2 (struct link_socket *sock,
                          sock->connect_retry_seconds,
                          sock->connect_timeout,
                          sock->connect_retry_max,
+                         sock->sockflags,
                          signal_received);
 
          if (*signal_received)
index e412f032b3c0c5ff07af8db1e50997c586139854..6877e665a79019823f09b0ba2db98b65310f7657 100644 (file)
--- a/socket.h
+++ b/socket.h
@@ -198,6 +198,7 @@ struct link_socket
 # define SF_USE_IP_PKTINFO (1<<0)
 # define SF_TCP_NODELAY (1<<1)
 # define SF_PORT_SHARE (1<<2)
+# define SF_HOST_RANDOMIZE (1<<3)
   unsigned int sockflags;
 
   /* for stream sockets */
@@ -447,6 +448,7 @@ bool unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int *
 #define GETADDR_MSG_VIRT_OUT          (1<<6)
 #define GETADDR_TRY_ONCE              (1<<7)
 #define GETADDR_UPDATE_MANAGEMENT_STATE (1<<8)
+#define GETADDR_RANDOMIZE             (1<<9)
 
 in_addr_t getaddr (unsigned int flags,
                   const char *hostname,
index 5c84929e36ddf2db944a987c96690cbd04663fcd..dde430da5543ff075f3cb61535374ab4ffd7a8fb 100644 (file)
@@ -1,5 +1,5 @@
 dnl define the OpenVPN version
-define(PRODUCT_VERSION,[2.1_rc19])
+define(PRODUCT_VERSION,[2.1_rc19a])
 dnl define the TAP version
 define(PRODUCT_TAP_ID,[tap0901])
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])