138 lines
4.9 KiB
Bash
Executable File
138 lines
4.9 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# LXS - Change root password
|
|
# Description: Change the root account password (interactive or generated)
|
|
# Author: LXS
|
|
# Date: 2025
|
|
|
|
# Load LXS common library (colors, separator, run_spinner, loggers, helpers)
|
|
# Prefers the sibling ../lib/common.sh (repo checkout or installed layout) and
|
|
# only hits the network when this script is run standalone via curl.
|
|
LXS_RAW_BASE="${LXS_RAW_BASE:-https://git.hyko.cx/hykocx/lxs/raw/branch/main}"
|
|
LXS_RAW_PLATFORM_BASE="${LXS_RAW_PLATFORM_BASE:-${LXS_RAW_BASE}/linux}"
|
|
_lxs_lib=""
|
|
if [ -n "${BASH_SOURCE[0]:-}" ]; then
|
|
_lxs_self=$(readlink -f "${BASH_SOURCE[0]}" 2>/dev/null) \
|
|
|| _lxs_self=$(realpath "${BASH_SOURCE[0]}" 2>/dev/null) \
|
|
|| _lxs_self="${BASH_SOURCE[0]}"
|
|
_lxs_lib="$(dirname "$_lxs_self")/../lib/common.sh"
|
|
fi
|
|
if [ -n "$_lxs_lib" ] && [ -r "$_lxs_lib" ]; then
|
|
# shellcheck disable=SC1090,SC1091
|
|
. "$_lxs_lib"
|
|
else
|
|
_lib=$(curl -fsSL "${LXS_RAW_PLATFORM_BASE}/lib/common.sh") || { echo "Failed to fetch lib/common.sh" >&2; exit 1; }
|
|
eval "$_lib"
|
|
unset _lib
|
|
fi
|
|
unset _lxs_lib _lxs_self
|
|
export LXS_LOG_FILE="/tmp/lxs_root_password.log"
|
|
|
|
require_root "$0" "$@"
|
|
|
|
set -u
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# Arguments
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
MODE=""
|
|
PASSWORD_LENGTH=24
|
|
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
-g|--generate) MODE="generate" ;;
|
|
-i|--interactive) MODE="interactive" ;;
|
|
--length=*) PASSWORD_LENGTH="${arg#*=}" ;;
|
|
-h|--help)
|
|
cat <<EOF
|
|
Usage: root-password.sh [options]
|
|
|
|
Options:
|
|
-i, --interactive Prompt for the new password (passwd root)
|
|
-g, --generate Generate a strong random password and apply it
|
|
--length=N Length of the generated password (default: 24)
|
|
-h, --help Show this help
|
|
|
|
With no option, an interactive menu is shown.
|
|
EOF
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo -e "${RED}Unknown option: $arg${NC}" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# Actions
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
change_interactive() {
|
|
info "Setting root password interactively..."
|
|
show_separator
|
|
if passwd root; then
|
|
show_separator
|
|
ok "Root password updated"
|
|
return 0
|
|
fi
|
|
show_separator
|
|
err "Failed to update root password"
|
|
return 1
|
|
}
|
|
|
|
change_generated() {
|
|
if ! [[ "$PASSWORD_LENGTH" =~ ^[0-9]+$ ]] || [ "$PASSWORD_LENGTH" -lt 12 ]; then
|
|
err "--length must be a number ≥ 12 (got: ${PASSWORD_LENGTH})"
|
|
return 1
|
|
fi
|
|
|
|
local new_password
|
|
new_password=$(generate_password "$PASSWORD_LENGTH")
|
|
if [ -z "$new_password" ]; then
|
|
err "Failed to generate a password"
|
|
return 1
|
|
fi
|
|
|
|
if ! echo "root:${new_password}" | chpasswd; then
|
|
err "Failed to apply the generated password"
|
|
return 1
|
|
fi
|
|
|
|
show_separator
|
|
ok "Root password updated"
|
|
echo ""
|
|
echo -e "${WHITE}${BOLD}New root password:${NC} ${YELLOW}${new_password}${NC}"
|
|
echo ""
|
|
warn "Store this password in a secure place. It will not be shown again."
|
|
show_separator
|
|
return 0
|
|
}
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# Menu (when no mode is given on the CLI)
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
if [ -z "$MODE" ]; then
|
|
echo -e "${WHITE}${BOLD}LXS - Change root password${NC}"
|
|
show_separator
|
|
echo -e " ${CYAN}[1]${NC} Set a new password interactively"
|
|
echo -e " ${CYAN}[2]${NC} Generate a strong random password"
|
|
echo -e " ${RED}[0]${NC} Cancel"
|
|
echo ""
|
|
echo -e -n "${BOLD}Choice [0-2]: ${NC}"
|
|
read -r choice
|
|
case "$choice" in
|
|
1) MODE="interactive" ;;
|
|
2) MODE="generate" ;;
|
|
0|"") info "Cancelled."; exit 0 ;;
|
|
*) err "Invalid option."; exit 1 ;;
|
|
esac
|
|
fi
|
|
|
|
case "$MODE" in
|
|
interactive) change_interactive ;;
|
|
generate) change_generated ;;
|
|
esac
|