diff options
author | Mathias Hall-Andersen <mathias@hall-andersen.dk> | 2020-05-17 22:07:59 +0200 |
---|---|---|
committer | Mathias Hall-Andersen <mathias@hall-andersen.dk> | 2020-05-17 22:07:59 +0200 |
commit | 16f21989b476f6dae5de0cf1607805cfc308a0f5 (patch) | |
tree | 34909cd00f757093988b8ae9139cb2dd25373bd3 /src/util.rs | |
parent | Remove "list_peers" and "lookup_peer". (diff) | |
download | wireguard-rs-16f21989b476f6dae5de0cf1607805cfc308a0f5.tar.xz wireguard-rs-16f21989b476f6dae5de0cf1607805cfc308a0f5.zip |
Elimited Daemonize dependencyrm-dummy
Diffstat (limited to '')
-rw-r--r-- | src/util.rs | 86 |
1 files changed, 86 insertions, 0 deletions
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(()) + } +} |