aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReiner Herrmann <reiner@reiner-h.de>2019-03-24 16:11:14 +0100
committerReiner Herrmann <reiner@reiner-h.de>2019-03-24 16:11:14 +0100
commit110876b09ba20673d6984589bdb2778a06916530 (patch)
tree2b79a42f66cde1858d40c6d7aaa480dae6898cb7
parentfb7b378d8709e5d861876f40cb5c408fdb5b2a43 (diff)
chroot to destination directory when having sufficient permissions
-rw-r--r--src/tftpd.rs29
1 files changed, 26 insertions, 3 deletions
diff --git a/src/tftpd.rs b/src/tftpd.rs
index c45f6e1..a833998 100644
--- a/src/tftpd.rs
+++ b/src/tftpd.rs
@@ -13,7 +13,7 @@ use std::path::{Path, PathBuf};
use std::time::Duration;
extern crate nix;
-use nix::unistd::{setresgid, setresuid, Gid, Uid};
+use nix::unistd::{chroot, setresgid, setresuid, Gid, Uid, ROOT};
extern crate getopts;
use getopts::Options;
@@ -218,7 +218,7 @@ impl Tftpd {
}
fn drop_privs(&self, uid: u32, gid: u32) -> Result<(), Box<Error>> {
- let root_uid = Uid::from_raw(0);
+ let root_uid = ROOT;
let root_gid = Gid::from_raw(0);
let unpriv_uid = Uid::from_raw(uid);
let unpriv_gid = Gid::from_raw(gid);
@@ -243,6 +243,22 @@ impl Tftpd {
Ok(())
}
+ fn chroot_destdir(&mut self) -> Result<(), nix::Error> {
+ /* chroot will only succeed if we have required permissions;
+ either running as root or having CAP_SYS_CHROOT.
+ propagate error only if chroot should have succeeded. */
+ match chroot(&self.conf.dir) {
+ Ok(_) => {
+ /* configured dir is now new root directory */
+ self.conf.dir = PathBuf::from("/");
+ Ok(())
+ },
+ Err(err) if err == nix::Error::from_errno(nix::errno::Errno::EPERM) => Ok(()),
+ Err(err) if Uid::effective() == ROOT => Err(err),
+ Err(_) => Ok(()),
+ }
+ }
+
pub fn start(&mut self) {
let socket = match UdpSocket::bind(format!("[::]:{}", self.conf.port)) {
Ok(s) => s,
@@ -251,6 +267,13 @@ impl Tftpd {
return;
}
};
+ match self.chroot_destdir() {
+ Ok(_) => {},
+ Err(err) => {
+ eprintln!("Changing root directory failed ({}).", err);
+ return;
+ }
+ }
match self.drop_privs(self.conf.uid, self.conf.gid) {
Ok(_) => (),
Err(err) => {
@@ -262,7 +285,7 @@ impl Tftpd {
match env::set_current_dir(&self.conf.dir) {
Ok(_) => (),
Err(err) => {
- eprintln!("Changing directory to {} failed ({}).", &self.conf.dir.display(), err);
+ eprintln!("Changing directory failed ({}).", err);
return;
}
}