Browse code

New try at AUTO_USERID.

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

james authored on 2006/11/13 18:44:10
Showing 9 changed files
... ...
@@ -134,6 +134,7 @@
134 134
 #define D_PACKET_TRUNC_DEBUG LOGLEV(7, 70, M_DEBUG)  /* PACKET_TRUNCATION_CHECK verbose */
135 135
 #define D_PING               LOGLEV(7, 70, M_DEBUG)  /* PING send/receive messages */
136 136
 #define D_PS_PROXY_DEBUG     LOGLEV(7, 70, M_DEBUG)  /* port share proxy debug */
137
+#define D_AUTO_USERID        LOGLEV(7, 70, M_DEBUG)  /* AUTO_USERID debugging */
137 138
 
138 139
 #define D_HANDSHAKE_VERBOSE  LOGLEV(8, 70, M_DEBUG)  /* show detailed description of each handshake */
139 140
 #define D_TLS_DEBUG_MED      LOGLEV(8, 70, M_DEBUG)  /* limited info from tls_session routines */
... ...
@@ -39,6 +39,8 @@
39 39
 #include "plugin.h"
40 40
 #include "options.h"
41 41
 #include "manage.h"
42
+#include "crypto.h"
43
+#include "route.h"
42 44
 
43 45
 #include "memdbg.h"
44 46
 
... ...
@@ -1311,6 +1313,64 @@ get_user_pass (struct user_pass *up,
1311 1311
   return true;
1312 1312
 }
1313 1313
 
1314
+#if AUTO_USERID
1315
+
1316
+static const char *
1317
+get_platform_prefix (void)
1318
+{
1319
+#if defined(TARGET_LINUX)
1320
+  return "L";
1321
+#elif defined(TARGET_SOLARIS)
1322
+  return "S";
1323
+#elif defined(TARGET_OPENBSD)
1324
+  return "O";
1325
+#elif defined(TARGET_DARWIN)
1326
+  return "M";
1327
+#elif defined(TARGET_NETBSD)
1328
+  return "N";
1329
+#elif defined(TARGET_FREEBSD)
1330
+  return "F";
1331
+#elif defined(WIN32)
1332
+  return "W";
1333
+#else
1334
+  return "X";
1335
+#endif
1336
+}
1337
+
1338
+void
1339
+get_user_pass_auto_userid (struct user_pass *up)
1340
+{
1341
+  struct gc_arena gc = gc_new ();
1342
+  MD5_CTX ctx;
1343
+  struct buffer buf;
1344
+  uint8_t macaddr[6];
1345
+  static uint8_t digest [MD5_DIGEST_LENGTH];
1346
+  static const uint8_t hashprefix[] = "AUTO_USERID_DIGEST";
1347
+
1348
+  CLEAR (*up);
1349
+  buf_set_write (&buf, (uint8_t*)up->username, USER_PASS_LEN);
1350
+  buf_printf (&buf, "%s", get_platform_prefix ());
1351
+  if (get_default_gateway_mac_addr (macaddr))
1352
+    {
1353
+      dmsg (D_AUTO_USERID, "GUPAU: macaddr=%s", format_hex_ex (macaddr, sizeof (macaddr), 0, 1, ":", &gc));
1354
+      MD5_Init (&ctx);
1355
+      MD5_Update (&ctx, hashprefix, sizeof (hashprefix) - 1);
1356
+      MD5_Update (&ctx, macaddr, sizeof (macaddr));
1357
+      MD5_Final (digest, &ctx);
1358
+      buf_printf (&buf, "%s", format_hex_ex (digest, sizeof (digest), 0, 256, " ", &gc));
1359
+    }
1360
+  else
1361
+    {
1362
+      buf_printf (&buf, "UNKNOWN");
1363
+    }
1364
+  up->defined = true;
1365
+  gc_free (&gc);
1366
+
1367
+  dmsg (D_AUTO_USERID, "GUPAU: AUTO_USERID: '%s'", up->username);
1368
+}
1369
+
1370
+#endif
1371
+
1314 1372
 void
1315 1373
 purge_user_pass (struct user_pass *up, const bool force)
1316 1374
 {
... ...
@@ -264,4 +264,8 @@ void openvpn_sleep (const int n);
264 264
 
265 265
 void configure_path (void);
266 266
 
267
+#if AUTO_USERID
268
+void get_user_pass_auto_userid (struct user_pass *up);
269
+#endif
270
+
267 271
 #endif
... ...
@@ -2017,3 +2017,152 @@ get_bypass_addresses (struct route_bypass *rb, const unsigned int flags)
2017 2017
 }
2018 2018
 
2019 2019
 #endif
2020
+
2021
+#if AUTO_USERID
2022
+
2023
+#if defined(TARGET_LINUX)
2024
+
2025
+bool
2026
+get_default_gateway_mac_addr (unsigned char *macaddr)
2027
+{
2028
+  struct ifreq *ifr, *ifend;
2029
+  in_addr_t ina, mask;
2030
+  struct ifreq ifreq;
2031
+  struct ifconf ifc;
2032
+  struct ifreq ifs[20]; // Maximum number of interfaces to scan
2033
+  int sd = -1;
2034
+  in_addr_t gwip = 0;
2035
+  bool ret = false;
2036
+
2037
+  if (!get_default_gateway (&gwip))
2038
+    {
2039
+      msg (M_WARN, "GDGMA: get_default_gateway failed");
2040
+      goto err;
2041
+    }
2042
+
2043
+  if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
2044
+    {
2045
+      msg (M_WARN, "GDGMA: socket() failed");
2046
+      goto err;
2047
+    }
2048
+
2049
+  ifc.ifc_len = sizeof (ifs);
2050
+  ifc.ifc_req = ifs;
2051
+  if (ioctl (sd, SIOCGIFCONF, &ifc) < 0)
2052
+    {
2053
+      msg (M_WARN, "GDGMA: ioctl(SIOCGIFCONF) failed");
2054
+      goto err;
2055
+    }
2056
+
2057
+  /* scan through interface list */
2058
+  ifend = ifs + (ifc.ifc_len / sizeof (struct ifreq));
2059
+  for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
2060
+    {
2061
+      if (ifr->ifr_addr.sa_family == AF_INET)
2062
+	{
2063
+	  ina = ntohl(((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr);
2064
+	  strncpynt (ifreq.ifr_name, ifr->ifr_name, sizeof (ifreq.ifr_name));
2065
+
2066
+	  dmsg (D_AUTO_USERID, "GDGMA: %s", ifreq.ifr_name);
2067
+
2068
+	  /* check that the interface is up, and not point-to-point or loopback */
2069
+	  if (ioctl (sd, SIOCGIFFLAGS, &ifreq) < 0)
2070
+	    {
2071
+	      dmsg (D_AUTO_USERID, "GDGMA: SIOCGIFFLAGS(%s) failed", ifreq.ifr_name);
2072
+	      continue;
2073
+	    }
2074
+
2075
+	  if ((ifreq.ifr_flags & (IFF_UP|IFF_LOOPBACK)) != IFF_UP)
2076
+	    {
2077
+	      dmsg (D_AUTO_USERID, "GDGMA: interface %s is down or loopback", ifreq.ifr_name);
2078
+	      continue;
2079
+	    }
2080
+
2081
+	  /* get interface netmask and check for correct subnet */
2082
+	  if (ioctl (sd, SIOCGIFNETMASK, &ifreq) < 0)
2083
+	    {
2084
+	      dmsg (D_AUTO_USERID, "GDGMA: SIOCGIFNETMASK(%s) failed", ifreq.ifr_name);
2085
+	      continue;
2086
+	    }
2087
+
2088
+	  mask = ntohl(((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
2089
+	  if (((gwip ^ ina) & mask) != 0)
2090
+	    {
2091
+	      dmsg (D_AUTO_USERID, "GDGMA: gwip=0x%08x ina=0x%08x mask=0x%08x",
2092
+		    (unsigned int)gwip,
2093
+		    (unsigned int)ina,
2094
+		    (unsigned int)mask);
2095
+	      continue;
2096
+	    }
2097
+	  break;
2098
+	}
2099
+    }
2100
+  if (ifr >= ifend)
2101
+    {
2102
+      msg (M_WARN, "GDGMA: couldn't find gw interface");
2103
+      goto err;
2104
+    }
2105
+
2106
+  /* now get the hardware address. */
2107
+  memset (&ifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));
2108
+  if (ioctl (sd, SIOCGIFHWADDR, &ifreq) < 0)
2109
+    {
2110
+      msg (M_WARN, "GDGMA: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
2111
+      goto err;
2112
+    }
2113
+
2114
+  memcpy (macaddr, &ifreq.ifr_hwaddr.sa_data, 6);
2115
+  ret = true;
2116
+
2117
+ err:
2118
+  if (sd >= 0)
2119
+    close (sd);
2120
+  return ret;
2121
+}
2122
+
2123
+#elif defined(WIN32)
2124
+
2125
+bool
2126
+get_default_gateway_mac_addr (unsigned char *macaddr)
2127
+{
2128
+  struct gc_arena gc = gc_new ();
2129
+  const IP_ADAPTER_INFO *adapters = get_adapter_info_list (&gc);
2130
+  in_addr_t gwip = 0;
2131
+  DWORD a_index;
2132
+  const IP_ADAPTER_INFO *ai;
2133
+
2134
+  if (!get_default_gateway (&gwip))
2135
+    {
2136
+      msg (M_WARN, "GDGMA: get_default_gateway failed");
2137
+      goto err;
2138
+    }
2139
+
2140
+  a_index = adapter_index_of_ip (adapters, gwip, NULL);
2141
+  ai = get_adapter (adapters, a_index);
2142
+
2143
+  if (!ai)
2144
+    {
2145
+      msg (M_WARN, "GDGMA: couldn't find gw interface");
2146
+      goto err;
2147
+    }
2148
+
2149
+  memcpy (macaddr, ai->Address, 6);
2150
+
2151
+  gc_free (&gc);
2152
+  return true;
2153
+
2154
+ err:
2155
+  gc_free (&gc);
2156
+  return false;
2157
+}
2158
+
2159
+#else
2160
+
2161
+bool
2162
+get_default_gateway_mac_addr (unsigned char *macaddr)
2163
+{
2164
+  return false;
2165
+}
2166
+
2167
+#endif
2168
+#endif /* AUTO_USERID */
... ...
@@ -150,6 +150,10 @@ void delete_routes (struct route_list *rl,
150 150
 
151 151
 void setenv_routes (struct env_set *es, const struct route_list *rl);
152 152
 
153
+#if AUTO_USERID
154
+bool get_default_gateway_mac_addr (unsigned char *macaddr);
155
+#endif
156
+
153 157
 #ifdef ENABLE_DEBUG
154 158
 void print_route_options (const struct route_option_list *rol,
155 159
 			  int level);
... ...
@@ -296,7 +296,13 @@ auth_user_pass_setup (const char *auth_file)
296 296
 {
297 297
   auth_user_pass_enabled = true;
298 298
   if (!auth_user_pass.defined)
299
-    get_user_pass (&auth_user_pass, auth_file, UP_TYPE_AUTH, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE);
299
+    {
300
+#if AUTO_USERID
301
+      get_user_pass_auto_userid (&auth_user_pass);
302
+#else
303
+      get_user_pass (&auth_user_pass, auth_file, UP_TYPE_AUTH, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE);
304
+#endif
305
+    }
300 306
 }
301 307
 
302 308
 /*
... ...
@@ -515,4 +515,13 @@ socket_defined (const socket_descriptor_t sd)
515 515
 #define CONNECT_NONBLOCK
516 516
 #endif
517 517
 
518
+/*
519
+ * Do we have the capability to support the AUTO_USERID feature? 
520
+ */
521
+#if defined(ENABLE_AUTO_USERID)
522
+#define AUTO_USERID 1
523
+#else
524
+#define AUTO_USERID 0
525
+#endif
526
+
518 527
 #endif
... ...
@@ -2505,7 +2505,7 @@ get_interface_info (DWORD index, struct gc_arena *gc)
2505 2505
  * IP_ADAPTER_INFO structure for that adapter.
2506 2506
  */
2507 2507
 
2508
-static const IP_ADAPTER_INFO *
2508
+const IP_ADAPTER_INFO *
2509 2509
 get_adapter (const IP_ADAPTER_INFO *ai, DWORD index)
2510 2510
 {
2511 2511
   if (ai && index != (DWORD)~0)
... ...
@@ -308,6 +308,7 @@ const IP_ADAPTER_INFO *get_tun_adapter (const struct tuntap *tt, const IP_ADAPTE
308 308
 
309 309
 const IP_ADAPTER_INFO *get_adapter_info (DWORD index, struct gc_arena *gc);
310 310
 const IP_PER_ADAPTER_INFO *get_per_adapter_info (const DWORD index, struct gc_arena *gc);
311
+const IP_ADAPTER_INFO *get_adapter (const IP_ADAPTER_INFO *ai, DWORD index);
311 312
 
312 313
 bool is_adapter_up (const struct tuntap *tt, const IP_ADAPTER_INFO *list);
313 314
 bool is_ip_in_adapter_subnet (const IP_ADAPTER_INFO *ai, const in_addr_t ip, in_addr_t *highest_netmask);