From 4f08d010b75e5ab887a5a88ca7d42814fd3918b1 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Fri, 24 Jan 2020 19:31:04 -0800 Subject: [PATCH] move unix listener to its own module --- src/server/listener/local.rs | 83 ++++++++++++++++++++++++++++++++++++ src/server/listener/mod.rs | 82 ++--------------------------------- 2 files changed, 87 insertions(+), 78 deletions(-) create mode 100644 src/server/listener/local.rs diff --git a/src/server/listener/local.rs b/src/server/listener/local.rs new file mode 100644 index 000000000..8dc7eb927 --- /dev/null +++ b/src/server/listener/local.rs @@ -0,0 +1,83 @@ +use crate::config::UnixDomain; +use crate::create_user_owned_dirs; +use crate::server::listener::{clientsession, umask}; +use crate::server::UnixListener; +use anyhow::{anyhow, bail, Context as _}; +use promise::spawn::spawn_into_main_thread; + +pub struct LocalListener { + listener: UnixListener, +} + +impl LocalListener { + pub fn new(listener: UnixListener) -> Self { + Self { listener } + } + + pub fn with_domain(unix_dom: &UnixDomain) -> anyhow::Result { + let listener = safely_create_sock_path(unix_dom)?; + Ok(Self::new(listener)) + } + + pub fn run(&mut self) { + for stream in self.listener.incoming() { + match stream { + Ok(stream) => { + spawn_into_main_thread(async move { + let mut session = clientsession::ClientSession::new(stream); + std::thread::spawn(move || session.run()); + }); + } + Err(err) => { + log::error!("accept failed: {}", err); + return; + } + } + } + } +} + +/// Take care when setting up the listener socket; +/// we need to be sure that the directory that we create it in +/// is owned by the user and has appropriate file permissions +/// that prevent other users from manipulating its contents. +fn safely_create_sock_path(unix_dom: &UnixDomain) -> anyhow::Result { + let sock_path = &unix_dom.socket_path(); + log::debug!("setting up {}", sock_path.display()); + + let _saver = umask::UmaskSaver::new(); + + let sock_dir = sock_path + .parent() + .ok_or_else(|| anyhow!("sock_path {} has no parent dir", sock_path.display()))?; + + create_user_owned_dirs(sock_dir)?; + + #[cfg(unix)] + { + use crate::running_under_wsl; + use std::os::unix::fs::PermissionsExt; + + if !running_under_wsl() && !unix_dom.skip_permissions_check { + // Let's be sure that the ownership looks sane + let meta = sock_dir.symlink_metadata()?; + + let permissions = meta.permissions(); + if (permissions.mode() & 0o22) != 0 { + bail!( + "The permissions for {} are insecure and currently \ + allow other users to write to it (permissions={:?})", + sock_dir.display(), + permissions + ); + } + } + } + + if sock_path.exists() { + std::fs::remove_file(sock_path)?; + } + + UnixListener::bind(sock_path) + .with_context(|| format!("Failed to bind to {}", sock_path.display())) +} diff --git a/src/server/listener/mod.rs b/src/server/listener/mod.rs index fc5c631b0..d0e92a100 100644 --- a/src/server/listener/mod.rs +++ b/src/server/listener/mod.rs @@ -1,18 +1,16 @@ -use crate::config::{configuration, TlsDomainServer, UnixDomain}; -use crate::create_user_owned_dirs; -use crate::server::UnixListener; +use crate::config::{configuration, TlsDomainServer}; use anyhow::{anyhow, bail, Context, Error}; -use log::{debug, error}; +use log::error; use native_tls::Identity; use promise::spawn::spawn_into_main_thread; use std::convert::TryFrom; -use std::fs::remove_file; use std::net::TcpListener; use std::path::{Path, PathBuf}; use std::sync::Arc; use std::thread; mod clientsession; +mod local; mod not_ossl; mod ossl; mod umask; @@ -22,33 +20,6 @@ use not_ossl as tls_impl; #[cfg(any(feature = "openssl", unix))] use ossl as tls_impl; -struct LocalListener { - listener: UnixListener, -} - -impl LocalListener { - pub fn new(listener: UnixListener) -> Self { - Self { listener } - } - - fn run(&mut self) { - for stream in self.listener.incoming() { - match stream { - Ok(stream) => { - spawn_into_main_thread(async move { - let mut session = clientsession::ClientSession::new(stream); - thread::spawn(move || session.run()); - }); - } - Err(err) => { - error!("accept failed: {}", err); - return; - } - } - } - } -} - #[derive(Debug)] pub enum IdentitySource { Pkcs12File { @@ -79,55 +50,10 @@ impl TryFrom for Identity { } } -/// Take care when setting up the listener socket; -/// we need to be sure that the directory that we create it in -/// is owned by the user and has appropriate file permissions -/// that prevent other users from manipulating its contents. -fn safely_create_sock_path(unix_dom: &UnixDomain) -> Result { - let sock_path = &unix_dom.socket_path(); - debug!("setting up {}", sock_path.display()); - - let _saver = umask::UmaskSaver::new(); - - let sock_dir = sock_path - .parent() - .ok_or_else(|| anyhow!("sock_path {} has no parent dir", sock_path.display()))?; - - create_user_owned_dirs(sock_dir)?; - - #[cfg(unix)] - { - use crate::running_under_wsl; - use std::os::unix::fs::PermissionsExt; - - if !running_under_wsl() && !unix_dom.skip_permissions_check { - // Let's be sure that the ownership looks sane - let meta = sock_dir.symlink_metadata()?; - - let permissions = meta.permissions(); - if (permissions.mode() & 0o22) != 0 { - bail!( - "The permissions for {} are insecure and currently \ - allow other users to write to it (permissions={:?})", - sock_dir.display(), - permissions - ); - } - } - } - - if sock_path.exists() { - remove_file(sock_path)?; - } - - UnixListener::bind(sock_path) - .with_context(|| format!("Failed to bind to {}", sock_path.display())) -} - pub fn spawn_listener() -> anyhow::Result<()> { let config = configuration(); for unix_dom in &config.unix_domains { - let mut listener = LocalListener::new(safely_create_sock_path(unix_dom)?); + let mut listener = local::LocalListener::with_domain(unix_dom)?; thread::spawn(move || { listener.run(); });