diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2017-01-30 10:08:54 +0100 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2017-01-30 10:08:54 +0100 |
| commit | c97361153b0a78c3f60baeca480f60a218eea05d (patch) | |
| tree | 46e2c6bbdd70e37addc2442ff6d1720e12bc30e0 | |
| parent | 5532e6e805644d23ea446e0608f5a76023345199 (diff) | |
| parent | 587d145c32a5225bc845d13d50502564e1db96df (diff) | |
| download | mullvadvpn-c97361153b0a78c3f60baeca480f60a218eea05d.tar.xz mullvadvpn-c97361153b0a78c3f60baeca480f60a218eea05d.zip | |
Merge branch 'initial-openvpn-plugin'
| -rw-r--r-- | Cargo.toml | 3 | ||||
| -rw-r--r-- | talpid_openvpn_plugin/Cargo.lock | 14 | ||||
| -rw-r--r-- | talpid_openvpn_plugin/Cargo.toml | 10 | ||||
| -rw-r--r-- | talpid_openvpn_plugin/src/ffi/consts.rs | 79 | ||||
| -rw-r--r-- | talpid_openvpn_plugin/src/ffi/mod.rs | 92 | ||||
| -rw-r--r-- | talpid_openvpn_plugin/src/lib.rs | 8 |
6 files changed, 206 insertions, 0 deletions
diff --git a/Cargo.toml b/Cargo.toml index bee6d9852c..3f273a71ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,3 +5,6 @@ authors = ["Linus Färnstrand <linus@mullvad.net>"] [dependencies] clonablechild = "0.1" + +[dependencies.talpid_openvpn_plugin] +path = "talpid_openvpn_plugin" diff --git a/talpid_openvpn_plugin/Cargo.lock b/talpid_openvpn_plugin/Cargo.lock new file mode 100644 index 0000000000..6bbe450750 --- /dev/null +++ b/talpid_openvpn_plugin/Cargo.lock @@ -0,0 +1,14 @@ +[root] +name = "talpid_openvpn_plugin" +version = "0.1.0" +dependencies = [ + "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b" diff --git a/talpid_openvpn_plugin/Cargo.toml b/talpid_openvpn_plugin/Cargo.toml new file mode 100644 index 0000000000..be65a23f4a --- /dev/null +++ b/talpid_openvpn_plugin/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "talpid_openvpn_plugin" +version = "0.1.0" +authors = ["Linus Färnstrand <linus@mullvad.net>"] + +[lib] +crate-type = ["dylib"] + +[dependencies] +lazy_static = "0.2" diff --git a/talpid_openvpn_plugin/src/ffi/consts.rs b/talpid_openvpn_plugin/src/ffi/consts.rs new file mode 100644 index 0000000000..ca82606751 --- /dev/null +++ b/talpid_openvpn_plugin/src/ffi/consts.rs @@ -0,0 +1,79 @@ +/// Constants for OpenVPN. Taken from include/openvpn-plugin.h in the OpenVPN repository: +/// https://github.com/OpenVPN/openvpn/blob/master/include/openvpn-plugin.h.in + +use std::collections::HashMap; +use std::os::raw::c_int; + + +// All types of events that a plugin can receive from OpenVPN. +pub const OPENVPN_PLUGIN_UP: c_int = 0; +pub const OPENVPN_PLUGIN_DOWN: c_int = 1; +pub const OPENVPN_PLUGIN_ROUTE_UP: c_int = 2; +pub const OPENVPN_PLUGIN_IPCHANGE: c_int = 3; +pub const OPENVPN_PLUGIN_TLS_VERIFY: c_int = 4; +pub const OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY: c_int = 5; +pub const OPENVPN_PLUGIN_CLIENT_CONNECT: c_int = 6; +pub const OPENVPN_PLUGIN_CLIENT_DISCONNECT: c_int = 7; +pub const OPENVPN_PLUGIN_LEARN_ADDRESS: c_int = 8; +pub const OPENVPN_PLUGIN_CLIENT_CONNECT_V2: c_int = 9; +pub const OPENVPN_PLUGIN_TLS_FINAL: c_int = 10; +pub const OPENVPN_PLUGIN_ENABLE_PF: c_int = 11; +pub const OPENVPN_PLUGIN_ROUTE_PREDOWN: c_int = 12; +pub const OPENVPN_PLUGIN_N: c_int = 13; + +lazy_static! { + pub static ref PLUGIN_EVENT_NAMES: HashMap<c_int, &'static str> = { + let mut map = HashMap::new(); + map.insert(OPENVPN_PLUGIN_UP, "PLUGIN_UP"); + map.insert(OPENVPN_PLUGIN_DOWN, "PLUGIN_DOWN"); + map.insert(OPENVPN_PLUGIN_ROUTE_UP, "PLUGIN_ROUTE_UP"); + map.insert(OPENVPN_PLUGIN_IPCHANGE, "PLUGIN_IPCHANGE"); + map.insert(OPENVPN_PLUGIN_TLS_VERIFY, "PLUGIN_TLS_VERIFY"); + map.insert(OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY, "PLUGIN_AUTH_USER_PASS_VERIFY"); + map.insert(OPENVPN_PLUGIN_CLIENT_CONNECT, "PLUGIN_CLIENT_CONNECT"); + map.insert(OPENVPN_PLUGIN_CLIENT_DISCONNECT, "PLUGIN_CLIENT_DISCONNECT"); + map.insert(OPENVPN_PLUGIN_LEARN_ADDRESS, "PLUGIN_LEARN_ADDRESS"); + map.insert(OPENVPN_PLUGIN_CLIENT_CONNECT_V2, "PLUGIN_CLIENT_CONNECT_V2"); + map.insert(OPENVPN_PLUGIN_TLS_FINAL, "PLUGIN_TLS_FINAL"); + map.insert(OPENVPN_PLUGIN_ENABLE_PF, "PLUGIN_ENABLE_PF"); + map.insert(OPENVPN_PLUGIN_ROUTE_PREDOWN, "PLUGIN_ROUTE_PREDOWN"); + map.insert(OPENVPN_PLUGIN_N, "PLUGIN_N"); + map + }; +} + +/// Returns the name of an OPENVPN_PLUGIN_* constant. +pub fn plugin_event_name(num: c_int) -> &'static str { + PLUGIN_EVENT_NAMES.get(&num).map(|s| *s).unwrap_or("UNKNOWN") +} + + +// Return values. Returned from the plugin to OpenVPN to indicate success or failure. Can also +// Accept (success) or decline (error) an operation, such as incoming client connection attempt. +pub const OPENVPN_PLUGIN_FUNC_SUCCESS: c_int = 0; +pub const OPENVPN_PLUGIN_FUNC_ERROR: c_int = 1; +pub const OPENVPN_PLUGIN_FUNC_DEFERRED: c_int = 2; + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn plugin_event_name_up() { + let name = plugin_event_name(0); + assert_eq!("PLUGIN_UP", name); + } + + #[test] + fn plugin_event_name_n() { + let name = plugin_event_name(13); + assert_eq!("PLUGIN_N", name); + } + + #[test] + fn plugin_event_name_not_existing() { + let name = plugin_event_name(-15); + assert_eq!("UNKNOWN", name); + } +} diff --git a/talpid_openvpn_plugin/src/ffi/mod.rs b/talpid_openvpn_plugin/src/ffi/mod.rs new file mode 100644 index 0000000000..019decf157 --- /dev/null +++ b/talpid_openvpn_plugin/src/ffi/mod.rs @@ -0,0 +1,92 @@ +/// FFI definitions for OpenVPN. See include/openvpn-plugin.h in the OpenVPN repository for +/// the original declarations of these structs and functions along with documentation for them: +/// https://github.com/OpenVPN/openvpn/blob/master/include/openvpn-plugin.h.in + +use std::os::raw::{c_char, c_int, c_uint, c_void}; + + +#[allow(dead_code)] +mod consts; +use self::consts::*; + + +/// Struct sent to `openvpn_plugin_open_v3` containing input values. +#[repr(C)] +pub struct openvpn_plugin_args_open_in { + type_mask: c_int, + argv: *const *const c_char, + envp: *const *const c_char, + callbacks: *const c_void, + ssl_api: ovpnSSLAPI, + ovpn_version: *const c_char, + ovpn_version_major: c_uint, + ovpn_version_minor: c_uint, + ovpn_version_patch: *const c_char, +} + +#[allow(dead_code)] +#[repr(C)] +enum ovpnSSLAPI { + SSLAPI_NONE, + SSLAPI_OPENSSL, + SSLAPI_MBEDTLS, +} + +/// Struct used for returning values from `openvpn_plugin_open_v3` to OpenVPN. +#[repr(C)] +pub struct openvpn_plugin_args_open_return { + type_mask: c_int, + handle: *const c_void, + return_list: *const c_void, +} + +/// Struct sent to `openvpn_plugin_func_v3` containing input values. +#[repr(C)] +pub struct openvpn_plugin_args_func_in { + event_type: c_int, + argv: *const *const c_char, + envp: *const *const c_char, + handle: *const c_void, + per_client_context: *const c_void, + current_cert_depth: c_int, + current_cert: *const c_void, +} + +/// Struct used for returning values from `openvpn_plugin_func_v3` to OpenVPN. +#[repr(C)] +pub struct openvpn_plugin_args_func_return { + return_list: *const c_void, +} + + +/// Called by OpenVPN when the plugin is first loaded. +/// Used to register which events the plugin wants to listen to (`type_mask`). Can also return an +/// arbitrary object inside `handle` that will then be passed to all subsequent calls to the +/// plugin. +#[no_mangle] +pub extern "C" fn openvpn_plugin_open_v3(_version: c_int, + _args: *const openvpn_plugin_args_open_in, + _retptr: *mut openvpn_plugin_args_open_return) + -> c_int { + println!("openvpn_plugin_open_v3()"); + OPENVPN_PLUGIN_FUNC_SUCCESS +} + +/// Called by OpenVPN just before the plugin is unloaded. Should correctly close the plugin and +/// deallocate any `handle` initialized by the plugin in `openvpn_plugin_open_v3` +#[no_mangle] +pub extern "C" fn openvpn_plugin_close_v1(_handle: *const c_void) { + println!("openvpn_plugin_close_v1()"); +} + +/// Called by OpenVPN for each OPENVPN_PLUGIN_* event that it registered for in +/// `openvpn_plugin_open_v3` +#[no_mangle] +pub extern "C" fn openvpn_plugin_func_v3(_version: c_int, + args: *const openvpn_plugin_args_func_in, + _retptr: *const openvpn_plugin_args_func_return) + -> c_int { + let event_name = unsafe { consts::plugin_event_name((*args).event_type) }; + println!("openvpn_plugin_func_v3({})", event_name); + OPENVPN_PLUGIN_FUNC_SUCCESS +} diff --git a/talpid_openvpn_plugin/src/lib.rs b/talpid_openvpn_plugin/src/lib.rs new file mode 100644 index 0000000000..a917ead7a5 --- /dev/null +++ b/talpid_openvpn_plugin/src/lib.rs @@ -0,0 +1,8 @@ +#[macro_use] +extern crate lazy_static; + +mod ffi; + +/// Publicly export the functions making up the public interface of the plugin. These are the C FFI +/// functions called by OpenVPN. +pub use ffi::{openvpn_plugin_open_v3, openvpn_plugin_close_v1, openvpn_plugin_func_v3}; |
