aboutsummaryrefslogtreecommitdiffstats
path: root/src/util.rs
diff options
context:
space:
mode:
authorMathias Hall-Andersen <mathias@hall-andersen.dk>2020-05-17 22:07:59 +0200
committerMathias Hall-Andersen <mathias@hall-andersen.dk>2020-05-17 22:07:59 +0200
commit16f21989b476f6dae5de0cf1607805cfc308a0f5 (patch)
tree34909cd00f757093988b8ae9139cb2dd25373bd3 /src/util.rs
parentRemove "list_peers" and "lookup_peer". (diff)
downloadwireguard-rs-16f21989b476f6dae5de0cf1607805cfc308a0f5.tar.xz
wireguard-rs-16f21989b476f6dae5de0cf1607805cfc308a0f5.zip
Elimited Daemonize dependencyrm-dummy
Diffstat (limited to '')
-rw-r--r--src/util.rs86
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(())
+ }
+}