From 1c2a97ffdf069b60a696a9825b56e61c08a10147 Mon Sep 17 00:00:00 2001 From: Reiner Herrmann Date: Sun, 24 Feb 2019 18:15:34 +0100 Subject: Bind to real tftp port (69) and drop privileges immediately after --- Cargo.toml | 1 + src/tftpd.rs | 44 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ab6e99f..0262809 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later" [dependencies] +nix = "0.13.0" [[bin]] name = "rtftpd" diff --git a/src/tftpd.rs b/src/tftpd.rs index 331b27d..68e82c7 100644 --- a/src/tftpd.rs +++ b/src/tftpd.rs @@ -1,10 +1,14 @@ use std::net::{SocketAddr,UdpSocket}; use std::fs::File; use std::path::Path; +use std::error::Error; use std::env; use std::io; use std::io::prelude::*; +extern crate nix; +use nix::unistd::{Gid,Uid,setresgid,setresuid}; + fn handle_wrq(_cl: &SocketAddr, _buf: &[u8]) -> Result<(), io::Error> { Ok(()) } @@ -175,12 +179,48 @@ fn handle_client(cl: &SocketAddr, buf: &[u8]) -> Result<(), io::Error> { Ok(()) } +fn drop_privs() -> Result<(), Box> { + let root_uid = Uid::from_raw(0); + let root_gid = Gid::from_raw(0); + let unpriv_uid = Uid::from_raw(65534); + let unpriv_gid = Gid::from_raw(65534); + + if Gid::current() == root_gid || Gid::effective() == root_gid { + setresgid(unpriv_gid, unpriv_gid, unpriv_gid)?; + } + + if Uid::current() == root_uid || Uid::effective() == root_uid { + setresuid(unpriv_uid, unpriv_uid, unpriv_uid)?; + } + + Ok(()) +} + fn main() { - let socket = UdpSocket::bind("127.0.0.1:12345").expect("Binding a socket failed."); + let socket = match UdpSocket::bind("0.0.0.0:69") { + Ok(s) => s, + Err(err) => { + println!("Binding a socket failed: {}", err); + return; + } + }; + match drop_privs() { + Ok(_) => (), + Err(err) => { + println!("Dropping privileges failed: {}", err); + return; + } + }; loop { let mut buf = [0; 2048]; - let (n, src) = socket.recv_from(&mut buf).expect("Receiving from the socket failed."); + let (n, src) = match socket.recv_from(&mut buf) { + Ok(args) => args, + Err(err) => { + println!("Receiving data from socket failed: {}", err); + break; + } + }; match handle_client(&src, &buf[0..n]) { /* errors intentionally ignored */ -- cgit v1.2.3