detect root by uid, not by the name root
A provider whose image logs you in as "ubuntu" at uid 0 would have walked straight past the previous check, which compared the string. What makes an account root is uid 0; "root" is only the usual label for it. Two places now ask id -u rather than comparing names: the answer — an account at uid 0 is refused whatever it is called, and says which case it is rather than a bare "not root" the invoker — the warning about working as root fires when SUDO_USER is unset OR when SUDO_USER is itself uid 0. The second is the one that hides: sudo from a uid-0 account sets SUDO_USER to something that reads like an ordinary user and is not. The EUID check that requires the script to run as root was already uid-based and is unchanged. Verified by creating a real uid-0 account named ubuntu on this box: refused with the uid named, where the name check accepted it. That account has been removed — userdel refused it at first because it matches by uid and saw PID 1 running as uid 0, so -f was needed, and deliberately not -r, since its home was /root. Confirmed afterwards that root, /root, root's shadow entry and sudo are all intact and that root is once again the only uid-0 account. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -199,14 +199,25 @@ ask_username() {
|
|||||||
echo " of hand. sudo gives you the same power when you ask for it, and"
|
echo " of hand. sudo gives you the same power when you ask for it, and"
|
||||||
echo " only then — which is why root is not accepted as an answer here."
|
echo " only then — which is why root is not accepted as an answer here."
|
||||||
|
|
||||||
# No SUDO_USER means this was started as root rather than through sudo, which
|
# Whether this was started FROM a root session, which usually means root is
|
||||||
# usually means root is how they are logged in. That is exactly the situation
|
# how they log in. That is exactly the situation the advice above is for, and
|
||||||
# the advice above is for, so it is worth saying plainly rather than leaving
|
# the one where general advice is easiest to assume is aimed at somebody else.
|
||||||
# as general guidance they can assume is aimed at somebody else.
|
#
|
||||||
if [[ -z "${SUDO_USER:-}" ]]; then
|
# Two ways to be in it, and the second is the one that hides: no SUDO_USER at
|
||||||
|
# all, or a SUDO_USER that is itself uid 0. Some providers ship an image whose
|
||||||
|
# default account is uid 0 under an ordinary-looking name, so `sudo` from it
|
||||||
|
# sets SUDO_USER to something that looks like a normal user and is not.
|
||||||
|
local invoker_uid=""
|
||||||
|
[[ -n "${SUDO_USER:-}" ]] && invoker_uid="$(id -u "$SUDO_USER" 2>/dev/null || true)"
|
||||||
|
|
||||||
|
if [[ -z "${SUDO_USER:-}" || "$invoker_uid" == "0" ]]; then
|
||||||
echo ""
|
echo ""
|
||||||
|
if [[ -n "${SUDO_USER:-}" ]]; then
|
||||||
|
warn "You are running this from '${SUDO_USER}', which is uid 0 — the root account."
|
||||||
|
else
|
||||||
warn "You are running this as root directly, not through sudo."
|
warn "You are running this as root directly, not through sudo."
|
||||||
echo " If root is how you normally log into this machine, now is the"
|
fi
|
||||||
|
echo " If that is how you normally log into this machine, now is the"
|
||||||
echo " moment to make an account and stop doing that."
|
echo " moment to make an account and stop doing that."
|
||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
@@ -225,7 +236,18 @@ ask_username() {
|
|||||||
# answered against a name that was never going to work.
|
# answered against a name that was never going to work.
|
||||||
[[ "$answer" =~ ^[a-z_][a-z0-9_-]*\$?$ && ${#answer} -le 32 ]] ||
|
[[ "$answer" =~ ^[a-z_][a-z0-9_-]*\$?$ && ${#answer} -le 32 ]] ||
|
||||||
fail "'${answer}' is not a usable Linux username — lower case, starting with a letter or underscore."
|
fail "'${answer}' is not a usable Linux username — lower case, starting with a letter or underscore."
|
||||||
[[ "$answer" == "root" ]] && fail "root is not the account to set up here."
|
# By uid, not by name. "root" is a label — what makes an account root is uid 0,
|
||||||
|
# and some providers ship an image whose default login is uid 0 under a
|
||||||
|
# friendlier name. Refusing only the string would let exactly that case through,
|
||||||
|
# which is the one worth catching.
|
||||||
|
local answer_uid
|
||||||
|
answer_uid="$(id -u "$answer" 2>/dev/null || true)"
|
||||||
|
if [[ "$answer_uid" == "0" ]]; then
|
||||||
|
if [[ "$answer" == "root" ]]; then
|
||||||
|
fail "root is not the account to set up here — see the warning above."
|
||||||
|
fi
|
||||||
|
fail "'${answer}' is uid 0 — the root account under another name, and not what to set up here."
|
||||||
|
fi
|
||||||
|
|
||||||
USERNAME="$answer"
|
USERNAME="$answer"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user