diff options
| author | 2020-05-17 22:07:59 +0200 | |
|---|---|---|
| committer | 2020-05-17 22:07:59 +0200 | |
| commit | 16f21989b476f6dae5de0cf1607805cfc308a0f5 (patch) | |
| tree | 34909cd00f757093988b8ae9139cb2dd25373bd3 /src | |
| parent | Remove "list_peers" and "lookup_peer". (diff) | |
| download | wireguard-rs-rm-dummy.tar.xz wireguard-rs-rm-dummy.zip | |
Elimited Daemonize dependencyrm-dummy
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 43 | ||||
| -rw-r--r-- | src/util.rs | 86 |
2 files changed, 111 insertions, 18 deletions
diff --git a/src/main.rs b/src/main.rs index bf42706..fb5ac2f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,9 +13,9 @@ mod configuration; mod platform; mod wireguard; -use log; +mod util; -use daemonize::Daemonize; +use log; use std::env; use std::process::exit; @@ -62,14 +62,14 @@ fn main() { let mut foreground = false; let mut args = env::args(); - args.next(); // skip path (argv[0]) - + // skip path (argv[0]) + args.next(); for arg in args { match arg.as_str() { "--foreground" | "-f" => { foreground = true; } - "--root" => { + "--disable-drop-privileges" => { drop_privileges = false; } dev => name = Some(dev.to_owned()), @@ -97,16 +97,26 @@ fn main() { exit(-3); }); - // daemonize + // drop privileges + if drop_privileges { + match util::drop_privileges() { + Ok(_) => (), + Err(e) => { + eprintln!("Failed to drop privileges: {}", e); + exit(-4); + } + } + } + + // daemonize to background if !foreground { - let daemonize = Daemonize::new() - .pid_file(format!("/tmp/wireguard-rs-{}.pid", name)) - .chown_pid_file(true) - .working_directory("/tmp") - .user("nobody") - .group("daemon") - .umask(0o777); - daemonize.start().expect("Failed to daemonize"); + match util::daemonize() { + Ok(_) => (), + Err(e) => { + eprintln!("Failed to daemonize: {}", e); + exit(-5); + } + } } // start logging @@ -114,10 +124,7 @@ fn main() { .try_init() .expect("Failed to initialize event logger"); - log::info!("starting {} wireguard device", name); - - // drop privileges - if drop_privileges {} + log::info!("Starting {} WireGuard device.", name); // start profiler (if enabled) #[cfg(feature = "profiler")] diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..dd7a669 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,86 @@ +use std::fmt; +use std::process::exit; + +use libc::{c_char, chdir, chroot, fork, getpwnam, getuid, setgid, setsid, setuid, umask}; + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] +pub enum DaemonizeError { + Fork, + SetSession, + SetGroup, + SetUser, + Chroot, + Chdir, +} + +impl fmt::Display for DaemonizeError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + DaemonizeError::Fork => "unable to fork", + DaemonizeError::SetSession => "unable to create new process session", + DaemonizeError::SetGroup => "unable to set group (drop privileges)", + DaemonizeError::SetUser => "unable to set user (drop privileges)", + DaemonizeError::Chroot => "unable to enter chroot jail", + DaemonizeError::Chdir => "failed to change directory", + } + .fmt(f) + } +} + +fn fork_and_exit() -> Result<(), DaemonizeError> { + let pid = unsafe { fork() }; + if pid < 0 { + Err(DaemonizeError::Fork) + } else if pid == 0 { + Ok(()) + } else { + exit(0); + } +} + +pub fn daemonize() -> Result<(), DaemonizeError> { + // fork from the original parent + fork_and_exit()?; + + // avoid killing the child when this parent dies + if unsafe { setsid() } < 0 { + return Err(DaemonizeError::SetSession); + } + + // fork again to create orphan + fork_and_exit() +} + +pub fn drop_privileges() -> Result<(), DaemonizeError> { + // retrieve nobody's uid & gid + let usr = unsafe { getpwnam("nobody\x00".as_ptr() as *const c_char) }; + if usr.is_null() { + return Err(DaemonizeError::SetGroup); + } + + // change root directory + let uid = unsafe { getuid() }; + if uid == 0 && unsafe { chroot("/tmp\x00".as_ptr() as *const c_char) } != 0 { + return Err(DaemonizeError::Chroot); + } + + // set umask for files + unsafe { umask(0) }; + + // change directory + if unsafe { chdir("/\x00".as_ptr() as *const c_char) } != 0 { + return Err(DaemonizeError::Chdir); + } + + // set group id to nobody + if unsafe { setgid((*usr).pw_gid) } != 0 { + return Err(DaemonizeError::SetGroup); + } + + // set user id to nobody + if unsafe { setuid((*usr).pw_uid) } != 0 { + Err(DaemonizeError::SetUser) + } else { + Ok(()) + } +} |
