summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--errlevel.h1
-rw-r--r--misc.c60
-rw-r--r--misc.h4
-rw-r--r--route.c149
-rw-r--r--route.h4
-rw-r--r--ssl.c8
-rw-r--r--syshead.h9
-rw-r--r--tun.c2
-rw-r--r--tun.h1
9 files changed, 236 insertions, 2 deletions
diff --git a/errlevel.h b/errlevel.h
index 426a4ac..9f420ae 100644
--- a/errlevel.h
+++ b/errlevel.h
@@ -134,6 +134,7 @@
#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 f02385a..c6423fa 100644
--- 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 fa13daf..ac76185 100644
--- 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 b041b3e..354a10c 100644
--- 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 fc27a5a..6630fed 100644
--- 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 3f0c664..41564ba 100644
--- 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
+ }
}
/*
diff --git a/syshead.h b/syshead.h
index f67b4c0..2a29ee0 100644
--- 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 f0c2d49..e305ee9 100644
--- 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 1bf17fa..b25587c 100644
--- 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);