Compare commits

...

365 Commits

Author SHA1 Message Date
Serge Hallyn
2bbe1af294 Release 4.17.1
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-12-31 13:23:26 -06:00
Tobias Stoeckmann
e3d051e4a8 su: Fix su - regression
Launch a login shell again if requested through "su -" or "su -l".

Fixes: d9923431eb ("src/: Use xasprintf() instead of its pattern")
Closes: <https://github.com/shadow-maint/shadow/issues/1160>
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-12-31 19:06:00 +01:00
Serge Hallyn
e2512d5741 Release 4.17.0
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-12-25 16:32:40 -06:00
Pranav Lawate
881a506ce4 Added information in lastlog man page for new option '-a'
Signed-off-by: Pranav Lawate <pran.lawate@gmail.com>
2024-12-25 08:40:46 -06:00
Alejandro Colomar
8821d3ff2d lib/fs/readlink/: readlinknul(): Fix return type
Fixes: 419ce14b6f (2024-11-01, "lib/fs/readlink/: readlinknul(): Add function")
Cc: Serge Halyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-09 21:26:00 -06:00
Alejandro Colomar
b9d00b64a1 lib/fs/readlink/readlinknul.h: readlinknul(): Silence warning
Use a temporary variable to silence a sign-mismatch diagnostic.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-09 21:26:00 -06:00
Pranav Lawate
205c23bff2 Added option -a for listing active users only, optimized using if aflg,return
Signed-off-by: Pranav Lawate <pran.lawate@gmail.com>
2024-12-09 21:04:21 -06:00
Alejandro Colomar
c39305569b lib/, src/: Use !streq() instead of its pattern
Except for the added (and sorted) includes, the removal of redundant
parentheses, and a few non-string cases that I've left out of the
change, this patch can be approximated with the following semantic
patch:

	$ cat ~/tmp/spatch/strneq.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/strneq.sp;

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-09 20:54:42 -06:00
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
8424d7c494 lib/sgetgrent.c: sgetgrent(): Fix use-after-free bug
We were reusing a leftover from parsing a previous line if
(i == NFIELDS-1).  A few lines below this check, we use read the element
in [3] (that is, [NFIELDS-1]), without having written it in this call.

Be stricter, and require that all NFIELDS fields are found.

Fixes: 45c6603cc8 (2007-10-07, "[svn-upgrade] Integrating new upstream version, shadow (19990709)")
Closes: <https://github.com/shadow-maint/shadow/issues/1144>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-09 19:46:29 -06:00
Serge Hallyn
b75ea29821 Release 4.17.0-rc1
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-12-05 23:52:36 -06:00
Alejandro Colomar
2f74389334 lib/gshadow.c: build_list(): Transform while loop into for loop
And 'n' is now an iterator.  Rename it to 'i' as usual.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
512deecca5 lib/gshadow.c: build_list(): Allocate at once
Instead of reallocating 1 more meber per iteration, calculate the total
amount that we want by counting the number of commas (delimiters) in the
string, plus one for the last element, plus one for the terminating
NULL.

This might result in overallocation of one element if the string is an
empty string, or if there's a trailing comma; however, that's not an
issue.  We can afford overallocating one element in certain cases, and
we get in exchange a much simpler function.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
2f4b5f5d80 lib/gshadow.c: Remove redundant variables
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
5ba62265b3 lib/gshadow.c: build_list(): Remove second parameter
We've simplified the function so much in the previous commits, that now
$2 is rather useless.  It only sets the output parameter to the same
value that the function returns.  It's simpler if the caller just sets
it itself after the call.

This removes the only 3-star pointer in the entire project.  :)

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
c1d597acbb lib/gshadow.c: sgetsgent(): Be consistent using NULL
0 is a horrible null-pointer constant.  Don't use it.
Especially, when just a few lines above, in the same function,
we've used NULL for the same thing.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
64ab7221fb lib/gshadow.c: build_list(): Compact ++ into previous statement
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
3feff7ae5b lib/gshadow.c: build_list(): Minimize use of pointer parameters
Use instead automatic variables as much as possible.
This reduces the number of dereferences, enhancing readability.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
30bcd185c3 lib/gshadow.c: Remove dead code
Nothing is using that value outside of build_list().
Keep it as an local variable.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
ecce8f098d lib/gshadow.c: Move zeroing to within build_list()
This makes build_list() less dependent on the context.
It starts from clean, whatever the state before the call was.
I was having a hard time understanding the reallocation,
until I saw that we were zeroing everything right before the call.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
712278add1 lib/gshadow.c: sgetsgent(): Remove superfluous condition
If n was 0, it doesn't hurt to set it again to 0;
and the list would be NULL, so it doesn't hurt free(3)ing it
and setting to NULL again either.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
de4715d978 lib/gshadow.c: build_list(): Remove dead assignment
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
f3464103fb lib/gshadow.c: build_list(): Improve variable and parameter names
It was hard to understand what each variable is.  Use a consistent
scheme, where a 'p' means a pointer, 'l' means list, and 'n' means
number of elements.  Those should be obvious from the name of the
function and the context, and will make it easier to read the code.
Also, the shorter names will allow focusing on the rest of the code.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
93887b4de6 lib/gshadow.c: build_list(): Remove unused variable
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
960947135c lib/gshadow.c: build_list(): Fix type of parameter
list ($2) is a pointer to a list of strings.  We were declaring it as an
array of pointers to strings, which was bogus.  It worked out of luck,
because array parameters are transformed into pointers by the compiler,
but it was incorrect.  Just look at how we're calling this function.

	$ grep build_list lib/gshadow.c
	build_list(char *s, char ***list, size_t *nlist)
		sgroup.sg_adm = build_list (fields[2], &admins, &nadmins);
		sgroup.sg_mem = build_list (fields[3], &members, &nmembers);
	$ grep '^static .*\<admins\>' lib/gshadow.c
	static /*@null@*//*@only@*/char **admins = NULL;
	$ grep '^static .*\<members\>' lib/gshadow.c
	static /*@null@*//*@only@*/char **members = NULL;

Fixes: 8e167d28af ("[svn-upgrade] Integrating new upstream version, shadow (4.0.8)")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -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
90afe61003 lib/, src/: Use strsep(3) instead of strtok(3)
strsep(3) is stateless, and so is easier to reason about.

It also has a slight difference: strtok(3) jumps over empty fields,
while strsep(3) respects them as empty fields.  In most of the cases
where we were using strtok(3), it makes more sense to respect empty
fields, and this commit probably silently fixes a few bugs.

In other cases (most notably filesystem paths), contiguous delimiters
("//") should be collapsed, so strtok(3) still makes more sense there.
This commit doesn't replace such strtok(3) calls.

While at this, remove some useless variables used by these calls, and
reduce the scope of others.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 15:33:32 -06:00
Iker Pedrosa
bdb5e2b79f CI: update artifacts action
v3 of upload-artifact actions is being deprecated, so let's move to v4.

Link: https://github.com/actions/upload-artifact
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-12-05 14:31:23 +01:00
Dennis Baurichter
f220407144 groupadd, groupmod: Update gshadow file with -U
When running groupadd or groupmod with the -U|--user option, also update
the group shadow database if it is used.

Fixes: 342c934a (2020-08-09, "add -U option to groupadd and groupmod")
Closes: <https://github.com/shadow-maint/shadow/issues/1124>
2024-12-03 11:16:13 +01: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
Alejandro Colomar
212ef97449 lib/gshadow_.h: __STDC__ is always 1
We require C11 since a long time ago.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-01 22:04:24 -06:00
Alejandro Colomar
1d6456542c lib/csrand.c: csrand(): Use read(2) instead of fread(2)
We don't need the heavy stdio for getting a few bytes from
</dev/urandom>.  Let's use the simpler POSIX API.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-01 21:43:25 -06:00
Alejandro Colomar
627b7364b5 src/login_nopam.c: resolve_hostname(): Use NI_MAXHOST instead of MAXHOSTNAMELEN with getnameinfo(3)
That's what the getnameinfo(3) manual page recommends.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-01 20:59:28 -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
Alejandro Colomar
365279ea95 share/container-build.sh: Fix path
The instructions are written so that this script should be run from the
root of the repository.  Specify the path from the root of the repo.
Before this fix, the command needed to be run from within <share/>.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-25 16:23:43 +01:00
Iker Pedrosa
742a230e30 CI: avoid cancelling all jobs when one fails
If a job in a matrix fails we don't want to cancel all jobs, thus we
need to set `fail-fast: false` as a strategy property.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-11-23 01:04:19 +01:00
Tobias Stoeckmann
929e61d604 lib/idmapping.c: Fix get_map_ranges range check
The get_map_ranges function shall support the whole accepted range
as specified in user_namespaces(7), i.e. upper and lower from 0 to
UINT_MAX - 1 as well as range from 1 to UINT_MAX. The actual limit of
range depends on values of upper and lower and adding the range
to either upper or lower shall never overflow UINT_MAX.

Fixes: 7c43eb2c4e (2024-07-11, "lib/idmapping.c: get_map_ranges(): Move range check to a2ul() call")
Fixes: ff2baed5db (2016-08-14, "idmapping: add more checks for overflow")
Fixes: 94da3dc5c8 (2016-08-14, "also check upper for wrap")
Fixes: 7f5a14817d (2016-07-31, "get_map_ranges: check for overflow")
Co-authored-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-13 18:17:03 +01:00
Alejandro Colomar
0b8c0c893c lib/, src/: Use NULL instead of 0 as a null pointer constant
GCC 15 will add -Wzero-as-null-pointer-constant for deprecating it,
and I'm working on a paper for deprecating it from ISO C too.
Let's remove any uses in our code base.

I've done this change by building GCC from master, adding
-Werror=zero-as-null-pointer-constant to ./autogen.sh, and fixing every
error that showed up.

Closes: <https://github.com/shadow-maint/shadow/issues/1120>
Link: <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117059>
Link: <https://software.codidact.com/posts/292718/292759#answer-292759>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-13 09:44:54 -06:00
Alejandro Colomar
8296e62957 lib/shadow.c: my_sgetspent(): There can be only one!
We already have sgetspent(), with identical semantics, defined in
<lib/sgetspent.c>.

	$ diff -u <(grepc sgetspent .) <(grepc my_sgetspent .)
	--- /dev/fd/63	2024-11-11 11:56:55.444055921 +0100
	+++ /dev/fd/62	2024-11-11 11:56:55.444055921 +0100
	@@ -1,23 +1,19 @@
	-./lib/sgetspent.c:struct spwd *
	-sgetspent(const char *string)
	+./lib/shadow.c:static struct spwd *my_sgetspent (const char *string)
	 {
	-	static char spwbuf[PASSWD_ENTRY_MAX_LENGTH];
	-	static struct spwd spwd;
	-	char *fields[FIELDS];
	-	char *cp;
	-	int i;
	+	int                 i;
	+	char                *fields[FIELDS];
	+	char                *cp;
	+	static char         spwbuf[BUFSIZ];
	+	static char         empty[] = "";
	+	static struct spwd  spwd;

		/*
		 * Copy string to local buffer.  It has to be tokenized and we
		 * have to do that to our private copy.
		 */

	-	if (strlen (string) >= sizeof spwbuf) {
	-		fprintf (shadow_logfd,
	-		         "%s: Too long passwd entry encountered, file corruption?\n",
	-		         shadow_progname);
	-		return NULL;	/* fail if too long */
	-	}
	+	if (strlen (string) >= sizeof spwbuf)
	+		return 0;
		strcpy (spwbuf, string);
		stpsep(spwbuf, "\n");

	@@ -30,14 +26,16 @@
			fields[i] = strsep(&cp, ":");

		if (i == (FIELDS - 1))
	-		fields[i++] = "";
	+		fields[i++] = empty;

		if (cp != NULL || (i != FIELDS && i != OFIELDS))
	-		return NULL;
	+		return 0;

		/*
		 * Start populating the structure.  The fields are all in
	-	 * static storage, as is the structure we pass back.
	+	 * static storage, as is the structure we pass back.  If we
	+	 * ever see a name with '+' as the first character, we try
	+	 * to turn on NIS processing.
		 */

		spwd.sp_namp = fields[0];
	@@ -46,13 +44,13 @@
		/*
		 * Get the last changed date.  For all of the integer fields,
		 * we check for proper format.  It is an error to have an
	-	 * incorrectly formatted number.
	+	 * incorrectly formatted number, unless we are using NIS.
		 */

		if (fields[2][0] == '\0')
			spwd.sp_lstchg = -1;
		else if (a2sl(&spwd.sp_lstchg, fields[2], NULL, 0, 0, LONG_MAX) == -1)
	-		return NULL;
	+		return 0;

		/*
		 * Get the minimum period between password changes.
	@@ -61,7 +59,7 @@
		if (fields[3][0] == '\0')
			spwd.sp_min = -1;
		else if (a2sl(&spwd.sp_min, fields[3], NULL, 0, 0, LONG_MAX) == -1)
	-		return NULL;
	+		return 0;

		/*
		 * Get the maximum number of days a password is valid.
	@@ -70,7 +68,7 @@
		if (fields[4][0] == '\0')
			spwd.sp_max = -1;
		else if (a2sl(&spwd.sp_max, fields[4], NULL, 0, 0, LONG_MAX) == -1)
	-		return NULL;
	+		return 0;

		/*
		 * If there are only OFIELDS fields (this is a SVR3.2 /etc/shadow
	@@ -93,7 +91,7 @@
		if (fields[5][0] == '\0')
			spwd.sp_warn = -1;
		else if (a2sl(&spwd.sp_warn, fields[5], NULL, 0, 0, LONG_MAX) == -1)
	-		return NULL;
	+		return 0;

		/*
		 * Get the number of days of inactivity before an account is
	@@ -103,7 +101,7 @@
		if (fields[6][0] == '\0')
			spwd.sp_inact = -1;
		else if (a2sl(&spwd.sp_inact, fields[6], NULL, 0, 0, LONG_MAX) == -1)
	-		return NULL;
	+		return 0;

		/*
		 * Get the number of days after the epoch before the account is
	@@ -113,7 +111,7 @@
		if (fields[7][0] == '\0')
			spwd.sp_expire = -1;
		else if (a2sl(&spwd.sp_expire, fields[7], NULL, 0, 0, LONG_MAX) == -1)
	-		return NULL;
	+		return 0;

		/*
		 * This field is reserved for future use.  But it isn't supposed
	@@ -123,8 +121,7 @@
		if (fields[8][0] == '\0')
			spwd.sp_flag = SHADOW_SP_FLAG_UNSET;
		else if (str2ul(&spwd.sp_flag, fields[8]) == -1)
	-		return NULL;
	+		return 0;

		return (&spwd);
	 }
	-./lib/prototypes.h:extern struct spwd *sgetspent (const char *string);

Closes: <https://github.com/shadow-maint/shadow/issues/1114>
Link: <https://www.youtube.com/watch?v=IpbvtSQvgWM>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-11 16:47:57 -06:00
Alejandro Colomar
19ce8b0abc src/login_nopam.c: Rely on the system's MAXHOSTNAMELEN
The reason for that code seems to be some ancient AIX version that
defined a value that was too small (32).  We don't support such systems.
In the link below, I found the following comment and code:

	 /*
	  * Some AIX versions advertise a too small MAXHOSTNAMELEN value (32).
	  * Result: long hostnames would be truncated, and connections would be
	  * dropped because of host name verification failures. Adrian van Bloois
	  * (A.vanBloois@info.nic.surfnet.nl) figured out what was the problem.
	  */

	#if (MAXHOSTNAMELEN < 64)
	#undef MAXHOSTNAMELEN
	#endif

	/* In case not defined in <sys/param.h>. */

	#ifndef MAXHOSTNAMELEN
	#define MAXHOSTNAMELEN  256             /* storage for host name */
	#endif

Today's systems seem to be much better regarding this macro.  Rely on
them.

Link: <https://sources.debian.org/src/tcp-wrappers/7.6.q-33/workarounds.c/?hl=36#L36>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-10 23:17:41 -06:00
Alejandro Colomar
9d8145acfc lib/gshadow.c: endsgent(): Invert logic to reduce indentation
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-10 23:11:43 -06:00
Alejandro Colomar
99a3ca17df lib/list.c: comma_to_list(): Use strchrcnt() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-10 23:07:19 -06:00
Alejandro Colomar
9efce1ac85 lib/string/strchr/: strchrcnt(): Add function
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-10 23:07:19 -06:00
Alejandro Colomar
67c42427a0 lib/string/strcmp/: streq(): Add function
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-10 23:07:19 -06:00
frostb1te
73e58adc6b src/gpasswd.c: is_valid_user_list(): Fix invalid free(3)
This fix addresses an issue in is_valid_user_list() where the free
operation was attempted on an address not allocated with malloc().  By
duplicating the pointer with xstrdup(users) into dup, and using dup as
the original pointer, we ensure that only the valid pointer is freed,
avoiding an invalid free operation.

This bug was introduced when changing some code that used strchrnul(3)
to use strsep(3) instead.  strsep(3) advances the pointer, unlike the
previous code.

This unconditionally leads to a bug:

-  Passing NULL to free(3), if the last field in the
   colon-separated-value list is non-empty.  This results in a memory
   leak.

-  Passing a pointer to the null byte ('\0') that terminates the string,
   if the last element of the colon-separated-value list is empty.  The
   most obvious reproducer of such a bogus free(3) call is:

       free(strdup("foo:") + 4);

   This results in Undefined Behavior, and could result in allocator
   data corruption.

Fixes: 16cb664865 (2024-07-01, "lib/, src/: Use strsep(3) instead of its pattern")
Suggested-by: <https://github.com/frostb1ten>
Reported-by: <https://github.com/frostb1ten>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Christian Brauner <christian@brauner.io>
2024-11-08 13:42:23 +01:00
Miroslav Cimerman
a0771fc01a man/shadow,man/gshadow: Fix grammar
Signed-off-by: Miroslav Cimerman <mc@doas.su>
2024-11-04 14:17:49 +01:00
Alejandro Colomar
86451e374b lib/fs/readlink/areadlink.h: areadlink(): Use PATH_MAX instead of a magic value
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-01 21:25:50 -05:00
Alejandro Colomar
ed569088cc lib/fs/readlink/areadlink.h: Cosmetic changes
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-01 21:25:50 -05:00
Alejandro Colomar
32f10c3dec lib/fs/readlink/, lib/: areadlink(): Move and rename function
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-01 21:25:50 -05:00
Alejandro Colomar
f8c7955bbb lib/: Use READLINKNUL() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-01 21:25:50 -05:00
Alejandro Colomar
5d5ab18890 lib/: Use readlinknul() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-01 21:25:50 -05:00
Alejandro Colomar
d78d1c2fd7 lib/fs/readlink/readlinknul.h: READLINKNUL(): Add macro
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-01 21:25:50 -05:00
Alejandro Colomar
419ce14b6f lib/fs/readlink/: readlinknul(): Add function
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-01 21:25:50 -05:00
Iker Pedrosa
c8c3731e05 CI: fix fedora build problems
The new fedora 41 has been released and some things have changed. Make
sure to install python and python3-dnf and specify the dnf version in
the roles.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-10-31 09:52:54 -05:00
Serge Hallyn
cd8a8da7de CI: fix handling of sources.list
Closes #1088

We can't be sure whether a github runner will have new- or old-
style sources.list, so check whether the new exists, else use
the old style.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-10-31 09:46:51 +01:00
Alejandro Colomar
6266a916c2 lib/loginprompt.c: login_prompt(): Use strtcpy() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-30 21:52:21 -05:00
Alejandro Colomar
3daf3f0cc4 lib/getdef.c: Remove dead code
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-30 21:15:30 -05:00
Alejandro Colomar
0589cbc135 lib/fields.c: Remove dead code
A few lines above, we've removed the '\n' already.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-30 21:15:30 -05:00
sgakerru
feead2f639 src/useradd.c: get_groups(): Fix memory leak 2024-10-30 12:58:55 +01:00
Marcin Nowakowski
326889ca81 Fix coverity unbound buffer issues
During coverity scan, there are reported four issues
with unbounded source buffer for each usage of input arg
directly with syslog function.

Sample coverity test report for chsh.c file:

 1. string_size_argv: argv contains strings with unknown size.
 int main (int argc, char **argv)
[...]
 4. var_assign_var: Assigning: user = argv[optind]. Both are now tainted.
 user = argv[optind];
[...]
CID 5771784: (#1 of 1): Unbounded source buffer (STRING_SIZE)
15. string_size: Passing string user of unknown size to syslog.
 SYSLOG ((LOG_INFO, "changed user '%s' shell to '%s'", user, loginsh));

Similar issue is reported three times more:
File: chfn.c, function: main, variable: user
File: passwd.c, function: main, variable: name
File: newgrp.c, function: main, variable: group

This commit is the first approach to fix the reported issues.
The proposed changes add conditions, which verify
the user and group names arguments, including their lengths.
This will not silence the coverity reports, but the change causes
that they are irrelevant and could be ignored.
2024-10-22 15:31:19 +02:00
Alejandro Colomar
afc4b574b7 lib/alloc/realloc*.h: Always reallocate at least 1 byte
glibc's realloc(3) is broken.  It was originally good (I believe) until
at some point, when it was changed to conform to C89, which had a bogus
specification that required that it returns NULL.  C99 fixed the mistake
from C89, and so glibc's realloc(3) is non-conforming to
C99/C11/POSIX.1-2008.  C17 broke again the definition of realloc(3).

Link: <https://github.com/shadow-maint/shadow/pull/1095>
Link: <https://nabijaczleweli.xyz/content/blogn_t/017-malloc0.html>
Link: <https://inbox.sourceware.org/libc-alpha/5gclfbrxfd7446gtwd2x2gfuquy7ukjdbrndphyfmfszxlft76@wwjz7spd4vd7/T/#t>
Co-developed-by: наб <nabijaczleweli@nabijaczleweli.xyz>
Signed-off-by: наб <nabijaczleweli@nabijaczleweli.xyz>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Acked-by: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-22 10:53:06 +02:00
Alejandro Colomar
12aa29b576 lib/alloc/realloc*.h: Rename macro parameter
This is in preparation for the following commit, which will need this
shorter parameter name to avoid breaking long lines.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-22 10:53:06 +02:00
Alejandro Colomar
30ab822cf3 doc/contributions/introduction.md: Fix typo in link
Fixes: 981bb8f9d1 ("doc: add contributions introduction")
Reported-by: наб <nabijaczleweli@nabijaczleweli.xyz>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-17 17:09:26 +02:00
Iker Pedrosa
0d1faafd3c CI: install libltdl-dev
Required to manage an autoconf macro.

Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-10-15 10:43:24 +02:00
Iker Pedrosa
c8600f1359 CI: run command as non-root user
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-10-15 10:43:24 +02:00
Iker Pedrosa
339a596374 CI: run Install dependencies workflow
Run this workflow instead of replicating the script every time we need
to install the dependencies.

Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-10-15 10:43:24 +02:00
Iker Pedrosa
99c4f445c7 CI: update Ubuntu repositories configuration
Recently Ubuntu updated its repositories configuration file from
`/etc/apt/sources.list` to `/etc/apt/sources.list.d/ubuntu.source`.
Thus, we need to update its location to be able to install all the
package dependencies.

In addition, the CI script was trying to uncomment the lines starting
with `deb-src`, but there is none in the new configuration file format.
Replace `Types: deb` by `Types: deb deb-src` at the beginning of the
line instead.

This commit merges all dependency installation scripts into a single
workflow, which will be called from all sites that have to install
dependencies.

Link: https://linuxconfig.org/ubuntus-repository-configuration-ubuntu-sources-have-moved-to-etc-apt-sources-list-d-ubuntu-sources
Closes: https://github.com/shadow-maint/shadow/issues/1088
Reported-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-10-15 10:43:24 +02:00
Alejandro Colomar
4a15739408 src/suauth.c: check_su_auth(): Use pointers to simplify
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-13 20:40:02 -05:00
Alejandro Colomar
fb731369fd src/suauth.c: check_su_auth(): Use strspn(3) instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-13 20:40:02 -05:00
Alejandro Colomar
276f3fde26 lib/gshadow.c: endsgent(): Remove dead assignment
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-13 20:40:02 -05:00
Alejandro Colomar
02d4af7f6f lib/port.c: portcmp(): Use strcmp(3) instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-13 20:40:02 -05:00
Alejandro Colomar
f45adadd28 lib/, src/: Use stpspn() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-13 20:40:02 -05:00
Iker Pedrosa
9035932496 useradd: fix comparison sign for write_full() return
I forgot to change the comparison sign that checks the return value of
write_full()

Closes: https://github.com/shadow-maint/shadow/issues/1072
Fixes: 8903b94c86 ("useradd: fix write_full() return value")
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2313559

Reported-by: <https://github.com/brown-midas>
Suggested-by: <https://github.com/brown-midas>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-10-04 21:01:58 -05:00
kugarocks
6c9e80165b src/useradd.c: Add the missing equals sign
Fixes: a7b169be18 ("src/useradd.c: Use stpsep() to simplify")
Reviewed-by: Alejandro Colomar <alx@kernel.org>
2024-10-04 20:59:23 -05:00
Alejandro Colomar
7a796897e5 src/check_subid_range.c: Remove dead code
I forgot to remove the setting of errno when I switched from
strtoul_noneg() to str2ul().  strtoul(3) needs errno for determining
success, but str2ul() does not.

Fixes: f3a1e1cf09 ("src/check_subid_range.c: Call str2ul() instead of strtoul_noneg()")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-03 10:38:56 +02:00
Tobias Stoeckmann
af66ffea33 man/subgid,man/subuid: Fix program list
The groupadd utility does not set information in subgid. Instead, list
all programs which actually can do so.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-10-02 13:03:38 +02:00
Tobias Stoeckmann
e7a970a189 man/passwd: Fix typo
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-10-02 13:03:38 +02:00
Alejandro Colomar
759d2373e4 src/useradd.c: Add fmkomstemp() to fix mode of </etc/default/useradd>
The mode of the file should be 644, but mkstemp(2) was transforming it
to 600.

To do this, we need a function that accepts a mode parameter.  While we
don't need a flags parameter, to avoid confusion with mkostemp(2), let's
add both a flags and a mode parameter.

Link: <https://github.com/shadow-maint/shadow/pull/1080>
Reported-by: kugarocks <kugacola@gmail.com>
Suggested-by: kugarocks <kugacola@gmail.com>
Tested-by: kugarocks <kugacola@gmail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-01 14:38:59 -05:00
Tobias Stoeckmann
e6a5484ced lib: Eliminate dead code
The tz function is only called if ENV_TZ starts with a slash.

If the specified file cannot be read, the code implies that ENV_TZ
would be returned if it does not start with a slash.

Since we know that it DOES start with a slash, the code can be
simplified to state that "TZ=CST6CDT" is returned as a default if
the specified file cannot be read.

Benefit of this change is that strcpy's use case here can be
easier verified.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-09-29 12:23:05 +02:00
Tobias Stoeckmann
dd6cddd481 lib/run_part: Adjust style
Remove some of these whitespaces.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-09-18 14:52:05 +02:00
Tobias Stoeckmann
76c97ed7ec lib/run_part: Unify error messages
At least if they can be assigned directly to a function call.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-09-18 14:52:05 +02:00
Tobias Stoeckmann
62bd261fbe lib: Fix typo
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-09-18 14:52:05 +02:00
Tobias Stoeckmann
6b4487e173 lib/run_part: Reduce visibility
The run_part function is only used in run_part.c itself, so no
need to expose it to other files.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-09-18 14:52:05 +02:00
Tobias Stoeckmann
db395130d1 lib/run_part: Unify logging
Use shadow_logfd for logging instead of fixed stderr to use
shadow's own logging infrastructure.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-09-18 14:52:05 +02:00
Tobias Stoeckmann
3ac50e1d02 lib/run_part: Use correct data types
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-09-18 14:52:05 +02: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
Iker Pedrosa
8903b94c86 useradd: fix write_full() return value
write_full() returns -1 on error and useradd was checking another value.

Closes: https://github.com/shadow-maint/shadow/issues/1072
Fixes: f45498a6c2 ("libmisc/write_full.c: Improve write_full()")

Reported-by: <https://github.com/brown-midas>
Suggested-by: <https://github.com/brown-midas>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-09-13 09:44:51 +02:00
Pino Toscano
b2b37863a6 lib/user_busy.c: Include <utmpx.h>
Since:
- utmpx APIs are used in non-Linux code blocks
- <utmpx.h> is already unconditionally included in Linux parts in other
  files
then unconditionally include it in this file as well.

Signed-off-by: Pino Toscano <toscano.pino@tiscali.it>
2024-09-12 11:43:39 +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
0663c91f80 src/: Invert logic to improve readability
And remove the (now) redundant comments.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-09-01 08:17:11 -05:00
Alejandro Colomar
1c127bd173 lib/chkname.c: is_valid_{user,group}_name(): Set errno to distinguish the reasons
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-09-01 08:17:11 -05:00
Alejandro Colomar
56d52997c3 man/userdel.8.xml: Reword '-f'
The previous wording seemed to say that -f implied -r.  It doesn't; -f
only skips safety checks, so reword accordingly.

Closes: <https://github.com/shadow-maint/shadow/issues/1062>
Reported-by: Martin von Wittich <martin.von.wittich@iserv.eu>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-09-01 07:45:30 -05:00
Alejandro Colomar
f5806e0511 lib/: Chain free(strzero(s))
This reduces the repetition of the argument, which could be error-prone.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-08-30 21:44:07 -05:00
Alejandro Colomar
dab8de8a72 lib/string/memset/: memzero(), strzero(): Return the pointer
This allows chaining with free(3) on the same line.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-08-30 21:44:07 -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
5c0b99c77e po/es.po: wsfix
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-08-22 22:51:57 -05:00
Alejandro Colomar
3dc840a56a lib/string/strftime.h: STRFTIME(): Tighten macro definition
strftime(3) is not a variadic function; there's exactly one argument
after the format string.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-08-22 22:51:57 -05:00
Alejandro Colomar
60da937c2f src/chage.c: print_day_as_date(): Handle errors from strfime(3)
Just like we do in day_to_str().

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-08-22 22:51:57 -05:00
Alejandro Colomar
6a2e298a5b src/chage.c: print_day_as_date(): Simplify error handling
If localtime_r(3) fails, just print future, as we do in day_to_str().
It should only fail for unrealistic dates, if at all.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-08-22 22:51:57 -05:00
Alejandro Colomar
683b3caa62 lib/, src/: Use %F instead of %Y-%m-%d with strftime(3)
%F is specified by ISO C99.  It adds semantic meaning as printing an
ISO 8601 date.

Scripted change:

	$ cat ~/tmp/spatch/strftime_F.sp
	@@
	@@

	- "%Y-%m-%d"
	+ "%F"
	$ find contrib/ lib* src/ -type f \
	| xargs spatch --sp-file ~/tmp/spatch/strftime_F.sp --in-place

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-08-22 22:51:57 -05:00
Chris Hofstaedtler
04592e4cc7 Remove references to cppw, cpgr
cppw, cpgr were Debian-only tools, which I've dropped in a recent upload.

Upstream should have never had tests for them.

Signed-off-by: Chris Hofstaedtler <zeha@debian.org>
2024-08-12 10:08:45 +02:00
Carles Pina i Estany
e04e493234 Update Catalan translation 2024-08-11 23:22:04 +02:00
Alejandro Colomar
3f5b4b5626 lib/, src/: Use local time for human-readable dates
That is, use localtime_r(3) instead of gmtime_r(3).

Closes: <https://github.com/shadow-maint/shadow/issues/1057>
Reported-by: Gus Kenion <https://github.com/kenion>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-08-01 10:12:44 +02:00
Eisuke Kawashima
f3f501c81c doc(login.defs): fix type of TTYPERM 2024-07-18 10:21:21 -05:00
Iker Pedrosa
fffa4d3e27 share/containers: remove unused dockerfiles
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-07-18 10:17:29 -05:00
Iker Pedrosa
28ffa634d8 CI: use Ansible build in Github Action
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-07-18 10:17:29 -05:00
Iker Pedrosa
4bc0c5b0b8 doc: update documentation to use Ansible build
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-07-18 10:17:29 -05:00
Iker Pedrosa
f56e79a2b7 share/container-build.sh: update to use Ansible build
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-07-18 10:17:29 -05:00
Iker Pedrosa
d8fb10f7b7 share/ansible: implement distribution selection
Distribution to run can be selected when running `ansible-playbook` by
appending `-e 'distribution=fedora'` to the command.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-07-18 10:17:29 -05:00
Iker Pedrosa
80c4e70da0 share/ansible: convert alpine dockerfile to ansible
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-07-18 10:17:29 -05:00
Iker Pedrosa
1d6f578f3e share/ansible: convert debian dockerfile to ansible
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-07-18 10:17:29 -05:00
Iker Pedrosa
9a53a8aebd share/ansible: move fedora ci_run to its own file
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-07-18 10:17:29 -05:00
Iker Pedrosa
36e8015e2b share/.gitignore: add build-out folder
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-07-18 10:17:29 -05:00
Iker Pedrosa
df50348a28 share/ansible: create roles
Create `build_container` and `ci_run` roles and move the fedora target
to them.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-07-18 10:17:29 -05:00
Iker Pedrosa
9a0cd7a231 share/ansible: convert fedora dockerfile to ansible
Using a dockerfile to build, install and test the code can be
problematic as we can't capture the log files to check what failed in
case of failure. This PR converts the fedora dockerfile to Ansible, an
open source IT automation tool. The tool can be used on the developers
and the CI system to check whether a piece of code can be built,
installed and tested.

This is the first patch in a series, where I will convert the existing
PR workflows to use Ansible instead of dockerfiles.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-07-18 10:17:29 -05:00
Chris Hofstaedtler
dfbc0db895 Makefile.am: avoid warning: EXTRA_DIST multiply defined
automake complained about duplicate definitions of EXTRA_DIST:

autoreconf: running: automake --add-missing --copy --no-force
Makefile.am:19: warning: EXTRA_DIST multiply defined in condition TRUE ...
Makefile.am:3: ... 'EXTRA_DIST' previously defined here
autoreconf: Leaving directory '.'

Signed-off-by: Chris Hofstaedtler <zeha@debian.org>
2024-07-18 09:21:57 -05:00
Chris Hofstaedtler
11e9627658 tests/libsubid/04_nss: fix setting basedir
Align on variable name BUILD_BASE_DIR for overriding the toplevel
directory. This is the same name as accepted by tests/common/config.sh.

Without this, the test libsubid/04_nss fails in Debian's autopkgtests.

Signed-off-by: Chris Hofstaedtler <zeha@debian.org>
2024-07-18 08:52:35 -05:00
Sebastian Gross
34f213211f man: groupmod: remove misleading -N option
The extra paragraph for --users mentions a -N option. groupmod has no -N
option.

Prevent confusion and remove its appearance.

Signed-off-by: Sebastian Gross <sgross@emlix.com>
2024-07-17 15:48:22 +02:00
Sebastian Gross
48b36a03e8 man: group(add|mod): clarify list format
The --users list option expect a string of comma separated values.
While this might be obvious to some others it is certainly not for others.

Remove this ambiguity.

Closes #848

Signed-off-by: Sebastian Gross <sgross@emlix.com>
2024-07-17 15:48:22 +02:00
Sebastian Gross
9176206a7c man: groupmod: fix misleading param
--append has no argument in groupmod.c but the man pages states GID as
parameter.

In order to avoid confusion remove it from man page.

Signed-off-by: Sebastian Gross <sgross@emlix.com>
2024-07-17 15:48:22 +02:00
Alejandro Colomar
8a93576ff9 lib/chkname.c: An object cannot expand further than the universe in which it resides
If you want a larger object, you'll have to wait at least until the
universe expands so much.

If an implementation doesn't recognize its own limitations, its a bug,
not a feature.

Closes: <https://github.com/shadow-maint/shadow/issues/1052>
Cc: Tobias Stoeckmann <tobias@stoeckmann.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-15 15:01:11 +02:00
Alejandro Colomar
63297e836d lib/atoi/strtoi/, tests/: strto[iu]_(): 1 is an invalid base
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-11 22:42:58 -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
b73c78581c lib/idmapping.c: get_map_ranges(): Don't exit() from a library function
Fixes: ff2baed5db ("idmapping: add more checks for overflow")
Link: <ff2baed5db (r136635300)>
Reported-by: Alejandro Colomar <alx@kernel.org>
Suggested-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-11 22:42:58 -05:00
Alejandro Colomar
c46c6a6e5a lib/idmapping.c: get_map_ranges(): Simplify iterator variables
Merge two iterator variables into one, and reduce its scope.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-11 22:42:58 -05:00
Alejandro Colomar
a184c2b555 lib/idmapping.c: get_map_ranges(): Remove dead code
This test is impossible.  The limits specified in a2ul() already cover
this.

Link: <ff2baed5db (r136635300)>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-11 22:42:58 -05:00
Alejandro Colomar
7c43eb2c4e lib/idmapping.c: get_map_ranges(): Move range check to a2ul() call
Link: <ff2baed5db (r136635300)>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-11 22:42:58 -05:00
Alejandro Colomar
57aa813c73 lib/idmapping.c: get_map_ranges(): Move range check to a2ul() call
Link: <ff2baed5db (r136635300)>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-11 22:42:58 -05:00
Alejandro Colomar
5586f43d48 lib/idmapping.c: get_map_ranges(): Move range check to a2ul() calls
Link: <ff2baed5db (r136635300)>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-11 22:42:58 -05:00
Alejandro Colomar
f89925c219 lib/idmapping.c: get_map_ranges(): Rename local variable
For a pointer iterator used often, a single-letter identifier is more
appropriate.  That reduces the length of lines considerably, avoiding
unnecessary line breaks.  And since we initialize it with

	m = mappings;

it's clear what it is.

Link: <ff2baed5db (r136635300)>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-11 22:42:58 -05:00
Alejandro Colomar
c2ebd210e7 lib/limits.c: check_logins(): Report LOGIN_ERROR_LOGIN if str2ul() ERANGE
Fixes: 10396f9536 ("* libmisc/limits.c: Parse the limits, umask, nice, maxlogin, file limit with getlog() / getulong().")
Link: <882cf59459>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-11 22:42:58 -05:00
Alejandro Colomar
568d26d7ed src/login_nopam.c: login_access(): Use stpsep() to simplify
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-08 20:25:01 -05:00
Alejandro Colomar
a7b169be18 src/useradd.c: Use stpsep() to simplify
This allows using plain strcmp(3) instead of MATCH().

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-08 20:25:01 -05:00
Alejandro Colomar
d95b899bfc lib/nss.c: nss_init(): Use stpsep() instead of strtok_r(3)
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-08 20:25:01 -05:00
Alejandro Colomar
8714ac0cd6 src/suauth.c: check_su_auth(): Use stpsep() to simplify
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-08 20:25:01 -05:00
Alejandro Colomar
64409c28b7 lib/string/strchr/stpcspn.[ch]: stpcspn(): Remove unused function
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-08 20:25:01 -05:00
Alejandro Colomar
a33d7430ed lib/attr.h: ATTR_STRING(): It only accepts one argument
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-08 20:25:01 -05:00
Alejandro Colomar
d91b22cc2f lib/, src/: Use stpsep() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-08 20:25:01 -05:00
Alejandro Colomar
39da15614e lib/string/strtok/stpsep.[ch]: stpsep(): Add function
This function is somewhat simpler to use than strsep(3) in some cases.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-08 20:25:01 -05:00
Chris Hofstaedtler
843c151f2c lib/find_new_[gu]id.c: include stdint.h for UINT16_MAX/UINT32_MAX
Signed-off-by: Chris Hofstaedtler <zeha@debian.org>
2024-07-08 01:19:49 +02:00
Alejandro Colomar
cee79c215a lib/port.c: getportent(): Use strsep(3) instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-06 07:44:02 -05:00
Alejandro Colomar
882db57f24 lib/port.c: getportent(): Align variables
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-06 07:44:02 -05:00
Alejandro Colomar
b4b4ff633a lib/port.c: getttyuser(): Use pointer arithmetic to simplify
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-06 07:44:02 -05:00
Alejandro Colomar
d9d0117e80 lib/port.c: getportent(): Use equivalent code to parse equally-formatted fields
The tty names field and the user names field have the same formatting:
a CSV terminated by a ':'.  Thus, we can --and should-- use the same
exact code for parsing both.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-06 07:44:02 -05:00
Alejandro Colomar
a198054456 lib/port.c: getportent(): Make sure the aren't too many fields in the CSV
Otherwise, the line is invalidly formatted, and we ignore it.

Detailed explanation:

There are two conditions on which we break out of the loops that precede
these added checks:

-  j is too big (we've exhausted the space in the static arrays)

	$ grep -r -e PORT_TTY -e PORT_IDS lib/port.*
	lib/port.c:	static char *ttys[PORT_TTY + 1];	/* some pointers to tty names     */
	lib/port.c:	static char *users[PORT_IDS + 1];	/* some pointers to user ids     */
	lib/port.c:	for (cp = buf, j = 0; j < PORT_TTY; j++) {
	lib/port.c:			if ((',' == *cp) && (j < PORT_IDS)) {
	lib/port.h: * PORT_IDS - Allowable number of IDs per entry.
	lib/port.h: * PORT_TTY - Allowable number of TTYs per entry.
	lib/port.h:#define	PORT_IDS	64
	lib/port.h:#define	PORT_TTY	64

-  strpbrk(3) found a ':', which signals the end of the comma-sepatated
   list, and the start of the next colon-separated field.

If the first character in the remainder of the string is not a ':', it
means we've exhausted the array size, but the CSV list was longer, so
we'd be truncating it.  Consider the entire line invalid, and skip it.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-06 07:44:02 -05:00
Alejandro Colomar
c3f97e251e lib/port.c: getportent(): Make sure there are at least 2 ':' in the line
Otherwise, the line is invalidly formatted, and we ignore it.

Closes: <https://github.com/shadow-maint/shadow/issues/1036>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-06 07:44:02 -05:00
Alejandro Colomar
f1f82c2105 lib/port.c: getportent(): Remove obvious comments
And do some style changes on the corresponding code.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-06 07:44:02 -05:00
Alejandro Colomar
e790993c5d lib/port.c: getportent(): Rename goto label
This label means we detected a bogus line, and want to skip it and jump
to the next one; rename it accordingly.  'again' seemed to say that it
was somehow looping on the same line.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-06 07:44:02 -05:00
Alejandro Colomar
bf84b3a855 lib/port.c: getttyuser(): Use goto to break out of nested loops
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-06 07:44:02 -05:00
Alejandro Colomar
a4b91048e9 lib/port.c: getttyuser(): Remove dead code
port.pt_names cannot be NULL; it always points to the static array ttys.

$ grep -rn pt_names
lib/port.c:157:	port.pt_names = ttys;
lib/port.c:159:		port.pt_names[j] = cp;
lib/port.c:172:	port.pt_names[j] = NULL;
lib/port.c:344:		for (i = 0; NULL != port->pt_names[i]; i++) {
lib/port.c:345:			if (portcmp (port->pt_names[i], tty) == 0) {
lib/port.c:350:		if (port->pt_names[i] == 0) {
lib/port.h:39: *	pt_names - pointer to array of device names in /dev/
lib/port.h:45:	char **pt_names;

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-06 07:44:02 -05:00
Alejandro Colomar
53ea42e67f contrib/adduser.c: main(): Use strcpy/cat(3) instead of their pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-03 10:03:12 -05:00
Alejandro Colomar
59e5eef38f contrib, lib/, src/, tests/: Use stpcpy(3) instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-03 10:03:12 -05:00
Alejandro Colomar
c6018240f8 lib/, src/: Use strrspn() instead of its pattern
This requires changing isspace(3) calls to an explicit accept string,
and I chose " \t\n" for it (as is done in other parts of this project),
which isn't exactly the same, but we probably don't want other
isspace(3) characters in those files, so it should work.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-03 10:03:12 -05:00
Alejandro Colomar
7c9da42db0 lib/sssd.c: Style fixes
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-03 10:03:12 -05:00
Alejandro Colomar
813c3ec6c5 src/login_nopam.c: login_access(): Simplify, calling strchr(3)
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-03 10:03:12 -05:00
Alejandro Colomar
9174697469 lib/getdef.c: def_load(): Use stp[c]spn() instead of their patterns
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-03 10:03:12 -05:00
Alejandro Colomar
2fcf520184 lib/string/strchr/: stp[c]spn(), strrspn(), strnul(): Add macros and functions
Often, a pointer is more useful than a length when calling these.

Link: <https://docs.oracle.com/cd/E86824_01/html/E54769/strrspn-3gen.html>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-03 10:03:12 -05:00
Alejandro Colomar
b38ee0c6d0 src/chage.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
ab9f4da83f src/faillog.c: Simplify, by calling str2sh() 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
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
e341291f99 src/passwd.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
b178fed180 src/useradd.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
ebdeb8f22a src/: Use get_[ug]id() where appropriate
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
a11ae5cf29 lib/shadow.c: my_sgetspent(): Simplify error handling
Handle negative values as errors from a2sl(), and reuse its
error-handling code.

Cc: Iker Pedrosa <ipedrosa@redhat.com>
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
7e754cc447 lib/shadow.c: my_sgetspent(): Remove dead code
spwd.sp_flag is an unsigned long, which can never be negative.

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
e9cc053df7 lib/shadow.c: my_sgetspent(): Merge 'else {if}' into 'else if'
This reduces indentation.

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
326bdfe70b lib/sgetspent.c: sgetspent(): 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
03521bccce lib/limits.c: setup_limits(): Simplify, by calling str2i(mode_t, ) instead of str2ul()
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
3fd1d62e29 lib/limits.c: setup_limits(): Simplify, by calling str2si() 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
312c3b1389 lib/limits.c: setup_limits(): Simplify, by calling a2si() 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
169cbe1f56 lib/limits.c: set_umask(): Simplify, by calling str2i(mode_t, ) instead of str2ul()
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
dba5600cef lib/limits.c: set_prio(): Simplify, by calling str2si() 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
5f2055c395 lib/getdef.c: getdef_long(): 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
45d4472c92 lib/getdef.c: getdef_unum(): Fix wrong limit check
The limit, since it's an unsigned int, should have been UINT_MAX, not
INT_MAX.  By calling a2ui() we can fix that and simplify too.

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
9415ce4a14 lib/getdef.c: getdef_num(): Simplify, by calling a2si() 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
866d911655 Remove groups(1)
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-02 13:32:13 -05:00
Alejandro Colomar
c7981fdd00 Remove id(1)
Distributions use id(1) from GNU coreutils or BusyBox.  Drop ours.

Closes: <https://github.com/shadow-maint/shadow/issues/1005>
Suggested-by: dkwo <nicolopiazzalunga@gmail.com>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Michael Vetter <jubalh@iodoru.org>
Cc: Sam James <sam@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-02 13:32:13 -05:00
Alejandro Colomar
379e9c32f7 lib/idmapping.c: Use long constants in prctl(2), and remove 0s
The prctl(2) system-call wrapper is implemented as a variadic function.
This makes it important to pass arguments to it of the right type (and
more importantly of the right width), to avoid undefined behavior.

While at it, check errors with ==-1, not <0, which is more explicit.

Also, PR_SET_KEEPCAPS(2const) doesn't need all arguments, so it can be
called with just two of them; remove unnecessary 0s.

See-also: prctl(2), PR_SET_KEEPCAPS(2const)
Link: <https://lore.kernel.org/linux-man/ddbdyaiptesjalgfmztxideej67e3yaob7ucsmbf6qvriwxiif@dohhxrqgwhrf/T/#med306b5b003f9cc7cc2de69fcdd7ee2d056d0954>
Cc: Xi Ruoyao <xry111@xry111.site>
Cc: Lukas Slebodnik <lslebodn@fedoraproject.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-02 13:12:22 -05:00
Alejandro Colomar
060b0849a6 lib/attr.h: Use C23-style attributes
They're stricter.  The GNU attributes are too lazy, and can be misused
more easily.  Also, mixing both has its own problems.

Link: <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108796>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
4eed3e84a1 lib/gshadow.c: Use XREALLOC() instead of silently continuing on ENOMEM
We should do better, and correctly handle errors, since this is library
code.  However, I'm lazy right now, so let's die hard, and let us
improve this later.

Link: <https://github.com/shadow-maint/shadow/pull/991#discussion_r1660308154>
Reported-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
53e1eb4045 src/: Remove dead code
FIRST_MEMBER_IS_ADMIN was never enabled.  And BTW, that code had been
broken for a long time, so probably nobody should manually enable it.

Link: <https://github.com/shadow-maint/shadow/pull/991#discussion_r1660308748>
Reported-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
ba3a51e90f lib/: Use [[gnu::alloc_size(...)]] on allocation functions
Suggested-by: Martin Uecker <uecker@tugraz.at>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
5111e5ed1b lib/: Use multi-line macro definitions
This reduces the complexity of those nested parentheses.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05: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
883bf71fc8 lib/alloc.[ch]: xmalloc(): Remove unused function
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
2cf73c99a6 lib/string/strcpy/zustr2stp.[ch], tests/: Remove ZUSTR2STP()
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
85a2f36992 src/logoutd.c: Use STRNCAT() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
cb3e2fbdcf src/logoutd.c: Use STRNDUPA() instead of its pattern
STRNDUPA() is equivalent to automatic storage allocation (alloca(3))
+ ZUSTR2STP().

The benefits of this refactor are:

-  The allocation size is always correct, and needs no comments, since
   it's now automatically calculated by the macro.

-  STRNDUPA() is probably more familiar, since
   -  strndupa(3) is a libc function,
   -  STRNDUPA() is the obvious wrapper that
      calculates the size based on the input array.

-  We can remove ZUSTR2STP().

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
ac591763fe src/newusers.c: Exit on ENOMEM, by calling xstrdup() instead of strdup(3)
The program was happily ignoring ENOMEM errors.

Fixes: 7f9e196903 ("* NEWS, src/newusers.c, src/Makefile.am: Added support for")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
103ffc5b1d lib/utmp.c: prepare_utmp(): Use xstrdup() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
3c09e40a1f lib/utmp.c: Use XSTRNDUP() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
2a0c0dd24b lib/string/strdup/: XSTRNDUP(), STRNDUPA(): Add macros
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
9a9faf86f0 lib/string/strcpy/strncat.[ch]: STRNCAT(): Add macro
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
44ba094766 src/groupmems.c: Fix number of elements in allocation
We are setting `sgrent.sg_adm[1] = NULL;`, so we need 2 elements.

Fixes: 87b56b19fb ("* NEWS, src/groupmems.c, man/groupmems.8.xml: Added support for [...]")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
c287317075 lib/gshadow.c: build_list(): Fix REALLOC() nmemb calculation
Fixes: efbbcade43 ("Use safer allocation macros")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
056f1d03ee lib/gshadow.c: build_list(): Fix forever loop on ENOMEM
Before this patch, the function looped while (s != NULL && *s != '\0').
However, nothing was modifying that string if REALLOC() failed, so the
loop was forever.

Fixes: 8e167d28af ("[svn-upgrade] Integrating new upstream version, shadow (4.0.8)")
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
8176e309ed src/useradd.c: tallylog_reset(): Use Basename() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
964df6ed6e lib/, src/: Use strchrnul(3) instead of its pattern
In the files where #include <string.h> is missing, add it, and sort the
includes.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
077f7b6ade lib/commonio.c: commonio_open(): MALLOC() and REALLOCF() already set ENOMEM
We don't need to set ENOMEM on failure of those functions.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
d611d1a947 lib/: Use REALLOCF() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
23663a1607 lib/, src/: Add missing include
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
bdf00dca44 lib/failure.c: failprint(): Remove dead code
This should have gone into the #else'd branch in 8451bed8b0, and
should have been removed in 3e602b58a2.

Fixes: 8451bed8b0 ("[svn-upgrade] Integrating new upstream version, shadow (4.0.13)")
Fixes: 3e602b58a2 ("Remove HAVE_STRFTIME ifdefs")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
bfb6aad7cb lib/, src/: Always pass NULL to time(2)
See time(2):

BUGS
     Error returns from this system  call  are  indistinguishable  from
     successful  reports  that  the  time  is  a few seconds before the
     Epoch, so the C library wrapper function never sets errno as a re‐
     sult of this call.

     The tloc argument is obsolescent and should always be NULL in  new
     code.  When tloc is NULL, the call cannot fail.

Fixes: 45c6603cc8 ("[svn-upgrade] Integrating new upstream version, shadow (19990709)")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
761eb07016 lib/getdate.y: NULL doesn't need a cast
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
2cb3deec72 lib/shadow.c: my_sgetspent(): Clarify that we're assigning an empty string
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
5e11e89fd9 lib/, src/: Reduce scope of local variables
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
847a19e7a3 src/login.c: Remove dead code
The functions that set these strings --do_rlogin() and login_prompt()--
make sure to terminate them with a NUL.

Fixes: 3704745289 ("* lib/defines.h: Define USER_NAME_MAX_LENGTH, based on utmp and [...]")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
e5d40a1863 src/logoutd.c: Remove unused variable
wait(2) accepts NULL if the status won't be read.  Simplify.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
89402f5171 src/su.c: save_caller_context(): Remove unused parameter
Fixes: e6c2e43937 ("Hardcoding Prog to known value")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-07-01 21:40:11 -05:00
Alejandro Colomar
40ab806066 lib/string/strcpy/, lib/, src/, tests/: Move all copying APIs to a subdirectory
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
89e4be3957 src/get_subid_owners.c: Use uid_t for holding UIDs (and GIDs)
Suggested-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
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
7f3ab84714 lib/limits.c: setrlimit_value(): Reimplement in terms of a2i()
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
6093c93e81 lib/get_uid.c: get_uid(): Reimplement in terms of a2i()
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
b198c1e782 lib/get_pid.c: get_pidfd_from_fd(): Don't open-code get_fd()
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
a80715448b lib/atoi/getnum.[ch]: get_fd(): Add function for parsing a file descriptor from a string
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
1557fac0a5 lib/: get_pid(): 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
6fd56468c3 lib/get_pid.c: get_pid(): Reimplement in terms of a2i()
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
509e3bcbf8 lib/: Don't open-code get_gid()
These functions were open-coding get_gid().  Use the actual function.

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
f85a07f140 lib/, libsubid/, po/, src/: get_gid(): 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
74a2ed4537 lib/get_gid.c: get_gid(): Reimplement in terms of a2i()
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
678c2a23ee src/: Use str2[u]l() instead of atoi(3)
atoi(3) easily triggers Undefined Behavior.  Replace it by str2[u]l(),
which are safe from that, and add type safety too.

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
24695e6f38 tests/unit/test_typetraits.c: Add tests for typetraits.h macros
Suggested-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
500ec3f8f3 lib/typetraits.h: Add macros that give information about a type
In the case of is_unsigned() and is_signed(), the natural thing would be
to compare to 0:

	#define is_unsigned(x)  (((typeof(x)) -1) > 0)
	#define is_signed(x)    (((typeof(x)) -1) < 0)

However, that would trigger -Wtype-limits, so we compare against 1,
which silences that, and does the same job.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-06-29 20:00:18 +02:00
Serge Hallyn
2457fc7c6b tests/run_some: make sure unshared root user can descend build dir
This was causing errors in my local testing in vms.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-06-28 14:45:25 -05:00
Alejandro Colomar
488bf4a519 Makefile.am: Use 'dist-hook' to clean up <tests/unit/Makefile>
Closes: <https://github.com/shadow-maint/shadow/issues/1027>
Reported-by: Chris Hofstaedtler <zeha@debian.org>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Co-developed-by: Serge Hallyn <shallyn@cisco.com>
Signed-off-by: Serge Hallyn <shallyn@cisco.com>
Co-developed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-06-28 09:37:27 -05:00
Serge Hallyn
75ea679799 have_range: open the subid db if needed
When we run for instance

  check_subid_range ubuntu u 100000 65536

when ubuntu user is defined and has that range, it returns no entries
because the subid db is not opened.  Open it in have_range if needed.

I haven't figured out why this ever worked.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-06-28 16:16:33 +02:00
Serge Hallyn
81b5b26925 libsubid test makefile: fix a typo
Fix a missing space after the -I path

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-06-28 16:16:33 +02:00
Alejandro Colomar
6e57238bf9 tests/unit/test_xasprintf.c: Fix use of volatile pointer
volatile needs to be casted away behind a [[gnu::noipa]] function, to
make that invisible to the compiler.  Otherwise, the compiler can see
that it is being discarded, and is free to abuse Undefined Behavior.

Closes: <https://github.com/shadow-maint/shadow/issues/1028>
Reported-by: Chris Hofstaedtler <zeha@debian.org>
Tested-by: Chris Hofstaedtler <zeha@debian.org>
Reviewed-by: Chris Hofstaedtler <zeha@debian.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-06-28 08:57:01 -05:00
Alejandro Colomar
3307a8f4f0 tests/unit/test_xasprintf.c: Cosmetic
This is in preparation for the following commit.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-06-28 08:57:01 -05:00
Serge Hallyn
d55367bb16 tests/: Support run_some from exported tarball
common/config.sh currently tries to find the top directory by looking
for .git.  There are also many places under tests/ where we use
hard-coded ../../.. to find things like ${TOP_DIR}/lib.

We don't actually ship the tests with 'make dist'.  So we will
be exporting tests/ as a separate tarball.  In particular, I want
to then import this in the debian package.  However, there it will
be under shadow.git/debian/tests, not shadow.git/tests.

To support this, accept the environment variable BUILD_BASE_DIR,
which should point to shadow.git.

An alternative would be to move the tests to their own git
tree.  However, keeping tests in separate git tree tends to
lead to repos getting out of sync.  And we'd still need to accept
something like BUILD_BASE_DIR.

Note there are a lot of tests under run-all, which I'm not converting
as they currently are not being run in CI, so I'm more likely to
break something.

Changelog:
  2024 05 26: Incorporate feedback from alejandro-colomar

Link: <https://salsa.debian.org/debian/shadow/-/merge_requests/21>
Link: <https://salsa.debian.org/debian/shadow/-/merge_requests/22>
Cc: Chris Hofstaedtler <zeha@debian.org>
Signed-off-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-06-26 23:59:07 +02:00
Alejandro Colomar
47edcd3045 lib/csrand.c: Fix the lower part of the domain of csrand_uniform()
I accidentally broke this code during an un-optimization.  We need to
start from a random value of the width of the limit, that is, 32 bits.

Thanks to Jason for pointing to his similar code in the kernel, which
made me see my mistake.

Fixes: 2a61122b5e ("Unoptimize the higher part of the domain of csrand_uniform()")
Closes: <https://github.com/shadow-maint/shadow/issues/1015>
Reported-by: Michael Brunnbauer <https://github.com/michaelbrunnbauer>
Link: <https://git.zx2c4.com/linux-rng/tree/drivers/char/random.c#n535>
Cc: "Jason A. Donenfeld" <Jason@zx2c4.com>
Link: <https://github.com/shadow-maint/shadow/pull/638>
Link: <https://github.com/shadow-maint/shadow/issues/634>
Link: <https://github.com/shadow-maint/shadow/pull/624>
Tested-by: Michael Brunnbauer <https://github.com/michaelbrunnbauer>
Reviewed-by: Michael Brunnbauer <https://github.com/michaelbrunnbauer>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-06-20 21:38:58 -05:00
Serge Hallyn
cde08e422d configure.ac: release 4.16.0
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-06-18 16:34:10 -05:00
Serge Hallyn
2df2c35bad release 4.16.0-rc1
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-06-13 21:24:10 -05:00
Serge Hallyn
9b7d786b6f configure.ac: specify tar-pax to avoid 99 char filename limit
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-06-13 21:24:10 -05:00
Alejandro Colomar
ca046af5d9 Remove support for rlogind in login(1), that is, remove the '-r' flag
The "quick hack" finally disappeared.  Probably nobody noticed.  ;)
(See the changes in <configure.ac> for the context of this pun.)

Probably everybody uses SSH these days for remote login.  Let's remove
this insecure method.

Closes: <https://github.com/shadow-maint/shadow/issues/992>
Reviewed-by: dkwo <nicolopiazzalunga@gmail.com>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: Michael Vetter <jubalh@iodoru.org>
Cc: Sam James <sam@gentoo.org>
Cc: Benedikt Brinkmann <datacobra@thinkbot.de>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-06-13 19:39:26 -05:00
Daniel Bershatsky
df59088641 libsubid: Fix code style issues 2024-06-12 21:45:31 +02:00
Daniel Bershatsky
b620b5d0d1 libsubid: Fail on plugin loading if no subid_free provided 2024-06-12 21:45:31 +02:00
Daniel Bershatsky
29dbcfbabd libsubid: Apply minor fixes 2024-06-12 21:45:31 +02:00
Daniel Bershatsky
0217516349 libsubid: Add routine to free allocated memory 2024-06-12 21:45:31 +02:00
Daniel Bershatsky
18f113cc46 libsubid: Dealocate memory on exit 2024-06-12 18:41:22 +02:00
lixinyun
10429edc14 src/groupmod.c: delete gr_free_members(&grp) to avoid double free
Groupmod -U may cause crashes because of double free. If without -a, the first free of (*ogrp).gr_mem is in gr_free_members(&grp), and then in gr_update without -n or gr_remove with -n.
Considering the minimal impact of modifications on existing code, delete gr_free_members(&grp) to avoid double free.Although this may seem reckless, the second free in two different positions will definitely be triggered, and the following two test cases can be used to illustrate the situation :

[root@localhost src]# ./useradd u1
[root@localhost src]# ./useradd u2
[root@localhost src]# ./useradd u3
[root@localhost src]# ./groupadd -U u1,u2,u3 g1
[root@localhost src]# ./groupmod -n g2 -U u1,u2 g1
Segmentation fault

This case would free (*ogrp).gr_mem in gr_free_members(&grp) due to assignment statements grp = *ogrp, then in if (nflg && (gr_remove (group_name) == 0)), which finally calls gr_free_members(grent) to free (*ogrp).gr_mem again.

[root@localhost src]# ./useradd u1
[root@localhost src]# ./useradd u2
[root@localhost src]# ./useradd u3
[root@localhost src]# ./groupadd -U u1,u2,u3 g1
[root@localhost src]# ./groupmod -U u1,u2 g1
Segmentation fault

The other case would free (*ogrp).gr_mem in gr_free_members(&grp) too, then in if (gr_update (&grp) == 0), which finally calls gr_free_members(grent) too to free (*ogrp).gr_mem again.

So the first free is unnecessary, maybe we can drop it.

Fixes: 342c934a35 ("add -U option to groupadd and groupmod")
Closes: <https://github.com/shadow-maint/shadow/issues/1013>
Link: <https://github.com/shadow-maint/shadow/pull/1007>
Link: <https://github.com/shadow-maint/shadow/pull/271>
Link: <https://github.com/shadow-maint/shadow/issues/265>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: lixinyun <li.xinyun@h3c.com>
2024-06-07 12:42:44 +02:00
Serge Hallyn
8acec35d1d man/lastlog: remove wrong use of keyword term
Per https://tdg.docbook.org/tdg/4.5/term, term is a word being
defined in a varlistentry.  The 'high uid' description is not a
varlistentry, so <term> and </term> show up in the processed
manpage.  See debian Bug#1072297.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-06-05 15:49:54 +02:00
Alejandro Colomar
69f74dbf8a lib/cast.h: const_cast(): Reimplement with _Generic(3)
This makes it much simpler and portable.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-06-04 09:10:23 +02:00
Iker Pedrosa
4e2453fa9f configure: move cmocka library detection
`PKG_CONFIG` variable needs to be set for `PKG_CHECK_MODULES` to
succeed, but this wasn't happening in Fedora because the first
appearance of `PKG_CHECK_MODULES` was conditionally skipped because this
distribution is compiled without `libbsd` support. Thus, moving the
cmocka library detection before libbsd fixes the problem.

Suggested-by: Lukas Slebodnik <lslebodn@fedoraproject.org>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2024-05-28 19:19:58 -05:00
Serge Hallyn
d0fef040ed tests: add the tests/ subdirectory to dist tarball
This is a first step to helping distributions to use our tests in CI.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-05-28 19:18:39 -05:00
Alejandro Colomar
71e28359d1 lib/atoi/strtou_noneg.[ch], tests/: strtoul_noneg(): Remove unused function
All call sites have been replaced by functions from "atoi/a2i.h" and
"atoi/str2i.h" recently.

Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-27 16:32:09 +02:00
Alejandro Colomar
f3a1e1cf09 src/check_subid_range.c: Call str2ul() instead of strtoul_noneg()
It is a simpler call, with more type safety.

A consequence of this change is that the program now accepts numbers in
bases 8 and 16.  That's not a problem here, I think.

Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-27 16:32:09 +02:00
Alejandro Colomar
fb49de61b7 lib/atoi/strtou_noneg.[ch], tests/: strtoull_noneg(): Remove unused function
All call sites were replaced by a2i() recently.

Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-27 16:32:09 +02:00
Alejandro Colomar
895dfd77d2 lib/gettime.c: gettime(): Call a2i() instead of strtoull_noneg()
time_t isn't necessarily unsigned (in fact, it's likely to be signed.
Therefore, parse the number as the right type, via a2i(time_t, ...).

Still, reject negative numbers, just to be cautious.  It was done
before (strtoull_noneg()), so it shouldn't be a problem.  (However,
strtoull_noneg() was only introduced recently, and before that we called
strtoull(3), which silently accepted negative values.)

Remove the limitation of ULONG_MAX, which seems arbitrary.  It probably
was written in times where 'time_t' had the same length of 'long', and
this was thus a test that the value didn't overflow 'time_t'.  Such a
test is implicit in the a2i() call, so forget about it.

Unify the error messages into a single one that provides all the info
(except the value of 'fallback').

Link: <cb610d54b4 (r136407772)>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Chris Lamb <lamby@debian.org>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-27 16:32:09 +02:00
Tianyu Chen
9dddcd29f1 STABLE.md: 4.15.x is now stable 2024-05-22 15:10:03 +02:00
Alejandro Colomar
a6eb312f60 src/login.c: main(): Use login_name_max_size()
Instead of raw sysconf(_SC_LOGIN_NAME_MAX) calls, which was being used
without error handling.

Fixes: 3b7cc05387 ("lib: replace `USER_NAME_MAX_LENGTH` macro")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-21 13:26:41 +02:00
Alejandro Colomar
99df9d746e lib/chkname.[ch]: login_name_max_size(): Add function
It encapsulates some logic that we may want to reuse elsewhere.

Link: <https://github.com/shadow-maint/shadow/pull/989>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-21 13:26:41 +02:00
Alejandro Colomar
27e467a61a lib/chkname.[ch]: Fix includes
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-21 13:26:41 +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
1ee066ae1e src/useradd.c: set_defaults(): Fix FILE* leak
Report:
> shadow-4.15.0/src/useradd.c:575:2: alloc_fn: Storage is returned from allocation function "fdopen".
> shadow-4.15.0/src/useradd.c:575:2: var_assign: Assigning: "ofp" = storage returned from "fdopen(ofd, "w")".
> shadow-4.15.0/src/useradd.c:734:2: leaked_storage: Variable "ofp" going out of scope leaks the storage it points to.
> 732|           }
> 733|
> 734|->         return ret;
> 735|   }
> 736|

Link: <https://issues.redhat.com/browse/RHEL-35383>
Reported-by: Iker Pedrosa <ipedrosa@redhat.com>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-18 01:15:10 +02:00
Alejandro Colomar
e7d1508e07 src/useradd.c: Add fmkstemp() to fix file-descriptor leak
This function creates a temporary file, and returns a FILE pointer to
it.  This avoids dealing with both a file descriptor and a FILE pointer,
and correctly deallocating the resources on error.

The code before this patch was leaking the file descriptor if fdopen(3)
failed.

Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-18 01:15:10 +02:00
Alejandro Colomar
a74c4b6ae1 src/useradd.c: De-duplicate code
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-18 01:15:10 +02:00
Alejandro Colomar
701fe4cf1a src/useradd.c: set_defaults(): Do not free(3) the result of asprintf(3) if it failed
See asprintf(3):

RETURN VALUE
     When successful,  these  functions  return  the  number  of  bytes
     printed, just like sprintf(3).  If memory allocation wasn’t possi‐
     ble,  or  some other error occurs, these functions will return -1,
     and the contents of strp are undefined.

Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-18 01:15:10 +02:00
Alejandro Colomar
37ae8827a0 src/useradd.c: set_defaults(): Rename goto label
This will help add other labels in the following commits.

Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-18 01:15:10 +02:00
Alejandro Colomar
f8fc6371f6 src/useradd.c: set_defaults(): Fix order of clean-ups
Resources should be freed in the inverse order of the allocation.
This refactor prepares for the following commits, which fix some leaks.

Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-18 01:15:10 +02:00
Iker Pedrosa
4c16416ebc port: fix OVERRUN (CWE-119)
```
shadow-4.15.0/lib/port.c:154:2: alias: Assigning: "port.pt_names" = "ttys". "port.pt_names" now points to element 0 of "ttys" (which consists of 65 8-byte elements).
shadow-4.15.0/lib/port.c:155:2: cond_const: Checking "j < 64" implies that "j" is 64 on the false branch.
shadow-4.15.0/lib/port.c:175:2: overrun-local: Overrunning array of 65 8-byte elements at element index 65 (byte offset 527) by dereferencing pointer "port.pt_names + (j + 1)".
173|           *cp = '\0';
174|           cp++;
175|->         port.pt_names[j + 1] = NULL;
176|
177|           /*
```

Resolves: https://issues.redhat.com/browse/RHEL-35383

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
2024-05-17 16:08:26 +02:00
Alejandro Colomar
0066743c49 lib/getrange.c: getrange(): Report an error when min>max
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-17 15:40:03 +02:00
Alejandro Colomar
29f135777e lib/getrange.c: getrange(): Add missing cast
isdigit(3) requires a cast if the argument is of type 'char'.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-17 15:40:03 +02:00
Alejandro Colomar
34f431f607 lib/getrange.c: getrange(): Add const to pointer
Now that we have const-generic macros, we can use a const pointer.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-17 15:40:03 +02:00
Alejandro Colomar
040ba6a853 lib/getrange.c: getrange(): Use a2ul() instead of strtoul_noneg()
It simplifies the error checking.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-17 15:40:03 +02:00
Alejandro Colomar
b0498564b2 lib/atoi/a2i.[ch]: Add const-generic macros
These overloaded macros allow passing either a const or a non-const
endp, and will call the appropriate function.  This kind of const
overloading has prior art in C23's string functions, such as memchr(3).

Martin suggested using an artificial function pointer in _Generic(3); it
allows switching on various types at the same time.

Also add a comment referring to liba2i's PDF manual for documentation.

Link: <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf#subsubsection.7.26.5.2>
Link: <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114731>
Link: <http://www.alejandro-colomar.es/share/dist/liba2i/git/HEAD/liba2i-HEAD.pdf>
Co-developed-by: Martin Uecker <muecker@gwdg.de>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-17 15:40:03 +02:00
Alejandro Colomar
26c9dd3715 lib/alloc.h: Reimplement [X]REALLOC[F]() macros with _Generic(3)
Instead of GNU builtins and extensions, these macros can be implemented
with C11's _Generic(3), and the result is much simpler (and safer, since
it's now an error, not just a warning).

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-15 12:08:00 +02:00
Frans Spiesschaert
18ecf3987e updated Dutch translation 2024-05-09 14:25:19 +02:00
Iker Pedrosa
9b3889696b man: update translations for username length
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
2024-05-09 10:56:27 +02:00
Iker Pedrosa
03c31bef87 man: update username length
Fixes: 6a1f45d932 ("lib/chkname.c: Support unlimited user name lengths")
Related-To: https://github.com/shadow-maint/shadow/pull/986

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
2024-05-09 10:56:27 +02:00
Alejandro Colomar
98aefe8772 lib/, src/: Rename some local variables
'endptr' is appropriate internally in strtol(3) because it's a pointer
to 'end', and 'end' itself is a pointer to one-after-the-last character
of the numeric string.  In other words,

	endptr == &end

However, naming the pointer whose address we pass to strtol(3)'s
'endptr' feels wrong, and causes me trouble while parsing the code; I
need to double check the number of dereferences, because something feels
wrong in my head.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-04 17:22:57 -05:00
Alejandro Colomar
f40bd94856 lib/getrange.c: getrange(): Use goto to deduplicate code
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-04 17:22:57 -05:00
Alejandro Colomar
7af7361fd6 lib/getrange.c: getrange(): Return early
It's doesn't make much sense to break from a switch() just to return.
Let's return early, to simplify.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-04 17:22:57 -05:00
Alejandro Colomar
bbb2735cc0 lib/getrange.c: getrange(): Return early to reduce indentation
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-04 17:22:57 -05:00
Alejandro Colomar
d7ab811a36 lib/getrange.c: getrange(): Don't else after return
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-04 17:22:57 -05:00
Alejandro Colomar
62a4daa2cd lib/getrange.c: getrange(): Return early to remove an else
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-04 17:22:57 -05:00
Alejandro Colomar
8d8062c770 lib/getrange.c: getrange(): Remove temporary variable
This means we set the pointees on error, which we didn't do before, but
since we return -1 on error and ignore (don't use) the pointees at call
site, that's fine.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-04 17:22:57 -05:00
Alejandro Colomar
38a0b0a610 lib/getrange.c: getrange(): Small refactor
All 3 non-error paths in the second part resulted in *has_min = true.
Set in once before the switch(), to simplify.

This means we set this variable on error, which we didn't do before,
but since we return -1 on error and ignore (don't use) the pointees at
call site, that's fine.

Also, move a couple of *has_max = true statements to before a comment,
in preparation for future commits.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-04 17:22:57 -05:00
Alejandro Colomar
6bf5d6d4f3 lib/getrange.c: getrange(): Small refactor
Set *has_{min,max} = false at the begining, so we only need to set them
to true later.

This means we set these variables on error, which we didn't do before,
but since we return -1 on error and ignore (don't use) the pointees at
call site, that's fine.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-05-04 17:22:57 -05:00
Iker Pedrosa
dbd3527c03 share/containers: update build flags for fedora 40
libpam is enabled to provide `passwd` binary from this package, as there
are several password quality checks that are enabled through a PAM
module. Same reason to disable account-tools-setuid.

sssd is disabled because `files provider` has been removed in sssd, and
the underlying functionality in shadow isn't needed anymore.

libcrack dependency was disabled some time ago, but the upstream repo
wasn't updated. Doing it now.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
2024-05-02 10:45:03 +02:00
Iker Pedrosa
dbf3b1ad51 share/containers: sort configuration options
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
2024-05-02 10:45:03 +02:00
Iker Pedrosa
b8f17f9c29 share/containers: fix indentation in fedora
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
2024-05-02 10:45:03 +02:00
Serge Hallyn
2e01b9d7d2 newuidmap and newgidmap manpages: fix fd description
The manpages for newuidmap and newgidmap had a typo "[pid[" instead
of "[pid]".  They were also unclear about what the /proc/pid fd should
be.  Fix both.

Closes #977

Reported-by: igo95862@yandex.ru
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-04-10 09:18:40 +02:00
Tobias Stoeckmann
5f5b21fd5c lib/env.c: treat out of memory condition as error
If not enough memory is available for more environment variables, treat
it exactly like not enough memory for new environment variable content.

Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-04-04 20:12:03 +02:00
Alejandro Colomar
f7fe4c5978 lib/atoi/: a2*(), str2*(): Add variants for other types
And type-generic macros that wrap them: a2i(), str2i()

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-29 14:29:13 -05: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
b085c3f612 lib/atoi/: Add a2[su]l() and reimplement get[u]long() in terms of them
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
Serge Hallyn
dc12e87fe7 configure.ac: release 4.15.1
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-03-23 18:33:45 -05:00
Alejandro Colomar
4827da0a2f src/login.c: Use localtime_r(3) instead of localtime(3)
This silences a CodeQL warning.  We don't care about reentrancy, but
after this patch we don't need to break a long line, so that's a win.

Reviewed-by: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-24 00:16:00 +01:00
Alejandro Colomar
0460dac019 lib/, src/: Use STRFTIME() instead of its pattern
Reviewed-by: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-24 00:16:00 +01:00
Alejandro Colomar
b3affb29cf lib/string/strftime.[ch]: STRFTIME(): Add macro
This macro makes sure that the first argument is an array, and
calculates its size.

Reviewed-by: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-24 00:16:00 +01:00
Serge Hallyn
0b3d017276 man/Makefile.am: ship config.xml
Other man/*.xml's import it, so they need it shipped as well.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-03-23 16:39:07 -05:00
Serge Hallyn
e08db2de4c man/po/Makefile.in: avoid unnecessary changes to git indexed files
Keep pot creation date out of our po files when we compare them.
Otherwise, we always think they need to be updated.

We prepend a line '# To re-generate, ....' to the shadow-man-pages.pot
file.  Do that before we compare the new candidate, because right
now our comparison to see if we've made changes always thinks we have.

Put some of the tempfiles in a mktemp -d'd directory, which we remove when
all's done.  This keeps the working tree cleaner.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-03-23 16:39:07 -05:00
Serge Hallyn
55c107617e update translations
Update .po and .pot files to reflect some changes in print
statements.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-03-23 16:39:07 -05:00
Serge Hallyn
673ff74fd4 Makefile.am: clean some tempfiles
Add some temporary files to CLEANFILES

Put test-driver in .gitignore

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-03-23 16:39:07 -05:00
Serge Hallyn
ead55e9ba8 getdef: avoid spurious error messages about unknown configuration options
def_find can return NULL for unset, not just unknown, config options.  So
move the decision of whether to log an error message about an unknown config
option back into def_find, which knows the difference.  Only putdef_str()
will pass a char* srcfile to def_find, so only calls from putdef_str will
cause the message, which was the original intent of fa68441bc4.

closes #967

fixes: fa68441bc4 ("Improve the login.defs unknown item error message")
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-03-21 11:21:33 +05:30
Enrico Scholz
000619344d lib/copydir:copy_entry(): use temporary stat buffer
There are no guarantees that fstatat() does not clobber the stat
buffer on errors.

Use a temporary buffer so that the following code sees correct
attributes of the source entry.

Issue #973

Signed-off-by: Enrico Scholz <enrico.scholz@sigma-chemnitz.de>
2024-03-21 02:44:12 +01:00
Antoine Roux
51a0d94a08 Fix wrong french translation
32 characters were wrongly translated to 16 in french translation file
2024-03-20 09:58:51 +05:30
Eli Schwartz
e44a9e631d gitignore: add a few more generated files to be ignored
before this, the following untracked files showed up in `git status`:

	lib/atoi/.dirstamp
	lib/string/.dirstamp
	lib/time/.dirstamp
	man/da/login.defs.d
	man/da/messages.mo
	man/de/login.defs.d
	man/de/messages.mo
	man/fr/login.defs.d
	man/fr/messages.mo
	man/it/login.defs.d
	man/it/messages.mo
	man/pl/login.defs.d
	man/pl/messages.mo
	man/ru/login.defs.d
	man/ru/messages.mo
	man/sv/login.defs.d
	man/sv/messages.mo
	man/uk/login.defs.d
	man/uk/messages.mo
	man/zh_CN/login.defs.d
	man/zh_CN/messages.mo
	test-driver

Signed-off-by: Eli Schwartz <eschwartz93@gmail.com>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
2024-03-18 17:06:07 -05:00
Samanta Navarro
2b67dc7765 lib/pam_pass_non_interactive.c: use strzero/free
The combination of bzero and free could be optimized away.

Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2024-03-14 17:20:30 -05:00
Alejandro Colomar
fce1d88479 lib/list.c: is_on_list(): Call strsep(3) instead of open-coding it
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 17:11:36 -05:00
Alejandro Colomar
46fd68c37e lib/list.c: is_on_list(): Move break condition to loop controlling expression
This change executes `i++` one more time before breaking, so we need to
update the `i+1` after the loop to just `i`.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 17:11:36 -05:00
Alejandro Colomar
fb01e07e83 lib/list.c: is_on_list(): Move code out of loop
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 17:11:36 -05:00
Alejandro Colomar
08ae38e394 lib/list.c: is_on_list(): Remove unnecessary use of temporary variable
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 17:11:36 -05:00
Alejandro Colomar
34b113baba lib/sgetspent.c: sgetspent(): Explicitly use an empty string literal
cp can only be an empty string literal in that conditional.  Use a
string literal to be more explicit.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 17:11:36 -05:00
Alejandro Colomar
93151689c0 lib/sgetspent.c: sgetspent(): Use NULL instead of 0 to mean a null pointer constant
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 17:11:36 -05:00
Alejandro Colomar
ae17e0291d lib/port.c: getportent(): Call strpbrk(3) instead of open-coding it
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 17:11:36 -05:00
Alejandro Colomar
03677d9acf lib/: Call strsep(3) instead of open-coding it
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 17:11:36 -05:00
Alejandro Colomar
5f8f19f267 lib/: Call strchrnul(3) instead of open-coding it
Performance tests made in 2007 are obsolete.  We should assume libc is
reasonably fast today (otherwise, report a bug to libc).

$ git blame -- lib/sgetgrent.c | grep strchr
45c6603cc (nekral-guest      2007-10-07 11:44:02 +0000  30)  *	WARNING: I profiled this once with and without strchr() calls
6f88bcf58 (nekral-guest      2008-05-26 08:31:14 +0000  97) 		cp = strchr (cp, ':');

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 17:11:36 -05:00
Alejandro Colomar
bed18501b1 lib/, src/: Call gmtime_r(3) instead of gmtime(3)
It's trivial to do the change, and it removes a CodeQL warning.
We don't need to be reentrant, but it doesn't hurt either.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 16:30:46 -05:00
Alejandro Colomar
8fcf6cccff lib/time/day_to_str.[ch]: day_to_str(): Accept a day instead of a date, and rename function
It was always being called with 'day * DAY', so do that internally and
simplify.  This grabs some code from print_day_as_date().

Cc: Tobias Stoeckmann <tobias@stoeckmann.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 16:30:46 -05:00
Alejandro Colomar
8fee869e9a src/passwd.c: print_status(): Fix typo (bogus use of the comma operator)
Amazing that this triggered no warnings at all.

Fixes: 355ad6a9e0 ("Have a single definition of date_to_str()")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 16:30:46 -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
19edb06fd2 lib/time/day_to_str.h: DAY_TO_STR(): Add macro
This macro ensures that the buffer is an array, and calculates the size.

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
88760598f0 src/sulogin.c: Invert logic to reduce indentation
Also, it was checking for >=0 for success, but since that code is for
opening a different tty as stdin, that was bogus.  But since it's
guaranteed to be either 0 or -1, this commit doesn't add any code to
make sure it's 0 (i.e., we could say !=0 instead of ==-1).  That's more
appropriate for a different commit.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 16:16:15 -05:00
Alejandro Colomar
efd169e010 lib/, src/: Use int main(void) where appropriate
Remove /*ARGSUSED*/ comments.  Instead, use appropriate declarators for
main().  ISO C allows using int main(void) if the parameters are going
to be unused.

Also, do some cosmetic changes in the uses of argc and argv, to show
where they are used.

And use *argv[], instead of **argv.  Array notation is friendlier, IMO.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 16:16:15 -05:00
Alejandro Colomar
da440b536c lib/: Clean up after previous removal of dead code
Just cosmetic changes.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 16:12:51 -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
Alejandro Colomar
ae3d71fb94 src/passwd.c: Don't print the program name twice in a log entry
OPENLOG() already sets the program name as the prefix.

This resulted in entries like:

$ journalctl 2>/dev/null | grep passwd
Mar 03 01:09:47 debian passwd[140744]: passwd: can't view or modify password information for root

Fixes: 8e167d28af ("[svn-upgrade] Integrating new upstream version, shadow (4.0.8)")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-14 16:01:32 -05:00
ed neville
4959cd10ae Noting copy_symlink behaviour
Mention that symlinks are modified when they prefix the skel directory.

Closes #933
2024-03-14 15:53:33 -05:00
Alejandro Colomar
a3cae72faa share/containers/, .github/workflows/: Don't make(1) twice
It was being done so that the second one prints errors without races.
However, the same thing can be achieved by passing -Orecurse to make(1).

And this makes the logs even more readable, since there's no racy output
at all.

Fixes: 97f79e3b27 ("CI: Make build logs more readable")
Link: <https://github.com/shadow-maint/shadow/pull/702>
Link: <https://github.com/nginx/unit/pull/1123>
Acked-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Andrew Clayton <a.clayton@nginx.com>
Cc: Konstantin Pavlov <thresh@nginx.com>
Cc: Dylan Arbour <https://github.com/arbourd>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-13 11:05:36 -05:00
Alejandro Colomar
26deef6945 lib/idmapping.c: get_map_ranges(): Merge two input checks into a simpler one
Previously, we were performing the following two checks:

-       if (ranges != ((argc + 2) / 3)) {
-       if ((ranges * 3) > argc) {

Let's draw a table of the possible input that would pass the first check:

argc:	0 1 2 3 4 5 6 7 8 9
rng:	0 1 1 1 2 2 2 3 3 3
a+2/3*3:0 3 3 3 6 6 6 9 9 9	<-- this is  roundup(argc, 3);
a+2/3:	0 1 1 1 2 2 2 3 3 3	<-- this is  roundup(argc, 3) / 3;
rng*3:	0 3 3 3 6 6 6 9 9 9

From those, let's extract those that would also pass the second check:

argc:	0     3     6     9
rng:	0     1     2     3
rng*3:	0     3     6     9

We can see that there's a simple check for this input:

+       if (ranges * 3 != argc) {

As a sanity check, let's draw a table of the acceptable input with that
check:

rng:	0     1     2     3
rng*3:	0     3     6     9
argc:	0     3     6     9

Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-13 10:55:00 -05:00
Skyler Ferrante
d2f2c1877a Adding checks for fd omission
Adding function check_fds to new file fd.c. The function check_fds
should be called in every setuid/setgid program.

Co-developed-by: Alejandro Colomar <alx@kernel.org>
2024-03-10 19:56:40 -05:00
Alejandro Colomar
b76fc2947f tests/unit/test_zustr2stp.c: Test ZUSTR2STP()
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-10 19:55:39 -05:00
Alejandro Colomar
ffb3992467 lib/string/zustr2stp.[ch]: Remove zustr2stp(); keep ZUSTR2STP()
The function should never be used; it's always used via its wrapper
macro.  To simplify, and reduce chances of confusion: remove the
function, and implement the macro directly in terms of
stpcpy(mempcpy(strnlen())).

Update the documentation, and improve the example, which was rather
confusing.

Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-10 19:55:39 -05:00
Serge Hallyn
ba43b49a52 configure.ac: Release 4.15.0
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-03-08 16:04:59 -06:00
Alejandro Colomar
89c4da43cb src/vipw.c: Use string literals to initialize 'Prog'
This avoids using argv[0], which is controlled by the user,
and might inject arbitrary text in stderr and the logs.

Link: <https://github.com/shadow-maint/shadow/issues/959>
Link: <https://github.com/shadow-maint/shadow/pull/960>
Cc: "Skyler Ferrante (RIT Student)" <sjf5462@rit.edu>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: Karel Zak <kzak@redhat.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Christian Brauner <christian@brauner.io>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-08 10:24:15 -06:00
Alejandro Colomar
0ab893a734 src/vipw.c: Reverse logic and variable name
Since we're checking for "vigr", it makes more sense to name the
variable accordingly.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-08 10:24:15 -06: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
Alejandro Colomar
d13844408c share/containers/: trap(1) to see the cmocka logs
Reviewed-by: "Serge E. Hallyn" <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-04 01:43:25 +01:00
Alejandro Colomar
e59a39663d share/containers/: Specify one argument per line
Reviewed-by: "Serge E. Hallyn" <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-04 01:43:25 +01:00
Alejandro Colomar
a14936cf2e .github/workflows/runner.yml: trap(1) to see the testsuite log
Otherwise, 'cat testsuite.log' isn't run, since 'set -e' aborts the
script earlier.

Reviewed-by: "Serge E. Hallyn" <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-03-04 01:43:25 +01:00
Serge Hallyn
959343fe79 configure.ac: release 4.15.0-rc3
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-02-29 19:51:37 -06:00
Alejandro Colomar
1af6b68cbe lib/utmp.c: Use the appropriate autotools macros for struct utmpx
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>
2024-02-21 15:43:25 +01:00
Alejandro Colomar
2806b827d8 lib/utmp.c: Use defined() instead of #if[n]def
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-21 15:43:25 +01:00
Alejandro Colomar
7e94a2f484 lib/utmp.c: Remove #endif comments
Indentation makes it clear which is which.

Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-21 15:43:25 +01:00
Alejandro Colomar
e5815acf37 lib/utmp.c: Merge preprocessor conditionals
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-21 15:43:25 +01:00
Alejandro Colomar
f4ea04b728 lib/utmp.c: Indent nested preprocessor conditionals
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-21 15:43:25 +01:00
Alejandro Colomar
5ff6edf9f2 lib/utmp.c: Replace UT_LINESIZE by a NITEMS() calculation
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>
2024-02-20 18:53:53 +01:00
Alejandro Colomar
544709fad3 lib/sizeof.h: memberof(): Add macro
This macro is useful to get the size of a member of a structure
without having a variable of that type.

Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-20 18:53:53 +01:00
Alejandro Colomar
8d1f0bcf99 lib/utmp.c: get_session_host(): Reduce scope of variable
This silences a warning about an unused variable.

Tested-by: Firas Khalil Khana <firasuke@gmail.com>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-20 18:53:53 +01:00
Alejandro Colomar
64bcb54fa9 lib/, src/, configure.ac: Use utmpx instead of utmp
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>
2024-02-20 18:53:53 +01:00
Alejandro Colomar
4d139ca466 lib/getdate.y: get_date(): Fix calculation
Instead of adding 1, we should add the value the we stored previously in
the variable.

Fixes: 45c6603cc8 ("[svn-upgrade] Integrating new upstream version, shadow (19990709)")
Closes: <https://github.com/shadow-maint/shadow/issues/939>
Link: <https://github.com/shadow-maint/shadow/pull/942>
Reported-by: Michael Vetter <jubalh@iodoru.org>
Reported-by: Gus Kenion <https://github.com/kenion>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-16 19:58:43 -06:00
Tomas Halman
e15aa5a8a6 src/passwd.c: check password length upper limit
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>
2024-02-16 15:46:08 -06:00
Tomas Halman
dfb4d8fdf9 src/passwd.c: inconsistent password length limit
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>
2024-02-16 15:46:08 -06:00
482 changed files with 150556 additions and 102338 deletions

View File

@@ -5,8 +5,21 @@ runs:
steps:
- shell: bash
run: |
sudo apt-get update -y
sudo apt-get install -y ubuntu-dev-tools libbsd-dev
sudo sed -Ei 's/^# deb-src /deb-src /' /etc/apt/sources.list
sudo apt-get update -y
if [ -f /etc/apt/sources.list.d/ubuntu.sources ]; then
echo "Found new-style sources.list.d"
cat /etc/apt/sources.list.d/ubuntu.sources
sudo sed -i 's/^Types: deb/Types: deb deb-src/' /etc/apt/sources.list.d/ubuntu.sources
else
echo "Found legacy sources.list"
cat /etc/apt/sources.list
sudo sed -i '/deb-src/d' /etc/apt/sources.list
sudo sed -i '/^deb /p;s/ /-src /' /etc/apt/sources.list
fi
export DEBIAN_PRIORITY=critical
export DEBIAN_FRONTEND=noninteractive
# let's try to work around upgrade breakage in a pkg we don't care about
sudo apt-mark hold grub-efi-amd64-bin grub-efi-amd64-signed
sudo apt-get update
sudo apt-get -y dist-upgrade
sudo apt-get -y install ubuntu-dev-tools automake autopoint xsltproc gettext expect byacc libtool libbsd-dev libltdl-dev pkgconf
sudo apt-get -y build-dep shadow

View File

@@ -25,18 +25,8 @@ jobs:
cat /proc/self/status
systemd-detect-virt
- name: Install dependencies
run: |
sudo cat /etc/apt/sources.list
sudo sed -i '/deb-src/d' /etc/apt/sources.list
sudo sed -i '/^deb /p;s/ /-src /' /etc/apt/sources.list
export DEBIAN_PRIORITY=critical
export DEBIAN_FRONTEND=noninteractive
# let's try to work around upgrade breakage in a pkg we don't care about
sudo apt-mark hold grub-efi-amd64-bin grub-efi-amd64-signed
sudo apt-get update
sudo apt-get -y dist-upgrade
sudo apt-get -y install ubuntu-dev-tools automake autopoint xsltproc gettext expect byacc libtool libbsd-dev pkgconf libcmocka-dev
sudo apt-get -y build-dep shadow
id: dependencies
uses: ./.github/actions/install-dependencies
- name: configure
run: |
autoreconf -v -f --install
@@ -49,8 +39,9 @@ jobs:
run: |
set -e
cd tests
trap 'cat testsuite.log' ERR
sudo ./run_some
cat testsuite.log
trap - ERR
# Make sure that 'make dist' makes a usable tarball with no missing files
dist-build:
@@ -60,18 +51,8 @@ jobs:
uses: actions/checkout@v3
- name: Install dependencies
run: |
sudo cat /etc/apt/sources.list
sudo sed -i '/deb-src/d' /etc/apt/sources.list
sudo sed -i '/^deb /p;s/ /-src /' /etc/apt/sources.list
export DEBIAN_PRIORITY=critical
export DEBIAN_FRONTEND=noninteractive
# let's try to work around upgrade breakage in a pkg we don't care about
sudo apt-mark hold grub-efi-amd64-bin grub-efi-amd64-signed
sudo apt-get update
sudo apt-get -y dist-upgrade
sudo apt-get -y install ubuntu-dev-tools automake autopoint xsltproc gettext expect byacc libtool libbsd-dev pkgconf
sudo apt-get -y build-dep shadow
id: dependencies
uses: ./.github/actions/install-dependencies
- name: Test make dist
run: |
@@ -88,6 +69,7 @@ jobs:
container-build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
os: [alpine, debian, fedora]
@@ -95,15 +77,25 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install Ansible
run: |
sudo apt-get update
sudo apt-get -y install ansible
- name: Build container
run: |
docker buildx build -f ./share/containers/${{ matrix.os }}.dockerfile . --output build-out
pushd share/ansible/
ansible-playbook playbook.yml -i inventory.ini -e 'distribution=${{ matrix.os }}'
popd
- name: Store artifacts
uses: actions/upload-artifact@v3
if: always()
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}-build
path: |
./build-out/config.log
./build-out/config.h
./share/ansible/build-out/config.log
./share/ansible/build-out/config.h
./share/ansible/build-out/build.log
./share/ansible/build-out/test-suite.log
if-no-files-found: ignore

View File

@@ -32,10 +32,7 @@ jobs:
- name: Build shadow-utils
run: |
PROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN)
make -kj$PROCESSORS || true
- name: Check build errors
run: make
make -Orecurse -j$PROCESSORS
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

5
.gitignore vendored
View File

@@ -3,9 +3,11 @@ lib*.a
*.o
*.lo
*.la
*.mo
*.gmo
.deps
.libs
.dirstamp
*.patch
*.rej
@@ -14,6 +16,8 @@ lib*.a
Makefile
Makefile.in
test-driver
/ABOUT-NLS
/aclocal.m4
/autom4te.cache
@@ -34,6 +38,7 @@ Makefile.in
/m4
/missing
/stamp-h1
/test-driver
/ylwrap
/po/*.header

View File

@@ -1,7 +1,5 @@
## Process this file with automake to produce Makefile.in
EXTRA_DIST = NEWS README
SUBDIRS = lib
if ENABLE_SUBIDS
@@ -13,3 +11,17 @@ SUBDIRS += src po contrib doc etc tests/unit
if ENABLE_REGENERATE_MAN
SUBDIRS += man
endif
CLEANFILES = man/8.out man/po/remove-potcdate.* man/*/login.defs.d man/*/*.mo
EXTRA_DIST = NEWS README tests/
dist-hook:
chmod -R u+w $(distdir)/tests
chmod u+w $(distdir)
mv $(distdir)/tests/unit $(distdir)/realunittest
mv $(distdir)/tests/tests $(distdir)/realtests
rm -rf $(distdir)/tests
mv $(distdir)/realtests $(distdir)/tests
rm -rf $(distdir)/tests/unit $(distdir)/tests/Makefile*
mv $(distdir)/realunittest $(distdir)/tests/unit

View File

@@ -2,10 +2,10 @@
The following stable branches are kindly maintained by trusted volunteers:
- 4.14.x
- 4.15.x
- git
- [main](https://www.alejandro-colomar.es/src/alx/shadow/stable/shadow.git/log/?h=4.14.x)
- [mirror](https://github.com/shadow-maint/shadow/tree/4.14.x)
- [main](https://www.alejandro-colomar.es/src/alx/shadow/stable/shadow.git/log/?h=4.15.x)
- [mirror](https://github.com/shadow-maint/shadow/tree/4.15.x)
- tarballs
- [main](https://www.alejandro-colomar.es/share/dist/shadow/4/4.14/)
- [main](https://www.alejandro-colomar.es/share/dist/shadow/4/4.15/)
- [mirror](https://github.com/shadow-maint/shadow/releases/)

View File

@@ -1,12 +1,12 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
m4_define([libsubid_abi_major], 4)
m4_define([libsubid_abi_major], 5)
m4_define([libsubid_abi_minor], 0)
m4_define([libsubid_abi_micro], 0)
m4_define([libsubid_abi], [libsubid_abi_major.libsubid_abi_minor.libsubid_abi_micro])
AC_INIT([shadow], [4.15.0-rc2], [pkg-shadow-devel@lists.alioth.debian.org], [],
AC_INIT([shadow], [4.17.1], [pkg-shadow-devel@lists.alioth.debian.org], [],
[https://github.com/shadow-maint/shadow])
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects])
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects tar-pax])
AC_CONFIG_MACRO_DIRS([m4])
AM_SILENT_RULES([yes])
AC_CONFIG_HEADERS([config.h])
@@ -49,7 +49,7 @@ AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
AC_CHECK_FUNCS(arc4random_buf futimes \
getentropy getrandom getspnam getusershell \
initgroups lckpwdf lutimes \
setgroups updwtmp updwtmpx innetgr \
setgroups updwtmpx innetgr \
getspnam_r \
rpmatch \
memset_explicit explicit_bzero stpecpy stpeprintf)
@@ -57,17 +57,13 @@ AC_SYS_LARGEFILE
dnl Checks for typedefs, structures, and compiler characteristics.
AC_CHECK_MEMBERS([struct utmp.ut_type,
struct utmp.ut_id,
struct utmp.ut_name,
struct utmp.ut_user,
struct utmp.ut_host,
struct utmp.ut_syslen,
struct utmp.ut_addr,
struct utmp.ut_addr_v6,
struct utmp.ut_time,
struct utmp.ut_xtime,
struct utmp.ut_tv],,,[[#include <utmp.h>]])
AC_CHECK_MEMBERS([struct utmpx.ut_name,
struct utmpx.ut_host,
struct utmpx.ut_syslen,
struct utmpx.ut_addr,
struct utmpx.ut_addr_v6,
struct utmpx.ut_time,
struct utmpx.ut_xtime],,,[[#include <utmpx.h>]])
dnl Checks for library functions.
AC_TYPE_GETGROUPS
@@ -163,13 +159,6 @@ fi])
AC_DEFINE_UNQUOTED(PASSWD_PROGRAM, "$shadow_cv_passwd_dir/passwd",
[Path to passwd program.])
dnl XXX - quick hack, should disappear before anyone notices :).
dnl XXX - I just read the above message :).
if test "$ac_cv_func_ruserok" = "yes"; then
AC_DEFINE(RLOGIN, 1, [Define if login should support the -r flag for rlogind.])
AC_DEFINE(RUSEROK, 0, [Define to the ruserok() "success" return value (0 or 1).])
fi
AC_ARG_ENABLE(shadowgrp,
[AS_HELP_STRING([--enable-shadowgrp], [enable shadow group support @<:@default=yes@:>@])],
[case "${enableval}" in
@@ -278,6 +267,7 @@ AC_DEFINE_UNQUOTED(GROUP_NAME_MAX_LENGTH, $with_group_name_max_length, [max grou
AC_SUBST(GROUP_NAME_MAX_LENGTH)
GROUP_NAME_MAX_LENGTH="$with_group_name_max_length"
AM_CONDITIONAL(USE_SHA_CRYPT, test "x$with_sha_crypt" = "xyes")
if test "$with_sha_crypt" = "yes"; then
AC_DEFINE(USE_SHA_CRYPT, 1, [Define to allow the SHA256 and SHA512 password encryption algorithms])
@@ -314,6 +304,10 @@ dnl needed (Linux glibc, Irix), but still link it if needed (Solaris).
AC_SEARCH_LIBS(gethostbyname, nsl)
PKG_CHECK_MODULES([CMOCKA], [cmocka], [have_cmocka="yes"],
[AC_MSG_WARN([libcmocka not found, cmocka tests will not be built])])
AM_CONDITIONAL([HAVE_CMOCKA], [test x$have_cmocka = xyes])
AC_CHECK_LIB([econf],[econf_readDirs],[LIBECONF="-leconf"],[LIBECONF=""])
if test -n "$LIBECONF"; then
AC_DEFINE_UNQUOTED([VENDORDIR], ["$enable_vendordir"],
@@ -695,7 +689,7 @@ AC_SUBST(LIBMD)
if test "$with_skey" = "yes"; then
AC_CHECK_LIB(md, MD5Init, [LIBMD=-lmd])
AC_CHECK_LIB(skey, skeychallenge, [LIBSKEY=-lskey],
[AC_MSG_ERROR([liskey missing. You can download S/Key source code from http://rsync1.it.gentoo.org/gentoo/distfiles/skey-1.1.5.tar.bz2])])
[AC_MSG_ERROR([libskey missing. You can download S/Key source code from http://rsync1.it.gentoo.org/gentoo/distfiles/skey-1.1.5.tar.bz2])])
AC_DEFINE(SKEY, 1, [Define to support S/Key logins.])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <stdio.h>
@@ -705,10 +699,6 @@ if test "$with_skey" = "yes"; then
]])],[AC_DEFINE(SKEY_BSD_STYLE, 1, [Define to support newer BSD S/Key API])],[])
fi
PKG_CHECK_MODULES([CMOCKA], [cmocka], [have_cmocka="yes"],
[AC_MSG_WARN([libcmocka not found, cmocka tests will not be built])])
AM_CONDITIONAL([HAVE_CMOCKA], [test x$have_cmocka = xyes])
AC_CHECK_FUNC(fgetpwent_r, [AC_DEFINE(HAVE_FGETPWENT_R, 1, [Defined to 1 if you have the declaration of 'fgetpwent_r'])])
AC_DEFINE_UNQUOTED(SHELL, ["$SHELL"], [The default shell.])

View File

@@ -118,6 +118,9 @@
#include <sys/stat.h>
#include <syslog.h>
#include "string/strcmp/streq.h"
#define IMMEDIATE_CHANGE /* Expire newly created password, must be changed
* immediately upon next login */
#define HAVE_QUOTAS /* Obvious */
@@ -291,12 +294,10 @@ main (void)
printf ("Home Directory [%s/%s]: ", DEFAULT_HOME, usrname);
fflush (stdout);
safeget (dir, sizeof (dir));
if (!strlen (dir))
{ /* hit return */
sprintf (dir, "%s/%s", DEFAULT_HOME, usrname);
}
if (!strlen(dir)) /* hit return */
sprintf(dir, "%s/%s", DEFAULT_HOME, usrname);
else if (dir[strlen (dir) - 1] == '/')
sprintf (dir+strlen(dir), "%s", usrname);
strcat(dir, usrname);
}
else
{
@@ -308,7 +309,7 @@ main (void)
fflush (stdout);
safeget (shell, sizeof (shell));
if (!strlen (shell))
sprintf (shell, "%s", DEFAULT_SHELL);
strcpy(shell, DEFAULT_SHELL);
else
{
char *sh;
@@ -316,7 +317,7 @@ main (void)
#ifdef HAVE_GETUSERSHELL
setusershell ();
while ((sh = getusershell ()) != NULL)
if (!strcmp (shell, sh))
if (streq(shell, sh))
ok = 1;
endusershell ();
#endif
@@ -327,7 +328,7 @@ main (void)
else
{
printf ("Shell NOT in /etc/shells, DEFAULT used\n");
sprintf (shell, "%s", DEFAULT_SHELL);
strcpy(shell, DEFAULT_SHELL);
}
}
}
@@ -491,12 +492,12 @@ safeget (char *buf, int maxlen)
bad = (!isalnum (c) && (c != '_') && (c != ' '));
*(buf++) = c;
}
*buf = '\0';
stpcpy(buf, "");
if (bad)
{
printf ("\nString contained banned character. Please stick to alphanumerics.\n");
*bstart = '\0';
stpcpy(bstart, "");
}
}

View File

@@ -471,12 +471,12 @@
The Shadow Suite contains replacement programs for:
su, login, passwd, newgrp, chfn, chsh, and id
su, login, passwd, newgrp, chfn, chsh
The package also contains the new programs:
chage, newusers, dpasswd, gpasswd, useradd, userdel, usermod,
groupadd, groupdel, groupmod, groups, pwck, grpck, lastlog, pwconv,
groupadd, groupdel, groupmod, pwck, grpck, lastlog, pwconv,
and pwunconv
Additionally, the library: libshadow.a is included for writing and/or
@@ -586,8 +586,6 @@
· /usr/bin/chsh
· /usr/bin/id
The BETA package has a save target in the Makefile, but it's commented
out because different distributions place the programs in different
places.
@@ -637,8 +635,6 @@
· /usr/man/man1/chsh.1.gz
· /usr/man/man1/id.1.gz
· /usr/man/man1/login.1.gz
· /usr/man/man1/passwd.1.gz
@@ -1377,7 +1373,7 @@
users or changing the group password, the /etc/gshadow file will be
changed.
The programs groups, groupadd, groupmod, and groupdel are provided as
The programs groupadd, groupmod, and groupdel are provided as
part of the Shadow Suite to modify groups.
The format of the /etc/group file is as follows:

View File

@@ -62,9 +62,11 @@ You can either generate a single image by running the following command from
the root folder of the project (i.e. Alpine):
```
docker build -f share/containers/alpine.dockerfile . --output build-out/alpine
ansible-playbook share/ansible/playbook.yml -i share/ansible/inventory.ini -e 'distribution=alpine'
```
**Note**: you'll need to install ansible to run this automation.
Or generate all of the images with the `container-build.sh` script, as if you
were running some of the CI checks locally:

View File

@@ -72,6 +72,6 @@ understand the project's development model:
* [Build & install](build_install.md)
* [Coding style](coding_style.md)
* [Tests](tests.md)
* [Continuous Integration](CI.md)
* [Continuous Integration](ci.md)
* [Releases](releases.md)
* [License](license.md)

View File

@@ -29,12 +29,48 @@ libshadow_la_SOURCES = \
age.c \
agetpass.c \
agetpass.h \
alloc.c \
alloc.h \
atoi/strtoi.c \
atoi/strtoi.h \
atoi/strtou_noneg.c \
atoi/strtou_noneg.h \
alloc/calloc.c \
alloc/calloc.h \
alloc/malloc.c \
alloc/malloc.h \
alloc/realloc.c \
alloc/realloc.h \
alloc/reallocf.c \
alloc/reallocf.h \
alloc/x/xcalloc.c \
alloc/x/xcalloc.h \
alloc/x/xmalloc.c \
alloc/x/xmalloc.h \
alloc/x/xrealloc.c \
alloc/x/xrealloc.h \
atoi/a2i/a2i.c \
atoi/a2i/a2i.h \
atoi/a2i/a2s.c \
atoi/a2i/a2s.h \
atoi/a2i/a2s_c.c \
atoi/a2i/a2s_c.h \
atoi/a2i/a2s_nc.c \
atoi/a2i/a2s_nc.h \
atoi/a2i/a2u.c \
atoi/a2i/a2u.h \
atoi/a2i/a2u_c.c \
atoi/a2i/a2u_c.h \
atoi/a2i/a2u_nc.c \
atoi/a2i/a2u_nc.h \
atoi/getnum.c \
atoi/getnum.h \
atoi/str2i/str2i.c \
atoi/str2i/str2i.h \
atoi/str2i/str2s.c \
atoi/str2i/str2s.h \
atoi/str2i/str2u.c \
atoi/str2i/str2u.h \
atoi/strtoi/strtoi.c \
atoi/strtoi/strtoi.h \
atoi/strtoi/strtou.c \
atoi/strtoi/strtou.h \
atoi/strtoi/strtou_noneg.c \
atoi/strtoi/strtou_noneg.h \
attr.h \
audit_help.c \
basename.c \
@@ -53,7 +89,6 @@ libshadow_la_SOURCES = \
console.c \
copydir.c \
csrand.c \
date_to_str.c \
defines.h \
encrypt.c \
env.c \
@@ -61,24 +96,25 @@ libshadow_la_SOURCES = \
faillog.h \
failure.c \
failure.h \
fd.c \
fields.c \
find_new_gid.c \
find_new_uid.c \
find_new_sub_gids.c \
find_new_sub_uids.c \
fputsx.c \
get_gid.c \
fs/readlink/areadlink.c \
fs/readlink/areadlink.h \
fs/readlink/readlinknul.c \
fs/readlink/readlinknul.h \
get_pid.c \
get_uid.c \
getdate.h \
getdate.y \
getdef.c \
getdef.h \
getlong.c \
getgr_nam_gid.c \
getrange.c \
gettime.c \
getulong.c \
groupio.c \
groupmem.c \
groupio.h \
@@ -92,8 +128,6 @@ libshadow_la_SOURCES = \
lockpw.c \
loginprompt.c \
mail.c \
memzero.c \
memzero.h \
motd.c \
must_be.h \
myname.c \
@@ -117,7 +151,6 @@ libshadow_la_SOURCES = \
pwdcheck.c \
pwmem.c \
remove_tree.c \
rlogin.c \
root_flag.c \
run_part.h \
run_part.c \
@@ -143,23 +176,51 @@ libshadow_la_SOURCES = \
spawn.c \
sssd.c \
sssd.h \
string/sprintf.c \
string/sprintf.h \
string/stpecpy.c \
string/stpecpy.h \
string/stpeprintf.c \
string/stpeprintf.h \
string/strncpy.h \
string/strtcpy.c \
string/strtcpy.h \
string/zustr2stp.c \
string/zustr2stp.h \
string/memset/memzero.c \
string/memset/memzero.h \
string/sprintf/snprintf.c \
string/sprintf/snprintf.h \
string/sprintf/stpeprintf.c \
string/sprintf/stpeprintf.h \
string/sprintf/xasprintf.c \
string/sprintf/xasprintf.h \
string/strchr/strchrcnt.c \
string/strchr/strchrcnt.h \
string/strchr/stpspn.c \
string/strchr/stpspn.h \
string/strchr/strnul.c \
string/strchr/strnul.h \
string/strchr/strrspn.c \
string/strchr/strrspn.h \
string/strcmp/streq.c \
string/strcmp/streq.h \
string/strcpy/stpecpy.c \
string/strcpy/stpecpy.h \
string/strcpy/strncat.c \
string/strcpy/strncat.h \
string/strcpy/strncpy.c \
string/strcpy/strncpy.h \
string/strcpy/strtcpy.c \
string/strcpy/strtcpy.h \
string/strdup/strndupa.c \
string/strdup/strndupa.h \
string/strdup/xstrdup.c \
string/strdup/xstrdup.h \
string/strdup/xstrndup.c \
string/strdup/xstrndup.h \
string/strftime.c \
string/strftime.h \
string/strtok/stpsep.c \
string/strtok/stpsep.h \
strtoday.c \
sub.c \
subordinateio.h \
subordinateio.c \
sulog.c \
time/day_to_str.c \
time/day_to_str.h \
ttytype.c \
typetraits.h \
tz.c \
ulimit.c \
user_busy.c \

View File

@@ -14,28 +14,30 @@
#include "prototypes.h"
#include "defines.h"
#include <stdio.h>
#include <grp.h>
#include <errno.h>
#include <grp.h>
#include <stdio.h>
#include <string.h>
#include "alloc.h"
#include "alloc/malloc.h"
#include "alloc/reallocf.h"
#include "shadowlog.h"
#ident "$Id$"
#define SEP ",:"
/*
* Add groups with names from LIST (separated by commas or colons)
* to the supplementary group set. Silently ignore groups which are
* already there. Warning: uses strtok().
* already there.
*/
int add_groups (const char *list)
int
add_groups(const char *list)
{
GETGROUPS_T *grouplist;
size_t i;
int ngroups;
bool added;
char *token;
char *g, *p;
char buf[1024];
int ret;
FILE *shadow_logfd = log_get_logfd();
@@ -70,13 +72,13 @@ int add_groups (const char *list)
}
added = false;
for (token = strtok (buf, SEP); NULL != token; token = strtok (NULL, SEP)) {
p = buf;
while (NULL != (g = strsep(&p, ",:"))) {
struct group *grp;
grp = getgrnam (token); /* local, no need for xgetgrnam */
grp = getgrnam(g); /* local, no need for xgetgrnam */
if (NULL == grp) {
fprintf (shadow_logfd, _("Warning: unknown group %s\n"),
token);
fprintf(shadow_logfd, _("Warning: unknown group %s\n"), g);
continue;
}

View File

@@ -11,24 +11,18 @@
#include <limits.h>
#include <readpassphrase.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ident "$Id$"
#include "alloc.h"
#include "alloc/malloc.h"
#if WITH_LIBBSD == 0
#include "freezero.h"
#endif /* WITH_LIBBSD */
#if !defined(PASS_MAX)
#define PASS_MAX BUFSIZ - 1
#endif
/*
* SYNOPSIS
* [[gnu::malloc(erase_pass)]]

View File

@@ -1,73 +0,0 @@
/*
* SPDX-FileCopyrightText: 1990 - 1994, Julianne Frances Haugh
* SPDX-FileCopyrightText: 1996 - 1998, Marek Michałkiewicz
* SPDX-FileCopyrightText: 2003 - 2006, Tomasz Kłoczko
* SPDX-FileCopyrightText: 2008 , Nicolas François
* SPDX-FileCopyrightText: 2023 , Alejandro Colomar <alx@kernel.org>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/* Replacements for malloc and strdup with error checking. Too trivial
to be worth copyrighting :-). I did that because a lot of code used
malloc and strdup without checking for NULL pointer, and I like some
message better than a core dump... --marekm
Yeh, but. Remember that bailing out might leave the system in some
bizarre state. You really want to put in error checking, then add
some back-out failure recovery code. -- jfh */
#include <config.h>
#ident "$Id$"
#include "alloc.h"
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include "defines.h"
#include "prototypes.h"
#include "shadowlog.h"
extern inline void *xmalloc(size_t size);
extern inline void *xmallocarray(size_t nmemb, size_t size);
extern inline void *mallocarray(size_t nmemb, size_t size);
extern inline void *reallocarrayf(void *p, size_t nmemb, size_t size);
extern inline char *xstrdup(const char *str);
void *
xcalloc(size_t nmemb, size_t size)
{
void *p;
p = calloc(nmemb, size);
if (p == NULL)
goto x;
return p;
x:
fprintf(log_get_logfd(), _("%s: %s\n"),
log_get_progname(), strerror(errno));
exit(13);
}
void *
xreallocarray(void *p, size_t nmemb, size_t size)
{
p = reallocarrayf(p, nmemb, size);
if (p == NULL)
goto x;
return p;
x:
fprintf(log_get_logfd(), _("%s: %s\n"),
log_get_progname(), strerror(errno));
exit(13);
}

View File

@@ -1,116 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023, Alejandro Colomar <alx@kernel.org>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef SHADOW_INCLUDE_LIB_MALLOC_H_
#define SHADOW_INCLUDE_LIB_MALLOC_H_
#include <config.h>
#include <assert.h>
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include "attr.h"
#include "defines.h"
#define CALLOC(n, type) ((type *) calloc(n, sizeof(type)))
#define XCALLOC(n, type) ((type *) xcalloc(n, sizeof(type)))
#define MALLOC(n, type) ((type *) mallocarray(n, sizeof(type)))
#define XMALLOC(n, type) ((type *) xmallocarray(n, sizeof(type)))
#define REALLOC(ptr, n, type) \
({ \
__auto_type p_ = (ptr); \
\
static_assert(__builtin_types_compatible_p(typeof(p_), type *), ""); \
\
(type *) reallocarray(p_, n, sizeof(type)); \
})
#define REALLOCF(ptr, n, type) \
({ \
__auto_type p_ = (ptr); \
\
static_assert(__builtin_types_compatible_p(typeof(p_), type *), ""); \
\
(type *) reallocarrayf(p_, n, sizeof(type)); \
})
#define XREALLOC(ptr, n, type) \
({ \
__auto_type p_ = (ptr); \
\
static_assert(__builtin_types_compatible_p(typeof(p_), type *), ""); \
\
(type *) xreallocarray(p_, n, sizeof(type)); \
})
ATTR_MALLOC(free)
inline void *xmalloc(size_t size);
ATTR_MALLOC(free)
inline void *xmallocarray(size_t nmemb, size_t size);
ATTR_MALLOC(free)
inline void *mallocarray(size_t nmemb, size_t size);
ATTR_MALLOC(free)
inline void *reallocarrayf(void *p, size_t nmemb, size_t size);
ATTR_MALLOC(free)
inline char *xstrdup(const char *str);
ATTR_MALLOC(free)
void *xcalloc(size_t nmemb, size_t size);
ATTR_MALLOC(free)
void *xreallocarray(void *p, size_t nmemb, size_t size);
inline void *
xmalloc(size_t size)
{
return xmallocarray(1, size);
}
inline void *
xmallocarray(size_t nmemb, size_t size)
{
return xreallocarray(NULL, nmemb, size);
}
inline void *
mallocarray(size_t nmemb, size_t size)
{
return reallocarray(NULL, nmemb, size);
}
inline void *
reallocarrayf(void *p, size_t nmemb, size_t size)
{
void *q;
q = reallocarray(p, nmemb, size);
/* realloc(p, 0) is equivalent to free(p); avoid double free. */
if (q == NULL && nmemb != 0 && size != 0)
free(p);
return q;
}
inline char *
xstrdup(const char *str)
{
return strcpy(XMALLOC(strlen(str) + 1, char), str);
}
#endif // include guard

11
lib/alloc/calloc.c Normal file
View File

@@ -0,0 +1,11 @@
// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh
// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz
// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko
// SPDX-FileCopyrightText: 2008 , Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "alloc/calloc.h"

20
lib/alloc/calloc.h Normal file
View File

@@ -0,0 +1,20 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ALLOC_CALLOC_H_
#define SHADOW_INCLUDE_LIB_ALLOC_CALLOC_H_
#include <config.h>
#include <stdlib.h>
#define CALLOC(n, type) \
( \
(type *) calloc(n, sizeof(type)) \
)
#endif // include guard

16
lib/alloc/malloc.c Normal file
View File

@@ -0,0 +1,16 @@
// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh
// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz
// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko
// SPDX-FileCopyrightText: 2008 , Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "alloc/malloc.h"
#include <stddef.h>
extern inline void *mallocarray(size_t nmemb, size_t size);

34
lib/alloc/malloc.h Normal file
View File

@@ -0,0 +1,34 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ALLOC_MALLOC_H_
#define SHADOW_INCLUDE_LIB_ALLOC_MALLOC_H_
#include <config.h>
#include <stdlib.h>
#include "attr.h"
#define MALLOC(n, type) \
( \
(type *) mallocarray(n, sizeof(type)) \
)
ATTR_ALLOC_SIZE(1, 2)
ATTR_MALLOC(free)
inline void *mallocarray(size_t nmemb, size_t size);
inline void *
mallocarray(size_t nmemb, size_t size)
{
return reallocarray(NULL, nmemb, size);
}
#endif // include guard

11
lib/alloc/realloc.c Normal file
View File

@@ -0,0 +1,11 @@
// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh
// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz
// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko
// SPDX-FileCopyrightText: 2008 , Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "alloc/realloc.h"

20
lib/alloc/realloc.h Normal file
View File

@@ -0,0 +1,20 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ALLOC_REALLOC_H_
#define SHADOW_INCLUDE_LIB_ALLOC_REALLOC_H_
#include <config.h>
#include <stdlib.h>
#define REALLOC(p, n, type) \
( \
_Generic(p, type *: (type *) reallocarray(p, (n) ?: 1, sizeof(type))) \
)
#endif // include guard

16
lib/alloc/reallocf.c Normal file
View File

@@ -0,0 +1,16 @@
// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh
// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz
// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko
// SPDX-FileCopyrightText: 2008 , Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "alloc/reallocf.h"
#include <stddef.h>
extern inline void *reallocarrayf(void *p, size_t nmemb, size_t size);

41
lib/alloc/reallocf.h Normal file
View File

@@ -0,0 +1,41 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ALLOC_REALLOCF_H_
#define SHADOW_INCLUDE_LIB_ALLOC_REALLOCF_H_
#include <config.h>
#include <stddef.h>
#include <stdlib.h>
#include "attr.h"
#define REALLOCF(p, n, type) \
( \
_Generic(p, type *: (type *) reallocarrayf(p, (n) ?: 1, sizeof(type)))\
)
ATTR_ALLOC_SIZE(2, 3)
ATTR_MALLOC(free)
inline void *reallocarrayf(void *p, size_t nmemb, size_t size);
inline void *
reallocarrayf(void *p, size_t nmemb, size_t size)
{
void *q;
q = reallocarray(p, nmemb ?: 1, size ?: 1);
if (q == NULL)
free(p);
return q;
}
#endif // include guard

36
lib/alloc/x/xcalloc.c Normal file
View File

@@ -0,0 +1,36 @@
// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh
// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz
// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko
// SPDX-FileCopyrightText: 2008 , Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "alloc/x/xcalloc.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "defines.h"
#include "shadowlog.h"
void *
xcalloc(size_t nmemb, size_t size)
{
void *p;
p = calloc(nmemb, size);
if (p == NULL)
goto x;
return p;
x:
fprintf(log_get_logfd(), _("%s: %s\n"),
log_get_progname(), strerror(errno));
exit(13);
}

28
lib/alloc/x/xcalloc.h Normal file
View File

@@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ALLOC_X_XCALLOC_H_
#define SHADOW_INCLUDE_LIB_ALLOC_X_XCALLOC_H_
#include <config.h>
#include <stddef.h>
#include <stdlib.h>
#include "attr.h"
#define XCALLOC(n, type) \
( \
(type *) xcalloc(n, sizeof(type)) \
)
ATTR_ALLOC_SIZE(1, 2)
ATTR_MALLOC(free)
void *xcalloc(size_t nmemb, size_t size);
#endif // include guard

16
lib/alloc/x/xmalloc.c Normal file
View File

@@ -0,0 +1,16 @@
// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh
// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz
// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko
// SPDX-FileCopyrightText: 2008 , Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "alloc/x/xmalloc.h"
#include <stddef.h>
extern inline void *xmallocarray(size_t nmemb, size_t size);

35
lib/alloc/x/xmalloc.h Normal file
View File

@@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ALLOC_X_XMALLOC_H_
#define SHADOW_INCLUDE_LIB_ALLOC_X_XMALLOC_H_
#include <config.h>
#include <stddef.h>
#include "alloc/x/xrealloc.h"
#include "attr.h"
#define XMALLOC(n, type) \
( \
(type *) xmallocarray(n, sizeof(type)) \
)
ATTR_ALLOC_SIZE(1, 2)
ATTR_MALLOC(free)
inline void *xmallocarray(size_t nmemb, size_t size);
inline void *
xmallocarray(size_t nmemb, size_t size)
{
return xreallocarray(NULL, nmemb, size);
}
#endif // include guard

35
lib/alloc/x/xrealloc.c Normal file
View File

@@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh
// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz
// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko
// SPDX-FileCopyrightText: 2008 , Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "alloc/x/xrealloc.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "alloc/reallocf.h"
#include "defines.h"
#include "shadowlog.h"
void *
xreallocarray(void *p, size_t nmemb, size_t size)
{
p = reallocarrayf(p, nmemb, size);
if (p == NULL)
goto x;
return p;
x:
fprintf(log_get_logfd(), _("%s: %s\n"),
log_get_progname(), strerror(errno));
exit(13);
}

31
lib/alloc/x/xrealloc.h Normal file
View File

@@ -0,0 +1,31 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_MALLOC_H_
#define SHADOW_INCLUDE_LIB_MALLOC_H_
#include <config.h>
#include <assert.h>
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include "attr.h"
#define XREALLOC(ptr, n, type) \
( \
_Generic(ptr, type *: (type *) xreallocarray(ptr, n, sizeof(type))) \
)
ATTR_ALLOC_SIZE(2, 3)
ATTR_MALLOC(free)
void *xreallocarray(void *p, size_t nmemb, size_t size);
#endif // include guard

7
lib/atoi/a2i/a2i.c Normal file
View File

@@ -0,0 +1,7 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/a2i/a2i.h"

62
lib/atoi/a2i/a2i.h Normal file
View File

@@ -0,0 +1,62 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2I_H_
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2I_H_
#include <config.h>
#include "atoi/a2i/a2s_c.h"
#include "atoi/a2i/a2s_nc.h"
#include "atoi/a2i/a2u_c.h"
#include "atoi/a2i/a2u_nc.h"
/*
* See the manual of these macros in liba2i's documentation:
* <http://www.alejandro-colomar.es/share/dist/liba2i/git/HEAD/liba2i-HEAD.pdf>
*/
#define a2i(TYPE, n, s, ...) \
( \
_Generic((void (*)(TYPE, typeof(s))) 0, \
void (*)(short, const char *): a2sh_c, \
void (*)(short, const void *): a2sh_c, \
void (*)(short, char *): a2sh_nc, \
void (*)(short, void *): a2sh_nc, \
void (*)(int, const char *): a2si_c, \
void (*)(int, const void *): a2si_c, \
void (*)(int, char *): a2si_nc, \
void (*)(int, void *): a2si_nc, \
void (*)(long, const char *): a2sl_c, \
void (*)(long, const void *): a2sl_c, \
void (*)(long, char *): a2sl_nc, \
void (*)(long, void *): a2sl_nc, \
void (*)(long long, const char *): a2sll_c, \
void (*)(long long, const void *): a2sll_c, \
void (*)(long long, char *): a2sll_nc, \
void (*)(long long, void *): a2sll_nc, \
void (*)(unsigned short, const char *): a2uh_c, \
void (*)(unsigned short, const void *): a2uh_c, \
void (*)(unsigned short, char *): a2uh_nc, \
void (*)(unsigned short, void *): a2uh_nc, \
void (*)(unsigned int, const char *): a2ui_c, \
void (*)(unsigned int, const void *): a2ui_c, \
void (*)(unsigned int, char *): a2ui_nc, \
void (*)(unsigned int, void *): a2ui_nc, \
void (*)(unsigned long, const char *): a2ul_c, \
void (*)(unsigned long, const void *): a2ul_c, \
void (*)(unsigned long, char *): a2ul_nc, \
void (*)(unsigned long, void *): a2ul_nc, \
void (*)(unsigned long long, const char *): a2ull_c, \
void (*)(unsigned long long, const void *): a2ull_c, \
void (*)(unsigned long long, char *): a2ull_nc, \
void (*)(unsigned long long, void *): a2ull_nc \
)(n, s, __VA_ARGS__) \
)
#endif // include guard

7
lib/atoi/a2i/a2s.c Normal file
View File

@@ -0,0 +1,7 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/a2i/a2s.h"

56
lib/atoi/a2i/a2s.h Normal file
View File

@@ -0,0 +1,56 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_H_
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_H_
#include <config.h>
#include "atoi/a2i/a2s_c.h"
#include "atoi/a2i/a2s_nc.h"
#define a2sh(n, s, ...) \
( \
_Generic(s, \
const char *: a2sh_c, \
const void *: a2sh_c, \
char *: a2sh_nc, \
void *: a2sh_nc \
)(n, s, __VA_ARGS__) \
)
#define a2si(n, s, ...) \
( \
_Generic(s, \
const char *: a2si_c, \
const void *: a2si_c, \
char *: a2si_nc, \
void *: a2si_nc \
)(n, s, __VA_ARGS__) \
)
#define a2sl(n, s, ...) \
( \
_Generic(s, \
const char *: a2sl_c, \
const void *: a2sl_c, \
char *: a2sl_nc, \
void *: a2sl_nc \
)(n, s, __VA_ARGS__) \
)
#define a2sll(n, s, ...) \
( \
_Generic(s, \
const char *: a2sll_c, \
const void *: a2sll_c, \
char *: a2sll_nc, \
void *: a2sll_nc \
)(n, s, __VA_ARGS__) \
)
#endif // include guard

17
lib/atoi/a2i/a2s_c.c Normal file
View File

@@ -0,0 +1,17 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/a2i/a2s_c.h"
extern inline int a2sh_c(short *restrict n, const char *s,
const char **restrict endp, int base, short min, short max);
extern inline int a2si_c(int *restrict n, const char *s,
const char **restrict endp, int base, int min, int max);
extern inline int a2sl_c(long *restrict n, const char *s,
const char **restrict endp, int base, long min, long max);
extern inline int a2sll_c(long long *restrict n, const char *s,
const char **restrict endp, int base, long long min, long long max);

64
lib/atoi/a2i/a2s_c.h Normal file
View File

@@ -0,0 +1,64 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_C_H_
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_C_H_
#include <config.h>
#include <errno.h>
#include <inttypes.h>
#include "atoi/a2i/a2s_nc.h"
#include "attr.h"
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2sh_c(short *restrict n, const char *s,
const char **restrict endp, int base, short min, short max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2si_c(int *restrict n, const char *s,
const char **restrict endp, int base, int min, int max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2sl_c(long *restrict n, const char *s,
const char **restrict endp, int base, long min, long max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2sll_c(long long *restrict n, const char *s,
const char **restrict endp, int base, long long min, long long max);
inline int
a2sh_c(short *restrict n, const char *s,
const char **restrict endp, int base, short min, short max)
{
return a2sh_nc(n, (char *) s, (char **) endp, base, min, max);
}
inline int
a2si_c(int *restrict n, const char *s,
const char **restrict endp, int base, int min, int max)
{
return a2si_nc(n, (char *) s, (char **) endp, base, min, max);
}
inline int
a2sl_c(long *restrict n, const char *s,
const char **restrict endp, int base, long min, long max)
{
return a2sl_nc(n, (char *) s, (char **) endp, base, min, max);
}
inline int
a2sll_c(long long *restrict n, const char *s,
const char **restrict endp, int base, long long min, long long max)
{
return a2sll_nc(n, (char *) s, (char **) endp, base, min, max);
}
#endif // include guard

17
lib/atoi/a2i/a2s_nc.c Normal file
View File

@@ -0,0 +1,17 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/a2i/a2s_nc.h"
extern inline int a2sh_nc(short *restrict n, char *s,
char **restrict endp, int base, short min, short max);
extern inline int a2si_nc(int *restrict n, char *s,
char **restrict endp, int base, int min, int max);
extern inline int a2sl_nc(long *restrict n, char *s,
char **restrict endp, int base, long min, long max);
extern inline int a2sll_nc(long long *restrict n, char *s,
char **restrict endp, int base, long long min, long long max);

91
lib/atoi/a2i/a2s_nc.h Normal file
View File

@@ -0,0 +1,91 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_NC_H_
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_NC_H_
#include <config.h>
#include <errno.h>
#include "atoi/strtoi/strtoi.h"
#include "attr.h"
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2sh_nc(short *restrict n, char *s,
char **restrict endp, int base, short min, short max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2si_nc(int *restrict n, char *s,
char **restrict endp, int base, int min, int max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2sl_nc(long *restrict n, char *s,
char **restrict endp, int base, long min, long max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2sll_nc(long long *restrict n, char *s,
char **restrict endp, int base, long long min, long long max);
inline int
a2sh_nc(short *restrict n, char *s,
char **restrict endp, int base, short min, short max)
{
int status;
*n = strtoi_(s, endp, base, min, max, &status);
if (status != 0) {
errno = status;
return -1;
}
return 0;
}
inline int
a2si_nc(int *restrict n, char *s,
char **restrict endp, int base, int min, int max)
{
int status;
*n = strtoi_(s, endp, base, min, max, &status);
if (status != 0) {
errno = status;
return -1;
}
return 0;
}
inline int
a2sl_nc(long *restrict n, char *s,
char **restrict endp, int base, long min, long max)
{
int status;
*n = strtoi_(s, endp, base, min, max, &status);
if (status != 0) {
errno = status;
return -1;
}
return 0;
}
inline int
a2sll_nc(long long *restrict n, char *s,
char **restrict endp, int base, long long min, long long max)
{
int status;
*n = strtoi_(s, endp, base, min, max, &status);
if (status != 0) {
errno = status;
return -1;
}
return 0;
}
#endif // include guard

7
lib/atoi/a2i/a2u.c Normal file
View File

@@ -0,0 +1,7 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/a2i/a2u.h"

56
lib/atoi/a2i/a2u.h Normal file
View File

@@ -0,0 +1,56 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_H_
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_H_
#include <config.h>
#include "atoi/a2i/a2u_c.h"
#include "atoi/a2i/a2u_nc.h"
#define a2uh(n, s, ...) \
( \
_Generic(s, \
const char *: a2uh_c, \
const void *: a2uh_c, \
char *: a2uh_nc, \
void *: a2uh_nc \
)(n, s, __VA_ARGS__) \
)
#define a2ui(n, s, ...) \
( \
_Generic(s, \
const char *: a2ui_c, \
const void *: a2ui_c, \
char *: a2ui_nc, \
void *: a2ui_nc \
)(n, s, __VA_ARGS__) \
)
#define a2ul(n, s, ...) \
( \
_Generic(s, \
const char *: a2ul_c, \
const void *: a2ul_c, \
char *: a2ul_nc, \
void *: a2ul_nc \
)(n, s, __VA_ARGS__) \
)
#define a2ull(n, s, ...) \
( \
_Generic(s, \
const char *: a2ull_c, \
const void *: a2ull_c, \
char *: a2ull_nc, \
void *: a2ull_nc \
)(n, s, __VA_ARGS__) \
)
#endif // include guard

19
lib/atoi/a2i/a2u_c.c Normal file
View File

@@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/a2i/a2u_c.h"
extern inline int a2uh_c(unsigned short *restrict n, const char *s,
const char **restrict endp, int base, unsigned short min,
unsigned short max);
extern inline int a2ui_c(unsigned int *restrict n, const char *s,
const char **restrict endp, int base, unsigned int min, unsigned int max);
extern inline int a2ul_c(unsigned long *restrict n, const char *s,
const char **restrict endp, int base, unsigned long min, unsigned long max);
extern inline int a2ull_c(unsigned long long *restrict n, const char *s,
const char **restrict endp, int base, unsigned long long min,
unsigned long long max);

65
lib/atoi/a2i/a2u_c.h Normal file
View File

@@ -0,0 +1,65 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_C_H_
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_C_H_
#include <config.h>
#include "atoi/a2i/a2u_nc.h"
#include "attr.h"
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2uh_c(unsigned short *restrict n, const char *s,
const char **restrict endp, int base, unsigned short min,
unsigned short max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2ui_c(unsigned int *restrict n, const char *s,
const char **restrict endp, int base, unsigned int min, unsigned int max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2ul_c(unsigned long *restrict n, const char *s,
const char **restrict endp, int base, unsigned long min, unsigned long max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2ull_c(unsigned long long *restrict n, const char *s,
const char **restrict endp, int base, unsigned long long min,
unsigned long long max);
inline int
a2uh_c(unsigned short *restrict n, const char *s,
const char **restrict endp, int base, unsigned short min,
unsigned short max)
{
return a2uh_nc(n, (char *) s, (char **) endp, base, min, max);
}
inline int
a2ui_c(unsigned int *restrict n, const char *s,
const char **restrict endp, int base, unsigned int min, unsigned int max)
{
return a2ui_nc(n, (char *) s, (char **) endp, base, min, max);
}
inline int
a2ul_c(unsigned long *restrict n, const char *s,
const char **restrict endp, int base, unsigned long min, unsigned long max)
{
return a2ul_nc(n, (char *) s, (char **) endp, base, min, max);
}
inline int
a2ull_c(unsigned long long *restrict n, const char *s,
const char **restrict endp, int base, unsigned long long min,
unsigned long long max)
{
return a2ull_nc(n, (char *) s, (char **) endp, base, min, max);
}
#endif // include guard

18
lib/atoi/a2i/a2u_nc.c Normal file
View File

@@ -0,0 +1,18 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/a2i/a2u_nc.h"
extern inline int a2uh_nc(unsigned short *restrict n, char *s,
char **restrict endp, int base, unsigned short min, unsigned short max);
extern inline int a2ui_nc(unsigned int *restrict n, char *s,
char **restrict endp, int base, unsigned int min, unsigned int max);
extern inline int a2ul_nc(unsigned long *restrict n, char *s,
char **restrict endp, int base, unsigned long min, unsigned long max);
extern inline int a2ull_nc(unsigned long long *restrict n, char *s,
char **restrict endp, int base, unsigned long long min,
unsigned long long max);

94
lib/atoi/a2i/a2u_nc.h Normal file
View File

@@ -0,0 +1,94 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_NC_H_
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_NC_H_
#include <config.h>
#include <errno.h>
#include "atoi/strtoi/strtou_noneg.h"
#include "attr.h"
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2uh_nc(unsigned short *restrict n, char *s,
char **restrict endp, int base, unsigned short min, unsigned short max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2ui_nc(unsigned int *restrict n, char *s,
char **restrict endp, int base, unsigned int min, unsigned int max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2ul_nc(unsigned long *restrict n, char *s,
char **restrict endp, int base, unsigned long min, unsigned long max);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
inline int a2ull_nc(unsigned long long *restrict n, char *s,
char **restrict endp, int base, unsigned long long min,
unsigned long long max);
inline int
a2uh_nc(unsigned short *restrict n, char *s,
char **restrict endp, int base, unsigned short min,
unsigned short max)
{
int status;
*n = strtou_noneg(s, endp, base, min, max, &status);
if (status != 0) {
errno = status;
return -1;
}
return 0;
}
inline int
a2ui_nc(unsigned int *restrict n, char *s,
char **restrict endp, int base, unsigned int min, unsigned int max)
{
int status;
*n = strtou_noneg(s, endp, base, min, max, &status);
if (status != 0) {
errno = status;
return -1;
}
return 0;
}
inline int
a2ul_nc(unsigned long *restrict n, char *s,
char **restrict endp, int base, unsigned long min, unsigned long max)
{
int status;
*n = strtou_noneg(s, endp, base, min, max, &status);
if (status != 0) {
errno = status;
return -1;
}
return 0;
}
inline int
a2ull_nc(unsigned long long *restrict n, char *s,
char **restrict endp, int base, unsigned long long min,
unsigned long long max)
{
int status;
*n = strtou_noneg(s, endp, base, min, max, &status);
if (status != 0) {
errno = status;
return -1;
}
return 0;
}
#endif // include guard

16
lib/atoi/getnum.c Normal file
View File

@@ -0,0 +1,16 @@
// SPDX-FileCopyrightText: 2009, Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include <sys/types.h>
#include "atoi/getnum.h"
extern inline int get_fd(const char *restrict fdstr, int *restrict fd);
extern inline int get_gid(const char *restrict gidstr, gid_t *restrict gid);
extern inline int get_pid(const char *restrict pidstr, pid_t *restrict pid);
extern inline int get_uid(const char *restrict uidstr, uid_t *restrict uid);

60
lib/atoi/getnum.h Normal file
View File

@@ -0,0 +1,60 @@
// SPDX-FileCopyrightText: 2009, Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_GETNUM_H_
#define SHADOW_INCLUDE_LIB_ATOI_GETNUM_H_
#include <config.h>
#include <limits.h>
#include <stddef.h>
#include <sys/types.h>
#include "atoi/a2i/a2i.h"
#include "atoi/a2i/a2s.h"
#include "attr.h"
#include "typetraits.h"
ATTR_STRING(1) ATTR_ACCESS(write_only, 2)
inline int get_fd(const char *restrict fdstr, int *restrict fd);
ATTR_STRING(1) ATTR_ACCESS(write_only, 2)
inline int get_gid(const char *restrict gidstr, gid_t *restrict gid);
ATTR_STRING(1) ATTR_ACCESS(write_only, 2)
inline int get_pid(const char *restrict pidstr, pid_t *restrict pid);
ATTR_STRING(1) ATTR_ACCESS(write_only, 2)
inline int get_uid(const char *restrict uidstr, uid_t *restrict uid);
inline int
get_fd(const char *restrict fdstr, int *restrict fd)
{
return a2si(fd, fdstr, NULL, 10, 0, INT_MAX);
}
inline int
get_gid(const char *restrict gidstr, gid_t *restrict gid)
{
return a2i(gid_t, gid, gidstr, NULL, 10, type_min(gid_t), type_max(gid_t));
}
inline int
get_pid(const char *restrict pidstr, pid_t *restrict pid)
{
return a2i(pid_t, pid, pidstr, NULL, 10, 1, type_max(pid_t));
}
inline int
get_uid(const char *restrict uidstr, uid_t *restrict uid)
{
return a2i(uid_t, uid, uidstr, NULL, 10, type_min(uid_t), type_max(uid_t));
}
#endif // include guard

8
lib/atoi/str2i/str2i.c Normal file
View File

@@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: 2007-2009, Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/str2i/str2i.h"

31
lib/atoi/str2i/str2i.h Normal file
View File

@@ -0,0 +1,31 @@
// SPDX-FileCopyrightText: 2007-2009, Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_STR2I_STR2I_H_
#define SHADOW_INCLUDE_LIB_ATOI_STR2I_STR2I_H_
#include <config.h>
#include "atoi/str2i/str2s.h"
#include "atoi/str2i/str2u.h"
#define str2i(TYPE, ...) \
( \
_Generic((TYPE) 0, \
short: str2sh, \
int: str2si, \
long: str2sl, \
long long: str2sll, \
unsigned short: str2uh, \
unsigned int: str2ui, \
unsigned long: str2ul, \
unsigned long long: str2ull \
)(__VA_ARGS__) \
)
#endif // include guard

14
lib/atoi/str2i/str2s.c Normal file
View File

@@ -0,0 +1,14 @@
// SPDX-FileCopyrightText: 2007-2009, Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/str2i/str2s.h"
extern inline int str2sh(short *restrict n, const char *restrict s);
extern inline int str2si(int *restrict n, const char *restrict s);
extern inline int str2sl(long *restrict n, const char *restrict s);
extern inline int str2sll(long long *restrict n, const char *restrict s);

57
lib/atoi/str2i/str2s.h Normal file
View File

@@ -0,0 +1,57 @@
// SPDX-FileCopyrightText: 2007-2009, Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_STR2I_STR2S_H_
#define SHADOW_INCLUDE_LIB_ATOI_STR2I_STR2S_H_
#include <config.h>
#include <limits.h>
#include <stddef.h>
#include "atoi/a2i/a2s.h"
#include "attr.h"
ATTR_STRING(2) ATTR_ACCESS(write_only, 1)
inline int str2sh(short *restrict n, const char *restrict s);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1)
inline int str2si(int *restrict n, const char *restrict s);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1)
inline int str2sl(long *restrict n, const char *restrict s);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1)
inline int str2sll(long long *restrict n, const char *restrict s);
inline int
str2sh(short *restrict n, const char *restrict s)
{
return a2sh(n, s, NULL, 0, SHRT_MIN, SHRT_MAX);
}
inline int
str2si(int *restrict n, const char *restrict s)
{
return a2si(n, s, NULL, 0, INT_MIN, INT_MAX);
}
inline int
str2sl(long *restrict n, const char *restrict s)
{
return a2sl(n, s, NULL, 0, LONG_MIN, LONG_MAX);
}
inline int
str2sll(long long *restrict n, const char *restrict s)
{
return a2sll(n, s, NULL, 0, LLONG_MIN, LLONG_MAX);
}
#endif // include guard

14
lib/atoi/str2i/str2u.c Normal file
View File

@@ -0,0 +1,14 @@
// SPDX-FileCopyrightText: 2007-2009, Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/str2i/str2u.h"
extern inline int str2uh(unsigned short *restrict n, const char *restrict s);
extern inline int str2ui(unsigned int *restrict n, const char *restrict s);
extern inline int str2ul(unsigned long *restrict n, const char *restrict s);
extern inline int str2ull(unsigned long long *restrict n, const char *restrict s);

57
lib/atoi/str2i/str2u.h Normal file
View File

@@ -0,0 +1,57 @@
// SPDX-FileCopyrightText: 2007-2009, Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_STR2I_STR2U_H_
#define SHADOW_INCLUDE_LIB_ATOI_STR2I_STR2U_H_
#include <config.h>
#include <limits.h>
#include <stddef.h>
#include "atoi/a2i/a2u.h"
#include "attr.h"
ATTR_STRING(2) ATTR_ACCESS(write_only, 1)
inline int str2uh(unsigned short *restrict n, const char *restrict s);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1)
inline int str2ui(unsigned int *restrict n, const char *restrict s);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1)
inline int str2ul(unsigned long *restrict n, const char *restrict s);
ATTR_STRING(2) ATTR_ACCESS(write_only, 1)
inline int str2ull(unsigned long long *restrict n, const char *restrict s);
inline int
str2uh(unsigned short *restrict n, const char *restrict s)
{
return a2uh(n, s, NULL, 0, 0, USHRT_MAX);
}
inline int
str2ui(unsigned int *restrict n, const char *restrict s)
{
return a2ui(n, s, NULL, 0, 0, UINT_MAX);
}
inline int
str2ul(unsigned long *restrict n, const char *restrict s)
{
return a2ul(n, s, NULL, 0, 0, ULONG_MAX);
}
inline int
str2ull(unsigned long long *restrict n, const char *restrict s)
{
return a2ull(n, s, NULL, 0, 0, ULLONG_MAX);
}
#endif // include guard

View File

@@ -1,15 +0,0 @@
// SPDX-FileCopyrightText: 2023, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/strtoi.h"
#include <stdint.h>
extern inline intmax_t strtoi_(const char *s, char **restrict endp, int base,
intmax_t min, intmax_t max, int *restrict status);
extern inline uintmax_t strtou_(const char *s, char **restrict endp, int base,
uintmax_t min, uintmax_t max, int *restrict status);

View File

@@ -1,96 +0,0 @@
// SPDX-FileCopyrightText: 2023, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_STRTOI_H_
#define SHADOW_INCLUDE_LIB_ATOI_STRTOI_H_
#include <config.h>
#include <errno.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/param.h>
#include "attr.h"
#define strtoNmax(TYPE, ...) \
( \
_Generic((TYPE) 0, \
intmax_t: strtoimax, \
uintmax_t: strtoumax \
)(__VA_ARGS__) \
)
#define strtoN(s, endp, base, min, max, status, TYPE) \
({ \
const char *s_ = s; \
char **endp_ = endp; \
int base_ = base; \
TYPE min_ = min; \
TYPE max_ = max; \
int *status_ = status; \
\
int e_, st_; \
char *end_; \
TYPE n_; \
\
if (endp_ == NULL) \
endp_ = &end_; \
if (status_ == NULL) \
status_ = &st_; \
\
if (base_ != 0 && (base_ < 0 || base_ > 36)) { \
*status_ = EINVAL; \
n_ = 0; \
\
} else { \
e_ = errno; \
errno = 0; \
n_ = strtoNmax(TYPE, s_, endp_, base_); \
\
if (*endp_ == s_) \
*status_ = ECANCELED; \
else if (errno == ERANGE || n_ < min_ || n_ > max_) \
*status_ = ERANGE; \
else if (**endp_ != '\0') \
*status_ = ENOTSUP; \
else \
*status_ = 0; \
\
errno = e_; \
} \
MAX(min_, MIN(max_, n_)); \
})
ATTR_STRING(1) ATTR_ACCESS(write_only, 2) ATTR_ACCESS(write_only, 6)
inline intmax_t strtoi_(const char *s, char **restrict endp, int base,
intmax_t min, intmax_t max, int *restrict status);
ATTR_STRING(1) ATTR_ACCESS(write_only, 2) ATTR_ACCESS(write_only, 6)
inline uintmax_t strtou_(const char *s, char **restrict endp, int base,
uintmax_t min, uintmax_t max, int *restrict status);
inline intmax_t
strtoi_(const char *s, char **restrict endp, int base,
intmax_t min, intmax_t max, int *restrict status)
{
return strtoN(s, endp, base, min, max, status, intmax_t);
}
inline uintmax_t
strtou_(const char *s, char **restrict endp, int base,
uintmax_t min, uintmax_t max, int *restrict status)
{
return strtoN(s, endp, base, min, max, status, uintmax_t);
}
#endif // include guard

13
lib/atoi/strtoi/strtoi.c Normal file
View File

@@ -0,0 +1,13 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/strtoi/strtoi.h"
#include <stdint.h>
extern inline intmax_t strtoi_(const char *s, char **restrict endp, int base,
intmax_t min, intmax_t max, int *restrict status);

64
lib/atoi/strtoi/strtoi.h Normal file
View File

@@ -0,0 +1,64 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_STRTOI_STRTOI_H_
#define SHADOW_INCLUDE_LIB_ATOI_STRTOI_STRTOI_H_
#include <config.h>
#include <errno.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/param.h>
#include "attr.h"
ATTR_STRING(1) ATTR_ACCESS(write_only, 2) ATTR_ACCESS(write_only, 6)
inline intmax_t strtoi_(const char *s, char **restrict endp, int base,
intmax_t min, intmax_t max, int *restrict status);
inline intmax_t
strtoi_(const char *s, char **restrict endp, int base,
intmax_t min, intmax_t max, int *restrict status)
{
int e, st;
char *end;
intmax_t n;
if (endp == NULL)
endp = &end;
if (status == NULL)
status = &st;
if (base != 0 && (base < 2 || base > 36)) {
*status = EINVAL;
return MAX(min, MIN(max, 0));
}
e = errno;
errno = 0;
n = strtoimax(s, endp, base);
if (*endp == s)
*status = ECANCELED;
else if (errno == ERANGE || n < min || n > max)
*status = ERANGE;
else if (**endp != '\0')
*status = ENOTSUP;
else
*status = 0;
errno = e;
return MAX(min, MIN(max, n));
}
#endif // include guard

13
lib/atoi/strtoi/strtou.c Normal file
View File

@@ -0,0 +1,13 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/strtoi/strtou.h"
#include <stdint.h>
extern inline uintmax_t strtou_(const char *s, char **restrict endp, int base,
uintmax_t min, uintmax_t max, int *restrict status);

64
lib/atoi/strtoi/strtou.h Normal file
View File

@@ -0,0 +1,64 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_STRTOI_STRTOU_H_
#define SHADOW_INCLUDE_LIB_ATOI_STRTOI_STRTOU_H_
#include <config.h>
#include <errno.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/param.h>
#include "attr.h"
ATTR_STRING(1) ATTR_ACCESS(write_only, 2) ATTR_ACCESS(write_only, 6)
inline uintmax_t strtou_(const char *s, char **restrict endp, int base,
uintmax_t min, uintmax_t max, int *restrict status);
inline uintmax_t
strtou_(const char *s, char **restrict endp, int base,
uintmax_t min, uintmax_t max, int *restrict status)
{
int e, st;
char *end;
uintmax_t n;
if (endp == NULL)
endp = &end;
if (status == NULL)
status = &st;
if (base != 0 && (base < 2 || base > 36)) {
*status = EINVAL;
return MAX(min, 0);
}
e = errno;
errno = 0;
n = strtoumax(s, endp, base);
if (*endp == s)
*status = ECANCELED;
else if (errno == ERANGE || n < min || n > max)
*status = ERANGE;
else if (**endp != '\0')
*status = ENOTSUP;
else
*status = 0;
errno = e;
return MAX(min, MIN(max, n));
}
#endif // include guard

View File

@@ -0,0 +1,13 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/strtoi/strtou_noneg.h"
#include <stdint.h>
extern inline uintmax_t strtou_noneg(const char *s, char **restrict endp,
int base, uintmax_t min, uintmax_t max, int *restrict status);

View File

@@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_STRTOI_STRTOU_NONEG_H_
#define SHADOW_INCLUDE_LIB_ATOI_STRTOI_STRTOU_NONEG_H_
#include <config.h>
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include "atoi/strtoi/strtoi.h"
#include "atoi/strtoi/strtou.h"
#include "attr.h"
ATTR_STRING(1) ATTR_ACCESS(write_only, 2) ATTR_ACCESS(write_only, 6)
inline uintmax_t strtou_noneg(const char *s, char **restrict endp,
int base, uintmax_t min, uintmax_t max, int *restrict status);
inline uintmax_t
strtou_noneg(const char *s, char **restrict endp, int base,
uintmax_t min, uintmax_t max, int *restrict status)
{
int st;
if (status == NULL)
status = &st;
if (strtoi_(s, endp, base, 0, 1, status) == 0 && *status == ERANGE)
return min;
return strtou_(s, endp, base, min, max, status);
}
#endif // include guard

View File

@@ -1,18 +0,0 @@
// SPDX-FileCopyrightText: 2023, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "atoi/strtou_noneg.h"
#include <stdint.h>
extern inline uintmax_t strtou_noneg(const char *s, char **restrict endp,
int base, uintmax_t min, uintmax_t max, int *restrict status);
extern inline unsigned long strtoul_noneg(const char *s,
char **restrict endp, int base);
extern inline unsigned long long strtoull_noneg(const char *s,
char **restrict endp, int base);

View File

@@ -1,68 +0,0 @@
// SPDX-FileCopyrightText: 2023, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_STRTOU_NONEG_H_
#define SHADOW_INCLUDE_LIB_ATOI_STRTOU_NONEG_H_
#include <config.h>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include "atoi/strtoi.h"
#include "attr.h"
ATTR_STRING(1) ATTR_ACCESS(write_only, 2) ATTR_ACCESS(write_only, 6)
inline uintmax_t strtou_noneg(const char *s, char **restrict endp,
int base, uintmax_t min, uintmax_t max, int *restrict status);
ATTR_STRING(1) ATTR_ACCESS(write_only, 2)
inline unsigned long strtoul_noneg(const char *s,
char **restrict endp, int base);
ATTR_STRING(1) ATTR_ACCESS(write_only, 2)
inline unsigned long long strtoull_noneg(const char *s,
char **restrict endp, int base);
inline uintmax_t
strtou_noneg(const char *s, char **restrict endp, int base,
uintmax_t min, uintmax_t max, int *restrict status)
{
int st;
if (status == NULL)
status = &st;
if (strtoi_(s, endp, base, 0, 1, status) == 0 && *status == ERANGE)
return min;
return strtou_(s, endp, base, min, max, status);
}
inline unsigned long
strtoul_noneg(const char *s, char **restrict endp, int base)
{
if (strtol(s, endp, base) < 0) {
errno = ERANGE;
return 0;
}
return strtoul(s, endp, base);
}
inline unsigned long long
strtoull_noneg(const char *s, char **restrict endp, int base)
{
if (strtol(s, endp, base) < 0) {
errno = ERANGE;
return 0;
}
return strtoull(s, endp, base);
}
#endif // include guard

View File

@@ -6,15 +6,17 @@
#if defined(__GNUC__)
# define MAYBE_UNUSED __attribute__((unused))
# define NORETURN __attribute__((__noreturn__))
# define format_attr(type, fmt, va) __attribute__((format(type, fmt, va)))
# define ATTR_ACCESS(...) __attribute__((access(__VA_ARGS__)))
# define MAYBE_UNUSED [[gnu::unused]]
# define NORETURN [[gnu::__noreturn__]]
# define format_attr(type, fmt, va) [[gnu::format(type, fmt, va)]]
# define ATTR_ACCESS(...) [[gnu::access(__VA_ARGS__)]]
# define ATTR_ALLOC_SIZE(...) [[gnu::alloc_size(__VA_ARGS__)]]
#else
# define MAYBE_UNUSED
# define NORETURN
# define format_attr(type, fmt, va)
# define ATTR_ACCESS(...)
# define ATTR_ALLOC_SIZE(...)
#endif
#if (__GNUC__ >= 11) && !defined(__clang__)
@@ -24,9 +26,9 @@
#endif
#if (__GNUC__ >= 14)
# define ATTR_STRING(...) [[gnu::null_terminated_string_arg(__VA_ARGS__)]]
# define ATTR_STRING(i) [[gnu::null_terminated_string_arg(i)]]
#else
# define ATTR_STRING(...)
# define ATTR_STRING(i)
#endif

View File

@@ -8,14 +8,8 @@
#include <config.h>
#include "must_be.h"
#define const_cast(T, p) \
({ \
static_assert(is_same_type(typeof(&*(p)), const T), ""); \
(T) (p); \
})
#define const_cast(T, p) _Generic(p, const T: (T) (p))
#endif // include guard

View File

@@ -5,14 +5,19 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
/*
* is_valid_user_name(), is_valid_group_name() - check the new user/group
* name for validity;
* return values:
* true - OK
* false - bad name
* errors:
* EINVAL Invalid name characters or sequences
* EOVERFLOW Name longer than maximum size
*/
#include <config.h>
#ident "$Id$"
@@ -20,12 +25,36 @@
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/param.h>
#include <unistd.h>
#include "defines.h"
#include "chkname.h"
#include "string/strcmp/streq.h"
int allow_bad_names = false;
static bool is_valid_name (const char *name)
size_t
login_name_max_size(void)
{
long conf;
errno = 0;
conf = sysconf(_SC_LOGIN_NAME_MAX);
if (conf == -1 && errno != 0)
return LOGIN_NAME_MAX;
return MIN(conf, PTRDIFF_MAX);
}
static bool
is_valid_name(const char *name)
{
if (allow_bad_names) {
return true;
@@ -49,13 +78,15 @@ static bool is_valid_name (const char *name)
(*name >= 'A' && *name <= 'Z') ||
(*name >= '0' && *name <= '9') ||
*name == '_' ||
*name == '.')) {
*name == '.'))
{
errno = EINVAL;
return false;
}
numeric = isdigit(*name);
while ('\0' != *++name) {
while (!streq(++name, "")) {
if (!((*name >= 'a' && *name <= 'z') ||
(*name >= 'A' && *name <= 'Z') ||
(*name >= '0' && *name <= '9') ||
@@ -63,45 +94,46 @@ static bool is_valid_name (const char *name)
*name == '.' ||
*name == '-' ||
(*name == '$' && name[1] == '\0')
)) {
))
{
errno = EINVAL;
return false;
}
numeric &= isdigit(*name);
}
return !numeric;
if (numeric) {
errno = EINVAL;
return false;
}
return true;
}
bool
is_valid_user_name(const char *name)
{
long conf;
size_t maxsize;
errno = 0;
conf = sysconf(_SC_LOGIN_NAME_MAX);
if (conf == -1 && errno != 0)
maxsize = LOGIN_NAME_MAX;
else
maxsize = conf;
if (strlen(name) >= maxsize)
if (strlen(name) >= login_name_max_size()) {
errno = EOVERFLOW;
return false;
}
return is_valid_name(name);
}
bool is_valid_group_name (const char *name)
bool
is_valid_group_name(const char *name)
{
/*
* Arbitrary limit for group names.
* HP-UX 10 limits to 16 characters
*/
if ( (GROUP_NAME_MAX_LENGTH > 0)
&& (strlen (name) > GROUP_NAME_MAX_LENGTH)) {
&& (strlen (name) > GROUP_NAME_MAX_LENGTH))
{
errno = EOVERFLOW;
return false;
}

View File

@@ -11,6 +11,7 @@
#ifndef _CHKNAME_H_
#define _CHKNAME_H_
/*
* is_valid_user_name(), is_valid_group_name() - check the new user/group
* name for validity;
@@ -19,8 +20,14 @@
* false - bad name
*/
#include "defines.h"
#include <config.h>
#include <stdbool.h>
#include <stddef.h>
extern size_t login_name_max_size(void);
extern bool is_valid_user_name (const char *name);
extern bool is_valid_group_name (const char *name);

View File

@@ -13,12 +13,15 @@
#include <sys/types.h>
#include <sys/stat.h>
#include "prototypes.h"
#include "defines.h"
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include "defines.h"
#include "prototypes.h"
#include "string/strcmp/streq.h"
static int chown_tree_at (int at_fd,
const char *path,
uid_t old_uid,
@@ -56,8 +59,8 @@ static int chown_tree_at (int at_fd,
/*
* Skip the "." and ".." entries
*/
if ( (strcmp (ent->d_name, ".") == 0)
|| (strcmp (ent->d_name, "..") == 0)) {
if ( streq(ent->d_name, ".")
|| streq(ent->d_name, "..")) {
continue;
}

View File

@@ -44,7 +44,7 @@ void do_cleanups (void)
{
unsigned int i;
/* Make sure there were no overflow */
/* Make sure there were no overflows */
assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-1]);
if (getpid () != cleanup_pid) {

View File

@@ -11,28 +11,33 @@
#ident "$Id$"
#include "defines.h"
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <limits.h>
#include <utime.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include "alloc.h"
#include "memzero.h"
#include "alloc/malloc.h"
#include "alloc/reallocf.h"
#include "atoi/getnum.h"
#include "commonio.h"
#include "defines.h"
#include "nscd.h"
#include "sssd.h"
#ifdef WITH_TCB
#include <tcb.h>
#endif /* WITH_TCB */
#include "prototypes.h"
#include "commonio.h"
#include "shadowlog_internal.h"
#include "string/sprintf.h"
#include "sssd.h"
#include "string/memset/memzero.h"
#include "string/sprintf/snprintf.h"
#include "string/strcmp/streq.h"
#include "string/strtok/stpsep.h"
/* local function prototypes */
@@ -194,7 +199,7 @@ static int do_lock_file (const char *file, const char *lock, bool log)
errno = EINVAL;
return 0;
}
buf[len] = '\0';
stpcpy(&buf[len], "");
if (get_pid(buf, &pid) == -1) {
if (log) {
(void) fprintf (shadow_logfd,
@@ -573,9 +578,7 @@ static void add_one_entry_nis (struct commonio_db *db,
int commonio_open (struct commonio_db *db, int mode)
{
char *buf;
char *cp;
char *line;
struct commonio_entry *p;
void *eptr = NULL;
int flags = mode;
size_t buflen;
@@ -636,21 +639,21 @@ int commonio_open (struct commonio_db *db, int mode)
buflen = BUFLEN;
buf = MALLOC(buflen, char);
if (NULL == buf) {
goto cleanup_ENOMEM;
}
if (NULL == buf)
goto cleanup_errno;
while (db->ops->fgets (buf, buflen, db->fp) == buf) {
struct commonio_entry *p;
while ( (strrchr (buf, '\n') == NULL)
&& (feof (db->fp) == 0)) {
size_t len;
buflen += BUFLEN;
cp = REALLOC(buf, buflen, char);
if (NULL == cp) {
goto cleanup_buf;
}
buf = cp;
buf = REALLOCF(buf, buflen, char);
if (NULL == buf)
goto cleanup_errno;
len = strlen (buf);
if (db->ops->fgets (buf + len,
(int) (buflen - len),
@@ -658,10 +661,7 @@ int commonio_open (struct commonio_db *db, int mode)
goto cleanup_buf;
}
}
cp = strrchr (buf, '\n');
if (NULL != cp) {
*cp = '\0';
}
stpsep(buf, "\n");
line = strdup (buf);
if (NULL == line) {
@@ -713,7 +713,6 @@ int commonio_open (struct commonio_db *db, int mode)
free (line);
cleanup_buf:
free (buf);
cleanup_ENOMEM:
errno = ENOMEM;
cleanup_errno:
saved_errno = errno;
@@ -832,10 +831,8 @@ int commonio_sort_wrt (struct commonio_db *shadow,
if (NULL == spw_ptr->eptr) {
continue;
}
if (strcmp (name, shadow->ops->getname (spw_ptr->eptr))
== 0) {
if (streq(name, shadow->ops->getname(spw_ptr->eptr)))
break;
}
}
if (NULL == spw_ptr) {
continue;
@@ -1036,7 +1033,7 @@ static /*@dependent@*/ /*@null@*/struct commonio_entry *next_entry_by_name (
for (p = pos; NULL != p; p = p->next) {
ep = p->eptr;
if ( (NULL != ep)
&& (strcmp (db->ops->getname (ep), name) == 0)) {
&& streq(db->ops->getname(ep), name)) {
break;
}
}
@@ -1242,7 +1239,7 @@ int commonio_rewind (struct commonio_db *db)
if (!db->isopen) {
errno = EINVAL;
return 0;
return NULL;
}
if (NULL == db->cursor) {
db->cursor = db->head;

View File

@@ -9,20 +9,25 @@
*/
#include <config.h>
#include "defines.h"
#include <stdio.h>
#include <string.h>
#include "defines.h"
#include "getdef.h"
#include "prototypes.h"
#include "string/strtcpy.h"
#include "string/strcmp/streq.h"
#include "string/strcpy/strtcpy.h"
#include "string/strtok/stpsep.h"
#ident "$Id$"
/*
* This is now rather generic function which decides if "tty" is listed
* under "cfgin" in config (directly or indirectly). Fallback to default if
* something is bad.
*/
static bool is_listed (const char *cfgin, const char *tty, bool def)
static bool
is_listed(const char *cfgin, const char *tty, bool def)
{
FILE *fp;
char buf[1024], *s;
@@ -45,14 +50,13 @@ static bool is_listed (const char *cfgin, const char *tty, bool def)
if (*cons != '/') {
char *pbuf;
STRTCPY(buf, cons);
pbuf = &buf[0];
while ((s = strtok (pbuf, ":")) != NULL) {
if (strcmp (s, tty) == 0) {
pbuf = buf;
while (NULL != (s = strsep(&pbuf, ":"))) {
if (streq(s, tty)) {
return true;
}
pbuf = NULL;
}
return false;
}
@@ -72,9 +76,8 @@ static bool is_listed (const char *cfgin, const char *tty, bool def)
*/
while (fgets (buf, sizeof (buf), fp) != NULL) {
/* Remove optional trailing '\n'. */
buf[strcspn (buf, "\n")] = '\0';
if (strcmp (buf, tty) == 0) {
stpsep(buf, "\n");
if (streq(buf, tty)) {
(void) fclose (fp);
return true;
}

View File

@@ -17,9 +17,11 @@
#include <sys/time.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include "alloc.h"
#include "alloc/x/xmalloc.h"
#include "attr.h"
#include "fs/readlink/areadlink.h"
#include "prototypes.h"
#include "defines.h"
#ifdef WITH_SELINUX
@@ -36,7 +38,8 @@
#include <attr/libattr.h>
#endif /* WITH_ATTR */
#include "shadowlog.h"
#include "string/sprintf.h"
#include "string/sprintf/xasprintf.h"
#include "string/strcmp/streq.h"
static /*@null@*/const char *src_orig;
@@ -66,7 +69,6 @@ static int copy_dir (const struct path_info *src, const struct path_info *dst,
const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static /*@null@*/char *readlink_malloc (const char *filename);
static int copy_symlink (const struct path_info *src, const struct path_info *dst,
MAYBE_UNUSED bool reset_selinux,
const struct stat *statp, const struct timespec mt[],
@@ -313,8 +315,8 @@ static int copy_tree_impl (const struct path_info *src, const struct path_info *
/*
* Skip the "." and ".." entries
*/
if (strcmp(ent->d_name, ".") == 0 ||
strcmp(ent->d_name, "..") == 0)
if (streq(ent->d_name, ".") ||
streq(ent->d_name, ".."))
{
continue;
}
@@ -400,6 +402,7 @@ static int copy_entry (const struct path_info *src, const struct path_info *dst,
{
int err = 0;
struct stat sb;
struct stat tmp_sb;
struct link_name *lp;
struct timespec mt[2];
@@ -423,7 +426,7 @@ static int copy_entry (const struct path_info *src, const struct path_info *dst,
* If the destination already exists do nothing.
* This is after the copy_dir above to still iterate into subdirectories.
*/
if (fstatat(dst->dirfd, dst->name, &sb, AT_SYMLINK_NOFOLLOW) != -1) {
if (fstatat(dst->dirfd, dst->name, &tmp_sb, AT_SYMLINK_NOFOLLOW) != -1) {
return err;
}
@@ -535,42 +538,6 @@ static int copy_dir (const struct path_info *src, const struct path_info *dst,
return err;
}
/*
* readlink_malloc - wrapper for readlink
*
* return NULL on error.
* The return string shall be freed by the caller.
*/
static /*@null@*/char *readlink_malloc (const char *filename)
{
size_t size = 1024;
while (true) {
ssize_t nchars;
char *buffer = MALLOC(size, char);
if (NULL == buffer) {
return NULL;
}
nchars = readlink (filename, buffer, size);
if (nchars < 0) {
free(buffer);
return NULL;
}
if ((size_t) nchars < size) { /* The buffer was large enough */
/* readlink does not nul-terminate */
buffer[nchars] = '\0';
return buffer;
}
/* Try again with a bigger buffer */
free (buffer);
size *= 2;
}
}
/*
* copy_symlink - copy a symlink
*
@@ -601,10 +568,9 @@ static int copy_symlink (const struct path_info *src, const struct path_info *ds
* destination directory name.
*/
oldlink = readlink_malloc (src->full_path);
if (NULL == oldlink) {
oldlink = areadlink(src->full_path);
if (NULL == oldlink)
return -1;
}
/* If src was a link to an entry of the src_orig directory itself,
* create a link to the corresponding entry in the dst_orig

View File

@@ -1,21 +1,19 @@
/*
* SPDX-FileCopyrightText: Alejandro Colomar <alx@kernel.org>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
// SPDX-FileCopyrightText: 2022-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#ident "$Id$"
#include <fcntl.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#if HAVE_SYS_RANDOM_H
#include <sys/random.h>
#endif
#include "bit.h"
#include "defines.h"
#include "prototypes.h"
@@ -23,6 +21,7 @@
#include "sizeof.h"
static uint32_t csrand32(void);
static uint32_t csrand_uniform32(uint32_t n);
static unsigned long csrand_uniform_slow(unsigned long n);
@@ -33,7 +32,7 @@ static unsigned long csrand_uniform_slow(unsigned long n);
unsigned long
csrand(void)
{
FILE *fp;
int fd;
unsigned long r;
#ifdef HAVE_GETENTROPY
@@ -55,17 +54,16 @@ csrand(void)
#endif
/* Use /dev/urandom as a last resort. */
fp = fopen("/dev/urandom", "r");
if (NULL == fp) {
fd = open("/dev/urandom", O_RDONLY);
if (fd == -1)
goto fail;
if (read(fd, &r, sizeof(r)) != sizeof(r)) {
close(fd);
goto fail;
}
if (fread(&r, sizeof(r), 1, fp) != 1) {
fclose(fp);
goto fail;
}
fclose(fp);
close(fd);
return r;
fail:
@@ -97,6 +95,13 @@ csrand_interval(unsigned long min, unsigned long max)
}
static uint32_t
csrand32(void)
{
return csrand();
}
/*
* Fast Random Integer Generation in an Interval
* ACM Transactions on Modeling and Computer Simulation 29 (1), 2019
@@ -109,12 +114,12 @@ csrand_uniform32(uint32_t n)
uint64_t r, mult;
if (n == 0)
return csrand();
return csrand32();
bound = -n % n; // analogous to `2^32 % n`, since `x % y == (x-y) % y`
do {
r = csrand();
r = csrand32();
mult = r * n;
rem = mult; // analogous to `mult % 2^32`
} while (rem < bound); // p = (2^32 % n) / 2^32; W.C.: n=2^31+1, p=0.5

View File

@@ -1,38 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2023, Alejandro Colomar <alx@kernel.org>
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <config.h>
#include <string.h>
#include <time.h>
#ident "$Id$"
#include "string/strtcpy.h"
#include "prototypes.h"
void
date_to_str(size_t size, char buf[size], long date)
{
time_t t;
const struct tm *tm;
t = date;
if (date < 0) {
(void) strtcpy(buf, "never", size);
return;
}
tm = gmtime(&t);
if (tm == NULL) {
(void) strtcpy(buf, "future", size);
return;
}
if (strftime(buf, size, "%Y-%m-%d", tm) == 0)
(void) strtcpy(buf, "future", size);
}

View File

@@ -25,6 +25,7 @@
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -202,4 +203,14 @@
# define shadow_getenv(name) getenv(name)
#endif
/*
* Maximum password length
*
* Consider that there is also limit in PAM (PAM_MAX_RESP_SIZE)
* currently set to 512.
*/
#if !defined(PASS_MAX)
#define PASS_MAX BUFSIZ - 1
#endif
#endif /* _DEFINES_H_ */

View File

@@ -16,11 +16,14 @@
#include <stdlib.h>
#include <string.h>
#include "alloc.h"
#include "alloc/x/xmalloc.h"
#include "alloc/x/xrealloc.h"
#include "prototypes.h"
#include "defines.h"
#include "shadowlog.h"
#include "string/sprintf.h"
#include "string/sprintf/snprintf.h"
#include "string/sprintf/xasprintf.h"
#include "string/strdup/xstrdup.h"
/*
@@ -127,30 +130,18 @@ void addenv (const char *string, /*@null@*/const char *value)
if ((newenvc & (NEWENVP_STEP - 1)) == 0) {
bool update_environ;
char **__newenvp;
/*
* If the resize operation succeeds we can
* happily go on, else print a message.
*/
update_environ = (environ == newenvp);
__newenvp = REALLOC(newenvp, newenvc + NEWENVP_STEP, char *);
newenvp = XREALLOC(newenvp, newenvc + NEWENVP_STEP, char *);
if (NULL != __newenvp) {
/*
* If this is our current environment, update
* environ so that it doesn't point to some
* free memory area (realloc() could move it).
*/
if (update_environ)
environ = __newenvp;
newenvp = __newenvp;
} else {
(void) fputs (_("Environment overflow\n"), log_get_logfd());
newenvc--;
free (newenvp[newenvc]);
}
/*
* If this is our current environment, update
* environ so that it doesn't point to some
* free memory area (realloc() could move it).
*/
if (update_environ)
environ = newenvp;
}
/*

View File

@@ -14,12 +14,14 @@
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include "defines.h"
#include "faillog.h"
#include "failure.h"
#include "memzero.h"
#include "prototypes.h"
#include "string/strtcpy.h"
#include "string/memset/memzero.h"
#include "string/strftime.h"
#include "string/strcpy/strtcpy.h"
#define YEAR (365L*DAY)
@@ -80,7 +82,7 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
}
STRTCPY(fl->fail_line, tty);
(void) time (&fl->fail_time);
fl->fail_time = time(NULL);
/*
* Seek back to the correct position in the file and write the
@@ -124,7 +126,7 @@ static bool too_many_failures (const struct faillog *fl)
return true; /* locked until reset manually */
}
(void) time (&now);
now = time(NULL);
if ((fl->fail_time + fl->fail_locktime) < now) {
return false; /* enough time since last failure */
}
@@ -240,19 +242,17 @@ void failprint (const struct faillog *fail)
struct tm *tp;
char lasttimeb[256];
char *lasttime = lasttimeb;
time_t NOW;
if (0 == fail->fail_cnt) {
return;
}
tp = localtime (&(fail->fail_time));
(void) time (&NOW);
/*
* Print all information we have.
*/
(void) strftime (lasttimeb, sizeof lasttimeb, "%c", tp);
STRFTIME(lasttimeb, "%c", tp);
/*@-formatconst@*/
(void) printf (ngettext ("%d failure since last login.\n"

41
lib/fd.c Normal file
View File

@@ -0,0 +1,41 @@
// SPDX-FileCopyrightText: 2024, Skyler Ferrante <sjf5462@rit.edu>
// SPDX-License-Identifier: BSD-3-Clause
/**
* To protect against file descriptor omission attacks, we open the std file
* descriptors with /dev/null if they are not already open. Code is based on
* fix_fds from sudo.c.
*/
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include "prototypes.h"
static void check_fd(int fd);
void
check_fds(void)
{
/**
* Make sure stdin, stdout, stderr are open
* If they are closed, set them to /dev/null
*/
check_fd(STDIN_FILENO);
check_fd(STDOUT_FILENO);
check_fd(STDERR_FILENO);
}
static void
check_fd(int fd)
{
int devnull;
if (fcntl(fd, F_GETFL, 0) != -1)
return;
devnull = open("/dev/null", O_RDWR);
if (devnull != fd)
abort();
}

View File

@@ -14,7 +14,13 @@
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include "prototypes.h"
#include "string/strchr/stpspn.h"
#include "string/strchr/strrspn.h"
#include "string/strcmp/streq.h"
#include "string/strtok/stpsep.h"
/*
* valid_field - insure that a field contains all legal characters
@@ -42,7 +48,7 @@ int valid_field (const char *field, const char *illegal)
}
/* Search if there are non-printable or control characters */
for (cp = field; '\0' != *cp; cp++) {
for (cp = field; !streq(cp, ""); cp++) {
unsigned char c = *cp;
if (!isprint (c)) {
err = 1;
@@ -62,7 +68,8 @@ int valid_field (const char *field, const char *illegal)
* prompt the user with the name of the field being changed and the
* current value.
*/
void change_field (char *buf, size_t maxsize, const char *prompt)
void
change_field(char *buf, size_t maxsize, const char *prompt)
{
char newf[200];
char *cp;
@@ -77,29 +84,17 @@ void change_field (char *buf, size_t maxsize, const char *prompt)
return;
}
cp = strchr (newf, '\n');
if (NULL == cp) {
if (stpsep(newf, "\n") == NULL)
return;
}
*cp = '\0';
if ('\0' != newf[0]) {
if (!streq(newf, "")) {
/*
* Remove leading and trailing whitespace. This also
* makes it possible to change the field to empty, by
* entering a space. --marekm
*/
while (newf < cp && isspace (cp[-1])) {
cp--;
}
*cp = '\0';
cp = newf;
while (isspace (*cp)) {
cp++;
}
stpcpy(strrspn(newf, " \t"), "");
cp = stpspn(newf, " \t");
strcpy (buf, cp);
}
}

View File

@@ -9,10 +9,11 @@
#include <config.h>
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include "alloc.h"
#include "alloc/calloc.h"
#include "prototypes.h"
#include "groupio.h"
#include "getdef.h"

View File

@@ -9,10 +9,11 @@
#include <config.h>
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include "alloc.h"
#include "alloc/calloc.h"
#include "prototypes.h"
#include "pwio.h"
#include "getdef.h"
@@ -304,7 +305,7 @@ int find_new_uid(bool sys_user,
return 0;
} else if (result == EEXIST || result == EINVAL) {
/*
* This GID is in use or unusable, we'll
* This UID is in use or unusable, we'll
* continue to the next.
*/
} else {
@@ -350,7 +351,7 @@ int find_new_uid(bool sys_user,
return 0;
} else if (result == EEXIST || result == EINVAL) {
/*
* This GID is in use or unusable, we'll
* This UID is in use or unusable, we'll
* continue to the next.
*/
} else {
@@ -413,7 +414,7 @@ int find_new_uid(bool sys_user,
return 0;
} else if (result == EEXIST || result == EINVAL) {
/*
* This GID is in use or unusable, we'll
* This UID is in use or unusable, we'll
* continue to the next.
*/
} else {
@@ -459,7 +460,7 @@ int find_new_uid(bool sys_user,
return 0;
} else if (result == EEXIST || result == EINVAL) {
/*
* This GID is in use or unusable, we'll
* This UID is in use or unusable, we'll
* continue to the next.
*/
} else {

View File

@@ -10,10 +10,11 @@
#include <config.h>
#include <stdio.h>
#include <string.h>
#include "defines.h"
#include "prototypes.h"
#ident "$Id$"
#include "string/strcmp/streq.h"
/*@null@*/char *
@@ -25,7 +26,7 @@ fgetsx(/*@returned@*/char *restrict buf, int cnt, FILE *restrict f)
while (cnt > 0) {
if (fgets (cp, cnt, f) != cp) {
if (cp == buf) {
return 0;
return NULL;
} else {
break;
}
@@ -33,10 +34,8 @@ fgetsx(/*@returned@*/char *restrict buf, int cnt, FILE *restrict f)
ep = strrchr (cp, '\\');
if ((NULL != ep) && (*(ep + 1) == '\n')) {
cnt -= ep - cp;
if (cnt > 0) {
cp = ep;
*cp = '\0';
}
if (cnt > 0)
cp = stpcpy(ep, "");
} else {
break;
}
@@ -48,7 +47,7 @@ int fputsx (const char *s, FILE * stream)
{
int i;
for (i = 0; '\0' != *s; i++, s++) {
for (i = 0; !streq(s, ""); i++, s++) {
if (putc (*s, stream) == EOF) {
return EOF;
}

View File

@@ -0,0 +1,10 @@
// SPDX-FileCopyrightText: 2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "fs/readlink/areadlink.h"
extern inline char *areadlink(const char *link);

View File

@@ -0,0 +1,53 @@
// SPDX-FileCopyrightText: 2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_FS_READLINK_AREADLINK_H_
#define SHADOW_INCLUDE_LIB_FS_READLINK_AREADLINK_H_
#include <config.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include "alloc/malloc.h"
#include "attr.h"
#include "fs/readlink/readlinknul.h"
ATTR_STRING(1)
inline char *areadlink(const char *link);
// Similar to readlink(2), but allocate and terminate the string.
inline char *
areadlink(const char *link)
{
size_t size = PATH_MAX;
while (true) {
int len;
char *buf;
buf = MALLOC(size, char);
if (NULL == buf)
return NULL;
len = readlinknul(link, buf, size);
if (len != -1)
return buf;
free(buf);
if (errno != E2BIG)
return NULL;
size *= 2;
}
}
#endif // include guard

View File

@@ -0,0 +1,14 @@
// SPDX-FileCopyrightText: 2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "fs/readlink/readlinknul.h"
#include <stddef.h>
#include <sys/types.h>
extern inline ssize_t readlinknul(const char *restrict link, char *restrict buf,
size_t size);

View File

@@ -0,0 +1,53 @@
// SPDX-FileCopyrightText: 2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_FS_READLINK_READLINKNUL_H_
#define SHADOW_INCLUDE_LIB_FS_READLINK_READLINKNUL_H_
#include <config.h>
#include <errno.h>
#include <stddef.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "attr.h"
#include "sizeof.h"
#define READLINKNUL(link, buf) readlinknul(link, buf, NITEMS(buf))
ATTR_STRING(1)
inline ssize_t readlinknul(const char *restrict link, char *restrict buf,
size_t size);
// Similar to readlink(2), but terminate the string.
inline ssize_t
readlinknul(const char *restrict link, char *restrict buf, size_t size)
{
size_t ulen;
ssize_t slen;
slen = readlink(link, buf, size);
if (slen == -1)
return -1;
ulen = slen;
if (ulen == size) {
stpcpy(&buf[size-1], "");
errno = E2BIG;
return -1;
}
stpcpy(&buf[ulen], "");
return slen;
}
#endif // include guard

View File

@@ -1,34 +0,0 @@
/*
* SPDX-FileCopyrightText: 2009 , Nicolas François
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <config.h>
#ident "$Id$"
#include "prototypes.h"
#include "defines.h"
int
get_gid(const char *gidstr, gid_t *gid)
{
long long val;
char *endptr;
errno = 0;
val = strtoll(gidstr, &endptr, 10);
if ( ('\0' == *gidstr)
|| ('\0' != *endptr)
|| (0 != errno)
|| (/*@+longintegral@*/val != (gid_t)val)/*@=longintegral@*/) {
return -1;
}
*gid = val;
return 0;
}

View File

@@ -1,8 +1,7 @@
/*
* SPDX-FileCopyrightText: 2009 , Nicolas François
*
* SPDX-License-Identifier: BSD-3-Clause
*/
// SPDX-FileCopyrightText: 2009, Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
@@ -14,28 +13,10 @@
#include <sys/stat.h>
#include <fcntl.h>
#include "string/sprintf.h"
#include "atoi/getnum.h"
#include "string/sprintf/snprintf.h"
int get_pid (const char *pidstr, pid_t *pid)
{
long long val;
char *endptr;
errno = 0;
val = strtoll(pidstr, &endptr, 10);
if ( ('\0' == *pidstr)
|| ('\0' != *endptr)
|| (0 != errno)
|| (val < 1)
|| (/*@+longintegral@*/val != (pid_t)val)/*@=longintegral@*/) {
return -1;
}
*pid = val;
return 0;
}
/*
* If use passed in fd:4 as an argument, then return the
* value '4', the fd to use.
@@ -43,20 +24,12 @@ int get_pid (const char *pidstr, pid_t *pid)
*/
int get_pidfd_from_fd(const char *pidfdstr)
{
long long val;
char *endptr;
struct stat st;
int pidfd;
struct stat st;
dev_t proc_st_dev, proc_st_rdev;
errno = 0;
val = strtoll(pidfdstr, &endptr, 10);
if ( ('\0' == *pidfdstr)
|| ('\0' != *endptr)
|| (0 != errno)
|| (val < 0)
|| (/*@+longintegral@*/val != (int)val)/*@=longintegral@*/) {
if (get_fd(pidfdstr, &pidfd) == -1)
return -1;
}
if (stat("/proc/self/uid_map", &st) < 0) {
return -1;
@@ -65,7 +38,7 @@ int get_pidfd_from_fd(const char *pidfdstr)
proc_st_dev = st.st_dev;
proc_st_rdev = st.st_rdev;
if (fstat(val, &st) < 0) {
if (fstat(pidfd, &st) < 0) {
return -1;
}
@@ -73,7 +46,7 @@ int get_pidfd_from_fd(const char *pidfdstr)
return -1;
}
return (int)val;
return pidfd;
}
int open_pidfd(const char *pidstr)

View File

@@ -1,34 +0,0 @@
/*
* SPDX-FileCopyrightText: 2009 , Nicolas François
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <config.h>
#ident "$Id$"
#include "prototypes.h"
#include "defines.h"
int
get_uid(const char *uidstr, uid_t *uid)
{
long long val;
char *endptr;
errno = 0;
val = strtoll(uidstr, &endptr, 10);
if ( ('\0' == *uidstr)
|| ('\0' != *endptr)
|| (0 != errno)
|| (/*@+longintegral@*/val != (uid_t)val)/*@=longintegral@*/) {
return -1;
}
*uid = val;
return 0;
}

View File

@@ -24,14 +24,16 @@
# undef static
#endif
#include <stdio.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "attr.h"
#include "getdate.h"
#include "string/strchr/stpspn.h"
#include "string/strcmp/streq.h"
#include <string.h>
/* Some old versions of bison generate parsers that use bcopy.
That loses on systems that don't provide the function, so we have
@@ -319,7 +321,7 @@ relunit : tUNUMBER tYEAR_UNIT {
yyRelYear += $1 * $2;
}
| tYEAR_UNIT {
yyRelYear++;
yyRelYear += $1;
}
| tUNUMBER tMONTH_UNIT {
yyRelMonth += $1 * $2;
@@ -328,7 +330,7 @@ relunit : tUNUMBER tYEAR_UNIT {
yyRelMonth += $1 * $2;
}
| tMONTH_UNIT {
yyRelMonth++;
yyRelMonth += $1;
}
| tUNUMBER tDAY_UNIT {
yyRelDay += $1 * $2;
@@ -337,7 +339,7 @@ relunit : tUNUMBER tYEAR_UNIT {
yyRelDay += $1 * $2;
}
| tDAY_UNIT {
yyRelDay++;
yyRelDay += $1;
}
| tUNUMBER tHOUR_UNIT {
yyRelHour += $1 * $2;
@@ -346,7 +348,7 @@ relunit : tUNUMBER tYEAR_UNIT {
yyRelHour += $1 * $2;
}
| tHOUR_UNIT {
yyRelHour++;
yyRelHour += $1;
}
| tUNUMBER tMINUTE_UNIT {
yyRelMinutes += $1 * $2;
@@ -355,7 +357,7 @@ relunit : tUNUMBER tYEAR_UNIT {
yyRelMinutes += $1 * $2;
}
| tMINUTE_UNIT {
yyRelMinutes++;
yyRelMinutes += $1;
}
| tUNUMBER tSEC_UNIT {
yyRelSeconds += $1 * $2;
@@ -364,7 +366,7 @@ relunit : tUNUMBER tYEAR_UNIT {
yyRelSeconds += $1 * $2;
}
| tSEC_UNIT {
yyRelSeconds++;
yyRelSeconds += $1;
}
;
@@ -625,16 +627,16 @@ static int LookupWord (char *buff)
bool abbrev;
/* Make it lowercase. */
for (p = buff; '\0' != *p; p++)
for (p = buff; !streq(p, ""); p++)
if (isupper (*p))
*p = tolower (*p);
if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0)
if (streq(buff, "am") || streq(buff, "a.m."))
{
yylval.Meridian = MERam;
return tMERIDIAN;
}
if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0)
if (streq(buff, "pm") || streq(buff, "p.m."))
{
yylval.Meridian = MERpm;
return tMERIDIAN;
@@ -646,7 +648,7 @@ static int LookupWord (char *buff)
else if (strlen (buff) == 4 && buff[3] == '.')
{
abbrev = true;
buff[3] = '\0';
stpcpy(&buff[3], "");
}
else
abbrev = false;
@@ -661,7 +663,7 @@ static int LookupWord (char *buff)
return tp->type;
}
}
else if (strcmp (buff, tp->name) == 0)
else if (streq(buff, tp->name))
{
yylval.Number = tp->value;
return tp->type;
@@ -669,17 +671,17 @@ static int LookupWord (char *buff)
}
for (tp = TimezoneTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0)
if (streq(buff, tp->name))
{
yylval.Number = tp->value;
return tp->type;
}
if (strcmp (buff, "dst") == 0)
if (streq(buff, "dst"))
return tDST;
for (tp = UnitsTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0)
if (streq(buff, tp->name))
{
yylval.Number = tp->value;
return tp->type;
@@ -689,9 +691,9 @@ static int LookupWord (char *buff)
i = strlen (buff) - 1;
if (buff[i] == 's')
{
buff[i] = '\0';
stpcpy(&buff[i], "");
for (tp = UnitsTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0)
if (streq(buff, tp->name))
{
yylval.Number = tp->value;
return tp->type;
@@ -700,7 +702,7 @@ static int LookupWord (char *buff)
}
for (tp = OtherTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0)
if (streq(buff, tp->name))
{
yylval.Number = tp->value;
return tp->type;
@@ -710,7 +712,7 @@ static int LookupWord (char *buff)
if (buff[1] == '\0' && isalpha (*buff))
{
for (tp = MilitaryTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0)
if (streq(buff, tp->name))
{
yylval.Number = tp->value;
return tp->type;
@@ -718,15 +720,15 @@ static int LookupWord (char *buff)
}
/* Drop out any periods and try the timezone table again. */
for (i = 0, p = q = buff; '\0' != *q; q++)
for (i = 0, p = q = buff; !streq(q, ""); q++)
if (*q != '.')
*p++ = *q;
else
i++;
*p = '\0';
stpcpy(p, "");
if (0 != i)
for (tp = TimezoneTable; NULL != tp->name; tp++)
if (strcmp (buff, tp->name) == 0)
if (streq(buff, tp->name))
{
yylval.Number = tp->value;
return tp->type;
@@ -746,8 +748,7 @@ yylex (void)
for (;;)
{
while (isspace (*yyInput))
yyInput++;
yyInput = stpspn(yyInput, " \t");
if (isdigit (c = *yyInput) || c == '-' || c == '+')
{
@@ -772,7 +773,7 @@ yylex (void)
for (p = buff; (c = *yyInput++, isalpha (c)) || c == '.';)
if (p < &buff[sizeof buff - 1])
*p++ = c;
*p = '\0';
stpcpy(p, "");
yyInput--;
return LookupWord (buff);
}
@@ -821,7 +822,7 @@ time_t get_date (const char *p, const time_t *now)
time_t Start;
yyInput = p;
Start = now ? *now : time ((time_t *) NULL);
Start = now ? *now : time(NULL);
tmp = localtime (&Start);
yyYear = tmp->tm_year + TM_YEAR_ORIGIN;
yyMonth = tmp->tm_mon + 1;
@@ -923,11 +924,8 @@ time_t get_date (const char *p, const time_t *now)
#if defined (TEST)
/* ARGSUSED */
int
main (ac, av)
int ac;
char *av[];
main(void)
{
char buff[MAX_BUFF_LEN + 1];
time_t d;
@@ -938,7 +936,7 @@ main (ac, av)
buff[MAX_BUFF_LEN] = 0;
while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
{
d = get_date (buff, (time_t *) NULL);
d = get_date(buff, NULL);
if (d == -1)
(void) printf ("Bad format - couldn't convert.\n");
else

View File

@@ -11,21 +11,29 @@
#ident "$Id$"
#include "prototypes.h"
#include "defines.h"
#include <ctype.h>
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#ifdef USE_ECONF
#include <libeconf.h>
#endif
#include "alloc.h"
#include "atoi/a2i/a2s.h"
#include "atoi/a2i/a2u.h"
#include "atoi/str2i/str2u.h"
#include "defines.h"
#include "getdef.h"
#include "prototypes.h"
#include "shadowlog_internal.h"
#include "string/sprintf.h"
#include "string/sprintf/xasprintf.h"
#include "string/strchr/stpspn.h"
#include "string/strchr/strrspn.h"
#include "string/strcmp/streq.h"
#include "string/strtok/stpsep.h"
/*
@@ -150,7 +158,6 @@ static struct itemdef def_table[] = {
{NULL, NULL}
};
#define NUMKNOWNDEFS (sizeof(knowndef_table)/sizeof(knowndef_table[0]))
static struct itemdef knowndef_table[] = {
#ifdef USE_PAM
PAMDEFS
@@ -176,7 +183,7 @@ static const char* def_fname = LOGINDEFS; /* login config defs file */
static bool def_loaded = false; /* are defs already loaded? */
/* local function prototypes */
static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *);
static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *, const char *);
static void def_load (void);
@@ -195,7 +202,7 @@ static void def_load (void);
def_load ();
}
d = def_find (item);
d = def_find (item, NULL);
return (NULL == d) ? NULL : d->value;
}
@@ -214,7 +221,7 @@ bool getdef_bool (const char *item)
def_load ();
}
d = def_find (item);
d = def_find (item, NULL);
if ((NULL == d) || (NULL == d->value)) {
return false;
}
@@ -231,23 +238,22 @@ bool getdef_bool (const char *item)
* values are handled.
*/
int getdef_num (const char *item, int dflt)
int
getdef_num(const char *item, int dflt)
{
struct itemdef *d;
long val;
int val;
struct itemdef *d;
if (!def_loaded) {
def_load ();
}
d = def_find (item);
d = def_find (item, NULL);
if ((NULL == d) || (NULL == d->value)) {
return dflt;
}
if ( (getlong(d->value, &val) == -1)
|| (val > INT_MAX)
|| (val < -1)) {
if (a2si(&val, d->value, NULL, 0, -1, INT_MAX) == -1) {
fprintf (shadow_logfd,
_("configuration error - cannot parse %s value: '%s'"),
item, d->value);
@@ -266,23 +272,22 @@ int getdef_num (const char *item, int dflt)
* values are handled.
*/
unsigned int getdef_unum (const char *item, unsigned int dflt)
unsigned int
getdef_unum(const char *item, unsigned int dflt)
{
struct itemdef *d;
long val;
unsigned int val;
struct itemdef *d;
if (!def_loaded) {
def_load ();
}
d = def_find (item);
d = def_find (item, NULL);
if ((NULL == d) || (NULL == d->value)) {
return dflt;
}
if ( (getlong(d->value, &val) == -1)
|| (val < 0)
|| (val > INT_MAX)) {
if (a2ui(&val, d->value, NULL, 0, 0, UINT_MAX) == -1) {
fprintf (shadow_logfd,
_("configuration error - cannot parse %s value: '%s'"),
item, d->value);
@@ -310,12 +315,12 @@ long getdef_long (const char *item, long dflt)
def_load ();
}
d = def_find (item);
d = def_find (item, NULL);
if ((NULL == d) || (NULL == d->value)) {
return dflt;
}
if (getlong(d->value, &val) == -1 || val < -1) {
if (a2sl(&val, d->value, NULL, 0, -1, LONG_MAX) == -1) {
fprintf (shadow_logfd,
_("configuration error - cannot parse %s value: '%s'"),
item, d->value);
@@ -342,12 +347,12 @@ unsigned long getdef_ulong (const char *item, unsigned long dflt)
def_load ();
}
d = def_find (item);
d = def_find (item, NULL);
if ((NULL == d) || (NULL == d->value)) {
return dflt;
}
if (getulong(d->value, &val) == -1) {
if (str2ul(&val, d->value) == -1) {
fprintf (shadow_logfd,
_("configuration error - cannot parse %s value: '%s'"),
item, d->value);
@@ -375,12 +380,9 @@ int putdef_str (const char *name, const char *value, const char *srcfile)
* Locate the slot to save the value. If this parameter
* is unknown then "def_find" will print an err message.
*/
d = def_find (name);
if (NULL == d) {
if (NULL != srcfile)
SYSLOG ((LOG_CRIT, "shadow: unknown configuration item '%s' in '%s'", name, srcfile));
d = def_find (name, srcfile);
if (NULL == d)
return -1;
}
/*
* Save off the value.
@@ -404,9 +406,12 @@ int putdef_str (const char *name, const char *value, const char *srcfile)
*
* Search through a table of configurable items to locate the
* specified configuration option.
*
* If srcfile is not NULL, and the item is not found, then report an error saying
* the unknown item was used in this file.
*/
static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name)
static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name, const char *srcfile)
{
struct itemdef *ptr;
@@ -415,7 +420,7 @@ static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name)
*/
for (ptr = def_table; NULL != ptr->name; ptr++) {
if (strcmp (ptr->name, name) == 0) {
if (streq(ptr->name, name)) {
return ptr;
}
}
@@ -425,13 +430,15 @@ static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name)
*/
for (ptr = knowndef_table; NULL != ptr->name; ptr++) {
if (strcmp (ptr->name, name) == 0) {
if (streq(ptr->name, name)) {
goto out;
}
}
fprintf (shadow_logfd,
_("configuration error - unknown item '%s' (notify administrator)\n"),
name);
if (srcfile != NULL)
SYSLOG ((LOG_CRIT, "shadow: unknown configuration item '%s' in '%s'", name, srcfile));
out:
return NULL;
@@ -523,7 +530,6 @@ static void def_load (void)
#else /* USE_ECONF */
static void def_load (void)
{
int i;
FILE *fp;
char buf[1024], *name, *value, *s;
@@ -555,28 +561,21 @@ static void def_load (void)
/*
* Trim trailing whitespace.
*/
for (i = (ptrdiff_t) strlen (buf) - 1; i >= 0; --i) {
if (!isspace (buf[i])) {
break;
}
}
i++;
buf[i] = '\0';
stpcpy(strrspn(buf, " \t\n"), "");
/*
* Break the line into two fields.
*/
name = buf + strspn (buf, " \t"); /* first nonwhite */
if (*name == '\0' || *name == '#')
name = stpspn(buf, " \t"); /* first nonwhite */
if (streq(name, "") || *name == '#')
continue; /* comment or empty */
s = name + strcspn (name, " \t"); /* end of field */
if (*s == '\0')
s = stpsep(name, " \t"); /* next field */
if (s == NULL)
continue; /* only 1 field?? */
*s++ = '\0';
value = s + strspn (s, " \"\t"); /* next nonwhite */
*(value + strcspn (value, "\"")) = '\0';
value = stpspn(s, " \"\t"); /* next nonwhite */
stpsep(value, "\"");
/*
* Store the value in def_table.
@@ -610,7 +609,7 @@ int main (int argc, char **argv)
def_load ();
for (i = 0; i < NUMDEFS; ++i) {
d = def_find (def_table[i].name);
d = def_find (def_table[i].name, NULL);
if (NULL == d) {
printf ("error - lookup '%s' failed\n",
def_table[i].name);

View File

@@ -1,11 +1,10 @@
/*
* SPDX-FileCopyrightText: 1991 - 1994, Julianne Frances Haugh
* SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz
* SPDX-FileCopyrightText: 2000 - 2006, Tomasz Kłoczko
* SPDX-FileCopyrightText: 2007 - 2009, Nicolas François
*
* SPDX-License-Identifier: BSD-3-Clause
*/
// SPDX-FileCopyrightText: 1991-1994, Julianne Frances Haugh
// SPDX-FileCopyrightText: 1996-2000, Marek Michałkiewicz
// SPDX-FileCopyrightText: 2000-2006, Tomasz Kłoczko
// SPDX-FileCopyrightText: 2007-2009, Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
@@ -14,30 +13,27 @@
#include <stdlib.h>
#include <errno.h>
#include <grp.h>
#include <sys/types.h>
#include "atoi/getnum.h"
#include "prototypes.h"
/*
* getgr_nam_gid - Return a pointer to the group specified by a string.
* The string may be a valid GID or a valid groupname.
* If the group does not exist on the system, NULL is returned.
*/
extern /*@only@*//*@null@*/struct group *getgr_nam_gid (/*@null@*/const char *grname)
extern /*@only@*//*@null@*/struct group *
getgr_nam_gid(/*@null@*/const char *grname)
{
long long gid;
char *endptr;
gid_t gid;
if (NULL == grname) {
if (NULL == grname)
return NULL;
}
errno = 0;
gid = strtoll(grname, &endptr, 10);
if ( ('\0' != *grname)
&& ('\0' == *endptr)
&& (0 == errno)
&& (/*@+longintegral@*/gid == (gid_t)gid)/*@=longintegral@*/) {
return xgetgrgid (gid);
}
return xgetgrnam (grname);
if (get_gid(grname, &gid) == 0)
return xgetgrgid(gid);
return xgetgrnam(grname);
}

View File

@@ -1,36 +0,0 @@
/*
* SPDX-FileCopyrightText: 2007 - 2009, Nicolas François
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <config.h>
#ident "$Id$"
#include <stdlib.h>
#include <errno.h>
#include "prototypes.h"
/*
* getlong - extract a long integer provided by the numstr string in *result
*
* It supports decimal, hexadecimal or octal representations.
*/
int
getlong(const char *restrict numstr, long *restrict result)
{
char *endptr;
long val;
errno = 0;
val = strtol(numstr, &endptr, 0);
if (('\0' == *numstr) || ('\0' != *endptr) || (0 != errno))
return -1;
*result = val;
return 0;
}

View File

@@ -1,8 +1,6 @@
/*
* SPDX-FileCopyrightText: 2008 , Nicolas François
*
* SPDX-License-Identifier: BSD-3-Clause
*/
// SPDX-FileCopyrightText: 2008, Nicolas François
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
@@ -12,9 +10,10 @@
#include <ctype.h>
#include <stdlib.h>
#include "atoi/strtou_noneg.h"
#include "atoi/a2i/a2u.h"
#include "defines.h"
#include "prototypes.h"
#include "string/strcmp/streq.h"
/*
@@ -30,65 +29,44 @@ getrange(const char *range,
unsigned long *min, bool *has_min,
unsigned long *max, bool *has_max)
{
char *endptr;
unsigned long n;
const char *end;
if (NULL == range)
return -1;
*min = 0;
*has_min = false;
*has_max = false;
if ('-' == range[0]) {
if (!isdigit(range[1]))
return -1;
errno = 0;
n = strtoul_noneg(&range[1], &endptr, 10);
if (('\0' != *endptr) || (0 != errno))
return -1;
/* -<long> */
*has_min = false;
*has_max = true;
*max = n;
} else {
errno = 0;
n = strtoul_noneg(range, &endptr, 10);
if (endptr == range || 0 != errno)
return -1;
switch (*endptr) {
case '\0':
/* <long> */
*has_min = true;
*has_max = true;
*min = n;
*max = n;
break;
case '-':
endptr++;
if ('\0' == *endptr) {
/* <long>- */
*has_min = true;
*has_max = false;
*min = n;
} else if (!isdigit (*endptr)) {
return -1;
} else {
*has_min = true;
*min = n;
errno = 0;
n = strtoul_noneg(endptr, &endptr, 10);
if ('\0' != *endptr || 0 != errno)
return -1;
/* <long>-<long> */
*has_max = true;
*max = n;
}
break;
default:
return -1;
}
end = range + 1;
goto parse_max;
}
return 0;
if (a2ul(min, range, &end, 10, 0, ULONG_MAX) == -1 && errno != ENOTSUP)
return -1;
*has_min = true;
switch (*end++) {
case '\0':
*has_max = true;
*max = *min;
return 0; /* <long> */
case '-':
if (streq(end, ""))
return 0; /* <long>- */
parse_max:
if (!isdigit((unsigned char) *end))
return -1;
if (a2ul(max, end, NULL, 10, *min, ULONG_MAX) == -1)
return -1;
*has_max = true;
return 0; /* <long>-<long>, or -<long> */
default:
return -1;
}
}

View File

@@ -1,8 +1,7 @@
/*
* SPDX-FileCopyrightText: 2017, Chris Lamb
*
* SPDX-License-Identifier: BSD-3-Clause
*/
// SPDX-FileCopyrightText: 2017, Chris Lamb
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
@@ -12,11 +11,12 @@
#include <limits.h>
#include <stdio.h>
#include "atoi/strtou_noneg.h"
#include "atoi/a2i/a2i.h"
#include "defines.h"
#include "prototypes.h"
#include "shadowlog.h"
/*
* gettime() returns the time as the number of seconds since the Epoch
*
@@ -24,13 +24,12 @@
* Epoch, 1970-01-01 00:00:00 +0000 (UTC), except that if the SOURCE_DATE_EPOCH
* environment variable is exported it will use that instead.
*/
/*@observer@*/time_t gettime (void)
/*@observer@*/time_t
gettime(void)
{
char *endptr;
char *source_date_epoch;
time_t fallback;
unsigned long long epoch;
FILE *shadow_logfd = log_get_logfd();
char *source_date_epoch;
FILE *shadow_logfd = log_get_logfd();
time_t fallback, epoch;
fallback = time (NULL);
source_date_epoch = shadow_getenv ("SOURCE_DATE_EPOCH");
@@ -38,32 +37,11 @@
if (!source_date_epoch)
return fallback;
errno = 0;
epoch = strtoull_noneg(source_date_epoch, &endptr, 10);
if (errno != 0) {
fprintf (shadow_logfd,
_("Environment variable $SOURCE_DATE_EPOCH: strtoull: %s\n"),
strerror(errno));
} else if (endptr == source_date_epoch) {
fprintf (shadow_logfd,
_("Environment variable $SOURCE_DATE_EPOCH: No digits were found: %s\n"),
endptr);
} else if (*endptr != '\0') {
fprintf (shadow_logfd,
_("Environment variable $SOURCE_DATE_EPOCH: Trailing garbage: %s\n"),
endptr);
} else if (epoch > ULONG_MAX) {
fprintf (shadow_logfd,
_("Environment variable $SOURCE_DATE_EPOCH: value must be smaller than or equal to %lu but was found to be: %llu\n"),
ULONG_MAX, epoch);
} else if ((time_t)epoch > fallback) {
fprintf (shadow_logfd,
_("Environment variable $SOURCE_DATE_EPOCH: value must be smaller than or equal to the current time (%lu) but was found to be: %llu\n"),
fallback, epoch);
} else {
/* Valid */
return epoch;
if (a2i(time_t, &epoch, source_date_epoch, NULL, 10, 0, fallback) == -1) {
fprintf(shadow_logfd,
_("Environment variable $SOURCE_DATE_EPOCH: a2i(\"%s\"): %s"),
source_date_epoch, strerror(errno));
return fallback;
}
return fallback;
return epoch;
}

View File

@@ -1,37 +0,0 @@
/*
* SPDX-FileCopyrightText: 2007 - 2009, Nicolas François
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <config.h>
#ident "$Id: getlong.c 2763 2009-04-23 09:57:03Z nekral-guest $"
#include <stdlib.h>
#include <errno.h>
#include "atoi/strtou_noneg.h"
#include "prototypes.h"
/*
* getulong - extract an unsigned long integer provided by the numstr string in *result
*
* It supports decimal, hexadecimal or octal representations.
*/
int
getulong(const char *restrict numstr, unsigned long *restrict result)
{
char *endptr;
unsigned long val;
errno = 0;
val = strtoul_noneg(numstr, &endptr, 0);
if (('\0' == *numstr) || ('\0' != *endptr) || (0 != errno))
return -1;
*result = val;
return 0;
}

View File

@@ -15,12 +15,14 @@
#include <assert.h>
#include <stdio.h>
#include "alloc.h"
#include "prototypes.h"
#include "defines.h"
#include "alloc/calloc.h"
#include "alloc/malloc.h"
#include "commonio.h"
#include "defines.h"
#include "getdef.h"
#include "groupio.h"
#include "prototypes.h"
#include "string/strcmp/streq.h"
static /*@null@*/struct commonio_entry *merge_group_entries (
@@ -262,8 +264,8 @@ static int group_open_hook (void)
struct group *g2 = gr2->eptr;
if (NULL != g1 &&
NULL != g2 &&
0 == strcmp (g1->gr_name, g2->gr_name) &&
0 == strcmp (g1->gr_passwd, g2->gr_passwd) &&
streq(g1->gr_name, g2->gr_name) &&
streq(g1->gr_passwd, g2->gr_passwd) &&
g1->gr_gid == g2->gr_gid) {
/* Both group entries refer to the same
* group. It is a split group. Merge the
@@ -331,7 +333,7 @@ static /*@null@*/struct commonio_entry *merge_group_entries (
for (i=0; NULL != gptr2->gr_mem[i]; i++) {
char **pmember = gptr1->gr_mem;
while (NULL != *pmember) {
if (0 == strcmp(*pmember, gptr2->gr_mem[i])) {
if (streq(*pmember, gptr2->gr_mem[i])) {
break;
}
pmember++;
@@ -354,7 +356,7 @@ static /*@null@*/struct commonio_entry *merge_group_entries (
for (i=0; NULL != gptr2->gr_mem[i]; i++) {
char **pmember = new_members;
while (NULL != *pmember) {
if (0 == strcmp(*pmember, gptr2->gr_mem[i])) {
if (streq(*pmember, gptr2->gr_mem[i])) {
break;
}
pmember++;

View File

@@ -12,11 +12,13 @@
#ident "$Id$"
#include "alloc.h"
#include "memzero.h"
#include "alloc/calloc.h"
#include "alloc/malloc.h"
#include "prototypes.h"
#include "defines.h"
#include "groupio.h"
#include "string/memset/memzero.h"
/*@null@*/ /*@only@*/struct group *__gr_dup (const struct group *grent)
{
@@ -81,10 +83,9 @@ void
gr_free(/*@only@*/struct group *grent)
{
free (grent->gr_name);
if (NULL != grent->gr_passwd) {
strzero (grent->gr_passwd);
free (grent->gr_passwd);
}
if (NULL != grent->gr_passwd)
free(strzero(grent->gr_passwd));
gr_free_members(grent);
free (grent);
}

View File

@@ -14,85 +14,44 @@
#ident "$Id$"
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "alloc.h"
#include "prototypes.h"
#include "alloc/malloc.h"
#include "alloc/realloc.h"
#include "alloc/x/xmalloc.h"
#include "defines.h"
#include "prototypes.h"
#include "string/strchr/strchrcnt.h"
#include "string/strcmp/streq.h"
#include "string/strtok/stpsep.h"
static /*@null@*/FILE *shadow;
static /*@null@*//*@only@*/char **members = NULL;
static size_t nmembers = 0;
static /*@null@*//*@only@*/char **admins = NULL;
static size_t nadmins = 0;
static struct sgrp sgroup;
static struct sgrp sgroup = {};
#define FIELDS 4
#ifdef USE_NIS
static bool nis_used;
static bool nis_ignore;
static enum { native, start, middle, native2 } nis_state;
static bool nis_bound;
static char *nis_domain;
static char *nis_key;
static int nis_keylen;
static char *nis_val;
static int nis_vallen;
#define IS_NISCHAR(c) ((c)=='+')
#endif
#ifdef USE_NIS
/*
* bind_nis - bind to NIS server
*/
static int bind_nis (void)
static /*@null@*/char **
build_list(char *s)
{
if (yp_get_default_domain (&nis_domain))
return -1;
char **l;
size_t i;
nis_bound = true;
return 0;
}
#endif
l = XMALLOC(strchrcnt(s, ',') + 2, char *);
static /*@null@*/char **build_list (char *s, char **list[], size_t * nlist)
{
char **ptr = *list;
size_t nelem = *nlist, size;
for (i = 0; s != NULL && !streq(s, ""); i++)
l[i] = strsep(&s, ",");
while (s != NULL && *s != '\0') {
size = (nelem + 1) * sizeof (ptr);
ptr = REALLOC(*list, size, char *);
if (NULL != ptr) {
ptr[nelem] = s;
nelem++;
*list = ptr;
*nlist = nelem;
s = strchr (s, ',');
if (NULL != s) {
*s = '\0';
s++;
}
}
}
size = (nelem + 1) * sizeof (ptr);
ptr = REALLOC(*list, size, char *);
if (NULL != ptr) {
ptr[nelem] = NULL;
*list = ptr;
}
return ptr;
l[i] = NULL;
return l;
}
void setsgent (void)
{
#ifdef USE_NIS
nis_state = native;
#endif
if (NULL != shadow) {
rewind (shadow);
} else {
@@ -109,7 +68,8 @@ void endsgent (void)
shadow = NULL;
}
/*@observer@*//*@null@*/struct sgrp *sgetsgent (const char *string)
/*@observer@*//*@null@*/struct sgrp *
sgetsgent(const char *string)
{
static char *sgrbuf = NULL;
static size_t sgrbuflen = 0;
@@ -121,64 +81,40 @@ void endsgent (void)
if (len > sgrbuflen) {
char *buf = REALLOC(sgrbuf, len, char);
if (NULL == buf) {
if (NULL == buf)
return NULL;
}
sgrbuf = buf;
sgrbuflen = len;
}
strcpy (sgrbuf, string);
cp = strrchr (sgrbuf, '\n');
if (NULL != cp) {
*cp = '\0';
}
stpsep(sgrbuf, "\n");
/*
* There should be exactly 4 colon separated fields. Find
* all 4 of them and save the starting addresses in fields[].
*/
for (cp = sgrbuf, i = 0; (i < FIELDS) && (NULL != cp); i++) {
fields[i] = cp;
cp = strchr (cp, ':');
if (NULL != cp) {
*cp++ = '\0';
}
}
for (cp = sgrbuf, i = 0; (i < FIELDS) && (NULL != cp); i++)
fields[i] = strsep(&cp, ":");
/*
* If there was an extra field somehow, or perhaps not enough,
* the line is invalid.
*/
if ((NULL != cp) || (i != FIELDS)) {
#ifdef USE_NIS
if (!IS_NISCHAR (fields[0][0])) {
return 0;
} else {
nis_used = true;
}
#else
return 0;
#endif
}
if (NULL != cp || i != FIELDS)
return NULL;
sgroup.sg_name = fields[0];
sgroup.sg_passwd = fields[1];
if (0 != nadmins) {
nadmins = 0;
free (admins);
admins = NULL;
}
if (0 != nmembers) {
nmembers = 0;
free (members);
members = NULL;
}
sgroup.sg_adm = build_list (fields[2], &admins, &nadmins);
sgroup.sg_mem = build_list (fields[3], &members, &nmembers);
free(sgroup.sg_adm);
free(sgroup.sg_mem);
sgroup.sg_adm = build_list(fields[2]);
sgroup.sg_mem = build_list(fields[3]);
return &sgroup;
}
@@ -209,42 +145,29 @@ void endsgent (void)
return NULL;
}
#ifdef USE_NIS
while (fgetsx (buf, buflen, fp) == buf)
#else
if (fgetsx (buf, buflen, fp) == buf)
#endif
{
while ( ((cp = strrchr (buf, '\n')) == NULL)
&& (feof (fp) == 0)) {
size_t len;
if (fgetsx(buf, buflen, fp) == NULL)
return NULL;
cp = REALLOC(buf, buflen * 2, char);
if (NULL == cp) {
return NULL;
}
buf = cp;
buflen *= 2;
while ( (strrchr(buf, '\n') == NULL)
&& (feof (fp) == 0)) {
size_t len;
len = strlen (buf);
if (fgetsx (&buf[len],
(int) (buflen - len),
fp) != &buf[len]) {
return NULL;
}
cp = REALLOC(buf, buflen * 2, char);
if (NULL == cp) {
return NULL;
}
cp = strrchr (buf, '\n');
if (NULL != cp) {
*cp = '\0';
buf = cp;
buflen *= 2;
len = strlen (buf);
if (fgetsx (&buf[len],
(int) (buflen - len),
fp) != &buf[len]) {
return NULL;
}
#ifdef USE_NIS
if (nis_ignore && IS_NISCHAR (buf[0])) {
continue;
}
#endif
return (sgetsgent (buf));
}
return NULL;
stpsep(buf, "\n");
return (sgetsgent (buf));
}
/*
@@ -253,96 +176,10 @@ void endsgent (void)
/*@observer@*//*@null@*/struct sgrp *getsgent (void)
{
#ifdef USE_NIS
bool nis_1_group = false;
struct sgrp *val;
#endif
if (NULL == shadow) {
setsgent ();
}
#ifdef USE_NIS
again:
/*
* See if we are reading from the local file.
*/
if (nis_state == native || nis_state == native2) {
/*
* Get the next entry from the shadow group file. Return
* NULL right away if there is none.
*/
val = fgetsgent (shadow);
if (NULL == val) {
return 0;
}
/*
* If this entry began with a NIS escape character, we have
* to see if this is just a single group, or if the entire
* map is being asked for.
*/
if (IS_NISCHAR (val->sg_name[0])) {
if ('\0' != val->sg_name[1]) {
nis_1_group = true;
} else {
nis_state = start;
}
}
/*
* If this isn't a NIS group and this isn't an escape to go
* use a NIS map, it must be a regular local group.
*/
if (!nis_1_group && (nis_state != start)) {
return val;
}
/*
* If this is an escape to use an NIS map, switch over to
* that bunch of code.
*/
if (nis_state == start) {
goto again;
}
/*
* NEEDSWORK. Here we substitute pieces-parts of this entry.
*/
return 0;
} else {
if (!nis_bound) {
if (bind_nis ()) {
nis_state = native2;
goto again;
}
}
if (nis_state == start) {
if (yp_first (nis_domain, "gshadow.byname", &nis_key,
&nis_keylen, &nis_val, &nis_vallen)) {
nis_state = native2;
goto again;
}
nis_state = middle;
} else if (nis_state == middle) {
if (yp_next (nis_domain, "gshadow.byname", nis_key,
nis_keylen, &nis_key, &nis_keylen,
&nis_val, &nis_vallen)) {
nis_state = native2;
goto again;
}
}
return sgetsgent (nis_val);
}
#else
return (fgetsgent (shadow));
#endif
}
/*
@@ -353,63 +190,13 @@ void endsgent (void)
{
struct sgrp *sgrp;
#ifdef USE_NIS
static char save_name[16];
int nis_disabled = 0;
#endif
setsgent ();
#ifdef USE_NIS
if (nis_used) {
again:
/*
* Search the gshadow.byname map for this group.
*/
if (!nis_bound) {
bind_nis ();
}
if (nis_bound) {
char *cp;
if (yp_match (nis_domain, "gshadow.byname", name,
strlen (name), &nis_val,
&nis_vallen) == 0) {
cp = strchr (nis_val, '\n');
if (NULL != cp) {
*cp = '\0';
}
nis_state = middle;
sgrp = sgetsgent (nis_val);
if (NULL != sgrp) {
strcpy (save_name, sgrp->sg_name);
nis_key = save_name;
nis_keylen = strlen (save_name);
}
return sgrp;
}
}
nis_state = native2;
}
#endif
#ifdef USE_NIS
if (nis_used) {
nis_ignore = true;
nis_disabled = true;
}
#endif
while ((sgrp = getsgent ()) != NULL) {
if (strcmp (name, sgrp->sg_name) == 0) {
if (streq(name, sgrp->sg_name)) {
break;
}
}
#ifdef USE_NIS
nis_ignore = false;
#endif
return sgrp;
}
@@ -449,53 +236,36 @@ int putsgent (const struct sgrp *sgrp, FILE * fp)
/*
* Copy the group name and passwd.
*/
strcpy (cp, sgrp->sg_name);
cp += strlen (cp);
*cp++ = ':';
strcpy (cp, sgrp->sg_passwd);
cp += strlen (cp);
*cp++ = ':';
cp = stpcpy(stpcpy(cp, sgrp->sg_name), ":");
cp = stpcpy(stpcpy(cp, sgrp->sg_passwd), ":");
/*
* Copy the administrators, separating each from the other
* with a ",".
*/
for (i = 0; NULL != sgrp->sg_adm[i]; i++) {
if (i > 0) {
*cp++ = ',';
}
if (i > 0)
cp = stpcpy(cp, ",");
strcpy (cp, sgrp->sg_adm[i]);
cp += strlen (cp);
cp = stpcpy(cp, sgrp->sg_adm[i]);
}
*cp = ':';
cp++;
cp = stpcpy(cp, ":");
/*
* Now do likewise with the group members.
*/
for (i = 0; NULL != sgrp->sg_mem[i]; i++) {
if (i > 0) {
*cp = ',';
cp++;
}
if (i > 0)
cp = stpcpy(cp, ",");
strcpy (cp, sgrp->sg_mem[i]);
cp += strlen (cp);
cp = stpcpy(cp, sgrp->sg_mem[i]);
}
*cp = '\n';
cp++;
*cp = '\0';
stpcpy(cp, "\n");
/*
* Output using the function which understands the line
* continuation conventions.
*/
if (fputsx (buf, fp) == EOF) {
free (buf);
return -1;

View File

@@ -30,7 +30,6 @@ struct sgrp {
#include <stdio.h> /* for FILE */
#if __STDC__
/*@observer@*//*@null@*/struct sgrp *getsgent (void);
/*@observer@*//*@null@*/struct sgrp *getsgnam (const char *);
/*@observer@*//*@null@*/struct sgrp *sgetsgent (const char *);
@@ -38,15 +37,6 @@ struct sgrp {
void setsgent (void);
void endsgent (void);
int putsgent (const struct sgrp *, FILE *);
#else
/*@observer@*//*@null@*/struct sgrp *getsgent ();
/*@observer@*//*@null@*/struct sgrp *getsgnam ();
/*@observer@*//*@null@*/struct sgrp *sgetsgent ();
/*@observer@*//*@null@*/struct sgrp *fgetsgent ();
void setsgent ();
void endsgent ();
int putsgent ();
#endif
#define GSHADOW "/etc/gshadow"
#endif /* ifndef _H_GSHADOW */

View File

@@ -12,13 +12,17 @@
#ident "$Id$"
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "defines.h"
#include "prototypes.h"
#include "getdef.h"
#include "string/sprintf.h"
#include "prototypes.h"
#include "string/sprintf/snprintf.h"
#include "string/strcmp/streq.h"
#include "string/strtok/stpsep.h"
/*
@@ -70,9 +74,9 @@ bool hushed (const char *username)
return false;
}
for (found = false; !found && (fgets (buf, sizeof buf, fp) == buf);) {
buf[strcspn (buf, "\n")] = '\0';
found = (strcmp (buf, pw->pw_shell) == 0) ||
(strcmp (buf, pw->pw_name) == 0);
stpsep(buf, "\n");
found = streq(buf, pw->pw_shell) ||
streq(buf, pw->pw_name);
}
(void) fclose (fp);
return found;

Some files were not shown because too many files have changed in this diff Show More