summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2026-06-18 16:09:57 +0200
committerGitHub <noreply@github.com>2026-06-18 16:09:57 +0200
commit1057fca4ebffbce36a5f31e6ff1524766cf7fe3b (patch)
tree63b88cb331c8e550baca7e7ce12dc8fe78293a64
parentabb323b83b55f0929151d96f5d98dbd3741a55eb (diff)
parente3b946e34b109406f38bfa5f78eb9a2ec7502bc9 (diff)
downloadvyos-1x-1057fca4ebffbce36a5f31e6ff1524766cf7fe3b.tar.gz
vyos-1x-1057fca4ebffbce36a5f31e6ff1524766cf7fe3b.zip
Merge pull request #5273 from alexandr-san4ez/T8985-rolling
password-reset: T8985: Fix unbounded `sed` ranges corrupting other user blocks
-rwxr-xr-xsrc/system/standalone_root_pw_reset42
1 files changed, 36 insertions, 6 deletions
diff --git a/src/system/standalone_root_pw_reset b/src/system/standalone_root_pw_reset
index aa712ad52..4cd4b98d4 100755
--- a/src/system/standalone_root_pw_reset
+++ b/src/system/standalone_root_pw_reset
@@ -27,7 +27,11 @@ CF=/opt/vyatta/etc/config/config.boot
ADMIN=vyos
set_encrypted_password() {
- local user=$1 epwd=$2 file=$3
+ local user_raw=$1 epwd=$2 file=$3
+ local user
+
+ # Escape the username before using it in awk/sed regexes
+ user=$(printf '%s' "$user_raw" | sed -e 's/\./\\&/g')
# Check if encrypted-password exists within this specific user's block
if awk "/ user $user \{/{f=1} f && /encrypted-password/{found=1; exit} f && /^ }/{exit} END{exit !found}" "$file"; then
@@ -35,15 +39,41 @@ set_encrypted_password() {
sed -i \
-e "/ user $user {/,/encrypted-password/s/encrypted-password .*\$/encrypted-password \"$epwd\"/" "$file"
else
- # Insert encrypted-password after plaintext-password
- sed -i \
- -e "/ user $user {/,/plaintext-password/s/\(plaintext-password .*\)\$/\1\n encrypted-password \"$epwd\"/" "$file"
+ # Key-only account: no encrypted-password or plaintext-password line exists
+ # in this user's block (e.g. authentication via SSH key only).
+ if awk "/ user $user \{/{f=1} f && /authentication \{/{found=1; exit} f && /^ \}/{exit} END{exit !found}" "$file"; then
+ # 'authentication' block exists - insert encrypted-password inside it
+ sed -i \
+ -e "/ user $user {/,/authentication {/s/\(authentication {\)\$/\1\n encrypted-password \"$epwd\"/" "$file"
+ else
+ # No authentication block at all. Without this branch the sed range
+ # above would overrun the block boundary and corrupt a later account's
+ # authentication block. Build the section from scratch instead.
+ sed -i \
+ -e "/ user $user {/a\\
+ authentication {\\
+ encrypted-password \"$epwd\"\\
+ plaintext-password \"\"\\
+ }" "$file"
+ fi
fi
}
clear_plaintext_password() {
- sed -i \
- -e "/ user $1 {/,/plaintext-password/s/plaintext-password .*\$/plaintext-password \"\"/" $2
+ local user_raw=$1 file=$2
+ local user
+
+ # Escape the username before using it in awk/sed regexes
+ user=$(printf '%s' "$user_raw" | sed -e 's/\./\\&/g')
+
+ # Only clear if plaintext-password exists within this specific user's block.
+ # Without this guard, if the user has no plaintext-password line the sed
+ # range never closes inside their block and spills into the next account
+ # that does have one, wiping that account's plaintext-password instead.
+ if awk "/ user $user \{/{f=1} f && /plaintext-password/{found=1; exit} f && /^ \}/{exit} END{exit !found}" "$file"; then
+ sed -i \
+ -e "/ user $user {/,/plaintext-password/s/plaintext-password .*\$/plaintext-password \"\"/" "$file"
+ fi
}