Make compile-time feature for SUID/SGID mode
This commit is contained in:
@@ -51,6 +51,7 @@ uuid = { version = "1.18.1", features = ["v4"] }
|
|||||||
default = ["mysql-admutils-compatibility"]
|
default = ["mysql-admutils-compatibility"]
|
||||||
tui = ["dep:ratatui"]
|
tui = ["dep:ratatui"]
|
||||||
mysql-admutils-compatibility = []
|
mysql-admutils-compatibility = []
|
||||||
|
suid-sgid-mode = []
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "mysqladm"
|
name = "mysqladm"
|
||||||
|
|||||||
@@ -19,12 +19,14 @@ use crate::{
|
|||||||
/// If neither is feasible, an error is returned.
|
/// If neither is feasible, an error is returned.
|
||||||
fn will_connect_to_external_server(
|
fn will_connect_to_external_server(
|
||||||
server_socket_path: Option<&PathBuf>,
|
server_socket_path: Option<&PathBuf>,
|
||||||
config_path: Option<&PathBuf>,
|
// This parameter is only used in suid-sgid-mode
|
||||||
|
#[allow(unused_variables)] config_path: Option<&PathBuf>,
|
||||||
) -> anyhow::Result<bool> {
|
) -> anyhow::Result<bool> {
|
||||||
if server_socket_path.is_some() {
|
if server_socket_path.is_some() {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "suid-sgid-mode")]
|
||||||
if config_path.is_some() {
|
if config_path.is_some() {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
@@ -33,11 +35,16 @@ fn will_connect_to_external_server(
|
|||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "suid-sgid-mode")]
|
||||||
if fs::metadata(DEFAULT_CONFIG_PATH).is_ok() {
|
if fs::metadata(DEFAULT_CONFIG_PATH).is_ok() {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "suid-sgid-mode")]
|
||||||
anyhow::bail!("No socket path or config path provided, and no default socket or config found");
|
anyhow::bail!("No socket path or config path provided, and no default socket or config found");
|
||||||
|
|
||||||
|
#[cfg(not(feature = "suid-sgid-mode"))]
|
||||||
|
anyhow::bail!("No socket path provided, and no default socket found");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function is used to bootstrap the connection to the server.
|
/// This function is used to bootstrap the connection to the server.
|
||||||
@@ -77,7 +84,7 @@ pub fn bootstrap_server_connection_and_drop_privileges(
|
|||||||
.init();
|
.init();
|
||||||
|
|
||||||
connect_to_external_server(server_socket_path)
|
connect_to_external_server(server_socket_path)
|
||||||
} else {
|
} else if cfg!(feature = "suid-sgid-mode") {
|
||||||
// NOTE: We need to be really careful with the code up until this point,
|
// NOTE: We need to be really careful with the code up until this point,
|
||||||
// as we might be running with elevated privileges.
|
// as we might be running with elevated privileges.
|
||||||
let server_connection = bootstrap_internal_server_and_drop_privs(config)?;
|
let server_connection = bootstrap_internal_server_and_drop_privs(config)?;
|
||||||
@@ -87,6 +94,8 @@ pub fn bootstrap_server_connection_and_drop_privileges(
|
|||||||
.init();
|
.init();
|
||||||
|
|
||||||
Ok(server_connection)
|
Ok(server_connection)
|
||||||
|
} else {
|
||||||
|
anyhow::bail!("SUID/SGID support is not enabled, cannot start internal server");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use nix::unistd::{Group as LibcGroup, User as LibcUser};
|
use nix::unistd::{Group as LibcGroup, User as LibcUser};
|
||||||
use std::{fs, os::unix::fs::PermissionsExt};
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
@@ -21,23 +20,6 @@ fn get_unix_groups(_user: &LibcUser) -> anyhow::Result<Vec<LibcGroup>> {
|
|||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the current executable is SUID or SGID.
|
|
||||||
///
|
|
||||||
/// If the check fails, an error is returned.
|
|
||||||
pub fn executable_is_suid_or_sgid() -> anyhow::Result<bool> {
|
|
||||||
let result = std::env::current_exe()
|
|
||||||
.context("Failed to get current executable path")
|
|
||||||
.and_then(|executable| {
|
|
||||||
fs::metadata(executable).context("Failed to get executable metadata")
|
|
||||||
})
|
|
||||||
.context("Failed to check SUID/SGID bits on executable")
|
|
||||||
.map(|metadata| {
|
|
||||||
let mode = metadata.permissions().mode();
|
|
||||||
mode & 0o4000 != 0 || mode & 0o2000 != 0
|
|
||||||
})?;
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
fn get_unix_groups(user: &LibcUser) -> anyhow::Result<Vec<LibcGroup>> {
|
fn get_unix_groups(user: &LibcUser) -> anyhow::Result<Vec<LibcGroup>> {
|
||||||
let user_cstr =
|
let user_cstr =
|
||||||
@@ -61,6 +43,31 @@ fn get_unix_groups(user: &LibcUser) -> anyhow::Result<Vec<LibcGroup>> {
|
|||||||
Ok(groups)
|
Ok(groups)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if the current executable is SUID or SGID.
|
||||||
|
///
|
||||||
|
/// If the check fails, an error is returned.
|
||||||
|
#[cfg(feature = "suid-sgid-mode")]
|
||||||
|
pub fn executable_is_suid_or_sgid() -> anyhow::Result<bool> {
|
||||||
|
use std::{fs, os::unix::fs::PermissionsExt};
|
||||||
|
let result = std::env::current_exe()
|
||||||
|
.context("Failed to get current executable path")
|
||||||
|
.and_then(|executable| {
|
||||||
|
fs::metadata(executable).context("Failed to get executable metadata")
|
||||||
|
})
|
||||||
|
.context("Failed to check SUID/SGID bits on executable")
|
||||||
|
.map(|metadata| {
|
||||||
|
let mode = metadata.permissions().mode();
|
||||||
|
mode & 0o4000 != 0 || mode & 0o2000 != 0
|
||||||
|
})?;
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "suid-sgid-mode"))]
|
||||||
|
#[inline]
|
||||||
|
pub fn executable_is_suid_or_sgid() -> anyhow::Result<bool> {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
|
||||||
impl UnixUser {
|
impl UnixUser {
|
||||||
pub fn from_uid(uid: u32) -> anyhow::Result<Self> {
|
pub fn from_uid(uid: u32) -> anyhow::Result<Self> {
|
||||||
let libc_uid = nix::unistd::Uid::from_raw(uid);
|
let libc_uid = nix::unistd::Uid::from_raw(uid);
|
||||||
|
|||||||
Reference in New Issue
Block a user