1230 Commits

Author SHA1 Message Date
Adam Williamson
b702d4c43f lib/chkhash.c: fix escaping in SHA-256 / SHA-512 / MD5 regexes
`\\n` inside square brackets doesn't include or exclude the
newline character. It includes or excludes a literal slash and
the literal character 'n'.

Fixes: c44f1e096a19 (2025-07-20; "chpasswd: Check hash before write when using -e")
Closes: <https://github.com/shadow-maint/shadow/issues/1519>
Signed-off-by: Adam Williamson <awilliam@redhat.com>
2026-01-29 12:32:16 +01:00
Alejandro Colomar
9a86c515a1 lib/chkhash.c: is_valid_hash(): Comment meaning of !hash and *
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2026-01-23 16:42:06 +01:00
Alejandro Colomar
bce404a7a8 lib/chkhash.c: is_valid_hash(): Update comment
This checks the entire shadow(5) 2nd field, which is more than just
a hash.

Reported-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2026-01-23 16:42:06 +01:00
Alejandro Colomar
9b67543987 lib/chkhash.c: is_valid_hash(): Accept an empty hash
It represents a passwordless account.
That is discouraged, but accepted.

Fixes: c44f1e096a19 (2025-07-20; "chpasswd: Check hash before write when using -e")
Link: <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1124835>
Reported-by: Marc 'Zugschlus' Haber <mh+githubvisible@zugschlus.de>
Reported-by: "Serge E. Hallyn" <serge@hallyn.com>
Reported-by: Adam Williamson <awilliam@redhat.com>
Co-authored-by: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2026-01-23 16:42:06 +01:00
Tobias Stoeckmann
b43089bcf1 lib/commonio.c: Drop lrename
The lrename function follows symlinks when renaming files. Since the
source is a temporary file and the target is the database file itself,
which is opened with O_NOFOLLOW, this function is only useful for an
attacker who manages to win some form of race.

Fixes: 0fa908302660 (2007-10-07; "[svn-upgrade] Integrating new upstream version, shadow (4.0.16)")
Fixes: 391a3847157c (2010-03-04; "2010-01-30  Paweł Hajdan, Jr.  <phajdan.jr@gentoo.org>")
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2026-01-14 23:56:46 +01:00
Tobias Stoeckmann
6cd3dcbbcc lib/commonio.c: Call utime for correct target
Since tmpf has been already renamed to target at this point, call utime
with target instead of tmpf.

Fixes: f8732b17dd1d (2026-01-14; "lib/commonio.c: Use unpredictable temporary names")
Reported-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2026-01-14 23:43:01 +01:00
Tobias Stoeckmann
c745eea4a4 lib/commonio.c: Larger buffer size for file names
Make sure that enough bytes exist for file name of temporary file which
is used to construct the next database file.

While at it, use a better variable name.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2026-01-14 13:05:45 +01:00
Tobias Stoeckmann
f8732b17dd lib/commonio.c: Use unpredictable temporary names
Make sure that an attacker with sufficient privileges cannot simply
create a file with expected temporary name to retrieve content of
previous and/or future database.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2026-01-14 13:05:45 +01:00
Tobias Stoeckmann
a472091869 lib/commonio.c: Unlink backup file on error
It doesn't make sense to keep a file around if it's not even a proper
backup.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2026-01-14 13:05:45 +01:00
Tobias Stoeckmann
d5638a5b2b lib/shadowlog_internal.h: Hide shadow_progname
Accessing and setting shadow_progname is not as straight-forward as it
might seem due to the way of linking libshadow_la with libsubid and
programs.

Enforce the usage of log_get_progname to make this less messy.

With last entry of shadowlog_internal.h gone, remove the file entirely.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2026-01-12 14:27:05 +01:00
Tobias Stoeckmann
ecaae2f8cd lib/shadowlog_internal.h: Drop shadow_logfd
Accessing this variable directly is a recipe for disaster, because
binaries and libraries can have different versions in them due to how
libshadow_la linking is performed.

Make sure that at least NULL check is always performed by calling the
proper getter function.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2026-01-12 14:27:05 +01:00
Tobias Stoeckmann
e37e43fd0a lib/motd.c: Remove unused include
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2026-01-11 03:05:31 +01:00
Tobias Stoeckmann
413c4908c8 Fix typos
Typos found with codespell

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2026-01-08 22:28:13 +01:00
Tobias Stoeckmann
78120f17df configure.ac: Drop libattr linking
The libattr dependency is no longer needed.

Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2026-01-08 09:12:02 +01:00
Tobias Stoeckmann
c8b7b5ef0d lib/copydir.c: Drop reset_selinux
The reset_selinux flag is always true, so it can be removed.
Remove all functions which are not used anymore as well.

Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2026-01-08 09:12:02 +01:00
Alejandro Colomar
ddc2549f87 lib/chkhash.c: is_valid_hash(): Accept '*' as the hash
This is widely accepted as an invalid hash, to remove password access
for an account (that is, no passwords will match the "hash").

Fixes: c44f1e096a19 (2025-07-20; "chpasswd: Check hash before write when using -e")
Closes: <https://github.com/shadow-maint/shadow/issues/1483>
Closes: <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1124835>
Reported-by: Chris Hofstaedtler <zeha@debian.org>
Reviewed-by: Chris Hofstaedtler <zeha@debian.org>
Cc: vinz <mmpx09@protonmail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2026-01-07 20:01:02 -06:00
Alejandro Colomar
87ec7a52ab lib/chkhash.c: is_valid_hash(): Accept a leading '!'
A leading '!' means that the account is locked.

Fixes: c44f1e096a19 (2025-07-20; "chpasswd: Check hash before write when using -e")
Link: <https://github.com/shadow-maint/shadow/issues/1483>
Link: <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1124835>
Reported-by: Chris Hofstaedtler <zeha@debian.org>
Reviewed-by: Chris Hofstaedtler <zeha@debian.org>
Cc: vinz <mmpx09@protonmail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2026-01-07 20:01:02 -06:00
Alejandro Colomar
9214a8e44d lib/: Use non-empty compound literals
While the empty one is more correct, {0} will also work, and will
likely silence diagnostics in old compiler versions.

Empty compound literals are only supported in GCC since commit
gcc.git 14cfa01755a6 (2022-08-25; "c: Support C2x empty initializer braces")

Reported-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-30 10:07:45 -06:00
Alejandro Colomar
ee7fa1dfc6 lib/, src/: Reduce scope of local variables
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-28 21:19:22 -06:00
Alejandro Colomar
0ff87bf37a lib/, src/: Some empty lists have 0 elements, not 1 empty string
In general, empty fields in a CSV are errors.  However, in some cases,
we want to allow passing empty lists, and the way to encode that is as
an empty string.  This was accidentally broken in 4.17.0, when we
switched from using strtok(3) to strsep(3), without remembering to
special-case an empty CSV.

The bug affected directly groupadd(8) and groupmod(8).

The bug also affected the library function add_groups().  In systems
using PAM, that function is unused.  On systems without PAM, it is
called by the library function setup_uid_gid(), with the contents of the
"CONSOLE_GROUPS" configuration (login.defs) CSV string.

setup_uid_gid() is directly called by su(1) and login(1) on systems
without PAM.

setup_uid_gid() is also called by the library function expire().

expire() is directly called by expiry(1), su(1), and login(1).

This bug is a regression introduced in the release 4.17.0, and present
in the releases 4.17.{0..4} and 4.18.0.

Fixes: 90afe61003ef (2024-12-05; "lib/, src/: Use strsep(3) instead of strtok(3)")
Link: <https://github.com/shadow-maint/shadow/issues/1420>
Reported-by: Osark Vieira <https://github.com/osark084>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-28 21:19:22 -06:00
Alejandro Colomar
977d76760b lib/, src/: Add blocks
This is in preparation for the following patch.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-28 21:19:22 -06:00
Alejandro Colomar
25aea74226 lib/chkname.c, src/: Strictly disallow really bad names
Some names are bad, and some names are really bad.  '--badname' should
only allow the mildly bad ones, which we can handle.  Some names are too
bad, and it's not possible to deal with them.  Reject them
unconditionally.

-  A leading '-' is too dangerous.  It breaks things like execve(2), and
   almost every command.

-  Spaces are used for delimiting lists of users and groups.

-  '"' is special in many languages, including the shell.  Having it in
   user names would be unnecessarily dangerous.

-  '#' is used for delimiting comments in several of our config files.
   Having it in usernames could result in incorrect configuration files.

-  "'" is special in many languages, including the shell.  Having it in
   user names would be unnecessarily dangerous.

-  ',' is used for delimiting lists of users and groups.

-  '/' is used for delimiting files, and thus could result in incorrect
   handling of users and groups.

-  ':' is the main delimiter in /etc/shadow and /etc/passwd.

-  ';' is special in many languages, including the shell.  Having it in
   user names would be unnecessarily dangerous.

There are other characters that we should disallow, but they need more
research to make sure we don't introduce regressions.  This set should
be less problematic.

Acked-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Reviewed-by: Chris Hofstaedtler <zeha@debian.org>
Cc: Marc 'Zugschlus' Haber <mh+githubvisible@zugschlus.de>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-25 22:40:55 -06:00
Tobias Stoeckmann
f6d9e5c019 lib/run_part.c: Fix error message
The failing function call was wait, not waitpid.

Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2025-12-24 14:57:37 +01:00
Tobias Stoeckmann
fa88997719 lib/obscure.c: Introduce obscure_get_range
Unify the retrieval of PASS_MIN_LEN and PASS_MAX_LEN for output
in passwd and actual checks.

Fixes wrong output for minimum password lengths if no such
restriction is configured: 5 is printed, 0 is in effect.

How to reproduce:

1. Use passwd compiled without PAM support
2. Do not specify PASS_MIN_LEN in login.defs
3. Run passwd as a user and enter your old password, then
   - you will see that 5 characters are expected
   - you can just press enter twice

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2025-12-20 20:22:50 +01:00
Tobias Stoeckmann
deb192fe78 lib/obscure.c: Fix PASS_MIN_LEN -1 case
The getdef_num implementation allows -1 to be specified in login.defs.
In general, -1 should be treated the same way as "not specified". In
this case, casting -1 to size_t leads to every password being "too
short."

Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2025-12-20 20:22:50 +01:00
Tobias Stoeckmann
876e874684 Fix documentation style
Always start a sentence with lowercase letter after 'Note:', 'Warning:',
etc. This unifies all occurrences.

No functional change.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2025-12-19 16:48:08 +01:00
Tobias Stoeckmann
1031f5a0fb lib/, src/: Drop 10000 as infinity
If password aging should not be performed, disable it properly. Just
specifying a "long enough time" is not infinity.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2025-12-19 15:21:49 +01:00
Tobias Stoeckmann
5369ad7566 lib/, src/: Fix formatting
Fix places where spaces were used instead of tabs.

No functional change.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2025-12-16 23:20:32 +01:00
Tobias Stoeckmann
7f59cb5ab3 lib/pwd2spwd.c: Set no aging information
The pwd_to_spwd routine claims that fields without corresponding
information in the password file are set to uninitialized values,
but sets some aging information. These cannot be available in
struct passwd.

Also, the code is only used in passwd to temporarily hold the
new password. All other values are copied from an existing entry
later on. If no entry exists, all values are dismissed anyway.

Clarify that everything is uninitialized except name and password.
Gets rid of magic value 10000 for sp_max.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2025-12-15 11:38:34 +01:00
Tobias Stoeckmann
d82cdfaf4c lib/pwd2spwd.c: Simplify style
No need for a nested block here.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2025-12-15 11:38:34 +01:00
Mike Gilbert
f973c406c5 lib/xgetXXbyYY.c: include stdint.h for SIZE_MAX
Fixes build failure:
```
In file included from xgetgrnam.c:40:
xgetXXbyYY.c: In function ‘xgetgrnam’:
xgetXXbyYY.c:83:31: error: ‘SIZE_MAX’ undeclared (first use in this function)
   83 |                 if (length == SIZE_MAX) {
      |                               ^~~~~~~~
```

Signed-off-by: Mike Gilbert <floppym@gentoo.org>
2025-12-13 21:46:32 +01:00
Alejandro Colomar
6a2e15c73b lib/tcbfuncs.c: rmdir_leading(): Create string just once
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-06 22:38:06 -06:00
Alejandro Colomar
4cf430b309 lib/tcbfuncs.c: rmdir_leading(): Constify input
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-06 22:38:06 -06:00
Alejandro Colomar
e7771cc196 lib/search/: lsearch_T(): Don't return anything
We don't use this value.  This silences a diagnostic about the unused
return value.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 21:22:45 -06:00
Alejandro Colomar
e3c217ec9e lib/: Rename XCALLOC() => xcalloc_T()
The 'T' in the name notes that this API is a type-safe variant of the
API it wraps.  This makes the names more explicative.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 21:22:45 -06:00
Alejandro Colomar
bc4e3712a6 lib/: Rename CALLOC() => calloc_T()
The 'T' in the name notes that this API is a type-safe variant of the
API it wraps.  This makes the names more explicative.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 21:22:45 -06:00
Alejandro Colomar
0d9193dcf6 lib/: Rename XMALLOC() => xmalloc_T()
The 'T' in the name notes that this API is a type-safe variant of the
API it wraps.  This makes the names more explicative.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 21:22:45 -06:00
Alejandro Colomar
0afe216953 lib/: Rename MALLOC() => malloc_T()
The 'T' in the name notes that this API is a type-safe variant of the
API it wraps.  This makes the names more explicative.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 21:22:45 -06:00
Alejandro Colomar
01a0aac628 lib/: Rename XREALLOC() => xrealloc_T()
The 'T' in the name notes that this API is a type-safe variant of the
API it wraps.  This makes the names more explicative.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 21:22:45 -06:00
Alejandro Colomar
e010eb2d4e lib/: Rename REALLOC() => realloc_T()
The 'T' in the name notes that this API is a type-safe variant of the
API it wraps.  This makes the names more explicative.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 21:22:45 -06:00
Alejandro Colomar
3de69c9668 lib/, src/: Rename REALLOCF() => reallocf_T()
The 'T' in the name notes that this API is a type-safe variant of the
API it wraps.  This makes the names more explicative.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 21:22:45 -06:00
Alejandro Colomar
d0a0c35cd8 lib/alloc/: REALLOC[F](): Move _Generic(3) to separate line
This should be more readable.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 21:22:45 -06:00
Alejandro Colomar
9705effba5 lib/: Use compound literals to avoid casts
Casts are unsafe.

Compound literals also have the ability of converting values, but they
don't have the unwanted effects on safety --casts disable most useful
diagnostics--.

Compound literals are lvalues, which means their address can be taken,
and they can also be assigned to.  To avoid this, we force lvalue
conversion through a statement expression.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 21:22:45 -06:00
Alejandro Colomar
882fbdf99b lib/alloc/: reallocarray[f]_(): Add helper macros to handle n?:1
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 21:22:45 -06:00
Alejandro Colomar
5e30a34a93 lib/gshadow.c: fgetsgent(): Don't use static variables
BTW, getline(3) says we are responsible for free(3)ing the buffer on
error.

Reported-by: Chris Hofstaedtler <zeha@debian.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 19:23:18 -06:00
Alejandro Colomar
c6178b722f lib/: Use getline(3) instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 19:23:18 -06:00
Alejandro Colomar
b0a7ce58b9 lib/, po/: Remove fgetsx() and fputsx()
It seems they never worked correctly.  Let's keep it simple and remove
support for escaped newlines.

Closes: <https://github.com/shadow-maint/shadow/issues/1055>
Reported-by: Chris Hofstaedtler <zeha@debian.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 19:23:18 -06:00
Alejandro Colomar
8a5d35cca4 lib/search/: Use (void)0 within _Generic(3) to avoid -Wunused-value diagnostics
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 09:21:50 -06:00
Alejandro Colomar
40be785f8a lib/sssd.h: sssd_flush_cache(): Define as static inline function
Being a macro, the unused return value triggers a diagnostic.
This probably needs further investigation, but we have the issue linked
below for that.

Link: <https://github.com/shadow-maint/shadow/issues/1221>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 09:21:50 -06:00
Alejandro Colomar
01db0fa627 lib/prefix_flag.c: Add [[gnu::unused]] to variable used in conditionally-compiled code
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2025-12-05 09:21:50 -06:00