aboutsummaryrefslogtreecommitdiffstats
path: root/src/configuration/uapi
diff options
context:
space:
mode:
authorMathias Hall-Andersen <mathias@hall-andersen.dk>2019-11-10 17:57:39 +0100
committerMathias Hall-Andersen <mathias@hall-andersen.dk>2019-11-10 17:57:39 +0100
commit2ff044dda954ad2402309bd9022b33dd385bb3d7 (patch)
tree3030233c8958c96e292a4f3dd80a7622eb042c26 /src/configuration/uapi
parentRemoval of secret key in the handshake module (diff)
downloadwireguard-rs-2ff044dda954ad2402309bd9022b33dd385bb3d7.tar.xz
wireguard-rs-2ff044dda954ad2402309bd9022b33dd385bb3d7.zip
Implemented UAPI "get" line-parser
Diffstat (limited to 'src/configuration/uapi')
-rw-r--r--src/configuration/uapi/get.rs15
-rw-r--r--src/configuration/uapi/mod.rs4
-rw-r--r--src/configuration/uapi/set.rs215
3 files changed, 234 insertions, 0 deletions
diff --git a/src/configuration/uapi/get.rs b/src/configuration/uapi/get.rs
new file mode 100644
index 0000000..c6f3c42
--- /dev/null
+++ b/src/configuration/uapi/get.rs
@@ -0,0 +1,15 @@
+use hex::FromHex;
+use subtle::ConstantTimeEq;
+use x25519_dalek::{PublicKey, StaticSecret};
+
+use super::{ConfigError, Configuration};
+
+struct Serializer<C: Configuration> {
+ config: C,
+}
+
+impl<C: Configuration> Serializer<C> {
+ fn get(&self) -> Vec<String> {
+ vec![]
+ }
+}
diff --git a/src/configuration/uapi/mod.rs b/src/configuration/uapi/mod.rs
new file mode 100644
index 0000000..5d89b94
--- /dev/null
+++ b/src/configuration/uapi/mod.rs
@@ -0,0 +1,4 @@
+mod get;
+mod set;
+
+use super::{ConfigError, Configuration};
diff --git a/src/configuration/uapi/set.rs b/src/configuration/uapi/set.rs
new file mode 100644
index 0000000..575c7ad
--- /dev/null
+++ b/src/configuration/uapi/set.rs
@@ -0,0 +1,215 @@
+use hex::FromHex;
+use subtle::ConstantTimeEq;
+use x25519_dalek::{PublicKey, StaticSecret};
+
+use super::{ConfigError, Configuration};
+
+#[derive(Copy, Clone)]
+enum ParserState {
+ Peer {
+ public_key: PublicKey, // peer identity
+ update_only: bool, // is the update_only flag set
+ },
+ Interface,
+}
+
+struct LineParser<C: Configuration> {
+ config: C,
+ state: ParserState,
+}
+
+struct Serializer<C: Configuration> {
+ config: C,
+}
+
+impl<C: Configuration> LineParser<C> {
+ fn new_peer(value: &str) -> Result<ParserState, ConfigError> {
+ match <[u8; 32]>::from_hex(value) {
+ Ok(pk) => Ok(ParserState::Peer {
+ public_key: PublicKey::from(pk),
+ update_only: false,
+ }),
+ Err(_) => Err(ConfigError::InvalidHexValue),
+ }
+ }
+
+ fn parse_line(&mut self, key: &str, value: &str) -> Option<ConfigError> {
+ let flush_peer = |st: ParserState| -> ParserState {
+ match st {
+ ParserState::Peer {
+ public_key,
+ update_only: false,
+ } => {
+ self.config.add_peer(&public_key);
+ ParserState::Peer {
+ public_key,
+ update_only: true,
+ }
+ }
+ _ => st,
+ }
+ };
+
+ // parse line and update parser state
+ let new_state = match self.state {
+ // configure the interface
+ ParserState::Interface => match key {
+ // opt: set private key
+ "private_key" => match <[u8; 32]>::from_hex(value) {
+ Ok(sk) => {
+ self.config.set_private_key(if sk == [0u8; 32] {
+ None
+ } else {
+ Some(StaticSecret::from(sk))
+ });
+ Ok(self.state)
+ }
+ Err(_) => Err(ConfigError::InvalidHexValue),
+ },
+
+ // opt: set listen port
+ "listen_port" => match value.parse() {
+ Ok(port) => {
+ self.config.set_listen_port(Some(port));
+ Ok(self.state)
+ }
+ Err(_) => Err(ConfigError::InvalidPortNumber),
+ },
+
+ // opt: set fwmark
+ "fwmark" => match value.parse() {
+ Ok(fwmark) => {
+ self.config
+ .set_fwmark(if fwmark == 0 { None } else { Some(fwmark) });
+ Ok(self.state)
+ }
+ Err(_) => Err(ConfigError::InvalidFwmark),
+ },
+
+ // opt: remove all peers
+ "replace_peers" => match value {
+ "true" => {
+ for p in self.config.get_peers() {
+ self.config.remove_peer(&p.public_key)
+ }
+ Ok(self.state)
+ }
+ _ => Err(ConfigError::UnsupportedValue),
+ },
+
+ // opt: transition to peer configuration
+ "public_key" => Self::new_peer(value),
+
+ // unknown key
+ _ => Err(ConfigError::InvalidKey),
+ },
+
+ // configure peers
+ ParserState::Peer { public_key, .. } => match key {
+ // opt: new peer
+ "public_key" => {
+ flush_peer(self.state);
+ Self::new_peer(value)
+ }
+
+ // opt: remove peer
+ "remove" => {
+ self.config.remove_peer(&public_key);
+ Ok(self.state)
+ }
+
+ // opt: update only
+ "update_only" => Ok(ParserState::Peer {
+ public_key,
+ update_only: true,
+ }),
+
+ // opt: set preshared key
+ "preshared_key" => match <[u8; 32]>::from_hex(value) {
+ Ok(psk) => {
+ let st = flush_peer(self.state);
+ self.config.set_preshared_key(
+ &public_key,
+ if psk.ct_eq(&[0u8; 32]).into() {
+ None
+ } else {
+ Some(psk)
+ },
+ );
+ Ok(st)
+ }
+ Err(_) => Err(ConfigError::InvalidHexValue),
+ },
+
+ // opt: set endpoint
+ "endpoint" => match value.parse() {
+ Ok(endpoint) => {
+ let st = flush_peer(self.state);
+ self.config.set_endpoint(&public_key, endpoint);
+ Ok(st)
+ }
+ Err(_) => Err(ConfigError::InvalidSocketAddr),
+ },
+
+ // opt: set persistent keepalive interval
+ "persistent_keepalive_interval" => match value.parse() {
+ Ok(secs) => {
+ let st = flush_peer(self.state);
+ self.config
+ .set_persistent_keepalive_interval(&public_key, secs);
+ Ok(st)
+ }
+ Err(_) => Err(ConfigError::InvalidKeepaliveInterval),
+ },
+
+ // opt replace allowed ips
+ "replace_allowed_ips" => {
+ let st = flush_peer(self.state);
+ self.config.replace_allowed_ips(&public_key);
+ Ok(st)
+ }
+
+ // opt add allowed ips
+ "allowed_ip" => {
+ let mut split = value.splitn(2, "/");
+ let addr = split.next().and_then(|x| x.parse().ok());
+ let cidr = split.next().and_then(|x| x.parse().ok());
+ match (addr, cidr) {
+ (Some(addr), Some(cidr)) => {
+ let st = flush_peer(self.state);
+ self.config.add_allowed_ip(&public_key, addr, cidr);
+ Ok(st)
+ }
+ _ => Err(ConfigError::InvalidAllowedIp),
+ }
+ }
+
+ // set protocol version of peer
+ "protocol_version" => {
+ let parse_res: Result<usize, _> = value.parse();
+ match parse_res {
+ Ok(version) => {
+ if version == 0 || version > self.config.get_protocol_version() {
+ Err(ConfigError::UnsupportedProtocolVersion)
+ } else {
+ Ok(self.state)
+ }
+ }
+ Err(_) => Err(ConfigError::UnsupportedProtocolVersion),
+ }
+ }
+
+ // unknown key
+ _ => Err(ConfigError::InvalidKey),
+ },
+ };
+
+ match new_state {
+ Err(e) => Some(e),
+ Ok(st) => {
+ self.state = st;
+ None
+ }
+ }
+ }
+}