From 0729d3d2d59ae58682d84529bd491cecd713d47b Mon Sep 17 00:00:00 2001 From: Heavybullets8 Date: Mon, 29 Apr 2024 08:24:02 +0000 Subject: [PATCH] Fix link errors (#162) Resolves #160 Due to recent policy changes in Dragonfish, modifications to certain files and directories have been restricted. This has necessitated a rethink in how we manage the visibility of paths between the user invoking sudo and the sudo environment itself. This update renames the `ensure_symlink` function to `ensure_sudoers` and modifies its functionality to better align with the new restrictions. Now, instead of creating symlinks, the function appends two lines to the sudoers file. These lines ensure that the `PATH` for users invoking sudo includes `$HOME/bin`, making it visible and accessible within the sudo environment. Changes: - Renamed `ensure_symlink` to `ensure_sudoers`. - Modified function to append `$HOME/bin` to the sudoer's `PATH`. This adjustment simplifies the configuration and enhances compliance with the updated Dragonfish policies. --- functions/deploy.sh | 81 ++++++++++++++++++++++++------------ heavy_script.sh | 9 ++-- utils/generate_config.sh | 10 ----- utils/permissions.sh | 88 ++++++++++++++++++++++++++++++++-------- 4 files changed, 130 insertions(+), 58 deletions(-) diff --git a/functions/deploy.sh b/functions/deploy.sh index 83936270..29b29455 100644 --- a/functions/deploy.sh +++ b/functions/deploy.sh @@ -38,6 +38,48 @@ update_repo() { fi } +ensure_sudoers() { + local env_keep_exists secure_path_exists TMP_FILE + local user="$1" + local user_bin_dir="$2/bin" + + # Check if specific entries already exist in the sudoers file + env_keep_exists=$(grep -c "Defaults:$user env_keep+=\"PATH\"" /etc/sudoers) + secure_path_exists=$(grep -c "Defaults:$user secure_path=\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$user_bin_dir\"" /etc/sudoers) + + # Exit the function if no changes are needed + if [[ $env_keep_exists -gt 0 && $secure_path_exists -gt 0 ]]; then + return 0 + fi + + # Create a temporary file only if changes are needed + TMP_FILE=$(mktemp) + + # Ensure cleanup on exit + trap 'rm -f "$TMP_FILE"' EXIT + + # Copy current sudoers to temp + cat /etc/sudoers > "$TMP_FILE" + + # Append new lines only if they don't already exist + if [[ $env_keep_exists -eq 0 ]]; then + echo "Defaults:$user env_keep+=\"PATH\"" >> "$TMP_FILE" + fi + + if [[ $secure_path_exists -eq 0 ]]; then + echo "Defaults:$user secure_path=\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$user_bin_dir\"" >> "$TMP_FILE" + fi + + # Check for syntax errors with visudo + if visudo -c -f "$TMP_FILE"; then + # If the temp file is okay, safely copy it to the actual sudoers file + sudo cp "$TMP_FILE" /etc/sudoers + echo -e "${green}Sudoers file has been updated successfully.${reset}\n" + else + echo -e "${red}Error found in sudoers temp file. No changes were made.${reset}" + fi +} + # colors reset='\033[0m' red='\033[0;31m' @@ -50,9 +92,8 @@ USER_HOME=$(get_user_home) script_name='heavyscript' script_dir="$USER_HOME/heavy_script" user_bin_dir="$USER_HOME/bin" -system_bin_dir="/usr/local/bin" user_script_wrapper="$user_bin_dir/$script_name" -system_script_wrapper="$system_bin_dir/$script_name" +invoking_user=$(get_invoking_user) main() { # Check if user has a home @@ -63,12 +104,6 @@ main() { exit 1 fi - if [[ $EUID -ne 0 ]]; then - echo -e "${yellow}Warning: The script is not running with root privileges. To create a symlink in ${blue}$system_bin_dir${yellow}, please rerun the script with sudo or as the root user.${reset}" - echo -e "${yellow}You can exit now with CTRL+C to rerun with sudo, or wait 10 seconds to continue without creating the system-wide symlink.${reset}" - sleep 10 - fi - # Check if the script repository already exists if [[ -d "$script_dir" ]]; then echo -e "${yellow}The ${blue}$script_name${yellow} repository already exists.${reset}" @@ -118,21 +153,19 @@ main() { mkdir "$user_bin_dir" fi - if [[ $EUID -ne 0 ]]; then - echo -e "${yellow}Warning: Skipping system-wrapper...${reset}" - # Create symlink inside user's bin only - echo -e "${blue}Creating $user_script_wrapper wrapper...${reset}" - ln -sf "$script_dir/bin/$script_name" "$user_script_wrapper" - chmod +x "$script_dir/bin/$script_name" - else - # Create symlink inside both user's and system's bin - echo -e "${blue}Creating $user_script_wrapper and $system_script_wrapper wrappers...${reset}" - ln -sf "$script_dir/bin/$script_name" "$user_script_wrapper" - ln -sf "$script_dir/bin/$script_name" "$system_script_wrapper" - chmod +x "$script_dir/bin/$script_name" - chmod +x "$system_script_wrapper" - fi + # Create symlink inside user's bin only + echo -e "${blue}Creating $user_script_wrapper wrapper...${reset}" + ln -sf "$script_dir/bin/$script_name" "$user_script_wrapper" + chmod +x "$script_dir/bin/$script_name" + + + echo + if [[ $EUID -eq 0 && -n $SUDO_USER ]]; then + echo -e "${blue}Adding $invoking_user and $USER_HOME to sudoers...${reset}" + ensure_sudoers "$invoking_user" "$USER_HOME" + fi + echo # Add $USER_HOME/bin to PATH in .bashrc and .zshrc @@ -143,13 +176,11 @@ main() { fi if ! grep -q "$user_bin_dir" "$USER_HOME/$rc_file"; then - echo -e "${blue}Adding $user_bin_dir to $rc_file...${reset}" + echo -e "${blue}Adding $user_bin_dir to $USER_HOME/$rc_file...${reset}" echo "export PATH=$user_bin_dir:\$PATH" >> "$USER_HOME/$rc_file" fi done - local invoking_user - invoking_user=$(get_invoking_user) if [[ $EUID -eq 0 && -n $SUDO_USER ]]; then echo -e "${green}Changing ownership of HeavyScript to ${blue}$invoking_user${green}...${reset}" chown -R "$invoking_user" "$script_dir" diff --git a/heavy_script.sh b/heavy_script.sh index f9ff2d7e..bd71ae8a 100644 --- a/heavy_script.sh +++ b/heavy_script.sh @@ -48,15 +48,14 @@ while IFS= read -r script_file; do source "$script_file" done < <(find functions utils -name "*.sh" -exec printf '%s\n' {} \;) -# Ensure symlink within /usr/local/bin is active, for when the script is run with sudo -ensure_symlink +# Ensure sudoers file contains the necessary configuration +if [[ $EUID -eq 0 ]]; then + ensure_sudoers +fi # generate the config.ini file if it does not exist generate_config_ini -# remove the [DNS] section from the config.ini file if it exists -remove_dns_section - # Separate bundled short options args=() for arg in "$@"; do diff --git a/utils/generate_config.sh b/utils/generate_config.sh index af909913..f2cb8d0f 100644 --- a/utils/generate_config.sh +++ b/utils/generate_config.sh @@ -9,13 +9,3 @@ generate_config_ini() { sleep 5 fi } - -remove_dns_section() { - local config_file="config.ini" - - # Check if the [DNS] section exists in the config.ini file - if grep -q "^\[DNS\]" "$config_file"; then - # Remove the [DNS] section from the config.ini file - awk '/^\[DNS\]/ {flag=1; next} /^\[SELFUPDATE\]/ {flag=0} !flag' "$config_file" > temp.ini && mv temp.ini "$config_file" - fi -} diff --git a/utils/permissions.sh b/utils/permissions.sh index 65812826..ee1ab4da 100644 --- a/utils/permissions.sh +++ b/utils/permissions.sh @@ -17,22 +17,74 @@ check_root() { fi } -ensure_symlink() { - local system_script_wrapper="/usr/local/bin/heavyscript" - local script_location="$script_path/bin/heavyscript" - - if [[ ! -L "$system_script_wrapper" || ! -e "$system_script_wrapper" ]]; then - echo "Warning: Symlink from $script_location to $system_script_wrapper is broken." - - if [[ $EUID -eq 0 ]]; then - echo -e "Restoring symlink in $system_script_wrapper...\n" - ln -sf "$script_location" "$system_script_wrapper" - chmod +x "$script_location" - else - echo "Warning: The script is not running as root. To restore the symlink, run the script with sudo using the following command:" - echo "sudo bash $script" - echo "or run the script as the root user." - sleep 5 - fi +ensure_sudoers() { + find_user_and_home() { + local script_path="$1" + while IFS=: read -r username _ _ _ _ home _; do + if [[ "$script_path" == "$home"* ]]; then + echo "$username|$home" + return 0 + fi + done < <(getent passwd | grep -Ev "nonexistent|nologin$") + } + + local user env_keep_exists secure_path_exists TMP_FILE home + + # Capture output, which contains both user and home + output=$(find_user_and_home "$script_path") + + # Split output into user and home + IFS='|' read -r user home <<< "$output" + + # No need to modify sudoers if the script is run as root + if [[ $user == "root" || $home == "/root" || $script_path == "/root/heavy_script" || -z $home || -z $user ]]; then + return 0 + fi + + local script_location="$home/bin" + + if [[ ! -f "$script_location/heavyscript" ]]; then + return 0 + fi + + + # Check if specific entries already exist in the sudoers file + env_keep_exists=$(grep -c "Defaults:$user env_keep+=\"PATH\"" /etc/sudoers) + secure_path_exists=$(grep -c "Defaults:$user secure_path=\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$script_location\"" /etc/sudoers) + + # Exit the function if no changes are needed + if [[ $env_keep_exists -gt 0 && $secure_path_exists -gt 0 ]]; then + return 0 + fi + + # Create a temporary file only if changes are needed + TMP_FILE=$(mktemp) + + # Ensure cleanup on exit + trap 'rm -f "$TMP_FILE"' EXIT + + # Copy current sudoers to temp + cat /etc/sudoers > "$TMP_FILE" + + # Append new lines only if they don't already exist + if [[ $env_keep_exists -eq 0 ]]; then + echo "Defaults:$user env_keep+=\"PATH\"" >> "$TMP_FILE" + fi + + if [[ $secure_path_exists -eq 0 ]]; then + echo "Defaults:$user secure_path=\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$script_location\"" >> "$TMP_FILE" + fi + + # Check for syntax errors with visudo + if visudo -c -f "$TMP_FILE"; then + # If the temp file is okay, safely copy it to the actual sudoers file + sudo cp "$TMP_FILE" /etc/sudoers + echo "Sudoers file has been updated successfully." + else + echo "Error found in sudoers temp file. No changes were made." fi -} \ No newline at end of file +} + + + +