Skip to content
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 35 additions & 17 deletions scripts/menu_recovery.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ reset_unraid_password() {
local mount_root=""
local dataset_list=""
local config_dir=""
local dataset mountpoint root_mountpoint resolved_mount_root resolved_config_dir
local dataset mountpoint resolved_mount_root resolved_config_dir
local config_list=""
local mount_failed=0
local config_candidate_count=0
local config_symlink_found=0
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

if ! command -v zpool >/dev/null 2>&1 || ! command -v zfs >/dev/null 2>&1; then
ui_msg "Password Reset" "ZFS tools are not available in this image."
Expand All @@ -60,7 +63,7 @@ reset_unraid_password() {
return 1
fi

if ! ui_confirm "Reset Password" "This removes config/passwd and config/shadow from the '$pool_name' boot pool. The next Unraid boot will have no web password. Continue?"; then
if ! ui_confirm "Reset Password" "This removes config/shadow and config/smbpasswd from the '$pool_name' boot pool. The next Unraid boot will require a new root password. Continue?"; then
return 0
fi

Expand Down Expand Up @@ -91,50 +94,65 @@ reset_unraid_password() {
break
fi
done < "$dataset_list"
rm -f "$dataset_list"

if [[ "$mount_failed" -eq 1 ]]; then
rm -f "$dataset_list"
zpool export "$pool_name" >/dev/null 2>&1 || true
rmdir "$mount_root" 2>/dev/null || true
ui_msg "Password Reset" "The '$pool_name' boot dataset could not be mounted."
return 1
fi

recovery_status "Locating the Unraid config directory..."
root_mountpoint="$(zfs get -H -o value mountpoint "$pool_name" 2>/dev/null || true)"
if [[ "$root_mountpoint" != /* ]]; then
resolved_mount_root="$(readlink -f -- "$mount_root" 2>/dev/null || true)"
if [[ -z "$resolved_mount_root" ]]; then
rm -f "$dataset_list"
zpool export "$pool_name" >/dev/null 2>&1 || true
rmdir "$mount_root" 2>/dev/null || true
ui_msg "Password Reset" "The '$pool_name' boot dataset does not have a usable mount point."
ui_msg "Password Reset" "Unable to resolve the temporary boot-pool mount root."
return 1
fi
config_dir="$mount_root${root_mountpoint%/}/config"
if [[ -L "$config_dir" ]]; then

config_list="$(mktemp /tmp/unraid-recovery-configs.XXXXXX)"
find -P "$mount_root" -type d -name config -print > "$config_list"
if find -P "$mount_root" -type l -name config -print -quit | grep -q .; then
config_symlink_found=1
fi

while IFS= read -r config_dir; do
resolved_config_dir="$(readlink -f -- "$config_dir" 2>/dev/null || true)"
if [[ "$resolved_config_dir" == "$resolved_mount_root"/* && -d "$resolved_config_dir" ]]; then
config_dir="$resolved_config_dir"
((++config_candidate_count))
fi
done < "$config_list"
rm -f "$config_list"
rm -f "$dataset_list"

if [[ "$config_symlink_found" -eq 1 ]]; then
zpool export "$pool_name" >/dev/null 2>&1 || true
rmdir "$mount_root" 2>/dev/null || true
ui_msg "Password Reset" "The boot config directory is a symlink. Refusing to modify it."
ui_msg "Password Reset" "A boot config directory is a symlink. Refusing to modify it."
return 1
fi
resolved_mount_root="$(readlink -f -- "$mount_root" 2>/dev/null || true)"
resolved_config_dir="$(readlink -f -- "$config_dir" 2>/dev/null || true)"
if [[ -z "$resolved_mount_root" || -z "$resolved_config_dir" || "$resolved_config_dir" != "$resolved_mount_root"/* || ! -d "$resolved_config_dir" ]]; then

if [[ "$config_candidate_count" -ne 1 ]]; then
zpool export "$pool_name" >/dev/null 2>&1 || true
rmdir "$mount_root" 2>/dev/null || true
ui_msg "Password Reset" "Expected config directory is unavailable or outside the boot pool."
ui_msg "Password Reset" "Expected exactly one boot config directory, found $config_candidate_count."
return 1
fi
config_dir="$resolved_config_dir"

recovery_status "Deleting config/passwd and config/shadow..."
if ! rm -f -- "$config_dir/passwd" "$config_dir/shadow"; then
recovery_status "Deleting config/shadow and config/smbpasswd..."
if ! rm -f -- "$config_dir/shadow" "$config_dir/smbpasswd"; then
zpool export "$pool_name" >/dev/null 2>&1 || true
rmdir "$mount_root" 2>/dev/null || true
ui_msg "Password Reset" "Unable to remove the saved password files."
return 1
fi

recovery_status "Verifying password files are absent..."
if [[ -e "$config_dir/passwd" || -e "$config_dir/shadow" ]]; then
if [[ -e "$config_dir/shadow" || -e "$config_dir/smbpasswd" ]]; then
zpool export "$pool_name" >/dev/null 2>&1 || true
rmdir "$mount_root" 2>/dev/null || true
ui_msg "Password Reset" "The password files are still present in the config directory."
Expand Down
Loading