Compare commits

...

2 Commits

Author SHA1 Message Date
wucke13
c2f8f9006a add control socket serde code 2023-10-19 23:40:08 +02:00
wucke13
c072b7825f add uds control socket to rosenpass
- add new, optional configuration parameter to the config file, `control_socket`
- enhance debug and trace logging in `app_server.rs`
- add optional attribute `maybe_control_socket` to `AppServer`
- registers the uds (if present) in mio, so that one `mio::poll` call can both check on control commands and normal handshake traffic
- sprinkle a little more documentation over `app_server.rs`
- inject control socket handling skeleton code to `AppServer::try_recv`
  - control socket is always processed first, then incoming traffic
2023-09-23 13:21:58 +02:00
6 changed files with 99 additions and 2 deletions

View File

@@ -2,6 +2,7 @@ public_key = "peer-a-public-key"
secret_key = "peer-a-secret-key"
listen = ["[::]:10001"]
verbosity = "Quiet"
control_socket = "rosenpassd.sock"
[[peers]]
public_key = "peer-b-public-key"

View File

@@ -1,6 +1,8 @@
use anyhow::bail;
use anyhow::Result;
use log::debug;
use log::trace;
use log::{error, info, warn};
use mio::Interest;
use mio::Token;
@@ -15,6 +17,7 @@ use std::net::SocketAddr;
use std::net::SocketAddrV4;
use std::net::SocketAddrV6;
use std::net::ToSocketAddrs;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use std::process::Stdio;
@@ -30,6 +33,7 @@ use crate::{
const IPV4_ANY_ADDR: Ipv4Addr = Ipv4Addr::new(0, 0, 0, 0);
const IPV6_ANY_ADDR: Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
const CONTROL_SOCKET_TOKEN: mio::Token = mio::Token(usize::MAX);
fn ipv4_any_binding() -> SocketAddr {
// addr, port
@@ -78,6 +82,9 @@ pub struct AppServer {
pub peers: Vec<AppPeer>,
pub verbosity: Verbosity,
pub all_sockets_drained: bool,
/// Optional control socket to change the configuration of a running rosenpassd
pub maybe_control_socket: Option<mio::net::UnixDatagram>,
}
/// A socket pointer is an index assigned to a socket;
@@ -335,11 +342,13 @@ impl HostPathDiscoveryEndpoint {
}
impl AppServer {
pub fn new(
pub fn new<P: AsRef<Path> + core::fmt::Debug>(
// TODO @wucke13 check if requiring Debug breaks important types that otherwise fulfill AsRef<Path>
sk: SSk,
pk: SPk,
addrs: Vec<SocketAddr>,
verbosity: Verbosity,
uds: Option<P>,
) -> anyhow::Result<Self> {
// setup mio
let mio_poll = mio::Poll::new()?;
@@ -417,13 +426,31 @@ impl AppServer {
}
// register all sockets to mio
debug!("registering all UDP sockets to mio");
for (i, socket) in sockets.iter_mut().enumerate() {
trace!("registering {socket:?}");
mio_poll
.registry()
.register(socket, Token(i), Interest::READABLE)?;
}
let mut maybe_control_socket = uds
.map(|p| {
debug!("binding control socket {p:?}");
mio::net::UnixDatagram::bind(p)
})
.transpose()?;
if let Some(control_socket) = &mut maybe_control_socket {
debug!("registering control socket to mio");
mio_poll.registry().register(
control_socket,
CONTROL_SOCKET_TOKEN,
Interest::READABLE,
)?;
}
// TODO use mio::net::UnixStream together with std::os::unix::net::UnixStream for Linux
debug!("finalizing AppServer creation");
Ok(Self {
crypt: CryptoServer::new(sk, pk),
@@ -433,6 +460,7 @@ impl AppServer {
events,
mio_poll,
all_sockets_drained: false,
maybe_control_socket,
})
}
@@ -638,6 +666,7 @@ impl AppServer {
Ok(())
}
// Polls the crypto servers state machine for new actions
pub fn poll(&mut self, rx_buf: &mut [u8]) -> anyhow::Result<AppPollResult> {
use crate::protocol::PollResult as C;
use AppPollResult as A;
@@ -654,7 +683,7 @@ impl AppServer {
}
}
/// Tries to receive a new message
/// Tries to receive a new control socket command or incoming message
///
/// - might wait for an duration up to `timeout`
/// - returns immediately if an error occurs
@@ -693,6 +722,27 @@ impl AppServer {
self.mio_poll.poll(&mut self.events, Some(timeout))?;
}
trace!("checking for new command on control socket");
// control socket always has priority
if let Some(control_socket) = &mut self.maybe_control_socket {
let mut buf = [0u8; 16];
match control_socket.recv(&mut buf) {
Ok(size) => {
// TODO handle command
// to send something here, use the following shell snippet:
//
// printf '\x7\' | nc -NuU rosenpassd.sock
log::debug!("buf received {:?}", &buf[0..size]);
}
Err(e) if e.kind() == ErrorKind::WouldBlock => {
trace!("no new commands on control socket")
}
Err(e) => return Err(e.into()),
}
}
// then normal traffic is processed
let mut would_block_count = 0;
for (sock_no, socket) in self.sockets.iter_mut().enumerate() {
match socket.recv_from(buf) {

View File

@@ -228,6 +228,7 @@ impl Cli {
pk,
config.listen,
config.verbosity,
config.control_socket.as_ref(),
)?);
for cfg_peer in config.peers {

View File

@@ -25,6 +25,8 @@ pub struct Rosenpass {
#[serde(skip)]
pub config_file_path: PathBuf,
pub control_socket: Option<PathBuf>,
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
@@ -133,6 +135,7 @@ impl Rosenpass {
verbosity: Verbosity::Quiet,
peers: vec![],
config_file_path: PathBuf::new(),
control_socket: None,
}
}

38
src/control_commands.rs Normal file
View File

@@ -0,0 +1,38 @@
//! Data structures representing the control messages going over the control socket
//!
//! This module uses the same de-/serialization mechanism as [crate::msgs].
//! If you want to interface with `rosenpassd`, this is where you can look up the format
//! of the messages that are accepted.
use crate::{data_lense, msgs::LenseView, RosenpassError};
data_lense! { ControlComand<C> :=
/// [MsgType] of this message
msg_type: 1
}
#[repr(u8)]
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
pub enum CommandType {
/// Add one peer
AddPeer = 0x10,
/// Remove all peers that match the given public key
RemovePeerPk = 0x11,
/// Remove all peers that match the given address
RemovePeerIp = 0x12,
}
impl TryFrom<u8> for CommandType {
type Error = RosenpassError;
fn try_from(value: u8) -> Result<Self, Self::Error> {
Ok(match value {
0x10 => CommandType::AddPeer,
0x11 => CommandType::RemovePeerPk,
0x12 => CommandType::RemovePeerIp,
_ => return Err(RosenpassError::InvalidMessageType(value)),
})
}
}

View File

@@ -8,6 +8,7 @@ pub mod labeled_prf;
pub mod app_server;
pub mod cli;
pub mod config;
pub mod control_commands;
pub mod msgs;
pub mod pqkem;
pub mod prftree;
@@ -26,6 +27,9 @@ pub enum RosenpassError {
},
#[error("invalid message type")]
InvalidMessageType(u8),
#[error("invalid command type")]
InvalidCommandType(u8),
}
impl RosenpassError {