From 5f31881ec189f02297b961c990c471568f25dbde Mon Sep 17 00:00:00 2001 From: james Date: Mon, 13 Nov 2006 09:44:10 +0000 Subject: 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 --- errlevel.h | 1 + misc.c | 60 +++++++++++++++++++++++++ misc.h | 4 ++ route.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ route.h | 4 ++ ssl.c | 8 +++- syshead.h | 9 ++++ tun.c | 2 +- tun.h | 1 + 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); -- cgit v1.2.3