diff options
| author | David Lönnhager <david.l@mullvad.net> | 2020-12-09 11:56:49 +0100 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2020-12-09 11:56:49 +0100 |
| commit | 83bdea1ba486c2625e99625e1948730359d01d22 (patch) | |
| tree | 04b5a599921110579982a100c4fffccd9ae92d1e | |
| parent | b9fa418e643abafd792b53d7bceadd918226d3b1 (diff) | |
| parent | 9fcb5ea993cd2b72ba28436e8c98cda7f2681d9c (diff) | |
| download | mullvadvpn-83bdea1ba486c2625e99625e1948730359d01d22.tar.xz mullvadvpn-83bdea1ba486c2625e99625e1948730359d01d22.zip | |
Merge branch 'workaround-component-id-bug'
| -rw-r--r-- | talpid-core/src/tunnel/openvpn/mod.rs | 40 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/openvpn/windows.rs | 53 |
2 files changed, 88 insertions, 5 deletions
diff --git a/talpid-core/src/tunnel/openvpn/mod.rs b/talpid-core/src/tunnel/openvpn/mod.rs index 7f299d8e73..fd186026d4 100644 --- a/talpid-core/src/tunnel/openvpn/mod.rs +++ b/talpid-core/src/tunnel/openvpn/mod.rs @@ -32,7 +32,7 @@ use std::{collections::HashSet, net::IpAddr}; #[cfg(windows)] use std::{ffi::OsStr, os::windows::ffi::OsStrExt, time::Instant}; use talpid_types::net::openvpn; -#[cfg(target_os = "linux")] +#[cfg(any(windows, target_os = "linux"))] use talpid_types::ErrorExt; use tokio::task; #[cfg(target_os = "linux")] @@ -51,6 +51,8 @@ use winapi::shared::{ winerror::{ERROR_FILE_NOT_FOUND, NO_ERROR}, ws2def::AF_UNSPEC, }; +#[cfg(windows)] +use winreg::enums::{KEY_READ, KEY_WRITE}; #[cfg(windows)] mod windows; @@ -60,6 +62,7 @@ mod windows; lazy_static! { static ref ADAPTER_ALIAS: U16CString = U16CString::from_str("Mullvad").unwrap(); static ref ADAPTER_POOL: U16CString = U16CString::from_str("Mullvad").unwrap(); + static ref ADAPTER_GUID_STR: String = windows::string_from_guid(&ADAPTER_GUID); } #[cfg(windows)] @@ -375,6 +378,38 @@ impl OpenVpnMonitor<OpenVpnCommand> { log::warn!("You may need to restart Windows to complete the install of Wintun"); } + // Workaround: OpenVPN looks up "ComponentId" to identify tunnel devices. + // If Wintun fails to create this registry value, create it here. + let adapter_key = + windows::find_adapter_registry_key(&*ADAPTER_GUID_STR, KEY_READ | KEY_WRITE); + match adapter_key { + Ok(adapter_key) => { + let component_id: io::Result<String> = adapter_key.get_value("ComponentId"); + match component_id { + Ok(_) => (), + Err(error) => { + if error.kind() == io::ErrorKind::NotFound { + if let Err(error) = adapter_key.set_value("ComponentId", &"wintun") + { + log::error!( + "{}", + error.display_chain_with_msg( + "Failed to set ComponentId registry value" + ) + ); + } + } + } + } + } + Err(error) => { + log::error!( + "{}", + error.display_chain_with_msg("Failed to find network adapter registry key") + ); + } + } + adapter }; @@ -696,8 +731,7 @@ impl<C: OpenVpnBuilder + 'static> OpenVpnMonitor<C> { .ca(resource_dir.join("ca.crt")); #[cfg(windows)] { - use std::ffi::OsString; - cmd.tunnel_alias(Some(OsString::from("Mullvad"))); + cmd.tunnel_alias(Some(ADAPTER_ALIAS.to_os_string())); cmd.windows_driver(Some(crate::process::openvpn::WindowsDriver::Wintun)); } if let Some(proxy_settings) = params.proxy.clone().take() { diff --git a/talpid-core/src/tunnel/openvpn/windows.rs b/talpid-core/src/tunnel/openvpn/windows.rs index f64892fcab..1c691794e0 100644 --- a/talpid-core/src/tunnel/openvpn/windows.rs +++ b/talpid-core/src/tunnel/openvpn/windows.rs @@ -13,10 +13,14 @@ use winapi::{ guiddef::GUID, minwindef::{BOOL, FARPROC, HINSTANCE, HMODULE}, }, - um::libloaderapi::{ - FreeLibrary, GetProcAddress, LoadLibraryExW, LOAD_WITH_ALTERED_SEARCH_PATH, + um::{ + libloaderapi::{ + FreeLibrary, GetProcAddress, LoadLibraryExW, LOAD_WITH_ALTERED_SEARCH_PATH, + }, + winreg::REGSAM, }, }; +use winreg::{enums::HKEY_LOCAL_MACHINE, RegKey}; type WintunOpenAdapterFn = @@ -241,3 +245,48 @@ impl Drop for WintunDll { unsafe { FreeLibrary(self.handle) }; } } + +/// Obtain a string representation for a GUID object. +pub fn string_from_guid(guid: &GUID) -> String { + use std::{ffi::OsString, os::windows::ffi::OsStringExt}; + use winapi::um::combaseapi::StringFromGUID2; + + let mut buffer = [0u16; 40]; + let length = unsafe { StringFromGUID2(guid, &mut buffer[0] as *mut _, buffer.len() as i32 - 1) } + as usize; + if length > 0 { + let length = length - 1; + OsString::from_wide(&buffer[0..length]) + .to_string_lossy() + .to_string() + } else { + "".to_string() + } +} + +pub fn find_adapter_registry_key(find_guid: &str, permissions: REGSAM) -> io::Result<RegKey> { + let net_devs = RegKey::predef(HKEY_LOCAL_MACHINE).open_subkey_with_flags( + r"SYSTEM\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}", + permissions, + )?; + let find_guid = find_guid.to_lowercase(); + + for subkey_name in net_devs.enum_keys() { + let subkey_name = match subkey_name { + Ok(subkey_name) => subkey_name, + Err(_error) => continue, + }; + + let subkey: io::Result<RegKey> = net_devs.open_subkey_with_flags(&subkey_name, permissions); + if let Ok(subkey) = subkey { + let guid_str: io::Result<String> = subkey.get_value("NetCfgInstanceId"); + if let Ok(guid_str) = guid_str { + if guid_str.to_lowercase() == find_guid { + return Ok(subkey); + } + } + } + } + + Err(io::Error::new(io::ErrorKind::NotFound, "device not found")) +} |
