Since we're checking for "vigr", it makes more sense to name the
variable accordingly.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Cherry-picked-from: 0ab893a734 ("src/vipw.c: Reverse logic and variable name")
Link: <https://github.com/shadow-maint/shadow/pull/962>
[alx: This is needed by 89c4da43cb ("src/vipw.c: Use string literals to initialize 'Prog'")
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Recently, we started using utmpx instead of utmp, and we updated
<./configure.ac> to do the checks for 'struct utmpx' instead of
'struct utmp'. However, I forgot to update the preprocessor
conditionals accordingly.
Fixes: 64bcb54fa9 ("lib/, src/, configure.ac: Use utmpx instead of utmp")
Link: <https://github.com/shadow-maint/shadow/pull/954>
Cc: Firas Khalil Khana <firasuke@gmail.com>
Cc: "A. Wilfox" <https://github.com/awilfox>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Cherry-picked-from: 1af6b68cbe ("lib/utmp.c: Use the appropriate autotools macros for struct utmpx")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Cherry-picked-from: 2806b827d8 ("lib/utmp.c: Use defined() instead of #if[n]def")
[alx: This is needed by 1af6b68cbe ("lib/utmp.c: Use the appropriate autotools macros for struct utmpx")]
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Indentation makes it clear which is which.
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Cherry-picked-from: 7e94a2f484 ("lib/utmp.c: Remove #endif comments")
[alx: This is needed by 1af6b68cbe ("lib/utmp.c: Use the appropriate autotools macros for struct utmpx")]
Signed-off-by: Alejandro Colomar <alx@kernel.org>
A difference between 'struct utmp' and 'struct utmpx' is that
the former uses UT_LINESIZE for the size of its array members,
while the latter doesn't have a standard variable to get its
size. Therefore, we need to get the number of elements in
the array with NITEMS().
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Cc: Firas Khalil Khana <firasuke@gmail.com>
Cc: "A. Wilfox" <https://github.com/awilfox>
Cherry-picked-from: 5ff6edf9f2 ("lib/utmp.c: Replace UT_LINESIZE by a NITEMS() calculation")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
utmpx is specified by POSIX as an XSI extension. That's more portable
than utmp, which is unavailable for example in musl libc. The manual
page specifies that in Linux (but it probably means in glibc), utmp and
utmpx (and the functions that use them) are identical, so this commit
shouldn't affect glibc systems.
Assume utmpx is always present.
Also, if utmpx is present, POSIX guarantees that some members exist:
- ut_user
- ut_id
- ut_line
- ut_pid
- ut_type
- ut_tv
So, rely on them unconditionally.
Fixes: 170b76cdd1 ("Disable utmpx permanently")
Closes: <https://github.com/shadow-maint/shadow/issues/945>
Reported-by: Firas Khalil Khana <firasuke@gmail.com>
Reported-by: "A. Wilfox" <https://github.com/awilfox>
Tested-by: Firas Khalil Khana <firasuke@gmail.com>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Cherry-picked-from: 64bcb54fa9 ("lib/, src/, configure.ac: Use utmpx instead of utmp")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This changes pull some more dependencies. That's too much for a stable
branch, I think. If anyone needs them, please ask for them, but for now
let's keep them out.
Reverts: 9d5591fba9 ("src/passwd.c: check password length upper limit")
Reverts: dbdda2a48a ("lib/: Saturate addition to avoid overflow")
Reverts: 541d4dde23 ("src/chage.c: Unify long overflow checks in print_day_as_date()")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
The passwd silently truncated the password length to PASS_MAX.
This patch introduces check that prints an error message
and exits the call.
Signed-off-by: Tomas Halman <tomas@halman.net>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Cherry-picked-from: f024002b3d66 ("src/passwd.c: inconsistent password length limit")
Cc: Serge Hallyn <serge@hallyn.com>
Link: <https://github.com/shadow-maint/shadow/pull/953>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
The passwd utility had hardcoded limit for password lenght set
to 200 characters. In the agetpass.c is used PASS_MAX for
this purpose.
This patch moves the PASS_MAX definition to common place
and uses it in both places.
Signed-off-by: Tomas Halman <tomas@halman.net>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Cherry-picked-from: f024002b3d66 ("src/passwd.c: inconsistent password length limit")
Cc: Serge Hallyn <serge@hallyn.com>
Link: <https://github.com/shadow-maint/shadow/pull/953>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Days officially roll over at 00:00 UTC, not at 12:00 UTC. I see no
reason to add that half day.
Also, remove the comment. It's likely to get stale.
So, get_date() gets the number of seconds since the Epoch. I wonder how
that thing works, but I'll assume it's something similar to getdate(3)
+ mktime(3). After that, we need to convert seconds since Epoch to days
since Epoch. That should be a simple division, AFAICS, since Epoch is
"1970‐01‐01 00:00:00 +0000 (UTC)". See mktime(3).
Fixes: 45c6603cc8 ("[svn-upgrade] Integrating new upstream version, shadow (19990709)")
Link: <https://github.com/shadow-maint/shadow/issues/939>
Reported-by: Michael Vetter <jubalh@iodoru.org>
Tested-by: Gus Kenion <https://github.com/kenion>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Cherry-picked-from: 1175932c0c ("lib/strtoday.c: strtoday(): Fix calculation")
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Link: <https://github.com/shadow-maint/shadow/pull/942>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Before 3b7cc05387 ("lib: replace `USER_NAME_MAX_LENGTH` macro"), this
code did use a length. It used a utmp(5) fixed-width buffer, so the
length matches the buffer size (there was no terminating NUL byte).
However, sysconf(_SC_LOGIN_NAME_MAX) returns a buffer size that accounts
for the terminating null byte; see sysconf(3). Thus, the commit that
introduced the call to sysconf(3), should have taken that detail into
account.
403a2e3771 ("lib/chkname.c: Take NUL byte into account"), by Tobias,
caught that bug in <lib/chkname.c>, but missed that the same commit that
introduced that bug, introduced the same bug in two other places.
This fixes all remaining calls to sysconf(_SC_LOGIN_NAME_MAX).
I still observe some suspicious code after this fix:
if (do_rlogin(hostname, username, max_size - 1, term, sizeof(term)))
...
login_prompt(username, max_size - 1);
We're passing size-1 to functions that want a size. But since the fix
to those will be different, let's do that in the following commits.
Link: <https://github.com/shadow-maint/shadow/pull/935>
Link: <https://github.com/shadow-maint/shadow/issues/920#issuecomment-1926002209>
Link: <https://github.com/shadow-maint/shadow/pull/757>
Link: <https://github.com/shadow-maint/shadow/issues/674>
See-also: 403a2e3771 ("lib/chkname.c: Take NUL byte into account")
Fixes: 3b7cc05387 ("lib: replace `USER_NAME_MAX_LENGTH` macro")
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Tobias Stoeckmann <tobias@stoeckmann.org>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Cherry-picked-from: 6551709e96 ("src/login.c: Fix off-by-one buggs")
Link: <https://github.com/shadow-maint/shadow/pull/936>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Very large values in /etc/shadow could lead to overflows. Make sure
that these calculations are saturated at LONG_MAX. Since entries are
based on days and not seconds since epoch, saturating won't hurt anyone.
Co-developed-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Co-developed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Cherry-picked-from: 674409e226 ("lib/: Saturate addition to avoid overflow")
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Link: <https://github.com/shadow-maint/shadow/pull/876>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
The conversion from day to seconds can be done in print_date
(renamed to print_day_as_date for clarification). This has the nice
benefit that DAY multiplication and long to time_t conversion are done
at just one place.
Co-developed-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Co-developed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Cherry-picked-from: 20100e4b22 ("src/chage.c: Unify long overflow checks in print_day_as_date()")
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Link: <https://github.com/shadow-maint/shadow/pull/876>
[alx: This is a pre-requisite for 674409e226 ("lib/: Saturate addition to avoid overflow")]
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This fixes build with glibc-2.33 (newer glibc merged libdl and libpthread
into libc):
```
libtool: link: x86_64-pc-linux-gnu-gcc -isystem /usr/include/bsd -DLIBBSD_OVERLAY -O2 -pipe -Wl,-O1 -o login login.o login_nopam.o -Wl,--as-needed ../lib/.libs/libshadow.a -lcrypt -lsystemd -lpam -lpam_misc -lbsd
/usr/lib/gcc/x86_64-pc-linux-gnu/13/../../../../x86_64-pc-linux-gnu/bin/ld: ../lib/.libs/libshadow.a(libshadow_la-nss.o): undefined reference to symbol 'dlclose@@GLIBC_2.2.5'
/usr/lib/gcc/x86_64-pc-linux-gnu/13/../../../../x86_64-pc-linux-gnu/bin/ld: /lib64/libdl.so.2: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
```
In Debian, the needed macro from libtool seems to be in libltdl-dev.
Signed-off-by: Sam James <sam@gentoo.org>
Cc: Iker Pedrosa <ikerpedrosam@gmail.com>
Cherry-picked-from: 0f4e59fd00 ("Link correctly with libdl")
Link: <https://github.com/shadow-maint/shadow/pull/917>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
If reallocation fails in function list, then reset the size to 0 again.
Without the reset, the next call assumes that `members` points to
a memory location with reserved space.
Also use size_t instead of int for size to prevent signed integer
overflows. The length of group lines is not limited.
Fixes 45c0003e53 (4.14 release series)
Proof of Concept:
- Prepare a group file (one long group line and a shorter one, both with a list of users)
$ echo -n "root:x:0:" > /tmp/uwu
$ yes , | tr -d '\n' | dd of=/tmp/uwu bs=10 count=3145728 seek=1 conv=notrunc iflag=fullblock
$ echo -e "\nbin:x:1:," >> /tmp/uwu
- Run grpck with tight memory constraints
$ ulimit -d 102400
$ grpck /tmp/uwu
Segmentation fault (core dumped)
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
Cherry-picked-from: a9e07c0feb ("lib/sgetgrent.c: fix null pointer dereference")
Link: <https://github.com/shadow-maint/shadow/pull/904>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
If shadow is built without libbsd support, then readpassphrase() needs
to be provided from the project.
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
With the recent changes both login and su compilation fail because there
are some missing dependencies from SELINUX library. Thus, add LIBSELINUX
to su and login for those cases where the library is used.
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Remove `utmp` structure as an argument and include its logic inside the
function. This will help remove any reference to utmp from login.
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
The functionality from this function is related to utmp. Restrict access
to `setutmp()` to the same file.
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
In some embedded systems, users only use the ps
provided by the busybox. But the ps provided by
the busybox does not support the -eo option by
default. As a result, an error is reported when
the userdel is used. So add a judgment on ps.
If there is no ps -eo, traverse the process directly.
The error information is as follows:
# userdel xsl
ps: invalid option -- 'e'
Signed-off-by: xiongshenglan <xiongshenglan@huawei.com>
Print a warning even for the root user if the provided shell isn't
listed in /etc/shells, but continue to execute the action.
In case of non root user exit.
See https://github.com/shadow-maint/shadow/issues/535
Add a comment at the top of that file explaining how to
regenerate it.
We should add a README, but I don't have time to draft one
right now.
Signed-off-by: Serge Hallyn <serge@hallyn.com>
Since newgrp is setuid-root, any write() system calls it does in order
to print error messages will be done as the root user.
Unprivileged users can get newgrp to print essentially arbitrary strings
to any open file in this way by passing those strings as argv[0] when
calling execve(). For example:
$ setpid() { (exec -a $1$'\n:' newgrp '' 2>/proc/sys/kernel/ns_last_pid & wait) >/dev/null; }
$ setpid 31000
$ readlink /proc/self
31001
This is not a vulnerability in newgrp; it is a bug in the Linux kernel.
However, this type of bug is not new [1] and it makes sense to try to
mitigate these types of bugs in userspace where possible.
[1]: https://lwn.net/Articles/476947/
Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
b1282224 (Add maximum padding to fit IPv6-Addresses, 2020-05-24) pads
the From field header using `maxIPv6Addrlen - 3`. This leaves the
Latest field header misaligned. Subtract 4 (the length of "From").
Fixes build error:
newusers.c: In function 'update_passwd':
newusers.c:433:21: error: 'sflg' undeclared (first use in this function); did you mean 'rflg'?
introduced by
5cd04d03f9
which forgot to define sflg for these configure options:
--without-sha-crypt --without-bcrypt --with-yescrypt
Using the --sha-rounds option without first giving a crypt method via the --crypt-method option results in comparisons with a NULL pointer and thus make chgpasswd segfault:
$ chgpasswd -s 1
zsh: segmentation fault chgpasswd -s 1
Current patch add a sanity check before these comparisons to ensure there is a defined encryption method.
How to trigger this password leak?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When gpasswd(1) asks for the new password, it asks twice (as is usual
for confirming the new password). Each of those 2 password prompts
uses agetpass() to get the password. If the second agetpass() fails,
the first password, which has been copied into the 'static' buffer
'pass' via STRFCPY(), wasn't being zeroed.
agetpass() is defined in <./libmisc/agetpass.c> (around line 91), and
can fail for any of the following reasons:
- malloc(3) or readpassphrase(3) failure.
These are going to be difficult to trigger. Maybe getting the system
to the limits of memory utilization at that exact point, so that the
next malloc(3) gets ENOMEM, and possibly even the OOM is triggered.
About readpassphrase(3), ENFILE and EINTR seem the only plausible
ones, and EINTR probably requires privilege or being the same user;
but I wouldn't discard ENFILE so easily, if a process starts opening
files.
- The password is longer than PASS_MAX.
The is plausible with physical access. However, at that point, a
keylogger will be a much simpler attack.
And, the attacker must be able to know when the second password is being
introduced, which is not going to be easy.
How to read the password after the leak?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Provoking the leak yourself at the right point by entering a very long
password is easy, and inspecting the process stack at that point should
be doable. Try to find some consistent patterns.
Then, search for those patterns in free memory, right after the victim
leaks their password.
Once you get the leak, a program should read all the free memory
searching for patterns that gpasswd(1) leaves nearby the leaked
password.
On 6/10/23 03:14, Seth Arnold wrote:
> An attacker process wouldn't be able to use malloc(3) for this task.
> There's a handful of tools available for userspace to allocate memory:
>
> - brk / sbrk
> - mmap MAP_ANONYMOUS
> - mmap /dev/zero
> - mmap some other file
> - shm_open
> - shmget
>
> Most of these return only pages of zeros to a process. Using mmap of an
> existing file, you can get some of the contents of the file demand-loaded
> into the memory space on the first use.
>
> The MAP_UNINITIALIZED flag only works if the kernel was compiled with
> CONFIG_MMAP_ALLOW_UNINITIALIZED. This is rare.
>
> malloc(3) doesn't zero memory, to our collective frustration, but all the
> garbage in the allocations is from previous allocations in the current
> process. It isn't leftover from other processes.
>
> The avenues available for reading the memory:
> - /dev/mem and /dev/kmem (requires root, not available with Secure Boot)
> - /proc/pid/mem (requires ptrace privileges, mediated by YAMA)
> - ptrace (requires ptrace privileges, mediated by YAMA)
> - causing memory to be swapped to disk, and then inspecting the swap
>
> These all require a certain amount of privileges.
How to fix it?
~~~~~~~~~~~~~~
memzero(), which internally calls explicit_bzero(3), or whatever
alternative the system provides with a slightly different name, will
make sure that the buffer is zeroed in memory, and optimizations are not
allowed to impede this zeroing.
This is not really 100% effective, since compilers may place copies of
the string somewhere hidden in the stack. Those copies won't get zeroed
by explicit_bzero(3). However, that's arguably a compiler bug, since
compilers should make everything possible to avoid optimizing strings
that are later passed to explicit_bzero(3). But we all know that
sometimes it's impossible to have perfect knowledge in the compiler, so
this is plausible. Nevertheless, there's nothing we can do against such
issues, except minimizing the time such passwords are stored in plain
text.
Security concerns
~~~~~~~~~~~~~~~~~
We believe this isn't easy to exploit. Nevertheless, and since the fix
is trivial, this fix should probably be applied soon, and backported to
all supported distributions, to prevent someone else having more
imagination than us to find a way.
Affected versions
~~~~~~~~~~~~~~~~~
All. Bug introduced in shadow 19990709. That's the second commit in
the git history.
Fixes: 45c6603cc8 ("[svn-upgrade] Integrating new upstream version, shadow (19990709)")
Reported-by: Alejandro Colomar <alx@kernel.org>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Seth Arnold <seth.arnold@canonical.com>
Cc: Christian Brauner <christian@brauner.io>
Cc: Balint Reczey <rbalint@debian.org>
Cc: Sam James <sam@gentoo.org>
Cc: David Runge <dvzrv@archlinux.org>
Cc: Andreas Jaeger <aj@suse.de>
Cc: <~hallyn/shadow@lists.sr.ht>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
- Invert conditional to reduce indentation.
- Reduce use of whitespace and newlines while unindenting.
- Reorder variable declarations.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
- Invert conditional to reduce indentation.
- Rewrite while loop calling strtok(3) as a for loop. This allows
doing more simplification inside the loop (see next commit).
Signed-off-by: Alejandro Colomar <alx@kernel.org>
- Fix indentation. It was very broken.
- Move variable declaration to the top of the block in which it's used.
- Reduce use of whitespace and newlines.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
- Invert conditional, to reduce indentation.
- Reduce use of whitespace and newlines while unindenting.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
- Merge nested conditionals into a single if, to reduce indentation.
- Indent (1 SP) nested preprocessor conditionals.
- Reduce use of whitespace and newlines while unindenting.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
- Use the temporary variable more, as it helps readability: it removes
a derefecence, which itself allows removing some parentheses.
- Use a shorter name, which is more common with temporaries, and so
there's less to read.
- Assign to *ranges at the end of the function. It's the same, but
with the other changes, I think this makes it slightly clearer.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
If we consider simple objects as arrays of size 1, we can considerably
simplify these APIs, merging the *ARRAY and the non-array variants.
That will produce more readable code, since lines will be shorter (by
not having ARRAY in the macro names, as all macros will consistently
handle arrays), and the allocated size will be also more explicit.
The syntax will now be of the form:
p = MALLOC(42, foo_t); // allocate 42 elements of type foo_t.
p = MALLOC(1, bar_t); // allocate 1 element of type foo_t.
The _array() allocation functions should _never_ be called directly, and
instead these macros should be used.
The non-array functions (e.g., malloc(3)) still have their place, but
are limited to allocating structures with flexible array members. For
any other uses, the macros should be used.
Thus, we don't use any array or ARRAY variants in any code any more, and
they are only used as implementation details of these macros.
Link: <https://software.codidact.com/posts/285898/288023#answer-288023>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
alloca(3) fails silently if not enough memory can be allocated on the
stack. Use checked dynamic allocation instead.
Also drop unnecessary manual NUL assignment, ensured by snprintf(3).
Co-developed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Allocate enough memory for the strings, two slashes and the NUL
terminator.
Reported-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Those comments were written when this function used 64 bits (and
temporary variables of 128 bits). Now it uses 32 bits, with temporaries
of 64 bits, so some values have changed.
Fixes: 2a61122b5e ("Unoptimize the higher part of the domain of csrand_uniform()")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This makes the function fit in less screens. This is to avoid consuming
more natural resources than we have available, and everyone knows the
supply of new-lines on a screen is not a renewable source[1].
Some transformations have been done thanks to free(NULL) being an alias
for loopity_loop(), as defined three comits ago. The real definition of
free(3) that everyone has been hiding is this:
void
free(void *p)
{
if (p == NULL)
loopity_loop();
else
real_free(p);
}
Link: [1] <https://www.kernel.org/doc/html/v6.3/process/coding-style.html#placing-braces-and-spaces>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This was to a loop, as "1234" is to computer security.
No really; a loop that ends in a (forward) goto, and has no continue in it.
Still want a loop? Take two:
#define loopity_loop() do { for (;;) { break; } continue; } while (0-0)
Closes: <https://github.com/shadow-maint/shadow/issues/736>
Easter-egg: 8492dee663 ("subids: support nsswitch")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
The permission also need to be checked before process_root_flag() since
that can chroot into non-selinux environment (unavailable selinux mount
point for example).
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
- Use SIZE_MAX rather than (size_t)-1, to improve readability.
- Move the only branch that breaks to the first place, so that we
remove an else. This reduces nesting while parsing the code.
- Now that we only have a 2-branch conditional where both branches
assign to the same variable, rewrite it as a ternary, to shorten.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
The error handling is performed after the loop. By just calling break it
is possible to reuse the error handling if status is not ERANGE.
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
A failure of DUP_FUNCTION is already handled for non-reentrant
function wrapper. Perform the check for reentrant version as well.
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
On failure, these are meant to return 0 with errno set. But if
an nss module is loaded, they were returning -ERRNO instead.
Signed-off-by: Serge Hallyn <serge@hallyn.com>
- Don't else after return or fail_exit().
- Prefer == over != (negated logic is more complex to think about it).
- Reduce nesting when reasonable.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
There's no reason to report all errors. Bail out at the first one,
which is simpler.
Suggested-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Some errors were being reported in stderr, but then they weren't really
being treated as errors.
If mkdir(2) for EEXIST, it's possible that the sysadmin pre-created the
user dir; don't fail. However, let's keep a log line, for having some
notice that it happened.
Also, run chmod(2) if mkdir(2) failed for EEXIST (so transform the
'else if' into an 'if').
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
OpenSSH and coreutils' chroot call chroot first and then chdir. Doing it
this way is a bit safer because otherwise something could happen between
chdir and chroot to the specified path (like exchange of links) so the
working directory would not end up within the chroot environment.
This is a purely defensive measure.
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
This is no real world security fix.
The overflow could occur if too many layered subsystems are encountered
because the function check_perms calls itself recursively.
It would already take a misconfigured system for this to achieve it.
Use an iterative approach by calling the do_check_perms in a loop
instead of calling itself recursively.
As a side note: At least GCC 13 optimized this code and already uses
a jmp in its assembler code. I could only see the stack overflow by
activating address sanitizer which prevented the optimization.
Co-developed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
If a user has home directory "/" and login shell "*" then login and su
enter an endless loop by constantly switching to the next subsystem.
This could also be achieved with a layered approach so just checking
for "/" as home directory is not enough to protect against such a
misconfiguration.
Just break the loop if it progressed too far. I doubt that this has
negative impact on any real setup.
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
If econf_getStringValue() fails, it will return an error and
set value to NULL. Look for the error and avoid dereferencing
value in that case.
Signed-off-by: Serge Hallyn <serge@hallyn.com>
The function is completely different based on USE_CONF. Either copy
will be easier to read if we just keep them completely separate.
Signed-off-by: Serge Hallyn <serge@hallyn.com>
You can see the memory leaks with address sanitizer if shadow is
compiled with `--enable-vendordir=/usr/etc`.
How to reproduce:
1. Prepare a custom shell file as root
```
mkdir -p /etc/shells.d
echo /bin/myshell > /etc/shells.d/custom
```
2. Run chsh as regular user
```
chsh
```
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
The getusershell implementation of musl returns every line within the
/etc/shells file, which even includes comments. Only consider absolute
paths for login shells.
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
Using --prefix in a setuid binary is quite dangerous. An unprivileged
user could prepare a custom shadow file in home directory. During a data
race the user could exchange directories with links which could lead to
exchange of shadow file in system's /etc directory.
This could be used for local privilege escalation.
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
Please find attached the french updated translation of shadow-man-page,
proofread by the debian-l10n-french mailing list contributors.
Signed-off-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Neither a pid_t below 1 nor a negative fd could be valid in this context.
Proof of Concept:
$ newuidmap -1 1 1 1
newuidmap: Could not open proc directory for target 4294967295
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
Some strings are first written into static char arrays before passed to
functions which expect a const char pointer anyway.
It is easier to pass these strings directly as arguments.
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
The fcntl call to set FD_CLOEXEC can be performed directly with the
previously performed open call by using the O_CLOEXEC flag.
O_CLOEXEC is required by POSIX.1-2008.
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
The only user of login_prompt is the login tool. This implies that the
first argument is always the same.
It is much easier to verify printf's format string and its argument if
both are next to each other.
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
Parsing optional environment variables after a login name is a feature
which is neither documented nor available in util-linux or busybox
login which are other wide spread login utilities used in Linux
distributions as reference.
Removing this feature resolves two issues:
- A memory leak exists if variables without an equal sign are used,
because set_env creates copies on its own. This could lead to OOM
situations in privileged part of login or may lead to heap spraying.
- Environment variables are not reset between login attempts. This
could lead to additional environment variables set for a user who
never intended to do so.
Proof of Concept on a system with shadow login without PAM and
util-linux agetty:
1. Provoke an invalid login, e.g. user `noone` and password `invalid`.
This starts shadow login and subsequent inputs are passed through
the function login_prompt.
2. Provoke an invalid login with environment variables, e.g.
user `noone HISTFILE=/tmp/owo` and password `invalid`.
3. Log in correctly with user `root`.
Now you can see with `echo $HISTFILE` that `/tmp/owo` has been set for
the root user.
This requires a malicious failed login attempt and a successful login
within the configured login timeout (default 60 seconds).
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
The getline function does not return a pointer but the amount of read
characters. The error return value to check for is -1.
Set buf to NULL to avoid dereference of an uninitialized stack value.
The getline function returns -1 if size argument is NULL. Always use
a valid pointer even if size is unimportant.
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
Add the relevant XKCD to the passwd(1) manual page. It already explains
most of the rationale behind this patch.
Add also reference to makepasswd(1), which is a good way to generate
strong passwords. Personally, I commonly run `makepasswd --chars 64` to
create my passwords, or 32 for passwords I need to type interactively
often.
The strength of a password is an exponential formula, where the base is
the size of the character set, and the exponent is the length of the
password. That already shows why long passwords of just lowercase
letters are better than short Pa$sw0rdZ3. But an even more important
point is that humans, when forced to use symbols in a password, are more
likely to do trivial substitutions on simple passwords, which doesn't
increase strength, and can instead give a false sense of strength, which
is dangerous.
Closes: <https://github.com/shadow-maint/shadow/issues/688>
Link: <https://xkcd.com/936/>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Destroying the handle does not actually disconnect, see [1].
Also free the key on user removal.
[1]: e9072e7d45/libsemanage/src/direct_api.c (L330)
Example adduser leak:
Direct leak of 1008 byte(s) in 14 object(s) allocated from:
#0 0x5638f2e782ae in __interceptor_malloc (./src/useradd+0xee2ae)
#1 0x7fb5cfffad09 in dbase_file_init src/database_file.c:170:45
Direct leak of 392 byte(s) in 7 object(s) allocated from:
#0 0x5638f2e782ae in __interceptor_malloc (./src/useradd+0xee2ae)
#1 0x7fb5cfffc929 in dbase_policydb_init src/database_policydb.c:187:27
Direct leak of 144 byte(s) in 2 object(s) allocated from:
#0 0x5638f2e782ae in __interceptor_malloc (./src/useradd+0xee2ae)
#1 0x7fb5cfffb519 in dbase_join_init src/database_join.c:249:28
[...]
Free the actual struct of the removed entry.
Example userdel report:
Direct leak of 40 byte(s) in 1 object(s) allocated from:
#0 0x55b230efe857 in reallocarray (./src/userdel+0xda857)
#1 0x55b230f6041f in mallocarray ./lib/./alloc.h:97:9
#2 0x55b230f6041f in commonio_open ./lib/commonio.c:563:7
#3 0x55b230f39098 in open_files ./src/userdel.c:555:6
#4 0x55b230f39098 in main ./src/userdel.c:1189:2
#5 0x7f9b48c64189 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
run_parts currently exists in useradd and userdel, this commit mirrors
the functionality with groupadd and groupdel
Hook for group{add,del} to include killing processes that have group
membership that would no longer exist to avoid membership ID reuse.
getline(3) is much more readable than manually looping. It has some
overhead due to the allocation of a buffer, but that shouldn't be a
problem here. If that was a problem, we could reuse the buffer (thus
making the function non-reentrant), but I don't think that's worth the
extra complexity.
Using rpmatch(3) instead of a simple y/n test provides i18n to the
response checking. We have a fall-back minimalistic implementation for
systems that lack this function (e.g., musl libc).
While we're at it, apply some other minor improvements to this file:
- Remove comment saying which files use this function. That's likely
to get outdated. And anyway, it's just a grep(1) away, so it doesn't
really add any value.
- Remove unnecessary casts to (void) that were used to verbosely ignore
errors from stdio calls. They add clutter without really adding much
value to the code (or I don't see it).
- Remove comments from the function body. They make the function less
readable. Instead, centralize the description of the function into a
man-page-like comment before the function definition. This keeps the
function body short and sweet.
- Add '#include <stdbool.h>', which was missing.
- Minor whitespace style changes (it doesn't hurt the diff at this
point, since most of the affected lines were already touched by other
changes, so I applied my preferred style :).
Acked-by: Samanta Navarro <ferivoz@riseup.net>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
The tools newgrp and useradd expect waitpid to behave as described in
its manual page. But the notes indicate that if SIGCHLD is ignored,
waitpid behaves differently.
A user could set SIGCHLD to ignore before starting newgrp through exec.
Children of newgrp would not become zombies and their PIDs could be
reassigned before newgrp could call kill with the child pid and SIGCONT.
The useradd tool is not installed setuid, but I have added the default
there as well (copied from vipw).
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
Do not stop after 79 characters. Read the complete line to avoid
arbitrary limitations.
Proof of Concept:
```
cat > passwd-poc << EOF
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
EOF
python -c "print(80*'y')" | pwck passwd-poc
```
Two lines should still be within the file because we agreed only once
to remove a duplicated line.
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
If make fails in a multi-process invocation, the log is pretty much
unreadable. To make it readable, build as much as can be built without
failing. Then run a single-process make again. If we succeeded
previously, this should be a no-op. If not, this run will stop at the
first error, which should be more readable, and will only print the few
lines we're interested in.
This has some side effects: Now we build as much as we can, instead of
failing as early as possible; this may make CI a bit slower. However,
it also has the benefit that you see _all_ the error messages that could
be given, instead of needing to fix the first error to see the next and
so on.
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
libbsd-devel libeconf-devel have already been added to the spec file and
they should be installed by the `dnf builddep` command.
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
e5905c4b ("Added control character check") introduced checking for
control characters but had the logic inverted, so it rejects all
characters that are not control ones.
Cast the character to `unsigned char` before passing to the character
checking functions to avoid UB.
Use strpbrk(3) for the illegal character test and return early.
Both semanage and libsemanage actually set the user's mls range to the
default of the seuser, which makes more sense and removes a bit of code
for usermod and useradd. More fine-grained details must always be set
with some other tool
(semanage) anyway.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
The --gid option accepts a group name or id. When a name is provided, it
is resolved to an id by looking up the name in the group database
(/etc/group).
The --prefix option overides the location of the passwd and group
databases. I suspect the --gid option was overlooked when wiring up the
--prefix option.
useradd --gid already respects --prefix; this change makes usermod
behave the same way.
Fixes: b6b2c756c9
Signed-off-by: Mike Gilbert <floppym@gentoo.org>
This commit will serve to document why we shouldn't worry about the
truncation in the call to strlcpy(3). Since we have one more byte in
tmptty than in full_tty, truncation will produce a string that is at
least one byte longer than full_tty. Such a string could never compare
equal, so we're actually handling the truncation in a clever way. Maybe
too clever, but that's why I'm documenting it here.
Now, about the simplification itself:
Since we made sure that both full_tty and tmptty are null-terminated, we
can call strcmp(3) instead of strncmp(3). We can also simplify the
return logic avoiding one branch.
Cc: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
* libmisc/utmp.c (is_my_tty): Declare the parameter as a char array,
not char *, as it is not necessarily null-terminated.
Avoid a read overrun when reading 'tty', which comes from
'ut_utname'.
Reported-by: Paul Eggert <eggert@cs.ucla.edu>
Co-developed-by: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
* libmisc/date_to_str.c (date_to_str): Do not crash if gmtime(3)
returns NULL because the timestamp is far in the future.
Reported-by: Paul Eggert <eggert@cs.ucla.edu>
Co-developed-by: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
* lib/gshadow.c (sgetsgent): Use strcpy(3) not strlcpy(3),
since the string is known to fit.
Signed-off-by: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
* lib/fields.c (change_field): Don't point
before array start; that has undefined behavior.
Signed-off-by: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
* lib/fields.c (change_field): Since we know the string fits,
use strcpy(3) rather than strlcpy(3).
Signed-off-by: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
gettime.c:25:30: warning: a function declaration without a prototype is deprecated in all versions of C [-Wstrict-prototypes]
/*@observer@*/time_t gettime ()
^
void
shellcheck warns against using echo with flags, as posix sh won't
support it. It suggests using printf, so let's do that.
Signed-off-by: Serge Hallyn <serge@hallyn.com>
bc github...
For some reason, the first test - ONLY on github - seems to not
give the '$ ' prompt expected when you spawn 'su testsuite'.
So just run the first test twice, and ignore the first failure.
It messes with the expected results.
We can do better than this in the expect scripts, but let's
get things running for now.
Signed-off-by: Serge Hallyn <serge@hallyn.com>
write_mapping() will do the following:
openat(proc_dir_fd, map_file, O_WRONLY);
An attacker could create a directory containing a symlink named
"uid_map" pointing to any file owned by root, and thus allow him to
overwrite any root-owned file.
Closes#635
newuidmap and newgidmap currently take an integner pid as
the first argument, determining the process id on which to
act. Accept also "fd:N", where N must be an open file
descriptor to the /proc/pid directory for the process to
act upon. This way, if you
exec 10</proc/99
newuidmap fd:10 100000 0 65536
and pid 99 dies and a new process happens to take pid 99 before
newuidmap happens to do its work, then since newuidmap will use
openat() using fd 10, it won't change the mapping for the new
process.
Example:
// terminal 1:
serge@jerom ~/src/nsexec$ ./nsexec -W -s 0 -S 0 -U
about to unshare with 10000000
Press any key to exec (I am 129176)
// terminal 2:
serge@jerom ~/src/shadow$ exec 10</proc/129176
serge@jerom ~/src/shadow$ sudo chown root src/newuidmap src/newgidmap
serge@jerom ~/src/shadow$ sudo chmod u+s src/newuidmap
serge@jerom ~/src/shadow$ sudo chmod u+s src/newgidmap
serge@jerom ~/src/shadow$ ./src/newuidmap fd:10 0 100000 10
serge@jerom ~/src/shadow$ ./src/newgidmap fd:10 0 100000 10
// Terminal 1:
uid=0(root) gid=0(root) groups=0(root)
Signed-off-by: Serge Hallyn <serge@hallyn.com>
We can't use a pointer that was input to realloc(3), nor any pointers
that point to reallocated memory, without making sure that the memory
wasn't moved. If we do, the Behavior is Undefined.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Use of these macros, apart from the benefits mentioned in the commit
that adds the macros, has some other good side effects:
- Consistency in getting the size of the object from sizeof(type),
instead of a mix of sizeof(type) sometimes and sizeof(*p) other
times.
- More readable code: no casts, and no sizeof(), so also shorter lines
that we don't need to cut.
- Consistency in using array allocation calls for allocations of arrays
of objects, even when the object size is 1.
Cc: Valentin V. Bartenev <vbartenev@gmail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This macros have several benefits over the standard functions:
- The type of the allocated object (not the pointer) is specified as an
argument, which improves readability:
- It is directly obvious what is the type of the object just by
reading the macro call.
- It allows grepping for all allocations of a given type.
This is admittedly similar to using sizeof() to get the size of the
object, but we'll see why this is better.
- In the case of reallocation macros, an extra check is performed to
make sure that the previous pointer was compatible with the allocated
type, which can avoid some mistakes.
- The cast is performed automatically, with a pointer type derived from
the type of the object. This is the best point of this macro, since
it does an automatic cast, where there's no chance of typos.
Usually, programmers have to decide whether to cast or not the result
of malloc(3). Casts usually hide warnings, so are to be avoided.
However, these functions already return a void *, so a cast doesn't
really add much danger. Moreover, a cast can even add warnings in
this exceptional case, if the type of the cast is different than the
type of the assigned pointer. Performing a manual cast is still not
perfect, since there are chances that a mistake will be done, and
even ignoring accidents, they clutter code, hurting readability.
And now we have a cast that is synced with sizeof.
- Whenever the type of the object changes, since we perform an explicit
cast to the old type, there will be a warning due to type mismatch in
the assignment, so we'll be able to see all lines that are affected
by such a change. This is especially important, since changing the
type of a variable and missing to update an allocation call far away
from the declaration is easy, and the consequences can be quite bad.
Cc: Valentin V. Bartenev <vbartenev@gmail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
We'll expand the contents in a following commit, so let's move the file
to a more generic name, have a dedicated header, and update includes.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Use the new header for xstrdup()
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This is guaranteed by ISO C. Now that we require ISO C (and even POSIX)
to compile, we can simplify this code.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
On 2/19/23 18:09, David Mudrich wrote:
> I am working on a RAM based Linux OS from source, and try to use
> latest versions of all software. I found shadow needs libbsd's
> readpassphrase(3) as superior alternative to getpass(3). While
> considering if I a) include libbsd, or include libbsd's code of
> readpassphrase(3) into shadow, found, that libbsd's readpassphrase(3)
> never returns \n or \r
> <https://cgit.freedesktop.org/libbsd/tree/src/readpassphrase.c>
> line 122, while agetpass() uses a check for \n in agetpass.c line 108.
> I assume it always fails.
Indeed, it always failed. I made a mistake when writing agetpass(),
assuming that readpassphrase(3) would keep newlines.
>
> I propose a check of len == PASS_MAX - 1, with false positive error for
> exactly PASS_MAX - 1 long passwords.
Instead, I added an extra byte to the allocation to allow a maximum
password length of PASS_MAX (which is the maximum for getpass(3), which
we're replacing.
While doing that, I notice that my previous implementation also had
another bug (minor): The maximum password length was PASS_MAX - 1
instead of PASS_MAX. That's also fixed in this commit.
Reported-by: David Mudrich <dmudrich@gmx.de>
Fixes: 155c9421b9 ("libmisc: agetpass(), erase_pass(): Add functions for getting passwords safely")
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Some programs don't support `(uint16_t) -1` or `(uint32_t) -1` as user
or group IDs. This is because `-1` is used as an error code or as an
unspecified ID, e.g. in `chown(2)` parameters, and in the past, `gid_t`
and `uid_t` have changed width. For legacy reasons, those values have
been kept reserved in programs today (for example systemd does this; see
the documentation in the link below).
This should not be confused with catching overflow in the ID values,
since that is already caught by our ERANGE checks. This is about not
using reserved values that have been reserved for legacy reasons.
Link: <https://systemd.io/UIDS-GIDS/>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
These comments should indicate which functions they really wrap.
An alternative would be to remove the line completely to avoid
future copy&paste mistakes.
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
This function simplifies the calculation of the bounds of the buffer for
catenating strings. It would also reduce error checking, but we don't
care about truncation in this specific code. :)
Signed-off-by: Alejandro Colomar <alx@kernel.org>
strncat(3), strlcpy(3), and many other functions are often misused for
catenating strings, when they should never be used for that. strlcat(3)
is good. However, there's no equivalent to strlcat(3) similar to
snprintf(3). Let's add stpecpy(), which is similar to strlcat(3), but
it is also the only function compatible with stpeprintf(), which makes
it more useful than strlcat(3).
Signed-off-by: Alejandro Colomar <alx@kernel.org>
All the string-copying functions called above do terminate the strings
they create with a NUL byte. Writing it again at the end of the buffer
is unnecessary paranoid code. Let's remove it.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This function allows reducing error checking (since errors are
propagated across chained calls), and also simplifies the calculation of
the start and end of the buffer where the string should be written.
Moreover, the new code is more optimized, since many calls to strlen(3)
have been removed.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
[v]stpeprintf() are similar to [v]snprintf(3), but they allow chaining.
[v]snprintf(3) are very dangerous for catenating strings, since the
obvious ways to do it invoke Undefined Behavior, and the ways that avoid
UB are very error-prone.
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
When trying to build shadow in a different directory I stumbled upon few
issues, this commit aims to fix all of them:
- The `subid.h` file is generated and hence in the build directory and
not in the source directory, so use `$(builddir)` instead of
`$(srcdir)`.
- Using `$<` instead of filenames utilises autotools to locate the files
in either the source or build directory automatically.
- `xsltproc` needs to access the files in login.defs.d in either the
source directory or the symlink in a language subdirectory, but it
does not interpret the `--path` as prefix of the entity path, but
rather a path under which to locate the basename of the entity
from the XML file. So specify the whole path to login.defs.d.
- The above point could be used to make the symlinks of login.defs.d
and entity path specifications in the XMLs obsolete, but I trying
not to propose possibly disrupting patches, so for the sake of
simplicity just specify `$(srcdir)` when creating the symlink.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
The intention of the code is just to not report an error message when
'typefile' doesn't exist. If we call access(2) and then fopen(2),
there's a race. It's not a huge problem, and the worst thing that can
happen is reporting an error when the file has been removed after
access(2). It's not a problem, but we can fix the race and at the same
time clarify the intention of not warning about ENOENT and also remove
one syscall. Seems like a win-win.
Suggested-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
- Every non-const pointer converts automatically to void *.
- Every pointer converts automatically to void *.
- void * converts to any other pointer.
- const void * converts to any other const pointer.
- Integer variables convert to each other.
I changed the declaration of a few variables in order to allow removing
a cast.
However, I didn't attempt to edit casts inside comparisons, since they
are very delicate. I also kept casts in variadic functions, since they
are necessary, and in allocation functions, because I have other plans
for them.
I also changed a few casts to int that are better as ptrdiff_t.
This change has triggered some warnings about const correctness issues,
which have also been fixed in this patch (see for example src/login.c).
Signed-off-by: Alejandro Colomar <alx@kernel.org>
We could use the standard (C11) _Noreturn qualifier, but it will be
deprecated in C23, and replaced by C++'s [[noreturn]], which is
compatible with the GCC attribute, so let's directly use the attribute,
and in the future we'll be able to switch to [[]].
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Recently, we removed support for 'struct utmpx'. We did it because utmp
and utmpx are identical, and while POSIX specifies utmpx (and not utmp),
GNU/Linux documentation seems to favor utmp. Also, this project
defaulted to utmp, so changing to utmpx would be more dangerous than
keeping old defaults, even if it's supposed to be the same.
Now, I just found more code that didn't make much sense: lib/utent.c
provides definitions for getutent(3) and friends in case the system
doesn't provide them, but we don't provide prototypes for those
definitions, so code using the functions would have never compiled.
Let's just remove these definitions as dead code.
Fixes: 3be7b9d75a ("Remove traces of utmpx")
Fixes: 170b76cdd1 ("Disable utmpx permanently")
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Closes#457
The existing prose was confusing, or simply wrong. Make it clear
that only the group ownership of the tty is affected, and how.
Also move the paragraph about defaults after the discussion of
acceptable TTYGROUPs, as this seems more natural.
Signed-off-by: Serge Hallyn <serge@hallyn.com>
In variadic functions we still do the cast. In POSIX, it's not
necessary, since NULL is required to be of type 'void *', and 'void *'
is guaranteed to have the same alignment and representation as 'char *'.
However, since ISO C still doesn't mandate that, and moreover they're
doing dubious stuff by adding nullptr, let's be on the cautious side.
Also, C++ requires that NULL is _not_ 'void *', but either plain 0 or
some magic stuff.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
If lines start with '\0' then it is possible to trigger out of
boundary accesses.
Check if indices are valid before accessing them.
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
If the file referenced by ENV_TZ has a zero length string, then an out
of boundary write occurs. Also the result can be wrong because it is
assumed that the file will always end with a newline.
Only override a newline character with '\0' to avoid these cases.
This cannot be considered to be security relevant because login.defs
and its contained references to system files should be trusted to begin
with.
Proof of Concept:
1. Compile shadow's su with address sanitizer and --without-libpam
2. Setup your /etc/login.defs to contain ENV_TZ=/etc/tzname
3. Prepare /etc/tzname to contain a '\0' byte at the beginning
`python -c "print('\x00')" > /etc/tzname`
4. Use su
`su -l`
You can see the following output:
`tz.c:45:8: runtime error: index 18446744073709551615 out of bounds for type 'char [8192]'`
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
We do need the unoptimized version of csrand_uniform() for high values
of `n`, since the optimized version depends on having __int128, and it's
not available on several platforms, including ARMv7, IA32, and MK68k.
This reverts commit 848f53c1d3c1362c86d3baab6906e1e4419d2634; however,
I applied some tweaks to the reverted commit.
Reported-by: Adam Sampson <ats@offog.org>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Now that we optimized csrand_uniform(), we don't need these functions.
This reverts commit 7c8fe291b1260e127c10562bfd7616961013730f.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Use a different algorithm to minimize rejection. This is essentially
the same algorithm implemented in the Linux kernel for
__get_random_u32_below(), but written in a more readable way, and
avoiding microopimizations that make it less readable.
Which (the Linux kernel implementation) is itself based on Daniel
Lemire's algorithm from "Fast Random Integer Generation in an Interval",
linked below. However, I couldn't really understand that paper very
much, so I had to reconstruct the proofs from scratch, just from what I
could understand from the Linux kernel implementation source code.
I constructed some graphical explanation of how it works, and why it
is optimal, because I needed to visualize it to understand it. It is
published in the GitHub pull request linked below.
Here goes a wordy explanation of why this algorithm based on
multiplication is better optimized than my original implementation based
on masking.
masking:
It discards the extra bits of entropy that are not necessary for
this operation. This works as if dividing the entire space of
possible csrand() values into smaller spaces of a size that is
a smaller power of 2. Each of those smaller spaces has a
rejection band, so we get as many rejection bands as spaces
there are. For smaller values of 'n', the size of each
rejection band is smaller, but having more rejection bands
compensates for this, and results in the same inefficiency as
for large values of 'n'.
multiplication:
It divides the entire space of possible random numbers in
chunks of size exactly 'n', so that there is only one rejection
band that is the remainder of `2^64 % n`. The worst case is
still similar to the masking algorithm, a rejection band that is
almost half the entire space (n = 2^63 + 1), but for lower
values of 'n', by only having one small rejection band, it is
much faster than the masking algorithm.
This algorithm, however, has one caveat: the implementation
is harder to read, since it relies on several bitwise tricky
operations to perform operations like `2^64 % n`, `mult % 2^64`,
and `mult / 2^64`. And those operations are different depending
on the number of bits of the maximum possible random number
generated by the function. This means that while this algorithm
could also be applied to get uniform random numbers in the range
[0, n-1] quickly from a function like rand(3), which only
produces 31 bits of (non-CS) random numbers, it would need to be
implemented differently. However, that's not a concern for us,
it's just a note so that nobody picks this code and expects it
to just work with rand(3) (which BTW I tried for testing it, and
got a bit confused until I realized this).
Finally, here's some light testing of this implementation, just to know
that I didn't goof it. I pasted this function into a standalone
program, and run it many times to find if it has any bias (I tested also
to see how many iterations it performs, and it's also almost always 1,
but that test is big enough to not paste it here).
int main(int argc, char *argv[])
{
printf("%lu\n", csrand_uniform(atoi(argv[1])));
}
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 1 | wc -l
341
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 1 | wc -l
339
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 1 | wc -l
338
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 2 | wc -l
336
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 2 | wc -l
328
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 2 | wc -l
335
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 0 | wc -l
332
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 0 | wc -l
331
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 0 | wc -l
327
This isn't a complete test for a cryptographically-secure random number
generator, of course, but I leave that for interested parties.
Link: <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e9a688bcb19348862afe30d7c85bc37c4c293471>
Link: <https://github.com/shadow-maint/shadow/pull/624#discussion_r1059574358>
Link: <https://arxiv.org/abs/1805.10941>
Cc: "Jason A. Donenfeld" <Jason@zx2c4.com>
Cc: Cristian Rodríguez <crrodriguez@opensuse.org>
Cc: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Cc: Björn Esser <besser82@fedoraproject.org>
Cc: Yann Droneaud <ydroneaud@opteya.com>
Cc: Joseph Myers <joseph@codesourcery.com>
Cc: Sam James <sam@gentoo.org>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
[Daniel Lemire: Added link to research paper in source code]
Cc: Daniel Lemire <daniel@lemire.me>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
It is common to use the expression 'sizeof(x) * CHAR_BIT' to mean the
width in bits of a type or object. Now that there are _WIDTH macros for
some types, indicating the number of bits that they use, it makes sense
to wrap this calculation in a macro of a similar name.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This API is similar to arc4random_uniform(3). However, for an input of
0, this function is equivalent to csrand(), while arc4random_uniform(0)
returns 0.
This function will be used to reimplement csrand_interval() as a wrapper
around this one.
The current implementation of csrand_interval() doesn't produce very good
random numbers. It has a bias. And that comes from performing some
unnecessary floating-point calculations that overcomplicate the problem.
Looping until the random number hits within bounds is unbiased, and
truncating unwanted bits makes the overhead of the loop very small.
We could reduce loop overhead even more, by keeping unused bits of the
random number, if the width of the mask is not greater than
ULONG_WIDTH/2, however, that complicates the code considerably, and I
prefer to be a bit slower but have simple code.
BTW, Björn really deserves the copyright for csrand() (previously known
as read_random_bytes()), since he rewrote it almost from scratch last
year, and I kept most of its contents. Since he didn't put himself in
the copyright back then, and BSD-3-Clause doesn't allow me to attribute
derived works, I won't add his name, but if he asks, he should be put in
the copyright too.
Cc: "Jason A. Donenfeld" <Jason@zx2c4.com>
Cc: Cristian Rodríguez <crrodriguez@opensuse.org>
Cc: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Cc: Björn Esser <besser82@fedoraproject.org>
Cc: Yann Droneaud <ydroneaud@opteya.com>
Cc: Joseph Myers <joseph@codesourcery.com>
Cc: Sam James <sam@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
These functions implement bit manipulation APIs, which will be added to
C23, so that in the far future, we will be able to replace our functions
by the standard ones, just by adding the stdc_ prefix, and including
<stdbit.h>.
However, we need to avoid UB for an input of 0, so slightly deviate from
C23, and use a different name (with _wrap) for distunguishing our API
from the standard one.
Cc: Joseph Myers <joseph@codesourcery.com>
Cc: Yann Droneaud <ydroneaud@opteya.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
arc4random(3) returns a number.
arc4random_buf(3) fills a buffer.
arc4random_uniform(3) returns a number less than a bound.
and I'd add a hypothetical one which we use:
*_interval() should return a number within the interval [min, max].
In reality, the function being called csrand() in this patch is not
really cryptographically secure, since it had a bias, but a subsequent
patch will fix that.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
We were always casting the result to u_long. Better just use that type
in the function. Since we're returning u_long, it makes sense to also
specify the input as u_long. In fact, that'll help for doing bitwise
operations inside this function.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
I have plans to split this function in smaller functions that implement
bits of this functionallity, to simplify the implementation. So, let's
use names that distinguish them.
This one produces a number within an interval, so make that clear. Also
make clear that the function produces cryptographically-secure numbers.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
strlcpy(3) might not be visible since it is declared in <bsd/string.h>.
This can lead to warnings, like:
fields.c: In function 'change_field':
fields.c:103:17: warning: implicit declaration of function 'strlcpy'; did you mean 'strncpy'? [-Wimplicit-function-declaration]
103 | strlcpy (buf, cp, maxsize);
| ^~~~~~~
| strncpy
../lib/fields.c:103:17: warning: type of 'strlcpy' does not match original declaration [-Wlto-type-mismatch]
103 | strlcpy (buf, cp, maxsize);
| ^
/usr/include/bsd/string.h:44:8: note: return value type mismatch
44 | size_t strlcpy(char *dst, const char *src, size_t siz);
| ^
/usr/include/bsd/string.h:44:8: note: type 'size_t' should match type 'int'
/usr/include/bsd/string.h:44:8: note: 'strlcpy' was previously declared here
/usr/include/bsd/string.h:44:8: note: code may be misoptimized unless '-fno-strict-aliasing' is used
Comparisons if different signedness can result in unexpected results.
Add casts to ensure operants are of the same type.
gettime.c: In function 'gettime':
gettime.c:58:26: warning: comparison of integer expressions of different signedness: 'long long unsigned int' and 'time_t' {aka 'long int'} [-Wsign-compare]
58 | } else if (epoch > fallback) {
| ^
Cast to time_t, since epoch is less than ULONG_MAX at this point.
idmapping.c: In function 'write_mapping':
idmapping.c:202:48: warning: comparison of integer expressions of different signedness: 'int' and 'long unsigned int' [-Wsign-compare]
202 | if ((written <= 0) || (written >= (bufsize - (pos - buf)))) {
| ^~
newgidmap.c: In function ‘main’:
newgidmap.c:178:40: warning: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’ [-Wsign-compare]
178 | if ((written <= 0) || (written >= sizeof(proc_dir_name))) {
| ^~
newuidmap.c: In function ‘main’:
newuidmap.c:107:40: warning: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’ [-Wsign-compare]
107 | if ((written <= 0) || (written >= sizeof(proc_dir_name))) {
| ^~
Instead of using volatile pointers to prevent the compiler from
optimizing the call away, use a memory barrier.
This requires support for embedded assembly, which should be fine after
the recent requirement bumps.
memset_s() has a different signature than memset(3) or explicit_bzero(),
thus the current code would not compile. Also memset_s()
implementations are quite rare.
Use the C23 standardized version memset_explicit(3).
Fixes: 7a799ebb ("Ensure memory cleaning")
Login timed out message prints only first few bytes when write is immediately followed by exit.
Calling exit from new handler provides enough time to display full message.
Commit 90424e7c ("Don't warn when failed to open /etc/nsswitch.conf")
removed the logging for failing to read /etc/nsswitch.conf to reduce the
noise in the case the file does not exists (e.g. musl based systems).
Reintroduce a warning if /etc/nsswitch.conf exists but we failed to read
it (e.g. permission denied).
Improves: 90424e7c ("Don't warn when failed to open /etc/nsswitch.conf")
gethostbyname(3) was removed in POSIX.1-2008. It has been obsoleted,
and replaced by getaddrinfo(3), which is superior in several ways:
- gethostbyname(3) is not reentrant. There's a GNU extension,
gethostbyname_r(3) which is reentrant, but it's not likely to be
standardized for the following reason. And we don't care too much
about this point either.
- gethostbyname(3) only supports IPv4, but getaddrinfo(3) supports both
IPv4 and IPv6 (and may support other address families in the future).
We don't care about reentrancy, so for keeping the code simple (i.e.,
not touch call site to add code to free(3) an allocated buffer), I added
a static buffer for inet_ntop(3). We could address that in the future,
but I don't think it's worth it.
BTW, we also replace inet_ntoa(3) by inet_ntop(3), as a consequence of
using getaddrinfo(3). inet_ntoa(3) is also marked as deprecated, but
that deprecation seems to have been documented only in the manual page,
and POSIX doesn't mark it as deprecated. The deprecation notice goes
back to when the inet_ntop(3) manual page was added by Sam Varshavchik
to the Linux man-pages in version 1.30 (year 2000).
So, this, apart from updating the code to POSIX.1-2008, is also adding
support for IPv6 :) Although, probably many other parts of the code are
written for IPv4 only, so I wouldn't yet claim support for it.
A few notes:
- I didn't check the return value of inet_ntop(3), since it can't fail
for the given input:
- EAFNOSUPPORT: We only call it with AF_INET and AF_INET6.
- ENOSPC: We calculate the size of the buffer to be wide enough:
MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) so it always fits.
Cc: Dave Hagewood <admin@arrowweb.com>
Cc: Sam Varshavchik
Cc: Jakub Jelinek <jakub@redhat.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Systems can suffer power interruptions whilst .lock files are in /etc,
preventing scripts and other automation tools from updating shadow's
files which persist across boots.
This commit replaces that mechanism with file locking to avoid problems
of power interruption/crashing.
Minor tweak to groupmems man page, requested by 'xx' on IRC.
Signed-off-by: ed neville <ed@s5h.net>
When the caller may not change the room number, work phone, or
home number, then rather than prompting for the new one it will
print the existing one. But due to a typo it printed the full name
in place of each of those.
Fix the fields being printed.
Signed-off-by: Serge Hallyn <serge@hallyn.com>
- Since strncpy(3) is not designed to write strings, but rather
(null-padded) character sequences (a.k.a. unterminated strings), we
had to manually append a '\0'. strlcpy(3) creates strings, so they
are always terminated. This removes dependencies between lines, and
also removes chances of accidents.
- Repurposing strncpy(3) to create strings requires calculating the
location of the terminating null byte, which involves a '-1'
calculation. This is a source of off-by-one bugs. The new code has
no '-1' calculations, so there's almost-zero chance of these bugs.
- strlcpy(3) doesn't padd with null bytes. Padding is relevant when
writing fixed-width buffers to binary files, when interfacing certain
APIs (I believe utmpx requires null padding at lease in some
systems), or when sending them to other processes or through the
network. This is not the case, so padding is effectively ignored.
- strlcpy(3) requires that the input string is really a string;
otherwise it crashes (SIGSEGV). Let's check if the input strings are
really strings:
- lib/fields.c:
- 'cp' was assigned from 'newft', and 'newft' comes from fgets(3).
- lib/gshadow.c:
- strlen(string) is calculated a few lines above.
- libmisc/console.c:
- 'cons' comes from getdef_str, which is a bit cryptic, but seems
to generate strings, I guess.1
- libmisc/date_to_str.c:
- It receives a string literal. :)
- libmisc/utmp.c:
- 'tname' comes from ttyname(3), which returns a string.
- src/su.c:
- 'tmp_name' has been passed to strcmp(3) a few lines above.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Since the project is supposed to be POSIX.1-2001 compliant it doesn't
make sense to have that added conditionally.
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
It is Undefined Behavior to declare errno (see NOTES in its manual page).
Instead of using the errno dummy declaration, use one that doesn't need
a comment.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Previous commits, to keep readability of the diffs, left the code that
was previously wrapped by preprocessor coditionals untouched. Apply
some minor cosmetic changes to merge it in the surrounding code.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
- USER_NAME_MAX_LENGTH was being calculated in terms of utmpx. Do it
in terms of utmp.
- Remove utmpx support from the whishlist.
- Remove unused tests about utmpx members.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
On Linux, utmpx and utmp are identical. However, documentation (manual
pages) covers utmp, and just says about utmpx that it's identical to
utmp. It seems that it's preferred to use utmp, at least by reading the
manual pages.
Moreover, we were defaulting to utmp (utmpx had to be explicitly enabled
at configuration time). So, it seems safer to just make it permanent,
which should not affect default builds.
Signed-off-by: Alejandro Colomar <alx@kernel.org>
We already made that assumption in commit b47aa1e9aa. While the
header is not required by POSIX (it is an XSI extension), it is defined
in systems that are of interest to this project (GNU/Linux).
Fixes: b47aa1e9aa ("Assume <utmpx.h> exists")
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
When useradd sends its ADD_USER event, it is filling in the id field. This is not yet written to disk. When auditd sees the event and the log format is enriched, auditd tries to lookup the user name but it does not exist. This causes the event to never be resolvable since ausearch relies on the lookup information attached by auditd.
The fix is to not send the id information for any event until after close_files() is called. Just the acct field is all that is
Patch by Steve Grubb (afaik).
Reported at https://bugzilla.redhat.com/show_bug.cgi?id=1713432
The OSes that are referred to by these comments, are extinct, but
their comments survived, fossilized in amber.
Reported-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
In a previous commit, we made USE_TERMIOS unconditionally defined.
Let's just remove it, and remove the condition everywhere.
Reported-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
All of the macros we're using are required by POSIX.1-2001.
Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
The function is obsolete. It is recommended to use getrlimit(2) instead
(see the manual page for ulimit(3) or the POSIX manual for it). Since
getrlimit(2) is required by POSIX.1-2001, we can rely on it.
Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Clang doesn't implement this attribute and reports an error. Work
around it by hiding it in a macro that will be empty in clang.
Reported-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
There are several issues with getpass(3).
Many implementations of it share the same issues that the infamous
gets(3). In glibc it's not so terrible, since it's a wrapper
around getline(3). But it still has an important bug:
If the password is long enough, getline(3) will realloc(3) memory,
and prefixes of the password will be laying around in some
deallocated memory.
See the getpass(3) manual page for more details, and especially
the commit that marked it as deprecated, which links to a long
discussion in the linux-man@ mailing list.
So, readpassphrase(3bsd) is preferrable, which is provided by
libbsd on GNU systems. However, using readpassphrase(3) directly
is a bit verbose, so we can write our own wrapper with a simpler
interface similar to that of getpass(3).
One of the benefits of writing our own interface around
readpassphrase(3) is that we can hide there any checks that should
be done always and which would be error-prone to repeat every
time. For example, check that there was no truncation in the
password.
Also, use malloc(3) to get the buffer, instead of using a global
buffer. We're not using a multithreaded program (and it wouldn't
make sense to do so), but it's nice to know that the visibility of
our passwords is as limited as possible.
erase_pass() is a clean-up function that handles all clean-up
correctly, including zeroing the entire buffer, and then
free(3)ing the memory. By using [[gnu::malloc(erase_pass)]], we
make sure that we don't leak the buffers in any case, since the
compiler will be able to enforce clean up.
Link: <https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit?id=7ca189099d73bde954eed2d7fc21732bcc8ddc6b>
Reported-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
The missing #include <gshadow.h> causes the configure check to fail
spuriously, resulting in HAVE_SHADOWGRP not being defined even
on systems that actually have sgetsgent (such as current glibc).
Allow supplementary groups to be set via the /etc/default/useradd config
file. Allowing an administrator to set additonal groups via the GROUPS
configurable and control the default behaviour of useradd.
This program has 10 calls to gets(3) according to grep(1). That
makes it a very unsafe program which should not be used at all.
Let's kill the program already.
See what gets(3) has to say:
SYNOPSIS
#include <stdio.h>
[[deprecated]] char *gets(char *s);
DESCRIPTION
Never use this function.
...
BUGS
Never use gets(). Because it is impossible to tell with‐
out knowing the data in advance how many characters
gets() will read, and because gets() will continue to
store characters past the end of the buffer, it is ex‐
tremely dangerous to use. It has been used to break com‐
puter security. Use fgets() instead.
For more information, see CWE‐242 (aka "Use of Inherently
Dangerous Function") at http://cwe.mitre.org/data/defini‐
tions/242.html
Acked-by: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
The minimum id allocation for system accounts shouldn't be 0 as this is
reserved for root.
Signed-off-by: Tomáš Mráz <tm@t8m.info>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Report error if usermod asked for moving homedir and it does not exist.
Signed-off-by: Tomáš Mráz <tm@t8m.info>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Introduced by c6c8130db4
After removing snprintf, the format string should get unescaped once.
Fixes#564
Reporter and patch author: DerMouse (github.com/DerMouse)
glibc, musl, FreeBSD, and OpenBSD define the MAX() and MIN()
macros in <sys/param.h> with the same definition that we use.
Let's not redefine it here and use the system one, as it's
effectively the same as we define (modulo whitespace).
See:
shadow (previously):
alx@asus5775:~/src/shadow/shadow$ grepc -ktm MAX
./lib/defines.h:318:#define MAX(x,y) (((x) > (y)) ? (x) : (y))
glibc:
alx@asus5775:~/src/gnu/glibc$ grepc -ktm -x 'sys/param.h$' MAX
./misc/sys/param.h:103:#define MAX(a,b) (((a)>(b))?(a):(b))
musl:
alx@asus5775:~/src/musl/musl$ grepc -ktm -x 'sys/param.h$' MAX
./include/sys/param.h:19:#define MAX(a,b) (((a)>(b))?(a):(b))
OpenBSD:
alx@asus5775:~/src/bsd/openbsd/src$ grepc -ktm -x 'sys/param.h$' MAX
./sys/sys/param.h:193:#define MAX(a,b) (((a)>(b))?(a):(b))
FreeBSD:
alx@asus5775:~/src/bsd/freebsd/freebsd-src$ grepc -ktm -x 'sys/param.h$' MAX
./sys/sys/param.h:333:#define MAX(a,b) (((a)>(b))?(a):(b))
Signed-off-by: Alejandro Colomar <alx@kernel.org>
free(3) accepts NULL, since the oldest ISO C. I guess the
paranoid code was taking care of prehistoric implementations of
free(3). I've never known of an implementation that doesn't
conform to this, so let's simplify this.
Remove xfree(3), which was effectively an equivalent of free(3).
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This tweaks the database locking logic so that failures in the
link-checking paths are more detailed.
The rationale for this is that I've experienced a non-deterministic
bug which seems to be coming from this logic, and I'd like to get
more details about the actual failing condition.
The setuid, setgid, and sticky bits are not copied during copy_tree.
Also start with very restrictive permissions before setting ownerships.
This prevents situations in which users in a group with less permissions
than others could win a race in opening the file before permissions are
removed again.
Proof of concept:
$ echo $HOME
/home/uwu
$ install -o uwu -g fandom -m 604 /dev/null /home/uwu/owo
$ ls -l /home/uwu/owo
-rw----r-- 1 uwu fandom 0 Sep 4 00:00 /home/uwu/owo
If /tmp is on another filesystem, then "usermod -md /tmp/uwu uwu" leads
to this temporary situation:
$ ls -l /tmp/uwu/owo
-rw----r-- 1 root root 0 Sep 4 00:00 /tmp/uwu/owo
This means that between openat and chownat_if_needed a user of group
fandom could open /tmp/uwu/owo and read the content when it is finally
written into the file.
Fixes regression introduced in faeab50e71.
If a directory contains fifos, then openat blocks until the other side
of the fifo is connected as well.
This means that users can prevent "usermod -m" from completing if their
home directories contain at least one fifo.
The groupadd from shadow does not allow upper case group names, the
same is true for the upstream shadow. But distributions like
Debian/Ubuntu/CentOS has their own way to cope with this problem,
this patch is picked up from Fedora [1] to relax the usernames
restrictions to allow the upper case group names, and the relaxation is
POSIX compliant because POSIX indicate that usernames are composed of
characters from the portable filename character set [A-Za-z0-9._-].
[1] https://src.fedoraproject.org/rpms/shadow-utils/blob/rawhide/f/shadow-4.8-goodname.patch
Signed-off-by: Alexander Kanavin <alex@linutronix.de>
useradd does not create the files if they don't exist, but if they exist
it will reset user data even if the data did not exist before creating
a hole and an explicitly zero'd data point resulting (especially for
high UIDs) in a lot of zeros ending up in containers and tarballs.
As rbalint points out, this was an exported fn. It also is
the only way for a libsubid user to do what it does, so let's
not drop it.
This reverts commit 477c8e6f42.
Use *at() functions to pin the directory operating in to avoid being
redirected by unprivileged users replacing parts of paths by symlinks to
privileged files.
Introduce a path_info struct with the full path and dirfd and name
information for *at() functions, since the full path is needed for link
resolution, SELinux label lookup and ACL attributes.
Use *at() functions to pin the directory operating in to avoid being
redirected by unprivileged users replacing parts of paths by symlinks to
privileged files.
Use *at() functions to pin the directory operating in to avoid being
redirected by unprivileged users replacing parts of paths by symlinks to
privileged files.
Allow the compiler to verify the format string against the supplied
arguments.
chage.c:239:51: warning: format not a string literal, format string not checked [-Wformat-nonliteral]
239 | (void) strftime (buf, sizeof buf, format, tp);
| ^~~~~~
salt.c:102:22: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
102 | static /*@observer@*/const unsigned long SHA_get_salt_rounds (/*@null@*/int *prefered_rounds);
| ^~~~~
salt.c:110:22: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
110 | static /*@observer@*/const unsigned long YESCRYPT_get_salt_cost (/*@null@*/int *prefered_cost);
| ^~~~~
subordinateio.c:160:8: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
160 | static const bool range_exists(struct commonio_db *db, const char *owner)
| ^~~~~
Compilers are free to ignore the indented hint and modern optimizations
should create good code by themself.
(As such it is for example deprecated in C++17.)
Version 1.19.1 was released in June 2014.
configure.ac:697: warning: AM_PROG_MKDIR_P: this macro is deprecated, and will soon be removed.
configure.ac:697: You should use the Autoconf-provided 'AC_PROG_MKDIR_P' macro instead,
configure.ac:697: and use '$(MKDIR_P)' instead of '$(mkdir_p)'in your Makefile.am files.
./lib/autoconf/general.m4:2434: AC_DIAGNOSE is expanded from...
aclocal.m4:780: AM_PROG_MKDIR_P is expanded from...
m4/po.m4:23: AM_PO_SUBDIRS is expanded from...
m4/gettext.m4:57: AM_GNU_GETTEXT is expanded from...
configure.ac:697: the top level
configure.ac:697: warning: The macro `AC_TRY_LINK' is obsolete.
configure.ac:697: You should run autoupdate.
./lib/autoconf/general.m4:2920: AC_TRY_LINK is expanded from...
lib/m4sugar/m4sh.m4:692: _AS_IF_ELSE is expanded from...
lib/m4sugar/m4sh.m4:699: AS_IF is expanded from...
./lib/autoconf/general.m4:2249: AC_CACHE_VAL is expanded from...
./lib/autoconf/general.m4:2270: AC_CACHE_CHECK is expanded from...
m4/gettext.m4:365: gt_INTL_MACOSX is expanded from...
m4/gettext.m4:57: AM_GNU_GETTEXT is expanded from...
configure.ac:697: the top level
configure.ac:697: warning: The macro `AC_TRY_LINK' is obsolete.
configure.ac:697: You should run autoupdate.
./lib/autoconf/general.m4:2920: AC_TRY_LINK is expanded from...
lib/m4sugar/m4sh.m4:692: _AS_IF_ELSE is expanded from...
lib/m4sugar/m4sh.m4:699: AS_IF is expanded from...
./lib/autoconf/general.m4:2249: AC_CACHE_VAL is expanded from...
./lib/autoconf/general.m4:2270: AC_CACHE_CHECK is expanded from...
m4/gettext.m4:57: AM_GNU_GETTEXT is expanded from...
configure.ac:697: the top level
configure.ac:697: warning: The macro `AC_TRY_LINK' is obsolete.
configure.ac:697: You should run autoupdate.
./lib/autoconf/general.m4:2920: AC_TRY_LINK is expanded from...
lib/m4sugar/m4sh.m4:692: _AS_IF_ELSE is expanded from...
lib/m4sugar/m4sh.m4:699: AS_IF is expanded from...
./lib/autoconf/general.m4:2249: AC_CACHE_VAL is expanded from...
./lib/autoconf/general.m4:2270: AC_CACHE_CHECK is expanded from...
m4/iconv.m4:20: AM_ICONV_LINK is expanded from...
m4/gettext.m4:57: AM_GNU_GETTEXT is expanded from...
configure.ac:697: the top level
See https://www.gnu.org/software/libtool/manual/html_node/LT_005fINIT.html
configure.ac:25: warning: The macro `AM_ENABLE_STATIC' is obsolete.
configure.ac:25: You should run autoupdate.
m4/ltoptions.m4:259: AM_ENABLE_STATIC is expanded from...
configure.ac:25: the top level
configure.ac:26: warning: The macro `AM_ENABLE_SHARED' is obsolete.
configure.ac:26: You should run autoupdate.
m4/ltoptions.m4:205: AM_ENABLE_SHARED is expanded from...
configure.ac:26: the top level
It was hard to extend the option specification string passed to
getopt_long as the third argument.
The origian code had a branch with WITH_SELINUX ifdef condition. If
one wants to add one more option char with another ifdef condition
like ENABLE_SUBIDS to the spec, the one must enumerate the specs for
all combinations of the conditions:
* WITH_SELINUX && ENABLE_SUBIDS
* WITH_SELINUX && !ENABLE_SUBIDS
* !WITH_SELINUX && ENABLE_SUBIDS
* !WITH_SELINUX && !ENABLE_SUBIDS
With this change, you can append an option char to the spec.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
On systems with Linux kernel < 3.17, getentropy() and getrandom() may
exist but return ENOSYS. Use /dev/urandom as a fallback to avoid a hard
requirement on Linux kernel version.
Fixes#512.
Signed-off-by: Xi Ruoyao <xry111@xry111.site>
In order to remove some of the FIXMEs it was necessary to change the
code and call getulong() instead of getlong().
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
No need to redeclare a variable with the same name and type. Just keep
the one with the biggest scope.
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
"egrep" is an obsolete alias for grep -E and newer greps will warn on usage
of egrep, so let's just swap it out.
Signed-off-by: Sam James <sam@gentoo.org>
Git wants to ensure that you do not read .git owned by other users.
But we fetch+build as 'build' user, and run tests as root user. Those
tests calculate git topdir using git rev-parse --show-toplevel, which
git now fails.
Setting safe.directory, seems wrong. Let's just use bash to figure
out the top dir.
Generating salt value depends on /dev/urandom. But after the
function process_root_flag changed the root directory, It does
not exist.
So, generate salt value before changeing the directory.
Fixes: #514
The markdown output for the maintainers, authors and contributors list
was wrapped in a single line and it was difficult to read. I've created
an unordered list to get a better output. On top of that I've also added
myself as a maintainer.
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
This used to be 16 for historical reasons but these days basically every
distro configures --with-group-name-max-length=32 to make it match the
max Linux username length, make it default.
Signed-off-by: Jami Kettunen <jami.kettunen@protonmail.com>
C++ requires extern "C" linkage specification to call functions from a C
library. Enclose the function definitions in subid.h in an extern "C"
block if compiling in C++ mode to achieve this.
Signed-off-by: Alois Wohlschlager <alois1@gmx-topmail.de>
useradd warns that a system user ID less than SYS_UID_MIN is outside the
expected range, even though that ID has been specifically selected with
the "-u" option.
In my opinion all the user ID's below SYS_UID_MAX are for the system,
thus I change the condition to take that into account.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2004911
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
If /etc/nsswitch.conf doesn't exist podman crashes because shadow_logfd
is NULL. In order to avoid that load the log file descriptor with the
log_get_logfd() helper function.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2038811
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
C89 and POSIX.1-2001 define signal(2) as returning a pointer to a
function returning 'void'. K&R C signal(2) signature is obsolete.
Use 'void' directly.
Also, instead of writing the function pointer type explicitly, use
POSIX's 'sighandler_t'.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Systems on which <sys/time.h> conflicted with <time.h> are obsolete.
This macro has been marked as obsolete by autoconf documentation.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
All current compilers support C89's 'const' keyword.
Autoconf declares this macro as obsolescent.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
As autoconf documentation says, this macro is obsolescent, as no
current systems have the bug in S_ISDIR, S_ISREG, etc..
The affected systems were Tektronix UTekV, Amdahl UTS, and
Motorola System V/88.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
INTERACTIVE Systems Corporation Unix is no longer sold, and Sun
said (long ago) that it would drop support for it on 2006-07-23.
So this macro has been obsolete for more than a decade.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
'mode_t' is defined by POSIX.1-2001 in <sys/types.h>.
It's unlikely to be missing.
See mode_t(3).
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
'pid_t' is defined by POSIX.1-2001 in <sys/types.h>.
It's unlikely to be missing.
See pid_t(3).
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
'off_t' is defined by POSIX.1-2001 in <sys/types.h>.
It's unlikely to be missing.
See off_t(3).
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
'uid_t' is defined by POSIX.1-2001 in <sys/types.h>.
It's unlikely to be missing.
See uid_t(3).
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
The macro HAVE_RUSEROK is not being used anywhere.
As the Linux manual page says, ruserok(3) is present on the BDSs, Solaris, and many other systems. This function appeared in 4.2BSD. So we probably can rely on its existence.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
The macro HAVE_GETADDRINFO is not being used anywhere.
BTW, the function is defined by POSIX.1-2001 and RFC 2553, so it's likely that it is always available.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
The macro HAVE_SIGACTION is not being used anywhere.
BTW, the function is defined by SVr4 and POSIX.1-2001, so it's likely that it is always available.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
The macro HAVE_GETTIMEOFDAY is not being used anywhere.
BTW, the function is defined by SVr4, 4.3BSD, and POSIX.1-2001, so
it's likely that it is always available.
POSIX.1-2008 marks it as obsolete, but only because
clock_gettime(2) provides more precission. Since gettimeofday(3)
is in use by many big projects, and it has no obvious dangers,
it's likely that it will continue to exist even if it's outside of
the POSIX standard.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
The macro HAVE_GETHOSTNAME is not being used anywhere.
BTW, the function is defined by SVr4, 4.4BSD, and POSIX.1-2001, so
it's likely that it is always available.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
The only place where the check was used was removed in 4e1afcd66.
BTW, it was unnecessary, since strchr(3) is defined by:
POSIX.1-2001, C89, SVr4, and 4.3BSD. Enough to rely on it.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
GNU autoconf documentation marks this macro as obsolescent, as
current systems are compatible with POSIX.
Simplify code to unconditionally include <sys/wait.h>, and don't
redefine WIFEXITSTATUS() and WIFEXITED(), since they are mandated
by POSIX.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
POSIX.1-2001 defines 'struct dirent' in <dirent.h>. It replaces
the old 'struct direct' found in BSDs. All of the systems that I
checked (including FreeBSD, NetBSD, and OpenBSD), now provide
<dirent.h> with 'struct dirent', as mandated by POSIX.
Since autoconf first checks <dirent.h> and only if it's missing it
checks other header files, it's clear that it will always find
<dirent.h>, so let's simplify.
GNU autoconf documentation declares this macro as obsolescent, and
acknowledges that all current systems with directory libraries
have <dirent.h>:
<https://www.gnu.org/software/autoconf/manual/autoconf-2.70/html_node/Particular-Headers.html>
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Compilers are allowed to and do optimize memset(3) calls away for
pointers not accessed in the future. Since the memzero wrappers purpose
is exactly to unconditionally override memory (e.g. for stored
passwords) do not implement via regular memset(3), but via either
memset_s(3), explicit_bzero(3) or a hand written implementation using
volatile pointers.
See https://wiki.sei.cmu.edu/confluence/display/c/MSC06-C.+Beware+of+compiler+optimizations
run_part() and run_parts() do not modify their directory, name and
action arguments.
Also include the header in the implementation to provide the prototypes.
useradd.c:2495:59: warning: cast discards ‘const’ qualifier from pointer target type [-Wcast-qual]
2495 | if (run_parts ("/etc/shadow-maint/useradd-pre.d", (char*)user_name,
| ^
useradd.c:2495:24: warning: passing argument 1 of ‘run_parts’ discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
2495 | if (run_parts ("/etc/shadow-maint/useradd-pre.d", (char*)user_name,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from useradd.c:45:
../lib/run_part.h:2:22: note: expected ‘char *’ but argument is of type ‘const char *’
2 | int run_parts (char *directory, char *name, char *action);
| ~~~~~~^~~~~~~~~
useradd.c:2496:25: warning: passing argument 3 of ‘run_parts’ discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
2496 | "useradd")) {
| ^~~~~~~~~
nss_init() does not modify its path argument, thus declare it const.
Also drop superfluous prototype.
nss.c:54:31: warning: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
54 | nsswitch_path = NSSWITCH;
| ^
Function declarations with no argument declare functions taking an
arbitrary number of arguments. Use the special type void to declare
functions taking no argument.
C89 defined isdigit as a function that tests for any decimal-digit
character, defining the decimal digits as 0 1 2 3 4 5 6 7 8 9.
I don't own a copy of C89 to check, but check in C17:
7.4.1.5
5.2.1
More specifically:
> In both the source and execution basic character sets, the value
> of each character after 0 in the above list of decimal digits
> shall be one greater than the value of the previous.
And since in ascii(7), the character after '9' is ':', it's highly
unlikely that any implementation will ever accept any
_decimal digit_ other than 0..9.
POSIX simply defers to the ISO C standard.
This is exactly what we wanted from ISDIGIT(c), so just use it.
Non-standard implementations might have been slower or considered
other characters as digits in the past, but let's assume
implementations available today conform to ISO C89.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
It wasn't being used at all. Let's remove it.
Use isdigit(3) directly in comments that referenced it.
Also, in those comments, remove an outdated reference to the fact
that ISDIGIT_LOCALE(c) might evaluate its argument more than once,
which could be true a few commits ago, until
IN_CTYPE_DEFINITION(c) was removed. Previously, the definition
for ISDIGIT_LOCALE(c) was:
#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
# define IN_CTYPE_DOMAIN(c) 1
#else
# define IN_CTYPE_DOMAIN(c) isascii(c)
#endif
#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
Which could evaluate 'c' twice on pre-C89 systems (which I hope
don't exist nowadays).
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Due to the recent removal of IN_CTYPE_DOMAIN(), the uppercase
macros that wrapped these standard calls are now defined to be
equivalent. Therefore, there's no need for the wrappers, and it
is much more readable to use the standard calls directly.
However, hold on with ISDIGIT*(), since it's not so obvious what
to do with it.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
The recent removal of STDC_HEADERS made IN_CTYPE_DOMAIN be defined
to 1 unconditionally. Remove the now unnecessary definition, and
propagate its truthness to expressions where it was used.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
We're in 2021. C89 is everywhere; in fact, there are many other
assumptions in the code that wouldn't probably hold on
pre-standard C environments. Let's simplify and assume that C89
is available.
The specific assumptions are that:
- <string.h>, and <stdlib.h> are available
- strchr(3), strrchr(3), and strtok(3) are available
- isalpha(3), isspace(3), isdigit(3), and isupper(3) are available
I think we can safely assume we have all of those.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
memset(3) has been in standard C since C89. It is also in
POSIX.1-2001, in SVr4, and in 4.3BSD (see memset(3) and memset(3p)).
We can assume that this function is always available.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
memcpy(3) has been in standard C since C89. It is also in
POSIX.1-2001, in SVr4, and in 4.3BSD (see memcpy(3) and memcpy(3p)).
We can assume that this function is always available.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
getgroups(2) has been in POSIX since POSIX.1-2001. It is also in
in SVr4 and in 4.3BSD (see getgroups(2) and getgroups(3p)).
We can assume that this function is always available.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
strftime(3) has been in standard C since C89. It is also in
POSIX.1-2001, and in SVr4 (see strftime(3) and strftime(3p)).
We can assume that this function is always available.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
sleep 2s before running newxidmap - it seems we were sometimes
racing, causing newxidmap to fail.
Make sure to remove /tmp/test-xidmap, for some reason they
were sometimes still there, causing test to fail.
Fix some irregular tabbing.
Signed-off-by: Serge Hallyn <serge@hallyn.com>
PARAMETERS:
According to the C2x charter, I reordered the parameters 'size'
and 'buf' from previously existing date_to_str() definitions.
C2x charter:
> 15. Application Programming Interfaces (APIs) should be
> self-documenting when possible. In particular, the order of
> parameters in function declarations should be arranged such that
> the size of an array appears before the array. The purpose is to
> allow Variable-Length Array (VLA) notation to be used. This not
> only makes the code's purpose clearer to human readers, but also
> makes static analysis easier. Any new APIs added to the Standard
> should take this into consideration.
I used 'long' for the date parameter, as some uses of the function
need to pass a negative value meaning "never".
FUNCTION BODY:
I didn't check '#ifdef HAVE_STRFTIME', which old definitions did,
since strftime(3) is guaranteed by the C89 standard, and all of
the conversion specifiers that we use are also specified by that
standard, so we don't need any extensions at all.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
The build was failing with duplicate symbol errors with -fno-common.
This is the default in GCC 10 and later, and explicitly enabled in some
distributions to catch problems like this. There were two causes:
- Prog and shadow_logfd were defined in a header file that was included
in multiple other files. Fix this by defining them once in
shadowlog.c, and having extern declarations in the header.
- Most of the tools (except id/nologin) also define a Prog variable,
which is not intended to alias the one in the library. Fix
this by renaming Prog in the library to shadow_progname, which also
matches the new accessor functions for it.
We were overriding this when --enable-shared was passed. We can actually
just dump the conditional logic as libtool will do the right thing for
us here anyway.
Without this patch, libsubid is installed as .0.
Signed-off-by: Sam James <sam@gentoo.org>
The SIGCHLD handler could have been ignored by parent process.
Make sure that we have default handling activated.
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
This conforms to PAM documentation and it is needed to support
ambient capabilities with PAM + libcap-2.58+.
Signed-off-by: Björn Fischer <bf@CeBiTec.Uni-Bielefeld.DE>
Rename libsubid symbols to all be prefixed with subid_.
Don't export anything but the subid_*.
Closes#443
Signed-off-by: Serge Hallyn <serge@hallyn.com>
* Change to markdown format
* Include an introduction
* Remove the commit mailing list from the contacts
* Add the IRC channel to the contacts
* Move 'S/Key' section to doc/README.skey
* Move authors and maintainers to AUTHORS.md
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Add an additional NULL check condition in spw_free() and pw_free() to
avoid freeing an already empty pointer.
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Rename list_subid_ranges to getsubids to provide a system binary to
check the sub*ids of a user. The intention is to provide this binary
with any distribution that includes the subid feature, so that system
administrators can check the subid ranges of a given user.
Finally, add a man page to explain the behaviour of getsubids.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1980780
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Always set SIGCHLD handler to default, even if the caller of vipw has
set SIGCHLD to ignore. If SIGCHLD is ignored no zombie processes would
be created, which in turn could mean that kill is called with an already
recycled pid.
Proof of Concept:
1. Compile nochld:
--
#include <signal.h>
#include <unistd.h>
int main(void) {
char *argv[] = { "vipw", NULL };
signal(SIGCHLD, SIG_IGN);
execvp("vipw", argv);
return 1;
}
--
2. Run nochld
3. Suspend child vi, which suspends vipw too:
`kill -STOP childpid`
4. Kill vi:
`kill -9 childpid`
5. You can see with ps that childpid is no zombie but disappeared
6. Bring vipw back into foreground
`fg`
The kill call sends SIGCONT to "childpid" which in turn could have been
already recycled for another process.
This is definitely not a vulnerability. It would take super user
operations, at which point an attacker would have already elevated
permissions.
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Change SELinux labels for files copied from the skeleton directory to
the home directory.
This could cause gnome's graphical user adding to fail without copying
the full skeleton files.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2022658
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
When using groupdel with a prefix, groupdel will attempt to read a
passwd file to look for any user in the group. When the file does not
exist it cores with segmentation fault.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1986111
If a line in hushlogins file, e.g. /etc/hushlogins, starts with
'\0', then current code performs an out of boundary write.
If the line lacks a newline at the end, then another character is
overridden.
With strcspn both cases are solved.
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
During shadowtcb_move() the directory is temporarily changed to be
owned by root:root with permissions 0700. After the change is done,
the ownership and permissions were supposed to be restored. The
call for chown() was there, but the chmod() call was missing. This
resulted in the broken TCB functionality. The added chmod() fixes
the issue.
Close the selabel handle to update the file_context. This means that the
file_context will be remmaped and used by selabel_lookup() to return
the appropriate context to label the home folder.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1993081
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Create the home and mail folders after the SELinux user has been set for
the added user. This will allow the folders to be created with the
SELinux user label.
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
The buggy code was introduced nearly 5 years ago at the
commit 08fd4b69e8. The
desired behavior is that SIGKILL will be sent to the
child if it does not exit within 2 seconds after it
receives SIGTERM. However, SIGALRM is masked while
waiting for the child so it cannot wake the program
up after 2 seconds to send SIGKILL.
An example shows the buggy behavior, which exists in
Ubuntu 18.04 LTS (with login 1:4.5-1ubuntu2).
```bash
user1@localhost:~$ su user2 -c '
_term() {
echo SIGTERM received
}
trap _term TERM
while true; do
sleep 1
echo still alive
done'
Password:
still alive
Session terminated, terminating shell...Terminated
SIGTERM received
still alive
still alive
still alive
still alive
```
(SIGTERM is sent in another user1's terminal by
executing `killall su`.)
Here is the desired behavior, which shows what the
commit fixes.
```bash
user1@localhost:~$ su user2 -c '
_term() {
echo SIGTERM received
}
trap _term TERM
while true; do
sleep 1
echo still alive
done'
Password:
still alive
Session terminated, terminating shell...Terminated
SIGTERM received
still alive
still alive
...killed.
user1@localhost:~$ echo $?
255
```
In some circumstances I want the default behaviour of useradd to
not add user entries to the lastlog and faillog databases. Allowing
this options behaviour to be controlled by the config file
/etc/default/useradd.
`sgent` is only initialized in `get_group()` if `is_shadowgrp` is true.
So we should also only attempt to free it if this is actually the case.
Can otherwise lead to:
```
free() double free detected in tcache 2 (gpasswd)
```
The GitHub and Debian permanently moved to HTTPS URLs and redirect
there. The Gentoo URL does not redirect to HTTPS, but still use it to
address certain kinds of attacks. Lastly, the NetBSD URL is only
available using HTTP.
subuid_count won't get used by usr_update(), but since we're passing it
as an argument we have to make sure it's always defined. So just define
it as pre-set to 0.
Closes#402
Signed-off-by: Serge Hallyn <serge@hallyn.com>
xml2po is deprecated. We've previously replaced xml2po with
itstool in man/generate_translations.mak, but there was still
an instance of it that only is exercised for 'make dist'.
Update that one. Now 'make dist' succeeds on a ubuntu focal
or newer host where xml2po is not available.
Signed-off-by: Serge Hallyn <serge@hallyn.com>
If SHA_CRYPT_MIN_ROUNDS and SHA_CRYPT_MAX_ROUNDS are both unspecified,
use SHA_ROUNDS_DEFAULT.
Previously, the code fell through, calling shadow_random(-1, -1). This
ultimately set rounds = (unsigned long) -1, which ends up being a very
large number! This then got capped to SHA_ROUNDS_MAX later in the
function.
The new behavior matches BCRYPT_get_salt_rounds().
Bug: https://bugs.gentoo.org/808195
Fixes: https://github.com/shadow-maint/shadow/issues/393
useradd generates an empty subid range when adding a new user. This is
caused because there are two variables, one local and the other one
global, that have a very similar name and they are used indistinctly in
the code. The local variable loads the SUB_*ID_COUNT configuration from
the login.defs file, while the global variable, which holds a value of
0, is used to generate the subid range. Causing the empty subid range
problem.
I've merged the two variables in the local one and removed the global
variable. I prefer to do it this way to reduce the scope of it but I'm
open to doing it the other way round.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1990653
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
When the -S and -a options are used for passwd to list the status
of all passwords, there is a chance the pw_passwd field of struct
passwd will be NULL. This can be due to 'files compat' being set
for passwd in /etc/nsswitch.conf and the usage of some features
not available in the 'files' mode (e.g. a plus sign at the start
of a line).
Example:
germ161:~ # grep passwd /etc/nsswitch.conf
passwd: files compat
germ161:~ # rpm -qa shadow
shadow-4.2.1-34.20.x86_64
germ161:~ # grep passwd /etc/nsswitch.conf
passwd: files compat
germ161:~ # grep + /etc/passwd
+@nisgroup
germ161:~ # passwd -S -a > /dev/null
Segmentation fault (core dumped)
With this commit:
germ161:~ # passwd -S -a > /dev/null
passwd: malformed password data obtained for user +@nisgroup
The only way of removing a group from the supplementary list is to use
-G option, and list all groups that the user is a member of except for
the one that wants to be removed. The problem lies when there's a user
that contains both local and remote groups, and the group to be removed
is a local one. As we need to include the remote group with -G option
the command will fail.
This reverts commit 140510de9d. This way,
it would be possible to remove the remote groups from the supplementary
list.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1967641
Resolves: https://github.com/shadow-maint/shadow/issues/338
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
new*idmap has a dependency with libeconf since commit
c464ec5570. I'm just adding it to the
Makefile to be able to compile in distributions that include libeconf.
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Since bbf4b79, we stopped shipping /etc/default/useradd, and therefore
install of shadow does not auto-create /etc/default. So when useradd
tries to save a new default, it needs to create the directory.
Closes#390.
Signed-off-by: Serge Hallyn <serge@hallyn.com>
libsubid's Makefile.am was always setting enable-shared in its LDFLAGS.
Do that only if not building static.
Closes#387
Signed-off-by: Serge Hallyn <shallyn@cisco.com>
There's a better way to do this, and I hope to clean that up,
but this fixes out of tree builds for me right now.
Closes#386
Signed-off-by: Serge Hallyn <serge@hallyn.com>
The useradd program should be consistent with userdel and usermod and use the
MAIL_SPOOL_DIR variable as the default spool, if it is defined. Otherwise,
don't create a new mailbox, because it won't be cleaned up by userdel when run
with the -r flag.
2020-03-11 20:00:09 +00:00
1100 changed files with 39104 additions and 28288 deletions
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.