Commit Graph

230 Commits

Author SHA1 Message Date
Alejandro Colomar
7182d6402f lib/, src/: Use streq() instead of its pattern
Except for the added (and sorted) includes, the removal of redundant
parentheses, a few cases that have been refactored for readability, and
a couple of non-string cases that I've left out of the change, this
patch can be approximated with the following semantic patch:

	$ cat ~/tmp/spatch/streq.sp
	@@
	expression s;
	@@

	- '\0' == *s
	+ streq(s, "")

	@@
	expression s;
	@@

	- '\0' == s[0]
	+ streq(s, "")

	@@
	expression s;
	@@

	- *s == '\0'
	+ streq(s, "")

	@@
	expression s;
	@@

	- s[0] == '\0'
	+ streq(s, "")

	$ find contrib/ lib* src/ -type f \
	| xargs spatch --in-place --sp-file ~/tmp/spatch/streq.sp;

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-09 20:54:42 -06:00
Alejandro Colomar
c8c1059384 src/: Transform do-while into while
list cannot be NULL in the first iteration, so we don't need a do-while.

Just in case it's not obvious: we know it's not NULL in the first
iteration because right above, in line 772, we've already dereferenced
it.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
9f129146ff lib/, src/: Use !streq() instead of its pattern
Except for the added (and sorted) includes, and the removal of redundant
parentheses, and one special case, this patch can be approximated with
the following semantic patch:

	$ cat ~/tmp/spatch/strneq.sp;
	@@
	expression a, b;
	@@

	- strcmp(a, b) != 0
	+ !streq(a, b)

	@@
	expression a, b;
	@@

	- 0 != strcmp(a, b)
	+ !streq(a, b)

	$ find contrib/ lib* src/ -type f \
	| xargs spatch --sp-file ~/tmp/spatch/strneq.sp --in-place;

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-01 22:23:19 -06:00
Alejandro Colomar
5581e74188 contrib/, lib/, src/: Use streq() instead of its pattern
Except for the added (and sorted) includes, and the removal of redundant
parentheses, this patch can be approximated with the following semantic
patch:

	$ cat ~/tmp/spatch/streq.sp;
	@@
	expression a, b;
	@@

	- strcmp(a, b) == 0
	+ streq(a, b)

	@@
	expression a, b;
	@@

	- 0 == strcmp(a, b)
	+ streq(a, b)

	@@
	expression a, b;
	@@

	- !strcmp(a, b)
	+ streq(a, b)

	$ find contrib/ lib* src/ -type f \
	| xargs spatch --sp-file ~/tmp/spatch/streq.sp --in-place;
	$ git restore lib/string/strcmp/streq.h;

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-01 22:23:19 -06:00
Volker Theile
a65fccf199 Allow setting an empty homedir
With the PR 352 it is not possible anymore to run `usermod --home "" <USERNAME>`. This PR will fix that regression.

Related to: https://github.com/shadow-maint/shadow/pull/352

Signed-off-by: Volker Theile <votdev@gmx.de>
2024-11-27 09:51:06 -06:00
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