mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-20 12:12:15 +02:00
wintun: open device with SetupAPI
With introduction of ring buffers Wintun device must be opened via SetupAPI. Signed-off-by: Lev Stipakov <lev@openvpn.net>
This commit is contained in:
parent
4dbcd85e50
commit
aeb5ce0ad7
@ -35,6 +35,12 @@
|
||||
#include <ws2tcpip.h> // for IPv6
|
||||
#include <tlhelp32.h> // for impersonating as LocalSystem
|
||||
|
||||
|
||||
#include <SetupAPI.h>
|
||||
#include <devguid.h>
|
||||
#include <cfgmgr32.h>
|
||||
#include <ndisguid.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
@ -343,12 +349,123 @@ namespace openvpn {
|
||||
}
|
||||
};
|
||||
|
||||
// given a TAP GUID, form the pathname of the TAP device node
|
||||
inline std::string tap_path(const TapNameGuidPair& tap, bool wintun)
|
||||
struct DeviceInstanceIdInterfacePair
|
||||
{
|
||||
std::string net_cfg_instance_id;
|
||||
std::string device_interface_list;
|
||||
};
|
||||
|
||||
class DevInfoSetHelper
|
||||
{
|
||||
public:
|
||||
DevInfoSetHelper()
|
||||
{
|
||||
handle = SetupDiGetClassDevsEx(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
bool is_valid()
|
||||
{
|
||||
return handle != INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
operator HDEVINFO()
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
|
||||
~DevInfoSetHelper()
|
||||
{
|
||||
if (is_valid())
|
||||
{
|
||||
SetupDiDestroyDeviceInfoList(handle);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
HDEVINFO handle;
|
||||
};
|
||||
|
||||
struct DeviceInstanceIdInterfaceList : public std::vector<DeviceInstanceIdInterfacePair>
|
||||
{
|
||||
DeviceInstanceIdInterfaceList()
|
||||
{
|
||||
DevInfoSetHelper device_info_set;
|
||||
if (!device_info_set.is_valid())
|
||||
return;
|
||||
|
||||
for (DWORD i = 0;; ++i)
|
||||
{
|
||||
SP_DEVINFO_DATA dev_info_data;
|
||||
ZeroMemory(&dev_info_data, sizeof(SP_DEVINFO_DATA));
|
||||
dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
BOOL res = SetupDiEnumDeviceInfo(device_info_set, i, &dev_info_data);
|
||||
if (!res)
|
||||
{
|
||||
if (GetLastError() == ERROR_NO_MORE_ITEMS)
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
Win::RegKey regkey;
|
||||
*regkey.ref() = SetupDiOpenDevRegKey(device_info_set, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
|
||||
if (!regkey.defined())
|
||||
continue;
|
||||
|
||||
std::string str_net_cfg_instance_id;
|
||||
|
||||
DWORD size;
|
||||
LONG status = RegQueryValueExA(regkey(), "NetCfgInstanceId", NULL, NULL, NULL, &size);
|
||||
if (status != ERROR_SUCCESS)
|
||||
continue;
|
||||
BufferAllocatedType<char, thread_unsafe_refcount> buf_net_cfg_inst_id(size, BufferAllocated::CONSTRUCT_ZERO);
|
||||
|
||||
status = RegQueryValueExA(regkey(), "NetCfgInstanceId", NULL, NULL, (LPBYTE)buf_net_cfg_inst_id.data(), &size);
|
||||
if (status == ERROR_SUCCESS)
|
||||
{
|
||||
buf_net_cfg_inst_id.data()[size - 1] = '\0';
|
||||
str_net_cfg_instance_id = std::string(buf_net_cfg_inst_id.data());
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
res = SetupDiGetDeviceInstanceId(device_info_set, &dev_info_data, NULL, 0, &size);
|
||||
if (res != FALSE && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
continue;
|
||||
|
||||
BufferAllocatedType<char, thread_unsafe_refcount> buf_dev_inst_id(size, BufferAllocated::CONSTRUCT_ZERO);
|
||||
if (!SetupDiGetDeviceInstanceId(device_info_set, &dev_info_data, buf_dev_inst_id.data(), size, &size))
|
||||
continue;
|
||||
buf_dev_inst_id.set_size(size);
|
||||
|
||||
ULONG dev_interface_list_size = 0;
|
||||
CONFIGRET cr = CM_Get_Device_Interface_List_Size(&dev_interface_list_size,
|
||||
(LPGUID)& GUID_DEVINTERFACE_NET,
|
||||
buf_dev_inst_id.data(),
|
||||
CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
|
||||
|
||||
if (cr != CR_SUCCESS)
|
||||
continue;
|
||||
|
||||
BufferAllocatedType<char, thread_unsafe_refcount> buf_dev_iface_list(dev_interface_list_size, BufferAllocated::CONSTRUCT_ZERO);
|
||||
cr = CM_Get_Device_Interface_List((LPGUID)& GUID_DEVINTERFACE_NET, buf_dev_inst_id.data(),
|
||||
buf_dev_iface_list.data(),
|
||||
dev_interface_list_size,
|
||||
CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
|
||||
if (cr != CR_SUCCESS)
|
||||
continue;
|
||||
|
||||
DeviceInstanceIdInterfacePair pair;
|
||||
pair.net_cfg_instance_id = str_net_cfg_instance_id;
|
||||
pair.device_interface_list = std::string(buf_dev_iface_list.data());
|
||||
push_back(pair);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// given a TAP GUID, form the pathname of the TAP device node
|
||||
inline std::string tap_path(const TapNameGuidPair& tap)
|
||||
{
|
||||
if (wintun)
|
||||
return std::string(USERMODEDEVICEDIR) + "WINTUN" + std::to_string(tap.net_luid_index);
|
||||
else
|
||||
return std::string(USERMODEDEVICEDIR) + tap.guid + std::string(TAP_WIN_SUFFIX);
|
||||
}
|
||||
|
||||
@ -364,30 +481,50 @@ namespace openvpn {
|
||||
for (TapNameGuidPairList::const_iterator i = guids.begin(); i != guids.end(); i++)
|
||||
{
|
||||
const TapNameGuidPair& tap = *i;
|
||||
const std::string path = tap_path(tap, wintun);
|
||||
|
||||
{
|
||||
// wintun device can be only opened under LocalSystem account
|
||||
std::unique_ptr<Win::Impersonate> imp;
|
||||
std::string path;
|
||||
|
||||
if (wintun)
|
||||
imp.reset(new Win::Impersonate(true));
|
||||
|
||||
hand.reset(::CreateFileA(path.c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0, /* was: FILE_SHARE_READ */
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
|
||||
0));
|
||||
}
|
||||
|
||||
if (hand.defined())
|
||||
if (wintun)
|
||||
{
|
||||
used = tap;
|
||||
path_opened = path;
|
||||
break;
|
||||
DeviceInstanceIdInterfaceList inst_id_interface_list;
|
||||
|
||||
for (const auto& inst_id_interface : inst_id_interface_list)
|
||||
{
|
||||
if (inst_id_interface.net_cfg_instance_id != tap.guid)
|
||||
continue;
|
||||
|
||||
path = inst_id_interface.device_interface_list;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
path = tap_path(tap);
|
||||
}
|
||||
|
||||
if (path.length() > 0)
|
||||
{
|
||||
// wintun device can be only opened under LocalSystem account
|
||||
std::unique_ptr<Win::Impersonate> imp;
|
||||
|
||||
if (wintun)
|
||||
imp.reset(new Win::Impersonate(true));
|
||||
|
||||
hand.reset(::CreateFileA(path.c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0, /* was: FILE_SHARE_READ */
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
|
||||
0));
|
||||
|
||||
if (hand.defined())
|
||||
{
|
||||
used = tap;
|
||||
path_opened = path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hand.release();
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ def build(parms, srcfile, unit_test=False):
|
||||
options['extra_lib'] += ' mbedtls.lib'
|
||||
|
||||
# build it
|
||||
vc_cmd(parms, r"cl %(extra_defs)s /DNOMINMAX /bigobj /D_CRT_SECURE_NO_WARNINGS /DUSE_ASIO /DASIO_STANDALONE /DASIO_NO_DEPRECATED /I %(asio)s\asio\include /DHAVE_LZ4 /I %(lz4)s %(extra_inc)s -DTAP_WIN_COMPONENT_ID=%(tap_component_id)s /I %(tap)s /I %(ovpn3)s\core /EHsc %(link_static_dynamic_flags)s /W0 %(dbg_rel_flags)s /nologo %(srcfile)s /link /LIBPATH:%(lz4)s%(extra_lib_path)s lz4.lib%(extra_lib)s ws2_32.lib crypt32.lib iphlpapi.lib winmm.lib user32.lib gdi32.lib advapi32.lib wininet.lib shell32.lib ole32.lib rpcrt4.lib Wtsapi32.lib" % options, arch=os.environ.get("ARCH"))
|
||||
vc_cmd(parms, r"cl %(extra_defs)s /DNOMINMAX /bigobj /D_CRT_SECURE_NO_WARNINGS /DUSE_ASIO /DASIO_STANDALONE /DASIO_NO_DEPRECATED /I %(asio)s\asio\include /DHAVE_LZ4 /I %(lz4)s %(extra_inc)s -DTAP_WIN_COMPONENT_ID=%(tap_component_id)s /I %(tap)s /I %(ovpn3)s\core /EHsc %(link_static_dynamic_flags)s /W0 %(dbg_rel_flags)s /nologo %(srcfile)s /link /LIBPATH:%(lz4)s%(extra_lib_path)s lz4.lib%(extra_lib)s ws2_32.lib crypt32.lib iphlpapi.lib winmm.lib user32.lib gdi32.lib advapi32.lib wininet.lib shell32.lib ole32.lib rpcrt4.lib Wtsapi32.lib Setupapi.lib Cfgmgr32.lib" % options, arch=os.environ.get("ARCH"))
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
Loading…
Reference in New Issue
Block a user