Compare commits

...

740 Commits

Author SHA1 Message Date
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
Serge Hallyn
0259f84583 release 4.15.0-rc2
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-02-15 17:54:19 -06:00
NorwayFun
d72d99a810 Update Georgian translation 2024-02-14 15:20:14 -06:00
Alejandro Colomar
f22ca217cd lib/chkname.c: is_valid_user_name(): Avoid a cast
By using a temporary vairable, we can remove a cast.

Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Tobias Stoeckmann <tobias@stoeckmann.org>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-13 16:13:05 -06:00
Alejandro Colomar
ad307ee42a lib/chkname.c: is_valid_user_name(): Remove unnecessary check
If (maxsize == -1), then ((size_t)maxsize == SIZE_MAX).  And no size can
ever be >= SIZE_MAX, so it will never return false if sysconf(3) reports
an unlimited user-name size via returning -1.  Well, to be pedantic,
that disallows a user-name siz of precisely SIZE_MAX bytes when
sysconf(3) returns -1.  However, that's probably a good thing; such a
long user name might trigger Undefined Behavior somewhere else, so be
cautious and disallow it.  I hope nobody will be using the entire
address space for a user name.

The commit that introduced that check missed that this code had always
supported unlimited user-name sizes since it was introduced by Iker in
3b7cc05387 ("lib: replace `USER_NAME_MAX_LENGTH` macro"), and
6be85b0baf ("lib/chkname.c: Use tmp variable to avoid a -Wsign-compare
warning") even clarified this in the commit message.

So, while the code in 6a1f45d932 ("lib/chkname.c: Support unlimited
user name lengths") wasn't bad per se, the commit message was incorrect.
What that patch did was adding code for handling EINVAL (or any other
errors that a future kernel might add).

To be more pedantically correct, that commit also allowed (under certain
circumstances, user names of SIZE_MAX bytes, but those were originally
allowed (by accident), and only became disallowed in 403a2e3771
("lib/chkname.c: Take NUL byte into account").  But again, let's
disallow those, just to be cautious.

Link: <https://github.com/shadow-maint/shadow/pull/935>
Link: <https://github.com/shadow-maint/shadow/pull/935#discussion_r1477429492>
See-also: 6be85b0baf ("lib/chkname.c: Use tmp variable to avoid a -Wsign-compare warning")
Fixes: 6a1f45d932 ("lib/chkname.c: Support unlimited user name lengths")
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Tobias Stoeckmann <tobias@stoeckmann.org>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-13 16:13:05 -06:00
Alejandro Colomar
15882a5f90 src/login.c: Fix off-by-one bugss
These functions expect a size, not a length.  Don't subtract 1 to the
size.

Link: <https://github.com/shadow-maint/shadow/pull/935>
Link: <https://github.com/shadow-maint/shadow/issues/920#issuecomment-1926002209>
Link: <https://github.com/shadow-maint/shadow/pull/757>
Link: <https://github.com/shadow-maint/shadow/issues/674>
See-also: 0656a90bfd0d ("src/login.c: Fix off-by-one buggs")
See-also: 403a2e3771 ("lib/chkname.c: Take NUL byte into account")
Fixes: 3b7cc05387 ("lib: replace `USER_NAME_MAX_LENGTH` macro")
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Tobias Stoeckmann <tobias@stoeckmann.org>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-13 16:13:05 -06:00
Alejandro Colomar
51cd6aec02 lib/: Don't say 'len' where 'size' is meant
Fixes: 45c6603cc8 ("[svn-upgrade] Integrating new upstream version, shadow (19990709)")
Fixes: 3b7cc05387 ("lib: replace `USER_NAME_MAX_LENGTH` macro")
Fixes: 6be85b0baf ("lib/chkname.c: Use tmp variable to avoid a -Wsign-compare warning")
See-also: 403a2e3771 ("lib/chkname.c: Take NUL byte into account")
See-also: 6a1f45d932 ("lib/chkname.c: Support unlimited user name lengths")
Fixes: 95ea61009d ("lib/chkname.c: Use precise comment")
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Tobias Stoeckmann <tobias@stoeckmann.org>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-13 16:13:05 -06:00
Alejandro Colomar
6551709e96 src/login.c: Fix off-by-one buggs
Before 3b7cc05387 ("lib: replace `USER_NAME_MAX_LENGTH` macro"), this
code did use a length.  It used a utmp(5) fixed-width buffer, so the
length matches the buffer size (there was no terminating NUL byte).
However, sysconf(_SC_LOGIN_NAME_MAX) returns a buffer size that accounts
for the terminating null byte; see sysconf(3).  Thus, the commit that
introduced the call to sysconf(3), should have taken that detail into
account.

403a2e3771 ("lib/chkname.c: Take NUL byte into account"), by Tobias,
caught that bug in <lib/chkname.c>, but missed that the same commit that
introduced that bug, introduced the same bug in two other places.
This fixes all remaining calls to sysconf(_SC_LOGIN_NAME_MAX).

I still observe some suspicious code after this fix:

	if (do_rlogin(hostname, username, max_size - 1, term, sizeof(term)))

	...

	login_prompt(username, max_size - 1);

We're passing size-1 to functions that want a size.  But since the fix
to those will be different, let's do that in the following commits.

Link: <https://github.com/shadow-maint/shadow/pull/935>
Link: <https://github.com/shadow-maint/shadow/issues/920#issuecomment-1926002209>
Link: <https://github.com/shadow-maint/shadow/pull/757>
Link: <https://github.com/shadow-maint/shadow/issues/674>
See-also: 403a2e3771 ("lib/chkname.c: Take NUL byte into account")
Fixes: 3b7cc05387 ("lib: replace `USER_NAME_MAX_LENGTH` macro")
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Tobias Stoeckmann <tobias@stoeckmann.org>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-13 16:13:05 -06:00
Tycho Andersen
714b6a53d5 usermod: refuse invalid uidmaps during --add-sub{u,g}ids
It is slightly confusing to allow adding these only to later refuse them.

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

Signed-off-by: Tycho Andersen <tycho@tycho.pizza>
2024-02-13 16:06:23 -06:00
Alejandro Colomar
1175932c0c lib/strtoday.c: strtoday(): Fix calculation
Days officially roll over at 00:00 UTC, not at 12:00 UTC.  I see no
reason to add that half day.

Also, remove the comment.  It's likely to get stale.

So, get_date() gets the number of seconds since the Epoch.  I wonder how
that thing works, but I'll assume it's something similar to getdate(3)
+ mktime(3).  After that, we need to convert seconds since Epoch to days
since Epoch.  That should be a simple division, AFAICS, since Epoch is
"1970‐01‐01 00:00:00 +0000 (UTC)".  See mktime(3).

Fixes: 45c6603cc8 ("[svn-upgrade] Integrating new upstream version, shadow (19990709)")
Link: <https://github.com/shadow-maint/shadow/issues/939>
Reported-by: Michael Vetter <jubalh@iodoru.org>
Tested-by: Gus Kenion <https://github.com/kenion>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-13 16:05:12 -06:00
Tobias Stoeckmann
674409e226 lib/: Saturate addition to avoid overflow
Very large values in /etc/shadow could lead to overflows.  Make sure
that these calculations are saturated at LONG_MAX.  Since entries are
based on days and not seconds since epoch, saturating won't hurt anyone.

Co-developed-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Co-developed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-13 16:02:49 -06:00
Tobias Stoeckmann
20100e4b22 src/chage.c: Unify long overflow checks in print_day_as_date()
The conversion from day to seconds can be done in print_date
(renamed to print_day_as_date for clarification).  This has the nice
benefit that DAY multiplication and long to time_t conversion are done
at just one place.

Co-developed-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Co-developed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-13 16:02:49 -06:00
Alejandro Colomar
7eb10e6298 etc/pam.d/Makefile.am: Fix typo
The commit we're fixing mentions that it wanted to move 'chpasswd', but
it removed 'ch_g_passwd' from 'pamd_acct_tools_files' and added
'chpasswd' to 'pamd_files'.  It seems it removed the wrong thing by
accident.

Fixes: 341d80c2c7 ("Makefile: move chpasswd and newusers to pamd target")
Link: <https://github.com/shadow-maint/shadow/pull/928#discussion_r1487687347>
Link: <https://github.com/shadow-maint/shadow/issues/926#issuecomment-1941324761>
Reported-by: Dominique Leuenberger <dleuenberger@suse.com>
Reported-by: Michael Vetter <jubalh@iodoru.org>
Cc: David Runge <dvzrv@archlinux.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Tested-by: Michael Vetter <jubalh@iodoru.org>
Reviewed-by: Michael Vetter <jubalh@iodoru.org>
Reviewed-by: loqs <https://github.com/loqs>
Co-developed-by: Dominique Leuenberger <dleuenberger@suse.com>
Signed-off-by: Dominique Leuenberger <dleuenberger@suse.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-13 18:45:04 +01:00
Alejandro Colomar
3e59e9613e AUTHORS.md: Format list
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-06 16:16:32 +01:00
Tobias Stoeckmann
95ea61009d lib/chkname.c: Use precise comment
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-02-04 17:03:12 -06:00
Tobias Stoeckmann
6a1f45d932 lib/chkname.c: Support unlimited user name lengths
If the system does not have a user name length limit, support it
accordingly. If the system has no _SC_LOGIN_NAME_MAX, use
LOGIN_NAME_MAX constant instead.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-02-04 17:03:12 -06:00
Tobias Stoeckmann
403a2e3771 lib/chkname.c: Take NUL byte into account
The _SC_LOGIN_NAME_MAX value includes space for the NUL byte. The length
of name must smaller than this value to be valid.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-02-04 17:03:12 -06:00
Serge Hallyn
37b02a5f88 release 4.15.0-rc1
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2024-02-01 17:12:09 -06:00
Samanta Navarro
cae6cea0e8 src/sulogin.c: Remove unused variable
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2024-02-01 14:37:00 +01:00
Samanta Navarro
f078412398 src/sulogin.c: Simplify password handling
The password returned by agetpass can be used directly without copying
it into a char array first.

Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2024-02-01 14:37:00 +01:00
Samanta Navarro
cb42ee620e src/sulogin.c: Use a do-while loop
Clarify how this endless while(true) loop can be stopped by using a
boolean variable as condition and turn it into a do-while loop.

Suggested-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2024-02-01 14:37:00 +01:00
Alejandro Colomar
f98e43ee11 tests/unit/test_atoi_strtoi.c: Test strtou_noneg()
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-31 22:26:19 -06:00
Alejandro Colomar
f2b240595b lib/atoi/strtou_noneg.[ch]: Add strtou_noneg()
It's like strtou_(), but rejects negative input, instead of silently
converting it to unsigned.

Link: <https://softwareengineering.stackexchange.com/a/449060/332848>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-31 22:26:19 -06:00
Alejandro Colomar
f632515581 tests/unit/Makefile.am: tfix
Fix typo.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-31 22:26:19 -06:00
Alejandro Colomar
40355150c4 tests/unit/test_atoi_strtoi.c: Test strtoi_()
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-31 22:26:19 -06:00
Alejandro Colomar
34ff8edb63 lib/atoi/strtoi.[ch]: strtoi_(), strtou_(): Add functions
These functions are identical to strtoi(3bsd) and strtou(3bsd), except
for one important thing: if both ERANGE and ENOTSUP conditions happen,
the BSD functions report ENOTSUP, which is bogus; our strtoi_() and
strtou_() report ERANGE.

Link: <https://lists.sr.ht/~hallyn/shadow/%3CZZoQDms6Sv6e5SPE%40debian%3E>
Link: <https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=57828>
Cc: Thorsten Glaser <tg@mirbsd.de>
Cc: christos <christos@netbsd.org>
Cc: roy <roy@netbsd.org>
Cc: Guillem Jover <guillem@hadrons.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-31 22:26:19 -06:00
Tomas Halman
49001ca846 src/passwd.c: implement reading password from pipe
New option --stdin/-t is available for root user. It is useful
for automation/setup and it makes shadow utils passwd more versatile.

Signed-off-by: Tomas Halman <tomas@halman.net>
2024-01-31 22:16:02 -06:00
Tomas Halman
3fff9d7621 lib/agetpass.[ch]: add function ro read from pipe
Add alternative function to agetpass for reading password
from stdin or pipe.

Signed-off-by: Tomas Halman <tomas@halman.net>
2024-01-31 22:16:02 -06:00
loqs
341d80c2c7 Makefile: move chpasswd and newusers to pamd target
Install pam configs for chpasswd and newusers when using ./configure --with-libpam --disable-account-tools-setuid.
Fixes https://github.com/shadow-maint/shadow/issues/810.

Tested-by: David Runge <dvzrv@archlinux.org>
2024-01-30 22:10:32 +01:00
Pablo Saavedra
cd9b4de327 lib/, src/: Make the use of MAYBE_UNUSED macro consistent
There is an inconsistent use of the MAYBE_UNUSED macro. Sometimes the
`int unused(x)` form is used form and others the `unused int x`. We'd
like to use the second form always.

Related-To: https://github.com/shadow-maint/shadow/issues/918

Suggested-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Pablo Saavedra <psaavedra@igalia.com>
2024-01-30 16:19:56 +01:00
Pablo Saavedra
5d5d212764 lib/, src/: Rename 'unused' macro as 'MAYBE_UNUSED'
Related-To: https://github.com/shadow-maint/shadow/issues/918

Suggested-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Pablo Saavedra <psaavedra@igalia.com>
2024-01-30 16:19:56 +01:00
Pablo Saavedra
da84d0ede7 Fix Build error 'parameter name omitted' in logind
Fixes #918 by adding the omitted parameter name in
active_sessions_count().

Signed-off-by: Pablo Saavedra <psaavedra@igalia.com>
2024-01-30 16:19:56 +01:00
Alejandro Colomar
1a377e318f src/sulogin.c: pw_entry(): Report errors by returning -1
Cc: Samanta Navarro <ferivoz@riseup.net>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-29 17:29:59 +01:00
Alejandro Colomar
6fb7fe11f2 src/passwd.c: Remove comments about flags that don't exist
Those flags have never existed, AFAICS.

Closes: <https://github.com/shadow-maint/shadow/issues/929>
Cc: Tomas Halman <tomas@halman.net>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-29 08:10:44 -06:00
Sam James
0f4e59fd00 Link correctly with libdl
This fixes build with glibc-2.33 (newer glibc merged libdl and libpthread
into libc):
```
libtool: link: x86_64-pc-linux-gnu-gcc -isystem /usr/include/bsd -DLIBBSD_OVERLAY -O2 -pipe -Wl,-O1 -o login login.o login_nopam.o  -Wl,--as-needed ../lib/.libs/libshadow.a -lcrypt -lsystemd -lpam -lpam_misc -lbsd
/usr/lib/gcc/x86_64-pc-linux-gnu/13/../../../../x86_64-pc-linux-gnu/bin/ld: ../lib/.libs/libshadow.a(libshadow_la-nss.o): undefined reference to symbol 'dlclose@@GLIBC_2.2.5'
/usr/lib/gcc/x86_64-pc-linux-gnu/13/../../../../x86_64-pc-linux-gnu/bin/ld: /lib64/libdl.so.2: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
```

In Debian, the needed macro from libtool seems to be in libltdl-dev.

Signed-off-by: Sam James <sam@gentoo.org>
2024-01-26 10:05:40 +01:00
Alejandro Colomar
6fcc0f6756 autogen.sh: CFLAGS: Use -Wno-unknown-attributes; Clang doesn't know [[gnu::access()]]
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-26 09:40:10 +01:00
Alejandro Colomar
d74ffd3c29 autogen.sh: CFLAGS: Add some -Werror=... flags that will be default soon
Clang 16 and GCC 14 have upgraded several warnings to errors by default.
Also, there are new warnings that will be requirements of ISO C23.  Add
all of those to our build.

Use Clang's -Wno-unknown-attribute-option, to ignore warnings that are
exclusive of GCC.  Sadly, GCC doesn't have such an option.

Link: <https://wiki.gentoo.org/wiki/Modern_C_porting#What_changed.3F>
Link: <https://github.com/shadow-maint/shadow/issues/922>
Suggested-by: Sam James <sam@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-26 09:40:10 +01:00
Alejandro Colomar
d452d1b812 src/usermod.c: grp_update(): Remove scope of variable, and fix const correctness
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-26 09:40:10 +01:00
Alejandro Colomar
5a5cd85bd2 src/useradd.c: get_defaults(): Use const temporary pointer to fix const correctness
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-26 09:40:10 +01:00
Alejandro Colomar
3e0cdc87b7 src/su.c: Use const_cast() to silence -Wincompatible-pointer-types-discards-qualifiers
argv is passed to execve(3), which for historic reasons is non-const,
but doesn't modify the strings.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-26 09:40:10 +01:00
Alejandro Colomar
e9fc8fc7ef lib/cast.h: const_cast(): Add macro for dropping 'const'
Uses of this macro indicate a code smell, but in some cases, libc
functions require breaking const correctness.  Use this macro to wrap
casts in such cases, so that we limit the danger of the cast.

It only permits discarding const.  Discarding any other qualifiers, or
doing other type changes should result in a compile-time error.

Link: <https://software.codidact.com/posts/286575/287345#answer-287345>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-26 09:40:10 +01:00
Alejandro Colomar
4ef08548cc lib/must_be.h: is_same_type(): Add macro
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-26 09:40:10 +01:00
Alejandro Colomar
9c5e433a3a lib/must_be.h: is_same_typeof(): Rename macro
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-26 09:40:10 +01:00
Alejandro Colomar
9340efbb0d src/su.c: do_check_perms(): Fix -Wincompatible-pointer-types bug
Fixes: ef95bb7ed1 ("src/su.c: Fix type of variable")
Closes: <https://github.com/shadow-maint/shadow/issues/915>
Reported-by: Sam James <sam@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-24 14:49:56 +01:00
Alejandro Colomar
0138819b2a tests/unit/test_atoi_strtou_noneg.c: Test strtou[l]l_noneg()
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-22 17:17:15 -06:00
Alejandro Colomar
f14670ee1a lib/, src/: Replace strtou[l]l(3) by strtou[l]l_noneg()
strtou[l]l(3) silently converts negative numbers into positive.  This
behavior is wrong: a negative value should be parsed as a negative
value, which would underflow unsigned (long) long, and so would return
the smallest possible value, 0, and set errno to ERANGE to report an
error.

Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-22 17:17:15 -06:00
Alejandro Colomar
4a2646f676 lib/atoi/strtou_noneg.[ch]: Add strtou[l]l_noneg()
These functions reject negative numbers, instead of silently converting
them into unsigned, which strtou[l]l(3) do.

Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-22 17:17:15 -06:00
Samanta Navarro
4d835c7ea4 src/sulogin.c: Free previously allocated memory
The sulogin program calls pw_entry in a loop while incorrect root
passwords are entered.

Free the previously allocated memory to avoid memory exhaustion.

Co-developed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2024-01-22 15:40:39 -06:00
Alejandro Colomar
08ae7af111 src/sulogin.c: Remove 'static' from local variable, but keep initialization
We don't need 'static', because it's in main(), which is only called
once.  However, we will need initialization as if it were 'static', so
use ={} to initialize it.  This will allow freeing the pointers before
they have been allocated.

Cc: Samanta Navarro <ferivoz@riseup.net>
Suggested-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-17 18:11:19 -06:00
Alejandro Colomar
4edda5d8ba src/sulogin.c: Remove 'static' from a temporary variable
There's no need to keep 'pass' in .bss:

$ grep -nC3 '\<pass\>' src/sulogin.c
58-/*ARGSUSED*/ int main (int argc, char **argv)
59-{
60-	int     err = 0;
61:	char    pass[BUFSIZ];
62-	char    **envp = environ;
63-	TERMIO  termio;
64-#ifndef USE_PAM
--
166-#endif
167-			exit (0);
168-		}
169:		STRTCPY(pass, cp);
170-		erase_pass (cp);
171-
172:		if (valid (pass, &pwent)) {	/* check encrypted passwords ... */
173-			break;	/* ... encrypted passwords matched */
174-		}
175-
176-		sleep (2);
177-		(void) puts (_("Login incorrect"));
178-	}
179:	MEMZERO(pass);
180-	(void) alarm (0);
181-	(void) signal (SIGALRM, SIG_DFL);
182-	environ = newenvp;	/* make new environment active */

Cc: Samanta Navarro <ferivoz@riseup.net>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-17 18:11:19 -06:00
Alejandro Colomar
d2c28a402a src/sulogin.c: Align local variables
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-17 18:11:19 -06:00
Alejandro Colomar
1faf4d6469 src/sulogin.c: Make static variables local to main()
Those variables are only used in main().  Restrict their scope.
Keep them static (.bss), as changing that may be dangerous.

Suggested-by: Samanta Navarro <ferivoz@riseup.net>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-17 18:11:19 -06:00
Alejandro Colomar
5214710432 src/sulogin.c: pw_entry(): Don't else after return
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-17 18:11:19 -06:00
Alejandro Colomar
8679878c8b lib/, src/, po/: pw_entry(): Move function to src/sulogin.c
That's the only file where it's called, and it's a delicate function.
Reduce the chances that other files call it.

Link: <https://github.com/shadow-maint/shadow/pull/908>
Suggested-by: Samanta Navarro <ferivoz@riseup.net>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-17 18:11:19 -06:00
Alejandro Colomar
2e56af1902 lib/, tests/: addsl(): Add addsl(), a variadic macro
Add a variadic macro addsl() that accepts an arbitrary number of
addends, instead of having specific versions like addsl2() or addsl3().

It is internally implemented by the addslN() function, which itself
calls addsl2().  addsl3() is now obsolete and thus removed.

Code should just call addsl().

Link: <https://github.com/shadow-maint/shadow/pull/882#discussion_r1437155212>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-16 16:58:18 +01:00
Alejandro Colomar
2e5fc4c90b lib/, tests/: addsl2(): Rename addsl() to addsl2()
This is for consistency with addsl3(), and in preparation for the
following commit, which will unify the interface into a single addsl()
macro.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-16 16:58:18 +01:00
Alejandro Colomar
1356b14a00 lib/defines.h: Don't wrap #undef in #ifdef
ISO C guarantees that #undef is a no-op if there is no such macro.

C11::6.10.3.5p2:
> A preprocessing directive of the form
>
>       # undef identifier new-line
>
> causes the specified identifier no longer to be defined as a macro
> name.  It is ignored if the specified identifier is not currently
> defined as a macro name.

Link: <http://port70.net/~nsz/c/c11/n1570.html#6.10.3.5p2>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-15 13:41:06 -06:00
Alejandro Colomar
effdb14786 lib/idmapping.c: write_mapping(): Fixx off-by-one bug
Link: <673c2a6f9a (r136830993)>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-15 13:37:09 -06:00
Alejandro Colomar
6bec1cf37c lib/: Use 'restrict' alongside [[gnu::access()]]
const + restrict imply read_only.

Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-15 13:14:28 -06:00
Alejandro Colomar
76e7de3fbb lib/: Use ATTR_ACCESS() instead of /*@out@*/
The compiler seems to ignore the attribute in a function pointer,
though.

Link: <https://splint.org/manual/manual.html#undefined>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-15 13:14:28 -06:00
Alejandro Colomar
561448443f lib/: get[u]long(): Use ATTR_ACCESS() instead of /*@out@*/
Link: <https://splint.org/manual/manual.html#undefined>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-15 13:14:28 -06:00
Alejandro Colomar
9ca6b71e76 lib/: Remove incorrect /*@out@*/ comment from functions that read the pointee
These functions (e.g., gr_free()), explicitly dereference the pointer
and read the pointee.

The /@out@/ comment, which is (almost) analogous to the
[[gnu::access(write_only, ...)]] attribute, means that the pointee can
be uninitialized, since it won't read it.  There's a difference between
/@out@/ and the GCC attribute: the attribute doesn't require that the
call writes to the pointee, while /@out@/ requires that the pointee be
fully initialized after the call, so it _must_ write to it.

A guess of why it was used is that these functions are similar to
free(3), which does not read the memory it frees, and so one would
assume that if it doesn't read, write_only (or equivalents) are good.
That's wrong in several ways:

-  free(3) does not read _nor_ write to the memory, so it would
   be slightly inappropriate to use write_only with it.  It wouldn't be
   "wrong", but [[gnu::access(none, ...)]] would be more appropriate.

-  Because /@out@/ requires that the call writes to the pointee, it
   would be wrong to use it in free(3), which doesn't write to the
   pointee.

-  Our functions are similar to free(3) conceptually, but they don't
   behave like free(3), since they do read the memory (pointee) (and
   also write to it), and thus they're actually read_write.

Link: <https://splint.org/manual/manual.html#undefined>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-15 13:14:28 -06:00
Alejandro Colomar
f1b9f8d829 lib/: Remove /*@out@*/ comments in return type
/*@out@*/ makes no sense in the return of a function, AFAICS.

Link: <https://splint.org/manual/manual.html#undefined>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-15 13:14:28 -06:00
Alejandro Colomar
7c1576cfb6 lib/: fgetsx(): Use ATTR_ACCESS() instead of /*@out@*/
Link: <https://splint.org/manual/manual.html#undefined>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-15 13:14:28 -06:00
Alejandro Colomar
a070b84f2e lib/: run_command(): Use ATTR_ACCESS() instead of /*@out@*/
Link: <https://splint.org/manual/manual.html#undefined>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-15 13:14:28 -06:00
Alejandro Colomar
9ac5b2fc5a lib/attr.h: Add ATTR_ACCESS()
This will replace the existing comments like /*@out@*/

Link: <https://splint.org/manual/manual.html#undefined>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-15 13:14:28 -06:00
Samanta Navarro
a9e07c0feb lib/sgetgrent.c: fix null pointer dereference
If reallocation fails in function list, then reset the size to 0 again.
Without the reset, the next call assumes that `members` points to
a memory location with reserved space.

Also use size_t instead of int for size to prevent signed integer
overflows. The length of group lines is not limited.

Fixes 45c0003e53 (4.14 release series)

Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2024-01-15 13:06:35 -06:00
Alejandro Colomar
4c0c7c52f1 lib/: get_pid(): Use the usual -1 as an error code
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-05 16:54:55 -06:00
Alejandro Colomar
18c428a6c9 lib/, src/: get_uid(): Use the usual -1 as an error code
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-05 16:54:55 -06:00
Alejandro Colomar
470baeabbd lib/, src/: get_gid(): Use the usual -1 as an error code
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-05 16:54:55 -06:00
Alejandro Colomar
ea253cb275 lib/, src/: getrange(): Use the usual -1 as an error code
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-05 16:54:55 -06:00
Alejandro Colomar
c595ea7e87 lib/getrange.c: Reduce indentation
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-05 16:54:55 -06:00
Alejandro Colomar
2a9b6d80e7 lib/, src/: getulong(): Use the usual -1 as an error code
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-05 16:54:55 -06:00
Alejandro Colomar
2d581cb337 lib/, src/: getlong(): Use the usual -1 as an error code
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-05 16:54:55 -06:00
Alejandro Colomar
173231a8ff tests/unit/test_adds.c: Test addsl() and addsl3()
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-05 15:45:08 -06:00
Alejandro Colomar
89e5a32966 lib/adds.[ch]: Add addsl() and addsl3()
These functions add 2 or 3 longs, saturating to LONG_{MIN,MAX} instead
of overflowing.

Cc: Tobias Stoeckmann <tobias@stoeckmann.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-05 15:45:08 -06:00
Tobias Stoeckmann
1a383194ff src/: Fix long/time_t handling
Special care has to be taken for 32 bit systems with a 64 bit time_t,
since their long data type is still 32 bit.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Link: <https://github.com/shadow-maint/shadow/pull/876>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-05 15:41:12 -06:00
Tobias Stoeckmann
2d188a9987 src/passwd.c: Add overflow check
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Link: <https://github.com/shadow-maint/shadow/pull/876>
Co-developed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-05 15:41:12 -06:00
Tobias Stoeckmann
3b5ba41d3e src/passwd.c: Switch to day precision
The size of time_t varies across systems, but since data type long is
more than enough to calculate with days (precision of shadow file),
use it instead.

Just in case a shadow file contains huge values, check for a possible
signed integer overflow.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Link: <https://github.com/shadow-maint/shadow/pull/876>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-05 15:41:12 -06:00
Tobias Stoeckmann
ecc3508877 lib/, src/: Remove SCALE definition
SCALE is always DAY (and has to be always DAY), so replace it with DAY
in source code and remove unneeded calculations.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Link: <https://github.com/shadow-maint/shadow/pull/876>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-05 15:41:12 -06:00
Tobias Stoeckmann
11091949be man/: add BCRYPT and YESCRYPT information
The BCRYPT and YESCRYPT relevant items should be described in
manual pages.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2023-12-27 10:48:48 -06:00
Tobias Stoeckmann
f89ba6822d man/: CONSOLE_GROUPS is only used without PAM
CONSOLE_GROUPS is only used if PAM is not in use, just like
CONSOLE itself.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2023-12-27 10:35:02 -06:00
Tobias Stoeckmann
97ddb0d80c man/: ENV_HZ is only used without PAM
Contrary to the comment in ENV_HZ.xml, ENV_HZ is not even used in
sulogin (anymore) if PAM support is enabled.

Skip paragraphs of sulogin if PAM support is enabled, since they would
be empty now.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2023-12-27 10:35:02 -06:00
Alejandro Colomar
0ee79295f6 lib/defines.h: Use 'time_t' for DAY
Special care has to be taken for 32 bit systems with a 64 bit time_t,
since their long data type is still 32 bit.

Since this macro expresses a number of seconds, and seconds are in units
of 'time_t' in C, the appropriate type for the multiplication is
'time_t'.

Reported-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-27 09:55:25 -06:00
Tobias Stoeckmann
ca6425e54e login.defs.5: Be specific that only -1 is allowed
Other negative values can have bad effects and won't be allowed
anymore.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2023-12-27 09:54:06 -06:00
Tobias Stoeckmann
b80c55946a lib/getdef.c: Reject negative values in getdef_* except -1
The values are retrieved from login.defs files, which normally do not
contain negative values. In fact, negative value -1 is used in many
code places as "feature disabled", which is normally achieved by
simply commenting out the key from the file.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2023-12-27 09:54:06 -06:00
Tobias Stoeckmann
8b8793920e man/: Support compiling in build directory
Having a dedicated build directory breaks manual page creation.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2023-12-25 10:08:24 -06:00
Alejandro Colomar
ddbd3a36c1 tests/unit/test_sprintf.c: Test SNPRINTF()
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-15 16:41:47 +01:00
Alejandro Colomar
cf9cc6963c lib/, src/: Use SNPRINTF() instead of its pattern
The variable declarations for the buffers have been aligned in this
commit, so that they appear in the diff, making it easier to review.

Some important but somewhat tangent changes included in this commit:

-  lib/nss.c: The size was being defined as 65, but then used as 64.
   That was a bug, although not an important one; we were just wasting
   one byte.  Fix that while we replace snprintf() by SNPRINTF(), which
   will get the size from sizeof(), and thus will use the real size.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-15 16:41:47 +01:00
Alejandro Colomar
8c6634d9bc lib/string/sprintf.[ch]: Add [v]snprintf_()
These functions are like [v]snprintf(3), but return -1 on truncation,
which makes it easier to test.  In fact, the API of swprintf(3), which
was invented later than snprintf(3), and is the wide-character version
of it, is identical to this snprintf_().

snprintf(3) is iseful in two cases:

-  We don't care if the output is truncated.  snprintf(3) is fine for
   those, and the return value can be ignored.  But snprintf_() is also
   fine for those.

-  Truncation is bad.  In that case, it's as bad as a hard error (-1)
   from snprintf, so merging both problems into the same error code
   makes it easier to handle errors.  Return the length if no truncation
   so that we can use it if necessary.

Not returning the whole length before truncation makes a better API,
which need not read the entire input, so it's less vulnerable to DoS
attacks when a malicious user controls the input.

Use these functions to implement SNPRINTF().

Cc: Samanta Navarro <ferivoz@riseup.net>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-15 16:41:47 +01:00
Alejandro Colomar
ce4c4d4ad5 lib/string/sprintf.h: Add SNPRINTF() macro
It wraps snprintf(3) so that it performs some steps that one might
forget, or might be prone to accidents:

-  It calculates the size of the destination buffer, and makes sure it's
   an array (otherwise, using sizeof(s) would be very bad).

-  It calculates if there's truncation or an error, returning -1 if so.

BTW, this macro doesn't have any issues of double evaluation, because
sizeof() doesn't evaluate its argument (unless it's a VLA, but then the
static_assert(3) within NITEMS() makes sure VLAs are not allowed).

This macro is very similar to STRTCPY(), defined in
<lib/string/strtcpy.h>.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-15 16:41:47 +01:00
Christian Göttsche
9c39b13194 src/chfn,chpasswd,newusers: declare fatal_exit() NORETURN
Help static analyzers to understand fatal_exit() does never return.
2023-12-14 07:40:40 -06:00
Christian Göttsche
d2e7edcd00 lib: avoid format truncation
commonio.c: In function 'commonio_unlock':
    commonio.c:487:49: warning: '.lock' directive output may be truncated writing 5 bytes into a region of size between 1 and 1024 [-Wformat-truncation=]
      487 |                 snprintf (lock, sizeof lock, "%s.lock", db->filename);
          |                                                 ^~~~~
    commonio.c:487:17: note: 'snprintf' output between 6 and 1029 bytes into a destination of size 1024
      487 |                 snprintf (lock, sizeof lock, "%s.lock", db->filename);
          |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2023-12-14 07:40:40 -06:00
Christian Göttsche
ce3a4ac7a3 lib: avoid double close on error
log.c:90:24: warning: double 'close' of file descriptor 'fd' [CWE-1341] [-Wanalyzer-fd-double-close]
    failure.c:94:24: warning: double 'close' of file descriptor 'fd' [CWE-1341] [-Wanalyzer-fd-double-close]
    failure.c:193:32: warning: double 'close' of file descriptor 'fd' [CWE-1341] [-Wanalyzer-fd-double-close]
    utmp.c:103:24: warning: double 'close' of file descriptor 'fd' [CWE-1341] [-Wanalyzer-fd-double-close]
2023-12-14 07:40:40 -06:00
Christian Göttsche
cdb2490ab6 Update close(2) checking
Check for close(2) failure at more places closing a file descriptor
written to.

Also ignore failures with errno set to EINTR (see man:close(2) for
details).
2023-12-14 07:40:40 -06:00
Christian Göttsche
92b889b671 src/useradd: free string
useradd.c:2329:10: warning: Potential leak of memory pointed to by 'btrfs_check' [unix.Malloc]
2023-12-14 07:40:40 -06:00
Christian Göttsche
6178f5a3df lib/failure,utmp: update error messages
Include errno description.
2023-12-14 07:40:40 -06:00
Christian Göttsche
7f20bb88ad lib/utmp: merge file access
Avoid checking if the file exists before opening it.

Resolves a CodeQL report of Time-of-check time-of-use filesystem race
condition.
2023-12-14 07:40:40 -06:00
Christian Göttsche
0d7cb003b7 src/useradd: avoid usage of sprintf
sprintf(3) does not take the destination buffer into account. Although
the destination in these case is large enough, sprintf(3) indicates a
code smell.

Use the xasprintf() wrapper.
2023-12-14 07:40:40 -06:00
Christian Göttsche
95a8de2a0a src/usermod,groups: use checked malloc
usermod.c:2165:24: warning: dereference of possibly-NULL ‘user_groups’ [CWE-690] [-Wanalyzer-possible-null-dereference]
2023-12-14 07:40:40 -06:00
Alejandro Colomar
76bbce3564 lib/, src/: Align variable definitions
This is just a cosmetic patch in preparation for others.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-13 10:06:34 -06:00
Alejandro Colomar
ce0fc161b4 src/login.c: Group preprocessor conditionals
Group them at the end of the list of variable definitions, and use
'#if defined()' instead of '#if[n]def'.  Also indent nested ones.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-13 09:15:09 -06:00
Tobias Stoeckmann
ab260fcd1f lib/defines.h: Remove ITI_AGING
ITI_AGING is not set through any build environment. If it would be set,
then timings in /etc/shadow would not fit anymore.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2023-12-13 09:08:12 -06:00
Alejandro Colomar
ef95bb7ed1 src/su.c: Fix type of variable
su.c:678:26: warning: format ‘%s’ expects argument of type ‘char *’, but argument 4 has type ‘const void *’ [-Wformat=]
su.c:681:44: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘const void *’ [-Wformat=]
su.c:683:46: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘const void *’ [-Wformat=]

Reported-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-13 09:06:59 -06:00
Alejandro Colomar
9858133cc6 lib/, src/: snprintf(3) already terminates strings with NUL
We don't need to terminate them manually after the call.  Remove all
that paranoid code, which in some cases was even wrong.  While at it,
let's do a few more things:

-  Use sizeof(buf) for the size of the buffer.  I found that a few cases
   were passing one less byte (probably because the last one was
   manually zeroed later).  This caused a double NUL.  snprintf(3) wants
   the size of the entire buffer to properly terminate it.  Passing the
   exact value hardcoded is brittle, so use sizeof().

-  Align and improve style of variable declarations.  This makes them
   appear in this diff, which will help review the patch.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-13 12:34:30 +01:00
Alejandro Colomar
93a5c47c2c lib/: Use ATTR_STRING() on stpecpy() and strtcpy()
These functions consume a source string.  Document that.  There's no way
to mark that they also produce a string in dst, though.  That will be up
to the static analyzer to guess.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 12:22:47 +01:00
Alejandro Colomar
a61cf0068b lib/attr.h: Add ATTR_STRING() attribute macro
It signals that a function parameter is a string _before_ the call.

Suggested-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 12:22:47 +01:00
Alejandro Colomar
1c464d9a2d lib/, src/: Fix error handling after strto[u]l[l](3)
-  Set errno = 0 before the call.  Otherwise, it may contain anything.
-  ERANGE is not the only possible errno value of these functions.  They
   can also set it to EINVAL.
-  Any errno value after these calls is bad; just compare against 0.
-  Don't check for the return value; just errno.  This function is
   guaranteed to not modify errno on success (POSIX).
-  Check endptr == str, which may or may not set EINVAL.

Suggested-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 12:21:55 +01:00
Alejandro Colomar
f6701d3efa lib/prefix_flag.c: Invert conditional to remove a branch
This simplifies the code, and is preparation for a following commit.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 12:21:55 +01:00
Alejandro Colomar
ad1e0e9f96 lib/string/strtcpy.h: Don't use a ternary op, to silence a -Wsign-compare warning
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 11:45:09 +01:00
Alejandro Colomar
62772039b7 src/gpasswd.c: Simplify cpp conditional
Since failure() is [[noreturn]], we can invert the conditional so that
we don't need an else.  This silences a -Wunused-parameter warning.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 11:45:09 +01:00
Alejandro Colomar
0c1ca49be3 src/gpasswd.c: Reduce scope of cpp conditional
This prepares for the next patch, which will invert the logic of the
conditional.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 11:45:09 +01:00
Alejandro Colomar
9035f90510 src/gpasswd.c: Mark failure() as [[noreturn]]
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 11:45:09 +01:00
Alejandro Colomar
ccc055d9d9 src/gpasswd.c: Move if out of cpp conditional
This simplifies the code a little bit, and prepares for the next
commits, which will clean up further.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 11:45:09 +01:00
Alejandro Colomar
1fcf807949 src/login_nopam.c: Add missing 'const'
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 11:45:09 +01:00
Alejandro Colomar
d2aa177c50 autogen.sh: CFLAGS: Add -Wno-expansion-to-defined
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 11:45:09 +01:00
Alejandro Colomar
82484117b3 lib/obscure.c: Mark parameter as [[maybe_unused]]
It's only used in certain builds.  This is to silence a -Wunused-parameter warning.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 11:45:09 +01:00
Alejandro Colomar
5ba6cd8545 lib/loginprompt.c: Remove dead code
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 11:45:09 +01:00
Alejandro Colomar
5e0c61cce3 lib/limits.c: Check for overflow without invoking UB
The multiplication was already invoking UB.  The test was flawed.
Use __builtin_mul_overflow() instead.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 11:45:09 +01:00
Alejandro Colomar
9b798b584a lib/limits.c: Fix wrong error check
strtol(3) doesn't specify a return value if (value == endptr).
It is always an error, if (value==endptr).

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 11:45:09 +01:00
Alejandro Colomar
00e4e0c735 lib/copydir.c: Cosmetic
I was investigating a warning in this function, but the code was
inscrutable.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 11:45:09 +01:00
Alejandro Colomar
97e9d60133 lib/commonio.c: Use uintmax_t to print nlink_t
See uintmax_t(3type).

While at it, remove the useless cast to (void).

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 11:45:09 +01:00
Alejandro Colomar
6be85b0baf lib/chkname.c: Use tmp variable to avoid a -Wsign-compare warning
I used size_t because:

sysconf(3) can return -1 if the value is not supported, but then it can
only mean that there's no limit.  Having no limit is the same as having
a limit of SIZE_MAX (to which -1 is converted).

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 11:45:09 +01:00
Alejandro Colomar
028e3e2764 autogen.sh: CFLAGS: Add -Wextra
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-04 11:45:09 +01:00
Alejandro Colomar
fc8389331e lib/string/: Fortify source of strtcpy(), stpecpy(), and zustr2stp()
By writing the terminating null byte via stpcpy(3), we take advantage of
_FORTIFY_SOURCE for the last byte, which was unprotected before this
commit.

Reported-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-03 22:24:29 -06:00
Alejandro Colomar
72060a2b2b lib/env.c: Replace strncpy(3) call by stpcpy(mempcpy(), "")
We were using strncpy(3), which is designed to copy from a string into a
(null-padded) fixed-size character array.  However, we were doing the
opposite: copying from a known-size array (which was a prefix of a
string), into a string.  That's why we had to manually zero the buffer
afterwards.

Use instead mempcpy(3) to copy the non-null bytes, and then terminate
with a null byte with stpcpy(..., "").

Cc: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-03 22:24:29 -06:00
Alejandro Colomar
dbb37b1b31 lib/string/: Move string-related files to string/ subdir
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-03 12:22:11 -06:00
Alejandro Colomar
d1ad64b40f configure.ac: AM_INIT_AUTOMAKE: Use [subdir-objects]
This will allow using subdirs.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-03 12:22:11 -06:00
Alejandro Colomar
4f16458b6c lib/, src/: Say 'long' instead of 'long int'
We were using 'long' in most places, so be consistent and use it
everywhere.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-03 09:58:19 -06:00
Alejandro Colomar
44b8f7b3ef lib/attr.h, lib/, src/: Move attributes to new header file
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-03 09:56:13 -06:00
Sergei Trofimovich
5abe0811b8 src: add missing declaration of getdef_bool
Upcoming `gcc-14` enabled a few warnings into errors, like
`-Wimplicit-function-declaration`. This caused `shadow` build to fail
as:

    pwunconv.c: In function 'main':
    pwunconv.c:132:13: error: implicit declaration of function 'getdef_bool' [-Wimplicit-function-declaration]
      132 |         if (getdef_bool("USE_TCB")) {
          |             ^~~~~~~~~~~

The change adds missing include headers.
2023-12-02 11:04:35 -06:00
Alejandro Colomar
0d2fa501ec lib/defines.h: Remove condition on __STRICT_ANSI__
We require C11 since a few releases ago.  It seems I missed this
reminder of ANSI C (C89) back then.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-28 17:00:46 +01:00
Alejandro Colomar
218235e9dd tests/unit/test_chkname.c: Test is_valid_user_name()
Suggested-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-28 16:57:54 +01:00
Tobias Stoeckmann
4b89ac41cb chsh: limit acceptable shells to absolute paths
If an entry in /etc/shells is not an absolute path (comments or
partial reads due to fgets), the line should not be considered as
a valid login shell.

In general all systems should have getusershells, but let's better
be safe than sorry.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2023-11-27 09:16:08 +01:00
Alejandro Colomar
721b9096eb lib/: Use NITEMS() instead of SIZEOF_ARRAY() where number of elements is meant
For arrays of char, both NITEMS() and SIZEOF_ARRAY() return the same
value.  However, NITEMS() is more appropriate.  Think of wide-character
equivalents of the same code; with NITEMS(), they would continue to be
valid, while with SIZEOF_ARRAY(), they would be wrong.

In the implementation of ZUSTR2STP(), we want SIZEOF_ARRAY() within the
static assert, because we're just comparing the sizes of the source and
destination buffers, and we don't care if we compare sizes or numbers of
elements, and using sizes is just simpler.  But we want NITEMS() in the
zustr2stp() call, where we want to copy a specific number of characters.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-26 21:01:05 -06:00
Alejandro Colomar
a5cddf243a lib/chkname.c: Update regex for valid names
The maximum length of 32 wasn't being enforced in the code, and POSIX
doesn't specify that maximum length either, so it seems it was an
arbitrary limit of the past that doesn't exist any more.  Use a regex
that has no length limit.

Closes: <https://github.com/shadow-maint/shadow/issues/836>
Link: <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-26 06:56:33 -06:00
Alejandro Colomar
fe62fc48bf tests/unit/test_strncpy.c: Test STRNCPY()
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-26 06:48:18 -06:00
Alejandro Colomar
ce30dfe255 lib/: Use STRNCPY() instead of strncpy(3)
We've recently fixed several bugs in the calculation of the size in this
function call.  Use this wrapper to prevent similar mistakes in the
future.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-26 06:48:18 -06:00
Alejandro Colomar
225530b7e1 lib/strncpy.h: Add STRNCPY() wrapper for strncpy(3)
This wrapper calculates the destination buffer's size, to avoid errors
in the size calculation.

A curious fact: this macro did exist in Version 7 Unix (with a slightly
different name).  I found it by chance, investigating the origins of
strncpy(3) and strncat(3) in V7, after Branden suggested me to do so,
related to recent discussions about string_copying(7).

	alx@debian:~/src/unix/unix/Research-V7$ grepc SCPYN .
	./usr/src/cmd/login.c:#define SCPYN(a, b)	strncpy(a, b, sizeof(a))

Our implementation is slightly better, because using nitems() we're
protected against passing a pointer instead of an array, and it's also
conceptually more appropriate: for wide characters, it would be

	#define WCSNCPY(dst, src)  wcsncpy(dst, src, NITEMS(dst))

Cc: "G. Branden Robinson" <branden@debian.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-26 06:48:18 -06:00
Alejandro Colomar
07ab1af55c lib/: Remove off-by-one bugs in calls to strncpy(3)
We're not even zeroing the last byte after this call.  This was a
completely gratuitous truncation of one byte, and the resulting
character array still wasn't guaranteed to be null terminated, because
strncpy(3) can't do that.

Just to clarify, none of these structures needed zeroing, as they are
treated as null-padded fixed-size character arrays.  Calling strncpy(3)
was actually the correct call, and the only problem was unnecessarily
truncating strings by one byte more than necessary.

Cc: Matthew House <mattlloydhouse@gmail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-26 06:48:18 -06:00
Alejandro Colomar
81f0e6a30f lib/log.c: Replace strncpy(3) call by STRTCPY()
This call was too clever.  It relied on the last byte of ll_line
being 0 due to a previous memzero() and not writing to it later.
Write an explicit terminating null byte, by using STRTCPY().

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-26 06:48:18 -06:00
Alejandro Colomar
09957c6d27 lib/failure.c: Replace strncpy(3) call by STRTCPY()
This call was way too clever.  It relied on the last byte of fail_line
being 0 due to it being in a static structure and never writing to it.
Write an explicit terminating null byte, by using STRTCPY().

Cc: Matthew House <mattlloydhouse@gmail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-26 06:48:18 -06:00
Alejandro Colomar
8a1a097afa lib/utmp.c: Replace strncpy(3) call by ZUSTR2STP()
We were copying from a (zero-padded) fixed-width character array to a
string, but strncpy(3) is meant to do the opposite thing.  ZUSTR2STP()
is designed to be used in this case (like strncat(3)).

Fixes: f40bdfa66a ("libmisc: implement `get_session_host()`")
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-26 06:48:18 -06:00
Alejandro Colomar
751f8e055b tests/: Remove references to cracklib
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-25 21:24:38 -06:00
Alejandro Colomar
45f34ee8c1 Remove libcrack support
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-25 21:24:38 -06:00
Alejandro Colomar
43b4e5a6c4 Remove FascistHistory() and FascistHistoryPw() calls
These functions don't seem to exist anymore.  I can't find them in
Debian, nor in a web search.  They probably were functions from an
ancient implementation of cracklib that doesn't exist anymore.

$ git remote -v
origin	git@github.com:cracklib/cracklib.git (fetch)
origin	git@github.com:cracklib/cracklib.git (push)
$ grep -rni fascisthistory
$ git log --grep FascistHistory
$ git log -S FascistHistory

Closes: <https://codesearch.debian.net/search?q=FascistHistory&literal=1>
Cc: Mike Frysinger <vapier@gentoo.org>
Acked-by: Michael Vetter <jubalh@iodoru.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-25 21:24:38 -06:00
Alejandro Colomar
1c50a44db6 lib/date_to_str.c: strftime(3) leaves the buffer undefined on failure
strftime(3) makes no guarantees about the contents of the buffer if the
formatted string wouldn't fit in the buffer.  It simply returns 0, and
it's the programmer's responsibility to do the right thing after that.

Let's write the string "future" if there's an error, similar to what we
do with gmtime(3)'s errors.

Also, `buf[size - 1] = '\0';` didn't make sense.  If the copy fits,
strftime(3) guarantees to terminate with NUL.  If it doesn't, the entire
contents of buf are undefined, so adding a NUL at the end of the buffer
would be dangerous: the string could contain anything, such as
"gimme root access now".  Remove that, now that we set the string to
"future", as with gmtime(3) errors.  This setting to '\0' comes from the
times when we used strncpy(3) in the implementation, and should have
been removed when I changed it to use strlcpy(3); however, I didn't
check we didn't need it anymore.

Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-23 08:04:39 -06:00
Alejandro Colomar
bbf1d9a800 src/logoutd.c: Fix theoretical buffer overrun
ut_line doesn't hold a string.  It is a null-padded fixed-width array.
Luckily, I don't think there has ever existed a ut_line ("/dev/tty*")
that was 32 bytes long.  That would have resulted in a buffer overrun.
Anyway, do the right thing, which is copying into a temporary string.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-22 12:58:17 +01:00
Alejandro Colomar
2eceb4381c lib/date_to_str.c, configure.ac: Replace calls to strlcpy(3) by strtcpy(3)
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-22 12:55:26 +01:00
Alejandro Colomar
3c5a563654 lib/date_to_str.c: Add missing include <config.h>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-22 12:55:26 +01:00
Alejandro Colomar
ff8e4ede1e lib/Makefile.am: Add missing source file
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-22 12:55:26 +01:00
Alejandro Colomar
f9fb855889 src/, lib/, tests/: Rename files defining strtcpy()
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-22 12:55:26 +01:00
Alejandro Colomar
090c019ada src/, lib/, tests/: Rename STRLCPY() to STRTCPY()
It is a wrapper around STRTCPY(), so use a proper name.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-22 12:55:26 +01:00
Alejandro Colomar
6adaa40135 lib/strlcpy.[ch]: Implement strtcpy(3) to replace strlcpy_()
There's been a very long and interesting discussion in linux-man@ and
libc-alpha@, where we've discussed all the string-copying functions,
their pros and cons, when should each be used and avoided, etc.

Paul Eggert pointed out an important problem of strlcpy(3): it is
vulnerable to DoS attacks if an attacker controls the length of the
source string.  And even if it doesn't control it, the function is dead
slow (because its API forces it to calculate strlen(src)).

We've agreed that the general solution for a truncating string-copying
function is to write a wrapper over strnlen(3)+memcpy(3), which is
limited to strnlen(src, sizeof(dst)).  This is not vulnerable to DoS,
and is very fast for all buffer sizes.  string_copying(7) has been
updated to reflect this, and provides a reference implementation for
this wrapper function.

This strtcpy(3) (t for truncation) wrapper happens to have the same API
that our strlcpy_() function had, so replace it with the better
implementation.  We don't need to update callers nor tests, since the
API is the same.

A future commit will rename STRLCPY() to STRTCPY(), and replace
remaining calls to strlcpy(3) by calls to this strtcpy(3).

Link: <https://lore.kernel.org/linux-man/ZU4SDh-Se5gjPny5@debian/T/#mfb5a3fdeb35487dec6f8d9e3d8548bd0d92c4975/>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-22 12:55:26 +01:00
Alejandro Colomar
0f27931155 lib/strlcpy.[ch]: Fix return type
To return an error code, we need ssize_t.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-22 12:55:26 +01:00
Alejandro Colomar
6879f46327 tests/unit/test_strlcpy.c: Test strlcpy_() and STRLCPY()
This test fails now, due to a bug: the return type of strlcpy_() is
size_t, but it should be ssize_t.  The next commit will pass the test,
by fixing the bug.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-22 12:55:26 +01:00
Alejandro Colomar
dad103bdb9 README.md, STABLE.md: record the stable branch URL(s).
Acked-by: Serge Hallyn <serge@hallyn.com>
Acked-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Sam James <sam@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-11-17 09:49:15 -06:00
Joakim Tjernlund
ee3a79c695 Define SUBUID_FILE/SUBGID_FILE
These where hard coded, make them definable like SHADOW_FILE

Signed-off-by: Joakim Tjernlund <joakim.tjernlund@infinera.com>
2023-11-13 12:40:48 +01:00
Iker Pedrosa
a9e642d444 CI: fix Fedora 39 build
libbsd is unwanted in Fedora and RHEL, and the recently released Fedora
39 doesn't contain this dependency in the base image.

shadow removed libbsd from its dependencies for Fedora 39, so let's
build without it to avoid compilation errors.

Resolves: https://github.com/shadow-maint/shadow/issues/839

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
2023-11-13 12:39:13 +01:00
Alejandro Colomar
5c86700fd7 lib/utmp.c: Don't check for NULL before free(3)
free(NULL) is valid; there's no need to check for NULL.  Simplify.

Fixes: 5178f8c5af ("utmp: call prepare_utmp() even if utent is NULL")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-10-29 21:12:02 -05:00
Serge Hallyn
b11129827a Add keys/ directory with public keys for maintainers
These can be used to verify releases.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-10-26 22:31:27 -05:00
Michael Vetter
01f6258df7 man: document --prefix option in chage, chpasswd and passwd
Support for `--prefix` was added in
https://github.com/shadow-maint/shadow/pull/714 and is available since
shadow 4.14.0.

Close https://github.com/shadow-maint/shadow/issues/822
2023-10-26 10:14:53 -05:00
Christian Göttsche
2fa907a522 libmisc/copydir: do not forget errors from directory copy
copydir.c:429:4: warning: Value stored to 'err' is never read [deadcode.DeadStores]

Also reduce indentation by bailing out early.

(cherry picked from commit d89f2fb06d1b81b56299f9d0bfe7a927a2282f19)
2023-10-21 21:37:38 -05:00
Serge Hallyn
fa68441bc4 Improve the login.defs unknown item error message
Closes #746

Only print the 'unknown item' message to syslog if we are
actually parsing a login.defs.  Prefix it with "shadow:" to make
it clear in syslog where it came from.

Also add the source filename to the console message.  I'm not
quite clear on the econf API, so not sure whether in that path we
will end up actually having the path, or printing ''.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-10-20 18:46:23 -05:00
Alejandro Colomar
d73f480ddc autogen.sh: Prepare CFLAGS before ./configure
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-10-20 21:05:33 +02:00
Alejandro Colomar
b3652d8a32 lib/: Add missing #include <config.h>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-10-20 21:05:33 +02:00
Alejandro Colomar
a6d795bac5 autogen.sh: CFLAGS: Add -Werror=implicit-function-declaration
This is not just a style issue.  This should be a hard error, and never
compile.  ISO C89 already had this feature as deprecated.  ISO C99
removed this deprecated feature, for good reasons.  If we compile
ignoring this warning, shadow is not going to behave well.

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

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

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

Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-10-20 21:05:33 +02:00
Alejandro Colomar
c5e5fee606 lib/copydir.c: Use goto to reduce a conditional branch
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-10-20 21:05:33 +02:00
Alejandro Colomar
2a558bd8cb tests/unit/test_xasprintf.c: Test x[v]asprintf()
Link: <https://github.com/shadow-maint/shadow/pull/816>
Suggested-by: Iker Pedrosa <ipedrosa@redhat.com>
Acked-by: Andreas Schneider <https://github.com/cryptomilk>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-10-20 21:05:33 +02:00
Alejandro Colomar
83c8a2d3fa lib/sprintf.[ch]: Add x[v]asprintf()
As other x...() wrappers around functions that allocate, these wrappers
are like [v]asprintf(3), but exit on failure.

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

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

Signed-off-by: Dimitri John Ledkov <dimitri.ledkov@canonical.com>
2023-10-16 12:45:21 -05:00
Dimitri John Ledkov
2e45fff44b Fix mixed-whitespace
Signed-off-by: Dimitri John Ledkov <dimitri.ledkov@canonical.com>
2023-10-16 12:45:21 -05:00
Iker Pedrosa
0d50e1e15f Remove TODO
Sad to remove this file, but things are going on and it doesn't seem to
be up to date.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-10-04 13:31:38 -05:00
Iker Pedrosa
fe299017b1 Remove shadow.spec.in
The file isn't up to date with the latest development, the last change
was made 15 years ago, so I'm removing it.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-10-04 13:31:38 -05:00
Iker Pedrosa
a0546212c0 Remove .travis.yml
It isn't used anywhere so let's remove it.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-10-04 13:31:38 -05:00
Iker Pedrosa
c883786f4f doc: remove WISHLIST
Another file that I remove with sadness. We were unable to complete the
first item but we are working hard on it.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-10-04 13:31:38 -05:00
Iker Pedrosa
bc35dfe4ec doc: remove README.platforms
I remove this file with sadness, as it contains data from old times.
Unfortunately, this data is no longer relevant. The source code
management tool will keep it in memory.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-10-04 13:31:38 -05:00
Iker Pedrosa
2cfa1743d3 doc: remove cracklib26.diff
Keeping a patch for a file no longer maintained is a bad idea, so I'm
removing it.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-10-04 13:31:38 -05:00
Iker Pedrosa
3a43d72e42 doc: remove console.c.spec.txt
I guess we are keeping this for historical purposes more than anything
else. If so, anybody can check the git history to recover the
specification.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-10-04 13:31:38 -05:00
Iker Pedrosa
b91b3793a9 contrib: remove udbachk.tgz
Having source code in a compressed file doesn't seem like a good idea. I
checked several distributions and they don't distribute this binary, so
let's remove it.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-10-04 13:31:38 -05:00
Iker Pedrosa
d702e08097 contrib: remove shadow-anonftp.patch
The patch is never applied upstream. If I were to take a gamble, I would
even say that it throws an error when trying to patch.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-10-04 13:31:38 -05:00
Iker Pedrosa
52d2198252 contrib: remove groupmems.shar
Not sure what this file is exactly, but there's already a groupmems.c
that should generate the binary responsible for managing  the members of
a user's primary group.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-10-04 13:31:38 -05:00
Iker Pedrosa
fbcd8b536a contrib: remove atudel
AFAIK, it isn't included in any distribution and it isn't used
internally in the project, so let's remove it.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-10-04 13:31:38 -05:00
Iker Pedrosa
13a7713384 CI: remove .builds folder
We stopped using the CI relying on this folder and moved to Github's, so
I'm removing these files.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-10-04 13:31:38 -05:00
Johannes Segitz
48aa12af31 useradd: Set proper SELinux labels for def_usrtemplate
Fixes: 74c17c716 ("Add support for skeleton files from /usr/etc/skel")

Signed-off-by: Johannes Segitz <jsegitz@suse.com>
2023-10-03 09:24:47 +02:00
Iker Pedrosa
4f49e3fd3e doc: add unit tests
Brief description of the unit testing framework and how to create test
cases with it.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-09-29 09:24:01 +02:00
Iker Pedrosa
0fc697a4b1 CI: build and run unit tests
Run `make check` after the project is built in every runner.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-09-29 09:24:01 +02:00
Iker Pedrosa
015448b049 tests: happy path for active_sessions_count()
Simple test to check the recently implemented logind functionality. It
also contains the changes to the build infrastructure, and the
gitignore.

Resolves: https://github.com/shadow-maint/shadow/issues/790

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-09-29 09:24:01 +02:00
Iker Pedrosa
163c424999 configure: add cmocka for unit tests
Prepare the ground for unit tests.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-09-29 09:24:01 +02:00
Christian Göttsche
247a869ccd faillog: check for overflows
Check for arithmetic overflows when computing offsets to avoid file
corruptions for huge UIDs.

Refactor the file lookup into a separate function.
2023-09-29 09:20:43 +02:00
Iker Pedrosa
5178f8c5af utmp: call prepare_utmp() even if utent is NULL
update_utmp() should also return 0 when success.

Fixes: 1f368e1c18 ("utmp: update
`update_utmp()")
Resolves: https://github.com/shadow-maint/shadow/issues/805

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-09-15 12:57:16 -05:00
Vasil Velichkov
bef4da47be groupadd: Improve error message when opening group file fails.
Both gr_open and sgr_open are using commonio_open function and when
there is a failure this function sets errno accordingly.
2023-09-04 16:04:42 +02:00
Alejandro Colomar
c1fd94d7d5 lib/mempcpy.[ch]: Remove our definition of mempcpy(3)
It is provided by glibc, musl, and FreeBSD.

Reported-by: Sam James <sam@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-04 08:57:43 -05:00
Alejandro Colomar
9b0f8ddc30 lib/pwauth.c: Replace getpass(3) by agetpass()
Closes: <https://github.com/shadow-maint/shadow/issues/797>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-04 08:57:18 -05:00
Alejandro Colomar
7c45a6e8ba lib/agetpass.h: Move prototypes to dedicated header
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-04 08:57:18 -05:00
Alejandro Colomar
158866bfdc lib/pwauth.c: Simplify empty string
And do not set 'clear' to point to the empty string.  After this commit,
'clear' only stores the result of getpass(3).  This will be useful to
change the code to use agetpass().

$ grep '\<clear\>' lib/pwauth.c;
	char *clear = NULL;
		clear = getpass (prompt);
		input = (clear == NULL) ? "" : clear;
		clear = getpass (prompt);
		input = (clear == NULL) ? "" : clear;
	if (NULL != clear) {
		strzero (clear);

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-04 08:57:18 -05:00
Alejandro Colomar
adbdd086a2 lib/pwauth.c: Remove dead code
There are no users of 'clear_pass' and 'wipe_clear_pass'.

$ grep -rn '\<clear_pass\>'
lib/pwauth.c:35:/*@null@*/char *clear_pass = NULL;
lib/pwauth.c:199:	 * not wipe it (the caller should wipe clear_pass when it is
lib/pwauth.c:203:	clear_pass = clear;

$ grep -rn wipe_clear_pass
lib/pwauth.c:34:bool wipe_clear_pass = true;
lib/pwauth.c:198:	 * if the external variable wipe_clear_pass is zero, we will
lib/pwauth.c:204:	if (wipe_clear_pass && (NULL != clear) && ('\0' != *clear)) {
ChangeLog:3813:	* lib/pwauth.c: Use a boolean for wipe_clear_pass and use_skey.

Remove them.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-04 08:57:18 -05:00
Alejandro Colomar
2b393114c7 lib/pwauth.c: Remove dead code
If the string is "", then strzero() is a no-op.  We don't need to test
that.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-04 08:57:18 -05:00
Alejandro Colomar
8893c51480 autogen.sh: Support out-of-tree builds
This allows to do the following:

~/src/shadow/shadow/master$ mkdir .tmp/ && cd .tmp/
~/src/shadow/shadow/master/.tmp$ ../autogen.sh

Link: <https://github.com/shadow-maint/shadow/issues/795>
Reviewed-by: Sam James <sam@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-04 15:47:14 +02:00
Alejandro Colomar
9514a841bc zustr2stp.h: Assert some assumptions about the size
If the destination buffer is an array, we can check our assumptions.
This adds a readable way to explain that dsize must be strictly > ssize.
The reason is that the destination string is the source + '\0'.

If the destination is not an array, it's up to _FORTIFY_SOURCE or
-fanalyzer to catch newly introduced errors.  There's nothing we can do;
at least not portably.

Suggested-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
3bf8d68f10 strlcpy.[ch]: Add strlcpy_()
This function is like strlcpy(3), but returns -1 on truncation, which
makes it much easier to test.  strlcpy(3) is useful in two cases:

-  We don't care if the output is truncated.  strlcpy(3) is fine for
   those, and the return value can be ignored.

-  Truncation is bad.  In that case, we just want to signal truncation,
   and the length of the original string is quite useless.  Return the
   length iff no truncation so that we can use it if necessary.

This simplifies the definition of the STRLCPY() macro.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
e7a292ed4f Use bzero(3) instead of its pattern
It was blessed by POSIX.1-2001, and GCC says that it won't go away,
possibly ever.

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

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

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

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

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

Link: [1] <https://stackoverflow.com/a/17097978>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
624bacfbd8 Use CALLOC() instead of its pattern
MALLOC() + memset() is simpler written as CALLOC().

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
24367027d6 Use STRLCPY() instead of its pattern
This makes it harder to make mistakes while editing the code.  Since the
sizeof's can be autocalculated, let the machine do that.  It also
reduces the cognitive load while reading the code.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
370652ba05 defines.h: Remove definition of STRFCPY()
It's not being used anymore.  We got rid of it in favor of better APIs.

Well, it's still being used in one place: a contrib/ patch, but I
explicitly want to break it, so that someone reviews it.  I don't want
to modify it, since it's not being tested, so it would be very risky for
me to touch it.  Instead, let it bitrot, and if someone cares, they'll
update it correctly.

BTW, the comment that said /* danger -side effects */ was wrong:
sizeof() doesn't evaluate the argument (unless it's a VLA), so there
wasn't really a double-evaluation issue.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
3029883888 passwd: Replace STRFCPY() by STRLCPY()
The variables are only being read as strings (char *), so data after the
'\0' can't be leaked.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
7bfcf1724c gpasswd: Replace STRFCPY() by STRLCPY()
The variable is only being read as a string (char *), so data after the
'\0' can't be leaked.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
fcc25a03cd login: Replace STRFCPY() by STRLCPY()
The variable is only being read as a string (char *), so data after the
'\0' can't be leaked.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
6dacb154e5 su: Replace STRFCPY() by STRLCPY()
The variables are only being read as strings (char *), so data after the
'\0' can't be leaked.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
3e0913f119 sulogin: Replace STRFCPY() by STRLCPY()
The variable is only being read as a string (char *), so data after the
'\0' can't be leaked.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
2ffc1a76f5 chsh: Replace STRFCPY() by STRLCPY()
The variables are only being read as strings (char *), so data after the
'\0' can't be leaked.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
8e33195c8e chfn: Replace STRFCPY() by STRLCPY()
The variables are only being read as strings (char *), so data after the
'\0' can't be leaked.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
5579b40e35 chage: Replace STRFCPY() by STRLCPY()
The variables are only being read as strings (char *), so data after the
'\0' can't be leaked.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
33abc8bcd9 strlcpy.h: Add STRLCPY() macro
It wraps strlcpy(3bsd) so that it performs some steps that one might
forget, or might be prone to accidents:

-  It calculates the size of the destination buffer, and makes sure it's
   an array (otherwise, using sizeof(dst) would be very bad).

-  It calculates if there's truncation, returning an easy-to-use value.

BTW, this macro doesn't have any issues of double evaluation, because
sizeof() doesn't evaluate its argument (unless it's a VLA, but then
the static_assert(3) within SIZEOF_ARRAY() makes sure VLAs are not
allowed).

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
b1b5c46668 Use ZUSTR2STP() instead of its pattern
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
983a844633 zustr2stp.h: Add ZUSTR2STP() macro
It's a wrapper around zustr2stp() that calls SIZEOF_ARRAY() internally.
The function call is usually --in our code base, always-- called with an
array as the second argument.  For such an argument, one should call
SIZEOF_ARRAY().  To avoid mistakes, and simplify usage, let's add this
macro that does it internally.

BTW, this macro doesn't have any issues of double evaluation, because
sizeof() doesn't evaluate its argument (unless it's a VLA, but then
the static_assert(3) within SIZEOF_ARRAY() makes sure VLAs are not
allowed).

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
02b1471d5b Call zustr2stp() where appropriate
These calls were intending to copy from a NUL-padded (possibly
non-NUL-terminated) character sequences contained in fixed-width arrays,
into a string, where extra padding is superfluous.  Use the appropriate
call, which removes the superfluous work.  That reduces the chance of
confusing maintainers about the intention of the code.

While at it, use the appropriate third parameter, which is the size of
the source buffer, and not the one of the destination buffer.  As a side
effect, this reduces the use of '-1', which itself reduces the chance of
off-by-one bugs.

Also, since using sizeof() on an array is dangerous, use SIZEOF_ARRAY().

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
6a576391d6 zustr2stp.[ch]: Add zustr2stp()
There's no standard function that copies from a null-padded character
sequence into a string.

A few standard functions can be workarounded to do that:

-  strncat(3):  This function is designed to catenate from a null-padded
   character sequence into a string.  The catch is that there's no
   *cpy() equivalent of it --strncpy(3) is not at all related to
   strncat(3); don't be fooled by the confusing name--, so one would
   need to zero the first byte before the call to strncat(3).  It also
   has the inconvenient that it returns a useless value.

-  strncpy(3):  This function is designed to copy from a string to a
   null-padded character sequence; the opposite of what we want to do.
   If one passes the size of src instead of the size of dst, and then
   manually zeroes the last byte of the dst buffer, something similar
   to what we want happens.  However, this does more than what we want:
   it also padds with NUL the remaining bytes after the terminating NUL.
   That extra work can confuse maintainers to believe that it's
   necessary.  That is exactly what happens in logout.c.

src/logoutd.c-46-	/*
src/logoutd.c-47-	 * ut_user may not have the terminating NUL.
src/logoutd.c-48-	 */
src/logoutd.c:49:	strncpy (user, ut->ut_user, sizeof (ut->ut_user));
src/logoutd.c-50-	user[sizeof (ut->ut_user)] = '\0';

   In that logout.c case --and in most invocations of strncpy(3), which
   is usually a wrong tool-- the extra work is not wanted, so it's
   preferrable to use the right tool, a function that does exactly
   what's needed and nothing more than that.  That tool is zustr2stp().

Read string_copying(7) for a more complete comparison of string copying
functions.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
ec1cc096e8 libmisc: Fix wrong #include
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
f3ee47fe3f Use MEMZERO() instead of its pattern
This patch implicitly adds the safety of SIZEOF_ARRAY(), since the calls
were using sizeof() instead.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
64ab401239 memzero.h: Add MEMZERO() macro
It calculates the size of the array safely, via SIZEOF_ARRAY(), instead of
sizeof(), which can be dangerous.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
e299942189 sizeof.h: Add SIZEOF_ARRAY() macro
This makes it safe to call sizeof() on an array.  Calling sizeof()
directly on an array is dangerous, because if the array changes to be a
pointer, the behavior will unexpectedly change.  It's the same problem
as with NITEMS().

Link: <https://stackoverflow.com/a/57537491>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
49ea7327d9 sizeof.h: Make NITEMS() and derivative macros safe against pointers
By using must_be_array(), code that calls NITEMS() or STRLEN() with
non-arrays will not compile.

Link: <https://stackoverflow.com/a/57537491>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
c3a8d02b9f must_be.h: Add must_be_array() macro
This macro statically asserts that the argument is an array.

Link: <https://stackoverflow.com/a/57537491>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
10f31a97e2 must_be.h: Add must_be() macro
It's like static_assert(3), but can be used in more places.  It's
necessary for writing a must_be_array() macro.

Link: <https://stackoverflow.com/a/57537491>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
328958ca01 sizeof.h: Move sizeof()-related macros to their own header
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
246edc0481 memzero.h: Remove no-op assignment
memset(3) returns the input pointer.  The assignment was effectively a
no-op, and just confused the code.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
2daa6cc65d memzero.[ch]: Define memzero() and strzero() as inline functions
There's no need to have these as macros, so use functions, which are a
lot safer: there's no need to worry about multiple evaluation of args,
and there's also more type safety.  Compiler warnings are also simpler,
as they don't dump all the nested macros.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
fca2fd65c0 memzero.h: Remove outdated comments
These comments were wrong.  Remove them instead of fixing them, since
now that we have this small header file, it's much easier to follow the
preprocessor conditionals.

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
6b11077f09 memzero.h: Move memzero() and strzero() to their own header
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-09-01 09:39:23 +02:00
Alejandro Colomar
093fb605f9 lib: Merge libmisc into libshadow
The separation was unnecessary, and caused build problems.  Let's go
wild and obliterate the library.  The files are moved to libshadow.

Scripted change:

$ find libmisc/ -type f \
| grep '\.[chy]$' \
| xargs mv -t lib;

Plus updating the Makefile and other references.  While at it, I've
sorted the sources lists.

Link: <https://github.com/shadow-maint/shadow/pull/792>
Reported-by: David Seifert <soap@gentoo.org>
Cc: Sam James <sam@gentoo.org>
Cc: Christian Bricart <christian@bricart.de>
Cc: Michael Vetter <jubalh@iodoru.org>
Cc: Robert Förster <Dessa@gmake.de>
[ soap tested the Gentoo package ]
Tested-by: David Seifert <soap@gentoo.org>
Acked-by: David Seifert <soap@gentoo.org>
Acked-by: Serge Hallyn <serge@hallyn.com>
Acked-by: Iker Pedrosa <ipedrosa@redhat.com>
Acked-by: <lslebodn@fedoraproject.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-08-31 08:55:26 +02:00
Alejandro Colomar
c34c2606cf lib, libmisc: Move source files to lib (where their headers were)
Scripted change:

$ find lib/ -type f \
| grep '\.h$' \
| sed 's,lib/,libmisc/,' \
| sed 's,\.h$,.c,' \
| xargs find 2>/dev/null \
| xargs mv -t lib/;

Plus updating the Makefiles.

Closes: <https://github.com/shadow-maint/shadow/issues/791>
Closes: <https://bugs.gentoo.org/912446>
Link: <https://github.com/shadow-maint/shadow/issues/763#issuecomment-1664383425>
Link: <https://github.com/shadow-maint/shadow/pull/776>
Link: <d0518cc250>
Reported-by: Christian Bricart <christian@bricart.de>
Reported-by: Robert Marmorstein <robert@marmorstein.org>
Cc: Sam James <sam@gentoo.org>
[ jubalh tested the openSUSE package ]
Tested-by: Michael Vetter <jubalh@iodoru.org>
Acked-by: Michael Vetter <jubalh@iodoru.org>
[ Robert F. tested the Gentoo package ]
Tested-by: Robert Förster <Dessa@gmake.de>
Cc: David Seifert <soap@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-08-30 17:22:38 +02:00
Christian Göttsche
f76c31f50e Avoid usage of sprintf
sprintf(3) does not take the destination buffer into account. Although
the destination in these case is large enough, sprintf(3) indicates a
code smell.

Use snprintf(3).
2023-08-21 16:04:09 -05:00
Christian Göttsche
e0d3ba6934 commonio: check for path truncations
Bail out if the paths generated for the backup and replacement database
are truncated.
2023-08-21 15:56:44 -05:00
Christian Göttsche
54ab542887 lib/btrfs: avoid NULL-dereference
btrfs.c:42:13: warning: use of NULL 'cmd' where non-null expected [CWE-476] [-Wanalyzer-null-argument]

Reviewed-by: Alejandro Colomar <alx@kernel.org>
2023-08-21 14:05:34 -05:00
Christian Göttsche
a08021eb0e lib/commonio: drop dead store
commonio.c:522:15: warning: Although the value stored to 'cp' is used in the enclosing expression, the value is never actually read from 'cp' [deadcode.DeadStores]

Reviewed-by: Alejandro Colomar <alx@kernel.org>
2023-08-21 14:05:27 -05:00
Christian Göttsche
931e7c0c2f login: use strlcpy to always NUL terminate
login.c:728:25: warning: ‘strncpy’ specified bound 256 equals destination size [-Wstringop-truncation]

Reviewed-by: Alejandro Colomar <alx@kernel.org>
2023-08-21 14:05:18 -05:00
Christian Göttsche
15f4421f10 lib: avoid dropping const qualifier during cast
subordinateio.c:360:20: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      360 |         range1 = (*(struct commonio_entry **) p1)->eptr;
          |                    ^
    subordinateio.c:364:20: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      364 |         range2 = (*(struct commonio_entry **) p2)->eptr;
          |                    ^

    groupio.c:215:15: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      215 |         if ((*(struct commonio_entry **) p1)->eptr == NULL) {
          |               ^
    groupio.c:218:15: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      218 |         if ((*(struct commonio_entry **) p2)->eptr == NULL) {
          |               ^
    groupio.c:222:34: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      222 |         u1 = ((struct group *) (*(struct commonio_entry **) p1)->eptr)->gr_gid;
          |                                  ^
    groupio.c:223:34: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      223 |         u2 = ((struct group *) (*(struct commonio_entry **) p2)->eptr)->gr_gid;
          |                                  ^

    pwio.c:187:15: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      187 |         if ((*(struct commonio_entry **) p1)->eptr == NULL)
          |               ^
    pwio.c:189:15: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      189 |         if ((*(struct commonio_entry **) p2)->eptr == NULL)
          |               ^
    pwio.c:192:35: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      192 |         u1 = ((struct passwd *) (*(struct commonio_entry **) p1)->eptr)->pw_uid;
          |                                   ^
    pwio.c:193:35: warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
      193 |         u2 = ((struct passwd *) (*(struct commonio_entry **) p2)->eptr)->pw_uid;
          |                                   ^

Reviewed-by: Alejandro Colomar <alx@kernel.org>
2023-08-21 13:54:27 -05:00
Christian Göttsche
856ffcfa5e Drop unnecessary cast to same type 2023-08-21 11:43:30 +02:00
Christian Göttsche
35edae5892 Declare usage and failure handler noreturn
Assist static analyzers in understanding final code paths.
2023-08-21 11:43:18 +02:00
Christian Göttsche
1aaa4ec5ba lib/tcbfuncs: operate on file descriptor rather than path 2023-08-21 11:29:17 +02:00
Alejandro Colomar
f45498a6c2 libmisc/write_full.c: Improve write_full()
Documentation:

-  Correct the comment documenting the function:

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

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

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

API:

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

Implementation:

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

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

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

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

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

Use:

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

Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-08-18 20:35:15 -05:00
Heiko Becker
890f911e17 Replace __{BEGIN,END}_DECLS with #ifdef __cplusplus
Fixes the build with musl libc.
2023-08-18 18:04:11 -05:00
Serge Hallyn
014536f5d5 release 4.14.0
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-08-15 21:38:30 -05:00
Serge Hallyn
ca0f828e7a pre-release 4.14.0-rc5
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-08-14 11:51:36 -05:00
Serge Hallyn
ebad5f840a configure.ac: check for strlcpy
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-08-14 09:08:35 -05:00
Michael Vetter
ae2a4507ed Remove intree website
AFAIK these files were not used in a while.
On 2023-04-27 we also archived the GitHub pages based repo:
https://github.com/shadow-maint/shadow-www

In 1654f42194 we mention the regular repo URL as our home page.

Also see:
https://github.com/shadow-maint/shadow/issues/114
2023-08-14 07:06:51 -05:00
Serge Hallyn
c1924dc5a1 4.14.0-rc4 pre-release
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-08-12 23:17:52 -05:00
Serge Hallyn
ee3e6112d3 Releases: add etc/shadow-maint to distfiles
Closes #784

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-08-12 23:16:56 -05:00
Serge Hallyn
2492fc00d4 4.14.0-rc3
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-08-10 09:33:07 -05:00
Iker Pedrosa
776bbd0ccb libmisc: include freezero
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-10 09:29:17 -05:00
Iker Pedrosa
0e0a310acf libmisc: add freezero source code
If shadow is built without libbsd support, then freezero() needs to be
provided from the project.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-10 09:29:17 -05:00
Iker Pedrosa
7d5eeb2135 libmisc: add readpassphrase source code
If shadow is built without libbsd support, then readpassphrase() needs
to be provided from the project.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-10 09:29:17 -05:00
Iker Pedrosa
c408c4ad3d configure: add with-libbsd option
It enables the build with libbsd support. By default it is enabled.

Resolves: https://github.com/shadow-maint/shadow/issues/779

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-10 09:29:17 -05:00
Iker Pedrosa
6ddd10482b man: include shadow-man.xsl in tarball
This will help generate man pages from tarball.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-09 21:33:21 -05:00
Iker Pedrosa
8e17459fa1 man: include its.rules in tarball
This will help generate the man pages from tarball.

Resolves: https://github.com/shadow-maint/shadow/issues/781

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-09 21:33:21 -05:00
Iker Pedrosa
c89b326350 autogen: enable lastlog build
Add "--enable-lastlog" to include lastlog man pages in tarball.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-07 09:42:11 -05:00
Christian Göttsche
969549fdf0 Add wrapper for write(2)
write(2) may not write the complete given buffer.  Add a wrapper to
avoid short writes.
2023-08-04 17:15:42 -05:00
Serge Hallyn
d63f3a0c0a tag 4.14.0-rc2
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-08-04 16:24:54 -05:00
Michael Vetter
d0518cc250 Add new files to libmisc_la_SOURCES
Resolves https://github.com/shadow-maint/shadow/issues/763
2023-08-04 15:39:55 -05:00
Serge Hallyn
4107c49ecd Add a make dist CI test
Add a CI test to check that make dist builds a usable tarball.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-08-04 14:15:49 -05:00
Serge Hallyn
95296dfd67 4.14.0-rc1
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-08-03 11:28:59 -05:00
Serge Hallyn
cf5596fc79 remove xmalloc.c from POTFILES.in
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-08-03 11:28:54 -05:00
Iker Pedrosa
f2155fadf1 logoutd: add missing <utmp.h> include
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
02e3e04205 CI: compile old utmp interface in Fedora
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
50affc546f src: add SELINUX library
With the recent changes both login and su compilation fail because there
are some missing dependencies from SELINUX library. Thus, add LIBSELINUX
to su and login for those cases where the library is used.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
78c09e3afe libmisc: conditionally compile utmp.c and logind.c
Depending on the configuration option selected.

Resolves: https://github.com/shadow-maint/shadow/issues/674

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
3b7cc05387 lib: replace USER_NAME_MAX_LENGTH macro
Replace it by `sysconf(_SC_LOGIN_NAME_MAX)`, which is the maximum
username length supported by the kernel.

Resolves: https://github.com/shadow-maint/shadow/issues/674

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
fb8f44d73f libmisc: call active_sessions_count()
Replace the utmp dependent code with the call to
`active_sessions_count()`.

Resolves: https://github.com/shadow-maint/shadow/issues/674

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
ede0665a5a libmisc: implement active_sessions_count()
Implement `active_sessions_count()` in `utmp.c` and `logind.c`.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
1f368e1c18 utmp: update update_utmp()
Remove `utmp` structure as an argument and include its logic inside the
function. This will help remove any reference to utmp from login.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
6b7108e347 utmp: move update_utmp
The functionality from this function is related to utmp. Restrict access
to `setutmp()` to the same file.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
b6ca83ea4c utmp: move failtmp()
The functionality from this function is related to btmp.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
f40bdfa66a libmisc: implement get_session_host()
Implement `get_session_host()` in `utmp.c` and `logind.c`.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
Iker Pedrosa
fb35ad15ae configure: new option enable-logind
Create new configuration option `enable-logind` to select which session
support functionality to build, logind or utmp. By default the option is
logind.

Resolves: https://github.com/shadow-maint/shadow/issues/674

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-08-02 10:13:28 -05:00
xiongshenglan
7bced397c9 shadow userdel: add the adaptation to the busybox ps in 01-kill_user_procs.sh
In some embedded systems, users only use the ps
provided by the busybox. But the ps provided by
the busybox does not support the -eo option by
default. As a result, an error is reported when
the userdel is used. So add a judgment on ps.
If there is no ps -eo, traverse the process directly.

The error information is as follows:
 # userdel xsl
ps: invalid option -- 'e'

Signed-off-by: xiongshenglan <xiongshenglan@huawei.com>
2023-07-28 21:24:36 -05:00
Michael Vetter
a692c880f1 chsh: warn if root sets a shell not listed in /etc/shells
Print a warning even for the root user if the provided shell isn't
listed in /etc/shells, but continue to execute the action.
In case of non root user exit.

See https://github.com/shadow-maint/shadow/issues/535
2023-07-27 12:35:27 -05:00
Michael Vetter
e5f05d7812 doc: mention ci workflow file to learn about deps
Fix https://github.com/shadow-maint/shadow/issues/38
2023-07-27 10:03:28 -05:00
Serge Hallyn
35e91daba0 man/po/Makefile: add a comment to shadow-man-pages.pot
Add a comment at the top of that file explaining how to
regenerate it.

We should add a README, but I don't have time to draft one
right now.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-07-21 23:34:32 -05:00
Vegard Nossum
9df4801e0b newgrp: fix potential string injection
Since newgrp is setuid-root, any write() system calls it does in order
to print error messages will be done as the root user.

Unprivileged users can get newgrp to print essentially arbitrary strings
to any open file in this way by passing those strings as argv[0] when
calling execve(). For example:

    $ setpid() { (exec -a $1$'\n:' newgrp '' 2>/proc/sys/kernel/ns_last_pid & wait) >/dev/null; }
    $ setpid 31000
    $ readlink /proc/self
    31001

This is not a vulnerability in newgrp; it is a bug in the Linux kernel.

However, this type of bug is not new [1] and it makes sense to try to
mitigate these types of bugs in userspace where possible.

[1]: https://lwn.net/Articles/476947/

Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
2023-07-21 23:32:19 -05:00
Todd Zullinger
2643f27b36 lastlog: fix alignment of Latest header
b1282224 (Add maximum padding to fit IPv6-Addresses, 2020-05-24) pads
the From field header using `maxIPv6Addrlen - 3`.  This leaves the
Latest field header misaligned.  Subtract 4 (the length of "From").
2023-07-18 10:49:13 -05:00
Iker Pedrosa
6f4dc321c3 configure: fix lastlog check
Fixes: 1bdcfa8d37 ("lastlog: stop building by
default")

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-07-17 13:01:34 -05:00
Alan D. Salewski
65255ea304 subuid.5: reference newusers(8) rather than newusers(1)
Resolves: https://github.com/shadow-maint/shadow/issues/752

Signed-off-by: Alan D. Salewski <ads@salewski.email>
2023-07-17 10:10:01 +02:00
Iker Pedrosa
c69fd917e3 CI: build lastlog in Fedora
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-07-15 07:39:53 -05:00
Iker Pedrosa
acea93eda9 man: conditionally build lastlog documentation
Resolves: https://github.com/shadow-maint/shadow/issues/674

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-07-15 07:39:53 -05:00
Iker Pedrosa
03251ffbc0 usermod: conditionally build lastlog functionality
Resolves: https://github.com/shadow-maint/shadow/issues/674

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-07-15 07:39:53 -05:00
Iker Pedrosa
d60595d8f2 useradd: conditionally build lastlog functionality
Resolves: https://github.com/shadow-maint/shadow/issues/674

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-07-15 07:39:53 -05:00
Iker Pedrosa
84a10ca019 login: conditionally build lastlog functionality
Resolves: https://github.com/shadow-maint/shadow/issues/674

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-07-15 07:39:53 -05:00
Iker Pedrosa
1bdcfa8d37 lastlog: stop building by default
Created a new configuration option `--enable-lastlog` to conditionally
build the lastlog binary. By default the option is disabled.

Resolves: https://github.com/shadow-maint/shadow/issues/674

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-07-15 07:39:53 -05:00
Iker Pedrosa
a0eeb9fbf2 CI: update debian repos
Latest debian version changed the location and format for the repos
file.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-07-14 11:49:40 +02:00
Bernd Kuhls
29da702491 Fix yescrypt support
Fixes build error:
newusers.c: In function 'update_passwd':
newusers.c:433:21: error: 'sflg' undeclared (first use in this function); did you mean 'rflg'?

introduced by
5cd04d03f9
which forgot to define sflg for these configure options:

--without-sha-crypt --without-bcrypt --with-yescrypt
2023-07-12 08:31:51 -05:00
Jeffrey Bencteux
53a17c1742 chgpasswd: fix segfault in command-line options
Using the --sha-rounds option without first giving a crypt method via the --crypt-method option results in comparisons with a NULL pointer and thus make chgpasswd segfault:

$ chgpasswd -s 1
zsh: segmentation fault  chgpasswd -s 1

Current patch add a sanity check before these comparisons to ensure there is a defined encryption method.
2023-06-22 14:51:34 -05:00
Alejandro Colomar
65c88a43a2 gpasswd(1): Fix password leak
How to trigger this password leak?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When gpasswd(1) asks for the new password, it asks twice (as is usual
for confirming the new password).  Each of those 2 password prompts
uses agetpass() to get the password.  If the second agetpass() fails,
the first password, which has been copied into the 'static' buffer
'pass' via STRFCPY(), wasn't being zeroed.

agetpass() is defined in <./libmisc/agetpass.c> (around line 91), and
can fail for any of the following reasons:

-  malloc(3) or readpassphrase(3) failure.

   These are going to be difficult to trigger.  Maybe getting the system
   to the limits of memory utilization at that exact point, so that the
   next malloc(3) gets ENOMEM, and possibly even the OOM is triggered.
   About readpassphrase(3), ENFILE and EINTR seem the only plausible
   ones, and EINTR probably requires privilege or being the same user;
   but I wouldn't discard ENFILE so easily, if a process starts opening
   files.

-  The password is longer than PASS_MAX.

   The is plausible with physical access.  However, at that point, a
   keylogger will be a much simpler attack.

And, the attacker must be able to know when the second password is being
introduced, which is not going to be easy.

How to read the password after the leak?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Provoking the leak yourself at the right point by entering a very long
password is easy, and inspecting the process stack at that point should
be doable.  Try to find some consistent patterns.

Then, search for those patterns in free memory, right after the victim
leaks their password.

Once you get the leak, a program should read all the free memory
searching for patterns that gpasswd(1) leaves nearby the leaked
password.

On 6/10/23 03:14, Seth Arnold wrote:
> An attacker process wouldn't be able to use malloc(3) for this task.
> There's a handful of tools available for userspace to allocate memory:
>
> -  brk / sbrk
> -  mmap MAP_ANONYMOUS
> -  mmap /dev/zero
> -  mmap some other file
> -  shm_open
> -  shmget
>
> Most of these return only pages of zeros to a process.  Using mmap of an
> existing file, you can get some of the contents of the file demand-loaded
> into the memory space on the first use.
>
> The MAP_UNINITIALIZED flag only works if the kernel was compiled with
> CONFIG_MMAP_ALLOW_UNINITIALIZED.  This is rare.
>
> malloc(3) doesn't zero memory, to our collective frustration, but all the
> garbage in the allocations is from previous allocations in the current
> process.  It isn't leftover from other processes.
>
> The avenues available for reading the memory:
> -  /dev/mem and /dev/kmem (requires root, not available with Secure Boot)
> -  /proc/pid/mem (requires ptrace privileges, mediated by YAMA)
> -  ptrace (requires ptrace privileges, mediated by YAMA)
> -  causing memory to be swapped to disk, and then inspecting the swap
>
> These all require a certain amount of privileges.

How to fix it?
~~~~~~~~~~~~~~

memzero(), which internally calls explicit_bzero(3), or whatever
alternative the system provides with a slightly different name, will
make sure that the buffer is zeroed in memory, and optimizations are not
allowed to impede this zeroing.

This is not really 100% effective, since compilers may place copies of
the string somewhere hidden in the stack.  Those copies won't get zeroed
by explicit_bzero(3).  However, that's arguably a compiler bug, since
compilers should make everything possible to avoid optimizing strings
that are later passed to explicit_bzero(3).  But we all know that
sometimes it's impossible to have perfect knowledge in the compiler, so
this is plausible.  Nevertheless, there's nothing we can do against such
issues, except minimizing the time such passwords are stored in plain
text.

Security concerns
~~~~~~~~~~~~~~~~~

We believe this isn't easy to exploit.  Nevertheless, and since the fix
is trivial, this fix should probably be applied soon, and backported to
all supported distributions, to prevent someone else having more
imagination than us to find a way.

Affected versions
~~~~~~~~~~~~~~~~~

All.  Bug introduced in shadow 19990709.  That's the second commit in
the git history.

Fixes: 45c6603cc8 ("[svn-upgrade] Integrating new upstream version, shadow (19990709)")
Reported-by: Alejandro Colomar <alx@kernel.org>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Seth Arnold <seth.arnold@canonical.com>
Cc: Christian Brauner <christian@brauner.io>
Cc: Balint Reczey <rbalint@debian.org>
Cc: Sam James <sam@gentoo.org>
Cc: David Runge <dvzrv@archlinux.org>
Cc: Andreas Jaeger <aj@suse.de>
Cc: <~hallyn/shadow@lists.sr.ht>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-10 20:35:50 -05:00
Alejandro Colomar
e69d556b63 src/useradd.c: create_mail(): Cosmetic
-  Invert conditional to reduce indentation.
-  Reduce use of whitespace and newlines while unindenting.
-  Reorder variable declarations.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-09 19:04:51 -05:00
Alejandro Colomar
0a90118089 src/useradd.c: create_home(): Cosmetic
-  Invert conditional to reduce indentation.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-09 19:04:51 -05:00
Alejandro Colomar
adf8b3f64f src/useradd.c: create_home(): Cosmetic
-  Invert conditional to reduce indentation.
-  Rewrite while loop calling strtok(3) as a for loop.  This allows
   doing more simplification inside the loop (see next commit).

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-09 19:04:47 -05:00
Alejandro Colomar
c01664c30c src/useradd.c: create_home(): Cosmetic
-  Fix indentation.  It was very broken.
-  Move variable declaration to the top of the block in which it's used.
-  Reduce use of whitespace and newlines.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-09 19:03:57 -05:00
Alejandro Colomar
7415885fb3 src/useradd.c: close_group_files(): Cosmetic
-  Invert conditional, to reduce indentation.
-  Reduce use of whitespace and newlines while unindenting.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-09 19:02:41 -05:00
Alejandro Colomar
89bdd3660c src/useradd.c: check_uid_range(): Cosmetic
-  Merge nested conditionals into a single if, to reduce indentation.
-  Indent (1 SP) nested preprocessor conditionals.
-  Reduce use of whitespace and newlines while unindenting.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-09 19:02:41 -05:00
Jaroslav Jindrak
4b06c28353 build: link passwd, chpasswd and chage against libdl 2023-06-09 16:22:24 +02:00
Jaroslav Jindrak
cc0aaaa18f configure: check whether fgetpwent_r is available before marking xprefix_getpwnam_r as reentrant 2023-06-09 16:22:24 +02:00
Jaroslav Jindrak
68bf73f319 passwd: fall back to non-PAM code when prefix is used
Prefix does not make sense when we use PAM, so when the option
is used behave as if --with-libpam=no was used to configure the
project.
2023-06-09 16:22:24 +02:00
Jaroslav Jindrak
2d0beef3bb chpasswd: fall back to non-PAM code when prefix is used
The prefix option does not make sense in that scenario and the
encryption options already do this.
2023-06-09 16:22:24 +02:00
Jaroslav Jindrak
13b0a2bf3b chpasswd: add --prefix/-P options 2023-06-09 16:22:24 +02:00
Jaroslav Jindrak
ef8a4449b1 chage: add --prefix/-P options 2023-06-09 16:22:24 +02:00
Jaroslav Jindrak
43e60eb681 passwd: Respect --prefix/-P options
Add prefix_getpwnam_r() and xprefix_getpwnam() and make passwd
use prefix-aware functions when handling the database.
2023-06-09 16:22:24 +02:00
Michael Vetter
ded9cab35d prefix: add prefix support 2023-06-09 16:22:24 +02:00
Iker Pedrosa
89a7ee7b22 strtoday: remove unnecessary cast
Resolves: https://github.com/shadow-maint/shadow/issues/704

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-06-09 07:48:48 -05:00
Alejandro Colomar
787ea57a18 Use temporary variable
-  Use the temporary variable more, as it helps readability: it removes
   a derefecence, which itself allows removing some parentheses.

-  Use a shorter name, which is more common with temporaries, and so
   there's less to read.

-  Assign to *ranges at the end of the function.  It's the same, but
   with the other changes, I think this makes it slightly clearer.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-08 09:05:39 -05:00
Alejandro Colomar
f2ac1e2540 realloc(NULL, ...) is equivalent to malloc(...)
Don't have a branch for when the old pointer is NULL.  realloc(3) can
handle that case just fine.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-08 09:05:39 -05:00
Alejandro Colomar
09775d3718 Simplify allocation APIs
If we consider simple objects as arrays of size 1, we can considerably
simplify these APIs, merging the *ARRAY and the non-array variants.

That will produce more readable code, since lines will be shorter (by
not having ARRAY in the macro names, as all macros will consistently
handle arrays), and the allocated size will be also more explicit.

The syntax will now be of the form:

    p = MALLOC(42, foo_t);  // allocate 42 elements of type foo_t.
    p = MALLOC(1, bar_t);   // allocate 1 element of type foo_t.

The _array() allocation functions should _never_ be called directly, and
instead these macros should be used.

The non-array functions (e.g., malloc(3)) still have their place, but
are limited to allocating structures with flexible array members.  For
any other uses, the macros should be used.

Thus, we don't use any array or ARRAY variants in any code any more, and
they are only used as implementation details of these macros.

Link: <https://software.codidact.com/posts/285898/288023#answer-288023>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-08 09:05:39 -05:00
Christian Göttsche
065a752b42 Drop alloca(3)
alloca(3) fails silently if not enough memory can be allocated on the
stack.  Use checked dynamic allocation instead.

Also drop unnecessary manual NUL assignment, ensured by snprintf(3).

Co-developed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-08 09:05:39 -05:00
Christian Göttsche
7a2b302e68 usermod: fix off-by-one issues
Allocate enough memory for the strings, two slashes and the NUL
terminator.

Reported-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-08 09:05:39 -05:00
Alejandro Colomar
170d24a251 libmisc/csrand.c: Update comments
Those comments were written when this function used 64 bits (and
temporary variables of 128 bits).  Now it uses 32 bits, with temporaries
of 64 bits, so some values have changed.

Fixes: 2a61122b5e ("Unoptimize the higher part of the domain of csrand_uniform()")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-06-05 16:50:40 -05:00
Alejandro Colomar
70399856c1 lib/nss.c: Fix use of invalid p
getline(3) might have succeeded in a previous iteration, in which case
p points to an offset that is not valid.  Make p NULL at the end of the
loop, to make sure it doesn't hold old stuff.

Link: <https://github.com/shadow-maint/shadow/pull/737#issuecomment-1568948769>
Reported-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-31 09:29:49 -05:00
Alejandro Colomar
848a95329c lib/nss.c: Fix use of uninitialized p
getline(3) might have never succeeded, in which case p is uninitialized
when used in strtok_r(3).

Link: <https://github.com/shadow-maint/shadow/pull/737#discussion_r1206007358>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-31 09:29:49 -05:00
Alejandro Colomar
54ba4814ae Centralize error handling
This makes the function fit in less screens.  This is to avoid consuming
more natural resources than we have available, and everyone knows the
supply of new-lines on a screen is not a renewable source[1].

Some transformations have been done thanks to free(NULL) being an alias
for loopity_loop(), as defined three comits ago.  The real definition of
free(3) that everyone has been hiding is this:

void
free(void *p)
{
	if (p == NULL)
		loopity_loop();
	else
		real_free(p);
}

Link: [1] <https://www.kernel.org/doc/html/v6.3/process/coding-style.html#placing-braces-and-spaces>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-31 09:29:49 -05:00
Alejandro Colomar
07b885318f Second verse, it gets worse; it gets no better than this
Just in case it's not obious:

	strlen("") < 8
	isalpha('\0') == false
	isdigit('\0') == false
	isspace('\0') == false

Link: <https://github.com/shadow-maint/shadow/pull/737>
Easter-egg: 8492dee663 ("subids: support nsswitch")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-31 09:29:49 -05:00
Alejandro Colomar
2f9ca4b49d ROFL: Rolling on the floor looping
Please tell me this was an easter egg :P

 #define go_banana() ({ goto nowhere; nowhere: 0-0; })

Closes: <https://github.com/shadow-maint/shadow/issues/736>
Easter-egg: 8492dee663 ("subids: support nsswitch")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-31 09:29:49 -05:00
Alejandro Colomar
8219fbd421 This ain't no loop
This was to a loop, as "1234" is to computer security.

No really; a loop that ends in a (forward) goto, and has no continue in it.

Still want a loop?  Take two:

 #define loopity_loop() do { for (;;) { break; } continue; } while (0-0)

Closes: <https://github.com/shadow-maint/shadow/issues/736>
Easter-egg: 8492dee663 ("subids: support nsswitch")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-31 09:29:49 -05:00
Iker Pedrosa
9233e5e0ae newusers: Improve error message
Fixes: b422e3c316: Check if crypt_method null before dereferencing

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-05-31 09:53:31 +02:00
Martin Kletzander
3c7327842c ch(g)passwd: Check selinux permissions upon startup
The permission also need to be checked before process_root_flag() since
that can chroot into non-selinux environment (unavailable selinux mount
point for example).

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2023-05-31 09:44:25 +02:00
Skyler Ferrante
b422e3c316 Check if crypt_method null before dereferencing
Make sure crypto_method set before sha-rounds. Only affects newusers.
2023-05-30 14:00:12 -05:00
Alejandro Colomar
d9f0246611 xgetXXbyYY: Simplify elifs
-  Use SIZE_MAX rather than (size_t)-1, to improve readability.

-  Move the only branch that breaks to the first place, so that we
   remove an else.  This reduces nesting while parsing the code.

-  Now that we only have a 2-branch conditional where both branches
   assign to the same variable, rewrite it as a ternary, to shorten.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-30 13:56:55 -05:00
Alejandro Colomar
89c9427087 xgetXXbyYY: Centralize error handling
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-30 13:56:55 -05:00
Alejandro Colomar
c8741a400d xgetXXbyYY: tfix
It seems obvious that it was a typo.

Link: <https://github.com/shadow-maint/shadow/pull/729#discussion_r1207551013>
Fixes: e73a2194b3 ("xgetXXbyYY: Handle DUP_FUNCTION failure")
Cc: Samanta Navarro <ferivoz@riseup.net>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-30 13:56:55 -05:00
Samanta Navarro
dcc90658fd xgetXXbyYY: Avoid duplicated error handling block
The error handling is performed after the loop. By just calling break it
is possible to reuse the error handling if status is not ERANGE.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-26 16:03:27 -05:00
Samanta Navarro
e73a2194b3 xgetXXbyYY: Handle DUP_FUNCTION failure
A failure of DUP_FUNCTION is already handled for non-reentrant
function wrapper. Perform the check for reentrant version as well.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-26 16:03:27 -05:00
Serge Hallyn
a80b792afc sub_[ug]id_{add,remove}: fix return values
On failure, these are meant to return 0 with errno set.  But if
an nss module is loaded, they were returning -ERRNO instead.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-05-26 15:16:29 -05:00
Martin Kletzander
8665fe1957 usermod: Small optimization using memmove for password unlock
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2023-05-26 15:14:02 -05:00
Alejandro Colomar
e3b7058110 Reorder logic to improve comprehensibility
-  Don't else after return or fail_exit().
-  Prefer == over != (negated logic is more complex to think about it).
-  Reduce nesting when reasonable.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-25 21:22:08 -05:00
Alejandro Colomar
5b117d5526 newusers: Fail early
There's no reason to report all errors.  Bail out at the first one,
which is simpler.

Suggested-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-25 21:22:08 -05:00
Alejandro Colomar
1957c8c881 newusers: Add missing error handling
Some errors were being reported in stderr, but then they weren't really
being treated as errors.

If mkdir(2) for EEXIST, it's possible that the sysadmin pre-created the
user dir; don't fail.  However, let's keep a log line, for having some
notice that it happened.

Also, run chmod(2) if mkdir(2) failed for EEXIST (so transform the
'else if' into an 'if').

Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-05-25 21:22:08 -05:00
Samanta Navarro
6491fef1e0 libmisc: Use safer chroot/chdir sequence
OpenSSH and coreutils' chroot call chroot first and then chdir. Doing it
this way is a bit safer because otherwise something could happen between
chdir and chroot to the specified path (like exchange of links) so the
working directory would not end up within the chroot environment.

This is a purely defensive measure.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-25 08:25:42 -05:00
Samanta Navarro
a116e20c76 su: Prevent stack overflow in check_perms
This is no real world security fix.

The overflow could occur if too many layered subsystems are encountered
because the function check_perms calls itself recursively.

It would already take a misconfigured system for this to achieve it.

Use an iterative approach by calling the do_check_perms in a loop
instead of calling itself recursively.

As a side note: At least GCC 13 optimized this code and already uses
a jmp in its assembler code. I could only see the stack overflow by
activating address sanitizer which prevented the optimization.

Co-developed-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-25 08:25:42 -05:00
Samanta Navarro
4ad359ccc6 subsystem: Prevent endless loop
If a user has home directory "/" and login shell "*" then login and su
enter an endless loop by constantly switching to the next subsystem.

This could also be achieved with a layered approach so just checking
for "/" as home directory is not enough to protect against such a
misconfiguration.

Just break the loop if it progressed too far. I doubt that this has
negative impact on any real setup.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-25 08:25:42 -05:00
Serge Hallyn
419cf1f1c4 def_load: avoid NULL deref
If econf_getStringValue() fails, it will return an error and
set value to NULL.  Look for the error and avoid dereferencing
value in that case.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-05-22 10:23:12 +02:00
Serge Hallyn
9e854f525d def_load: split the econf from non-econf definition
The function is completely different based on USE_CONF.  Either copy
will be easier to read if we just keep them completely separate.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-05-22 10:23:12 +02:00
Tobias Stoeckmann
8175b1532e Plug econf memory leaks
You can see the memory leaks with address sanitizer if shadow is
compiled with `--enable-vendordir=/usr/etc`.

How to reproduce:

1. Prepare a custom shell file as root
```
mkdir -p /etc/shells.d
echo /bin/myshell > /etc/shells.d/custom
```

2. Run chsh as regular user
```
chsh
```

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2023-05-19 08:02:24 -05:00
Samanta Navarro
7321ceaf69 chsh: Verify that login shell path is absolute
The getusershell implementation of musl returns every line within the
/etc/shells file, which even includes comments. Only consider absolute
paths for login shells.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-18 16:03:41 +02:00
Samanta Navarro
812f934e77 process_prefix_flag: Drop privileges
Using --prefix in a setuid binary is quite dangerous. An unprivileged
user could prepare a custom shadow file in home directory. During a data
race the user could exchange directories with links which could lead to
exchange of shadow file in system's /etc directory.

This could be used for local privilege escalation.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-18 15:36:59 +02:00
bubu
1132b89236 Update French translations
Please find attached the french updated translation of shadow-man-page,
proofread by the debian-l10n-french mailing list contributors.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-05-15 08:42:40 -05:00
Samanta Navarro
4ef4477535 get_pid.c: Use tighter validation checks
Neither a pid_t below 1 nor a negative fd could be valid in this context.

Proof of Concept:

$ newuidmap -1 1 1 1
newuidmap: Could not open proc directory for target 4294967295

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-15 09:21:16 +02:00
Markus Hiereth
a022d39d2a replace inadequate German translation of login error message
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-05-11 17:01:43 -05:00
Markus Hiereth
bd6db6f226 Update German translations
find the attached German message catalogue proofread by the German
language team.

Best regards
Markus

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-05-11 11:05:59 -05:00
Samanta Navarro
666468cc36 Remove some static char arrays
Some strings are first written into static char arrays before passed to
functions which expect a const char pointer anyway.

It is easier to pass these strings directly as arguments.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-11 11:05:29 -05:00
Samanta Navarro
72290ede0e commonio: Use do_lock_file again
This avoids regressions introduced with do_fcntl_lock.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-11 10:59:21 -05:00
Serge Hallyn
4abcbb056e Fix broken docbook translations
its by default does not support xml tags inside translatable
units.  Use custom its rules from

https://www.w3.org/TR/xml-i18n-bp/#relating-docbook-plus-its

to enable the tags which are in use by docbook.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-05-10 09:15:53 +02:00
ed neville
0bce9c9808 open with O_CREAT when lock path does not exist
Reported in #686, by wyj611 when trying to lock a file that is not
present

Lock method should be F_SETLKW rather than open file descriptor
2023-05-08 08:16:11 -05:00
Samanta Navarro
627631bf9a commonio_open: Remove fcntl call
The fcntl call to set FD_CLOEXEC can be performed directly with the
previously performed open call by using the O_CLOEXEC flag.

O_CLOEXEC is required by POSIX.1-2008.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-05 16:15:46 +02:00
Samanta Navarro
e899e3d745 commonio_lock_nowait: Remove deprecated code
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-05 16:15:46 +02:00
Samanta Navarro
7109b7c066 login_prompt: Simplify login_prompt API
The only user of login_prompt is the login tool. This implies that the
first argument is always the same.

It is much easier to verify printf's format string and its argument if
both are next to each other.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-03 07:54:28 -05:00
Samanta Navarro
3010ec11ae login_prompt: Use _exit in signal handler
Calling exit is not signal safe.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-03 07:54:28 -05:00
Samanta Navarro
8fc8de382a login_prompt: Do not parse environment variables
Parsing optional environment variables after a login name is a feature
which is neither documented nor available in util-linux or busybox
login which are other wide spread login utilities used in Linux
distributions as reference.

Removing this feature resolves two issues:

- A memory leak exists if variables without an equal sign are used,
  because set_env creates copies on its own. This could lead to OOM
  situations in privileged part of login or may lead to heap spraying.
- Environment variables are not reset between login attempts. This
  could lead to additional environment variables set for a user who
  never intended to do so.

Proof of Concept on a system with shadow login without PAM and
util-linux agetty:

1. Provoke an invalid login, e.g. user `noone` and password `invalid`.
   This starts shadow login and subsequent inputs are passed through
   the function login_prompt.
2. Provoke an invalid login with environment variables, e.g.
   user `noone HISTFILE=/tmp/owo` and password `invalid`.
3. Log in correctly with user `root`.

Now you can see with `echo $HISTFILE` that `/tmp/owo` has been set for
the root user.

This requires a malicious failed login attempt and a successful login
within the configured login timeout (default 60 seconds).

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-05-03 07:54:28 -05:00
Samanta Navarro
c0fc4d2122 libmisc/yesno.c: Fix regression
The getline function does not return a pointer but the amount of read
characters. The error return value to check for is -1.

Set buf to NULL to avoid dereference of an uninitialized stack value.

The getline function returns -1 if size argument is NULL. Always use
a valid pointer even if size is unimportant.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-04-28 11:22:48 -05:00
Alejandro Colomar
0c4fa6ee0a libmisc, man: Drop old check and advice for complex character sets in passwords
Add the relevant XKCD to the passwd(1) manual page.  It already explains
most of the rationale behind this patch.

Add also reference to makepasswd(1), which is a good way to generate
strong passwords.  Personally, I commonly run `makepasswd --chars 64` to
create my passwords, or 32 for passwords I need to type interactively
often.

The strength of a password is an exponential formula, where the base is
the size of the character set, and the exponent is the length of the
password.  That already shows why long passwords of just lowercase
letters are better than short Pa$sw0rdZ3.  But an even more important
point is that humans, when forced to use symbols in a password, are more
likely to do trivial substitutions on simple passwords, which doesn't
increase strength, and can instead give a false sense of strength, which
is dangerous.

Closes: <https://github.com/shadow-maint/shadow/issues/688>
Link: <https://xkcd.com/936/>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-04-27 09:16:08 +02:00
Christian Göttsche
7078ed1e0b semanage: disconnect to free libsemanage internals
Destroying the handle does not actually disconnect, see [1].
Also free the key on user removal.

[1]: e9072e7d45/libsemanage/src/direct_api.c (L330)

Example adduser leak:

    Direct leak of 1008 byte(s) in 14 object(s) allocated from:
        #0 0x5638f2e782ae in __interceptor_malloc (./src/useradd+0xee2ae)
        #1 0x7fb5cfffad09 in dbase_file_init src/database_file.c:170:45

    Direct leak of 392 byte(s) in 7 object(s) allocated from:
        #0 0x5638f2e782ae in __interceptor_malloc (./src/useradd+0xee2ae)
        #1 0x7fb5cfffc929 in dbase_policydb_init src/database_policydb.c:187:27

    Direct leak of 144 byte(s) in 2 object(s) allocated from:
        #0 0x5638f2e782ae in __interceptor_malloc (./src/useradd+0xee2ae)
        #1 0x7fb5cfffb519 in dbase_join_init src/database_join.c:249:28

    [...]
2023-04-26 17:52:54 -05:00
Christian Göttsche
a8dd8ce6c9 commonio: free removed database entries
Free the actual struct of the removed entry.

Example userdel report:

    Direct leak of 40 byte(s) in 1 object(s) allocated from:
        #0 0x55b230efe857 in reallocarray (./src/userdel+0xda857)
        #1 0x55b230f6041f in mallocarray ./lib/./alloc.h:97:9
        #2 0x55b230f6041f in commonio_open ./lib/commonio.c:563:7
        #3 0x55b230f39098 in open_files ./src/userdel.c:555:6
        #4 0x55b230f39098 in main ./src/userdel.c:1189:2
        #5 0x7f9b48c64189 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
2023-04-26 17:52:54 -05:00
ed neville
4e1f674c41 run_parts for groupadd and groupdel
run_parts currently exists in useradd and userdel, this commit mirrors
the functionality with groupadd and groupdel

Hook for group{add,del} to include killing processes that have group
membership that would no longer exist to avoid membership ID reuse.
2023-04-26 17:38:24 -05:00
lilinjie
15a64f9e7f fix typos
Signed-off-by: lilinjie <lilinjie@uniontech.com>
2023-04-26 17:35:58 -05:00
Alejandro Colomar
e28deeb8e9 libmisc/yesno.c: Use getline(3) and rpmatch(3)
getline(3) is much more readable than manually looping.  It has some
overhead due to the allocation of a buffer, but that shouldn't be a
problem here.  If that was a problem, we could reuse the buffer (thus
making the function non-reentrant), but I don't think that's worth the
extra complexity.

Using rpmatch(3) instead of a simple y/n test provides i18n to the
response checking.  We have a fall-back minimalistic implementation for
systems that lack this function (e.g., musl libc).

While we're at it, apply some other minor improvements to this file:

-  Remove comment saying which files use this function.  That's likely
   to get outdated.  And anyway, it's just a grep(1) away, so it doesn't
   really add any value.

-  Remove unnecessary casts to (void) that were used to verbosely ignore
   errors from stdio calls.  They add clutter without really adding much
   value to the code (or I don't see it).

-  Remove comments from the function body.  They make the function less
   readable.  Instead, centralize the description of the function into a
   man-page-like comment before the function definition.  This keeps the
   function body short and sweet.

-  Add '#include <stdbool.h>', which was missing.

-  Minor whitespace style changes (it doesn't hurt the diff at this
   point, since most of the affected lines were already touched by other
   changes, so I applied my preferred style :).

Acked-by: Samanta Navarro <ferivoz@riseup.net>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-04-26 17:32:47 -05:00
Samanta Navarro
7b686d8bd6 newgrp/useradd: always set SIGCHLD to default
The tools newgrp and useradd expect waitpid to behave as described in
its manual page. But the notes indicate that if SIGCHLD is ignored,
waitpid behaves differently.

A user could set SIGCHLD to ignore before starting newgrp through exec.
Children of newgrp would not become zombies and their PIDs could be
reassigned before newgrp could call kill with the child pid and SIGCONT.

The useradd tool is not installed setuid, but I have added the default
there as well (copied from vipw).

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-04-26 08:27:45 -05:00
Serge Hallyn
7ed1df2e80 Update AUTHORS to add Marek Michałkiewicz
Closes #708

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-04-24 09:01:22 +02:00
Samanta Navarro
0c83b98105 Read whole line in yes_or_no
Do not stop after 79 characters. Read the complete line to avoid
arbitrary limitations.

Proof of Concept:

```
cat > passwd-poc << EOF
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
EOF
python -c "print(80*'y')" | pwck passwd-poc
```

Two lines should still be within the file because we agreed only once
to remove a duplicated line.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
2023-04-21 18:12:56 -05:00
Christian Göttsche
c80788a3ac useradd/usermod: add --selinux-range argument
Add a command line argument to useradd(8) and usermod(8) to specify the
MLS range for a SELinux user mapping.

Improves: #676
2023-04-19 09:19:19 +02:00
Alejandro Colomar
97f79e3b27 CI: Make build logs more readable
If make fails in a multi-process invocation, the log is pretty much
unreadable.  To make it readable, build as much as can be built without
failing.  Then run a single-process make again.  If we succeeded
previously, this should be a no-op.  If not, this run will stop at the
first error, which should be more readable, and will only print the few
lines we're interested in.

This has some side effects:  Now we build as much as we can, instead of
failing as early as possible; this may make CI a bit slower.  However,
it also has the benefit that you see _all_ the error messages that could
be given, instead of needing to fix the first error to see the next and
so on.

Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-04-18 09:21:09 +02:00
Iker Pedrosa
075ed522be ci: remove explicit fedora dependencies
libbsd-devel libeconf-devel have already been added to the spec file and
they should be installed by the `dnf builddep` command.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-04-13 13:05:32 +02:00
Iker Pedrosa
e047a3acc6 README: add reference to contribution guidelines
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-04-03 10:42:22 -05:00
Iker Pedrosa
981bb8f9d1 doc: add contributions introduction
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-04-03 10:42:22 -05:00
Iker Pedrosa
f6f14a2a83 doc: add license
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-04-03 10:42:22 -05:00
Iker Pedrosa
29df94eb4a doc: add releases
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-04-03 10:42:22 -05:00
Iker Pedrosa
6ceddd9205 doc: add Continuous Integration
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-04-03 10:42:22 -05:00
Iker Pedrosa
77c6cc9857 doc: add tests
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-04-03 10:42:22 -05:00
Iker Pedrosa
d40c58dc3b doc: add coding style
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-04-03 10:42:22 -05:00
Iker Pedrosa
1f15ea5955 doc: add build & install
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-04-03 10:42:22 -05:00
Serge Hallyn
30f3ea4bd3 trivial: vipw.8: fix grammar
Signed-off-by: Serge Hallyn <shallyn@cisco.com>
2023-04-03 13:06:14 +02:00
Christian Göttsche
2eee4c67f5 sssd: skip flushing if executable does not exist
Avoid unnecessary syslog output, like:

    Apr 01 13:35:09 dlaptop userdel[45872]: userdel: sss_cache exited with status 1
    Apr 01 13:35:09 dlaptop userdel[45872]: userdel: Failed to flush the sssd cache.
2023-04-03 13:05:30 +02:00
Christian Göttsche
2eaea70111 Overhaul valid_field()
e5905c4b ("Added control character check") introduced checking for
control characters but had the logic inverted, so it rejects all
characters that are not control ones.

Cast the character to `unsigned char` before passing to the character
checking functions to avoid UB.

Use strpbrk(3) for the illegal character test and return early.
2023-03-31 09:53:40 -05:00
Martin Kletzander
a5f9ef8b7f semanage: Do not set default SELinux range
Both semanage and libsemanage actually set the user's mls range to the
default of the seuser, which makes more sense and removes a bit of code
for usermod and useradd.  More fine-grained details must always be set
with some other tool
(semanage) anyway.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2023-03-31 16:13:02 +02:00
Michael Vetter
b44d7f78e0 Fix typo in groupadd usage 2023-03-31 16:04:42 +02:00
Christian Göttsche
189a01f7a7 ci: update Differential ShellCheck
Run on pushes and drop unnecessary write access.

Should avoid pull-requests comments like
https://github.com/shadow-maint/shadow/pull/695#issuecomment-1491876950
2023-03-31 15:54:39 +02:00
tomspiderlabs
e5905c4b84 Added control character check
Added control character check, returning -1 (to "err") if control characters are present.
2023-03-30 19:23:00 -05:00
Mike Gilbert
bd2d0079c9 usermod: respect --prefix for --gid option
The --gid option accepts a group name or id. When a name is provided, it
is resolved to an id by looking up the name in the group database
(/etc/group).

The --prefix option overides the location of the passwd and group
databases. I suspect the --gid option was overlooked when wiring up the
--prefix option.

useradd --gid already respects --prefix; this change makes usermod
behave the same way.

Fixes: b6b2c756c9
Signed-off-by: Mike Gilbert <floppym@gentoo.org>
2023-03-29 09:05:23 +02:00
Alejandro Colomar
4c210a29bc Fix su(1) silent truncation
*  src/su.c (check_perms): Do not silently truncate user name.

Reported-by: Paul Eggert <eggert@cs.ucla.edu>
Co-developed-by: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-03-28 13:00:38 +02:00
Alejandro Colomar
1d7d94ed7d Simplify is_my_tty()
This commit will serve to document why we shouldn't worry about the
truncation in the call to strlcpy(3).  Since we have one more byte in
tmptty than in full_tty, truncation will produce a string that is at
least one byte longer than full_tty.  Such a string could never compare
equal, so we're actually handling the truncation in a clever way.  Maybe
too clever, but that's why I'm documenting it here.

Now, about the simplification itself:

Since we made sure that both full_tty and tmptty are null-terminated, we
can call strcmp(3) instead of strncmp(3).  We can also simplify the
return logic avoiding one branch.

Cc: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-03-28 13:00:38 +02:00
Alejandro Colomar
e27ca53091 Fix is_my_tty() buffer overrun
*  libmisc/utmp.c (is_my_tty): Declare the parameter as a char array,
   not char *, as it is not necessarily null-terminated.
   Avoid a read overrun when reading 'tty', which comes from
   'ut_utname'.

Reported-by: Paul Eggert <eggert@cs.ucla.edu>
Co-developed-by: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-03-28 13:00:38 +02:00
Alejandro Colomar
664d361fa5 Add STRLEN(): a constexpr strlen(3) for string literals
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-03-28 13:00:38 +02:00
Alejandro Colomar
03af2940f7 Fix crash with large timestamps
*  libmisc/date_to_str.c (date_to_str): Do not crash if gmtime(3)
   returns NULL because the timestamp is far in the future.

Reported-by: Paul Eggert <eggert@cs.ucla.edu>
Co-developed-by: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-03-28 13:00:38 +02:00
Paul Eggert
ea3d49506f Prefer strcpy(3) to strlcpy(3) when either works
* lib/gshadow.c (sgetsgent): Use strcpy(3) not strlcpy(3),
since the string is known to fit.

Signed-off-by: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-03-28 13:00:38 +02:00
Paul Eggert
a926a26f0c Fix change_field() buffer underrun
* lib/fields.c (change_field): Don't point
before array start; that has undefined behavior.

Signed-off-by: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-03-28 13:00:38 +02:00
Paul Eggert
690ca8c238 Omit unneeded test in change_field()
* fields.c (change_field): Omit unnecessary test.

Signed-off-by: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-03-28 13:00:38 +02:00
Paul Eggert
5686d9162e Simplify change_field() by using strcpy
* lib/fields.c (change_field): Since we know the string fits,
use strcpy(3) rather than strlcpy(3).

Signed-off-by: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-03-28 13:00:38 +02:00
skyler-ferrante
c089196e15 Fix null dereference in basename
On older kernels (<=linux-5.17), argv[0] can be null. Basename would
call strrchr with null if argc==0. Fixes issue #680
2023-03-27 10:10:37 -05:00
Iker Pedrosa
300d6ef45c CI: script for local container build
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-03-26 12:45:34 -05:00
Iker Pedrosa
d4f31a5b3e CI: build project in containers
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-03-26 12:45:34 -05:00
Iker Pedrosa
411a66476d container: add fedora
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-03-26 12:45:34 -05:00
Iker Pedrosa
3efab2039f container: add debian
Signed-off-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-03-26 12:45:34 -05:00
Iker Pedrosa
baff19767d container: add alpine
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-03-26 12:45:34 -05:00
Iker Pedrosa
53a4bda9ba SECURITY.md: add Iker Pedrosa
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-03-20 10:54:45 -05:00
Christian Göttsche
f2c4949707 selinux: use type safe function pointer assignment 2023-03-20 08:47:52 +01:00
Christian Göttsche
37bf59067f Use strict prototype in definition
gettime.c:25:30: warning: a function declaration without a prototype is deprecated in all versions of C [-Wstrict-prototypes]
    /*@observer@*/time_t gettime ()
                                 ^
                                  void
2023-03-20 08:47:52 +01:00
Vinícius dos Santos Oliveira
e638841f5a Add .editorconfig 2023-03-02 16:33:06 -06:00
Serge Hallyn
61ca915ac5 run_some: fix shellcheck warning
shellcheck warns against using echo with flags, as posix sh won't
support it.  It suggests using printf, so let's do that.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-02-27 21:38:45 -06:00
Serge Hallyn
6d03bbea96 fail on any run_some test failure
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-02-27 21:38:45 -06:00
Serge Hallyn
add4ab4bf0 ignore first test in run_some
bc github...

For some reason, the first test - ONLY on github - seems to not
give the '$ ' prompt expected when you spawn 'su testsuite'.
So just run the first test twice, and ignore the first failure.
2023-02-27 21:38:45 -06:00
Serge Hallyn
4da831c02f swap first two tests - does the first one still fail?
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-02-27 21:38:45 -06:00
Serge Hallyn
421c6cf951 tests: remove some github runner PATH tweaking
It messes with the expected results.

We can do better than this in the expect scripts, but let's
get things running for now.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-02-27 21:38:45 -06:00
Alejandro Colomar
a72065a108 tests: Support git-worktree(1)
git-worktree(1) uses a regular file for <.git>, instead of a directory.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-27 14:16:50 -06:00
Serge Hallyn
4445cee19d tests: newuidmap and newgidmap: update expected fail message
The failure message got changed, but the tests looking for it did
not.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-02-24 21:46:29 -06:00
Serge Hallyn
aa15bc445e libsubid: include alloc.h
Fixes: efbbcade43: Use safer allocation macros
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-02-24 21:27:02 -06:00
Serge Hallyn
9a9e163e71 run_some: log stderr
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-02-24 20:11:14 -06:00
Vinícius dos Santos Oliveira
05e2adf509 Validate fds created by the user
write_mapping() will do the following:

openat(proc_dir_fd, map_file, O_WRONLY);

An attacker could create a directory containing a symlink named
"uid_map" pointing to any file owned by root, and thus allow him to
overwrite any root-owned file.
2023-02-24 16:20:57 -06:00
Serge Hallyn
7ff33fae6f get_pidfd_from_fd: return -1 on error, not 0
Fixes: 6974df39a: newuidmap and newgidmap: support passing pid as fd
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-02-24 13:54:54 -06:00
Serge Hallyn
17efd59252 g-h-a workflow: workaround
Skip updating grub packages that are currently breaking
apt-get dist-upgrade.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-02-24 13:27:57 -06:00
Serge Hallyn
e4e3212122 Fix regression in some translation strings
Fixes: d80df2c8a: Update translation
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-02-24 12:56:05 -06:00
Iker Pedrosa
3b3d3e5cd4 lib: bit_ceil_wrapul(): stop recursion
It should call bit_ceilul() instead of itself.

Fixes: 0712b236c3 ("Add bit manipulation functions")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-02-24 12:44:14 -06:00
Iker Pedrosa
21d88b4525 lib: define ULONG_WIDTH if non-existent
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2023-02-24 12:44:14 -06:00
maqi
d80df2c8a0 Update translation 2023-02-24 12:41:50 -06:00
Serge Hallyn
6974df39a7 newuidmap and newgidmap: support passing pid as fd
Closes #635

newuidmap and newgidmap currently take an integner pid as
the first argument, determining the process id on which to
act.  Accept also "fd:N", where N must be an open file
descriptor to the /proc/pid directory for the process to
act upon.  This way, if you

exec 10</proc/99
newuidmap fd:10 100000 0 65536

and pid 99 dies and a new process happens to take pid 99 before
newuidmap happens to do its work, then since newuidmap will use
openat() using fd 10, it won't change the mapping for the new
process.

Example:

// terminal 1:
serge@jerom ~/src/nsexec$ ./nsexec -W -s 0 -S 0 -U
about to unshare with 10000000
Press any key to exec (I am 129176)

// terminal 2:
serge@jerom ~/src/shadow$ exec 10</proc/129176
serge@jerom ~/src/shadow$ sudo chown root src/newuidmap src/newgidmap
serge@jerom ~/src/shadow$ sudo chmod u+s src/newuidmap
serge@jerom ~/src/shadow$ sudo chmod u+s src/newgidmap
serge@jerom ~/src/shadow$ ./src/newuidmap fd:10 0 100000 10
serge@jerom ~/src/shadow$ ./src/newgidmap fd:10 0 100000 10

// Terminal 1:
uid=0(root) gid=0(root) groups=0(root)

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-02-24 12:35:49 -06:00
Alejandro Colomar
7668f77439 Fix use-after-free of pointer after realloc(3)
We can't use a pointer that was input to realloc(3), nor any pointers
that point to reallocated memory, without making sure that the memory
wasn't moved.  If we do, the Behavior is Undefined.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-23 20:28:43 -06:00
Alejandro Colomar
efbbcade43 Use safer allocation macros
Use of these macros, apart from the benefits mentioned in the commit
that adds the macros, has some other good side effects:

-  Consistency in getting the size of the object from sizeof(type),
   instead of a mix of sizeof(type) sometimes and sizeof(*p) other
   times.

-  More readable code: no casts, and no sizeof(), so also shorter lines
   that we don't need to cut.

-  Consistency in using array allocation calls for allocations of arrays
   of objects, even when the object size is 1.

Cc: Valentin V. Bartenev <vbartenev@gmail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-23 20:28:43 -06:00
Alejandro Colomar
6e58c12752 libmisc: Add safer allocation macros
This macros have several benefits over the standard functions:

-  The type of the allocated object (not the pointer) is specified as an
   argument, which improves readability:
   -  It is directly obvious what is the type of the object just by
      reading the macro call.
   -  It allows grepping for all allocations of a given type.

   This is admittedly similar to using sizeof() to get the size of the
   object, but we'll see why this is better.

-  In the case of reallocation macros, an extra check is performed to
   make sure that the previous pointer was compatible with the allocated
   type, which can avoid some mistakes.

-  The cast is performed automatically, with a pointer type derived from
   the type of the object.  This is the best point of this macro, since
   it does an automatic cast, where there's no chance of typos.

   Usually, programmers have to decide whether to cast or not the result
   of malloc(3).  Casts usually hide warnings, so are to be avoided.
   However, these functions already return a void *, so a cast doesn't
   really add much danger.  Moreover, a cast can even add warnings in
   this exceptional case, if the type of the cast is different than the
   type of the assigned pointer.  Performing a manual cast is still not
   perfect, since there are chances that a mistake will be done, and
   even ignoring accidents, they clutter code, hurting readability.
   And now we have a cast that is synced with sizeof.

-  Whenever the type of the object changes, since we perform an explicit
   cast to the old type, there will be a warning due to type mismatch in
   the assignment, so we'll be able to see all lines that are affected
   by such a change.  This is especially important, since changing the
   type of a variable and missing to update an allocation call far away
   from the declaration is easy, and the consequences can be quite bad.

Cc: Valentin V. Bartenev <vbartenev@gmail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-23 20:28:43 -06:00
Alejandro Colomar
f332379ea0 Use xreallocarray() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-23 20:28:43 -06:00
Alejandro Colomar
190a702225 Use reallocarrayf() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-23 20:28:43 -06:00
Alejandro Colomar
191f04f7dc Use *array() allocation functions where appropriate
This prevents overflow from multiplication.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-23 20:28:43 -06:00
Alejandro Colomar
727275a027 Use xcalloc(3) instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-23 20:28:43 -06:00
Alejandro Colomar
d81506de1e libmisc: Add safer allocation functions
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-23 20:28:43 -06:00
Alejandro Colomar
881c1d63a1 libmisc: Move xmalloc.c to alloc.c
We'll expand the contents in a following commit, so let's move the file
to a more generic name, have a dedicated header, and update includes.

Signed-off-by: Alejandro Colomar <alx@kernel.org>

Use the new header for xstrdup()

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-23 20:28:43 -06:00
Alejandro Colomar
a578617cc0 Use calloc(3) instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-23 20:28:43 -06:00
Alejandro Colomar
1aa22c1467 Use reallocarray(3) instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-23 20:28:43 -06:00
Alejandro Colomar
45c0003e53 Use reallocf(3) instead of its pattern
In addition, don't set local variables just before return.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-23 20:28:43 -06:00
Alejandro Colomar
56e4842db0 malloc(3) already sets errno to ENOMEM
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-23 20:28:43 -06:00
Alejandro Colomar
0e1d017993 Rely on realloc(NULL, ...) being equivalent to malloc(...)
This is guaranteed by ISO C.  Now that we require ISO C (and even POSIX)
to compile, we can simplify this code.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-23 20:28:43 -06:00
Alejandro Colomar
5c5dc75641 libmisc: agetpass(): Fix bug detecting truncation
On 2/19/23 18:09, David Mudrich wrote:
> I am working on a RAM based Linux OS from source, and try to use
> latest versions of all software.  I found shadow needs libbsd's
> readpassphrase(3) as superior alternative to getpass(3).  While
> considering if I a) include libbsd, or include libbsd's code of
> readpassphrase(3) into shadow, found, that libbsd's readpassphrase(3)
> never returns \n or \r
> <https://cgit.freedesktop.org/libbsd/tree/src/readpassphrase.c>
> line 122, while agetpass() uses a check for \n in agetpass.c line 108.
> I assume it always fails.

Indeed, it always failed.  I made a mistake when writing agetpass(),
assuming that readpassphrase(3) would keep newlines.

>
> I propose a check of len == PASS_MAX - 1, with false positive error for
> exactly PASS_MAX - 1 long passwords.

Instead, I added an extra byte to the allocation to allow a maximum
password length of PASS_MAX (which is the maximum for getpass(3), which
we're replacing.

While doing that, I notice that my previous implementation also had
another bug (minor): The maximum password length was PASS_MAX - 1
instead of PASS_MAX.  That's also fixed in this commit.

Reported-by: David Mudrich <dmudrich@gmx.de>
Fixes: 155c9421b9 ("libmisc: agetpass(), erase_pass(): Add functions for getting passwords safely")
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-20 12:16:01 +01:00
Martin Kletzander
baae5b4a06 find_new_[gu]id(): Skip over IDs that are reserved for legacy reasons
Some programs don't support `(uint16_t) -1` or `(uint32_t) -1` as user
or group IDs.  This is because `-1` is used as an error code or as an
unspecified ID, e.g. in `chown(2)` parameters, and in the past, `gid_t`
and `uid_t` have changed width.  For legacy reasons, those values have
been kept reserved in programs today (for example systemd does this; see
the documentation in the link below).

This should not be confused with catching overflow in the ID values,
since that is already caught by our ERANGE checks.  This is about not
using reserved values that have been reserved for legacy reasons.

Link: <https://systemd.io/UIDS-GIDS/>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2023-02-20 12:10:02 +01:00
Samanta Navarro
0dfeb9e674 Fix comments
These comments should indicate which functions they really wrap.
An alternative would be to remove the line completely to avoid
future copy&paste mistakes.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-02-16 13:23:08 -06:00
Samanta Navarro
c53b36fe85 Fix grammar
Use proper grammar (third-person singular).

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-02-16 13:23:08 -06:00
Samanta Navarro
b8ea76ba72 Fix typo
It should be "if" not "is".

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-02-16 13:23:08 -06:00
Samanta Navarro
d5d1932370 Fix typos
It is a user, not an user.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-02-16 13:23:08 -06:00
Alejandro Colomar
5956cea1d1 Use stpecpy() where appropriate
This function simplifies the calculation of the bounds of the buffer for
catenating strings.  It would also reduce error checking, but we don't
care about truncation in this specific code. :)

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-16 11:29:33 +01:00
Alejandro Colomar
709e6b4497 Add stpecpy()
strncat(3), strlcpy(3), and many other functions are often misused for
catenating strings, when they should never be used for that.  strlcat(3)
is good.  However, there's no equivalent to strlcat(3) similar to
snprintf(3).  Let's add stpecpy(), which is similar to strlcat(3), but
it is also the only function compatible with stpeprintf(), which makes
it more useful than strlcat(3).

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-16 11:29:33 +01:00
Alejandro Colomar
e0e9e57a72 Add mempcpy(3)
We'll use it for implementing stpecpy(), and may be interesting to have
it around.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-16 11:29:33 +01:00
Alejandro Colomar
8a9285aacb Remove unnecessary NUL terminators
All the string-copying functions called above do terminate the strings
they create with a NUL byte.  Writing it again at the end of the buffer
is unnecessary paranoid code.  Let's remove it.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-16 11:29:33 +01:00
Alejandro Colomar
46610792e9 Use stpeprintf() where appropriate
This function allows reducing error checking (since errors are
propagated across chained calls), and also simplifies the calculation of
the start and end of the buffer where the string should be written.

Moreover, the new code is more optimized, since many calls to strlen(3)
have been removed.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-16 11:29:33 +01:00
Alejandro Colomar
7e213cfb50 Add stpeprintf()
[v]stpeprintf() are similar to [v]snprintf(3), but they allow chaining.
[v]snprintf(3) are very dangerous for catenating strings, since the
obvious ways to do it invoke Undefined Behavior, and the ways that avoid
UB are very error-prone.

Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-16 11:29:33 +01:00
Alejandro Colomar
a187ad8e9e agetpass.c: Use SPDX tags
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-16 11:29:33 +01:00
Martin Kletzander
ca9e309d30 Fix VPATH build
When trying to build shadow in a different directory I stumbled upon few
issues, this commit aims to fix all of them:

- The `subid.h` file is generated and hence in the build directory and
	not in the source directory, so use `$(builddir)` instead of
	`$(srcdir)`.

- Using `$<` instead of filenames utilises autotools to locate the files
  in either the source or build directory automatically.

- `xsltproc` needs to access the files in login.defs.d in either the
  source directory or the symlink in a language subdirectory, but it
	does not interpret the `--path` as prefix of the entity path, but
	rather a path under which to locate the basename of the entity
	from the XML file.  So specify the whole path to login.defs.d.

- The above point could be used to make the symlinks of login.defs.d
  and entity path specifications in the XMLs obsolete, but I trying
	not to propose possibly disrupting patches, so for the sake of
	simplicity just specify `$(srcdir)` when creating the symlink.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
2023-02-13 10:01:17 +01:00
Alejandro Colomar
5da8388fc6 ttytype(): Fix race
The intention of the code is just to not report an error message when
'typefile' doesn't exist.  If we call access(2) and then fopen(2),
there's a race.  It's not a huge problem, and the worst thing that can
happen is reporting an error when the file has been removed after
access(2).  It's not a problem, but we can fix the race and at the same
time clarify the intention of not warning about ENOENT and also remove
one syscall.  Seems like a win-win.

Suggested-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-09 10:03:03 -06:00
Alejandro Colomar
bddcd9b095 Remove superfluous casts
-  Every non-const pointer converts automatically to void *.
-  Every pointer converts automatically to void *.
-  void * converts to any other pointer.
-  const void * converts to any other const pointer.
-  Integer variables convert to each other.

I changed the declaration of a few variables in order to allow removing
a cast.

However, I didn't attempt to edit casts inside comparisons, since they
are very delicate.  I also kept casts in variadic functions, since they
are necessary, and in allocation functions, because I have other plans
for them.

I also changed a few casts to int that are better as ptrdiff_t.

This change has triggered some warnings about const correctness issues,
which have also been fixed in this patch (see for example src/login.c).

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-09 10:03:03 -06:00
Serge Hallyn
66daa74232 run on github runner 2023-02-09 09:55:04 -06:00
Serge Hallyn
8728bd87ed tests: print default timeout message to stderr
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-02-09 09:55:04 -06:00
Serge Hallyn
6a51e6893e use self-hosted runner for testsuite
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-02-09 09:55:04 -06:00
Alejandro Colomar
416707b087 Use the noreturn attribute, rather than comments
This will allow the compiler to understand these functions better.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-08 22:01:01 -06:00
Alejandro Colomar
b34387745a lib/defines.h: Add NORETURN attribute macro
We could use the standard (C11) _Noreturn qualifier, but it will be
deprecated in C23, and replaced by C++'s [[noreturn]], which is
compatible with the GCC attribute, so let's directly use the attribute,
and in the future we'll be able to switch to [[]].

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-08 22:01:01 -06:00
Alejandro Colomar
e762ab8b54 Assume getutent(3) exists (remove dead code)
Recently, we removed support for 'struct utmpx'.  We did it because utmp
and utmpx are identical, and while POSIX specifies utmpx (and not utmp),
GNU/Linux documentation seems to favor utmp.  Also, this project
defaulted to utmp, so changing to utmpx would be more dangerous than
keeping old defaults, even if it's supposed to be the same.

Now, I just found more code that didn't make much sense: lib/utent.c
provides definitions for getutent(3) and friends in case the system
doesn't provide them, but we don't provide prototypes for those
definitions, so code using the functions would have never compiled.

Let's just remove these definitions as dead code.

Fixes: 3be7b9d75a ("Remove traces of utmpx")
Fixes: 170b76cdd1 ("Disable utmpx permanently")
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-08 17:21:34 +01:00
Alejandro Colomar
f301a4ca19 Handle reallocf(3) errors
Reported-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-03 22:03:38 -06:00
Alejandro Colomar
0ec157d579 Fix memory leaks by replacing realloc(3) with reallocf(3)
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-03 22:03:38 -06:00
Alejandro Colomar
82480995b4 Remove unused function: gr_append_member()
Reported-by: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-03 22:03:38 -06:00
Serge Hallyn
1058872a0b Improve TTYGROUP description in login.defs manpage
Closes #457

The existing prose was confusing, or simply wrong.  Make it clear
that only the group ownership of the tty is affected, and how.
Also move the paragraph about defaults after the discussion of
acceptable TTYGROUPs, as this seems more natural.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-02-02 22:03:45 -06:00
Alejandro Colomar
1f6f1669cf Remove superfluous casts to 'void*'
Every non-const pointer converts automatically to it.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-02 22:03:26 -06:00
Alejandro Colomar
62172f6fb5 Call NULL by its name
In variadic functions we still do the cast.  In POSIX, it's not
necessary, since NULL is required to be of type 'void *', and 'void *'
is guaranteed to have the same alignment and representation as 'char *'.
However, since ISO C still doesn't mandate that, and moreover they're
doing dubious stuff by adding nullptr, let's be on the cautious side.
Also, C++ requires that NULL is _not_ 'void *', but either plain 0 or
some magic stuff.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-02 13:08:30 -06:00
Alejandro Colomar
1482224c54 Use freezero(3) where suitable
It originated in OpenBSD, and is available in libbsd.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-02 12:04:28 +01:00
Samanta Navarro
8e0ad48c21 Prevent out of boundary access
If lines start with '\0' then it is possible to trigger out of
boundary accesses.

Check if indices are valid before accessing them.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-02-01 15:47:35 -06:00
Samanta Navarro
ffc480c2e9 Explicitly override only newlines
Override only newlines with '\0' to avoid undesired truncation of
actual line content.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-02-01 15:47:35 -06:00
Samanta Navarro
37ae232080 Correctly handle illegal system file in tz
If the file referenced by ENV_TZ has a zero length string, then an out
of boundary write occurs. Also the result can be wrong because it is
assumed that the file will always end with a newline.

Only override a newline character with '\0' to avoid these cases.

This cannot be considered to be security relevant because login.defs
and its contained references to system files should be trusted to begin
with.

Proof of Concept:

1. Compile shadow's su with address sanitizer and --without-libpam

2. Setup your /etc/login.defs to contain ENV_TZ=/etc/tzname

3. Prepare /etc/tzname to contain a '\0' byte at the beginning

`python -c "print('\x00')" > /etc/tzname`

4. Use su

`su -l`

You can see the following output:

`tz.c:45:8: runtime error: index 18446744073709551615 out of bounds for type 'char [8192]'`

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-02-01 15:47:35 -06:00
Alejandro Colomar
03bbe6c418 leading_zerosul(): Fix bug
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-02-01 09:10:34 +01:00
Alejandro Colomar
2a61122b5e Unoptimize the higher part of the domain of csrand_uniform()
__int128, which is needed for optimizing that part of the range, is not
always available.  We need the unoptimized version for portability
reasons.

Closes: <https://github.com/shadow-maint/shadow/issues/634>
Fixes: 1a0e13f94e ("Optimize csrand_uniform()")
Reported-by: Adam Sampson <ats@offog.org>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-30 18:24:15 +01:00
Alejandro Colomar
0712b236c3 Add bit manipulation functions
We do need the unoptimized version of csrand_uniform() for high values
of `n`, since the optimized version depends on having __int128, and it's
not available on several platforms, including ARMv7, IA32, and MK68k.

This reverts commit 848f53c1d3c1362c86d3baab6906e1e4419d2634; however,
I applied some tweaks to the reverted commit.

Reported-by: Adam Sampson <ats@offog.org>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-30 18:24:15 +01:00
Alejandro Colomar
848f53c1d3 Revert "Add bit manipulation functions"
Now that we optimized csrand_uniform(), we don't need these functions.

This reverts commit 7c8fe291b1260e127c10562bfd7616961013730f.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-27 21:48:37 -06:00
Alejandro Colomar
1a0e13f94e Optimize csrand_uniform()
Use a different algorithm to minimize rejection.  This is essentially
the same algorithm implemented in the Linux kernel for
__get_random_u32_below(), but written in a more readable way, and
avoiding microopimizations that make it less readable.

Which (the Linux kernel implementation) is itself based on Daniel
Lemire's algorithm from "Fast Random Integer Generation in an Interval",
linked below.  However, I couldn't really understand that paper very
much, so I had to reconstruct the proofs from scratch, just from what I
could understand from the Linux kernel implementation source code.

I constructed some graphical explanation of how it works, and why it
is optimal, because I needed to visualize it to understand it.  It is
published in the GitHub pull request linked below.

Here goes a wordy explanation of why this algorithm based on
multiplication is better optimized than my original implementation based
on masking.

masking:

	It discards the extra bits of entropy that are not necessary for
	this operation.  This works as if dividing the entire space of
	possible csrand() values into smaller spaces of a size that is
	a smaller power of 2.  Each of those smaller spaces has a
	rejection band, so we get as many rejection bands as spaces
	there are.  For smaller values of 'n', the size of each
	rejection band is smaller, but having more rejection bands
	compensates for this, and results in the same inefficiency as
	for large values of 'n'.

multiplication:

	It divides the entire space of possible random numbers in
	chunks of size exactly 'n', so that there is only one rejection
	band that is the remainder of `2^64 % n`.  The worst case is
	still similar to the masking algorithm, a rejection band that is
	almost half the entire space (n = 2^63 + 1), but for lower
	values of 'n', by only having one small rejection band, it is
	much faster than the masking algorithm.

	This algorithm, however, has one caveat: the implementation
	is harder to read, since it relies on several bitwise tricky
	operations to perform operations like `2^64 % n`, `mult % 2^64`,
	and `mult / 2^64`.  And those operations are different depending
	on the number of bits of the maximum possible random number
	generated by the function.  This means that while this algorithm
	could also be applied to get uniform random numbers in the range
	[0, n-1] quickly from a function like rand(3), which only
	produces 31 bits of (non-CS) random numbers, it would need to be
	implemented differently.  However, that's not a concern for us,
	it's just a note so that nobody picks this code and expects it
	to just work with rand(3) (which BTW I tried for testing it, and
	got a bit confused until I realized this).

Finally, here's some light testing of this implementation, just to know
that I didn't goof it.  I pasted this function into a standalone
program, and run it many times to find if it has any bias (I tested also
to see how many iterations it performs, and it's also almost always 1,
but that test is big enough to not paste it here).

int main(int argc, char *argv[])
{
	printf("%lu\n", csrand_uniform(atoi(argv[1])));
}

$ seq 1 1000 | while read _; do ./a.out 3; done | grep 1 | wc -l
341
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 1 | wc -l
339
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 1 | wc -l
338
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 2 | wc -l
336
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 2 | wc -l
328
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 2 | wc -l
335
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 0 | wc -l
332
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 0 | wc -l
331
$ seq 1 1000 | while read _; do ./a.out 3; done | grep 0 | wc -l
327

This isn't a complete test for a cryptographically-secure random number
generator, of course, but I leave that for interested parties.

Link: <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e9a688bcb19348862afe30d7c85bc37c4c293471>
Link: <https://github.com/shadow-maint/shadow/pull/624#discussion_r1059574358>
Link: <https://arxiv.org/abs/1805.10941>
Cc: "Jason A. Donenfeld" <Jason@zx2c4.com>
Cc: Cristian Rodríguez <crrodriguez@opensuse.org>
Cc: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Cc: Björn Esser <besser82@fedoraproject.org>
Cc: Yann Droneaud <ydroneaud@opteya.com>
Cc: Joseph Myers <joseph@codesourcery.com>
Cc: Sam James <sam@gentoo.org>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
[Daniel Lemire: Added link to research paper in source code]
Cc: Daniel Lemire <daniel@lemire.me>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-27 21:48:37 -06:00
Alejandro Colomar
217b054cf5 Use WIDTHOF() instead of its expansion
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-27 21:48:37 -06:00
Alejandro Colomar
3f90eff494 Add WIDTHOF() to get the width in bits
It is common to use the expression 'sizeof(x) * CHAR_BIT' to mean the
width in bits of a type or object.  Now that there are _WIDTH macros for
some types, indicating the number of bits that they use, it makes sense
to wrap this calculation in a macro of a similar name.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-27 21:48:37 -06:00
Alejandro Colomar
1db190cb66 Rewrite csrand_interval() as a wrapper around csrand_uniform()
The old code didn't produce very good random numbers.  It had a bias.
And that was from performing some unnecessary floating-point
calculations that overcomplicate the problem.

Cc: "Jason A. Donenfeld" <Jason@zx2c4.com>
Cc: Cristian Rodríguez <crrodriguez@opensuse.org>
Cc: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Cc: Björn Esser <besser82@fedoraproject.org>
Cc: Yann Droneaud <ydroneaud@opteya.com>
Cc: Joseph Myers <joseph@codesourcery.com>
Cc: Sam James <sam@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-27 21:48:37 -06:00
Alejandro Colomar
31375d48ca Add csrand_uniform()
This API is similar to arc4random_uniform(3).  However, for an input of
0, this function is equivalent to csrand(), while arc4random_uniform(0)
returns 0.

This function will be used to reimplement csrand_interval() as a wrapper
around this one.

The current implementation of csrand_interval() doesn't produce very good
random numbers.  It has a bias.  And that comes from performing some
unnecessary floating-point calculations that overcomplicate the problem.

Looping until the random number hits within bounds is unbiased, and
truncating unwanted bits makes the overhead of the loop very small.

We could reduce loop overhead even more, by keeping unused bits of the
random number, if the width of the mask is not greater than
ULONG_WIDTH/2, however, that complicates the code considerably, and I
prefer to be a bit slower but have simple code.

BTW, Björn really deserves the copyright for csrand() (previously known
as read_random_bytes()), since he rewrote it almost from scratch last
year, and I kept most of its contents.  Since he didn't put himself in
the copyright back then, and BSD-3-Clause doesn't allow me to attribute
derived works, I won't add his name, but if he asks, he should be put in
the copyright too.

Cc: "Jason A. Donenfeld" <Jason@zx2c4.com>
Cc: Cristian Rodríguez <crrodriguez@opensuse.org>
Cc: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Cc: Björn Esser <besser82@fedoraproject.org>
Cc: Yann Droneaud <ydroneaud@opteya.com>
Cc: Joseph Myers <joseph@codesourcery.com>
Cc: Sam James <sam@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-27 21:48:37 -06:00
Alejandro Colomar
4a56f2baab Add bit manipulation functions
These functions implement bit manipulation APIs, which will be added to
C23, so that in the far future, we will be able to replace our functions
by the standard ones, just by adding the stdc_ prefix, and including
<stdbit.h>.

However, we need to avoid UB for an input of 0, so slightly deviate from
C23, and use a different name (with _wrap) for distunguishing our API
from the standard one.

Cc: Joseph Myers <joseph@codesourcery.com>
Cc: Yann Droneaud <ydroneaud@opteya.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-27 21:48:37 -06:00
Alejandro Colomar
be1f4f7972 Move csrand() to a new file csrand.c
A set of APIs similar to arc4random(3) is complex enough to deserve its
own file.

Cc: "Jason A. Donenfeld" <Jason@zx2c4.com>
Cc: Cristian Rodríguez <crrodriguez@opensuse.org>
Cc: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Cc: Björn Esser <besser82@fedoraproject.org>
Cc: Yann Droneaud <ydroneaud@opteya.com>
Cc: Joseph Myers <joseph@codesourcery.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-27 21:48:37 -06:00
Alejandro Colomar
986ef4e69c Use naming consistent with other common functions
arc4random(3) returns a number.
arc4random_buf(3) fills a buffer.
arc4random_uniform(3) returns a number less than a bound.

and I'd add a hypothetical one which we use:

*_interval() should return a number within the interval [min, max].

In reality, the function being called csrand() in this patch is not
really cryptographically secure, since it had a bias, but a subsequent
patch will fix that.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-27 21:48:37 -06:00
Alejandro Colomar
6d2337d9e8 Fix types of the csrand_interval() API
We were always casting the result to u_long.  Better just use that type
in the function.  Since we're returning u_long, it makes sense to also
specify the input as u_long.  In fact, that'll help for doing bitwise
operations inside this function.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-27 21:48:37 -06:00
Alejandro Colomar
8f441c9f7a Use a more precise name for a CSPRNG API with an interval
I have plans to split this function in smaller functions that implement
bits of this functionallity, to simplify the implementation.  So, let's
use names that distinguish them.

This one produces a number within an interval, so make that clear.  Also
make clear that the function produces cryptographically-secure numbers.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-27 21:48:37 -06:00
Stefan Schubert
a27d5c51f1 Supporting vendor given -shells- configuration file 2023-01-26 22:45:32 -06:00
Samanta Navarro
b2d202cb5d libmisc: fix grammar
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-01-26 22:44:39 -06:00
Samanta Navarro
b312bc0b4d Fix typos
Typos found with codespell.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
2023-01-26 22:44:39 -06:00
Christian Göttsche
194014678e Declare constant data structure const
./lib/pam_defs.h:18:24: warning: ‘conv’ defined but not used [-Wunused-variable]
       18 | static struct pam_conv conv = {
          |                        ^~~~
2023-01-25 12:31:17 +01:00
Christian Göttsche
89be7c0465 Provide strlcpy declaration
strlcpy(3) might not be visible since it is declared in <bsd/string.h>.
This can lead to warnings, like:

    fields.c: In function 'change_field':
    fields.c:103:17: warning: implicit declaration of function 'strlcpy'; did you mean 'strncpy'? [-Wimplicit-function-declaration]
      103 |                 strlcpy (buf, cp, maxsize);
          |                 ^~~~~~~
          |                 strncpy

    ../lib/fields.c:103:17: warning: type of 'strlcpy' does not match original declaration [-Wlto-type-mismatch]
      103 |                 strlcpy (buf, cp, maxsize);
          |                 ^
    /usr/include/bsd/string.h:44:8: note: return value type mismatch
       44 | size_t strlcpy(char *dst, const char *src, size_t siz);
          |        ^
    /usr/include/bsd/string.h:44:8: note: type 'size_t' should match type 'int'
    /usr/include/bsd/string.h:44:8: note: 'strlcpy' was previously declared here
    /usr/include/bsd/string.h:44:8: note: code may be misoptimized unless '-fno-strict-aliasing' is used
2023-01-25 12:31:17 +01:00
Christian Göttsche
c99d8d0a08 Avoid comparisons of different signs
Comparisons if different signedness can result in unexpected results.
Add casts to ensure operants are of the same type.

    gettime.c: In function 'gettime':
    gettime.c:58:26: warning: comparison of integer expressions of different signedness: 'long long unsigned int' and 'time_t' {aka 'long int'} [-Wsign-compare]
       58 |         } else if (epoch > fallback) {
          |                          ^

Cast to time_t, since epoch is less than ULONG_MAX at this point.

    idmapping.c: In function 'write_mapping':
    idmapping.c:202:48: warning: comparison of integer expressions of different signedness: 'int' and 'long unsigned int' [-Wsign-compare]
      202 |                 if ((written <= 0) || (written >= (bufsize - (pos - buf)))) {
          |                                                ^~

    newgidmap.c: In function ‘main’:
    newgidmap.c:178:40: warning: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’ [-Wsign-compare]
      178 |         if ((written <= 0) || (written >= sizeof(proc_dir_name))) {
          |                                        ^~
    newuidmap.c: In function ‘main’:
    newuidmap.c:107:40: warning: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’ [-Wsign-compare]
      107 |         if ((written <= 0) || (written >= sizeof(proc_dir_name))) {
          |                                        ^~
2023-01-25 12:31:17 +01:00
Christian Göttsche
43508ac476 Drop redundant declaration
environ is exported in <unistd.h>.

    env.c:29:15: warning: redundant redeclaration of 'environ' [-Wredundant-decls]
       29 | extern char **environ;
          |               ^~~~~~~
    login.c:92:15: warning: redundant redeclaration of ‘environ’ [-Wredundant-decls]
       92 | extern char **environ;
          |               ^~~~~~~
    sulogin.c:40:15: warning: redundant redeclaration of ‘environ’ [-Wredundant-decls]
       40 | extern char **environ;
          |               ^~~~~~~
    newgrp.c:32:15: warning: redundant redeclaration of ‘environ’ [-Wredundant-decls]
       32 | extern char **environ;
          |               ^~~~~~~
2023-01-25 12:31:17 +01:00
Christian Göttsche
46d3058341 copydir: fix impl usage
copydir.c: In function 'copy_dir':
    copydir.c:517:32: warning: passing argument 1 of 'copy_tree' from incompatible pointer type [-Wincompatible-pointer-types]
      517 |             return (copy_tree (src, dst, false, reset_selinux,
          |                                ^~~
          |                                |
          |                                const struct path_info *
    In file included from copydir.c:20:
    ../lib/prototypes.h:108:35: note: expected 'const char *' but argument is of type 'const struct path_info *'
      108 | extern int copy_tree (const char *src_root, const char *dst_root,
          |                       ~~~~~~~~~~~~^~~~~~~~
    copydir.c:517:37: warning: passing argument 2 of 'copy_tree' from incompatible pointer type [-Wincompatible-pointer-types]
      517 |             return (copy_tree (src, dst, false, reset_selinux,
          |                                     ^~~
          |                                     |
          |                                     const struct path_info *
    ../lib/prototypes.h:108:57: note: expected 'const char *' but argument is of type 'const struct path_info *'
      108 | extern int copy_tree (const char *src_root, const char *dst_root,
          |                                             ~~~~~~~~~~~~^~~~~~~~

Fixes: 74c17c71 ("Add support for skeleton files from /usr/etc/skel")
2023-01-25 12:31:17 +01:00
Christian Göttsche
e0d79ee032 Modernize manual memzero implementation
Instead of using volatile pointers to prevent the compiler from
optimizing the call away, use a memory barrier.
This requires support for embedded assembly, which should be fine after
the recent requirement bumps.
2023-01-25 11:07:25 +01:00
Christian Göttsche
90ead3cfb8 Replace flawed memset_s usage
memset_s() has a different signature than memset(3) or explicit_bzero(),
thus the current code would not compile.  Also memset_s()
implementations are quite rare.
Use the C23 standardized version memset_explicit(3).

Fixes: 7a799ebb ("Ensure memory cleaning")
2023-01-25 11:07:25 +01:00
Alejandro Colomar
b2bed465e8 Use getnameinfo(3) instead of our own equivalent
I didn't know getnameinfo(3) existed, so I implemented it, or something
similar to it called inet_sockaddr2str().  Let's use the standard API.

Link: <https://inbox.sourceware.org/libc-alpha/0f25d60f-f183-b518-b6c1-6d46aa63ee57@gmail.com/T/>
Link: <https://stackoverflow.com/a/42190913/6872717>
Link: <https://github.com/shadow-maint/shadow/pull/617>
Link: <https://software.codidact.com/posts/287748>
Cc: Zack Weinberg <zack@owlfolio.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-20 10:23:03 -06:00
Alejandro Colomar
ac8b81c2b7 Prefer getrandom(3)/getentropy(3) over arc4random(3bsd)
arc4random(3) without kernel support is unsafe, as it can't know when to
drop the buffer.  Since we depend on libbsd since recently, we have
arc4random(3) functions always available, and thus, this code would have
always called arc4random_buf(3bsd), which is unsafe.  Put it after some
better alternatives, at least until in a decade or so all systems have a
recent enough glibc.

glibc implements arc4random(3) safely, since it's just a wrapper around
getrandom(2).

Link: <https://inbox.sourceware.org/libc-alpha/20220722122137.3270666-1-adhemerval.zanella@linaro.org/>
Link: <https://inbox.sourceware.org/libc-alpha/5c29df04-6283-9eee-6648-215b52cfa26b@cs.ucla.edu/T/>
Cc: Cristian Rodríguez <crrodriguez@opensuse.org>
Cc: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Cc: Guillem Jover <guillem@hadrons.org>
Cc: Björn Esser <besser82@fedoraproject.org>
Reviewed-by: "Jason A. Donenfeld" <Jason@zx2c4.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-16 10:12:31 +01:00
Serge Hallyn
39ecca84d4 workflow: update checkout acton v2 to v3
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2023-01-13 09:51:05 +01:00
SoumyaWind
670cae8348 shadow: Fix can not print full login timeout message
Login timed out message prints only first few bytes when write is immediately followed by exit.
Calling exit from new handler provides enough time to display full message.
2023-01-12 18:30:32 -06:00
lilinjie
abeb5f3794 fix typo
Signed-off-by: lilinjie <lilinjie@uniontech.com>
2023-01-12 12:10:57 +01:00
Christian Göttsche
1d936c968a Warn if failed to read existing /etc/nsswitch.conf
Commit 90424e7c ("Don't warn when failed to open /etc/nsswitch.conf")
removed the logging for failing to read /etc/nsswitch.conf to reduce the
noise in the case the file does not exists (e.g. musl based systems).

Reintroduce a warning if /etc/nsswitch.conf exists but we failed to read
it (e.g. permission denied).

Improves: 90424e7c ("Don't warn when failed to open /etc/nsswitch.conf")
2023-01-04 14:21:43 -06:00
Alejandro Colomar
609c641323 Call inet_sockaddr2str() instead of inet_ntop(3)
To simplify.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-02 08:20:43 +01:00
Alejandro Colomar
bb3a89577c Add inet_sockaddr2str() to wrap inet_ntop(3)
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-02 08:20:43 +01:00
Alejandro Colomar
eec5f9fccc Replace gethostbyname(3) by getaddrinfo(3)
gethostbyname(3) was removed in POSIX.1-2008.  It has been obsoleted,
and replaced by getaddrinfo(3), which is superior in several ways:

-  gethostbyname(3) is not reentrant.  There's a GNU extension,
   gethostbyname_r(3) which is reentrant, but it's not likely to be
   standardized for the following reason.  And we don't care too much
   about this point either.

-  gethostbyname(3) only supports IPv4, but getaddrinfo(3) supports both
   IPv4 and IPv6 (and may support other address families in the future).

We don't care about reentrancy, so for keeping the code simple (i.e.,
not touch call site to add code to free(3) an allocated buffer), I added
a static buffer for inet_ntop(3).  We could address that in the future,
but I don't think it's worth it.

BTW, we also replace inet_ntoa(3) by inet_ntop(3), as a consequence of
using getaddrinfo(3).  inet_ntoa(3) is also marked as deprecated, but
that deprecation seems to have been documented only in the manual page,
and POSIX doesn't mark it as deprecated.  The deprecation notice goes
back to when the inet_ntop(3) manual page was added by Sam Varshavchik
to the Linux man-pages in version 1.30 (year 2000).

So, this, apart from updating the code to POSIX.1-2008, is also adding
support for IPv6 :)  Although, probably many other parts of the code are
written for IPv4 only, so I wouldn't yet claim support for it.

A few notes:

-  I didn't check the return value of inet_ntop(3), since it can't fail
   for the given input:

   -  EAFNOSUPPORT:  We only call it with AF_INET and AF_INET6.
   -  ENOSPC:  We calculate the size of the buffer to be wide enough:
               MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) so it always fits.

Cc: Dave Hagewood <admin@arrowweb.com>
Cc: Sam Varshavchik
Cc: Jakub Jelinek <jakub@redhat.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-01-02 08:20:43 +01:00
ed neville
65470e5c7d changing lock mechanism
Systems can suffer power interruptions whilst .lock files are in /etc,
preventing scripts and other automation tools from updating shadow's
files which persist across boots.

This commit replaces that mechanism with file locking to avoid problems
of power interruption/crashing.

Minor tweak to groupmems man page, requested by 'xx' on IRC.

Signed-off-by: ed neville <ed@s5h.net>
2022-12-29 13:58:49 -06:00
Serge Hallyn
bc18c184e5 chfn: new_fields: fix wrong fields printed
When the caller may not change the room number, work phone, or
home number, then rather than prompting for the new one it will
print the existing one.  But due to a typo it printed the full name
in place of each of those.

Fix the fields being printed.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2022-12-23 09:04:02 +01:00
Alejandro Colomar
eb164165f6 Add NITEMS(arr) to get the number of elements of an array
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-22 18:20:02 -06:00
Alejandro Colomar
220b352b70 Use strlcpy(3) instead of its pattern
-  Since strncpy(3) is not designed to write strings, but rather
   (null-padded) character sequences (a.k.a. unterminated strings), we
   had to manually append a '\0'.  strlcpy(3) creates strings, so they
   are always terminated.  This removes dependencies between lines, and
   also removes chances of accidents.

-  Repurposing strncpy(3) to create strings requires calculating the
   location of the terminating null byte, which involves a '-1'
   calculation.  This is a source of off-by-one bugs.  The new code has
   no '-1' calculations, so there's almost-zero chance of these bugs.

-  strlcpy(3) doesn't padd with null bytes.  Padding is relevant when
   writing fixed-width buffers to binary files, when interfacing certain
   APIs (I believe utmpx requires null padding at lease in some
   systems), or when sending them to other processes or through the
   network.  This is not the case, so padding is effectively ignored.

-  strlcpy(3) requires that the input string is really a string;
   otherwise it crashes (SIGSEGV).  Let's check if the input strings are
   really strings:

   -  lib/fields.c:
      -  'cp' was assigned from 'newft', and 'newft' comes from fgets(3).

   -  lib/gshadow.c:
      -  strlen(string) is calculated a few lines above.

   -  libmisc/console.c:
      -  'cons' comes from getdef_str, which is a bit cryptic, but seems
         to generate strings, I guess.1

   -  libmisc/date_to_str.c:
      -  It receives a string literal.  :)

   -  libmisc/utmp.c:
      -  'tname' comes from ttyname(3), which returns a string.

   -  src/su.c:
      -  'tmp_name' has been passed to strcmp(3) a few lines above.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-22 18:03:39 -06:00
Iker Pedrosa
a48d77bdef strtoday.c: remove unused defines.h inclusion
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2022-12-22 10:39:45 -06:00
Iker Pedrosa
bb0c89d944 strtoday.c: remove USE_GETDATE as it was always used
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2022-12-22 10:39:45 -06:00
Iker Pedrosa
e4441489bc strtoday.c: remove POSIX 1995 conditional dependency
Since the project is supposed to be POSIX.1-2001 compliant it doesn't
make sense to have that added conditionally.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2022-12-22 10:39:45 -06:00
Alejandro Colomar
647d46507d Assume struct tm is defined in <time.h>
It has been a requirement since at least C90, according to tm(3type).

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-22 09:49:02 -06:00
Alejandro Colomar
d96bb2868d Assume struct stat has st_atim and st_mtim fields
That's required by POSIX.1-2008.

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-22 09:49:02 -06:00
Alejandro Colomar
5d7a3b80e9 Remove USE_SYSLOG preprocessor conditional, which was always defined
Reported-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-22 11:44:36 +01:00
Alejandro Colomar
350b1e8683 Remove dead code
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-22 11:44:36 +01:00
Alejandro Colomar
e2df287aad Don't redefine errno(3)
It is Undefined Behavior to declare errno (see NOTES in its manual page).
Instead of using the errno dummy declaration, use one that doesn't need
a comment.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-22 11:43:29 +01:00
Alejandro Colomar
ed69feaaff Fix typos in length calculations
Link: <https://github.com/shadow-maint/shadow/pull/607>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-22 10:34:04 +01:00
Alejandro Colomar
06c30450ce Use 'uintmax_t' to print 'gid_t'
This is shorter to write than 'unsigned long int', so we can collapse
some lines.  It is guaranteed by C99.

Link: <https://github.com/shadow-maint/shadow/pull/607>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-22 10:34:04 +01:00
Alejandro Colomar
587ce83e3f Fix off-by-one mistakes
The buffers have a size of 512 (see xmalloc() above), which is what
snprintf(3) expects.

Link: <https://github.com/shadow-maint/shadow/pull/607>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-22 10:34:04 +01:00
Alejandro Colomar
b990b167d4 Cosmetic fixes
Previous commits, to keep readability of the diffs, left the code that
was previously wrapped by preprocessor coditionals untouched.  Apply
some minor cosmetic changes to merge it in the surrounding code.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-22 10:31:43 +01:00
Alejandro Colomar
3be7b9d75a Remove traces of utmpx
-  USER_NAME_MAX_LENGTH was being calculated in terms of utmpx.  Do it
   in terms of utmp.
-  Remove utmpx support from the whishlist.
-  Remove unused tests about utmpx members.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-22 10:31:43 +01:00
Alejandro Colomar
170b76cdd1 Disable utmpx permanently
On Linux, utmpx and utmp are identical.  However, documentation (manual
pages) covers utmp, and just says about utmpx that it's identical to
utmp.  It seems that it's preferred to use utmp, at least by reading the
manual pages.

Moreover, we were defaulting to utmp (utmpx had to be explicitly enabled
at configuration time).  So, it seems safer to just make it permanent,
which should not affect default builds.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-22 10:31:43 +01:00
Alejandro Colomar
2da7607ea6 Assume <utmpx.h> always exists
We already made that assumption in commit b47aa1e9aa.  While the
header is not required by POSIX (it is an XSI extension), it is defined
in systems that are of interest to this project (GNU/Linux).

Fixes: b47aa1e9aa ("Assume <utmpx.h> exists")
Cc: Serge Hallyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-22 10:31:43 +01:00
Alejandro Colomar
5fae37271e Remove pwdauth.c
We don't know what it was for.  If anyone cares, it's in git history.
In my distro, there seem to be no traces of it:

alx@debian:~$ apt-file find pwdauth
alx@debian:~$

Link: <https://codesearch.debian.net/search?q=pwdauth&literal=1>
Link: <https://github.com/shadow-maint/shadow/pull/612>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-21 08:22:22 -06:00
Michael Vetter
74c17c7167 Add support for skeleton files from /usr/etc/skel
This patch is used by openSUSE to make useradd look for
skeleton files in /usr/etc/skel additionally to /etc/skel
in accordance with
https://uapi-group.org/specifications/specs/base_directory_specification/
2022-12-19 09:43:03 -06:00
Michael Vetter
37412f505e Fix useradd audit event logging of ID field
When useradd sends its ADD_USER event, it is filling in the id field. This is not yet written to disk. When auditd sees the event and the log format is enriched, auditd tries to lookup the user name but it does not exist. This causes the event to never be resolvable since ausearch relies on the lookup information attached by auditd.

The fix is to not send the id information for any event until after close_files() is called. Just the acct field is all that is

Patch by Steve Grubb (afaik).

Reported at https://bugzilla.redhat.com/show_bug.cgi?id=1713432
2022-12-15 16:29:42 -06:00
Alejandro Colomar
6b6e005ce1 Remove comments that survived the Helicoprion
The OSes that are referred to by these comments, are extinct, but
their comments survived, fossilized in amber.

Reported-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
428a2078b6 Ping? :)
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
54847a76da Remove preprocessor conditionals that are always true
In a previous commit, we made USE_TERMIOS unconditionally defined.
Let's just remove it, and remove the condition everywhere.

Reported-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
f2ae6a42a4 Remove code conditional on USE_TERMIO
The definition for this macro was removed in a previous commit.

Reported-by: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
5669b34891 Assume socket(2) exists
It is required by POSIX.1-2001.

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
3d32dd05bb Assume inet_ntoa(3) exists
It is required by POSIX.1-2001.

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
0e0c55aeca Assume F_* and SEEK_* macros are defined
They are required by POSIX.1-2001.

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
9dfa71f71c Remove code conditional on S_SPLINT_S
I don't know for sure what that is, but it's redefining setlocale(3)
and LC_ALL, which is are defined by C99, so it's supect of being some
variety of an extinct dynosaur.  Maybe related to the Dodo.

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
143e346dd5 Assume strdup(3) exists
It is required by POSIX.1-2001.

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
56e989ccf7 Assume strcasecmp(3) exists
It is required by POSIX.1-2001.

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
06f4acee99 Assume rmdir(2) exists
It is required by POSIX.1-2001.

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
dfc93b35cc Assume mkdir(2) exists
It is required by POSIX.1-2001.

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
61299d69ad Assume B[0-9]* macros are defined
All of the macros we're using are required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
f51c6838ac Assume SIGTTOU is defined
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
307502d8b5 Assume SIGTSTP is defined
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
74c8015730 Assume RLIMIT_STACK is defined
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
c916715a6c Assume RLIMIT_NOFILE is defined
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
5ebf28c999 Assume RLIMIT_FSIZE is defined
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
91adf3b8bb Assume RLIMIT_DATA is defined
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
891d8dbedd Assume RLIMIT_CPU is defined
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
7a4906fc75 Assume RLIMIT_AS is defined
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
e1a39e1dfc Assume RLIMIT_CORE is defined
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
cbc363f671 Assume getgrgid_r(3) exists
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
88eb38f4ab Assume getgrnam_r(3) exists
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
e5e5df1966 Assume getpwuid_r(3) exists
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
e788001977 Assume getpwnam_r(3) exists
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
a082a3975f Assume fsync(2) exists
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
e71c23586a Assume fchown(2) exists
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
9c86e07067 Assume fchmod(2) exists
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
55c62b663f Assume l64a(3) exists
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
48391fb862 Assume <netdb.h> exists
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
b76d9b540a Remove preprocessor conditionals that are always true
Since the last commit, LIMITS is always defined.  Remove the dummy
macro, and all conditionals on it.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
9d695340b4 Assume <sys/resource.h> exists
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
cdaa04e460 Remove uses of ulimit(3)
The function is obsolete.  It is recommended to use getrlimit(2) instead
(see the manual page for ulimit(3) or the POSIX manual for it).  Since
getrlimit(2) is required by POSIX.1-2001, we can rely on it.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
0527fa677b Add indentation to heavy use of preprocessor conditionals
This clarifies which code is under which conditions,
for further clenaup.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
7b1fc83e9b Remove unused check for <utime.h>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
eecd021c04 Remove unused check for <syslog.h>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
5777e583cd Assume <termios.h> exists
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
b47aa1e9aa Assume <utmpx.h> exists
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
85d2688d62 Remove unused check for <sys/time.h>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
578f286215 Assume <unistd.h> exists
It is required by POSIX.1-2001.

Cc: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
28e565aa83 Remove unused check for <fcntl.h>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-15 16:22:05 -06:00
Alejandro Colomar
d7baafb2eb Assume strstr(3) exists
ISO C99 requires strstr(3).

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-12 09:16:43 +01:00
Alejandro Colomar
0793782d31 Assume snprintf(3) exists
ISO C99 requires snprintf(3).

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-12 09:16:43 +01:00
Alejandro Colomar
7d3213741e Assume rename(2) exists
ISO C99 requires rename(2).

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-12 09:16:43 +01:00
Alejandro Colomar
9d8c3df93c Assume NULL exists
ISO C99 requires NULL.

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-12 09:16:43 +01:00
Alejandro Colomar
3a32f5278d Assume strerror(3) exists
ISO C99 requires strerror(3).

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-12 09:16:43 +01:00
Alejandro Colomar
5e8df2b2b5 Assume fputs(3) exists
ISO C99 requires fputs(3).

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-12 09:16:43 +01:00
Alejandro Colomar
c26b682381 Assume <locale.h> exists
ISO C99 requires <locale.h>.

Other files in the project already include <locale.h> unconditionally,
so it's reasonable to assume that it is always available.

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-12 09:16:43 +01:00
Alejandro Colomar
d34c834ea8 Remove unused check for <limits.h>
Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-12 09:16:43 +01:00
Alejandro Colomar
1eaa30756e Assume <errno.h> exists
ISO C99 requires <errno.h>.

Many files in the project already include <errno.h> unconditionally,
so it's reasonable to assume that it is always available.

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-12 09:16:43 +01:00
Alejandro Colomar
c4d9dcacc9 Assume <stdbool.h> exists
ISO C99 requires <stdbool.h>.

Many files in the project already include <stdbool.h> unconditionally,
so it's reasonable to assume that it is always available.

Link: <https://github.com/shadow-maint/shadow/pull/600>
Cc: Christian Göttsche <cgzones@googlemail.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-12 09:16:43 +01:00
James Addison
ed6c505312 Add '62_usermod_remove_supplementary_groups' test case to test runner scripts (run_some) 2022-12-11 10:58:37 -06:00
James Addison
f2bcb7a1b8 Add '62_usermod_remove_supplementary_groups' test case to test runner scripts (run_all, run_all.coverage) 2022-12-11 10:58:37 -06:00
James Addison
20f8ead9ec Add regression test for 'usermod -rG' -- it should not add users to groups they did not previously belong to 2022-12-11 10:58:37 -06:00
James Addison
899f7a43b1 Preparation / clarity: rename existing usermod test from 'remove_supplemental_groups' to 'clear_supplemental_groups' 2022-12-11 10:58:37 -06:00
Guillem Jover
2a5b8810bb agetpass: Hook into build-system
Signed-off-by: Guillem Jover <guillem@hadrons.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-05 10:47:19 +01:00
Alejandro Colomar
ab91ec10b4 Hide [[gnu::malloc(deallocator)]] in a macro
Clang doesn't implement this attribute and reports an error.  Work
around it by hiding it in a macro that will be empty in clang.

Reported-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-05 10:47:19 +01:00
Alejandro Colomar
554f86bafa Replace the deprecated getpass(3) by our agetpass()
getpass(3) is broken in all implementations; in some, more than
others, but somewhat broken in all of them.  Check the immediate
previous commit, which added the functions, for more details.
Check also the Linux man-pages commit that marked it as
deprecated, for more details:
7ca189099d73bde954eed2d7fc21732bcc8ddc6b.

Link: <https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit?id=7ca189099d73bde954eed2d7fc21732bcc8ddc6b>
Reported-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-05 10:47:19 +01:00
Alex Colomar
155c9421b9 libmisc: agetpass(), erase_pass(): Add functions for getting passwords safely
There are several issues with getpass(3).

Many implementations of it share the same issues that the infamous
gets(3).  In glibc it's not so terrible, since it's a wrapper
around getline(3).  But it still has an important bug:

If the password is long enough, getline(3) will realloc(3) memory,
and prefixes of the password will be laying around in some
deallocated memory.

See the getpass(3) manual page for more details, and especially
the commit that marked it as deprecated, which links to a long
discussion in the linux-man@ mailing list.

So, readpassphrase(3bsd) is preferrable, which is provided by
libbsd on GNU systems.  However, using readpassphrase(3) directly
is a bit verbose, so we can write our own wrapper with a simpler
interface similar to that of getpass(3).

One of the benefits of writing our own interface around
readpassphrase(3) is that we can hide there any checks that should
be done always and which would be error-prone to repeat every
time.  For example, check that there was no truncation in the
password.

Also, use malloc(3) to get the buffer, instead of using a global
buffer.  We're not using a multithreaded program (and it wouldn't
make sense to do so), but it's nice to know that the visibility of
our passwords is as limited as possible.

erase_pass() is a clean-up function that handles all clean-up
correctly, including zeroing the entire buffer, and then
free(3)ing the memory.  By using [[gnu::malloc(erase_pass)]], we
make sure that we don't leak the buffers in any case, since the
compiler will be able to enforce clean up.

Link: <https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit?id=7ca189099d73bde954eed2d7fc21732bcc8ddc6b>
Reported-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-05 10:47:19 +01:00
Alex Colomar
8cce4557e0 Don't 'else' after a 'noreturn' call
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-12-05 10:47:19 +01:00
Iker Pedrosa
99ce21a313 CI: add libbsd and pkg-config dependencies
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Co-developed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-11-28 09:07:41 -06:00
Florian Weimer
a281f241b5 Fix HAVE_SHADOWGRP configure check
The missing #include <gshadow.h> causes the configure check to fail
spuriously, resulting in HAVE_SHADOWGRP not being defined even
on systems that actually have sgetsgent (such as current glibc).
2022-11-21 08:06:14 -06:00
Andy Zaugg
e8d2bc8d8b Allow supplementary groups to be added via config file
Allow supplementary groups to be set via the /etc/default/useradd config
file. Allowing an administrator to set additonal groups via the GROUPS
configurable and control the default behaviour of useradd.
2022-11-18 15:10:56 -06:00
Iker Pedrosa
e0524e813a useradd: check if subid range exists for user
Check if a user already has a subid range before assigning one.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2012929

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2022-11-18 09:04:42 -06:00
Serge Hallyn
24b44b686e Release 4.13
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2022-11-08 10:29:30 -06:00
Serge Hallyn
690bd8a878 update changelog 2022-11-08 10:28:10 -06:00
Serge Hallyn
90424e7c20 Don't warn when failed to open /etc/nsswitch.conf
Maybe we should have a debug mode where it's still printed, but
we don't, so let's be quieter.

Closes #557
2022-11-08 10:18:17 -06:00
David Michael
eaebea55a4 useradd: Fix buffer overflow when using a prefix
The buffer length did not count the string's trailing null byte.

Signed-off-by: David Michael <fedora.dm0@gmail.com>
2022-10-24 16:15:13 -05:00
Alejandro Colomar
0336454503 adduser-old.c: Remove program
This program has 10 calls to gets(3) according to grep(1).  That
makes it a very unsafe program which should not be used at all.
Let's kill the program already.

See what gets(3) has to say:

SYNOPSIS
       #include <stdio.h>

       [[deprecated]] char *gets(char *s);

DESCRIPTION
       Never use this function.

       ...

BUGS
       Never use gets().  Because it is impossible to tell with‐
       out knowing the  data  in  advance  how  many  characters
       gets()  will  read,  and  because gets() will continue to
       store characters past the end of the buffer,  it  is  ex‐
       tremely dangerous to use.  It has been used to break com‐
       puter security.  Use fgets() instead.

       For more information, see CWE‐242 (aka "Use of Inherently
       Dangerous Function") at http://cwe.mitre.org/data/defini‐
       tions/242.html

Acked-by: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-10-17 09:06:08 -05:00
Iker Pedrosa
16afe18142 Raise limit for passwd and shadow entry length
Moreover, include checks to prevent writing entries longer than the
length limit.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1422497

Signed-off-by: Tomáš Mráz <tm@t8m.info>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2022-10-14 10:41:40 +02:00
Iker Pedrosa
fbf275da19 lastlog: check for localtime() return value
Signed-off-by: Tomáš Mráz <tm@t8m.info>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2022-10-07 09:53:02 -05:00
Iker Pedrosa
1e5f9a72b0 man: add missing space in useradd.8.xml
Resolves: https://github.com/shadow-maint/shadow/issues/580

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2022-10-07 12:35:35 +02:00
xyz
e5db28a4bf fix usermod -rG x y while user y is not in group x will cause user y add into group x 2022-10-06 20:29:44 -05:00
Iker Pedrosa
d324c6776b libmisc: minimum id check for system accounts
The minimum id allocation for system accounts shouldn't be 0 as this is
reserved for root.

Signed-off-by: Tomáš Mráz <tm@t8m.info>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2022-10-06 20:09:35 -05:00
Iker Pedrosa
ead03afeba usermod: report error if homedir does not exist
Report error if usermod asked for moving homedir and it does not exist.

Signed-off-by: Tomáš Mráz <tm@t8m.info>
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
2022-10-06 20:08:51 -05:00
Xiami
e503fd574b chage: Fix regression in print_date
Introduced by c6c8130db4

After removing snprintf, the format string should get unescaped once.

Fixes #564

Reporter and patch author: DerMouse (github.com/DerMouse)
2022-10-05 12:43:45 +02:00
Alejandro Colomar
3dc1754e50 Use libc MAX() and MIN()
glibc, musl, FreeBSD, and OpenBSD define the MAX() and MIN()
macros in <sys/param.h> with the same definition that we use.
Let's not redefine it here and use the system one, as it's
effectively the same as we define (modulo whitespace).

See:

shadow (previously):

alx@asus5775:~/src/shadow/shadow$ grepc -ktm MAX
./lib/defines.h:318:#define MAX(x,y) (((x) > (y)) ? (x) : (y))

glibc:

alx@asus5775:~/src/gnu/glibc$ grepc -ktm -x 'sys/param.h$' MAX
./misc/sys/param.h:103:#define MAX(a,b) (((a)>(b))?(a):(b))

musl:

alx@asus5775:~/src/musl/musl$ grepc -ktm -x 'sys/param.h$' MAX
./include/sys/param.h:19:#define MAX(a,b) (((a)>(b))?(a):(b))

OpenBSD:

alx@asus5775:~/src/bsd/openbsd/src$ grepc -ktm -x 'sys/param.h$' MAX
./sys/sys/param.h:193:#define	MAX(a,b) (((a)>(b))?(a):(b))

FreeBSD:

alx@asus5775:~/src/bsd/freebsd/freebsd-src$ grepc -ktm -x 'sys/param.h$' MAX
./sys/sys/param.h:333:#define	MAX(a,b) (((a)>(b))?(a):(b))

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-09-30 16:13:36 -05:00
Alex Colomar
0d9799de04 Don't test for NULL before calling free(3)
free(3) accepts NULL, since the oldest ISO C.  I guess the
paranoid code was taking care of prehistoric implementations of
free(3).  I've never known of an implementation that doesn't
conform to this, so let's simplify this.

Remove xfree(3), which was effectively an equivalent of free(3).

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-09-29 16:03:53 +02:00
Frans Spiesschaert
1b0e189e35 updated Dutch translation 2022-09-27 16:01:31 -05:00
Christian Göttsche
8e53db927a lib: use memzero where applicable
Use memzero when operating in a buffer of known size to clear all bytes
and avoid leaking the size of the stored data.
2022-09-27 16:52:06 +02:00
Christian Göttsche
e74bfe2c75 lib: use strzero where applicable
Replace `memzero (s, strlen(s))` with just the internal wrapper
`strzero (s)` where the underlying allocated size is not known.
2022-09-27 16:52:06 +02:00
Luca BRUNO
14e7caf6b2 lib/commonio: make lock failures more detailed
This tweaks the database locking logic so that failures in the
link-checking paths are more detailed.
The rationale for this is that I've experienced a non-deterministic
bug which seems to be coming from this logic, and I'd like to get
more details about the actual failing condition.
2022-09-15 10:31:13 -05:00
Samanta Navarro
cde221b858 copy_tree: carefully treat permissions
The setuid, setgid, and sticky bits are not copied during copy_tree.

Also start with very restrictive permissions before setting ownerships.

This prevents situations in which users in a group with less permissions
than others could win a race in opening the file before permissions are
removed again.

Proof of concept:

$ echo $HOME
/home/uwu
$ install -o uwu -g fandom -m 604 /dev/null /home/uwu/owo
$ ls -l /home/uwu/owo
-rw----r-- 1 uwu fandom 0 Sep  4 00:00 /home/uwu/owo

If /tmp is on another filesystem, then "usermod -md /tmp/uwu uwu" leads
to this temporary situation:

$ ls -l /tmp/uwu/owo
-rw----r-- 1 root root  0 Sep  4 00:00 /tmp/uwu/owo

This means that between openat and chownat_if_needed a user of group
fandom could open /tmp/uwu/owo and read the content when it is finally
written into the file.
2022-09-14 10:11:32 +02:00
Jan Macku
f33e7def06 ci(lint): add shell linter - Differential ShellCheck
It performs differential ShellCheck scans and report results directly in pull request.

documentation: https://github.com/redhat-plumbers-in-action/differential-shellcheck

Signed-off-by: Jan Macku <jamacku@redhat.com>
2022-09-12 19:29:24 -05:00
Samanta Navarro
10cd68e0f0 copy_tree: do not block on fifos
Fixes regression introduced in faeab50e71.

If a directory contains fifos, then openat blocks until the other side
of the fifo is connected as well.

This means that users can prevent "usermod -m" from completing if their
home directories contain at least one fifo.
2022-09-09 15:19:12 +02:00
Samanta Navarro
f3bdb28e57 copy_tree: use fchmodat instead of chmod
Fixes regression introduced in faeab50e71
for setups configured without acl support.
2022-09-09 15:19:12 +02:00
genBTC
23634d8de7 useradd: check MLS enablement before setting serange Resolves: https://github.com/shadow-maint/shadow/issues/552 2022-09-02 20:29:34 -05:00
Alexander Kanavin
cfc981df2a shadow: use relaxed usernames
The groupadd from shadow does not allow upper case group names, the
same is true for the upstream shadow. But distributions like
Debian/Ubuntu/CentOS has their own way to cope with this problem,
this patch is picked up from Fedora [1] to relax the usernames
restrictions to allow the upper case group names, and the relaxation is
POSIX compliant because POSIX indicate that usernames are composed of
characters from the portable filename character set [A-Za-z0-9._-].

[1] https://src.fedoraproject.org/rpms/shadow-utils/blob/rawhide/f/shadow-4.8-goodname.patch

Signed-off-by: Alexander Kanavin <alex@linutronix.de>
2022-09-02 20:27:14 -05:00
NorwayFun
9e1c0ffef4 po: Georgian translation
po: Georgian translation
2022-09-02 20:21:42 -05:00
NorwayFun
78378400b9 po: Georgian translation
po: Georgian translation
2022-09-02 20:21:42 -05:00
David Kalnischkies
ebf9b232b0 useradd: Do not reset non-existent data in {last,fail}log
useradd does not create the files if they don't exist, but if they exist
it will reset user data even if the data did not exist before creating
a hole and an explicitly zero'd data point resulting (especially for
high UIDs) in a lot of zeros ending up in containers and tarballs.
2022-08-31 16:13:46 +02:00
Serge Hallyn
7136e24f8a Revert "Drop unused function subid_init()"
As rbalint points out, this was an exported fn.  It also is
the only way for a libsubid user to do what it does, so let's
not drop it.

This reverts commit 477c8e6f42.
2022-08-21 13:20:56 -05:00
Tim Biermann
eb3562f3c0 useradd.8.xml: fix default group id from 100 to 1000 according to bbf4b79 2022-08-21 13:17:38 -05:00
937 changed files with 160925 additions and 105115 deletions

View File

@@ -1,32 +0,0 @@
image: alpine/latest
# apk add --update alpine-sdk
packages:
- cmd:setcap
- autoconf
- automake
- byacc
- expect
- gettext
- gettext-dev
- gettext-lang
- libcap-dev
- libtool
- linux-pam-dev
- sed
sources:
- https://github.com/shadow-maint/shadow
tasks:
- build: |
cd shadow
./autogen.sh --without-selinux --disable-man --disable-nls
grep ENABLE_ config.status
- tasks: |
cd shadow
cat /proc/self/uid_map
cat /proc/self/status
make
make DESTDIR=/tmp/shadow-inst install
sudo make install
#TODO - fix up the tests. Let's merge what's here now as it
#at least tests build.
#(cd tests; sudo ./run_some || { cat testsuite.log; false; })

View File

@@ -1,31 +0,0 @@
image: fedora/latest
packages:
- autoconf
- automake
- byacc
- expect
- findutils
- gettext
- gettext-devel
- git
- libselinux-devel
- libsemanage-devel
- libtool
- libxslt
sources:
- https://github.com/shadow-maint/shadow
tasks:
- build: |
cd shadow
./autogen.sh --with-selinux --enable-man
grep ENABLE_ config.status
- tasks: |
cd shadow
cat /proc/self/uid_map
cat /proc/self/status
make
make DESTDIR=/tmp/shadow-inst install
sudo make install
#TODO - fix up the tests. Let's merge what's here now as it
#at least tests build.
#(cd tests; sudo ./run_some || { cat testsuite.log; false; })

View File

@@ -1,26 +0,0 @@
image: ubuntu/focal
packages:
- automake
- autopoint
- xsltproc
- libselinux1-dev
- gettext
- expect
- byacc
- libtool
sources:
- https://github.com/shadow-maint/shadow
tasks:
- build: |
cd shadow
./autogen.sh --without-selinux --disable-man
grep ENABLE_ config.status
- tasks: |
cd shadow
cat /proc/self/uid_map
cat /proc/self/status
systemd-detect-virt
make
make DESTDIR=/tmp/shadow-inst install
sudo make install
(cd tests; sudo ./run_some || { cat testsuite.log; false; })

View File

@@ -1,26 +0,0 @@
image: ubuntu/22.04
packages:
- automake
- autopoint
- xsltproc
- libselinux1-dev
- gettext
- expect
- byacc
- libtool
sources:
- https://github.com/shadow-maint/shadow
tasks:
- build: |
cd shadow
./autogen.sh --without-selinux --enable-man
grep ENABLE_ config.status
- tasks: |
cat /proc/self/uid_map
cat /proc/self/status
systemd-detect-virt
cd shadow
make
make DESTDIR=/tmp/shadow-inst install
sudo make install
(cd tests; sudo ./run_some || { cat testsuite.log; false; })

4
.editorconfig Normal file
View File

@@ -0,0 +1,4 @@
root = true
[*.{c,h}]
indent_style = tab

View File

@@ -6,7 +6,7 @@ runs:
- shell: bash
run: |
sudo apt-get update -y
sudo apt-get install -y ubuntu-dev-tools
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
sudo apt-get -y build-dep shadow

110
.github/workflows/runner.yml vendored Normal file
View File

@@ -0,0 +1,110 @@
name: CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: debug
run: |
id
which bash
whoami
env
ps -ef
pwd
cat /proc/self/uid_map
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
- name: configure
run: |
autoreconf -v -f --install
./autogen.sh --without-selinux --disable-man --with-yescrypt
- run: make
- run: make install DESTDIR=${HOME}/rootfs
- run: sudo make install
- name: run tests in shell with tty
shell: 'script -q -e -c "bash {0}"'
run: |
set -e
cd tests
trap 'cat testsuite.log' ERR
sudo ./run_some
trap - ERR
# Make sure that 'make dist' makes a usable tarball with no missing files
dist-build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
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
- name: Test make dist
run: |
./autogen.sh
make dist
f=shadow-*.tar.gz
tar -zxf $f
d=$(basename $f .tar.gz)
cd $d
./configure
make -j5
make check
container-build:
runs-on: ubuntu-latest
strategy:
matrix:
os: [alpine, debian, fedora]
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Build container
run: |
docker buildx build -f ./share/containers/${{ matrix.os }}.dockerfile . --output build-out
- name: Store artifacts
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.os }}-build
path: |
./build-out/config.log
./build-out/config.h
if-no-files-found: ignore

View File

@@ -14,7 +14,7 @@ jobs:
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Install dependencies
id: dependencies
@@ -32,7 +32,27 @@ jobs:
- name: Build shadow-utils
run: |
PROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN)
make -j$PROCESSORS
make -Orecurse -j$PROCESSORS
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
differential-shellcheck:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
# Doc: https://github.com/redhat-plumbers-in-action/differential-shellcheck#usage
- name: Differential ShellCheck
uses: redhat-plumbers-in-action/differential-shellcheck@v3
with:
severity: warning
token: ${{ secrets.GITHUB_TOKEN }}

7
.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
@@ -47,5 +52,5 @@ Makefile.in
/shadow.spec
/shadow-*.tar.*
/libmisc/getdate.c
/lib/getdate.c
/libsubid/subid.h

View File

@@ -1,52 +0,0 @@
dist: bionic
sudo: false
language: c
compiler:
- gcc
- clang
arch:
- amd64
- arm64
- ppc64le
- s390x
before_install:
- sudo apt-get update -qq
- sudo apt-get -y install -qq automake autopoint xsltproc libselinux1-dev gettext expect
- sudo apt-get -y install -qq byacc libtool
script:
- ./autogen.sh --without-selinux --disable-man
- grep ENABLE_ config.status
- make
env:
global:
- secure: "G47VYFrtzqalrVjixTqBG9Qsa8EZRcaqsh1k6fq5JgEyHmMQActpvTUDs9FXf1MEqiY5XX3VDVfBsZgKPHgmHsMzD1bX11xpnpGByB8g7gr8I3u2ZkCREqgi77a5l3LeBh+seWiambe/DYOgvPCNa6pCynLgR9advqtgKhpCruU="
addons:
coverity_scan:
project:
name: "shadow-maint/shadow"
description: "Upstream shadow utils tree"
notification_email: christian.brauner@ubuntu.com,serge@hallyn.com
build_command_prepend: "./autogen.sh --without-selinux --disable-man"
build_command: "make -j4"
branch_pattern: master
script:
- cat /proc/self/uid_map
- cat /proc/self/status
- systemd-detect-virt
- ./autogen.sh --without-selinux --disable-man
- grep ENABLE_ config.status
- make
- sudo make install
- (cd tests; sudo ./run_some; cat testsuite.log)
# vim:et:ts=2:sw=2

View File

@@ -3,11 +3,20 @@ reports and various comments. This list may be incomplete, I received
a lot of mail...
# Maintainers
* Marek Michałkiewicz <marekm72@gmail.com> (1995-2000)
* Tomasz Kłoczko <kloczek@pld.org.pl> (2000-2007)
* Nicolas François <nicolas.francois@centraliens.net> (2007-2014)
* Serge E. Hallyn <serge@hallyn.com> (2014-now)
* Christian Brauner <christian@brauner.io> (2019-now)
* Iker Pedrosa <ipedrosa@redhat.com> (2022-now)
* Alejandro Colomar <alx@kernel.org> (2023-now) (4.14 stable)
To verify signatures on releases, use the following keys under keys/ :
* Serge Hallyn: keys/66D0387DB85D320F8408166DB175CFA98F192AF2.asc
* Christian Brauner: keys/4880B8C9BD0E5106FC070F4F7B3C391EFEA93624.asc
* Iker Pedrosa: keys/4E80EF49C7987B6DE2F81F5005079C6C3A653E57.asc
* Alejandro Colomar: keys/A9348594CE31283A826FBDD8D57633D441E25BB5.asc
# Authors and contributors
* Adam Rudnicki <adam@v-lo.krakow.pl>

View File

@@ -1,3 +1,32 @@
2022-11-08 Serge Hallyn <serge@hallyn.com>
* useradd.8: fix default group ID (Tim Biermann)
* Revert drop of subid_init() (Serge Hallyn)
* Georgian translation (NorwayFun)
* useradd: Avoid taking unneeded space: do not reset non-existent data
in lastlog (David Kalnischkies)
* relax username restrictions (Alexander Kanavin)
* selinux: check MLS enabled before setting serange (genBTC)
* copy_tree: use fchmodat instead of chmod (Samanta Navarro)
* copy_tree: don't block on FIFOs (Samanta Navarro)
* add shell linter (Jan Macku)
* copy_tree: carefully treat permissions (Samanta Navarro)
* lib/commonio: make lock failures more detailed (Luca BRUNO)
* lib: use strzero and memzero where applicable (Christian Göttsche)
* Update Dutch translation (Frans Spiesschaert)
* Don't test for NULL before calling free (Alex Colomar)
* Use libc MAX() and MIN() (Alejandro Colomar)
* chage: Fix regression in print_date (Xiami)
* usermod: report error if homedir does not exist (Iker Pedrosa)
* libmisc: minimum id check for system accounts (Iker Pedrosa)
* fix usermod -rG x y wrongly adding a group (xyz)
* man: add missing space in useradd.8.xml (Iker Pedrosa)
* lastlog: check for localtime() return value (Iker Pedrosa)
* Raise limit for passwd and shadow entry length (Iker Pedrosa)
* Remove adduser-old.c (Alejandro Colomar)
* useradd: Fix buffer overflow when using a prefix (David Michael)
* Don't warn when failed to open /etc/nsswitch.conf (Serge Hallyn)
2022-08-15 Serge Hallyn <serge@hallyn.com>
* Address CVE-2013-4235 (TOCTTOU when copying directories)
@@ -9529,7 +9558,7 @@
* NEWS: release date corrected.
* NEWS, src/su.c:
fixed set enviroment too early when using PAM, so move it to !USE_PAM
fixed set environment too early when using PAM, so move it to !USE_PAM
(patch submitted by Mike Frysinger <vapier@gentoo.org>).
2006-07-30 Tomasz Kłoczko <kloczek@pld.org.pl>
@@ -10216,7 +10245,7 @@
* NEWS: cleanups.
* autogen.sh:
by default in development enviroment use CFLAGS="-O2 -Wall".
by default in development environment use CFLAGS="-O2 -Wall".
* src/chgpasswd.c (main): remove two unused variables (newgr and now).
@@ -11625,7 +11654,7 @@
in OPTIONS section). Describe -a and -k options.
* NEWS, src/su.c:
fixed twice copy enviroment which causes auth problems (bug was introduced in 4.0.12;
fixed twice copy environment which causes auth problems (bug was introduced in 4.0.12;
fix by Nicolas François <nicolas.francois@centraliens.net>).
* src/passwd.c, po/ja.po, po/ko.po, po/nb.po, po/nl.po, po/nn.po, po/pl.po, po/pt.po, po/pt_BR.po, po/ro.po, po/ru.po, po/sk.po, po/sq.po, po/sv.po, po/tl.po, po/tr.po, po/uk.po, po/vi.po, po/zh_CN.po, po/zh_TW.po, po/bs.po, po/ca.po, po/cs.po, po/da.po, po/de.po, po/el.po, po/es.po, po/eu.po, po/fi.po, po/fr.po, po/he.po, po/id.po, po/it.po:
@@ -12555,7 +12584,7 @@
http://bugs.debian.org/48002
* src/login.c, NEWS:
fixed loggin of username on succesful login (was using the normal username,
fixed loggin of username on successful login (was using the normal username,
when it should have used pam_user) http://bugs.debian.org/47819
2005-06-02 Tomasz Kłoczko <kloczek@pld.org.pl>
@@ -13000,7 +13029,7 @@
* man/pl/usermod.8: finish sync with english version.
* man/hu/login.1, man/pl/login.1, NEWS, man/Attic/login.1, man/de/login.1:
removed fragment about abilities pass enviroment variables in login prompt.
removed fragment about abilities pass environment variables in login prompt.
* man/Attic/gpasswd.1, man/Attic/newgrp.1:
fixes by Nicolas Nicolas François <nicolas.francois@centraliens.net> (not all
@@ -13479,7 +13508,7 @@
removed not used translations.
* NEWS, src/su.c:
fix adding of pam_env env variables to enviroment (Martin Schlemmer <azarah@nosferatu.za.org>).
fix adding of pam_env env variables to environment (Martin Schlemmer <azarah@nosferatu.za.org>).
* NEWS, configure.in:
fixed filling MAIL_SPOOL_DIR and MAIL_SPOOL_FILE variables which was allways
@@ -13576,7 +13605,7 @@
* NEWS, src/su.c:
add pam_open_session() support. If builded without PAM support
propagate $DISPLAY and $XAUTHORITY enviroment variables.
propagate $DISPLAY and $XAUTHORITY environment variables.
Based on http://www.gentoo.org/cgi-bin/viewcvs.cgi/sys-apps/shadow/files/shadow-4.0.4.1-su-pam_open_session.patch?rev=1.1
2004-10-23 Tomasz Kłoczko <kloczek@pld.org.pl>

View File

@@ -1,15 +1,18 @@
## Process this file with automake to produce Makefile.in
EXTRA_DIST = NEWS README TODO shadow.spec.in
EXTRA_DIST = NEWS README
SUBDIRS = libmisc lib
SUBDIRS = lib
if ENABLE_SUBIDS
SUBDIRS += libsubid
endif
SUBDIRS += src po contrib doc etc
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 = tests/

14
NEWS
View File

@@ -696,7 +696,7 @@ shadow-4.0.18 -> shadow-4.0.18.1 03-08-2006
shadow-4.0.17 -> shadow-4.0.18 01-08-2006
*** general:
- su: fixed set enviroment too early when using PAM, so move it to !USE_PAM
- su: fixed set environment too early when using PAM, so move it to !USE_PAM
(patch submitted by Mike Frysinger <vapier@gentoo.org>),
- groupadd, groupmod, useradd, usermod: fixed UID/GID overflow (fixed
http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=198920)
@@ -855,7 +855,7 @@ shadow-4.0.14 -> shadow-4.0.15 13-03-2006
- su: move exit() outside libmisc/shell.c::shell() for handle shell() errors
on higher level (now is better visable where some programs exit with 126
and 127 exit codes); added new shell() parameter (char *const envp[])
which allow fix preserving enviroment in su on using -p, (patch by
which allow fix preserving environment in su on using -p, (patch by
Alexander Gattin <xrgtn@yandex.ru>),
- su: added handle -c,--command option for GNU su compliance (merge
437_su_-c_option Debian patch),
@@ -966,7 +966,7 @@ shadow-4.0.12 -> shadow-4.0.13 10-10-2005
to example described in ident(1) man page (modern compilers like latest GCC
removes not used functions by global optimization).
So "ident /usr/bin/passwd" will show again some useable informations
- su: fixed twice copy enviroment which causes auth problems
- su: fixed twice copy environment which causes auth problems
(bug was introduced in 4.0.12; fix by Nicolas François <nicolas.francois@centraliens.net>),
- chage: differentiate the different failure causes by the exit value
This will permit to adduser Debian script to detect if chage failed because the
@@ -1133,7 +1133,7 @@ shadow-4.0.9 -> shadow-4.0.10 28-06-2005
http://bugs.debian.org/53702
- login: check for hushed login and pass PAM_SILENT if true,
http://bugs.debian.org/48002
- login: fixed username on succesful login (was using the normal username,
- login: fixed username on successful login (was using the normal username,
when it should have used pam_user) http://bugs.debian.org/47819
- remove using SHADOWPWD #define so now shadow is always built with shadow
password support,
@@ -1212,7 +1212,7 @@ shadow-4.0.7 -> shadow-4.0.8 26-04-2005
(without gshadow) doesn't permit to use newgrp,
- newgrp(1): newgrp uses /bin/sh (not bash),
- faillog(8): updated after rewritten faillog command for use getopt_long(),
- login(1): removed fragment about abilities pass enviroment variables in login prompt,
- login(1): removed fragment about abilities pass environment variables in login prompt,
- gshadow(5): new file (by Nicolas Nicolas François <nicolas.francois@centraliens.net>),
- usermod(8): fixed #302388 Debian bug: added separated -o option description,
@@ -1242,7 +1242,7 @@ shadow-4.0.6 -> shadow-4.0.7 26-01-2005
shadow-4.0.5 -> shadow-4.0.6 08-11-2004
- su: fixed adding of pam_env env variables to enviroment
- su: fixed adding of pam_env env variables to environment
(Martin Schlemmer <azarah@nosferatu.za.org>),
- autoconf: fixed filling MAIL_SPOOL_DIR and MAIL_SPOOL_FILE variables
which was always empty (Gregorio Guidi <g.guidi@sns.it>),
@@ -1275,7 +1275,7 @@ shadow-4.0.4.1 -> shadow-4.0.5 27-10-2004
including symlinks placed into /etc/skel/public_html for example.
http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=66819
- su: add pam_open_session() support. If built without PAM support
propagate $DISPLAY and $XAUTHORITY enviroment variables.
propagate $DISPLAY and $XAUTHORITY environment variables.
Based on http://www.gentoo.org/cgi-bin/viewcvs.cgi/sys-apps/shadow/files/shadow-4.0.4.1-su-pam_open_session.patch?rev=1.1
- applied 036_pam_access_with_preauth.patch Debian patch submited by Bjorn
Torkelsson <Bjorn.Torkelsson@hpc2n.umu.se>: add support for PAM account

View File

@@ -17,6 +17,12 @@ are used for managing group accounts.
* [Issue tracker](https://github.com/shadow-maint/shadow/issues)
* [Releases](https://github.com/shadow-maint/shadow/releases)
## Code
The main development branch is at [https://github.com/shadow-maint/shadow.git](https://github.com/shadow-maint/shadow)
See [STABLE.md](https://github.com/shadow-maint/shadow/blob/master/STABLE.md) for a list of supported stable branches.
## Contacts
There are several ways to contact us:
* [the general discussion mailing list](
@@ -31,6 +37,11 @@ There are several ways to contact us:
https://alioth-lists-archive.debian.net/pipermail/pkg-shadow-commits/),
only used for historical purposes
## Contributions
Contributions are welcome. Follow the
[guidelines](doc/contributions/introduction.md) before posting any patches.
## Authors and maintainers
Authors and maintainers are listed in [AUTHORS.md](
https://github.com/shadow-maint/shadow/blob/master/AUTHORS.md).

View File

@@ -9,3 +9,4 @@ At the moment only the latest release is supported.
Security vulnerabilities may be reported to
* Serge Hallyn <serge@hallyn.com> (B175CFA98F192AF2)
* Christian Brauner <christian@brauner.io> (4880B8C9BD0E5106FC070F4F7B3C391EFEA93624)
* Iker Pedrosa <ipedrosa@redhat.com> (4E80EF49C7987B6DE2F81F5005079C6C3A653E57)

11
STABLE.md Normal file
View File

@@ -0,0 +1,11 @@
# Supported stable branches
The following stable branches are kindly maintained by trusted volunteers:
- 4.15.x
- git
- [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.15/)
- [mirror](https://github.com/shadow-maint/shadow/releases/)

127
TODO
View File

@@ -1,127 +0,0 @@
* Create a common usage function that'd take the array of
long options and an array of descriptions and output that so things would
be standardized across the utils.
Usage strings should be normalized and split first.
Investigate optparse.
/etc/default/useradd
* GROUP=1000 should accept a group name.
Check when RLOGIN is enabled if ruserok() exists
Move selinux_file_context out of libmisc/copydir.c
Review hardcoded root account?
review all call to strto
libmisc/cleanup_user.c
cleanup needed (cleanup_report_add_user* not used)
libxcrypt support
* http://wiki.linuxfromscratch.org/patches/browser/trunk/shadow/shadow-4.0.18.1-owl_blowfish-1.patch
implement getlong, getulong.
avoid atoi, atol, atoul, strtol, strtoul, ...
manpages: comment the RLOGIN parts
Replace build_list (in lib/gshadow.c) and list (in lib/sgetgrent.c) by
comma_to_list()
Revert the modified files if all files could not be changed.
* or warn and indicate which files were modified and which were not.
* check the order the files are modified.
report nscd_flush_cache failures?
call nscd from the programs or from lib (commonio?)
PAM: check if a non-interactive conversation function could be used to set
the password in chpasswd and newusers
WITH_SELINUX
- review all tools to check that the strategies are consistent
chage, chfn, chsh: same change needed as in passwd.
- probably need moving check_selinux_access to a separate file.
testsuite
- newgrp
- test with unknown user's GID
newusers
- add logging to SYSLOG & AUDIT
- use CREATE_HOME
- Add a -Z option (see useradd / usermod)
Document when/where option appeared, document whether an option is standard
or not.
Check all the expiry semantics
ALL:
- move base passwd/shadow/group/gshadow operation to module for allow write
different backend modules for db, NIS, LDAP and others. Default backend it
will be goot if will be chosen depending on /etc/nsswitch.conf and allow
override this by -r <repository> options (where the <repository> can be
file, db, nis nisplus, ldap .. like on /etc/nsswitch.conf in service column).
passwd have old piece of code with handling -r option and it will be good
finish this and propagate on other shadow tools for allow operate on other
user databases by well known tools.
- Protect against signals. Register do_cleanups in a signal handler.
- login.defs
- generate depending on configuration
- useradd:
- add handle create user mail spool in maildir format.
- Add support for -k in -D mode
- Add support for -K in -D mode
- Add option to create or not the mail spool (and set the default in -D
mode)
- Change -l to reset the entry if an entry was already there
- set the mask in mkdir?
- userdel:
- add backup option for the removal of user resources,
- user_busy: check that the user is not running any processes.
- missing "deleting group" FAILED
- home dir removed, but userdel may fail and may leave the user
=> warning needed
- usermod
- add an option equivalent to useradd's -l (only when uid is changed)
- the mode of new home directories should be set according to the
original mode. Does copy_tree does this?
- user renamed, order is not kept in /etc/group (see
47_usermod-l_no_shadow_file). This is a problem when the first user is
considered as the admin.
- see mail "user ID change" on April, 15
+ fix call to chown (combination of -m and -u/-g)
+ add tests
- passwd:
- check combination of options (e.g. -u/-l)
- when -u refuse to unlock because it would create an empty password, it
should not display "Password changed."
exit instead?
- newgrp: check the USE_PAM section.
- pwck
- Add check to move passwd passwords to shadow if there is a shadow
entry (with a password).
- Add check to move passwd passwords to shadow if there is a shadow
file.
- Support an alternative /etc/tcb directory as second parameter.
- add options -g / -G to specify alternative group / gshadow files
- su
- add a login.defs configuration parameter to add variables to keep in
the environment with "su -l" (TERM/TERMCOLOR/...)
- vipw
- set ACLs and XATTRs on the temporary file (and backups?)
- vipw + selinux -> use lib/selinux.c

View File

@@ -1,9 +1,21 @@
#! /bin/sh
autoreconf -v -f --install || exit 1
autoreconf -v -f --install "$(dirname "$0")" || exit 1
./configure \
CFLAGS="-O2 -Wall" \
CFLAGS="-O2"
CFLAGS="$CFLAGS -Wall"
CFLAGS="$CFLAGS -Wextra"
CFLAGS="$CFLAGS -Werror=implicit-function-declaration"
CFLAGS="$CFLAGS -Werror=implicit-int"
CFLAGS="$CFLAGS -Werror=incompatible-pointer-types"
CFLAGS="$CFLAGS -Werror=int-conversion"
CFLAGS="$CFLAGS -Wno-expansion-to-defined"
CFLAGS="$CFLAGS -Wno-unknown-attributes"
CFLAGS="$CFLAGS -Wno-unknown-warning-option"
"$(dirname "$0")"/configure \
CFLAGS="$CFLAGS" \
--enable-lastlog \
--enable-man \
--enable-maintainer-mode \
--enable-shared \

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.12.2], [pkg-shadow-devel@lists.alioth.debian.org], [],
AC_INIT([shadow], [4.16.0], [pkg-shadow-devel@lists.alioth.debian.org], [],
[https://github.com/shadow-maint/shadow])
AM_INIT_AUTOMAKE([1.11 foreign dist-xz])
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])
@@ -32,47 +32,30 @@ AC_PROG_CC
AC_PROG_LN_S
AC_PROG_YACC
LT_INIT
LT_LIB_DLLOAD
dnl Checks for libraries.
dnl Checks for header files.
AC_HEADER_STDBOOL
AC_CHECK_HEADERS(crypt.h errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \
utmpx.h termios.h termio.h sgtty.h sys/ioctl.h syslog.h paths.h \
utime.h ulimit.h sys/capability.h sys/random.h sys/resource.h \
gshadow.h lastlog.h locale.h rpc/key_prot.h netdb.h acl/libacl.h \
AC_CHECK_HEADERS(crypt.h utmp.h \
termio.h sgtty.h sys/ioctl.h paths.h \
sys/capability.h sys/random.h \
gshadow.h lastlog.h rpc/key_prot.h acl/libacl.h \
attr/libattr.h attr/error_context.h)
dnl shadow now uses the libc's shadow implementation
AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
AC_CHECK_FUNCS(arc4random_buf l64a fchmod fchown fsync futimes \
AC_CHECK_FUNCS(arc4random_buf futimes \
getentropy getrandom getspnam getusershell \
getutent initgroups lckpwdf lutimes \
setgroups updwtmp updwtmpx innetgr getpwnam_r \
getpwuid_r getgrnam_r getgrgid_r getspnam_r \
memset_s explicit_bzero)
initgroups lckpwdf lutimes \
setgroups updwtmpx innetgr \
getspnam_r \
rpmatch \
memset_explicit explicit_bzero stpecpy stpeprintf)
AC_SYS_LARGEFILE
dnl Checks for typedefs, structures, and compiler characteristics.
AC_CHECK_MEMBERS([struct stat.st_atim])
AC_CHECK_MEMBERS([struct stat.st_atimensec])
AC_CHECK_MEMBERS([struct stat.st_mtim])
AC_CHECK_MEMBERS([struct stat.st_mtimensec])
AC_STRUCT_TM
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,
@@ -82,29 +65,11 @@ AC_CHECK_MEMBERS([struct utmpx.ut_name,
struct utmpx.ut_time,
struct utmpx.ut_xtime],,,[[#include <utmpx.h>]])
if test "$ac_cv_header_lastlog_h" = "yes"; then
AC_CACHE_CHECK(for ll_host in struct lastlog,
ac_cv_struct_lastlog_ll_host,
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <lastlog.h>],
[struct lastlog ll; char *cp = ll.ll_host;]
)],
[ac_cv_struct_lastlog_ll_host=yes],
[ac_cv_struct_lastlog_ll_host=no]
)
)
if test "$ac_cv_struct_lastlog_ll_host" = "yes"; then
AC_DEFINE(HAVE_LL_HOST, 1,
[Define if struct lastlog has ll_host])
fi
fi
dnl Checks for library functions.
AC_TYPE_GETGROUPS
AC_FUNC_UTIME_NULL
AC_REPLACE_FUNCS(mkdir putgrent putpwent putspent rename rmdir)
AC_REPLACE_FUNCS(putgrent putpwent putspent)
AC_REPLACE_FUNCS(sgetgrent sgetpwent sgetspent)
AC_REPLACE_FUNCS(snprintf strcasecmp strdup strerror strstr)
AC_CHECK_FUNC(setpgrp)
AC_CHECK_FUNC(secure_getenv, [AC_DEFINE(HAS_SECURE_GETENV,
@@ -116,6 +81,10 @@ if test "$ac_cv_header_shadow_h" = "yes"; then
ac_cv_libc_shadowgrp,
AC_RUN_IFELSE([AC_LANG_SOURCE([
#include <shadow.h>
#ifdef HAVE_GSHADOW_H
#include <gshadow.h>
#endif
int
main()
{
struct sgrp *sg = sgetsgent("test:x::");
@@ -190,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 :).
AC_DEFINE(USE_SYSLOG, 1, [Define to use syslog().])
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
@@ -226,17 +188,6 @@ AC_ARG_ENABLE(account-tools-setuid,
[enable_acct_tools_setuid="no"]
)
AC_ARG_ENABLE(utmpx,
[AS_HELP_STRING([--enable-utmpx],
[enable loggin in utmpx / wtmpx @<:@default=no@:>@])],
[case "${enableval}" in
yes) enable_utmpx="yes" ;;
no) enable_utmpx="no" ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-utmpx) ;;
esac],
[enable_utmpx="no"]
)
AC_ARG_ENABLE(subordinate-ids,
[AS_HELP_STRING([--enable-subordinate-ids],
[support subordinate ids @<:@default=yes@:>@])],
@@ -244,6 +195,20 @@ AC_ARG_ENABLE(subordinate-ids,
[enable_subids="maybe"]
)
AC_ARG_ENABLE(lastlog,
[AS_HELP_STRING([--enable-lastlog],
[enable lastlog @<:@default=no@:>@])],
[enable_lastlog="${enableval}"],
[enable_lastlog="no"]
)
AC_ARG_ENABLE(logind,
[AS_HELP_STRING([--enable-logind],
[enable logind @<:@default=yes@:>@])],
[enable_logind="${enableval}"],
[enable_logind="yes"]
)
AC_ARG_WITH(audit,
[AS_HELP_STRING([--with-audit], [use auditing support @<:@default=yes if found@:>@])],
[with_audit=$withval], [with_audit=maybe])
@@ -268,9 +233,6 @@ AC_ARG_WITH(skey,
AC_ARG_WITH(tcb,
[AS_HELP_STRING([--with-tcb], [use tcb support (incomplete) @<:@default=yes if found@:>@])],
[with_tcb=$withval], [with_tcb=maybe])
AC_ARG_WITH(libcrack,
[AS_HELP_STRING([--with-libcrack], [use libcrack @<:@default=no@:>@])],
[with_libcrack=$withval], [with_libcrack=no])
AC_ARG_WITH(sha-crypt,
[AS_HELP_STRING([--with-sha-crypt], [allow the SHA256 and SHA512 password encryption algorithms @<:@default=yes@:>@])],
[with_sha_crypt=$withval], [with_sha_crypt=yes])
@@ -292,6 +254,9 @@ AC_ARG_WITH(group-name-max-length,
AC_ARG_WITH(su,
[AS_HELP_STRING([--with-su], [build and install su program and man page @<:@default=yes@:>@])],
[with_su=$withval], [with_su=yes])
AC_ARG_WITH(libbsd,
[AS_HELP_STRING([--with-libbsd], [use libbsd support @<:@default=yes if found@:>@])],
[with_libbsd=$withval], [with_libbsd=yes])
if test "$with_group_name_max_length" = "no" ; then
with_group_name_max_length=0
@@ -302,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])
@@ -336,12 +302,16 @@ dnl Check for some functions in libc first, only if not found check for
dnl other libraries. This should prevent linking libnsl if not really
dnl needed (Linux glibc, Irix), but still link it if needed (Solaris).
AC_SEARCH_LIBS(inet_ntoa, inet)
AC_SEARCH_LIBS(socket, socket)
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"],
[Directory for distribution provided configuration files])
ECONF_CPPFLAGS="-DUSE_ECONF=1"
AC_ARG_ENABLE([vendordir],
AS_HELP_STRING([--enable-vendordir=DIR], [Directory for distribution provided configuration files]),,[])
@@ -349,6 +319,9 @@ fi
AC_SUBST(ECONF_CPPFLAGS)
AC_SUBST(LIBECONF)
AC_SUBST([VENDORDIR], [$enable_vendordir])
if test "x$enable_vendordir" != x; then
AC_DEFINE(HAVE_VENDORDIR, 1, [Define to support vendor settings.])
fi
AM_CONDITIONAL([HAVE_VENDORDIR], [test "x$enable_vendordir" != x])
if test "$enable_shadowgrp" = "yes"; then
@@ -393,6 +366,39 @@ if test "$enable_subids" != "no"; then
fi
AM_CONDITIONAL(ENABLE_SUBIDS, test "x$enable_subids" != "xno")
if test "$enable_lastlog" = "yes" && test "$ac_cv_header_lastlog_h" = "yes"; then
AC_CACHE_CHECK(for ll_host in struct lastlog,
ac_cv_struct_lastlog_ll_host,
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <lastlog.h>],
[struct lastlog ll; char *cp = ll.ll_host;]
)],
[ac_cv_struct_lastlog_ll_host=yes],
[ac_cv_struct_lastlog_ll_host=no]
)
)
if test "$ac_cv_struct_lastlog_ll_host" = "yes"; then
AC_DEFINE(HAVE_LL_HOST, 1,
[Define if struct lastlog has ll_host])
AC_DEFINE(ENABLE_LASTLOG, 1, [Define to support lastlog.])
enable_lastlog="yes"
else
AC_MSG_ERROR([Cannot enable support for lastlog on systems where the data structures aren't available])
enable_subids="no"
fi
fi
AM_CONDITIONAL(ENABLE_LASTLOG, test "x$enable_lastlog" != "xno")
AC_SUBST(LIBSYSTEMD)
if test "$enable_logind" = "yes"; then
AC_CHECK_LIB(systemd, sd_session_get_remote_host,
[enable_logind="yes"; [LIBSYSTEMD=-lsystemd];
AC_DEFINE(ENABLE_LOGIND, 1,
[Define to manage session support with logind.])],
[enable_logind="no"])
fi
AM_CONDITIONAL(ENABLE_LOGIND, test "x$enable_logind" != "xno")
AC_SUBST(LIBCRYPT)
AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt],
[AC_MSG_ERROR([crypt() not found])])
@@ -401,6 +407,28 @@ AC_SUBST(LIYESCRYPT)
AC_CHECK_LIB(crypt, crypt, [LIYESCRYPT=-lcrypt],
[AC_MSG_ERROR([crypt() not found])])
AC_SUBST(LIBBSD)
if test "$with_libbsd" != "no"; then
AC_SEARCH_LIBS([readpassphrase], [bsd], [], [
AC_MSG_ERROR([readpassphrase() is missing, either from libc or libbsd])
])
AS_IF([test "$ac_cv_search_readpassphrase" = "-lbsd"], [
PKG_CHECK_MODULES([LIBBSD], [libbsd-overlay])
])
dnl Make sure either the libc or libbsd provide the header.
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $LIBBSD_CFLAGS"
AC_CHECK_HEADERS([readpassphrase.h])
AS_IF([test "$ac_cv_header_readpassphrase_h" != "yes"], [
AC_MSG_ERROR([readpassphrase.h is missing])
])
CFLAGS="$save_CFLAGS"
AC_DEFINE(WITH_LIBBSD, 1, [Build shadow with libbsd support])
else
AC_DEFINE(WITH_LIBBSD, 0, [Build shadow without libbsd support])
fi
AM_CONDITIONAL(WITH_LIBBSD, test x$with_libbsd = xyes)
AC_SUBST(LIBACL)
if test "$with_acl" != "no"; then
AC_CHECK_HEADERS(acl/libacl.h attr/error_context.h, [acl_header="yes"], [acl_header="no"])
@@ -485,17 +513,6 @@ if test "$with_audit" != "no"; then
fi
fi
AC_SUBST(LIBCRACK)
if test "$with_libcrack" = "yes"; then
echo "checking cracklib flavour, don't be surprised by the results"
AC_CHECK_LIB(crack, FascistCheck,
[LIBCRACK=-lcrack AC_DEFINE(HAVE_LIBCRACK, 1, [Defined if you have libcrack.])])
AC_CHECK_LIB(crack, FascistHistory,
AC_DEFINE(HAVE_LIBCRACK_HIST, 1, [Defined if you have the ts&szs cracklib.]))
AC_CHECK_LIB(crack, FascistHistoryPw,
AC_DEFINE(HAVE_LIBCRACK_PW, 1, [Defined if it includes *Pw functions.]))
fi
if test "$with_btrfs" != "no"; then
AC_CHECK_HEADERS([sys/statfs.h linux/magic.h linux/btrfs_tree.h], \
[btrfs_headers="yes"], [btrfs_headers="no"])
@@ -682,14 +699,7 @@ if test "$with_skey" = "yes"; then
]])],[AC_DEFINE(SKEY_BSD_STYLE, 1, [Define to support newer BSD S/Key API])],[])
fi
if test "$enable_utmpx" = "yes"; then
if test "$ac_cv_header_utmpx_h" != "yes"; then
AC_MSG_ERROR([The utmpx.h header file is required for utmpx support.])
fi
AC_DEFINE(USE_UTMPX,
1,
[Define if utmpx should be used])
fi
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.])
@@ -723,7 +733,6 @@ AC_CONFIG_FILES([
man/uk/Makefile
man/zh_CN/Makefile
man/zh_TW/Makefile
libmisc/Makefile
lib/Makefile
libsubid/Makefile
libsubid/subid.h
@@ -731,7 +740,8 @@ AC_CONFIG_FILES([
contrib/Makefile
etc/Makefile
etc/pam.d/Makefile
shadow.spec
etc/shadow-maint/Makefile
tests/unit/Makefile
])
AC_OUTPUT
@@ -739,7 +749,6 @@ echo
echo "shadow will be compiled with the following features:"
echo
echo " auditing support: $with_audit"
echo " CrackLib support: $with_libcrack"
echo " PAM support: $with_libpam"
if test "$with_libpam" = "yes"; then
echo " suid account management tools: $enable_acct_tools_setuid"
@@ -757,6 +766,9 @@ echo " yescrypt passwords encryption: $with_yescrypt"
echo " nscd support: $with_nscd"
echo " sssd support: $with_sssd"
echo " subordinate IDs support: $enable_subids"
echo " enable lastlog: $enable_lastlog"
echo " enable logind: $enable_logind"
echo " use file caps: $with_fcaps"
echo " install su: $with_su"
echo " enabled vendor dir: $enable_vendordir"
echo

View File

@@ -1,6 +1,4 @@
# This is a dummy Makefile.am to get automake work flawlessly,
# and also cooperate to make a distribution for `make dist'
EXTRA_DIST = README adduser.c adduser-old.c adduser.sh adduser2.sh \
atudel groupmems.shar pwdauth.c shadow-anonftp.patch \
udbachk.tgz
EXTRA_DIST = README adduser.c adduser.sh adduser2.sh

View File

@@ -2,9 +2,6 @@ People keep sending various adduser programs and scripts... They are
all in this directory. I haven't tested them, use at your own risk.
Anyway, the best one I've seen so far is adduser-3.x from Debian.
atudel is a perl script to remove at jobs owned by the specified user
(atrm in at-2.9 for Linux can't do that).
udbachk.tgz is a passwd/group/shadow file integrity checker.
--marekm

View File

@@ -1,300 +0,0 @@
/****
** 03/17/96
** hacked a bit more, removed unused code, cleaned up for gcc -Wall.
** --marekm
**
** 02/26/96
** modified to call shadow utils (useradd,chage,passwd) on shadowed
** systems - Cristian Gafton, gafton@sorosis.ro
**
** 6/27/95
** shadow-adduser 1.4:
**
** now it copies the /etc/skel dir into the person's dir,
** makes the mail folders, changed some defaults and made a 'make
** install' just for the hell of it.
**
** Greg Gallagher
** CIN.Net
**
** 1/28/95
** shadow-adduser 1.3:
**
** Basically a bug-fix on my additions in 1.2. Thanks to Terry Stewart
** (stew@texas.net) for pointing out one of the many idiotic bugs I introduced.
** It was such a stupid bug that I would have never seen it myself.
**
** Brandon
*****
** 01/27/95
**
** shadow-adduser 1.2:
** I took the C source from adduser-shadow (credits are below) and made
** it a little more worthwhile. Many small changes... Here's
** the ones I can remember:
**
** Removed support for non-shadowed systems (if you don't have shadow,
** use the original adduser, don't get this shadow version!)
** Added support for the correct /etc/shadow fields (Min days before
** password change, max days before password change, Warning days,
** and how many days from expiry date does the account go invalid)
** The previous version just left all of those fields blank.
** There is still one field left (expiry date for the account, period)
** which I have left blank because I do not use it and didn't want to
** spend any more time on this. I'm sure someone will put it in and
** tack another plethora of credits on here. :)
** Added in the password date field, which should always reflect the last
** date the password was changed, for expiry purposes. "passwd" always
** updates this field, so the adduser program should set it up right
** initially (or a user could keep thier initial password forever ;)
** The number is in days since Jan 1st, 1970.
**
** Have fun with it, and someone please make
** a real version(this is still just a hack)
** for us all to use (and Email it to me???)
**
** Brandon
** photon@usis.com
**
*****
** adduser 1.0: add a new user account (For systems not using shadow)
** With a nice little interface and a will to do all the work for you.
**
** Craig Hagan
** hagan@opine.cs.umass.edu
**
** Modified to really work, look clean, and find unused uid by Chris Cappuccio
** chris@slinky.cs.umass.edu
**
*****
**
** 01/19/95
**
** FURTHER modifications to enable shadow passwd support (kludged, but
** no more so than the original) by Dan Crowson - dcrowson@mo.net
**
** Search on DAN for all changes...
**
*****
**
** cc -O -o adduser adduser.c
** Use gcc if you have it... (political reasons beyond my control) (chris)
**
** I've gotten this program to work with success under Linux (without
** shadow) and SunOS 4.1.3. I would assume it should work pretty well
** on any system that uses no shadow. (chris)
**
** If you have no crypt() then try
** cc -DNO_CRYPT -O -o adduser adduser.c xfdes.c
** I'm not sure how login operates with no crypt()... I guess
** the same way we're doing it here.
*/
#include <pwd.h>
#include <grp.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <sys/time.h>
#include <sys/stat.h>
#define DEFAULT_SHELL "/bin/bash" /* because BASH is your friend */
#define DEFAULT_HOME "/home"
#define USERADD_PATH "/usr/sbin/useradd"
#define CHAGE_PATH "/usr/sbin/chage"
#define PASSWD_PATH "/usr/bin/passwd"
#define DEFAULT_GROUP 100
#define DEFAULT_MAX_PASS 60
#define DEFAULT_WARN_PASS 10
/* if you use this feature, you will get a lot of complaints from users
who rarely use their accounts :) (something like 3 months would be
more reasonable) --marekm */
#define DEFAULT_USER_DIE /* 10 */ 0
void main()
{
char foo[32];
char uname[9],person[32],dir[32],shell[32];
unsigned int group,min_pass,max_pass,warn_pass,user_die;
/* the group and uid of the new user */
int bad=0,done=0,correct=0,gets_warning=0;
char cmd[255];
struct group *grp;
/* flags, in order:
* bad to see if the username is in /etc/passwd, or if strange stuff has
* been typed if the user might be put in group 0
* done allows the program to exit when a user has been added
* correct loops until a password is found that isn't in /etc/passwd
* gets_warning allows the fflush to be skipped for the first gets
* so that output is still legible
*/
/* The real program starts HERE! */
if(geteuid()!=0)
{
printf("It seems you don't have access to add a new user. Try\n");
printf("logging in as root or su root to gain super-user access.\n");
exit(1);
}
/* Sanity checks
*/
if (!(grp=getgrgid(DEFAULT_GROUP))){
printf("Error: the default group %d does not exist on this system!\n",
DEFAULT_GROUP);
printf("adduser must be recompiled.\n");
exit(1);
};
while(!correct) { /* loop until a "good" uname is chosen */
while(!done) {
printf("\nLogin to add (^C to quit): ");
if(gets_warning) /* if the warning was already shown */
fflush(stdout); /* fflush stdout, otherwise set the flag */
else
gets_warning=1;
gets(uname);
if(!strlen(uname)) {
printf("Empty input.\n");
done=0;
continue;
};
/* what I saw here before made me think maybe I was running DOS */
/* might this be a solution? (chris) */
if (getpwnam(uname) != NULL) {
printf("That name is in use, choose another.\n");
done=0;
} else
done=1;
}; /* done, we have a valid new user name */
/* all set, get the rest of the stuff */
printf("\nEditing information for new user [%s]\n",uname);
printf("\nFull Name [%s]: ",uname);
gets(person);
if (!strlen(person)) {
bzero(person,sizeof(person));
strcpy(person,uname);
};
do {
bad=0;
printf("GID [%d]: ",DEFAULT_GROUP);
gets(foo);
if (!strlen(foo))
group=DEFAULT_GROUP;
else
if (isdigit (*foo)) {
group = atoi(foo);
if (! (grp = getgrgid (group))) {
printf("unknown gid %s\n",foo);
group=DEFAULT_GROUP;
bad=1;
};
} else
if ((grp = getgrnam (foo)))
group = grp->gr_gid;
else {
printf("unknown group %s\n",foo);
group=DEFAULT_GROUP;
bad=1;
}
if (group==0){ /* You're not allowed to make root group users! */
printf("Creation of root group users not allowed (must be done by hand)\n");
group=DEFAULT_GROUP;
bad=1;
};
} while(bad);
fflush(stdin);
printf("\nIf home dir ends with a / then [%s] will be appended to it\n",uname);
printf("Home Directory [%s/%s]: ",DEFAULT_HOME,uname);
fflush(stdout);
gets(dir);
if (!strlen(dir)) { /* hit return */
sprintf(dir,"%s/%s",DEFAULT_HOME,uname);
fflush(stdin);
} else
if (dir[strlen(dir)-1]=='/')
sprintf(dir+strlen(dir),"%s",uname);
printf("\nShell [%s]: ",DEFAULT_SHELL);
fflush(stdout);
gets(shell);
if (!strlen(shell))
sprintf(shell,"%s",DEFAULT_SHELL);
printf("\nMin. Password Change Days [0]: ");
gets(foo);
min_pass=atoi(foo);
printf("Max. Password Change Days [%d]: ",DEFAULT_MAX_PASS);
gets(foo);
if (strlen(foo) > 1)
max_pass = atoi(foo);
else
max_pass = DEFAULT_MAX_PASS;
printf("Password Warning Days [%d]: ",DEFAULT_WARN_PASS);
gets(foo);
warn_pass = atoi(foo);
if (warn_pass==0)
warn_pass = DEFAULT_WARN_PASS;
printf("Days after Password Expiry for Account Locking [%d]: ",DEFAULT_USER_DIE);
gets(foo);
user_die = atoi(foo);
if (user_die == 0)
user_die = DEFAULT_USER_DIE;
printf("\nInformation for new user [%s] [%s]:\n",uname,person);
printf("Home directory: [%s] Shell: [%s]\n",dir,shell);
printf("GID: [%d]\n",group);
printf("MinPass: [%d] MaxPass: [%d] WarnPass: [%d] UserExpire: [%d]\n",
min_pass,max_pass,warn_pass,user_die);
printf("\nIs this correct? [y/N]: ");
fflush(stdout);
gets(foo);
done=bad=correct=(foo[0]=='y'||foo[0]=='Y');
if(bad!=1)
printf("\nUser [%s] not added\n",uname);
}
bzero(cmd,sizeof(cmd));
sprintf(cmd,"%s -g %d -d %s -s %s -c \"%s\" -m -k /etc/skel %s",
USERADD_PATH,group,dir,shell,person,uname);
printf("Calling useradd to add new user:\n%s\n",cmd);
if(system(cmd)){
printf("User add failed!\n");
exit(errno);
};
bzero(cmd,sizeof(cmd));
sprintf(cmd,"%s -m %d -M %d -W %d -I %d %s", CHAGE_PATH,
min_pass,max_pass,warn_pass,user_die,uname);
printf("%s\n",cmd);
if(system(cmd)){
printf("There was an error setting password expire values\n");
exit(errno);
};
bzero(cmd,sizeof(cmd));
sprintf(cmd,"%s %s",PASSWD_PATH,uname);
system(cmd);
printf("\nDone.\n");
}

View File

@@ -60,7 +60,7 @@
** Added in the password date field, which should always reflect the last
** date the password was changed, for expiry purposes. "passwd" always
** updates this field, so the adduser program should set it up right
** initially (or a user could keep thier initial password forever ;)
** initially (or a user could keep their initial password forever ;)
** The number is in days since Jan 1st, 1970.
**
** Have fun with it, and someone please make
@@ -489,7 +489,7 @@ safeget (char *buf, int maxlen)
while ((c = getc (stdin)) != EOF && (c != '\n') && (++i < maxlen))
{
bad = (!isalnum (c) && (c != '_') && (c != ' '));
*(buf++) = (char) c;
*(buf++) = c;
}
*buf = '\0';

View File

@@ -1,58 +0,0 @@
#!/usr/bin/perl
#
# SPDX-FileCopyrightText: 1996 Brian R. Gaeke
# SPDX-License-Identifier: BSD-4-Clause
#
# Additionally:
#
# This software is provided without support and without any obligation
# on the part of Brian R. Gaeke to assist in its use, correction,
# modification or enhancement.
#
#######################################################################
#
# this is atudel, version 2, by Brian R. Gaeke <brg@dgate.org>
#
require "getopts.pl";
&Getopts('v');
$username = shift(@ARGV);
&usage unless $username;
sub usage
{
print STDERR "atudel - remove all at jobs owned by a user\n";
print STDERR "usage: $0 [-v] username\n";
exit(1);
}
# odd. unless getpwnam($uname) doesn't seem to work for $uname eq "root" on
# my linux system. but this does.
die "user $username does not exist; stopping"
unless defined(getpwnam($username));
print "searching for at jobs owned by user $username ..." if $opt_v;
chdir "/var/spool/atjobs" ||
die "can't chdir to /var/spool/atjobs: $!\nstopping";
opendir(DIR,".") || die "can't opendir(/var/spool/atjobs): $!\nstopping";
@files = grep(!/^\./,grep(-f,readdir(DIR)));
closedir DIR;
foreach $x (@files)
{
$owner = (getpwuid((stat($x))[4]))[0];
push(@nuke_bait,$x) if $owner eq $username;
}
if (@nuke_bait)
{
print "removed jobIDs: @{nuke_bait}.\n" if $opt_v;
unlink @nuke_bait;
}
elsif ($opt_v)
{
print "\n";
}
exit 0;

View File

@@ -1,465 +0,0 @@
#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2.1).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 2000-05-25 14:41 CDT by <gk4@gnu.austin.ibm.com>.
# Source directory was `/home/gk4/src/groupmem'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 1960 -rw-r--r-- Makefile
# 6348 -rw-r--r-- groupmems.c
# 3372 -rw------- groupmems.8
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
if test "$gettext_dir" = FAILED && test -f $dir/gettext \
&& ($dir/gettext --version >/dev/null 2>&1)
then
set `$dir/gettext --version 2>&1`
if test "$3" = GNU
then
gettext_dir=$dir
fi
fi
if test "$locale_dir" = FAILED && test -f $dir/shar \
&& ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
then
locale_dir=`$dir/shar --print-text-domain-dir`
fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
echo=echo
else
TEXTDOMAINDIR=$locale_dir
export TEXTDOMAINDIR
TEXTDOMAIN=sharutils
export TEXTDOMAIN
echo="$gettext_dir/gettext -s"
fi
if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then
shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then
shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then
shar_touch='touch -am $3$4$5$6$2 "$8"'
else
shar_touch=:
echo
$echo 'WARNING: not restoring timestamps. Consider getting and'
$echo "installing GNU \`touch', distributed in GNU File Utilities..."
echo
fi
rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch
#
if mkdir _sh10937; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
exit 1
fi
# ============= Makefile ==============
if test -f 'Makefile' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'Makefile' '(file already exists)'
else
$echo 'x -' extracting 'Makefile' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
/*
# SPDX-FileCopyrightText: 2000, International Business Machines, Inc.
# SPDX-FileCopyrightText: 2000, George Kraft IV, gk4@us.ibm.com
# SPDX-License-Identifier: BSD-3-Clause
#
X
all: groupmems
X
groupmems: groupmems.c
X cc -g -o groupmems groupmems.c -L. -lshadow
X
install: groupmems
X -/usr/sbin/groupadd groups
X install -o root -g groups -m 4770 groupmems /usr/bin
X
install.man: groupmems.8
X install -o root -g root -m 644 groupmems.8 /usr/man/man8
X
SHAR_EOF
(set 20 00 05 25 14 40 28 'Makefile'; eval "$shar_touch") &&
chmod 0644 'Makefile' ||
$echo 'restore of' 'Makefile' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'Makefile:' 'MD5 check failed'
b46cf7ef8d59149093c011ced3f3103c Makefile
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'Makefile'`"
test 1960 -eq "$shar_count" ||
$echo 'Makefile:' 'original size' '1960,' 'current size' "$shar_count!"
fi
fi
# ============= groupmems.c ==============
if test -f 'groupmems.c' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'groupmems.c' '(file already exists)'
else
$echo 'x -' extracting 'groupmems.c' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'groupmems.c' &&
/*
X * SPDX-FileCopyrightText: 2000, International Business Machines, Inc.
X * SPDX-FileCopyrightText: 2000, George Kraft IV, gk4@us.ibm.com
X * SPDX-License-Identifier: BSD-3-Clause
X */
/*
**
** Utility "groupmem" adds and deletes members from a user's group.
**
** Setup (as "root"):
**
** groupadd -r groups
** chmod 2770 groupmems
** chown root.groups groupmems
** groupmems -g groups -a gk4
**
** Usage (as "gk4"):
**
** groupmems -a olive
** groupmems -a jordan
** groupmems -a meghan
** groupmems -a morgan
** groupmems -a jake
** groupmems -l
** groupmems -d jake
** groupmems -l
*/
X
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "defines.h"
#include "groupio.h"
X
/* Exit Status Values */
X
#define EXIT_SUCCESS 0 /* success */
#define EXIT_USAGE 1 /* invalid command syntax */
#define EXIT_GROUP_FILE 2 /* group file access problems */
#define EXIT_NOT_ROOT 3 /* not superuser */
#define EXIT_NOT_EROOT 4 /* not effective superuser */
#define EXIT_NOT_PRIMARY 5 /* not primary owner of group */
#define EXIT_NOT_MEMBER 6 /* member of group does not exist */
#define EXIT_MEMBER_EXISTS 7 /* member of group already exists */
X
#define TRUE 1
#define FALSE 0
X
/* Globals */
X
extern int optind;
extern char *optarg;
static char *adduser = NULL;
static char *deluser = NULL;
static char *thisgroup = NULL;
static int purge = FALSE;
static int list = FALSE;
static int exclusive = 0;
X
static int isroot(void) {
X return getuid() ? FALSE : TRUE;
}
X
static int isgroup(void) {
X gid_t g = getgid();
X struct group *grp = getgrgid(g);
X
X return TRUE;
}
X
static char *whoami(void) {
X struct group *grp = getgrgid(getgid());
X struct passwd *usr = getpwuid(getuid());
X
X if (0 == strcmp(usr->pw_name, grp->gr_name)) {
X return (char *)strdup(usr->pw_name);
X } else {
X return NULL;
X }
}
X
static void
addtogroup(char *user, char **members) {
X int i;
X char **pmembers;
X
X for (i = 0; NULL != members[i]; i++ ) {
X if (0 == strcmp(user, members[i])) {
X fprintf(stderr, "Member already exists\n");
X exit(EXIT_MEMBER_EXISTS);
X }
X }
X
X if (0 == i) {
X pmembers = (char **)calloc(2, sizeof(char *));
X } else {
X pmembers = (char **)realloc(members, sizeof(char *)*(i+1));
X }
X
X *members = *pmembers;
X members[i] = user;
X members[i+1] = NULL;
}
X
static void
rmfromgroup(char *user, char **members) {
X int i;
X int found = FALSE;
X
X i = 0;
X while (!found && NULL != members[i]) {
X if (0 == strcmp(user, members[i])) {
X found = TRUE;
X } else {
X i++;
X }
X }
X
X while (found && NULL != members[i]) {
X members[i] = members[++i];
X }
X
X if (!found) {
X fprintf(stderr, "Member to remove could not be found\n");
X exit(EXIT_NOT_MEMBER);
X }
}
X
static void
nomembers(char **members) {
X int i;
X
X for (i = 0; NULL != members[i]; i++ ) {
X members[i] = NULL;
X }
}
X
static void
members(char **members) {
X int i;
X
X for (i = 0; NULL != members[i]; i++ ) {
X printf("%s ", members[i]);
X
X if (NULL == members[i+1]) {
X printf("\n");
X } else {
X printf(" ");
X }
X }
}
X
static void usage(void) {
X fprintf(stderr, "usage: groupmems -a username | -d username | -D | -l [-g groupname]\n");
X exit(EXIT_USAGE);
}
X
main(int argc, char **argv) {
X int arg, i;
X char *name;
X struct group *grp;
X
X while ((arg = getopt(argc, argv, "a:d:g:Dl")) != EOF) {
X switch (arg) {
X case 'a':
X adduser = strdup(optarg);
X ++exclusive;
X break;
X case 'd':
X deluser = strdup(optarg);
X ++exclusive;
X break;
X case 'g':
X thisgroup = strdup(optarg);
X break;
X case 'D':
X purge = TRUE;
X ++exclusive;
X break;
X case 'l':
X list = TRUE;
X ++exclusive;
X break;
X default:
X usage();
X }
X }
X
X if (exclusive > 1 || optind < argc) {
X usage();
X }
X
X if (!isroot() && NULL != thisgroup) {
X fprintf(stderr, "Only root can add members to different groups\n");
X exit(EXIT_NOT_ROOT);
X } else if (isroot() && NULL != thisgroup) {
X name = thisgroup;
X } else if (!isgroup()) {
X fprintf(stderr, "Group access is required\n");
X exit(EXIT_NOT_EROOT);
X } else if (NULL == (name = whoami())) {
X fprintf(stderr, "Not primary owner of current group\n");
X exit(EXIT_NOT_PRIMARY);
X }
X
X if (!gr_lock()) {
X fprintf(stderr, "Unable to lock group file\n");
X exit(EXIT_GROUP_FILE);
X }
X
X if (!gr_open(O_RDWR)) {
X fprintf(stderr, "Unable to open group file\n");
X exit(EXIT_GROUP_FILE);
X }
X
X grp = (struct group *)gr_locate(name);
X
X if (NULL != adduser) {
X addtogroup(adduser, grp->gr_mem);
X gr_update(grp);
X } else if (NULL != deluser) {
X rmfromgroup(deluser, grp->gr_mem);
X gr_update(grp);
X } else if (purge) {
X nomembers(grp->gr_mem);
X gr_update(grp);
X } else if (list) {
X members(grp->gr_mem);
X }
X
X if (!gr_close()) {
X fprintf(stderr, "Cannot close group file\n");
X exit(EXIT_GROUP_FILE);
X }
X
X gr_unlock();
X
X exit(EXIT_SUCCESS);
}
X
/* EOF */
SHAR_EOF
(set 20 00 05 25 14 36 38 'groupmems.c'; eval "$shar_touch") &&
chmod 0644 'groupmems.c' ||
$echo 'restore of' 'groupmems.c' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'groupmems.c:' 'MD5 check failed'
f0dd68f8d762d89d24d3ce1f4141f981 groupmems.c
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'groupmems.c'`"
test 6348 -eq "$shar_count" ||
$echo 'groupmems.c:' 'original size' '6348,' 'current size' "$shar_count!"
fi
fi
# ============= groupmems.8 ==============
if test -f 'groupmems.8' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'groupmems.8' '(file already exists)'
else
$echo 'x -' extracting 'groupmems.8' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'groupmems.8' &&
X.\"
X.\" SPDX-FileCopyrightText: 2000, International Business Machines, Inc.
X.\" SPDX-FileCopyrightText: 2000, George Kraft IV, gk4@us.ibm.com
X.\" SPDX-License-Identifier: BSD-3-Clause
X.\"
X.\" $Id$
X.\"
X.TH GROUPMEMS 8
X.SH NAME
groupmems \- Administer members of a user's primary group
X.SH SYNOPSIS
X.B groupmems
\fB-a\fI user_name \fR |
\fB-d\fI user_name \fR |
\fB-l\fR |
\fB-D\fR |
[\fB-g\fI group_name \fR]
X.SH DESCRIPTION
The \fBgroupmems\fR utility allows a user to administer their own
group membership list without the requirement of superuser privileges.
The \fBgroupmems\fR utility is for systems that configure its users to
be in their own name sake primary group (i.e., guest / guest).
X.P
Only the superuser, as administrator, can use \fBgroupmems\fR to alter
the memberships of other groups.
X.IP "\fB-a \fIuser_name\fR"
Add a new user to the group membership list.
X.IP "\fB-d \fIuser_name\fR"
Delete a user from the group membership list.
X.IP "\fB-l\fR"
List the group membership list.
X.IP "\fB-D\fR"
Delete all users from the group membership list.
X.IP "\fB-g \fIgroup_name\fR"
The superuser can specify which group membership list to modify.
X.SH SETUP
The \fBgroupmems\fR executable should be in mode \fB2770\fR as user \fBroot\fR
and in group \fBgroups\fR. The system administrator can add users to
group groups to allow or disallow them using the \fBgroupmems\fR utility
to manager their own group membership list.
X.P
X $ groupadd -r groups
X.br
X $ chmod 2770 groupmems
X.br
X $ chown root.groups groupmems
X.br
X $ groupmems -g groups -a gk4
X.SH FILES
/etc/group
X.br
/etc/gshadow
X.SH SEE ALSO
X.BR chfn (1),
X.BR chsh (1),
X.BR useradd (8),
X.BR userdel (8),
X.BR usermod (8),
X.BR passwd (1),
X.BR groupadd (8),
X.BR groupdel (8)
X.SH AUTHOR
George Kraft IV (gk4@us.ibm.com)
X.\" EOF
SHAR_EOF
(set 20 00 05 25 14 38 23 'groupmems.8'; eval "$shar_touch") &&
chmod 0600 'groupmems.8' ||
$echo 'restore of' 'groupmems.8' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'groupmems.8:' 'MD5 check failed'
181e6cd3a3c9d3df320197fa2cde2b4a groupmems.8
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'groupmems.8'`"
test 3372 -eq "$shar_count" ||
$echo 'groupmems.8:' 'original size' '3372,' 'current size' "$shar_count!"
fi
fi
rm -fr _sh10937
exit 0

View File

@@ -1,308 +0,0 @@
/*
* pwdauth.c - program to verify a given username/password pair.
*
* Run it with username in argv[1] (may be omitted - default is the
* current user), and send it the password over a pipe on stdin.
* Exit status: 0 - correct password, 1 - wrong password, >1 - other
* errors. For use with shadow passwords, this program should be
* installed setuid root.
*
* This can be used, for example, by xlock - you don't have to install
* this large and complex (== possibly insecure) program setuid root,
* just modify it to run this simple program to do the authentication.
*
* Recent versions (xlockmore-3.9) are cleaner, and drop privileges as
* soon as possible after getting the user's encrypted password.
* Using this program probably doesn't make it more secure, and has one
* disadvantage: since we don't get the encrypted user's password at
* startup (but at the time the user is authenticated), it is not clear
* how we should handle errors (like getpwnam() returning NULL).
* - fail the authentication? Problem: no way to unlock (other than kill
* the process from somewhere else) if the NIS server stops responding.
* - succeed and unlock? Problem: it's too easy to unlock by unplugging
* the box from the network and waiting until NIS times out...
*
* This program is Copyright (C) 1996 Marek Michalkiewicz
* <marekm@i17linuxb.ists.pwr.wroc.pl>.
*
* It may be used and distributed freely for any purposes. There is no
* warranty - use at your own risk. I am not liable for any damages etc.
* If you improve it, please send me your changes.
*/
static char rcsid[] = "$Id$";
/*
* Define USE_SYSLOG to use syslog() to log successful and failed
* authentication. This should be safe even if your system has
* the infamous syslog buffer overrun security problem...
*/
#define USE_SYSLOG
/*
* Define HAVE_GETSPNAM to get shadow passwords using getspnam().
* Some systems don't have getspnam(), but getpwnam() returns
* encrypted passwords only if running as root.
*
* According to the xlock source (not tested, except Linux) -
* define: Linux, Solaris 2.x, SVR4, ...
* undef: HP-UX with Secured Passwords, FreeBSD, NetBSD, QNX.
* Known not supported (yet): Ultrix, OSF/1, SCO.
*/
#define HAVE_GETSPNAM
/*
* Define HAVE_PW_ENCRYPT to use pw_encrypt() instead of crypt().
* pw_encrypt() is like the standard crypt(), except that it may
* support better password hashing algorithms.
*
* Define if linking with libshadow.a from the shadow password
* suite (Linux, SunOS 4.x?).
*/
#undef HAVE_PW_ENCRYPT
/*
* Define HAVE_AUTH_METHODS to support the shadow suite specific
* extension: the encrypted password field contains a list of
* administrator defined authentication methods, separated by
* semicolons. This program only supports the standard password
* authentication method (a string that doesn't start with '@').
*/
#undef HAVE_AUTH_METHODS
/*
* FAIL_DELAY - number of seconds to sleep before exiting if the
* password was wrong, to slow down password guessing attempts.
*/
#define FAIL_DELAY 2
/* No user-serviceable parts below :-). */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <pwd.h>
#ifdef USE_SYSLOG
#include <syslog.h>
#ifndef LOG_AUTHPRIV
#define LOG_AUTHPRIV LOG_AUTH
#endif
#endif
#ifdef HAVE_GETSPNAM
#include <shadow.h>
#endif
#ifdef HAVE_PW_ENCRYPT
extern char *pw_encrypt();
#define crypt pw_encrypt
#endif
/*
* Read the password (one line) from fp. We don't turn off echo
* because we expect input from a pipe.
*/
static char *
get_line(fp)
FILE *fp;
{
static char buf[128];
char *cp;
int ch;
cp = buf;
while ((ch = getc(fp)) != EOF && ch != '\0' && ch != '\n') {
if (cp >= buf + sizeof buf - 1)
break;
*cp++ = ch;
}
*cp = '\0';
return buf;
}
/*
* Get the password file entry for the current user. If the name
* returned by getlogin() is correct (matches the current real uid),
* return the entry for that user. Otherwise, return the entry (if
* any) matching the current real uid. Return NULL on failure.
*/
static struct passwd *
get_my_pwent()
{
uid_t uid = getuid();
char *name = getlogin();
if (name && *name) {
struct passwd *pw = getpwnam(name);
if (pw && pw->pw_uid == uid)
return pw;
}
return getpwuid(uid);
}
/*
* Verify the password. The system-dependent shadow support is here.
*/
static int
password_auth_ok(pw, pass)
const struct passwd *pw;
const char *pass;
{
int result;
char *cp;
#ifdef HAVE_AUTH_METHODS
char *buf;
#endif
#ifdef HAVE_GETSPNAM
struct spwd *sp;
#endif
if (pw) {
#ifdef HAVE_GETSPNAM
sp = getspnam(pw->pw_name);
if (sp)
cp = sp->sp_pwdp;
else
#endif
cp = pw->pw_passwd;
} else
cp = "xx";
#ifdef HAVE_AUTH_METHODS
buf = strdup(cp); /* will be modified by strtok() */
if (!buf) {
fprintf(stderr, "Out of memory.\n");
exit(13);
}
cp = strtok(buf, ";");
while (cp && *cp == '@')
cp = strtok(NULL, ";");
/* fail if no password authentication for this user */
if (!cp)
cp = "xx";
#endif
if (*pass || *cp)
result = (strcmp(crypt(pass, cp), cp) == 0);
else
result = 1; /* user with no password */
#ifdef HAVE_AUTH_METHODS
free(buf);
#endif
return result;
}
/*
* Main program.
*/
int
main(argc, argv)
int argc;
char **argv;
{
struct passwd *pw;
char *pass, *name;
char myname[32];
#ifdef USE_SYSLOG
openlog("pwdauth", LOG_PID | LOG_CONS, LOG_AUTHPRIV);
#endif
pw = get_my_pwent();
if (!pw) {
#ifdef USE_SYSLOG
syslog(LOG_ERR, "can't get login name for uid %d.\n",
(int) getuid());
#endif
fprintf(stderr, "Who are you?\n");
exit(2);
}
strncpy(myname, pw->pw_name, sizeof myname - 1);
myname[sizeof myname - 1] = '\0';
name = myname;
if (argc > 1) {
name = argv[1];
pw = getpwnam(name);
}
pass = get_line(stdin);
if (password_auth_ok(pw, pass)) {
#ifdef USE_SYSLOG
syslog(pw->pw_uid ? LOG_INFO : LOG_NOTICE,
"user `%s' entered correct password for `%.32s'.\n",
myname, name);
#endif
exit(0);
}
#ifdef USE_SYSLOG
/* be careful not to overrun the syslog buffer */
syslog((!pw || pw->pw_uid) ? LOG_NOTICE : LOG_WARNING,
"user `%s' entered incorrect password for `%.32s'.\n",
myname, name);
#endif
#ifdef FAIL_DELAY
sleep(FAIL_DELAY);
#endif
fprintf(stderr, "Wrong password.\n");
exit(1);
}
#if 0
/*
* You can use code similar to the following to run this program.
* Return values: >=0 - program exit status (use the <sys/wait.h>
* macros to get the exit code, it is shifted left by 8 bits),
* -1 - check errno.
*/
int
verify_password(const char *username, const char *password)
{
int pipe_fd[2];
int pid, wpid, status;
if (pipe(pipe_fd))
return -1;
if ((pid = fork()) == 0) {
char *arg[3];
char *env[1];
/* child */
close(pipe_fd[1]);
if (pipe_fd[0] != 0) {
if (dup2(pipe_fd[0], 0) != 0)
_exit(127);
close(pipe_fd[0]);
}
arg[0] = "/usr/bin/pwdauth";
arg[1] = username;
arg[2] = NULL;
env[0] = NULL;
execve(arg[0], arg, env);
_exit(127);
} else if (pid == -1) {
/* error */
close(pipe_fd[0]);
close(pipe_fd[1]);
return -1;
}
/* parent */
close(pipe_fd[0]);
write(pipe_fd[1], password, strlen(password));
write(pipe_fd[1], "\n", 1);
close(pipe_fd[1]);
while ((wpid = wait(&status)) != pid) {
if (wpid == -1)
return -1;
}
return status;
}
#endif

View File

@@ -1,147 +0,0 @@
Hello Marek,
I have created a diffile against the 980403 release that adds
functionality to newusers for automatic handling of users with only
anonymous ftp login (using the guestgroup feature in ftpaccess, which
means that the users home directory looks like '/home/user/./'). It also
adds a commandline argument to specify an initial directory structure
for such users, with a tarball normally containing the bin,lib,etc
directories used in the chrooted environment.
I am using it to automatically create chunks of users with only ftp
access for a webserver.
I have tried to follow your coding standards and I believe it is bug
free but.. well, who knows. :) It's not much code however.
I hope you find it useful. Do what you like with it, feel free to ask if
anything is unclear.
Best rgds,
Calle Karlsson
ckn@kash.se
diff -uNr shadow-980403.orig/src/newusers.c shadow-980403/src/newusers.c
--- shadow-980403.orig/src/newusers.c Fri Jan 30 00:22:43 1998
+++ shadow-980403/src/newusers.c Fri Apr 17 16:55:33 1998
@@ -76,11 +76,35 @@
static void
usage(void)
{
- fprintf(stderr, "Usage: %s [ input ]\n", Prog);
+ fprintf (stderr, "Usage: %s [-p prototype tarfile] [ input ]\n", Prog);
+ fprintf (stderr, "The prototype tarfile is only used for users\n");
+ fprintf (stderr, "marked as anonymous ftp users. It must be a full pathname.\n");
exit(1);
}
/*
+ * createuserdir - create a directory and chmod it
+ */
+
+static int
+createuserdir (char * dir, int uid, int gid, int line)
+{
+ if (mkdir (dir, 0777 & ~getdef_num("UMASK", 077))) {
+ fprintf (stderr, "%s: line %d: mkdir %s failed\n",
+ Prog, line, dir);
+ return -1;
+ }
+
+ if (chown (dir, uid, gid)) {
+ fprintf (stderr, "%s: line %d: chown %s failed\n",
+ Prog, line, dir);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
* add_group - create a new group or add a user to an existing group
*/
@@ -328,6 +352,8 @@
main(int argc, char **argv)
{
char buf[BUFSIZ];
+ char anonproto[BUFSIZ];
+ int flag;
char *fields[8];
int nfields;
char *cp;
@@ -340,12 +366,23 @@
Prog = Basename(argv[0]);
- if (argc > 1 && argv[1][0] == '-')
- usage ();
+ * anonproto = '\0';
+
+ while ((flag = getopt (argc, argv, "p:h")) != EOF) {
+ switch (flag) {
+ case 'p':
+ STRFCPY(anonproto, optarg);
+ break;
+ case 'h':
+ default:
+ usage ();
+ break;
+ }
+ }
- if (argc == 2) {
- if (! freopen (argv[1], "r", stdin)) {
- snprintf(buf, sizeof buf, "%s: %s", Prog, argv[1]);
+ if (optind < argc) {
+ if (! freopen (argv[optind], "r", stdin)) {
+ snprintf(buf, sizeof buf, "%s: %s", Prog, argv[optind]);
perror (buf);
exit (1);
}
@@ -499,15 +536,36 @@
if (fields[6][0])
newpw.pw_shell = fields[6];
- if (newpw.pw_dir[0] && access(newpw.pw_dir, F_OK)) {
- if (mkdir (newpw.pw_dir,
- 0777 & ~getdef_num("UMASK", 077)))
- fprintf (stderr, "%s: line %d: mkdir failed\n",
- Prog, line);
- else if (chown (newpw.pw_dir,
- newpw.pw_uid, newpw.pw_gid))
- fprintf (stderr, "%s: line %d: chown failed\n",
- Prog, line);
+ if (newpw.pw_dir[0]) {
+ char * userdir = strdup (newpw.pw_dir);
+ char * anonpart;
+ int rc;
+
+ if ((anonpart = strstr (userdir, "/./"))) {
+ * anonpart = '\0';
+ anonpart += 2;
+ }
+
+ if (access(userdir, F_OK))
+ rc = createuserdir (userdir, newpw.pw_uid, newpw.pw_gid, line);
+ else
+ rc = 0;
+
+ if (rc == 0 && anonpart) {
+ if (* anonproto) {
+ char cmdbuf [BUFSIZ];
+ snprintf(cmdbuf, sizeof cmdbuf,
+ "cd %s; tar xf %s",
+ userdir, anonproto);
+ system (cmdbuf);
+ }
+ if (strlen (anonpart) > 1) {
+ strcat (userdir, anonpart);
+ if (access (userdir, F_OK))
+ createuserdir (userdir, newpw.pw_uid, newpw.pw_gid, line);
+ }
+ }
+ free (userdir);
}
/*

Binary file not shown.

View File

@@ -1,5 +1,4 @@
# This is a dummy Makefile.am to get automake work flawlessly,
# and also cooperate to make a distribution for `make dist'
EXTRA_DIST = HOWTO README.limits \
README.platforms WISHLIST console.c.spec.txt cracklib26.diff
EXTRA_DIST = HOWTO README.limits

View File

@@ -1,33 +0,0 @@
# $Id$
#
# This is the current (still incomplete) list of platforms this
# package has been verified to work on. Additions (preferably
# in the format as described below) are welcome. Thanks!
#
# V: last version reported to work
# H: host type
# L: Linux libc version
# D: Linux distribution, or other OS name and version
# C: changes (if any)
# R: reported by
V: 980529
H: sparc-unknown-linux-gnu
L: glibc-2.0.7
D: Ultrapenguin-1.0.9
C: had to explicitly disable desrpc.
R: Bjorn Christianson <bjorn@cascade.psychology.mcmaster.ca>
V: 980724
H: i486-pc-linux-gnulibc1
L: libc-5.4.33
D: Debian-1.3.1.r6
C: none (use dpkg-buildpackage)
R: Marek Michalkiewicz <marekm@linux.org.pl>
V: current
H: i686-pc-linux-gnu
L: glibc-2.0.7.19981211
D: Debian-2.1
C: none (use dpkg-buildpackage)
R: Marek Michalkiewicz <marekm@linux.org.pl>

View File

@@ -1,39 +0,0 @@
$Id$
This is my wishlist for the shadow suite, in no particular order. Feel
free to do anything from this list and mail me the diffs :-).
Patches in diff -u format, against the latest version (sometimes in the
"beta" directory) are preferred and make my job easier. Please, no
MIME, base64, quoted-printable, or HTML. For very big patches, or if
your mailer can corrupt them, please use gzip and uuencode. Thanks!
New ideas to add to this list are welcome, too. --marekm
- fix all the bugs, of course
- implement "su only" accounts (no logins, only su from other account)
- rewrite getdef.c to be more general? (no hardcoded names)
- patch for rlogind/telnetd to create utmp entry and fill in ut_addr
- option to specify encrypted password in passwd (for yppasswdd, so it
doesn't need to know about shadow/non-shadow); should probably use a pipe
(less insecure than command line arguments)
- add support for changing NIS passwords
- add option to check passwords by piping them to external programs
- add functionality of the contrib/rpasswd.c wrapper to passwd
- option to generate pronounceable passwords (like on SCO), external program?
- poppassd (remote password change for eudora etc.)
- add support for passwd/shadow db files (glibc)
- vipw: check password files for errors after editing
- add "maximum time users allowed to stay logged in" limit option to logoutd
- handle quotes in /etc/environment like the shell does (but sshd doesn't...)
- better utmpx support (logoutd, ...)
- better OPIE support (report number of logins left, etc.)
- new option for /etc/suauth: don't load user's environment (force "su -")
suggested by Ulisses Alonso Camaro
- find out why recent releases won't compile on Solaris
- newusers should be able to copy /etc/skel to the new home directory
(like useradd)
- add directories where other packages can add hooks for package-specific
per-user configuration, to be executed with run-parts. Some hooks should
be executed at package install time for existing users, likewise for
package removal and possibly modification. (Debian Bug#36019)

View File

@@ -1,36 +0,0 @@
$Id$
Specification for console.c source file --
input values --
tty -- character pointer to device name with leading "/dev/"
removed.
return values --
0 -- false
1 -- true
int console (char * tty)
if "CONSOLE" string value is not present in login.defs
return true
if the first character of "CONSOLE" string value is not "/"
treat the string as a ":" delimited list of device
names and search for the value of tty in that
tokenized list.
if a match is found
return true
return false
if the file named by "CONSOLE" cannot be opened
return true
scan the file looking for a match between the input line
and the value of tty
if a match is found
return true
return false

View File

@@ -0,0 +1,73 @@
# Build & install
The following page explains how to build and install the shadow project.
Additional information on how to do this in a container environment is provided
at the end of the page.
## Local
### Dependency installation
This projects depends on other software packages that need to be installed
before building it. We recommend using the dependency installation commands
provided by the distributions to install them. Some examples below.
Debian:
```
apt-get build-dep shadow
```
Fedora:
```
dnf builddep shadow-utils
```
An alternative would be to take a look at the CI workflow [file](../../.github/workflows/runner.yml)
and get the package names from there. This has the advantage that it
also includes new dependencies needed for the development version
which might have not been present in the last release.
### Configure
The first step is to configure it. You can use the
`autogen.sh` script provided by the project. Example:
```
./autogen.sh --without-selinux --enable-man --with-yescrypt
```
### Build
The next step is to build the project:
```
make -j4
```
### Install
The last step is to install it. We recommend avoiding this step and using a
disposable system like a VM or a container instead.
```
make install
```
## Containers
Alternatively, you can use any of the preconfigured container images builders
to build and install shadow.
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
```
Or generate all of the images with the `container-build.sh` script, as if you
were running some of the CI checks locally:
```
share/container-build.sh
```

25
doc/contributions/ci.md Normal file
View File

@@ -0,0 +1,25 @@
# Continuous Integration (CI)
Shadow runs a CI workflow every time a pull-request (PR) is updated. This
workflow contains several checks to assure the quality of the project, and
only pull-requests with green results are merged.
## Build & install
The project is built & installed on Ubuntu, Alpine, Debian and Fedora. The last
three distributions are built & installed on containers, and the workflow can
be triggered locally by following the instructions specified in the
[Build & install](build_install.md#containers) page.
## System tests
The project is tested on Ubuntu. For that purpose it is built & installed in
this distribution in a VM. You can run this step locally by following the
instructions provided in the [Tests](tests.md#system-tests) page.
## Static code analysis
C and shell static code analysis is also executed. For that purpose
[CodeQL](https://codeql.github.com/) and
[Differential ShellCheck](https://github.com/marketplace/actions/differential-shellcheck)
are used.

View File

@@ -0,0 +1,12 @@
# Coding style
* For a general guidance refer to the
[Linux kernel coding style](https://www.kernel.org/doc/html/latest/process/coding-style.html)
* Patches that change the existing coding style are not welcome, as they make
downstream porting harder for the distributions
## Indentation
Tabs are preferred over spaces for indentation. Loading the `.editorconfig`
file in your preferred IDE may help you configure it.

View File

@@ -0,0 +1,77 @@
# Introduction
## Git and Github
We recommend you to get familiar with the
[git](https://guides.github.com/introduction/git-handbook) and
[Github](https://guides.github.com) workflows before posting any changes.
### Set up in a nut shell
The following steps describe the process in a nut shell to provide you a basic
template:
* Create an account on [GitHub](https://github.com)
* Fork the [shadow repository](https://github.com/shadow-maint/shadow)
* Clone the shadow repository
```
git clone https://github.com/shadow-maint/shadow.git
```
* Add your fork as an extra remote
```
git remote add $ghusername git@github.com:$ghusername/shadow.git
```
* Setup your name contact e-mail that you want to use for the development
```
git config user.name "John Smith"
git config user.email "john.smith@home.com"
```
**Note**: this will setup the user information only for this repository. You
can also add `--global` switch to the `git config` command to setup these
options globally and thus making them available in every git repository.
* Create a working branch
```
git checkout -b my-changes
```
* Commit changes
```
vim change-what-you-need
git commit -s
```
Check
[the kernel patches guide](https://www.kernel.org/doc/html/v4.14/process/submitting-patches.html#describe-your-changes)
to get an idea on how to write a good commit message.
* Push your changes to your GitHub repository
```
git push $ghusername my-changes --force
```
* Open a Pull Request against shadow project by clicking on the link provided
in the output of the previous step
* Make sure that all Continuous Integration checks are green and wait review
## Internal guidelines
Additionally, you should also check the following internal guidelines to
understand the project's development model:
* [Build & install](build_install.md)
* [Coding style](coding_style.md)
* [Tests](tests.md)
* [Continuous Integration](CI.md)
* [Releases](releases.md)
* [License](license.md)

View File

@@ -0,0 +1,10 @@
# License
All new source code committed to the shadow project is assumed to be made
available under the [BSD-3-Clause](../../COPYING) license unless the submitter
specifies another license at that time. The shadow maintainers reserve the
right to refuse a submission if the license is deemed incompatible with the
goals of the project.
**Note**: old code may be made available under another license, check the
license tag for each file to get additional information.

View File

@@ -0,0 +1,7 @@
# Releases
The shadow project doesn't follow any specific timeline to release new software
versions. Usually, they are released when a major milestone is finished.
Released source code, alongside the release notes, are provided in the
[release Github page](https://github.com/shadow-maint/shadow/releases).

View File

@@ -0,0 +1,34 @@
# Tests
Currently, shadow provides unit and system tests.
## Unit tests
Unit testing is provided by the [cmocka](https://cmocka.org/) framework. It's
recommended to read the
[basics](https://cmocka.org/talks/cmocka_unit_testing_and_mocking.pdf) and
[API](https://api.cmocka.org/) before writing any test case.
In addition, you can check [test_logind.c](../../tests/unit/test_logind.c) to
get a general idea on how to implement unit tests for shadow using cmocka.
You can execute unit tests by running:
```
make check
```
## System tests
These type of tests are written in shell. Unfortunately, the testing framework
is tightly coupled to the Ubuntu distribution and it can only be run in this
distribution. Besides, if anything fails during the execution the system can
be left in an unstable state. Taking that into account you shouldn't run this
workflow in your host machine, we recommend to use a disposable system like a
VM or a container instead.
You can execute system tests by running:
```
cd tests && ./run_all`.
```

View File

@@ -1,340 +0,0 @@
diff -ur orig/cracklib26_small/cracklib/fascist.c cracklib26_small/cracklib/fascist.c
--- orig/cracklib26_small/cracklib/fascist.c Mon Dec 15 02:56:55 1997
+++ cracklib26_small/cracklib/fascist.c Sat Apr 4 22:14:45 1998
@@ -12,6 +12,7 @@
#include <ctype.h>
#include <sys/types.h>
#include <pwd.h>
+#include <string.h>
#define ISSKIP(x) (isspace(x) || ispunct(x))
@@ -460,28 +461,27 @@
}
char *
-FascistGecos(password, uid)
+FascistGecosPw(password, pwd)
char *password;
- int uid;
+ struct passwd *pwd;
{
int i;
int j;
int wc;
char *ptr;
- struct passwd *pwp;
char gbuffer[STRINGSIZE];
char tbuffer[STRINGSIZE];
char *uwords[STRINGSIZE];
char longbuffer[STRINGSIZE * 2];
- if (!(pwp = getpwuid(uid)))
+ if (!pwd)
{
return ("you are not registered in the password file");
}
/* lets get really paranoid and assume a dangerously long gecos entry */
- strncpy(tbuffer, pwp->pw_name, STRINGSIZE);
+ strncpy(tbuffer, pwd->pw_name, STRINGSIZE);
tbuffer[STRINGSIZE-1] = '\0';
if (GTry(tbuffer, password))
{
@@ -490,12 +490,13 @@
/* it never used to be that you got passwd strings > 1024 chars, but now... */
- strncpy(tbuffer, pwp->pw_gecos, STRINGSIZE);
+ strncpy(tbuffer, pwd->pw_gecos, STRINGSIZE);
tbuffer[STRINGSIZE-1] = '\0';
strcpy(gbuffer, Lowercase(tbuffer));
wc = 0;
ptr = gbuffer;
+ uwords[0] = (char *) 0;
while (*ptr)
{
@@ -530,6 +531,8 @@
*(ptr++) = '\0';
}
}
+ if (!uwords[0])
+ return ((char *) 0); /* empty gecos */
#ifdef DEBUG
for (i = 0; uwords[i]; i++)
{
@@ -586,9 +589,10 @@
}
char *
-FascistLook(pwp, instring)
+FascistLookPw(pwp, instring, pwd)
PWDICT *pwp;
char *instring;
+ struct passwd *pwd;
{
int i;
char *ptr;
@@ -667,7 +671,7 @@
return ("it looks like a National Insurance number.");
}
- if (ptr = FascistGecos(password, getuid()))
+ if (ptr = FascistGecosPw(password, pwd ? pwd : getpwuid(getuid())))
{
return (ptr);
}
@@ -715,9 +719,10 @@
}
char *
-FascistCheck(password, path)
+FascistCheckPw(password, path, pwd)
char *password;
char *path;
+ struct passwd *pwd;
{
static char lastpath[STRINGSIZE];
static PWDICT *pwp;
@@ -750,5 +755,29 @@
strncpy(lastpath, path, STRINGSIZE);
}
- return (FascistLook(pwp, pwtrunced));
+ return (FascistLookPw(pwp, pwtrunced, pwd));
+}
+
+char *
+FascistGecos(password, uid)
+ char *password;
+ int uid;
+{
+ return (FascistGecosPw(password, getpwuid(uid)));
+}
+
+char *
+FascistLook(pwp, instring)
+ PWDICT *pwp;
+ char *instring;
+{
+ return (FascistLookPw(pwp, instring, (char *) 0));
+}
+
+char *
+FascistCheck(password, path)
+ char *password;
+ char *path;
+{
+ return (FascistCheckPw(password, path, (char *) 0));
}
diff -ur orig/cracklib26_small/cracklib/packer.h cracklib26_small/cracklib/packer.h
--- orig/cracklib26_small/cracklib/packer.h Mon Dec 15 00:09:30 1997
+++ cracklib26_small/cracklib/packer.h Sat Jan 10 22:13:46 1998
@@ -34,6 +34,7 @@
FILE *dfp;
FILE *wfp;
+ int canfree;
int32 flags;
#define PFOR_WRITE 0x0001
#define PFOR_FLUSH 0x0002
diff -ur orig/cracklib26_small/cracklib/packlib.c cracklib26_small/cracklib/packlib.c
--- orig/cracklib26_small/cracklib/packlib.c Fri Jul 9 22:22:58 1993
+++ cracklib26_small/cracklib/packlib.c Sat Jan 10 22:28:49 1998
@@ -16,7 +16,7 @@
char *mode;
{
int32 i;
- static PWDICT pdesc;
+ PWDICT *pdesc;
char iname[STRINGSIZE];
char dname[STRINGSIZE];
char wname[STRINGSIZE];
@@ -25,92 +25,94 @@
FILE *ifp;
FILE *wfp;
- if (pdesc.header.pih_magic == PIH_MAGIC)
- {
- fprintf(stderr, "%s: another dictionary already open\n", prefix);
+ if ((pdesc = (PWDICT *) malloc(sizeof(PWDICT))) == 0)
return ((PWDICT *) 0);
- }
- memset(&pdesc, '\0', sizeof(pdesc));
+ memset(pdesc, '\0', sizeof(*pdesc));
sprintf(iname, "%s.pwi", prefix);
sprintf(dname, "%s.pwd", prefix);
sprintf(wname, "%s.hwm", prefix);
- if (!(pdesc.dfp = fopen(dname, mode)))
+ if (!(pdesc->dfp = fopen(dname, mode)))
{
perror(dname);
+ free(pdesc);
return ((PWDICT *) 0);
}
- if (!(pdesc.ifp = fopen(iname, mode)))
+ if (!(pdesc->ifp = fopen(iname, mode)))
{
- fclose(pdesc.dfp);
+ fclose(pdesc->dfp);
perror(iname);
+ free(pdesc);
return ((PWDICT *) 0);
}
- if (pdesc.wfp = fopen(wname, mode))
+ if (pdesc->wfp = fopen(wname, mode))
{
- pdesc.flags |= PFOR_USEHWMS;
+ pdesc->flags |= PFOR_USEHWMS;
}
- ifp = pdesc.ifp;
- dfp = pdesc.dfp;
- wfp = pdesc.wfp;
+ ifp = pdesc->ifp;
+ dfp = pdesc->dfp;
+ wfp = pdesc->wfp;
if (mode[0] == 'w')
{
- pdesc.flags |= PFOR_WRITE;
- pdesc.header.pih_magic = PIH_MAGIC;
- pdesc.header.pih_blocklen = NUMWORDS;
- pdesc.header.pih_numwords = 0;
+ pdesc->flags |= PFOR_WRITE;
+ pdesc->header.pih_magic = PIH_MAGIC;
+ pdesc->header.pih_blocklen = NUMWORDS;
+ pdesc->header.pih_numwords = 0;
- fwrite((char *) &pdesc.header, sizeof(pdesc.header), 1, ifp);
+ fwrite((char *) &pdesc->header, sizeof(pdesc->header), 1, ifp);
} else
{
- pdesc.flags &= ~PFOR_WRITE;
+ pdesc->flags &= ~PFOR_WRITE;
- if (!fread((char *) &pdesc.header, sizeof(pdesc.header), 1, ifp))
+ if (!fread((char *) &pdesc->header, sizeof(pdesc->header), 1, ifp))
{
fprintf(stderr, "%s: error reading header\n", prefix);
- pdesc.header.pih_magic = 0;
+ pdesc->header.pih_magic = 0;
fclose(ifp);
fclose(dfp);
+ free(pdesc);
return ((PWDICT *) 0);
}
- if (pdesc.header.pih_magic != PIH_MAGIC)
+ if (pdesc->header.pih_magic != PIH_MAGIC)
{
fprintf(stderr, "%s: magic mismatch\n", prefix);
- pdesc.header.pih_magic = 0;
+ pdesc->header.pih_magic = 0;
fclose(ifp);
fclose(dfp);
+ free(pdesc);
return ((PWDICT *) 0);
}
- if (pdesc.header.pih_blocklen != NUMWORDS)
+ if (pdesc->header.pih_blocklen != NUMWORDS)
{
fprintf(stderr, "%s: size mismatch\n", prefix);
- pdesc.header.pih_magic = 0;
+ pdesc->header.pih_magic = 0;
fclose(ifp);
fclose(dfp);
+ free(pdesc);
return ((PWDICT *) 0);
}
- if (pdesc.flags & PFOR_USEHWMS)
+ if (pdesc->flags & PFOR_USEHWMS)
{
- if (fread(pdesc.hwms, 1, sizeof(pdesc.hwms), wfp) != sizeof(pdesc.hwms))
+ if (fread(pdesc->hwms, 1, sizeof(pdesc->hwms), wfp) != sizeof(pdesc->hwms))
{
- pdesc.flags &= ~PFOR_USEHWMS;
+ pdesc->flags &= ~PFOR_USEHWMS;
}
}
}
-
- return (&pdesc);
+ pdesc->canfree = 1;
+ return (pdesc);
}
int
@@ -159,8 +161,13 @@
fclose(pwp->ifp);
fclose(pwp->dfp);
+ if (pwp->wfp)
+ fclose(pwp->wfp);
- pwp->header.pih_magic = 0;
+ if (pwp->canfree)
+ free(pwp);
+ else
+ pwp->header.pih_magic = 0;
return (0);
}
@@ -307,6 +314,11 @@
register char *this;
int idx;
+/*
+ * comment in npasswd-2.0beta4 says this:
+ * This does not work under all circumstances, so don't bother
+ */
+#if 0
if (pwp->flags & PFOR_USEHWMS)
{
idx = string[0] & 0xff;
@@ -317,6 +329,10 @@
lwm = 0;
hwm = PW_WORDS(pwp) - 1;
}
+#else
+ lwm = 0;
+ hwm = PW_WORDS(pwp);
+#endif
#ifdef DEBUG
printf("---- %lu, %lu ----\n", lwm, hwm);
diff -ur orig/cracklib26_small/util/mkdict cracklib26_small/util/mkdict
--- orig/cracklib26_small/util/mkdict Fri Jul 9 22:23:03 1993
+++ cracklib26_small/util/mkdict Sat Apr 4 22:31:45 1998
@@ -14,9 +14,16 @@
SORT="sort"
###SORT="sort -T /tmp"
-cat $* |
+### Use zcat to read compressed (as well as uncompressed) dictionaries.
+### Compressed dictionaries can save quite a lot of disk space.
+
+CAT="gzip -cdf"
+###CAT="zcat"
+###CAT="cat"
+
+$CAT $* |
tr '[A-Z]' '[a-z]' |
- tr -cd '[\012a-z0-9]' |
+ tr -cd '\012[a-z][0-9]' |
$SORT |
uniq |
grep -v '^#' |

View File

@@ -1,15 +0,0 @@
<head>
<title>shadow - Welcome</title>
</head>
<body>
<h2> Welcome!</h2>
<p> This is the shadow tool suite home page. </p>
<p>
You can find releases <a href="https://github.com/shadow-maint/shadow/releases">here</a>.
</p>
<p>
Raise issues, request features, and report bugs <a href="https://github.com/shadow-maint/shadow/issues">here</a>.
</p>
</body>

View File

@@ -20,4 +20,4 @@ EXTRA_DIST = \
$(sysconf_DATA) \
$(default_DATA)
SUBDIRS = pam.d
SUBDIRS = pam.d shadow-maint

View File

@@ -227,11 +227,6 @@ PASS_WARN_AGE 7
#
SU_WHEEL_ONLY no
#
# If compiled with cracklib support, sets the path to the dictionaries
#
CRACKLIB_DICTPATH /var/cache/cracklib/cracklib_dict
#
# Min/max values for automatic uid selection in useradd(8)
#

View File

@@ -2,20 +2,20 @@
# and also cooperate to make a distribution for `make dist'
pamd_files = \
chpasswd \
chfn \
chsh \
groupmems \
login \
newusers \
passwd
pamd_acct_tools_files = \
chage \
chgpasswd \
chpasswd \
groupadd \
groupdel \
groupmod \
newusers \
useradd \
userdel \
usermod

View File

@@ -0,0 +1,5 @@
shadowmaint_files = \
groupdel-pre.d/01-kill_group_procs.sh \
userdel-pre.d/01-kill_user_procs.sh
EXTRA_DIST = $(shadowmaint_files)

View File

@@ -0,0 +1,26 @@
#!/bin/sh
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
GROUPID=`awk -F: '$1 == "'"${SUBJECT}"'" { print $3 }' /etc/group`
if [ "${GROUPID}" = "" ]; then
exit 0
fi
for status in /proc/*/status; do
# either this isn't a process or its already dead since expanding the list
[ -f "$status" ] || continue
tbuf=${status%/status}
pid=${tbuf#/proc/}
case "$pid" in
"$$") continue;;
[0-9]*) :;;
*) continue
esac
grep -q '^Groups:.*\b'"${GROUPID}"'\b.*' "/proc/$pid/status" || continue
kill -9 "$pid" || echo "cannot kill $pid" 1>&2
done

View File

@@ -4,14 +4,17 @@ PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# Check user exists, and if so, send sigkill to processes that the user owns
RUNNING=`ps -eo user | grep -Fx "$SUBJECT" | wc -l`
# if the user does not exist, RUNNING will be 0
if [ "${RUNNING}x" = "0x" ]; then
exit 0
ps -eo user >/dev/null 2>&1
if [ $? -eq 0 ]; then
RUNNING=`ps -eo user | grep -Fx "$SUBJECT" | wc -l`
# if the user does not exist, RUNNING will be 0
if [ "${RUNNING}x" = "0x" ]; then
exit 0
fi
fi
# If there is no ps -eo, traverse the process directly.
ls -1 /proc | while IFS= read -r PROC; do
echo "$PROC" | grep -E '^[0-9]+$' >/dev/null
if [ $? -ne 0 ]; then

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,58 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
wc44x8aaET0FtmmJmRfxzQSEkczkR4AM
=K+Fs
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -0,0 +1,185 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
=xU87
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -0,0 +1,147 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
=2CmL
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -5,57 +5,128 @@ DEFS =
noinst_LTLIBRARIES = libshadow.la
if USE_PAM
LIBCRYPT_PAM = $(LIBCRYPT)
else
LIBCRYPT_PAM =
endif
AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir) $(ECONF_CPPFLAGS)
libshadow_la_CPPFLAGS = $(ECONF_CPPFLAGS)
if HAVE_VENDORDIR
libshadow_la_CPPFLAGS += -DVENDORDIR=\"$(VENDORDIR)\"
endif
libshadow_la_CPPFLAGS += -I$(top_srcdir)
libshadow_la_CFLAGS = $(LIBBSD_CFLAGS) $(LIBCRYPT_PAM) $(LIBSYSTEMD)
libshadow_la_LIBADD = $(LIBADD_DLOPEN)
libshadow_la_SOURCES = \
addgrps.c \
adds.c \
adds.h \
age.c \
agetpass.c \
agetpass.h \
alloc.c \
alloc.h \
atoi/a2i.c \
atoi/a2i.h \
atoi/str2i.c \
atoi/str2i.h \
atoi/strtoi.c \
atoi/strtoi.h \
atoi/strtou_noneg.c \
atoi/strtou_noneg.h \
attr.h \
audit_help.c \
basename.c \
bit.c \
bit.h \
cast.h \
chkname.c \
chkname.h \
chowndir.c \
chowntty.c \
cleanup.c \
cleanup_group.c \
cleanup_user.c \
commonio.c \
commonio.h \
console.c \
copydir.c \
csrand.c \
defines.h \
encrypt.c \
env.c \
exitcodes.h \
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 \
getdef.c \
getdef.h \
get_gid.c \
getlong.c \
get_pid.c \
get_uid.c \
getulong.c \
getdate.h \
getdate.y \
getdef.c \
getdef.h \
getgr_nam_gid.c \
getrange.c \
gettime.c \
groupio.c \
groupmem.c \
groupio.h \
gshadow.c \
hushed.c \
idmapping.h \
idmapping.c \
isexpired.c \
limits.c \
list.c \
lockpw.c \
loginprompt.c \
mail.c \
memzero.c \
memzero.h \
motd.c \
must_be.h \
myname.c \
nss.c \
nscd.c \
nscd.h \
shadowlog.c \
shadowlog.h \
shadowlog_internal.h \
sssd.c \
sssd.h \
obscure.c \
pam_defs.h \
pam_pass.c \
pam_pass_non_interactive.c \
port.c \
port.h \
prefix_flag.c \
prototypes.h \
pwauth.c \
pwauth.h \
pwio.c \
pwio.h \
pwd_init.c \
pwd2spwd.c \
pwdcheck.c \
pwmem.c \
remove_tree.c \
root_flag.c \
run_part.h \
run_part.c \
subordinateio.h \
subordinateio.c \
salt.c \
selinux.c \
semanage.c \
setugid.c \
setupenv.c \
sgetgrent.c \
sgetpwent.c \
sgetspent.c \
@@ -64,14 +135,74 @@ libshadow_la_SOURCES = \
shadow.c \
shadowio.c \
shadowio.h \
shadowlog.c \
shadowlog.h \
shadowlog_internal.h \
shadowmem.c \
shell.c \
sizeof.h \
spawn.c \
utent.c
sssd.c \
sssd.h \
string/sprintf.c \
string/sprintf.h \
string/stpecpy.c \
string/stpecpy.h \
string/stpeprintf.c \
string/stpeprintf.h \
string/strftime.c \
string/strftime.h \
string/strncpy.h \
string/strtcpy.c \
string/strtcpy.h \
string/zustr2stp.h \
strtoday.c \
sub.c \
subordinateio.h \
subordinateio.c \
sulog.c \
time/day_to_str.c \
time/day_to_str.h \
ttytype.c \
tz.c \
ulimit.c \
user_busy.c \
valid.c \
write_full.c \
xgetpwnam.c \
xprefix_getpwnam.c \
xgetpwuid.c \
xgetgrnam.c \
xgetgrgid.c \
xgetspnam.c \
yesno.c
if WITH_TCB
libshadow_la_SOURCES += tcbfuncs.c tcbfuncs.h
endif
if WITH_BTRFS
libshadow_la_SOURCES += btrfs.c
endif
if ENABLE_LASTLOG
libshadow_la_SOURCES += log.c
endif
if ENABLE_LOGIND
libshadow_la_SOURCES += logind.c
else
libshadow_la_SOURCES += utmp.c
endif
if !WITH_LIBBSD
libshadow_la_SOURCES += \
freezero.h \
freezero.c \
readpassphrase.h \
readpassphrase.c
endif
# These files are unneeded for some reason, listed in
# order of appearance:
#
@@ -79,4 +210,5 @@ endif
EXTRA_DIST = \
.indent.pro \
gshadow_.h
gshadow_.h \
xgetXXbyYY.c

View File

@@ -17,6 +17,8 @@
#include <stdio.h>
#include <grp.h>
#include <errno.h>
#include "alloc.h"
#include "shadowlog.h"
#ident "$Id$"
@@ -29,7 +31,7 @@
*/
int add_groups (const char *list)
{
GETGROUPS_T *grouplist, *tmp;
GETGROUPS_T *grouplist;
size_t i;
int ngroups;
bool added;
@@ -46,7 +48,7 @@ int add_groups (const char *list)
i = 16;
for (;;) {
grouplist = (gid_t *) malloc (i * sizeof (GETGROUPS_T));
grouplist = MALLOC(i, GETGROUPS_T);
if (NULL == grouplist) {
return -1;
}
@@ -88,19 +90,17 @@ int add_groups (const char *list)
fputs (_("Warning: too many groups\n"), shadow_logfd);
break;
}
tmp = (gid_t *) realloc (grouplist, (size_t)(ngroups + 1) * sizeof (GETGROUPS_T));
if (NULL == tmp) {
free (grouplist);
grouplist = REALLOCF(grouplist, (size_t) ngroups + 1, GETGROUPS_T);
if (grouplist == NULL) {
return -1;
}
tmp[ngroups] = grp->gr_gid;
grouplist[ngroups] = grp->gr_gid;
ngroups++;
grouplist = tmp;
added = true;
}
if (added) {
ret = setgroups ((size_t)ngroups, grouplist);
ret = setgroups (ngroups, grouplist);
free (grouplist);
return ret;
}
@@ -109,6 +109,6 @@ int add_groups (const char *list)
return 0;
}
#else /* HAVE_SETGROUPS && !USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
extern int ISO_C_forbids_an_empty_translation_unit;
#endif /* HAVE_SETGROUPS && !USE_PAM */

15
lib/adds.c Normal file
View File

@@ -0,0 +1,15 @@
// SPDX-FileCopyrightText: 2023, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#include <config.h>
#include "adds.h"
#include <stddef.h>
extern inline long addsl2(long a, long b);
extern inline long addslN(size_t n, long addend[n]);
extern inline int cmpl(const void *p1, const void *p2);

86
lib/adds.h Normal file
View File

@@ -0,0 +1,86 @@
// SPDX-FileCopyrightText: 2023, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ADDS_H_
#define SHADOW_INCLUDE_LIB_ADDS_H_
#include <config.h>
#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include <stdlib.h>
#include "sizeof.h"
#define addsl(a, b, ...) \
({ \
long addend_[] = {a, b, __VA_ARGS__}; \
\
addslN(NITEMS(addend_), addend_); \
})
inline long addsl2(long a, long b);
inline long addslN(size_t n, long addend[n]);
inline int cmpl(const void *p1, const void *p2);
inline long
addsl2(long a, long b)
{
if (a > 0 && b > LONG_MAX - a) {
errno = EOVERFLOW;
return LONG_MAX;
}
if (a < 0 && b < LONG_MIN - a) {
errno = EOVERFLOW;
return LONG_MIN;
}
return a + b;
}
inline long
addslN(size_t n, long addend[n])
{
int e;
if (n == 0) {
errno = EDOM;
return 0;
}
e = errno;
while (n > 1) {
qsort(addend, n, sizeof(addend[0]), cmpl);
errno = 0;
addend[0] = addsl2(addend[0], addend[--n]);
if (errno == EOVERFLOW)
return addend[0];
}
errno = e;
return addend[0];
}
inline int
cmpl(const void *p1, const void *p2)
{
const long *l1 = p1;
const long *l2 = p2;
if (*l1 < *l2)
return -1;
if (*l1 > *l2)
return +1;
return 0;
}
#endif // include guard

View File

@@ -13,12 +13,15 @@
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include "prototypes.h"
#include "defines.h"
#include "exitcodes.h"
#include <pwd.h>
#include <grp.h>
#include "adds.h"
#include "defines.h"
#include "exitcodes.h"
#include "prototypes.h"
#ident "$Id$"
#ifndef PASSWD_PROGRAM
@@ -112,7 +115,7 @@ int expire (const struct passwd *pw, /*@null@*/const struct spwd *sp)
_exit (126);
}
(void) execl (PASSWD_PROGRAM, PASSWD_PROGRAM, pw->pw_name, (char *) 0);
(void) execl (PASSWD_PROGRAM, PASSWD_PROGRAM, pw->pw_name, (char *) NULL);
err = errno;
perror ("Can't execute " PASSWD_PROGRAM);
_exit ((ENOENT == err) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
@@ -139,7 +142,7 @@ int expire (const struct passwd *pw, /*@null@*/const struct spwd *sp)
void agecheck (/*@null@*/const struct spwd *sp)
{
long now = (long) time ((time_t *) 0) / SCALE;
long now = time(NULL) / DAY;
long remain;
if (NULL == sp) {
@@ -162,9 +165,9 @@ void agecheck (/*@null@*/const struct spwd *sp)
return;
}
remain = sp->sp_lstchg + sp->sp_max - now;
remain = addsl(sp->sp_lstchg, sp->sp_max, -now);
if (remain <= sp->sp_warn) {
remain /= DAY / SCALE;
if (remain > 1) {
(void) printf (_("Your password will expire in %ld days.\n"),
remain);

145
lib/agetpass.c Normal file
View File

@@ -0,0 +1,145 @@
/*
* SPDX-FileCopyrightText: 2022, Alejandro Colomar <alx@kernel.org>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <config.h>
#include "agetpass.h"
#include <limits.h>
#include <readpassphrase.h>
#include <stdlib.h>
#include <string.h>
#ident "$Id$"
#include "alloc.h"
#if WITH_LIBBSD == 0
#include "freezero.h"
#endif /* WITH_LIBBSD */
/*
* SYNOPSIS
* [[gnu::malloc(erase_pass)]]
* char *agetpass(const char *prompt);
* char *agetpass_stdin();
*
* void erase_pass(char *pass);
*
* ARGUMENTS
* agetpass()
* prompt String to be printed before reading a password.
*
* erase_pass()
* pass password previously returned by agetpass().
*
* DESCRIPTION
* agetpass()
* This function is very similar to getpass(3). It has several
* advantages compared to getpass(3):
*
* - Instead of using a static buffer, agetpass() allocates memory
* through malloc(3). This makes the function thread-safe, and
* also reduces the visibility of the buffer.
*
* - agetpass() doesn't reallocate internally. Some
* implementations of getpass(3), such as glibc, do that, as a
* consequence of calling getline(3). That's a bug in glibc,
* which allows leaking prefixes of passwords in freed memory.
*
* - agetpass() doesn't overrun the output buffer. If the input
* password is too long, it simply fails. Some implementations
* of getpass(3), share the same bug that gets(3) has.
*
* As soon as possible, the password obtained from agetpass() be
* erased by calling erase_pass(), to avoid possibly leaking the
* password.
*
* agetpass_stdin()
* This function is the same as previous one (agetpass). Just the
* password is read from stdin and terminal is not required.
*
* erase_pass()
* This function first clears the password, by calling
* explicit_bzero(3) (or an equivalent call), and then frees the
* allocated memory by calling free(3).
*
* NULL is a valid input pointer, and in such a case, this call is
* a no-op.
*
* RETURN VALUE
* agetpass() returns a newly allocated buffer containing the
* password on success. On error, errno is set to indicate the
* error, and NULL is returned.
*
* ERRORS
* agetpass()
* This function may fail for any errors that malloc(3) or
* readpassphrase(3) may fail, and in addition it may fail for the
* following errors:
*
* ENOBUFS
* The input password was longer than PASS_MAX.
*
* CAVEATS
* If a password is passed twice to erase_pass(), the behavior is
* undefined.
*/
static char *
agetpass_internal(const char *prompt, int flags)
{
char *pass;
size_t len;
/*
* Since we want to support passwords upto PASS_MAX, we need
* PASS_MAX bytes for the password itself, and one more byte for
* the terminating '\0'. We also want to detect truncation, and
* readpassphrase(3) doesn't detect it, so we need some trick.
* Let's add one more byte, and if the password uses it, it
* means the introduced password was longer than PASS_MAX.
*/
pass = MALLOC(PASS_MAX + 2, char);
if (pass == NULL)
return NULL;
if (readpassphrase(prompt, pass, PASS_MAX + 2, flags) == NULL)
goto fail;
len = strlen(pass);
if (len == PASS_MAX + 1) {
errno = ENOBUFS;
goto fail;
}
return pass;
fail:
freezero(pass, PASS_MAX + 2);
return NULL;
}
char *
agetpass(const char *prompt)
{
return agetpass_internal(prompt, RPP_REQUIRE_TTY);
}
char *
agetpass_stdin()
{
return agetpass_internal(NULL, RPP_STDIN);
}
void
erase_pass(char *pass)
{
freezero(pass, PASS_MAX + 2);
}

23
lib/agetpass.h Normal file
View File

@@ -0,0 +1,23 @@
/*
* SPDX-FileCopyrightText: 2022-2023, Alejandro Colomar <alx@kernel.org>
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef SHADOW_INCLUDE_LIB_AGETPASS_H_
#define SHADOW_INCLUDE_LIB_AGETPASS_H_
#include <config.h>
#include "attr.h"
#include "defines.h"
void erase_pass(char *pass);
ATTR_MALLOC(erase_pass)
char *agetpass(const char *prompt);
char *agetpass_stdin();
#endif // include guard

View File

@@ -3,6 +3,7 @@
* 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
*/
@@ -11,7 +12,7 @@
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 */
@@ -20,34 +21,53 @@
#ident "$Id$"
#include <stdio.h>
#include "alloc.h"
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include "defines.h"
#include "prototypes.h"
#include "shadowlog.h"
/*@maynotreturn@*/ /*@only@*//*@out@*//*@notnull@*/void *xmalloc (size_t size)
{
void *ptr;
ptr = malloc (size);
if (NULL == ptr) {
(void) fprintf (log_get_logfd(),
_("%s: failed to allocate memory: %s\n"),
log_get_progname(), strerror (errno));
exit (13);
}
return ptr;
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);
}
/*@maynotreturn@*/ /*@only@*//*@notnull@*/char *xstrdup (const char *str)
{
return strcpy (xmalloc (strlen (str) + 1), str);
}
void xfree(void *ap)
void *
xreallocarray(void *p, size_t nmemb, size_t size)
{
if (ap) {
free(ap);
}
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);
}

101
lib/alloc.h Normal file
View File

@@ -0,0 +1,101 @@
// 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"
#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) \
( \
_Generic(ptr, type *: (type *) reallocarray(ptr, n, sizeof(type))) \
)
#define REALLOCF(ptr, n, type) \
( \
_Generic(ptr, type *: (type *) reallocarrayf(ptr, n, sizeof(type))) \
)
#define XREALLOC(ptr, n, type) \
( \
_Generic(ptr, type *: (type *) xreallocarray(ptr, 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

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

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

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

@@ -0,0 +1,386 @@
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_H_
#define SHADOW_INCLUDE_LIB_ATOI_A2I_H_
#include <config.h>
#include <errno.h>
#include "atoi/strtoi.h"
#include "atoi/strtou_noneg.h"
#include "attr.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__) \
)
#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__) \
)
#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__) \
)
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);
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);
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);
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
a2sh_c(short *restrict n, const char *s,
const char **restrict endp, int base, short min, short max)
{
return a2sh(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(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(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(n, (char *) s, (char **) endp, base, min, 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(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(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(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(n, (char *) s, (char **) endp, base, min, 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;
}
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

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

@@ -0,0 +1,18 @@
// 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.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);
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);

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

@@ -0,0 +1,108 @@
// 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_H_
#define SHADOW_INCLUDE_LIB_ATOI_STR2I_H_
#include <config.h>
#include <limits.h>
#include <stddef.h>
#include "atoi/a2i.h"
#include "attr.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__) \
)
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);
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
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);
}
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

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

@@ -0,0 +1,15 @@
// 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);

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

@@ -0,0 +1,96 @@
// 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/strtou_noneg.c Normal file
View File

@@ -0,0 +1,13 @@
// 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);

39
lib/atoi/strtou_noneg.h Normal file
View File

@@ -0,0 +1,39 @@
// 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 <stddef.h>
#include <stdint.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);
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

33
lib/attr.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef SHADOW_INCLUDE_LIB_ATTR_H_
#define SHADOW_INCLUDE_LIB_ATTR_H_
#include "config.h"
#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__)))
#else
# define MAYBE_UNUSED
# define NORETURN
# define format_attr(type, fmt, va)
# define ATTR_ACCESS(...)
#endif
#if (__GNUC__ >= 11) && !defined(__clang__)
# define ATTR_MALLOC(deallocator) [[gnu::malloc(deallocator)]]
#else
# define ATTR_MALLOC(deallocator)
#endif
#if (__GNUC__ >= 14)
# define ATTR_STRING(...) [[gnu::null_terminated_string_arg(__VA_ARGS__)]]
#else
# define ATTR_STRING(...)
#endif
#endif // include guard

View File

@@ -21,6 +21,8 @@
#include <libaudit.h>
#include <errno.h>
#include <stdio.h>
#include "attr.h"
#include "prototypes.h"
#include "shadowlog.h"
int audit_fd;
@@ -54,7 +56,7 @@ void audit_help_open (void)
* id - uid or gid that the operation is being performed on. This is used
* only when user is NULL.
*/
void audit_logger (int type, unused const char *pgname, const char *op,
void audit_logger (int type, MAYBE_UNUSED const char *pgname, const char *op,
const char *name, unsigned int id,
shadow_audit_result result)
{
@@ -62,7 +64,7 @@ void audit_logger (int type, unused const char *pgname, const char *op,
return;
} else {
audit_log_acct_message (audit_fd, type, NULL, op, name, id,
NULL, NULL, NULL, (int) result);
NULL, NULL, NULL, result);
}
}
@@ -77,11 +79,11 @@ void audit_logger_message (const char *message, shadow_audit_result result)
NULL, /* hostname */
NULL, /* addr */
NULL, /* tty */
(int) result);
result);
}
}
#else /* WITH_AUDIT */
extern int errno; /* warning: ANSI C forbids an empty source file */
extern int ISO_C_forbids_an_empty_translation_unit;
#endif /* WITH_AUDIT */

View File

@@ -21,6 +21,10 @@
#include "prototypes.h"
/*@observer@*/const char *Basename (const char *str)
{
if (str == NULL) {
abort ();
}
char *cp = strrchr (str, '/');
return (NULL != cp) ? cp + 1 : str;

19
lib/bit.c Normal file
View File

@@ -0,0 +1,19 @@
/*
* SPDX-FileCopyrightText: 2022 - 2023, Alejandro Colomar <alx@kernel.org>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <config.h>
#ident "$Id$"
#include "bit.h"
#include <limits.h>
extern inline unsigned long bit_ceilul(unsigned long x);
extern inline unsigned long bit_ceil_wrapul(unsigned long x);
extern inline int leading_zerosul(unsigned long x);

53
lib/bit.h Normal file
View File

@@ -0,0 +1,53 @@
/*
* SPDX-FileCopyrightText: 2022 - 2023, Alejandro Colomar <alx@kernel.org>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef SHADOW_INCLUDE_LIB_BIT_H_
#define SHADOW_INCLUDE_LIB_BIT_H_
#include <config.h>
#include <limits.h>
#ifndef ULONG_WIDTH
#define ULONG_WIDTH (sizeof(unsigned long) * CHAR_BIT)
#endif
inline unsigned long bit_ceilul(unsigned long x);
inline unsigned long bit_ceil_wrapul(unsigned long x);
inline int leading_zerosul(unsigned long x);
/* stdc_bit_ceilul(3) */
inline unsigned long
bit_ceilul(unsigned long x)
{
return 1 + (ULONG_MAX >> leading_zerosul(x));
}
/* stdc_bit_ceilul(3), but wrap instead of having Undefined Behavior */
inline unsigned long
bit_ceil_wrapul(unsigned long x)
{
if (x == 0)
return 0;
return bit_ceilul(x);
}
/* stdc_leading_zerosul(3) */
inline int
leading_zerosul(unsigned long x)
{
return (x == 0) ? ULONG_WIDTH : __builtin_clzl(x);
}
#endif // include guard

View File

@@ -39,7 +39,7 @@ static int run_btrfs_subvolume_cmd(const char *subcmd, const char *arg1, const c
NULL
};
if (access(cmd, X_OK)) {
if (!cmd || access(cmd, X_OK)) {
return 1;
}

15
lib/cast.h Normal file
View File

@@ -0,0 +1,15 @@
// SPDX-FileCopyrightText: 2022-2024, Alejandro Colomar <alx@kernel.org>
// SPDX-License-Identifier: BSD-3-Clause
#ifndef SHADOW_INCLUDE_LIB_CAST_H_
#define SHADOW_INCLUDE_LIB_CAST_H_
#include <config.h>
#define const_cast(T, p) _Generic(p, const T: (T) (p))
#endif // include guard

120
lib/chkname.c Normal file
View File

@@ -0,0 +1,120 @@
// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh
// SPDX-FileCopyrightText: 1996-2000, Marek Michałkiewicz
// SPDX-FileCopyrightText: 2001-2005, Tomasz Kłoczko
// SPDX-FileCopyrightText: 2005-2008, Nicolas François
// 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
*/
#include <config.h>
#ident "$Id$"
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
#include <unistd.h>
#include "defines.h"
#include "chkname.h"
int allow_bad_names = false;
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 conf;
}
static bool is_valid_name (const char *name)
{
if (allow_bad_names) {
return true;
}
/*
* User/group names must match BRE regex:
* [a-zA-Z0-9_.][a-zA-Z0-9_.-]*$\?
*
* as a non-POSIX, extension, allow "$" as the last char for
* sake of Samba 3.x "add machine script"
*
* Also do not allow fully numeric names or just "." or "..".
*/
int numeric;
if ('\0' == *name ||
('.' == *name && (('.' == name[1] && '\0' == name[2]) ||
'\0' == name[1])) ||
!((*name >= 'a' && *name <= 'z') ||
(*name >= 'A' && *name <= 'Z') ||
(*name >= '0' && *name <= '9') ||
*name == '_' ||
*name == '.')) {
return false;
}
numeric = isdigit(*name);
while ('\0' != *++name) {
if (!((*name >= 'a' && *name <= 'z') ||
(*name >= 'A' && *name <= 'Z') ||
(*name >= '0' && *name <= '9') ||
*name == '_' ||
*name == '.' ||
*name == '-' ||
(*name == '$' && name[1] == '\0')
)) {
return false;
}
numeric &= isdigit(*name);
}
return !numeric;
}
bool
is_valid_user_name(const char *name)
{
if (strlen(name) >= login_name_max_size())
return false;
return is_valid_name(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)) {
return false;
}
return is_valid_name (name);
}

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

@@ -51,7 +51,7 @@ void chown_tty (const struct passwd *info)
*/
if ( (fchown (STDIN_FILENO, info->pw_uid, gid) != 0)
|| (fchmod (STDIN_FILENO, (mode_t)getdef_num ("TTYPERM", 0600)) != 0)) {
|| (fchmod (STDIN_FILENO, getdef_num ("TTYPERM", 0600)) != 0)) {
int err = errno;
FILE *shadow_logfd = log_get_logfd();

View File

@@ -9,6 +9,7 @@
#include <assert.h>
#include <stdio.h>
#include "attr.h"
#include "defines.h"
#include "groupio.h"
#include "sgroupio.h"
@@ -22,7 +23,7 @@
*/
void cleanup_report_add_group (void *group_name)
{
const char *name = (const char *)group_name;
const char *name = group_name;
SYSLOG ((LOG_ERR, "failed to add group %s", name));
#ifdef WITH_AUDIT
@@ -40,7 +41,7 @@ void cleanup_report_add_group (void *group_name)
*/
void cleanup_report_del_group (void *group_name)
{
const char *name = (const char *)group_name;
const char *name = group_name;
SYSLOG ((LOG_ERR, "failed to remove group %s", name));
#ifdef WITH_AUDIT
@@ -95,7 +96,7 @@ void cleanup_report_mod_gshadow (void *cleanup_info)
*/
void cleanup_report_add_group_group (void *group_name)
{
const char *name = (const char *)group_name;
const char *name = group_name;
SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, gr_dbname ()));
#ifdef WITH_AUDIT
@@ -115,7 +116,7 @@ void cleanup_report_add_group_group (void *group_name)
*/
void cleanup_report_add_group_gshadow (void *group_name)
{
const char *name = (const char *)group_name;
const char *name = group_name;
SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, sgr_dbname ()));
#ifdef WITH_AUDIT
@@ -136,7 +137,7 @@ void cleanup_report_add_group_gshadow (void *group_name)
*/
void cleanup_report_del_group_group (void *group_name)
{
const char *name = (const char *)group_name;
const char *name = group_name;
SYSLOG ((LOG_ERR,
"failed to remove group %s from %s",
@@ -159,7 +160,7 @@ void cleanup_report_del_group_group (void *group_name)
*/
void cleanup_report_del_group_gshadow (void *group_name)
{
const char *name = (const char *)group_name;
const char *name = group_name;
SYSLOG ((LOG_ERR,
"failed to remove group %s from %s",
@@ -178,7 +179,7 @@ void cleanup_report_del_group_gshadow (void *group_name)
*
* It should be registered after the group file is successfully locked.
*/
void cleanup_unlock_group (unused void *arg)
void cleanup_unlock_group (MAYBE_UNUSED void *arg)
{
if (gr_unlock () == 0) {
fprintf (log_get_logfd(),
@@ -198,7 +199,7 @@ void cleanup_unlock_group (unused void *arg)
*
* It should be registered after the gshadow file is successfully locked.
*/
void cleanup_unlock_gshadow (unused void *arg)
void cleanup_unlock_gshadow (MAYBE_UNUSED void *arg)
{
if (sgr_unlock () == 0) {
fprintf (log_get_logfd(),

View File

@@ -9,6 +9,7 @@
#include <assert.h>
#include <stdio.h>
#include "attr.h"
#include "defines.h"
#include "pwio.h"
#include "shadowio.h"
@@ -16,13 +17,13 @@
#include "shadowlog.h"
/*
* cleanup_report_add_user - Report failure to add an user to the system
* cleanup_report_add_user - Report failure to add a user to the system
*
* It should be registered when it is decided to add an user to the system.
* It should be registered when it is decided to add a user to the system.
*/
void cleanup_report_add_user (void *user_name)
{
const char *name = (const char *)user_name;
const char *name = user_name;
SYSLOG ((LOG_ERR, "failed to add user %s", name));
#ifdef WITH_AUDIT
@@ -51,15 +52,15 @@ void cleanup_report_mod_passwd (void *cleanup_info)
}
/*
* cleanup_report_add_user_passwd - Report failure to add an user to
* cleanup_report_add_user_passwd - Report failure to add a user to
* /etc/passwd
*
* It should be registered when it is decided to add an user to the
* It should be registered when it is decided to add a user to the
* /etc/passwd database.
*/
void cleanup_report_add_user_passwd (void *user_name)
{
const char *name = (const char *)user_name;
const char *name = user_name;
SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, pw_dbname ()));
#ifdef WITH_AUDIT
@@ -71,15 +72,15 @@ void cleanup_report_add_user_passwd (void *user_name)
}
/*
* cleanup_report_add_user_shadow - Report failure to add an user to
* cleanup_report_add_user_shadow - Report failure to add a user to
* /etc/shadow
*
* It should be registered when it is decided to add an user to the
* It should be registered when it is decided to add a user to the
* /etc/shadow database.
*/
void cleanup_report_add_user_shadow (void *user_name)
{
const char *name = (const char *)user_name;
const char *name = user_name;
SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, spw_dbname ()));
#ifdef WITH_AUDIT
@@ -95,7 +96,7 @@ void cleanup_report_add_user_shadow (void *user_name)
*
* It should be registered after the passwd database is successfully locked.
*/
void cleanup_unlock_passwd (unused void *arg)
void cleanup_unlock_passwd (MAYBE_UNUSED void *arg)
{
if (pw_unlock () == 0) {
fprintf (log_get_logfd(),
@@ -114,7 +115,7 @@ void cleanup_unlock_passwd (unused void *arg)
*
* It should be registered after the shadow database is successfully locked.
*/
void cleanup_unlock_shadow (unused void *arg)
void cleanup_unlock_shadow (MAYBE_UNUSED void *arg)
{
if (spw_unlock () == 0) {
fprintf (log_get_logfd(),

View File

@@ -21,6 +21,9 @@
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include "alloc.h"
#include "memzero.h"
#include "nscd.h"
#include "sssd.h"
#ifdef WITH_TCB
@@ -29,10 +32,12 @@
#include "prototypes.h"
#include "commonio.h"
#include "shadowlog_internal.h"
#include "string/sprintf.h"
/* local function prototypes */
static int lrename (const char *, const char *);
static int check_link_count (const char *file);
static int check_link_count (const char *file, bool log);
static int do_lock_file (const char *file, const char *lock, bool log);
static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
const char *name,
@@ -85,23 +90,31 @@ int lrename (const char *old, const char *new)
res = rename (old, new);
#ifdef __GLIBC__
if (NULL != r) {
free (r);
}
free (r);
#endif /* __GLIBC__ */
return res;
}
static int check_link_count (const char *file)
static int check_link_count (const char *file, bool log)
{
struct stat sb;
if (stat (file, &sb) != 0) {
if (log) {
(void) fprintf (shadow_logfd,
"%s: %s file stat error: %s\n",
shadow_progname, file, strerror (errno));
}
return 0;
}
if (sb.st_nlink != 2) {
if (log) {
fprintf(shadow_logfd,
"%s: %s: lock file already used (nlink: %ju)\n",
shadow_progname, file, (uintmax_t) sb.st_nlink);
}
return 0;
}
@@ -111,11 +124,11 @@ static int check_link_count (const char *file)
static int do_lock_file (const char *file, const char *lock, bool log)
{
int fd;
pid_t pid;
ssize_t len;
int retval;
char buf[32];
int fd;
int retval;
char buf[32];
pid_t pid;
ssize_t len;
fd = open (file, O_CREAT | O_TRUNC | O_WRONLY, 0600);
if (-1 == fd) {
@@ -128,9 +141,9 @@ static int do_lock_file (const char *file, const char *lock, bool log)
}
pid = getpid ();
snprintf (buf, sizeof buf, "%lu", (unsigned long) pid);
SNPRINTF(buf, "%lu", (unsigned long) pid);
len = (ssize_t) strlen (buf) + 1;
if (write (fd, buf, (size_t) len) != len) {
if (write_full(fd, buf, len) == -1) {
if (log) {
(void) fprintf (shadow_logfd,
"%s: %s file write error: %s\n",
@@ -153,12 +166,7 @@ static int do_lock_file (const char *file, const char *lock, bool log)
close (fd);
if (link (file, lock) == 0) {
retval = check_link_count (file);
if ((0==retval) && log) {
(void) fprintf (shadow_logfd,
"%s: %s: lock file already used\n",
shadow_progname, file);
}
retval = check_link_count (file, log);
unlink (file);
return retval;
}
@@ -187,7 +195,7 @@ static int do_lock_file (const char *file, const char *lock, bool log)
return 0;
}
buf[len] = '\0';
if (get_pid (buf, &pid) == 0) {
if (get_pid(buf, &pid) == -1) {
if (log) {
(void) fprintf (shadow_logfd,
"%s: existing lock file %s with an invalid PID '%s'\n",
@@ -219,12 +227,7 @@ static int do_lock_file (const char *file, const char *lock, bool log)
retval = 0;
if (link (file, lock) == 0) {
retval = check_link_count (file);
if ((0==retval) && log) {
(void) fprintf (shadow_logfd,
"%s: %s: lock file already used\n",
shadow_progname, file);
}
retval = check_link_count (file, log);
} else {
if (log) {
(void) fprintf (shadow_logfd,
@@ -253,25 +256,13 @@ static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
return NULL;
}
#ifdef HAVE_FCHOWN
if (fchown (fileno (fp), sb->st_uid, sb->st_gid) != 0) {
goto fail;
}
#else /* !HAVE_FCHOWN */
if (chown (name, sb->st_mode) != 0) {
goto fail;
}
#endif /* !HAVE_FCHOWN */
#ifdef HAVE_FCHMOD
if (fchmod (fileno (fp), sb->st_mode & 0664) != 0) {
goto fail;
}
#else /* !HAVE_FCHMOD */
if (chmod (name, sb->st_mode & 0664) != 0) {
goto fail;
}
#endif /* !HAVE_FCHMOD */
return fp;
fail:
@@ -337,9 +328,7 @@ static void free_linked_list (struct commonio_db *db)
p = db->head;
db->head = p->next;
if (NULL != p->line) {
free (p->line);
}
free (p->line);
if (NULL != p->eptr) {
db->ops->free (p->eptr);
@@ -353,7 +342,7 @@ static void free_linked_list (struct commonio_db *db)
int commonio_setname (struct commonio_db *db, const char *name)
{
snprintf (db->filename, sizeof (db->filename), "%s", name);
SNPRINTF(db->filename, "%s", name);
db->setname = true;
return 1;
}
@@ -367,38 +356,28 @@ bool commonio_present (const struct commonio_db *db)
int commonio_lock_nowait (struct commonio_db *db, bool log)
{
char* file = NULL;
char* lock = NULL;
size_t lock_file_len;
size_t file_len;
int err = 0;
int err = 0;
char *file = NULL;
char *lock = NULL;
if (db->locked) {
return 1;
}
file_len = strlen(db->filename) + 11;/* %lu max size */
lock_file_len = strlen(db->filename) + 6; /* sizeof ".lock" */
file = (char*)malloc(file_len);
if (file == NULL) {
if (asprintf(&file, "%s.%ju", db->filename, (uintmax_t) getpid()) == -1)
goto cleanup_ENOMEM;
}
lock = (char*)malloc(lock_file_len);
if (lock == NULL) {
if (asprintf(&lock, "%s.lock", db->filename) == -1)
goto cleanup_ENOMEM;
}
snprintf (file, file_len, "%s.%lu",
db->filename, (unsigned long) getpid ());
snprintf (lock, lock_file_len, "%s.lock", db->filename);
if (do_lock_file (file, lock, log) != 0) {
db->locked = true;
lock_count++;
err = 1;
}
cleanup_ENOMEM:
if (file)
free(file);
if (lock)
free(lock);
free(file);
free(lock);
return err;
}
@@ -489,7 +468,7 @@ static void dec_lock_count (void)
int commonio_unlock (struct commonio_db *db)
{
char lock[1024];
char lock[1029];
if (db->isopen) {
db->readonly = true;
@@ -506,7 +485,7 @@ int commonio_unlock (struct commonio_db *db)
* then call ulckpwdf() (if used) on last unlock.
*/
db->locked = false;
snprintf (lock, sizeof lock, "%s.lock", db->filename);
SNPRINTF(lock, "%s.lock", db->filename);
unlink (lock);
dec_lock_count ();
return 1;
@@ -624,7 +603,7 @@ int commonio_open (struct commonio_db *db, int mode)
fd = open (db->filename,
(db->readonly ? O_RDONLY : O_RDWR)
| O_NOCTTY | O_NONBLOCK | O_NOFOLLOW);
| O_NOCTTY | O_NONBLOCK | O_NOFOLLOW | O_CLOEXEC);
saved_errno = errno;
db->fp = NULL;
if (fd >= 0) {
@@ -655,22 +634,19 @@ int commonio_open (struct commonio_db *db, int mode)
return 0;
}
/* Do not inherit fd in spawned processes (e.g. nscd) */
fcntl (fileno (db->fp), F_SETFD, FD_CLOEXEC);
buflen = BUFLEN;
buf = (char *) malloc (buflen);
buf = MALLOC(buflen, char);
if (NULL == buf) {
goto cleanup_ENOMEM;
}
while (db->ops->fgets (buf, (int) buflen, db->fp) == buf) {
while ( ((cp = strrchr (buf, '\n')) == NULL)
while (db->ops->fgets (buf, buflen, db->fp) == buf) {
while ( (strrchr (buf, '\n') == NULL)
&& (feof (db->fp) == 0)) {
size_t len;
buflen += BUFLEN;
cp = (char *) realloc (buf, buflen);
cp = REALLOC(buf, buflen, char);
if (NULL == cp) {
goto cleanup_buf;
}
@@ -704,7 +680,7 @@ int commonio_open (struct commonio_db *db, int mode)
}
}
p = (struct commonio_entry *) malloc (sizeof *p);
p = MALLOC(1, struct commonio_entry);
if (NULL == p) {
goto cleanup_entry;
}
@@ -781,7 +757,7 @@ commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
return 0;
}
entries = malloc (n * sizeof (struct commonio_entry *));
entries = MALLOC(n, struct commonio_entry *);
if (entries == NULL) {
return -1;
}
@@ -918,9 +894,9 @@ static int write_all (const struct commonio_db *db)
int commonio_close (struct commonio_db *db)
{
char buf[1024];
int errors = 0;
struct stat sb;
int errors = 0;
char buf[1024];
struct stat sb;
if (!db->isopen) {
errno = EINVAL;
@@ -951,7 +927,11 @@ int commonio_close (struct commonio_db *db)
/*
* Create backup file.
*/
snprintf (buf, sizeof buf, "%s-", db->filename);
if (SNPRINTF(buf, "%s-", db->filename) == -1) {
(void) fclose (db->fp);
db->fp = NULL;
goto fail;
}
#ifdef WITH_SELINUX
if (set_selinux_file_context (db->filename, S_IFREG) != 0) {
@@ -966,15 +946,15 @@ int commonio_close (struct commonio_db *db)
errors++;
}
db->fp = NULL;
#ifdef WITH_SELINUX
if (reset_selinux_file_context () != 0) {
errors++;
}
#endif
if (errors != 0) {
db->fp = NULL;
if (errors != 0)
goto fail;
}
} else {
/*
* Default permissions for new [g]shadow files.
@@ -984,7 +964,8 @@ int commonio_close (struct commonio_db *db)
sb.st_gid = db->st_gid;
}
snprintf (buf, sizeof buf, "%s+", db->filename);
if (SNPRINTF(buf, "%s+", db->filename) == -1)
goto fail;
#ifdef WITH_SELINUX
if (set_selinux_file_context (db->filename, S_IFREG) != 0) {
@@ -1004,13 +985,11 @@ int commonio_close (struct commonio_db *db)
if (fflush (db->fp) != 0) {
errors++;
}
#ifdef HAVE_FSYNC
if (fsync (fileno (db->fp)) != 0) {
errors++;
}
#else /* !HAVE_FSYNC */
sync ();
#endif /* !HAVE_FSYNC */
if (fclose (db->fp) != 0) {
errors++;
}
@@ -1102,7 +1081,7 @@ int commonio_update (struct commonio_db *db, const void *eptr)
return 1;
}
/* not found, new entry */
p = (struct commonio_entry *) malloc (sizeof *p);
p = MALLOC(1, struct commonio_entry);
if (NULL == p) {
db->ops->free (nentry);
errno = ENOMEM;
@@ -1139,7 +1118,7 @@ int commonio_append (struct commonio_db *db, const void *eptr)
return 0;
}
/* new entry */
p = (struct commonio_entry *) malloc (sizeof *p);
p = MALLOC(1, struct commonio_entry);
if (NULL == p) {
db->ops->free (nentry);
errno = ENOMEM;
@@ -1200,14 +1179,14 @@ int commonio_remove (struct commonio_db *db, const char *name)
commonio_del_entry (db, p);
if (NULL != p->line) {
free (p->line);
}
free (p->line);
if (NULL != p->eptr) {
db->ops->free (p->eptr);
}
free(p);
return 1;
}

View File

@@ -11,8 +11,11 @@
#ifndef COMMONIO_H
#define COMMONIO_H
#include "attr.h"
#include "defines.h" /* bool */
/*
* Linked list entry.
*/
@@ -37,7 +40,7 @@ struct commonio_ops {
/*
* free() the object including any strings pointed by it.
*/
void (*free) (/*@out@*/ /*@only@*/void *);
void (*free)(/*@only@*/void *);
/*
* Return the name of the object (for example, pw_name
@@ -61,7 +64,9 @@ struct commonio_ops {
* fgets and fputs (can be replaced by versions that
* understand line continuation conventions).
*/
/*@null@*/char *(*fgets) (/*@returned@*/ /*@out@*/char *s, int n, FILE *stream);
ATTR_ACCESS(write_only, 1, 2)
/*@null@*/char *(*fgets)(/*@returned@*/char *restrict s, int n,
FILE *restrict stream);
int (*fputs) (const char *, FILE *);
/*
@@ -123,6 +128,7 @@ extern int commonio_setname (struct commonio_db *, const char *);
extern bool commonio_present (const struct commonio_db *db);
extern int commonio_lock (struct commonio_db *);
extern int commonio_lock_nowait (struct commonio_db *, bool log);
extern int do_fcntl_lock (const char *file, bool log, short type);
extern int commonio_open (struct commonio_db *, int);
extern /*@observer@*/ /*@null@*/const void *commonio_locate (struct commonio_db *, const char *);
extern int commonio_update (struct commonio_db *, const void *);

View File

@@ -13,6 +13,7 @@
#include <stdio.h>
#include "getdef.h"
#include "prototypes.h"
#include "string/strtcpy.h"
#ident "$Id$"
@@ -44,8 +45,7 @@ static bool is_listed (const char *cfgin, const char *tty, bool def)
if (*cons != '/') {
char *pbuf;
strncpy (buf, cons, sizeof (buf));
buf[sizeof (buf) - 1] = '\0';
STRTCPY(buf, cons);
pbuf = &buf[0];
while ((s = strtok (pbuf, ":")) != NULL) {
if (strcmp (s, tty) == 0) {
@@ -71,8 +71,9 @@ static bool is_listed (const char *cfgin, const char *tty, bool def)
* See if this tty is listed in the console file.
*/
while (fgets (buf, (int) sizeof (buf), fp) != NULL) {
buf[strlen (buf) - 1] = '\0';
while (fgets (buf, sizeof (buf), fp) != NULL) {
/* Remove optional trailing '\n'. */
buf[strcspn (buf, "\n")] = '\0';
if (strcmp (buf, tty) == 0) {
(void) fclose (fp);
return true;

View File

@@ -17,6 +17,9 @@
#include <sys/time.h>
#include <fcntl.h>
#include <stdio.h>
#include "alloc.h"
#include "attr.h"
#include "prototypes.h"
#include "defines.h"
#ifdef WITH_SELINUX
@@ -33,6 +36,7 @@
#include <attr/libattr.h>
#endif /* WITH_ATTR */
#include "shadowlog.h"
#include "string/sprintf.h"
static /*@null@*/const char *src_orig;
@@ -64,12 +68,12 @@ static int copy_dir (const struct path_info *src, const struct path_info *dst,
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,
unused bool reset_selinux,
MAYBE_UNUSED bool reset_selinux,
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 int copy_hardlink (const struct path_info *dst,
unused bool reset_selinux,
MAYBE_UNUSED bool reset_selinux,
struct link_name *lp);
static int copy_special (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
@@ -93,7 +97,7 @@ static int fchown_if_needed (int fdst, const struct stat *statp,
* error_acl - format the error messages for the ACL and EQ libraries.
*/
format_attr(printf, 2, 3)
static void error_acl (unused struct error_context *ctx, const char *fmt, ...)
static void error_acl (MAYBE_UNUSED struct error_context *ctx, const char *fmt, ...)
{
va_list ap;
FILE *shadow_logfd = log_get_logfd();
@@ -126,12 +130,12 @@ static int perm_copy_path(const struct path_info *src,
{
int src_fd, dst_fd, ret;
src_fd = openat(src->dirfd, src->name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
src_fd = openat(src->dirfd, src->name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
if (src_fd < 0) {
return -1;
}
dst_fd = openat(dst->dirfd, dst->name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
dst_fd = openat(dst->dirfd, dst->name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
if (dst_fd < 0) {
(void) close (src_fd);
return -1;
@@ -152,12 +156,12 @@ static int attr_copy_path(const struct path_info *src,
{
int src_fd, dst_fd, ret;
src_fd = openat(src->dirfd, src->name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
src_fd = openat(src->dirfd, src->name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
if (src_fd < 0) {
return -1;
}
dst_fd = openat(dst->dirfd, dst->name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
dst_fd = openat(dst->dirfd, dst->name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
if (dst_fd < 0) {
(void) close (src_fd);
return -1;
@@ -206,11 +210,7 @@ static void remove_link (/*@only@*/struct link_name *ln)
static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, const struct stat *sb)
{
struct link_name *lp;
size_t src_len;
size_t dst_len;
size_t name_len;
size_t len;
struct link_name *lp;
/* copy_tree () must be the entry point */
assert (NULL != src_orig);
@@ -226,16 +226,11 @@ static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, c
return NULL;
}
lp = (struct link_name *) xmalloc (sizeof *lp);
src_len = strlen (src_orig);
dst_len = strlen (dst_orig);
name_len = strlen (name);
lp = XMALLOC(1, struct link_name);
lp->ln_dev = sb->st_dev;
lp->ln_ino = sb->st_ino;
lp->ln_count = sb->st_nlink;
len = name_len - src_len + dst_len + 1;
lp->ln_name = (char *) xmalloc (len);
(void) snprintf (lp->ln_name, len, "%s%s", dst_orig, name + src_len);
xasprintf(&lp->ln_name, "%s%s", dst_orig, name + strlen(src_orig));
lp->ln_next = links;
links = lp;
@@ -312,55 +307,43 @@ static int copy_tree_impl (const struct path_info *src, const struct path_info *
set_orig = true;
}
while ((0 == err) && (ent = readdir (dir)) != NULL) {
char *src_name = NULL;
char *dst_name;
struct path_info src_entry, dst_entry;
/*
* Skip the "." and ".." entries
*/
if ((strcmp (ent->d_name, ".") != 0) &&
(strcmp (ent->d_name, "..") != 0)) {
char *src_name;
char *dst_name;
size_t src_len = strlen (ent->d_name) + 2;
size_t dst_len = strlen (ent->d_name) + 2;
src_len += strlen (src->full_path);
dst_len += strlen (dst->full_path);
src_name = (char *) malloc (src_len);
dst_name = (char *) malloc (dst_len);
if ((NULL == src_name) || (NULL == dst_name)) {
err = -1;
} else {
/*
* Build the filename for both the source and
* the destination files.
*/
struct path_info src_entry, dst_entry;
(void) snprintf (src_name, src_len, "%s/%s",
src->full_path, ent->d_name);
(void) snprintf (dst_name, dst_len, "%s/%s",
dst->full_path, ent->d_name);
src_entry.full_path = src_name;
src_entry.dirfd = dirfd(dir);
src_entry.name = ent->d_name;
dst_entry.full_path = dst_name;
dst_entry.dirfd = dst_fd;
dst_entry.name = ent->d_name;
err = copy_entry (&src_entry, &dst_entry,
reset_selinux,
old_uid, new_uid,
old_gid, new_gid);
}
if (NULL != src_name) {
free (src_name);
}
if (NULL != dst_name) {
free (dst_name);
}
if (strcmp(ent->d_name, ".") == 0 ||
strcmp(ent->d_name, "..") == 0)
{
continue;
}
if (asprintf(&src_name, "%s/%s", src->full_path, ent->d_name) == -1)
{
err = -1;
continue;
}
if (asprintf(&dst_name, "%s/%s", dst->full_path, ent->d_name) == -1)
{
err = -1;
goto skip;
}
src_entry.full_path = src_name;
src_entry.dirfd = dirfd(dir);
src_entry.name = ent->d_name;
dst_entry.full_path = dst_name;
dst_entry.dirfd = dst_fd;
dst_entry.name = ent->d_name;
err = copy_entry(&src_entry, &dst_entry, reset_selinux,
old_uid, new_uid, old_gid, new_gid);
free(dst_name);
skip:
free(src_name);
}
(void) closedir (dir);
(void) close (dst_fd);
@@ -417,78 +400,70 @@ 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];
if (fstatat(src->dirfd, src->name, &sb, AT_SYMLINK_NOFOLLOW) == -1) {
/* If we cannot stat the file, do not care. */
} else {
#ifdef HAVE_STRUCT_STAT_ST_ATIM
mt[0].tv_sec = sb.st_atim.tv_sec;
mt[0].tv_nsec = sb.st_atim.tv_nsec;
#else /* !HAVE_STRUCT_STAT_ST_ATIM */
mt[0].tv_sec = sb.st_atime;
# ifdef HAVE_STRUCT_STAT_ST_ATIMENSEC
mt[0].tv_nsec = sb.st_atimensec;
# else /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */
mt[0].tv_nsec = 0;
# endif /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */
#endif /* !HAVE_STRUCT_STAT_ST_ATIM */
return 0;
}
#ifdef HAVE_STRUCT_STAT_ST_MTIM
mt[1].tv_sec = sb.st_mtim.tv_sec;
mt[1].tv_nsec = sb.st_mtim.tv_nsec;
#else /* !HAVE_STRUCT_STAT_ST_MTIM */
mt[1].tv_sec = sb.st_mtime;
# ifdef HAVE_STRUCT_STAT_ST_MTIMENSEC
mt[1].tv_nsec = sb.st_mtimensec;
# else /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */
mt[1].tv_nsec = 0;
# endif /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */
#endif /* !HAVE_STRUCT_STAT_ST_MTIM */
mt[0].tv_sec = sb.st_atim.tv_sec;
mt[0].tv_nsec = sb.st_atim.tv_nsec;
if (S_ISDIR (sb.st_mode)) {
err = copy_dir (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
mt[1].tv_sec = sb.st_mtim.tv_sec;
mt[1].tv_nsec = sb.st_mtim.tv_nsec;
/*
* Copy any symbolic links
*/
if (S_ISDIR (sb.st_mode)) {
err = copy_dir (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
else if (S_ISLNK (sb.st_mode)) {
err = copy_symlink (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
/*
* 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, &tmp_sb, AT_SYMLINK_NOFOLLOW) != -1) {
return err;
}
/*
* See if this is a previously copied link
*/
/*
* Copy any symbolic links
*/
else if ((lp = check_link (src->full_path, &sb)) != NULL) {
err = copy_hardlink (dst, reset_selinux, lp);
}
else if (S_ISLNK (sb.st_mode)) {
err = copy_symlink (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
/*
* Deal with FIFOs and special files. The user really
* shouldn't have any of these, but it seems like it
* would be nice to copy everything ...
*/
/*
* See if this is a previously copied link
*/
else if (!S_ISREG (sb.st_mode)) {
err = copy_special (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
else if ((lp = check_link (src->full_path, &sb)) != NULL) {
err = copy_hardlink (dst, reset_selinux, lp);
}
/*
* Create the new file and copy the contents. The new
* file will be owned by the provided UID and GID values.
*/
/*
* Deal with FIFOs and special files. The user really
* shouldn't have any of these, but it seems like it
* would be nice to copy everything ...
*/
else {
err = copy_file (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
else if (!S_ISREG (sb.st_mode)) {
err = copy_special (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
/*
* Create the new file and copy the contents. The new
* file will be owned by the provided UID and GID values.
*/
else {
err = copy_file (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
}
return err;
@@ -511,6 +486,7 @@ static int copy_dir (const struct path_info *src, const struct path_info *dst,
gid_t old_gid, gid_t new_gid)
{
int err = 0;
struct stat dst_sb;
/*
* Create a new target directory, make it owned by
@@ -522,15 +498,23 @@ static int copy_dir (const struct path_info *src, const struct path_info *dst,
return -1;
}
#endif /* WITH_SELINUX */
if ( (mkdirat (dst->dirfd, dst->name, statp->st_mode) != 0)
/*
* If the destination is already a directory, don't change it
* but copy into it (recursively).
*/
if (fstatat(dst->dirfd, dst->name, &dst_sb, AT_SYMLINK_NOFOLLOW) == 0 && S_ISDIR(dst_sb.st_mode)) {
return (copy_tree_impl (src, dst, false, reset_selinux,
old_uid, new_uid, old_gid, new_gid) != 0);
}
if ( (mkdirat (dst->dirfd, dst->name, 0700) != 0)
|| (chownat_if_needed (dst, statp,
old_uid, new_uid, old_gid, new_gid) != 0)
|| (fchmodat (dst->dirfd, dst->name, statp->st_mode & 07777, AT_SYMLINK_NOFOLLOW) != 0)
#ifdef WITH_ACL
|| ( (perm_copy_path (src, dst, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
|| (chmod (dst, statp->st_mode) != 0)
#endif /* !WITH_ACL */
#endif /* WITH_ACL */
#ifdef WITH_ATTR
/*
* If the third parameter is NULL, all extended attributes
@@ -564,7 +548,7 @@ static /*@null@*/char *readlink_malloc (const char *filename)
while (true) {
ssize_t nchars;
char *buffer = (char *) malloc (size);
char *buffer = MALLOC(size, char);
if (NULL == buffer) {
return NULL;
}
@@ -599,7 +583,7 @@ static /*@null@*/char *readlink_malloc (const char *filename)
* Return 0 on success, -1 on error.
*/
static int copy_symlink (const struct path_info *src, const struct path_info *dst,
unused bool reset_selinux,
MAYBE_UNUSED bool reset_selinux,
const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
@@ -627,13 +611,11 @@ static int copy_symlink (const struct path_info *src, const struct path_info *ds
* create a link to the corresponding entry in the dst_orig
* directory.
*/
if (strncmp (oldlink, src_orig, strlen (src_orig)) == 0) {
size_t len = strlen (dst_orig) + strlen (oldlink) - strlen (src_orig) + 1;
char *dummy = (char *) xmalloc (len);
(void) snprintf (dummy, len, "%s%s",
dst_orig,
oldlink + strlen (src_orig));
free (oldlink);
if (strncmp(oldlink, src_orig, strlen(src_orig)) == 0) {
char *dummy;
xasprintf(&dummy, "%s%s", dst_orig, oldlink + strlen(src_orig));
free(oldlink);
oldlink = dummy;
}
@@ -673,7 +655,7 @@ static int copy_symlink (const struct path_info *src, const struct path_info *ds
* Return 0 on success, -1 on error.
*/
static int copy_hardlink (const struct path_info *dst,
unused bool reset_selinux,
MAYBE_UNUSED bool reset_selinux,
struct link_name *lp)
{
/* FIXME: selinux, ACL, Extended Attributes needed? */
@@ -692,6 +674,7 @@ static int copy_hardlink (const struct path_info *dst,
return 0;
}
/*
* copy_special - copy a special file
*
@@ -702,30 +685,33 @@ static int copy_hardlink (const struct path_info *dst,
*
* Return 0 on success, -1 on error.
*/
static int copy_special (const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
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 int
copy_special(const struct path_info *src, const struct path_info *dst,
bool reset_selinux,
const struct stat *statp, const struct timespec mt[],
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{
int err = 0;
#ifdef WITH_SELINUX
if (set_selinux_file_context (dst->full_path, statp->st_mode & S_IFMT) != 0) {
#if defined(WITH_SELINUX)
if (set_selinux_file_context(dst->full_path, statp->st_mode & S_IFMT) != 0)
return -1;
}
#endif /* WITH_SELINUX */
#endif
if ( (mknodat (dst->dirfd, dst->name, statp->st_mode & ~07777U, statp->st_rdev) != 0)
|| (chownat_if_needed (dst, statp,
old_uid, new_uid, old_gid, new_gid) != 0)
#ifdef WITH_ACL
|| ( (perm_copy_path (src, dst, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
|| (fchmodat (dst->dirfd, dst->name, statp->st_mode & 07777, AT_SYMLINK_NOFOLLOW) != 0)
#endif /* !WITH_ACL */
#ifdef WITH_ATTR
if (mknodat(dst->dirfd, dst->name, statp->st_mode & ~07777U, statp->st_rdev) == -1)
return -1;
if (chownat_if_needed(dst, statp, old_uid, new_uid, old_gid, new_gid) == -1)
return -1;
if (fchmodat(dst->dirfd, dst->name, statp->st_mode & 07777, AT_SYMLINK_NOFOLLOW) == -1)
return -1;
#if defined(WITH_ACL)
if (perm_copy_path(src, dst, &ctx) == -1 && errno != 0)
return -1;
#endif
#if defined(WITH_ATTR)
/*
* If the third parameter is NULL, all extended attributes
* except those that define Access Control Lists are copied.
@@ -733,51 +719,16 @@ static int copy_special (const struct path_info *src, const struct path_info *ds
* file systems with and without ACL support needs some
* additional logic so that no unexpected permissions result.
*/
|| ( !reset_selinux
&& (attr_copy_path (src, dst, NULL, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ATTR */
|| (utimensat (dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) != 0)) {
err = -1;
if (!reset_selinux) {
if (attr_copy_path(src, dst, NULL, &ctx) == -1 && errno != 0)
return -1;
}
#endif
return err;
}
if (utimensat(dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) == -1)
return -1;
/*
* full_write - write entire buffer
*
* Write up to count bytes from the buffer starting at buf to the
* file referred to by the file descriptor fd.
* Retry in case of a short write.
*
* Returns the number of bytes written on success, -1 on error.
*/
static ssize_t full_write(int fd, const void *buf, size_t count) {
ssize_t written = 0;
while (count > 0) {
ssize_t res;
res = write(fd, buf, count);
if (res < 0) {
if (errno == EINTR) {
continue;
}
return res;
}
if (res == 0) {
break;
}
written += res;
buf = (const unsigned char*)buf + res;
count -= (size_t)res;
}
return written;
return 0;
}
/*
@@ -810,16 +761,15 @@ static int copy_file (const struct path_info *src, const struct path_info *dst,
return -1;
}
#endif /* WITH_SELINUX */
ofd = openat (dst->dirfd, dst->name, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC | O_NOFOLLOW | O_CLOEXEC, statp->st_mode & 07777);
ofd = openat (dst->dirfd, dst->name, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC | O_NOFOLLOW | O_CLOEXEC, 0600);
if ( (ofd < 0)
|| (fchown_if_needed (ofd, statp,
old_uid, new_uid, old_gid, new_gid) != 0)
|| (fchmod (ofd, statp->st_mode & 07777) != 0)
#ifdef WITH_ACL
|| ( (perm_copy_fd (src->full_path, ifd, dst->full_path, ofd, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
|| (fchmod (ofd, statp->st_mode & 07777) != 0)
#endif /* !WITH_ACL */
#endif /* WITH_ACL */
#ifdef WITH_ATTR
/*
* If the third parameter is NULL, all extended attributes
@@ -857,7 +807,7 @@ static int copy_file (const struct path_info *src, const struct path_info *dst,
break;
}
if (full_write (ofd, buf, (size_t)cnt) < 0) {
if (write_full(ofd, buf, cnt) == -1) {
(void) close (ofd);
(void) close (ifd);
return -1;
@@ -865,7 +815,7 @@ static int copy_file (const struct path_info *src, const struct path_info *dst,
}
(void) close (ifd);
if (close (ofd) != 0) {
if (close (ofd) != 0 && errno != EINTR) {
return -1;
}

142
lib/csrand.c Normal file
View File

@@ -0,0 +1,142 @@
/*
* SPDX-FileCopyrightText: Alejandro Colomar <alx@kernel.org>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <config.h>
#ident "$Id$"
#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"
#include "shadowlog.h"
#include "sizeof.h"
static uint32_t csrand_uniform32(uint32_t n);
static unsigned long csrand_uniform_slow(unsigned long n);
/*
* Return a uniformly-distributed CS random u_long value.
*/
unsigned long
csrand(void)
{
FILE *fp;
unsigned long r;
#ifdef HAVE_GETENTROPY
/* getentropy may exist but lack kernel support. */
if (getentropy(&r, sizeof(r)) == 0)
return r;
#endif
#ifdef HAVE_GETRANDOM
/* Likewise getrandom. */
if (getrandom(&r, sizeof(r), 0) == sizeof(r))
return r;
#endif
#ifdef HAVE_ARC4RANDOM_BUF
/* arc4random_buf can never fail. */
arc4random_buf(&r, sizeof(r));
return r;
#endif
/* Use /dev/urandom as a last resort. */
fp = fopen("/dev/urandom", "r");
if (NULL == fp) {
goto fail;
}
if (fread(&r, sizeof(r), 1, fp) != 1) {
fclose(fp);
goto fail;
}
fclose(fp);
return r;
fail:
fprintf(log_get_logfd(), _("Unable to obtain random bytes.\n"));
exit(1);
}
/*
* Return a uniformly-distributed CS random value in the interval [0, n-1].
*/
unsigned long
csrand_uniform(unsigned long n)
{
if (n == 0 || n > UINT32_MAX)
return csrand_uniform_slow(n);
return csrand_uniform32(n);
}
/*
* Return a uniformly-distributed CS random value in the interval [min, max].
*/
unsigned long
csrand_interval(unsigned long min, unsigned long max)
{
return csrand_uniform(max - min + 1) + min;
}
/*
* Fast Random Integer Generation in an Interval
* ACM Transactions on Modeling and Computer Simulation 29 (1), 2019
* <https://arxiv.org/abs/1805.10941>
*/
static uint32_t
csrand_uniform32(uint32_t n)
{
uint32_t bound, rem;
uint64_t r, mult;
if (n == 0)
return csrand();
bound = -n % n; // analogous to `2^32 % n`, since `x % y == (x-y) % y`
do {
r = csrand();
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
r = mult >> WIDTHOF(n); // analogous to `mult / 2^32`
return r;
}
static unsigned long
csrand_uniform_slow(unsigned long n)
{
unsigned long r, max, mask;
max = n - 1;
mask = bit_ceil_wrapul(n) - 1;
do {
r = csrand();
r &= mask; // optimization
} while (r > max); // p = ((mask+1) % n) / (mask+1); W.C.: p=0.5
return r;
}

View File

@@ -6,41 +6,8 @@
#include "config.h"
#if HAVE_STDBOOL_H
# include <stdbool.h>
#else
# if ! HAVE__BOOL
# ifdef __cplusplus
typedef bool _Bool;
# else
typedef unsigned char _Bool;
# endif
# endif
# define bool _Bool
# define false (0)
# define true (1)
# define __bool_true_false_are_defined 1
#endif
/* Take care of NLS matters. */
#ifdef S_SPLINT_S
extern char *setlocale(int categories, const char *locale);
# define LC_ALL (6)
extern char * bindtextdomain (const char * domainname, const char * dirname);
extern char * textdomain (const char * domainname);
# define _(Text) Text
# define ngettext(Msgid1, Msgid2, N) \
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
#else
#ifdef HAVE_LOCALE_H
# include <locale.h>
#else
# undef setlocale
# define setlocale(category, locale) (NULL)
# ifndef LC_ALL
# define LC_ALL 6
# endif
#endif
#include <stdbool.h>
#include <locale.h>
#define gettext_noop(String) (String)
/* #define gettext_def(String) "#define String" */
@@ -57,22 +24,18 @@ extern char * textdomain (const char * domainname);
# define ngettext(Msgid1, Msgid2, N) \
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
#endif
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if HAVE_ERRNO_H
# include <errno.h>
#endif
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <unistd.h>
/*
* crypt(3), crypt_gensalt(3), and their
@@ -85,22 +48,6 @@ extern char * textdomain (const char * domainname);
#include <sys/time.h>
#include <time.h>
#ifdef HAVE_MEMSET_S
# define memzero(ptr, size) memset_s((ptr), 0, (size))
#elif defined HAVE_EXPLICIT_BZERO /* !HAVE_MEMSET_S */
# define memzero(ptr, size) explicit_bzero((ptr), (size))
#else /* !HAVE_MEMSET_S && HAVE_EXPLICIT_BZERO */
static inline void memzero(void *ptr, size_t size)
{
volatile unsigned char * volatile p = ptr;
while (size--) {
*p++ = '\0';
}
}
#endif /* !HAVE_MEMSET_S && !HAVE_EXPLICIT_BZERO */
#define strzero(s) memzero(s, strlen(s)) /* warning: evaluates twice */
#include <dirent.h>
/*
@@ -123,7 +70,6 @@ static inline void memzero(void *ptr, size_t size)
#endif
#endif
#ifdef USE_SYSLOG
#include <syslog.h>
#ifndef LOG_WARN
@@ -170,14 +116,6 @@ static inline void memzero(void *ptr, size_t size)
#define SYSLOG(x) syslog x
#endif /* !ENABLE_NLS */
#else /* !USE_SYSLOG */
#define SYSLOG(x) /* empty */
#define openlog(a,b,c) /* empty */
#define closelog() /* empty */
#endif /* !USE_SYSLOG */
/* The default syslog settings can now be changed here,
in just one place. */
@@ -192,63 +130,25 @@ static inline void memzero(void *ptr, size_t size)
#define OPENLOG(progname) openlog(progname, SYSLOG_OPTIONS, SYSLOG_FACILITY)
#ifndef F_OK
# define F_OK 0
# define X_OK 1
# define W_OK 2
# define R_OK 4
#endif
#ifndef SEEK_SET
# define SEEK_SET 0
# define SEEK_CUR 1
# define SEEK_END 2
#endif
#if HAVE_TERMIOS_H
# include <termios.h>
# define STTY(fd, termio) tcsetattr(fd, TCSANOW, termio)
# define GTTY(fd, termio) tcgetattr(fd, termio)
# define TERMIO struct termios
# define USE_TERMIOS
#else /* assumed HAVE_TERMIO_H */
# include <sys/ioctl.h>
# include <termio.h>
# define STTY(fd, termio) ioctl(fd, TCSETA, termio)
# define GTTY(fd, termio) ioctl(fd, TCGETA, termio)
# define TEMRIO struct termio
# define USE_TERMIO
#endif
#include <termios.h>
#define STTY(fd, termio) tcsetattr(fd, TCSANOW, termio)
#define GTTY(fd, termio) tcgetattr(fd, termio)
#define TERMIO struct termios
/*
* Password aging constants
*
* DAY - seconds / day
* WEEK - seconds / week
* SCALE - seconds / aging unit
*/
/* Solaris defines this in shadow.h */
#ifndef DAY
#define DAY (24L*3600L)
#define DAY ((time_t) 24 * 3600)
#endif
#define WEEK (7*DAY)
#ifdef ITI_AGING
#define SCALE 1
#else
#define SCALE DAY
#endif
/* Copy string pointed by B to array A with size checking. It was originally
in lmain.c but is _very_ useful elsewhere. Some setuid root programs with
very sloppy coding used to assume that BUFSIZ will always be enough... */
/* danger - side effects */
#define STRFCPY(A,B) \
(strncpy((A), (B), sizeof(A) - 1), (A)[sizeof(A) - 1] = '\0')
#ifndef PASSWD_FILE
#define PASSWD_FILE "/etc/passwd"
#endif
@@ -261,24 +161,20 @@ static inline void memzero(void *ptr, size_t size)
#define SHADOW_FILE "/etc/shadow"
#endif
#ifndef SUBUID_FILE
#define SUBUID_FILE "/etc/subuid"
#endif
#ifndef SUBGID_FILE
#define SUBGID_FILE "/etc/subgid"
#endif
#ifdef SHADOWGRP
#ifndef SGROUP_FILE
#define SGROUP_FILE "/etc/gshadow"
#endif
#endif
#ifndef NULL
#define NULL ((void *) 0)
#endif
#ifdef sun /* hacks for compiling on SunOS */
# ifndef SOLARIS
extern int fputs ();
extern char *strdup ();
extern char *strerror ();
# endif
#endif
/*
* string to use for the pw_passwd field in /etc/passwd when using
* shadow passwords - most systems use "x" but there are a few
@@ -288,52 +184,18 @@ extern char *strerror ();
#define SHADOW_PASSWD_STRING "x"
#endif
#define SHADOW_SP_FLAG_UNSET ((unsigned long int)-1)
#define SHADOW_SP_FLAG_UNSET ((unsigned long)-1)
#ifdef WITH_AUDIT
#ifdef __u8 /* in case we use pam < 0.80 */
/* in case we use pam < 0.80 */
#undef __u8
#endif
#ifdef __u32
#undef __u32
#endif
#include <libaudit.h>
#endif
/* To be used for verified unused parameters */
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
# define unused __attribute__((unused))
# define format_attr(type, index, check) __attribute__((format (type, index, check)))
#else
# define unused
# define format_attr(type, index, check)
#endif
/* ! Arguments evaluated twice ! */
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
#endif
/* Maximum length of usernames */
#ifdef HAVE_UTMPX_H
# include <utmpx.h>
# define USER_NAME_MAX_LENGTH (sizeof (((struct utmpx *)NULL)->ut_user))
#else
# include <utmp.h>
# ifdef HAVE_STRUCT_UTMP_UT_USER
# define USER_NAME_MAX_LENGTH (sizeof (((struct utmp *)NULL)->ut_user))
# else
# ifdef HAVE_STRUCT_UTMP_UT_NAME
# define USER_NAME_MAX_LENGTH (sizeof (((struct utmp *)NULL)->ut_name))
# else
# define USER_NAME_MAX_LENGTH 32
# endif
# endif
#endif
/* Maximum length of passwd entry */
#define PASSWD_ENTRY_MAX_LENGTH 32768
#ifdef HAVE_SECURE_GETENV
# define shadow_getenv(name) secure_getenv(name)
@@ -341,4 +203,14 @@ extern char *strerror ();
# 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

@@ -15,9 +15,14 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "alloc.h"
#include "prototypes.h"
#include "defines.h"
#include "shadowlog.h"
#include "string/sprintf.h"
/*
* NEWENVP_STEP must be a power of two. This is the number
* of (char *) pointers to allocate at a time, to avoid using
@@ -26,7 +31,6 @@
#define NEWENVP_STEP 16
size_t newenvc = 0;
/*@null@*/char **newenvp = NULL;
extern char **environ;
static const char *const forbid[] = {
"_RLD_=",
@@ -42,7 +46,7 @@ static const char *const forbid[] = {
"PATH=",
"SHELL=",
"SHLIB_PATH=",
(char *) 0
NULL
};
/* these are allowed, but with no slashes inside
@@ -51,7 +55,7 @@ static const char *const noslash[] = {
"LANG=",
"LANGUAGE=",
"LC_", /* anything with the LC_ prefix */
(char *) 0
NULL
};
/*
@@ -59,23 +63,18 @@ static const char *const noslash[] = {
*/
void initenv (void)
{
newenvp = (char **) xmalloc (NEWENVP_STEP * sizeof (char *));
newenvp = XMALLOC(NEWENVP_STEP, char *);
*newenvp = NULL;
}
void addenv (const char *string, /*@null@*/const char *value)
{
char *cp, *newstring;
size_t i;
size_t n;
char *cp, *newstring;
size_t i, n;
if (NULL != value) {
size_t len = strlen (string) + strlen (value) + 2;
int wlen;
newstring = xmalloc (len);
wlen = snprintf (newstring, len, "%s=%s", string, value);
assert (wlen == (int) len -1);
xasprintf(&newstring, "%s=%s", string, value);
} else {
newstring = xstrdup (string);
}
@@ -87,7 +86,7 @@ void addenv (const char *string, /*@null@*/const char *value)
cp = strchr (newstring, '=');
if (NULL == cp) {
free (newstring);
free(newstring);
return;
}
@@ -104,7 +103,7 @@ void addenv (const char *string, /*@null@*/const char *value)
}
if (i < newenvc) {
free (newenvp[i]);
free(newenvp[i]);
newenvp[i] = newstring;
return;
}
@@ -127,32 +126,19 @@ void addenv (const char *string, /*@null@*/const char *value)
*/
if ((newenvc & (NEWENVP_STEP - 1)) == 0) {
char **__newenvp;
size_t newsize;
bool update_environ;
update_environ = (environ == newenvp);
newenvp = XREALLOC(newenvp, newenvc + NEWENVP_STEP, char *);
/*
* If the resize operation succeeds we can
* happily go on, else print a message.
* If this is our current environment, update
* environ so that it doesn't point to some
* free memory area (realloc() could move it).
*/
newsize = (newenvc + NEWENVP_STEP) * sizeof (char *);
__newenvp = (char **) realloc (newenvp, newsize);
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 (environ == newenvp) {
environ = __newenvp;
}
newenvp = __newenvp;
} else {
(void) fputs (_("Environment overflow\n"), log_get_logfd());
newenvc--;
free (newenvp[newenvc]);
}
if (update_environ)
environ = newenvp;
}
/*
@@ -168,9 +154,9 @@ void addenv (const char *string, /*@null@*/const char *value)
*/
void set_env (int argc, char *const *argv)
{
int noname = 1;
char variable[1024];
char *cp;
int noname = 1;
char variable[1024];
char *cp;
for (; argc > 0; argc--, argv++) {
if (strlen (*argv) >= sizeof variable) {
@@ -179,9 +165,7 @@ void set_env (int argc, char *const *argv)
cp = strchr (*argv, '=');
if (NULL == cp) {
int wlen;
wlen = snprintf (variable, sizeof variable, "L%d", noname);
assert (wlen < (int) sizeof(variable));
assert(SNPRINTF(variable, "L%d", noname) != -1);
noname++;
addenv (variable, *argv);
} else {
@@ -194,8 +178,7 @@ void set_env (int argc, char *const *argv)
}
if (NULL != *p) {
strncpy (variable, *argv, (size_t)(cp - *argv));
variable[cp - *argv] = '\0';
stpcpy(mempcpy(variable, *argv, (size_t)(cp - *argv)), "");
printf (_("You may not change $%s\n"),
variable);
continue;

View File

@@ -14,10 +14,16 @@
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include "defines.h"
#include "faillog.h"
#include "getdef.h"
#include "failure.h"
#include "memzero.h"
#include "prototypes.h"
#include "string/strftime.h"
#include "string/strtcpy.h"
#define YEAR (365L*DAY)
/*
* failure - make failure entry
@@ -41,7 +47,7 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
fd = open (FAILLOG_FILE, O_RDWR);
if (fd < 0) {
SYSLOG ((LOG_WARN,
"Can't write faillog entry for UID %lu in %s.",
"Can't write faillog entry for UID %lu in %s: %m",
(unsigned long) uid, FAILLOG_FILE));
return;
}
@@ -53,7 +59,7 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
*/
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|| (read (fd, (char *) fl, sizeof *fl) != (ssize_t) sizeof *fl)) {
|| (read (fd, fl, sizeof *fl) != (ssize_t) sizeof *fl)) {
/* This is not necessarily a failure. The file is
* initially zero length.
*
@@ -75,7 +81,7 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
fl->fail_cnt++;
}
strncpy (fl->fail_line, tty, sizeof (fl->fail_line) - 1);
STRTCPY(fl->fail_line, tty);
(void) time (&fl->fail_time);
/*
@@ -86,13 +92,26 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
*/
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|| (write (fd, (char *) fl, sizeof *fl) != (ssize_t) sizeof *fl)
|| (close (fd) != 0)) {
SYSLOG ((LOG_WARN,
"Can't write faillog entry for UID %lu in %s.",
(unsigned long) uid, FAILLOG_FILE));
(void) close (fd);
|| (write_full(fd, fl, sizeof *fl) == -1)) {
goto err_write;
}
if (close (fd) != 0 && errno != EINTR) {
goto err_close;
}
return;
err_write:
{
int saved_errno = errno;
(void) close (fd);
errno = saved_errno;
}
err_close:
SYSLOG ((LOG_WARN,
"Can't write faillog entry for UID %lu to %s: %m",
(unsigned long) uid, FAILLOG_FILE));
}
static bool too_many_failures (const struct faillog *fl)
@@ -144,7 +163,7 @@ int failcheck (uid_t uid, struct faillog *fl, bool failed)
fd = open (FAILLOG_FILE, failed?O_RDONLY:O_RDWR);
if (fd < 0) {
SYSLOG ((LOG_WARN,
"Can't open the faillog file (%s) to check UID %lu. "
"Can't open the faillog file (%s) to check UID %lu: %m; "
"User access authorized.",
FAILLOG_FILE, (unsigned long) uid));
return 1;
@@ -163,7 +182,7 @@ int failcheck (uid_t uid, struct faillog *fl, bool failed)
*/
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|| (read (fd, (char *) fl, sizeof *fl) != (ssize_t) sizeof *fl)) {
|| (read (fd, fl, sizeof *fl) != (ssize_t) sizeof *fl)) {
(void) close (fd);
return 1;
}
@@ -185,18 +204,30 @@ int failcheck (uid_t uid, struct faillog *fl, bool failed)
fail.fail_cnt = 0;
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|| (write (fd, (const void *) &fail, sizeof fail) != (ssize_t) sizeof fail)
|| (close (fd) != 0)) {
SYSLOG ((LOG_WARN,
"Can't reset faillog entry for UID %lu in %s.",
(unsigned long) uid, FAILLOG_FILE));
(void) close (fd);
|| (write_full(fd, &fail, sizeof fail) == -1)) {
goto err_write;
}
if (close (fd) != 0 && errno != EINTR) {
goto err_close;
}
} else {
(void) close (fd);
}
return 1;
err_write:
{
int saved_errno = errno;
(void) close (fd);
errno = saved_errno;
}
err_close:
SYSLOG ((LOG_WARN,
"Can't reset faillog entry for UID %lu in %s: %m",
(unsigned long) uid, FAILLOG_FILE));
return 1;
}
/*
@@ -223,7 +254,7 @@ void failprint (const struct faillog *fail)
/*
* 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"
@@ -234,62 +265,3 @@ void failprint (const struct faillog *fail)
fail->fail_cnt, lasttime, fail->fail_line);
/*@=formatconst@*/
}
/*
* failtmp - update the cumulative failure log
*
* failtmp updates the (struct utmp) formatted failure log which
* maintains a record of all login failures.
*/
void failtmp (const char *username,
#ifdef USE_UTMPX
const struct utmpx *failent
#else /* !USE_UTMPX */
const struct utmp *failent
#endif /* !USE_UTMPX */
)
{
const char *ftmp;
int fd;
/*
* Get the name of the failure file. If no file has been defined
* in login.defs, don't do this.
*/
ftmp = getdef_str ("FTMP_FILE");
if (NULL == ftmp) {
return;
}
/*
* Open the file for append. It must already exist for this
* feature to be used.
*/
if (access (ftmp, F_OK) != 0) {
return;
}
fd = open (ftmp, O_WRONLY | O_APPEND);
if (-1 == fd) {
SYSLOG ((LOG_WARN,
"Can't append failure of user %s to %s.",
username, ftmp));
return;
}
/*
* Append the new failure record and close the log file.
*/
if ( (write (fd, (const void *) failent, sizeof *failent) != (ssize_t) sizeof *failent)
|| (close (fd) != 0)) {
SYSLOG ((LOG_WARN,
"Can't append failure of user %s to %s.",
username, ftmp));
(void) close (fd);
}
}

View File

@@ -13,11 +13,6 @@
#include "defines.h"
#include "faillog.h"
#ifdef USE_UTMPX
#include <utmpx.h>
#else /* !USE_UTMPX */
#include <utmp.h>
#endif /* !USE_UTMPX */
/*
* failure - make failure entry
@@ -45,17 +40,5 @@ extern int failcheck (uid_t uid, struct faillog *fl, bool failed);
*/
extern void failprint (const struct faillog *);
/*
* failtmp - update the cumulative failure log
*
* failtmp updates the (struct utmp) formatted failure log which
* maintains a record of all login failures.
*/
#ifdef USE_UTMPX
extern void failtmp (const char *username, const struct utmpx *);
#else /* !USE_UTMPX */
extern void failtmp (const char *username, const struct utmp *);
#endif /* !USE_UTMPX */
#endif

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

@@ -21,9 +21,9 @@
*
* The supplied field is scanned for non-printable and other illegal
* characters.
* + -1 is returned if an illegal character is present.
* + 1 is returned if no illegal characters are present, but the field
* contains a non-printable character.
* + -1 is returned if an illegal or control character is present.
* + 1 is returned if no illegal or control characters are present,
* but the field contains a non-printable character.
* + 0 is returned otherwise.
*/
int valid_field (const char *field, const char *illegal)
@@ -37,20 +37,19 @@ int valid_field (const char *field, const char *illegal)
/* For each character of field, search if it appears in the list
* of illegal characters. */
for (cp = field; '\0' != *cp; cp++) {
if (strchr (illegal, *cp) != NULL) {
err = -1;
break;
}
if (illegal && NULL != strpbrk (field, illegal)) {
return -1;
}
if (0 == err) {
/* Search if there are some non-printable characters */
for (cp = field; '\0' != *cp; cp++) {
if (!isprint (*cp)) {
err = 1;
break;
}
/* Search if there are non-printable or control characters */
for (cp = field; '\0' != *cp; cp++) {
unsigned char c = *cp;
if (!isprint (c)) {
err = 1;
}
if (iscntrl (c)) {
err = -1;
break;
}
}
@@ -74,7 +73,7 @@ void change_field (char *buf, size_t maxsize, const char *prompt)
printf ("\t%s [%s]: ", prompt, buf);
(void) fflush (stdout);
if (fgets (newf, (int) maxsize, stdin) != newf) {
if (fgets (newf, maxsize, stdin) != newf) {
return;
}
@@ -91,17 +90,16 @@ void change_field (char *buf, size_t maxsize, const char *prompt)
* entering a space. --marekm
*/
while (--cp >= newf && isspace (*cp));
cp++;
while (newf < cp && isspace (cp[-1])) {
cp--;
}
*cp = '\0';
cp = newf;
while (('\0' != *cp) && isspace (*cp)) {
while (isspace (*cp)) {
cp++;
}
strncpy (buf, cp, maxsize - 1);
buf[maxsize - 1] = '\0';
strcpy (buf, cp);
}
}

View File

@@ -12,6 +12,7 @@
#include <stdio.h>
#include <errno.h>
#include "alloc.h"
#include "prototypes.h"
#include "groupio.h"
#include "getdef.h"
@@ -40,15 +41,14 @@ static int get_ranges (bool sys_group, gid_t *min_id, gid_t *max_id,
*preferred_min = (gid_t) 1;
/* Get the minimum ID range from login.defs or default to 101 */
*min_id = (gid_t) getdef_ulong ("SYS_GID_MIN", 101UL);
*min_id = getdef_ulong ("SYS_GID_MIN", 101UL);
/*
* If SYS_GID_MAX is unspecified, we should assume it to be one
* less than the GID_MIN (which is reserved for non-system accounts)
*/
gid_def_max = (gid_t) getdef_ulong ("GID_MIN", 1000UL) - 1;
*max_id = (gid_t) getdef_ulong ("SYS_GID_MAX",
(unsigned long) gid_def_max);
gid_def_max = getdef_ulong ("GID_MIN", 1000UL) - 1;
*max_id = getdef_ulong ("SYS_GID_MAX", gid_def_max);
/* Check that the ranges make sense */
if (*max_id < *min_id) {
@@ -60,12 +60,19 @@ static int get_ranges (bool sys_group, gid_t *min_id, gid_t *max_id,
(unsigned long) *max_id);
return EINVAL;
}
/*
* Zero is reserved for root and the allocation algorithm does not
* work right with it.
*/
if (*min_id == 0) {
*min_id = (gid_t) 1;
}
} else {
/* Non-system groups */
/* Get the values from login.defs or use reasonable defaults */
*min_id = (gid_t) getdef_ulong ("GID_MIN", 1000UL);
*max_id = (gid_t) getdef_ulong ("GID_MAX", 60000UL);
*min_id = getdef_ulong ("GID_MIN", 1000UL);
*max_id = getdef_ulong ("GID_MAX", 60000UL);
/*
* The preferred minimum should match the standard ID minimum
@@ -92,6 +99,7 @@ static int get_ranges (bool sys_group, gid_t *min_id, gid_t *max_id,
*
* On success, return 0
* If the ID is in use, return EEXIST
* If the ID might clash with -1, return EINVAL
* If the ID is outside the range, return ERANGE
* In other cases, return errno from getgrgid()
*/
@@ -105,6 +113,11 @@ static int check_gid (const gid_t gid,
return ERANGE;
}
/* Check for compatibility with 16b and 32b gid_t error codes */
if (gid == UINT16_MAX || gid == UINT32_MAX) {
return EINVAL;
}
/*
* Check whether we already detected this GID
* using the gr_next() loop
@@ -176,10 +189,10 @@ int find_new_gid (bool sys_group,
* gr_locate_gid() found the GID in an as-yet uncommitted
* entry. We'll proceed below and auto-set a GID.
*/
} else if (result == EEXIST || result == ERANGE) {
} else if (result == EEXIST || result == ERANGE || result == EINVAL) {
/*
* Continue on below. At this time, we won't
* treat these two cases differently.
* treat these three cases differently.
*/
} else {
/*
@@ -219,14 +232,13 @@ int find_new_gid (bool sys_group,
*/
/* Create an array to hold all of the discovered GIDs */
used_gids = malloc (sizeof (bool) * (gid_max +1));
used_gids = CALLOC (gid_max + 1, bool);
if (NULL == used_gids) {
fprintf (log_get_logfd(),
_("%s: failed to allocate memory: %s\n"),
log_get_progname(), strerror (errno));
return -1;
}
memset (used_gids, false, sizeof (bool) * (gid_max + 1));
/* First look for the lowest and highest value in the local database */
(void) gr_rewind ();
@@ -290,8 +302,11 @@ int find_new_gid (bool sys_group,
*gid = id;
free (used_gids);
return 0;
} else if (result == EEXIST) {
/* This GID is in use, we'll continue to the next */
} else if (result == EEXIST || result == EINVAL) {
/*
* This GID is in use or unusable, we'll
* continue to the next.
*/
} else {
/*
* An unexpected error occurred.
@@ -333,8 +348,11 @@ int find_new_gid (bool sys_group,
*gid = id;
free (used_gids);
return 0;
} else if (result == EEXIST) {
/* This GID is in use, we'll continue to the next */
} else if (result == EEXIST || result == EINVAL) {
/*
* This GID is in use or unusable, we'll
* continue to the next.
*/
} else {
/*
* An unexpected error occurred.
@@ -393,8 +411,11 @@ int find_new_gid (bool sys_group,
*gid = id;
free (used_gids);
return 0;
} else if (result == EEXIST) {
/* This GID is in use, we'll continue to the next */
} else if (result == EEXIST || result == EINVAL) {
/*
* This GID is in use or unusable, we'll
* continue to the next.
*/
} else {
/*
* An unexpected error occurred.
@@ -436,8 +457,11 @@ int find_new_gid (bool sys_group,
*gid = id;
free (used_gids);
return 0;
} else if (result == EEXIST) {
/* This GID is in use, we'll continue to the next */
} else if (result == EEXIST || result == EINVAL) {
/*
* This GID is in use or unusable, we'll
* continue to the next.
*/
} else {
/*
* An unexpected error occurred.

View File

@@ -59,6 +59,6 @@ int find_new_sub_gids (gid_t *range_start, unsigned long *range_count)
return 0;
}
#else /* !ENABLE_SUBIDS */
extern int errno; /* warning: ANSI C forbids an empty source file */
extern int ISO_C_forbids_an_empty_translation_unit;
#endif /* !ENABLE_SUBIDS */

View File

@@ -59,6 +59,6 @@ int find_new_sub_uids (uid_t *range_start, unsigned long *range_count)
return 0;
}
#else /* !ENABLE_SUBIDS */
extern int errno; /* warning: ANSI C forbids an empty source file */
extern int ISO_C_forbids_an_empty_translation_unit;
#endif /* !ENABLE_SUBIDS */

View File

@@ -12,6 +12,7 @@
#include <stdio.h>
#include <errno.h>
#include "alloc.h"
#include "prototypes.h"
#include "pwio.h"
#include "getdef.h"
@@ -40,15 +41,14 @@ static int get_ranges (bool sys_user, uid_t *min_id, uid_t *max_id,
*preferred_min = (uid_t) 1;
/* Get the minimum ID range from login.defs or default to 101 */
*min_id = (uid_t) getdef_ulong ("SYS_UID_MIN", 101UL);
*min_id = getdef_ulong ("SYS_UID_MIN", 101UL);
/*
* If SYS_UID_MAX is unspecified, we should assume it to be one
* less than the UID_MIN (which is reserved for non-system accounts)
*/
uid_def_max = (uid_t) getdef_ulong ("UID_MIN", 1000UL) - 1;
*max_id = (uid_t) getdef_ulong ("SYS_UID_MAX",
(unsigned long) uid_def_max);
uid_def_max = getdef_ulong ("UID_MIN", 1000UL) - 1;
*max_id = getdef_ulong ("SYS_UID_MAX", uid_def_max);
/* Check that the ranges make sense */
if (*max_id < *min_id) {
@@ -60,12 +60,19 @@ static int get_ranges (bool sys_user, uid_t *min_id, uid_t *max_id,
(unsigned long) *max_id);
return EINVAL;
}
/*
* Zero is reserved for root and the allocation algorithm does not
* work right with it.
*/
if (*min_id == 0) {
*min_id = (uid_t) 1;
}
} else {
/* Non-system users */
/* Get the values from login.defs or use reasonable defaults */
*min_id = (uid_t) getdef_ulong ("UID_MIN", 1000UL);
*max_id = (uid_t) getdef_ulong ("UID_MAX", 60000UL);
*min_id = getdef_ulong ("UID_MIN", 1000UL);
*max_id = getdef_ulong ("UID_MAX", 60000UL);
/*
* The preferred minimum should match the standard ID minimum
@@ -92,6 +99,7 @@ static int get_ranges (bool sys_user, uid_t *min_id, uid_t *max_id,
*
* On success, return 0
* If the ID is in use, return EEXIST
* If the ID might clash with -1, return EINVAL
* If the ID is outside the range, return ERANGE
* In other cases, return errno from getpwuid()
*/
@@ -105,6 +113,11 @@ static int check_uid(const uid_t uid,
return ERANGE;
}
/* Check for compatibility with 16b and 32b uid_t error codes */
if (uid == UINT16_MAX || uid == UINT32_MAX) {
return EINVAL;
}
/*
* Check whether we already detected this UID
* using the pw_next() loop
@@ -176,10 +189,10 @@ int find_new_uid(bool sys_user,
* pw_locate_uid() found the UID in an as-yet uncommitted
* entry. We'll proceed below and auto-set an UID.
*/
} else if (result == EEXIST || result == ERANGE) {
} else if (result == EEXIST || result == ERANGE || result == EINVAL) {
/*
* Continue on below. At this time, we won't
* treat these two cases differently.
* treat these three cases differently.
*/
} else {
/*
@@ -219,14 +232,13 @@ int find_new_uid(bool sys_user,
*/
/* Create an array to hold all of the discovered UIDs */
used_uids = malloc (sizeof (bool) * (uid_max +1));
used_uids = CALLOC(uid_max + 1, bool);
if (NULL == used_uids) {
fprintf (log_get_logfd(),
_("%s: failed to allocate memory: %s\n"),
log_get_progname(), strerror (errno));
return -1;
}
memset (used_uids, false, sizeof (bool) * (uid_max + 1));
/* First look for the lowest and highest value in the local database */
(void) pw_rewind ();
@@ -290,8 +302,11 @@ int find_new_uid(bool sys_user,
*uid = id;
free (used_uids);
return 0;
} else if (result == EEXIST) {
/* This UID is in use, we'll continue to the next */
} else if (result == EEXIST || result == EINVAL) {
/*
* This GID is in use or unusable, we'll
* continue to the next.
*/
} else {
/*
* An unexpected error occurred.
@@ -333,8 +348,11 @@ int find_new_uid(bool sys_user,
*uid = id;
free (used_uids);
return 0;
} else if (result == EEXIST) {
/* This UID is in use, we'll continue to the next */
} else if (result == EEXIST || result == EINVAL) {
/*
* This GID is in use or unusable, we'll
* continue to the next.
*/
} else {
/*
* An unexpected error occurred.
@@ -393,8 +411,11 @@ int find_new_uid(bool sys_user,
*uid = id;
free (used_uids);
return 0;
} else if (result == EEXIST) {
/* This UID is in use, we'll continue to the next */
} else if (result == EEXIST || result == EINVAL) {
/*
* This GID is in use or unusable, we'll
* continue to the next.
*/
} else {
/*
* An unexpected error occurred.
@@ -436,8 +457,11 @@ int find_new_uid(bool sys_user,
*uid = id;
free (used_uids);
return 0;
} else if (result == EEXIST) {
/* This UID is in use, we'll continue to the next */
} else if (result == EEXIST || result == EINVAL) {
/*
* This GID is in use or unusable, we'll
* continue to the next.
*/
} else {
/*
* An unexpected error occurred.

View File

@@ -16,7 +16,8 @@
#ident "$Id$"
/*@null@*/char *fgetsx (/*@returned@*/ /*@out@*/char *buf, int cnt, FILE * f)
/*@null@*/char *
fgetsx(/*@returned@*/char *restrict buf, int cnt, FILE *restrict f)
{
char *cp = buf;
char *ep;

30
lib/freezero.c Normal file
View File

@@ -0,0 +1,30 @@
/* $OpenBSD: malloc.c,v 1.267 2020/11/23 15:42:11 otto Exp $ */
/*
* Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
void
freezero(void *ptr, size_t sz)
{
/* This is legal. */
if (ptr == NULL)
return;
explicit_bzero(ptr, sz);
free(ptr);
}

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