use crate::settings::Settings; use log::log; use std::ffi::CString; use std::io::{Error, ErrorKind}; // https://blog.lxsang.me/post/id/28.0 pub fn drop_privileges(settings: &Settings) -> Result<(), Error> { log::info!( "Dropping privileges to {}:{}", settings.user, settings.group ); // the group id need to be set first, because, when the user privileges drop, // we are unable to drop the group privileges if !settings.group.is_empty() { drop_privileges_group(&settings.group)?; } if !settings.user.is_empty() { drop_privileges_user(&settings.user)?; } Ok(()) } fn drop_privileges_group(group: &str) -> Result<(), Error> { // get the gid from username if let Ok(cstr) = CString::new(group.as_bytes()) { let p = unsafe { libc::getgrnam(cstr.as_ptr()) }; if p.is_null() { log::error!("Unable to getgrnam of group: {}", group); return Err(Error::last_os_error()); } if unsafe { libc::setgid((*p).gr_gid) } != 0 { log::error!("Unable to setgid of group: {}", group); return Err(Error::last_os_error()); } } else { return Err(Error::new( ErrorKind::Other, "Cannot create CString from String (group)!", )); } Ok(()) } fn drop_privileges_user(user: &str) -> Result<(), Error> { // get the uid from username if let Ok(cstr) = CString::new(user.as_bytes()) { let p = unsafe { libc::getpwnam(cstr.as_ptr()) }; if p.is_null() { log::error!("Unable to getpwnam of user: {}", user); return Err(Error::last_os_error()); } if unsafe { libc::setuid((*p).pw_uid) } != 0 { log::error!("Unable to setuid of user: {}", user); return Err(Error::last_os_error()); } } else { return Err(Error::new( ErrorKind::Other, "Cannot create CString from String (user)!", )); } Ok(()) }