How POSIX User ID and Supplementary Group IDs are Set On Login
This is usually done by the login(1)
setuid executable.
It looks up /etc/passwd
with the username and gets the User ID and the Primary Group ID. This is the 0:0
in /etc/passwd
.
root:*:0:0:Superuser:/root:/usr/local/bin/fish
It looks up /etc/group
with the username and gets all the groups the user is in (Supplementary Group IDs).
Then, it spawns a shell (the shell command is also read from /etc/passwd
) in a new session (kernel concept) with the User ID, Primary Group ID, Supplementary Group IDs. It also sets $USER
and other environment variables.
One uid can have multiple names, and one gid can have multiple names.
Here’s an example from FreeBSD:
/etc/passwd
:
root:*:0:0:Superuser:/root:/usr/local/bin/fish
toor:*:0:0:Bourne-again Superuser:/root:
/etc/group
:
wheel:*:0:root
operator:*:5:root
Now observe the magic:
user@ed ~> doas -s -u root
root@ed ~# groups
wheel operator
root@ed ~# exit
user@ed ~> doas -s -u toor
toor@ed ~# groups
wheel
An even more cursed idea:
root:*:0:0::/root:
toor:*:0:5::/root:
As it turns out, the source of uid/gid comes is less straightforward than simply reading /etc/passwd
. libc (providing getpwent(3)
and family) reads /etc/nsswitch.conf
to see if it should access /etc/passwd
or some other place.
Authentication modules like pam_unix.so
in Linux-PAM uses getpwent(3)
to check passwords of UNIX users.
Update(2024-07-07): Don’t know where else to put it, so I’m putting it here.
On OpenBSD, doas(1)
sets an attribute on the controlling terminal with ioctl(2)
. I wonder what other ways one can associate metadata with tty.