TCB(5)
TCB(5) β alternative password shadowing scheme π
Okay bestie, let me tell you about tcb β it's this iconic alternative to the traditional password shadowing scheme and honestly it's giving "why didn't we always do it this way" energy. Buckle up. π
THE PROBLEM (a.k.a. why the old way is lowkey a mess) π
So with the traditional password shadowing scheme, here's the situation: password hashes and password aging info for all users live in one single file β /etc/shadow. Which means if some process needs info about just one user, it's forced to have privileges big enough to access data on all users. That's a genuine design flaw, and it's most painfully obvious with passwd(1).
Let me paint the picture: say you want unprivileged users to be able to change their own passwords. Whatever permissions you slap on /etc/shadow, passwd(1) β when it's invoked by unprivileged user U β still has to be able to modify that file's contents. So if malicious user U finds a way to take control of the passwd(1) process (buffer overflow, some other bug in the passwd(1) code, in the libraries it uses, or even in the kernel), that user can now change everyone's passwords and basically own the whole system. Not slay. Not slay at all. π
THE SOLUTION β¨
The fix is honestly so straightforward β each user gets their own separate shadow-style file. User U's shadow file is owned by U, so passwd(1) invoked by U doesn't need superuser privileges at all. Main character energy for every single user, fr fr. π
The directory where all users' shadow files live is /etc/tcb:
drwx--x--- 2 root shadow 1024 Jul 4 01:18 /etc/tcb
And for each user there's a directory under /etc/tcb with the appropriate ownership and permissions:
# ls -l /etc/tcb
total 2
drwx--s--- 2 root auth 1024 Jul 4 01:18 root
drwx--s--- 2 user auth 1024 Jul 4 01:18 user
...and so on. Each of those directories contains a shadow file for just the appropriate user:
# ls -l /etc/tcb/user
total 1
-rw-r----- 1 user auth 91 Jul 4 01:18 shadow
The per-user directories also double as scratch space for temporary and lock files that are needed during password change. Iconic multitasking honestly. π¦
THE ADVANTAGES πΈ
This design has the following benefits:
passwd(1)only needs to be SGID to groupshadow, not SUID to root.chage(1)and/usr/libexec/chkpwd/tcb_chkpwdare SGID to groupshadowtoo, which under the tcb scheme means they only have the privilege to access the user's own shadow file entry. So a bug in one of these utilities can at most give a malicious user direct access to their own shadow file. Damage contained, periodt. π«Ά- If a process needs read-only access to all shadow files, it's sufficient to give it the supplementary groups
"shadow"and"auth". - On systems supporting NSS, this scheme is completely transparent to applications that need read-only access to shadow file info. The
libnss_tcblibrary implementsgetspnam(3)and other related functions with their traditional semantics. Password changing is provided bypam_tcb(8), a PAM module.
See the tcb_convert(8) manual page for instructions on how to enable the tcb scheme seamlessly. π§
THE DISADVANTAGES (we keep it real here) π
Honestly, there are a few minor ones:
- It's impractical to lock all of the shadow database (see
tcb_unconvert(8)). - Giving a process read-only access to all shadow files as described above has the side-effect of also giving it read-write access to the shadow entry of the (pseudo-)user it's running as.
- It's impossible to give a process privileges sufficient for read-only access to a single shadow file only, without also having it actually run as that user.
- The user management tools initially required heavy patching to support the tcb scheme. π
WORKAROUNDS FOR FILESYSTEM LIMITS π
Okay so here's a fun little filesystem quirk: with ext2fs, the maximum number of hardlinks to a single file is limited to 32000. Which means with this filesystem, there can be at most 31998 directory entries in /etc/tcb and β with the filesystem layout described above β at most 31998 users. Math is mathing and it's giving limits. π
The workaround: a tcb directory of user U can live not only in /etc/tcb, but also in /etc/tcb/:some/path. In that latter case, there should be a symlink /etc/tcb/U -> /etc/tcb/:some/path/U.
Starting with tcb 0.9.8, directories that match the shell pattern /etc/tcb/:* are not treated as per-user directories by tcb libraries. These directories are reserved to hold symlinked per-user directories, and for other purposes.
By default, shadow suite utilities create directory entries directly in /etc/tcb; if you're expecting more than 31998 users on the system, you can switch on the symlink creation anytime by editing the login.defs(5) config file. Easy. β¨
AUTHORS π«Ά
The tcb suite was implemented for Openwall GNU/*/Linux by Rafal Wojtczuk <nergal at owl.openwall.com> and Solar Designer <solar at owl.openwall.com>. pam_tcb is meant to be backwards-compatible with pam_unix, so some design decisions are cloned from pam_unix. Also, certain less critical code fragments, as well as some of the code layout, are taken from the Linux-PAM implementation of pam_unix. The names of contributors to pam_unix can be found under orig_copyright/ in the source distribution of the tcb suite. Legend behavior. π
SEE ALSO π
And that's the whole vibe bestie β brought to you by the Openwall Project, dated 18 April 2003 (yeah she's an older icon but she still slays). Go forth and shadow securely. π β¨ π π¦ πΈ π π«Ά
π¦ where this page comes from
- nixpkgs unstable: tcb 1.2
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms