Commit Graph

225 Commits

Author SHA1 Message Date
Tobias Stoeckmann 81078c57fb Fix typos
Typos in comments and configure output, i.e. no functional change.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-09-13 22:27:08 +02:00
Alejandro Colomar 1f11a5ce5a src/: Recommend --badname only if it is useful
(Review with -w (--ignore-all-space).)

Closes: <https://github.com/shadow-maint/shadow/issues/1067>
Reported-by: Anselm Schüler <mail@anselmschueler.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-09-01 08:17:11 -05:00
Alejandro Colomar 87a5145719 lib/: Move memzero.[ch] under lib/string/memset/
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-08-30 21:44:07 -05:00
Alejandro Colomar 745281f295 lib/atoi/, *: Split files 2024-07-11 22:42:58 -05:00
Alejandro Colomar 2dda45a390 src/usermod.c: Use id_t for parsing uid_t and gid_t
Use a static_assert(3) to make sure that id_t == uid_t == gid_t.

And use uintmax_t to print it, since on Linux they are unsigned types.

Link: <https://github.com/shadow-maint/shadow/pull/951>
Reviewed-by: Tycho Andersen <tycho@tycho.pizza>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-11 22:42:58 -05:00
Alejandro Colomar cfb8df4a91 src/usermod.c: Rename identifiers ralated to [ug]id's
It was unclear why this code is using ulong.  Since these only handle
uid's and gid's, rename the identifiers accordingly, after id_t.

Link: <https://github.com/shadow-maint/shadow/pull/951>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-11 22:42:58 -05:00
Alejandro Colomar 0464c1abf1 src/usermod.c: Simplify, by calling a2sl() instead of str2sl()
Reviewed-by: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-02 22:52:31 +02:00
Alejandro Colomar 3049bef9c3 lib/alloc/, lib/, src/, tests/: Organize the allocation APIs in a new subdirectory
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar 29f4f03def lib/string/strdup/xstrdup.[ch], lib/, src/: Move xstrdup() to its own file
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar d9923431eb src/: Use xasprintf() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar 16cb664865 lib/, src/: Use strsep(3) instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar 22272347b6 lib/string/sprintf/, lib/, src/, tests/: Move all sprintf(3)-like APIs to a subdirectory
And have a separate file for each pair of APIs.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar 1f7c00b8f7 src/usermod.c: Fix const correctness
Now that we use liba2i's const-generic macros, we can (and must) use a
'const char **' endp where the input string is 'const char *'.

Reviewed-by: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-06-29 20:00:18 +02:00
Alejandro Colomar 7f86f893ab lib/, po/, src/: get_uid(): Move function to "atoi/getnum.h"
Implement it as an inline function, and add restrict and ATTR_STRING()
and ATTR_ACCESS() as appropriate.

Reviewed-by: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-06-29 20:00:18 +02:00
Alejandro Colomar 8ad2768472 src/usermod.c: getulong_range(): Reimplement in terms of a2ul()
Reviewed-by: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-06-29 20:00:18 +02:00
Alejandro Colomar d8e6a8b99b src/usermod.c: update_gshadow(): Add helper function
Keep the while loop in the outer function, and move the iteration code
to this new helper.  This makes it a bit more readable.

Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-20 09:37:01 +02:00
Alejandro Colomar adf37cccd0 src/usermod.c: update_group(): Add helper function
Keep the while loop in the outer function, and move the iteration code
to this new helper.  This makes it a bit more readable.

Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-20 09:37:01 +02:00
Alejandro Colomar da77a82ecb src/usermod.c: update_gshadow_file(): Reduce scope of local variable
After _every_ iteration, 'changed' is always 'false'.  We don't need to
have it outside of the loop.

See:

$ grepc update_gshadow_file . \
| grep -e changed -e goto -e continue -e break -e free_ngrp -e '{' -e '}' \
| pcre2grep -v -M '{\n\t*}';
{
	bool               changed;
	changed = false;
	while ((sgrp = sgr_next ()) != NULL) {
		if (!was_member && !was_admin && !is_member) {
			continue;
		}
		if (was_admin && lflg) {
			changed = true;
		}
		if (was_member) {
			if ((!Gflg) || is_member) {
				if (lflg) {
					changed = true;
				}
			} else {
				changed = true;
			}
		} else if (is_member) {
			changed = true;
		}
		if (!changed)
			goto free_nsgrp;
		changed = false;
	}
}

This was already true in the commit that introduced the code:

$ git show 45c6603cc:src/usermod.c \
| grepc update_gshadow \
| grep -e changed -e goto -e break -e continue -e '\<if\>' -e '{' -e '}' \
| pcre2grep -v -M '{\n\t*}';
{
	int changed;
	changed = 0;
	while ((sgrp = sgr_next())) {
		 * See if the user was a member of this group
		 * See if the user was an administrator of this group
		 * See if the user specified this group as one of their
		if (!was_member && !was_admin && !is_member)
			continue;
		if (was_admin && lflg) {
			changed = 1;
		}
		if (was_member && (!Gflg || is_member)) {
			if (lflg) {
				changed = 1;
			}
		} else if (was_member && Gflg && !is_member) {
			changed = 1;
		} else if (!was_member && Gflg && is_member) {
			changed = 1;
		}
		if (!changed)
			continue;
		changed = 0;
	}
}

Fixes: 45c6603cc8 ("[svn-upgrade] Integrating new upstream version, shadow (19990709)")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-20 09:37:01 +02:00
Alejandro Colomar 68d42a8fbe src/usermod.c: update_group_file(): Reduce scope of local variable
After _every_ iteration, 'changed' is always 'false'.  We don't need to
have it outside of the loop.

See:

$ grepc update_group_file . \
| grep -e changed -e goto -e continue -e break -e free_ngrp -e '{' -e '}' \
| pcre2grep -v -M '{\n\t*}';
{
	bool                changed;
	changed = false;
	while ((grp = gr_next ()) != NULL) {
		if (!was_member && !is_member) {
			continue;
		}
		if (was_member) {
			if ((!Gflg) || is_member) {
				if (lflg) {
					changed = true;
				}
			} else {
				changed = true;
			}
		} else if (is_member) {
			changed = true;
		}
		if (!changed)
			goto free_ngrp;
		changed = false;
free_ngrp:
	}
}

This was already true in the commit that introduced the code:

$ git show 45c6603cc:src/usermod.c \
| grepc update_group \
| grep -e changed -e goto -e break -e continue -e '\<if\>' -e '{' -e '}' \
| pcre2grep -v -M '{\n\t*}';
{
	int changed;
	changed = 0;
	while ((grp = gr_next())) {
		 * See if the user specified this group as one of their
		if (!was_member && !is_member)
			continue;
		if (was_member && (!Gflg || is_member)) {
			if (lflg) {
				changed = 1;
			}
		} else if (was_member && Gflg && !is_member) {
			changed = 1;
		} else if (!was_member && Gflg && is_member) {
			changed = 1;
		}
		if (!changed)
			continue;
		changed = 0;
	}
}

Fixes: 45c6603cc8 ("[svn-upgrade] Integrating new upstream version, shadow (19990709)")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-20 09:37:01 +02:00
Alejandro Colomar 71a3238b79 src/usermod.c: update_gshadow_file(): Fix RESOURCE_LEAK (CWE-772)
Report:
> shadow-4.15.0/src/usermod.c:864:3: alloc_fn: Storage is returned from allocation function "__sgr_dup".
> shadow-4.15.0/src/usermod.c:864:3: var_assign: Assigning: "nsgrp" = storage returned from "__sgr_dup(sgrp)".
> shadow-4.15.0/src/usermod.c:964:1: leaked_storage: Variable "nsgrp" going out of scope leaks the storage it points to.
> 962|                   free (nsgrp);
> 963|           }
> 964|-> }
> 965|   #endif                                /* SHADOWGRP */
> 966|

Link: https://issues.redhat.com/browse/RHEL-35383
Reported-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-20 09:37:01 +02:00
Alejandro Colomar 61964aa06b src/usermod.c: update_group_file(): Fix RESOURCE_LEAK (CWE-772)
Report:
> shadow-4.15.0/src/usermod.c:734:3: alloc_fn: Storage is returned from allocation function "__gr_dup".
> shadow-4.15.0/src/usermod.c:734:3: var_assign: Assigning: "ngrp" = storage returned from "__gr_dup(grp)".
> shadow-4.15.0/src/usermod.c:815:1: leaked_storage: Variable "ngrp" going out of scope leaks the storage it points to.
> 813|                   gr_free(ngrp);
> 814|           }
> 815|-> }
> 816|
> 817|   #ifdef SHADOWGRP

Link: https://issues.redhat.com/browse/RHEL-35383
Reported-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-20 09:37:01 +02:00
Alejandro Colomar 81bc78ec5c src/usermod.c: Rename update_gshadow() => update_gshadow_file()
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-20 09:37:01 +02:00
Alejandro Colomar b089a63ab3 src/usermod.c: Rename update_group() => update_group_file()
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-20 09:37:01 +02:00
Alejandro Colomar 151f14ad69 src/usermod.c: Reduce scope of local variables
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-20 09:37:01 +02:00
Alejandro Colomar f39ac101ff lib/, src/: str2*(): Rename functions and reorder parameters
This makes them compatible with liba2i's functions.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-29 14:29:13 -05:00
Alejandro Colomar 27e236ca79 lib/, src/, po/: get[u]long(): Move functions to lib/atoi/str2i.h
And make them inline.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-29 14:29:13 -05:00
Alejandro Colomar 82e28ad534 src/: Use DAY_TO_STR() instead of its pattern
Cc: Tobias Stoeckmann <tobias@stoeckmann.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 16:30:46 -05:00
Alejandro Colomar be05c62bd7 lib/, src/, po/: date_to_str(): Move function to header, and make inline
BTW, there's no translatable string in there.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 16:30:46 -05:00
Alejandro Colomar 33825ab57d lib/, src/: Remove all code wrapped in defined(USE_NIS)
I don't find any way to enable USE_NIS, so it looks like it's all
dead code.  Bury it.

Closes: <https://github.com/shadow-maint/shadow/issues/909>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 16:12:51 -05:00
Skyler Ferrante e6c2e43937 Hardcoding Prog to known value
See #959. We now set Prog (program name) based on hardcoded value instead
of argv[0]. This is to help prevent escape sequence injection.
2024-03-07 22:23:04 +01:00
Tycho Andersen 714b6a53d5 usermod: refuse invalid uidmaps during --add-sub{u,g}ids
It is slightly confusing to allow adding these only to later refuse them.

Here is a (lightly tested :) patch to also refuse them when adding.

Signed-off-by: Tycho Andersen <tycho@tycho.pizza>
2024-02-13 16:06:23 -06:00
Alejandro Colomar d452d1b812 src/usermod.c: grp_update(): Remove scope of variable, and fix const correctness
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-26 09:40:10 +01:00
Alejandro Colomar 18c428a6c9 lib/, src/: get_uid(): Use the usual -1 as an error code
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-05 16:54:55 -06:00
Alejandro Colomar 2d581cb337 lib/, src/: getlong(): Use the usual -1 as an error code
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-05 16:54:55 -06:00
Tobias Stoeckmann ecc3508877 lib/, src/: Remove SCALE definition
SCALE is always DAY (and has to be always DAY), so replace it with DAY
in source code and remove unneeded calculations.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Link: <https://github.com/shadow-maint/shadow/pull/876>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-05 15:41:12 -06:00
Christian Göttsche cdb2490ab6 Update close(2) checking
Check for close(2) failure at more places closing a file descriptor
written to.

Also ignore failures with errno set to EINTR (see man:close(2) for
details).
2023-12-14 07:40:40 -06:00
Christian Göttsche 95a8de2a0a src/usermod,groups: use checked malloc
usermod.c:2165:24: warning: dereference of possibly-NULL ‘user_groups’ [CWE-690] [-Wanalyzer-possible-null-dereference]
2023-12-14 07:40:40 -06:00
Alejandro Colomar 1c464d9a2d lib/, src/: Fix error handling after strto[u]l[l](3)
-  Set errno = 0 before the call.  Otherwise, it may contain anything.
-  ERANGE is not the only possible errno value of these functions.  They
   can also set it to EINVAL.
-  Any errno value after these calls is bad; just compare against 0.
-  Don't check for the return value; just errno.  This function is
   guaranteed to not modify errno on success (POSIX).
-  Check endptr == str, which may or may not set EINVAL.

Suggested-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 12:21:55 +01:00
Alejandro Colomar dbb37b1b31 lib/string/: Move string-related files to string/ subdir
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-03 12:22:11 -06:00
Alejandro Colomar 4f16458b6c lib/, src/: Say 'long' instead of 'long int'
We were using 'long' in most places, so be consistent and use it
everywhere.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-03 09:58:19 -06:00
Alejandro Colomar d5e1c1e475 lib/, src/: Use xasprintf() instead of its pattern
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-10-20 21:05:33 +02:00
Alejandro Colomar ad3b31a59e lib/, src/: Use asprintf(3) instead of strlen(3)+malloc(3)+snprintf(3)
asprintf(3) is non-standard, but is provided by GNU, the BSDs, and musl.
That makes it portable enough for us to use.

This function is much simpler than the burdensome code for allocating
the right size.  Being simpler, it's thus safer.

I took the opportunity to fix the style to my preferred one in the
definitions of variables used in these calls, and also in the calls to
free(3) with these pointers.  That isn't gratuituous, but has a reason:
it makes those appear in the diff for this patch, which helps review it.
Oh, well, I had an excuse :)

Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-10-20 21:05:33 +02:00
Dimitri John Ledkov 088fe2618f Fix badname option to be singular just like useradd.
Badnames still accepted, note that previously usage already stated
singular form, whilst manpage and real one was plural only.

Fixes: 45d6746219 ("src: correct "badname" option")

Signed-off-by: Dimitri John Ledkov <dimitri.ledkov@canonical.com>
2023-10-16 12:45:21 -05:00
Dimitri John Ledkov 2e45fff44b Fix mixed-whitespace
Signed-off-by: Dimitri John Ledkov <dimitri.ledkov@canonical.com>
2023-10-16 12:45:21 -05:00
Alejandro Colomar e7a292ed4f Use bzero(3) instead of its pattern
It was blessed by POSIX.1-2001, and GCC says that it won't go away,
possibly ever.

memset(3) is dangerous, as the 2nd and 3rd arguments can be accidentally
swapped --who remembers what's the order of the 2nd and 3rd parameters
to memset(3) without checking the manual page or some code that uses
it?--.  Some recent compilers may be able to catch that via some
warnings, but those are not infalible.  And even if compiler warnings
could always catch that, the time lost in fixing or checking the docs is
lost for no clear gain.  Having a sane API that is unambiguous is the
Right Thing (tm); and that API is bzero(3).

If someone doesn't believe memset(3) is error-prone, please read the
book "Unix Network Programming", Volume 1, 3rd Edition by Stevens, et
al., Section 1.2.  See a stackoverflow reference in the link below[1].

bzero(3) had a bad fame in the bad old days, because some ancient
systems (I'm talking of many decades ago) shipped a broken version of
bzero(3).  We can assume that all systems in which current shadow utils
can be built, have a working version of bzero(3) --if not, please fix
your broken system; don't blame the programmer--.

One reason that some use today to avoid bzero(3) in favor of memset(3)
is that memset(3) is more often used; but that's a circular reasoning.
Even if bzero(3) wasn't supported by the system, it would need to be
invented.  It's the right API.

Another reason that some argue is that POSIX.1-2008 removed the
specification of bzero(3).  That's not a problem, because GCC will
probably support it forever, and even if it didn't, we can redefine it
like we do with memzero().  bzero(3) is just a one-liner wrapper around
memset(3).

Link: [1] <https://stackoverflow.com/a/17097978>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar 6b11077f09 memzero.h: Move memzero() and strzero() to their own header
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar f45498a6c2 libmisc/write_full.c: Improve write_full()
Documentation:

-  Correct the comment documenting the function:

   write_full() doesn't write "up to" count bytes (which is write(2)'s
   behavior, and exactly what this function is designed to avoid), but
   rather exactly count bytes (on success).

-  While fixing the documentation, take the time to add a man-page-like
   comment as in other APIs.  Especially, since we'll have to document
   a few other changes from this patch, such as the modified return
   values.

-  Partial writes are still possible on error.  It's the caller's
   responsibility to handle that possibility.

API:

-  In write(2), it's useful to know how many bytes were transferred,
   since it can have short writes.  In this API, since it either writes
   it all or fails, that value is useless, and callers only want to know
   if it succeeded or not.  Thus, just return 0 or -1.

Implementation:

-  Use `== -1` instead of `< 0` to check for write(2) syscall errors.
   This is wisdom from Michael Kerrisk.  This convention is useful
   because it more explicitly tells maintainers that the only value
   which can lead to that path is -1.  Otherwise, a maintainer of the
   code might be confused to think that other negative values are
   possible.  Keep it simple.

-  The path under `if (res == 0)` was unreachable, since the loop
   condition `while (count > 0)` precludes that possibility.  Remove the
   dead code.

-  Use a temporary variable of type `const char *` to avoid a cast.

-  Rename `res`, which just holds the result from write(2), to `w`,
   which more clearly shows that it's just a very-short-lived variable
   (by it's one-letter name), and also relates itself more to write(2).
   I find it more readable.

-  Move the definition of `w` to the top of the function.  Now that the
   function is significantly shorter, the lifetime of the variable is
   clearer, and I find it more readable this way.

Use:

-  Also use `== -1` to check errors.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-08-18 20:35:15 -05:00
Christian Göttsche 969549fdf0 Add wrapper for write(2)
write(2) may not write the complete given buffer.  Add a wrapper to
avoid short writes.
2023-08-04 17:15:42 -05:00
Iker Pedrosa 03251ffbc0 usermod: conditionally build lastlog functionality
Resolves: https://github.com/shadow-maint/shadow/issues/674

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-07-15 07:39:53 -05:00
Alejandro Colomar 09775d3718 Simplify allocation APIs
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>
2023-06-08 09:05:39 -05:00