summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2020-12-09 11:56:49 +0100
committerDavid Lönnhager <david.l@mullvad.net>2020-12-09 11:56:49 +0100
commit83bdea1ba486c2625e99625e1948730359d01d22 (patch)
tree04b5a599921110579982a100c4fffccd9ae92d1e
parentb9fa418e643abafd792b53d7bceadd918226d3b1 (diff)
parent9fcb5ea993cd2b72ba28436e8c98cda7f2681d9c (diff)
downloadmullvadvpn-83bdea1ba486c2625e99625e1948730359d01d22.tar.xz
mullvadvpn-83bdea1ba486c2625e99625e1948730359d01d22.zip
Merge branch 'workaround-component-id-bug'
-rw-r--r--talpid-core/src/tunnel/openvpn/mod.rs40
-rw-r--r--talpid-core/src/tunnel/openvpn/windows.rs53
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"))
+}