]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
New try at AUTO_USERID.
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Mon, 13 Nov 2006 09:44:10 +0000 (09:44 +0000)
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Mon, 13 Nov 2006 09:44:10 +0000 (09:44 +0000)
Implemented AUTO_USERID using
MD5(MAC address(primary network adapter)).
Currently implemented for Linux and Windows.

Basically if ENABLE_AUTO_USERID is defined,
the --auth-user-pass option will not prompt
for username/password, but will rather generate
a unique username and blank password.

git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@1459 e7ae566f-a301-0410-adde-c780ea21d3b5

errlevel.h
misc.c
misc.h
route.c
route.h
ssl.c
syshead.h
tun.c
tun.h

index 426a4ac8007ed6ec909964b573b518c64be4a3e9..9f420ae9e6347ade3f7266eb94b78747ca427495 100644 (file)
 #define D_PACKET_TRUNC_DEBUG LOGLEV(7, 70, M_DEBUG)  /* PACKET_TRUNCATION_CHECK verbose */
 #define D_PING               LOGLEV(7, 70, M_DEBUG)  /* PING send/receive messages */
 #define D_PS_PROXY_DEBUG     LOGLEV(7, 70, M_DEBUG)  /* port share proxy debug */
+#define D_AUTO_USERID        LOGLEV(7, 70, M_DEBUG)  /* AUTO_USERID debugging */
 
 #define D_HANDSHAKE_VERBOSE  LOGLEV(8, 70, M_DEBUG)  /* show detailed description of each handshake */
 #define D_TLS_DEBUG_MED      LOGLEV(8, 70, M_DEBUG)  /* limited info from tls_session routines */
diff --git a/misc.c b/misc.c
index f02385ae2fa6baf7f21155cadb67d4fe67bbc3ad..c6423fa806d9d656d2bb62e058be904667cc6845 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -39,6 +39,8 @@
 #include "plugin.h"
 #include "options.h"
 #include "manage.h"
+#include "crypto.h"
+#include "route.h"
 
 #include "memdbg.h"
 
@@ -1311,6 +1313,64 @@ get_user_pass (struct user_pass *up,
   return true;
 }
 
+#if AUTO_USERID
+
+static const char *
+get_platform_prefix (void)
+{
+#if defined(TARGET_LINUX)
+  return "L";
+#elif defined(TARGET_SOLARIS)
+  return "S";
+#elif defined(TARGET_OPENBSD)
+  return "O";
+#elif defined(TARGET_DARWIN)
+  return "M";
+#elif defined(TARGET_NETBSD)
+  return "N";
+#elif defined(TARGET_FREEBSD)
+  return "F";
+#elif defined(WIN32)
+  return "W";
+#else
+  return "X";
+#endif
+}
+
+void
+get_user_pass_auto_userid (struct user_pass *up)
+{
+  struct gc_arena gc = gc_new ();
+  MD5_CTX ctx;
+  struct buffer buf;
+  uint8_t macaddr[6];
+  static uint8_t digest [MD5_DIGEST_LENGTH];
+  static const uint8_t hashprefix[] = "AUTO_USERID_DIGEST";
+
+  CLEAR (*up);
+  buf_set_write (&buf, (uint8_t*)up->username, USER_PASS_LEN);
+  buf_printf (&buf, "%s", get_platform_prefix ());
+  if (get_default_gateway_mac_addr (macaddr))
+    {
+      dmsg (D_AUTO_USERID, "GUPAU: macaddr=%s", format_hex_ex (macaddr, sizeof (macaddr), 0, 1, ":", &gc));
+      MD5_Init (&ctx);
+      MD5_Update (&ctx, hashprefix, sizeof (hashprefix) - 1);
+      MD5_Update (&ctx, macaddr, sizeof (macaddr));
+      MD5_Final (digest, &ctx);
+      buf_printf (&buf, "%s", format_hex_ex (digest, sizeof (digest), 0, 256, " ", &gc));
+    }
+  else
+    {
+      buf_printf (&buf, "UNKNOWN");
+    }
+  up->defined = true;
+  gc_free (&gc);
+
+  dmsg (D_AUTO_USERID, "GUPAU: AUTO_USERID: '%s'", up->username);
+}
+
+#endif
+
 void
 purge_user_pass (struct user_pass *up, const bool force)
 {
diff --git a/misc.h b/misc.h
index fa13dafefc2d7933af7822bb2676e7ca60ec2a3b..ac761857b5b26bcfc306f20074fc5b2a56217acf 100644 (file)
--- a/misc.h
+++ b/misc.h
@@ -264,4 +264,8 @@ void openvpn_sleep (const int n);
 
 void configure_path (void);
 
+#if AUTO_USERID
+void get_user_pass_auto_userid (struct user_pass *up);
+#endif
+
 #endif
diff --git a/route.c b/route.c
index b041b3e53d335a994ef1641612fdcbd7b27d4178..354a10cbb7450bba485f2d0ff99ebe76f0c90131 100644 (file)
--- a/route.c
+++ b/route.c
@@ -2017,3 +2017,152 @@ get_bypass_addresses (struct route_bypass *rb, const unsigned int flags)
 }
 
 #endif
+
+#if AUTO_USERID
+
+#if defined(TARGET_LINUX)
+
+bool
+get_default_gateway_mac_addr (unsigned char *macaddr)
+{
+  struct ifreq *ifr, *ifend;
+  in_addr_t ina, mask;
+  struct ifreq ifreq;
+  struct ifconf ifc;
+  struct ifreq ifs[20]; // Maximum number of interfaces to scan
+  int sd = -1;
+  in_addr_t gwip = 0;
+  bool ret = false;
+
+  if (!get_default_gateway (&gwip))
+    {
+      msg (M_WARN, "GDGMA: get_default_gateway failed");
+      goto err;
+    }
+
+  if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
+    {
+      msg (M_WARN, "GDGMA: socket() failed");
+      goto err;
+    }
+
+  ifc.ifc_len = sizeof (ifs);
+  ifc.ifc_req = ifs;
+  if (ioctl (sd, SIOCGIFCONF, &ifc) < 0)
+    {
+      msg (M_WARN, "GDGMA: ioctl(SIOCGIFCONF) failed");
+      goto err;
+    }
+
+  /* scan through interface list */
+  ifend = ifs + (ifc.ifc_len / sizeof (struct ifreq));
+  for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
+    {
+      if (ifr->ifr_addr.sa_family == AF_INET)
+       {
+         ina = ntohl(((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr);
+         strncpynt (ifreq.ifr_name, ifr->ifr_name, sizeof (ifreq.ifr_name));
+
+         dmsg (D_AUTO_USERID, "GDGMA: %s", ifreq.ifr_name);
+
+         /* check that the interface is up, and not point-to-point or loopback */
+         if (ioctl (sd, SIOCGIFFLAGS, &ifreq) < 0)
+           {
+             dmsg (D_AUTO_USERID, "GDGMA: SIOCGIFFLAGS(%s) failed", ifreq.ifr_name);
+             continue;
+           }
+
+         if ((ifreq.ifr_flags & (IFF_UP|IFF_LOOPBACK)) != IFF_UP)
+           {
+             dmsg (D_AUTO_USERID, "GDGMA: interface %s is down or loopback", ifreq.ifr_name);
+             continue;
+           }
+
+         /* get interface netmask and check for correct subnet */
+         if (ioctl (sd, SIOCGIFNETMASK, &ifreq) < 0)
+           {
+             dmsg (D_AUTO_USERID, "GDGMA: SIOCGIFNETMASK(%s) failed", ifreq.ifr_name);
+             continue;
+           }
+
+         mask = ntohl(((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
+         if (((gwip ^ ina) & mask) != 0)
+           {
+             dmsg (D_AUTO_USERID, "GDGMA: gwip=0x%08x ina=0x%08x mask=0x%08x",
+                   (unsigned int)gwip,
+                   (unsigned int)ina,
+                   (unsigned int)mask);
+             continue;
+           }
+         break;
+       }
+    }
+  if (ifr >= ifend)
+    {
+      msg (M_WARN, "GDGMA: couldn't find gw interface");
+      goto err;
+    }
+
+  /* now get the hardware address. */
+  memset (&ifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));
+  if (ioctl (sd, SIOCGIFHWADDR, &ifreq) < 0)
+    {
+      msg (M_WARN, "GDGMA: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
+      goto err;
+    }
+
+  memcpy (macaddr, &ifreq.ifr_hwaddr.sa_data, 6);
+  ret = true;
+
+ err:
+  if (sd >= 0)
+    close (sd);
+  return ret;
+}
+
+#elif defined(WIN32)
+
+bool
+get_default_gateway_mac_addr (unsigned char *macaddr)
+{
+  struct gc_arena gc = gc_new ();
+  const IP_ADAPTER_INFO *adapters = get_adapter_info_list (&gc);
+  in_addr_t gwip = 0;
+  DWORD a_index;
+  const IP_ADAPTER_INFO *ai;
+
+  if (!get_default_gateway (&gwip))
+    {
+      msg (M_WARN, "GDGMA: get_default_gateway failed");
+      goto err;
+    }
+
+  a_index = adapter_index_of_ip (adapters, gwip, NULL);
+  ai = get_adapter (adapters, a_index);
+
+  if (!ai)
+    {
+      msg (M_WARN, "GDGMA: couldn't find gw interface");
+      goto err;
+    }
+
+  memcpy (macaddr, ai->Address, 6);
+
+  gc_free (&gc);
+  return true;
+
+ err:
+  gc_free (&gc);
+  return false;
+}
+
+#else
+
+bool
+get_default_gateway_mac_addr (unsigned char *macaddr)
+{
+  return false;
+}
+
+#endif
+#endif /* AUTO_USERID */
diff --git a/route.h b/route.h
index fc27a5a5731f76cfbb17af9d9a5602e8bf4e03ff..6630fed7677030c3f6a52eb0684ed0c5641965ad 100644 (file)
--- a/route.h
+++ b/route.h
@@ -150,6 +150,10 @@ void delete_routes (struct route_list *rl,
 
 void setenv_routes (struct env_set *es, const struct route_list *rl);
 
+#if AUTO_USERID
+bool get_default_gateway_mac_addr (unsigned char *macaddr);
+#endif
+
 #ifdef ENABLE_DEBUG
 void print_route_options (const struct route_option_list *rol,
                          int level);
diff --git a/ssl.c b/ssl.c
index 3f0c664b62917ec6d2a0c59ea063a9a5f82c3833..41564ba21698bb1836b11a31056dbe5b975c2e50 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -296,7 +296,13 @@ auth_user_pass_setup (const char *auth_file)
 {
   auth_user_pass_enabled = true;
   if (!auth_user_pass.defined)
-    get_user_pass (&auth_user_pass, auth_file, UP_TYPE_AUTH, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE);
+    {
+#if AUTO_USERID
+      get_user_pass_auto_userid (&auth_user_pass);
+#else
+      get_user_pass (&auth_user_pass, auth_file, UP_TYPE_AUTH, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE);
+#endif
+    }
 }
 
 /*
index f67b4c005a76b56fc1fbc8460c32ce5346dcb894..2a29ee025de2007652396b25a8631454118c751b 100644 (file)
--- a/syshead.h
+++ b/syshead.h
@@ -515,4 +515,13 @@ socket_defined (const socket_descriptor_t sd)
 #define CONNECT_NONBLOCK
 #endif
 
+/*
+ * Do we have the capability to support the AUTO_USERID feature? 
+ */
+#if defined(ENABLE_AUTO_USERID)
+#define AUTO_USERID 1
+#else
+#define AUTO_USERID 0
+#endif
+
 #endif
diff --git a/tun.c b/tun.c
index f0c2d49440de4413e8dcdb616750de5ebdc3684d..e305ee9864be78e4d6eeca0cb88549337e7b5a5d 100644 (file)
--- a/tun.c
+++ b/tun.c
@@ -2505,7 +2505,7 @@ get_interface_info (DWORD index, struct gc_arena *gc)
  * IP_ADAPTER_INFO structure for that adapter.
  */
 
-static const IP_ADAPTER_INFO *
+const IP_ADAPTER_INFO *
 get_adapter (const IP_ADAPTER_INFO *ai, DWORD index)
 {
   if (ai && index != (DWORD)~0)
diff --git a/tun.h b/tun.h
index 1bf17fa3f3dd70a59a4bf65763db594409299241..b25587c99d487640a7ec77d0bcafa50ea7cb858d 100644 (file)
--- a/tun.h
+++ b/tun.h
@@ -308,6 +308,7 @@ const IP_ADAPTER_INFO *get_tun_adapter (const struct tuntap *tt, const IP_ADAPTE
 
 const IP_ADAPTER_INFO *get_adapter_info (DWORD index, struct gc_arena *gc);
 const IP_PER_ADAPTER_INFO *get_per_adapter_info (const DWORD index, struct gc_arena *gc);
+const IP_ADAPTER_INFO *get_adapter (const IP_ADAPTER_INFO *ai, DWORD index);
 
 bool is_adapter_up (const struct tuntap *tt, const IP_ADAPTER_INFO *list);
 bool is_ip_in_adapter_subnet (const IP_ADAPTER_INFO *ai, const in_addr_t ip, in_addr_t *highest_netmask);