summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-05-27 08:24:24 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-05-27 08:24:24 -0300
commitb8f08c59ab655a2fdc7a71c8abf5895a85758a14 (patch)
treec1233dbefa25db09722e643b32d92a3d3950c402
parent513b791fd21fabfa8b9990b34eeb8a1871110a4a (diff)
parentb5243e12d97f084a374de209952a6740ec9c407f (diff)
downloadmullvadvpn-b8f08c59ab655a2fdc7a71c8abf5895a85758a14.tar.xz
mullvadvpn-b8f08c59ab655a2fdc7a71c8abf5895a85758a14.zip
Merge branch 'wireguard-key-generation-on-android'
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt55
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt3
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/model/PublicKey.kt3
-rw-r--r--mullvad-jni/src/daemon_interface.rs19
-rw-r--r--mullvad-jni/src/into_java.rs35
-rw-r--r--mullvad-jni/src/lib.rs42
6 files changed, 148 insertions, 9 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt
index 11bfabe912..4a853b2f7b 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt
@@ -1,6 +1,7 @@
package net.mullvad.mullvadvpn
import kotlinx.coroutines.launch
+import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
@@ -23,15 +24,19 @@ class ConnectFragment : Fragment() {
private lateinit var notificationBanner: NotificationBanner
private lateinit var status: ConnectionStatus
- private lateinit var daemon: Deferred<MullvadDaemon>
+ private var daemon = CompletableDeferred<MullvadDaemon>()
+ private var generateWireguardKeyJob = generateWireguardKey()
+
+ private var activeAction: Job? = null
private var attachListenerJob: Job? = null
private var updateViewJob: Job? = null
+ private var waitForDaemonJob: Job? = null
override fun onAttach(context: Context) {
super.onAttach(context)
- daemon = (context as MainActivity).asyncDaemon
+ waitForDaemonJob = waitForDaemon((context as MainActivity).asyncDaemon)
}
override fun onCreateView(
@@ -61,14 +66,20 @@ class ConnectFragment : Fragment() {
return view
}
-
override fun onDestroyView() {
+ waitForDaemonJob?.cancel()
attachListenerJob?.cancel()
detachListener()
+ generateWireguardKeyJob.cancel()
updateViewJob?.cancel()
super.onDestroyView()
}
+ private fun waitForDaemon(asyncDaemon: Deferred<MullvadDaemon>) =
+ GlobalScope.launch(Dispatchers.Default) {
+ daemon.complete(asyncDaemon.await())
+ }
+
private fun attachListener() = GlobalScope.launch(Dispatchers.Default) {
daemon.await().onTunnelStateChange = { state -> updateViewJob = updateView(state) }
}
@@ -77,12 +88,42 @@ class ConnectFragment : Fragment() {
daemon.await().onTunnelStateChange = null
}
- private fun connect() = GlobalScope.launch(Dispatchers.Default) {
- daemon.await().connect()
+ private fun generateWireguardKey() = GlobalScope.launch(Dispatchers.Default) {
+ val daemon = this@ConnectFragment.daemon.await()
+ val key = daemon.getWireguardKey()
+
+ if (key == null) {
+ daemon.generateWireguardKey()
+ }
+ }
+
+ private fun connect() {
+ updateViewToPreConnecting()
+ activeAction?.cancel()
+
+ activeAction = GlobalScope.launch(Dispatchers.Default) {
+ generateWireguardKeyJob.join()
+ daemon.await().connect()
+ }
+ }
+
+ private fun disconnect() {
+ activeAction?.cancel()
+
+ activeAction = GlobalScope.launch(Dispatchers.Default) {
+ daemon.await().disconnect()
+ }
}
- private fun disconnect() = GlobalScope.launch(Dispatchers.Default) {
- daemon.await().disconnect()
+ private fun updateViewToPreConnecting() {
+ val connecting = TunnelStateTransition.Connecting()
+ val disconnected = TunnelStateTransition.Disconnected()
+
+ headerBar.setState(disconnected)
+
+ actionButton.state = connecting
+ notificationBanner.setState(connecting)
+ status.setState(connecting)
}
private fun updateView(state: TunnelStateTransition) = GlobalScope.launch(Dispatchers.Main) {
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt
index 80ac09eef2..e9f54769b2 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt
@@ -1,6 +1,7 @@
package net.mullvad.mullvadvpn
import net.mullvad.mullvadvpn.model.AccountData
+import net.mullvad.mullvadvpn.model.PublicKey
import net.mullvad.mullvadvpn.model.RelayList
import net.mullvad.mullvadvpn.model.RelaySettingsUpdate
import net.mullvad.mullvadvpn.model.Settings
@@ -16,9 +17,11 @@ class MullvadDaemon {
external fun connect()
external fun disconnect()
+ external fun generateWireguardKey(): Boolean
external fun getAccountData(accountToken: String): AccountData?
external fun getRelayLocations(): RelayList
external fun getSettings(): Settings
+ external fun getWireguardKey(): PublicKey?
external fun setAccount(accountToken: String?)
external fun updateRelaySettings(update: RelaySettingsUpdate)
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/PublicKey.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/PublicKey.kt
new file mode 100644
index 0000000000..30408c4a9b
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/PublicKey.kt
@@ -0,0 +1,3 @@
+package net.mullvad.mullvadvpn.model
+
+data class PublicKey(val key: ByteArray)
diff --git a/mullvad-jni/src/daemon_interface.rs b/mullvad-jni/src/daemon_interface.rs
index db14a92373..bb92ea9cc8 100644
--- a/mullvad-jni/src/daemon_interface.rs
+++ b/mullvad-jni/src/daemon_interface.rs
@@ -4,6 +4,7 @@ use mullvad_types::{
account::AccountData, relay_constraints::RelaySettingsUpdate, relay_list::RelayList,
settings::Settings, states::TargetState,
};
+use talpid_types::net::wireguard;
#[derive(Debug, err_derive::Error)]
pub enum Error {
@@ -60,6 +61,16 @@ impl DaemonInterface {
Ok(())
}
+ pub fn generate_wireguard_key(&self) -> Result<()> {
+ let (tx, rx) = oneshot::channel();
+
+ self.send_command(ManagementCommand::GenerateWireguardKey(tx))?;
+
+ rx.wait()
+ .map_err(|_| Error::NoResponse)?
+ .map_err(Error::RpcError)
+ }
+
pub fn get_account_data(&self, account_token: String) -> Result<AccountData> {
let (tx, rx) = oneshot::channel();
@@ -87,6 +98,14 @@ impl DaemonInterface {
Ok(rx.wait().map_err(|_| Error::NoResponse)?)
}
+ pub fn get_wireguard_key(&self) -> Result<Option<wireguard::PublicKey>> {
+ let (tx, rx) = oneshot::channel();
+
+ self.send_command(ManagementCommand::GetWireguardKey(tx))?;
+
+ rx.wait().map_err(|_| Error::NoResponse)
+ }
+
pub fn set_account(&self, account_token: Option<String>) -> Result<()> {
let (tx, rx) = oneshot::channel();
diff --git a/mullvad-jni/src/into_java.rs b/mullvad-jni/src/into_java.rs
index 743328dbff..92d75b4a27 100644
--- a/mullvad-jni/src/into_java.rs
+++ b/mullvad-jni/src/into_java.rs
@@ -1,7 +1,7 @@
use crate::get_class;
use jni::{
objects::{JList, JObject, JString, JValue},
- sys::jint,
+ sys::{jint, jsize},
JNIEnv,
};
use mullvad_types::{
@@ -12,7 +12,7 @@ use mullvad_types::{
CustomTunnelEndpoint,
};
use std::fmt::Debug;
-use talpid_types::tunnel::TunnelStateTransition;
+use talpid_types::{net::wireguard::PublicKey, tunnel::TunnelStateTransition};
pub trait IntoJava<'env> {
type JavaType;
@@ -73,6 +73,37 @@ where
}
}
+impl<'array, 'env> IntoJava<'env> for &'array [u8] {
+ type JavaType = JObject<'env>;
+
+ fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType {
+ let size = self.len();
+ let array = env
+ .new_byte_array(size as jsize)
+ .expect("Failed to create a Java array of bytes");
+
+ let data = unsafe { std::slice::from_raw_parts(self.as_ptr() as *const i8, size) };
+
+ env.set_byte_array_region(array, 0, data)
+ .expect("Failed to copy bytes to Java array");
+
+ JObject::from(array)
+ }
+}
+
+impl<'env> IntoJava<'env> for PublicKey {
+ type JavaType = JObject<'env>;
+
+ fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType {
+ let class = get_class("net/mullvad/mullvadvpn/model/PublicKey");
+ let key = env.auto_local(self.as_bytes().into_java(env));
+ let parameters = [JValue::Object(key.as_obj())];
+
+ env.new_object(&class, "([B)V", &parameters)
+ .expect("Failed to create PublicKey Java object")
+ }
+}
+
impl<'env> IntoJava<'env> for AccountData {
type JavaType = JObject<'env>;
diff --git a/mullvad-jni/src/lib.rs b/mullvad-jni/src/lib.rs
index 83e60e0486..9e1b0c3b38 100644
--- a/mullvad-jni/src/lib.rs
+++ b/mullvad-jni/src/lib.rs
@@ -12,6 +12,7 @@ use crate::{
};
use jni::{
objects::{GlobalRef, JObject, JString},
+ sys::{jboolean, JNI_FALSE, JNI_TRUE},
JNIEnv,
};
use lazy_static::lazy_static;
@@ -30,6 +31,7 @@ const CLASSES_TO_LOAD: &[&str] = &[
"net/mullvad/mullvadvpn/model/LocationConstraint$City",
"net/mullvad/mullvadvpn/model/LocationConstraint$Country",
"net/mullvad/mullvadvpn/model/LocationConstraint$Hostname",
+ "net/mullvad/mullvadvpn/model/PublicKey",
"net/mullvad/mullvadvpn/model/Relay",
"net/mullvad/mullvadvpn/model/RelayList",
"net/mullvad/mullvadvpn/model/RelayListCity",
@@ -197,6 +199,26 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_disconnect(_: J
#[no_mangle]
#[allow(non_snake_case)]
+pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_generateWireguardKey(
+ _: JNIEnv,
+ _: JObject,
+) -> jboolean {
+ let daemon = DAEMON_INTERFACE.lock();
+
+ match daemon.generate_wireguard_key() {
+ Ok(()) => JNI_TRUE,
+ Err(error) => {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg("Failed to generate wireguard key")
+ );
+ JNI_FALSE
+ }
+ }
+}
+
+#[no_mangle]
+#[allow(non_snake_case)]
pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getAccountData<'env, 'this>(
env: JNIEnv<'env>,
_: JObject<'this>,
@@ -257,6 +279,26 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getSettings<'en
#[no_mangle]
#[allow(non_snake_case)]
+pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getWireguardKey<'env, 'this>(
+ env: JNIEnv<'env>,
+ _: JObject<'this>,
+) -> JObject<'env> {
+ let daemon = DAEMON_INTERFACE.lock();
+
+ match daemon.get_wireguard_key() {
+ Ok(public_key) => public_key.into_java(&env),
+ Err(error) => {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg("Failed to get wireguard key")
+ );
+ JObject::null()
+ }
+ }
+}
+
+#[no_mangle]
+#[allow(non_snake_case)]
pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_setAccount(
env: JNIEnv,
_: JObject,