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
... | ... |
@@ -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 |
{ |
... | ... |
@@ -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); |