diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2018-06-13 14:17:19 -0300 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2018-06-13 14:17:19 -0300 |
| commit | 88dea50f85c7b8b546324ca5985f06b43fa815ba (patch) | |
| tree | cbdcc952f5fe8bfc0a47101552327ae6e7299ab8 | |
| parent | ca69ab47086db77e393769256d1d09e37bbb3802 (diff) | |
| parent | 6548f4e07471070e3538cc2a9f043f5b2b67545d (diff) | |
| download | mullvadvpn-88dea50f85c7b8b546324ca5985f06b43fa815ba.tar.xz mullvadvpn-88dea50f85c7b8b546324ca5985f06b43fa815ba.zip | |
Merge branch 'talpid-openvpn-plugin-ipc-credentials'
| -rw-r--r-- | talpid-core/src/tunnel/openvpn.rs | 78 | ||||
| -rw-r--r-- | talpid-openvpn-plugin/src/lib.rs | 25 | ||||
| -rw-r--r-- | talpid-openvpn-plugin/src/processing.rs | 21 |
3 files changed, 105 insertions, 19 deletions
diff --git a/talpid-core/src/tunnel/openvpn.rs b/talpid-core/src/tunnel/openvpn.rs index 58fa15eca2..c63429a4f5 100644 --- a/talpid-core/src/tunnel/openvpn.rs +++ b/talpid-core/src/tunnel/openvpn.rs @@ -12,6 +12,7 @@ use std::thread; use std::time::Duration; use talpid_ipc; +use uuid; mod errors { error_chain!{ @@ -59,10 +60,14 @@ impl<C: OpenVpnBuilder> OpenVpnMonitor<C> { L: Fn(OpenVpnPluginEvent, HashMap<String, String>) + Send + Sync + 'static, P: AsRef<Path>, { - let event_dispatcher = - event_server::start(on_event).chain_err(|| ErrorKind::EventDispatcherError)?; + let credentials = uuid::Uuid::new_v4().to_string(); + let event_dispatcher = event_server::start(credentials.clone(), on_event) + .chain_err(|| ErrorKind::EventDispatcherError)?; - cmd.plugin(plugin_path, vec![event_dispatcher.address().to_owned()]); + cmd.plugin( + plugin_path, + vec![event_dispatcher.address().to_owned(), credentials], + ); let child = cmd .start() .chain_err(|| ErrorKind::ChildProcessError("Failed to start"))?; @@ -216,30 +221,41 @@ impl ProcessHandle for OpenVpnProcHandle { mod event_server { use super::OpenVpnPluginEvent; - use jsonrpc_core::{Error, IoHandler}; + use jsonrpc_core::{Compatibility, Error, MetaIoHandler, Metadata}; use std::collections::HashMap; + use std::sync::atomic::{AtomicBool, Ordering}; + use std::sync::Arc; use talpid_ipc; /// Construct and start the IPC server with the given event listener callback. - pub fn start<L>(on_event: L) -> talpid_ipc::Result<talpid_ipc::IpcServer> + pub fn start<L>(credentials: String, on_event: L) -> talpid_ipc::Result<talpid_ipc::IpcServer> where L: Fn(OpenVpnPluginEvent, HashMap<String, String>) + Send + Sync + 'static, { - let rpc = OpenVpnEventApiImpl { on_event }; - let mut io = IoHandler::new(); + let rpc = OpenVpnEventApiImpl { + credentials, + on_event, + }; + let mut io = MetaIoHandler::with_compatibility(Compatibility::V2); io.extend_with(rpc.to_delegate()); talpid_ipc::IpcServer::start(io.into()) } build_rpc_trait! { pub trait OpenVpnEventApi { - #[rpc(name = "openvpn_event")] - fn openvpn_event(&self, OpenVpnPluginEvent, HashMap<String, String>) + type Metadata; + + #[rpc(meta, name = "authenticate")] + fn authenticate(&self, Self::Metadata, String) -> Result<bool, Error>; + + #[rpc(meta, name = "openvpn_event")] + fn openvpn_event(&self, Self::Metadata, OpenVpnPluginEvent, HashMap<String, String>) -> Result<(), Error>; } } struct OpenVpnEventApiImpl<L> { + credentials: String, on_event: L, } @@ -247,16 +263,60 @@ mod event_server { where L: Fn(OpenVpnPluginEvent, HashMap<String, String>) + Send + Sync + 'static, { + type Metadata = Meta; + + fn authenticate( + &self, + metadata: Self::Metadata, + credentials: String, + ) -> Result<bool, Error> { + if credentials == self.credentials { + metadata.authenticated.store(true, Ordering::Relaxed); + Ok(true) + } else { + Ok(false) + } + } + fn openvpn_event( &self, + metadata: Self::Metadata, event: OpenVpnPluginEvent, env: HashMap<String, String>, ) -> Result<(), Error> { trace!("OpenVPN event {:?}", event); + metadata.check_authentication()?; (self.on_event)(event, env); Ok(()) } } + + #[derive(Clone)] + struct Meta { + authenticated: Arc<AtomicBool>, + } + + impl Default for Meta { + fn default() -> Self { + Meta { + authenticated: Arc::new(AtomicBool::new(false)), + } + } + } + + impl Meta { + fn check_authentication(&self) -> Result<(), Error> { + if self.authenticated.load(Ordering::Relaxed) { + trace!("Authenticated"); + Ok(()) + } else { + trace!("Not authenticated"); + Err(Error::invalid_request()) + } + } + } + + impl Metadata for Meta {} } diff --git a/talpid-openvpn-plugin/src/lib.rs b/talpid-openvpn-plugin/src/lib.rs index 71c332a212..9c6c690339 100644 --- a/talpid-openvpn-plugin/src/lib.rs +++ b/talpid-openvpn-plugin/src/lib.rs @@ -57,6 +57,11 @@ openvpn_plugin!( ::EventProcessor ); +pub struct Arguments { + server_id: talpid_ipc::IpcServerId, + credentials: String, +} + fn openvpn_open( args: Vec<CString>, _env: HashMap<CString, CString>, @@ -64,22 +69,30 @@ fn openvpn_open( env_logger::init(); debug!("Initializing plugin"); - let core_server_id = parse_args(&args)?; - info!("Connecting back to talpid core at {}", core_server_id); - let processor = EventProcessor::new(&core_server_id).chain_err(|| ErrorKind::InitHandleFailed)?; + let arguments = parse_args(&args)?; + info!("Connecting back to talpid core at {}", arguments.server_id); + let processor = EventProcessor::new(&arguments).chain_err(|| ErrorKind::InitHandleFailed)?; Ok((INTERESTING_EVENTS.to_vec(), processor)) } -fn parse_args(args: &[CString]) -> Result<talpid_ipc::IpcServerId> { +fn parse_args(args: &[CString]) -> Result<Arguments> { let mut args_iter = openvpn_plugin::ffi::parse::string_array_utf8(args) .chain_err(|| ErrorKind::ParseArgsFailed)? .into_iter(); + let _plugin_path = args_iter.next(); - let core_server_id: talpid_ipc::IpcServerId = args_iter + let server_id: talpid_ipc::IpcServerId = args_iter .next() .ok_or_else(|| ErrorKind::Msg("No core server id given as first argument".to_owned()))?; - Ok(core_server_id) + let credentials = args_iter + .next() + .ok_or_else(|| ErrorKind::Msg("No IPC credentials given as second argument".to_owned()))?; + + Ok(Arguments { + server_id, + credentials, + }) } diff --git a/talpid-openvpn-plugin/src/processing.rs b/talpid-openvpn-plugin/src/processing.rs index a376665888..cadaf80647 100644 --- a/talpid-openvpn-plugin/src/processing.rs +++ b/talpid-openvpn-plugin/src/processing.rs @@ -1,10 +1,15 @@ use openvpn_plugin; use std::collections::HashMap; use std::sync::Mutex; -use talpid_ipc::{IpcServerId, WsIpcClient}; +use talpid_ipc::WsIpcClient; + +use super::Arguments; error_chain! { errors { + AuthDenied { + description("Authentication failed with Talpid Core IPC server") + } IpcSendingError { description("Failed while sending an event over the IPC channel") } @@ -18,10 +23,18 @@ pub struct EventProcessor { } impl EventProcessor { - pub fn new(server_id: &IpcServerId) -> Result<EventProcessor> { + pub fn new(arguments: &Arguments) -> Result<EventProcessor> { trace!("Creating EventProcessor"); - let ipc_client = - WsIpcClient::connect(server_id).chain_err(|| "Unable to create IPC client")?; + let mut ipc_client = + WsIpcClient::connect(&arguments.server_id).chain_err(|| "Unable to create IPC client")?; + + trace!("Authenticating EventProcessor"); + match ipc_client.call("authenticate", &[&arguments.credentials]) { + Ok(true) => trace!("Credentials accepted"), + Ok(false) => bail!(ErrorKind::AuthDenied), + Err(error) => bail!(Error::with_chain(error, ErrorKind::AuthDenied)), + } + Ok(EventProcessor { ipc_client: Mutex::new(ipc_client), }) |
