Compare commits

...

575 Commits

Author SHA1 Message Date
Serge Hallyn ef45bb2496 configure.ac: release 4.3
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2016-03-16 17:11:36 -07:00
Serge Hallyn edec2d057d Merge pull request #13 from t8m/master
Add ability to clear or set lastlog record for user via lastlog command
2016-03-05 00:07:24 -08:00
Tomas Mraz 66897b6f6d Add ability to clear or set lastlog record for user via lastlog command
This functionality is useful because there is now a feature
of Linux-PAM's pam_lastlog module to block expired users (users
which did not login recently enough) from login. This commit
complements it so the sysadmin is able to unblock such expired user.

Signed-off-by: Tomáš Mráz <tmraz@fedoraproject.org>
2016-03-03 15:37:01 +01:00
Serge Hallyn af064545bf useradd: respect -r flag when allocating subuids
We intend to not create subuids for system users. However we are
checking for command line flags after we check whether -r flag
was set, so it was never found to be true.  Fix that.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2016-02-18 09:20:43 -08:00
Serge Hallyn 9ab9e6f331 Merge pull request #12 from stgraber/master
Tweak uid/gid map default configuration
2016-02-15 15:27:20 -08:00
Stéphane Graber 65c2617140 Tweak uid/gid map default configuration
- Use an allocation of 65536 uids and gids to allow for POSIX-compliant
   user owned namespaces.
 - Don't allocate a uid/gid map to system users.
   Unfortunately checking for --system isn't quite enough as some
   distribution wrappers always call useradd without --system and take care
   of choosing a uid and gid themselves, so also check whether the
   requested uid/gid is in the user range.

This is taken from a patch I wrote for Ubuntu a couple years ago and
which somehow didn't make it upstream.

Signed-off-by: Stéphane Graber <stgraber@ubuntu.com>
2016-02-15 18:11:10 -05:00
Serge Hallyn 24468e4525 Merge pull request #11 from taizo/typo_in_japanese_usage_desc
typo in japanese usage description of useradd.
2016-01-11 17:20:57 -08:00
Taizo Ito df11d701e1 typo in japanese usage description of useradd. 2016-01-04 13:27:31 +09:00
Bastian Blank d2fa8c5d4b Fix user busy errors at userdel
From: Bastian Blank <bastian.blank@credativ.de>
Acked-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2015-11-17 10:53:55 -06:00
Serge Hallyn e01bad7d3c Merge pull request #4 from xnox/master
Make shadow more robust in hostile environments
2015-11-12 23:07:29 -06:00
Serge Hallyn 4c4896f0d5 Merge pull request #9 from shadow-maint/idmapleak
Idmapleak
2015-11-12 23:03:09 -06:00
Serge Hallyn 5fadb341c3 Merge pull request #8 from shadow-maint/newgrpleak
Fix a resource leak in syslog_sg
2015-11-12 23:02:13 -06:00
Serge Hallyn 29ee91ae7d Merge pull request #6 from stoeckmann/master
Clear passwords on __gr_dup/__pw_dup errors and fix memory leak
2015-08-09 19:57:38 -05:00
Serge Hallyn 5533eb40d1 Merge pull request #5 from vapier/master
misc autoool fixes
2015-08-09 19:51:54 -05:00
Serge Hallyn 533d2bab3d get_map_ranges: initialize argidx to 0 at top of loop
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2015-08-06 00:34:25 -05:00
Serge Hallyn f68f813073 Fix a resource leak in syslog_sg
Reported at https://alioth.debian.org/tracker/?func=detail&atid=411478&aid=315135&group_id=30580
by Alejandro Joya (afjoyacr-guest)

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2015-08-06 00:25:01 -05:00
Serge Hallyn 7edb32e75f Fix a resource leak in libmis/idmapping.c
Reported at https://alioth.debian.org/tracker/?func=detail&atid=411478&aid=315136&group_id=30580
by Alejandro Joya.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2015-08-06 00:10:13 -05:00
Serge Hallyn acf11efe54 Merge pull request #7 from shadow-maint/2015-07-20/vflg
Don't limit subuid/subgid support to local users
2015-07-23 10:11:46 -05:00
Serge Hallyn a887847ca2 Don't limit subuid/subgid support to local users
The current implementation of subuid/subgid support in usermod requires the
user to be a local user present in /etc/passwd.  There doesn't seem to be a
good reason for this; subuids should work equally well for users whose
records are in other NSS databases.

Bug-Ubuntu: https://bugs.launchpad.net/bugs/1475749

Author: Steve Langasek <steve.langasek@ubuntu.com>
Acked-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2015-07-20 12:14:26 -05:00
Tobias Stoeckmann c17f5ec460 Free memory on error path
When multiple entries with the same name are encountered, nentry is
not properly freed, which results in a memory leak.
2015-07-12 14:30:32 +02:00
Tobias Stoeckmann df5dafe049 Clear passwords on __gr_dup/__pw_dup errors.
The functions __gr_dup and __pw_dup do not explicitly zero the
memory which hold the passwords after free. The gr_free and pw_free
functions do this explicitly.

To guarantee same behaviour, it's possible to call these *_free
functions directly from __*_dup, because the memory is initialized
with zeros at the beginning. Calling free(NULL) has no negative
effect and can be considered safe these days.
2015-07-11 13:00:13 +02:00
Jesse W. Hathaway 3c32fd4a29 Allow deleting the group even if it is the primary group of a user
This is helpful when using configuration management tools such as
Puppet, where you are managing the groups in a central location and you
don't need this safeguard.

Signed-off-by: "Jesse W. Hathaway" <jesse@mbuki-mvuki.org>
Acked-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2015-06-16 14:18:44 -05:00
Serge Hallyn ecb6f0c3e3 newgidmap manpage: remove wrongly added extra pid arg
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2015-06-04 23:45:58 -05:00
Mike Frysinger 169e14c7ac ignore the compile file
Newer autotools installs this file.
2015-04-30 02:46:08 -04:00
Mike Frysinger 316fa38dbc rename configure.in
Newer autotools complains when the file is named configure.in.
2015-04-30 02:43:30 -04:00
Hank Leininger 884895ae25 Expand the error message when newuidmap / newgidmap do not like the user/group ownership of their target process.
Currently the error is just:

newuidmap: Target [pid] is owned by a different user

With this patch it will be like:

newuidmap: Target [pid] is owned by a different user: uid:0 pw_uid:0 st_uid:0, gid:0 pw_gid:0 st_gid:99

Why is this useful?  Well, in my case...

The grsecurity kernel-hardening patch includes an option to make parts
of /proc unreadable, such as /proc/pid/ dirs for processes not owned by
the current uid.  This comes with an option to make /proc/pid/
directories readable by a specific gid; sysadmins and the like are then
put into that group so they can see a full 'ps'.

This means that the check in new[ug]idmap fails, as in the above quoted
error - /proc/[targetpid] is owned by root, but the group is 99 so that
users in group 99 can see the process.

Some Googling finds dozens of people hitting this problem, but not
*knowing* that they have hit this problem, because the errors and
circumstances are non-obvious.

Some graceful way of handling this and not failing, will be next ;)  But
in the meantime it'd be nice to have new[ug]idmap emit a more useful
error, so that it's easier to troubleshoot.

Thanks!

Signed-off-by: Hank Leininger <hlein@korelogic.com>
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2015-04-06 08:23:36 -05:00
Serge Hallyn 464456fa31 Merge pull request #3 from vapier/master
man: useradd(8): fix typo in German translation
2015-03-16 17:08:55 +00:00
Dimitri John Ledkov bab349b46e Create dbs with correct permissions. 2015-02-27 17:01:31 +00:00
Dimitri John Ledkov 46a72bc342 Force use shadow, even if missing. 2015-02-27 17:01:30 +00:00
Dimitri John Ledkov ee43f47f45 Do not fail on missing files in /etc/, create them instead.
passwd, shadow, group, gshadow etc. can be managed via nss -
e.g. system default accounts can be specified using nss_altfiles,
rather than in /etc/. Thus despite having default accounts, these
files can be missing on disk and thus should be opened with O_CREATE
whenever they are attempted to be opened in O_RDWR modes.
2015-02-27 17:01:29 +00:00
Dimitri John Ledkov 71c6165dcd Do not report unknown settings, when compiled with PAM.
When compiled with PAM certain settings are not used, however they are
still defined in the stock login.defs file. Thus every command reports
them as "unknown setting contact administrator".

Alternative would be to parse stock login.defs and comment out/remove
settings that are not applied, when compiled with PAM.
2015-02-27 17:01:28 +00:00
Dimitri John Ledkov 51c1fc93e3 Do not bail out on missing login.defs.
For most operations tools have compiled-in defaults, and thus can
operate without login.defs present.
2015-02-27 17:01:27 +00:00
Duncan Eastoe 17887b216d Suppress pwconv passwd- chmod failure message
Prevent chmod failure message from displaying if the failure
was due to the backup file not existing.

If there is no backup file present and if no changes have been
made, then this error would always appear since the backup
file isn't created in this situation.

Signed-off-by: Duncan Eastoe <deastoe@Brocade.com>
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2015-02-17 10:15:02 -06:00
Mike Frysinger 01eab0c3b9 man: useradd(8): fix typo in German translation
When referring to USERGROUPS_ENAB, the German mentions /etc/default/useradd
when it should be /etc/login.defs (like the original English does).

Reported-by: Stefan Kiesler <heavymetal@gmx.de>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
2015-02-14 00:21:14 -05:00
Nicolas François 6b65c6aeae Test userdel/usermod when homedir is a symlink 2014-09-21 00:36:24 +02:00
Nicolas François 3fb292f3c7 Extend checks for changing U/GID in home directory
Add files with user or group owner different from the user.
2014-09-21 00:36:23 +02:00
Nicolas François a8bf8af5aa Extend checks for moving home directory
Add hard link to files inside or outside the home directory)
Add files with user or group owner different from the user.
2014-09-21 00:36:16 +02:00
Nicolas François d8c8e8b4b6 subids options added to usermod's usage 2014-09-21 00:17:30 +02:00
Nicolas François 930e76ad0d Provides coverage with traceability to test cases 2014-09-21 00:17:29 +02:00
Nicolas François 83b5a746d9 Add missing configuration files 2014-09-21 00:17:27 +02:00
Nicolas François a7f8176be6 useradd now uses link rather than rename 2014-09-21 00:17:26 +02:00
Nicolas François 1b4db814ea Add support for syscall failure tests 2014-09-21 00:17:25 +02:00
Nicolas François 9ae9ca833a Add cleanup script 2014-09-21 00:17:24 +02:00
Nicolas François 66f87b8caf Add config to disable execution of failure tests 2014-09-21 00:17:23 +02:00
Nicolas François bba85fcae3 Add tests for subids handling 2014-09-21 00:16:57 +02:00
Nicolas François a0104a9ed8 Use build_path from common/config.sh 2014-09-20 15:46:14 +02:00
Nicolas François 112e015f05 Force removal of files when restoring system config 2014-09-20 15:40:46 +02:00
Nicolas François e6246599eb Update list of files in login and passwd packages 2014-09-20 15:39:32 +02:00
Bostjan Skufca 1d049b6aed sub[ug]id: compare range before comparing username/UID, to avoid unnecessary syscalls
Change suggested by Nicolas François as performance optimization.
Performance penalty would be really noticeable when usernames are
stored in remote databases (ldap).

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2014-09-17 15:48:24 -05:00
Bostjan Skufca 37e2a687e3 sub[ug]id manpages: add note about performance when using login names versus UIDs
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2014-09-17 15:48:17 -05:00
Bostjan Skufca a113b87c45 newuidmap/newgidmap: added support for user matching by UID in /etc/sub[ug]id
Until now only exact username specification in /etc/sub[ug]id file allowed the
mapping. This prevented normal use for those users who use multiple usernames
with the same UID, as it rejected mapping even though it was allowed for
another username with the same UID.

This patch initially retains the old behaviour, for performance's sake. In the
first pass, new[ug]idmap only searches for exact username match.
If that yields no valid results, it continues into another loop, which does UID
resolution and comparison. If either definition (numeric UID mapping
specification or mapping specification for another username with the same UID as
current username) is found, it is used.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2014-09-17 15:48:10 -05:00
Serge Hallyn b999d48941 Add tests from the old svn tree
We're losing the svn history (which we could probably keep if we tried
hard enough) but don't consider that worthwhile.

Note these tests are destructive, so run them only in a throwaway
environment like a chroot, container, or vm.

The tests/run.all script should be the one which launches all the tests.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2014-09-17 14:42:55 -05:00
James Le Cuirot 2cb54158b8 Check size of uid_t and gid_t using AC_CHECK_SIZEOF
This built-in check is simpler than the previous method and, most
importantly, works when cross-compiling.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2014-09-04 17:29:27 -05:00
James Le Cuirot 420943657c Fix building without subordinate IDs support
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2014-09-04 17:29:23 -05:00
Serge Hallyn 4911773b77 From: Svante Signell <svante.signell@gmail.com>
Currently shadow fails to build from source and is flagged as
out-of-date. This is due to a usage of PATH_MAX, which is not defined
on GNU/Hurd. The attached patch solves this problem by allocating a
fixed number of 32 bytes for the string proc_dir_name in files
src/procuidmap.c and src/procgidmap.c. (In fact only 18 bytes are
needed)

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2014-06-26 16:48:56 -05:00
Serge Hallyn 980c804153 man: newuid and newgid: point out that root must be allocated subuids
Users may otherwise be confused and think that because the kernel
does not restrict uid mappings to the root user (within his
current uid mappings), newuidmap will ignore /etc/subuid for the
root user.  It will not.

Reported-by: Philippe Grégoire <gregoirep@hotmail.com>
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
2014-06-13 09:41:09 -05:00
Eric W. Biederman 578947e661 newuidmap,newgidmap: Correct the range size sanity check in get_map_ranges
The number of ranges should be the ceiling of the number of arguments divided
by three.

Without this fix newuidmap and newgidmap always report and error and fail,
which is very much not what we want.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2013-09-10 17:51:40 -05:00
Nicolas François 5e87ff0615 Improve vipw error report when editor fails
* src/vipw.c: After waitpid(), use errno only if waitpid returned
	-1. Debian#688260
	* src/vipw.c: Likewise for system().
2013-08-25 16:27:58 +02:00
Serge Hallyn d409947e9a Document the subuid related functions in subordinateio.c
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2013-08-23 16:00:36 -05:00
victory ba527c728e Updated Japanese translation to 558t
* po/ja.po: Updated to 558t
2013-08-23 22:31:00 +02:00
Serge Hallyn 50bb452dd1 newuidmap.1 and newgidmap.1: note limitation
Note that they may be used only once for a given process.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2013-08-23 15:16:43 -05:00
Nicolas François 90ac3a3207 Update translation files.
* man/po/shadow-man-pages.pot: Regenerated.
	* man/po/*.po: Updated PO files.
2013-08-23 20:29:43 +02:00
Nicolas François 684de2abff Fix encoding.
* man/newgrp.1.xml: Fix encoding.
	* man/sg.1.xml: Likewise.
2013-08-23 20:29:42 +02:00
Nicolas François 44faa3b796 Unfuzzy according to previous change.
* man/po/da.po: Unfuzzy according to previous change.
	* man/po/de.po: Likewise.
	* man/po/fr.po: Likewise.
	* man/po/it.po: Likewise.
	* man/po/pl.po: Likewise.
	* man/po/ru.po: Likewise.
	* man/po/sv.po: Likewise.
	* man/po/zh_CN.po: Likewise.
2013-08-23 20:29:41 +02:00
Nicolas François 138682fd30 Avoid spaces between <option> and <replaceable>
* man/chage.1.xml: Add a non breaking space between options and
	their parameter because xml2po removes those spaces. Alioth#314401
	* man/chfn.1.xml: Likewise.
	* man/chgpasswd.8.xml: Likewise.
	* man/chpasswd.8.xml: Likewise.
	* man/chsh.1.xml: Likewise.
	* man/faillog.8.xml: Likewise.
	* man/gpasswd.1.xml: Likewise.
	* man/groupadd.8.xml: Likewise.
	* man/groupdel.8.xml: Likewise.
	* man/groupmems.8.xml: Likewise.
	* man/groupmod.8.xml: Likewise.
	* man/grpck.8.xml: Likewise.
	* man/lastlog.8.xml: Likewise.
	* man/newusers.8.xml: Likewise.
	* man/passwd.1.xml: Likewise.
	* man/pwck.8.xml: Likewise.
	* man/pwconv.8.xml: Likewise.
	* man/su.1.xml: Likewise.
	* man/useradd.8.xml: Likewise.
	* man/userdel.8.xml: Likewise.
	* man/usermod.8.xml: Likewise.
	* man/vipw.8.xml: Likewise.
2013-08-23 20:29:40 +02:00
Nicolas François 373dd2dc3d Create baseline for changing manpage options.
* man/po/shadow-man-pages.pot: Regenerated.
	* man/po/*.po: Updated PO files.
2013-08-23 20:29:39 +02:00
Nicolas François 3ea09ae998 Fix encoding.
* man/po/de.po: Fix encoding.
2013-08-23 20:29:33 +02:00
Nicolas François 115aeef1c4 Fix subordinate_next() return value.
* lib/subordinateio.c (subordinate_next): Fix return value.
2013-08-19 21:32:27 +02:00
Nicolas François 2883ff6ad5 Include <stdio.h>
* libmisc/idmapping.c: Include <stdio.h> needed for fprintf() and
	stderr.
2013-08-16 01:13:20 +02:00
Nicolas François c3b6417226 Remove debug info. 2013-08-16 01:11:50 +02:00
Nicolas François eceedf43cf Improve documentation.
* man/login.defs.d/SUB_GID_COUNT.xml: Document newusers behavior
	when the user already have subordinate group IDs.
	* man/login.defs.d/SUB_UID_COUNT.xml: Likewise.
	* man/login.defs.d/SUB_GID_COUNT.xml: Fix typo (MAX<->MIN).
	* man/login.defs.d/SUB_UID_COUNT.xml: Likewise.
2013-08-15 17:30:20 +02:00
Nicolas François 6f8dd000f6 Improve diagnostic.
* src/usermod.c: Check early if /etc/subuid (/etc/subgid) exists
	when option -v/-V (-w/-W) are provided.
2013-08-15 17:30:19 +02:00
Nicolas François 2e46882a9b Fix parse of ranges.
* src/usermod.c: Fix parse of ranges. The hyphen might be followed
	by a negative integer.
2013-08-15 17:30:19 +02:00
Nicolas François 5917347c6f Fix boundary conditions.
* lib/subordinateio.c (find_free_range): max is allowed for new
	ranges.
2013-08-15 17:30:19 +02:00
Nicolas François 7d5732cb49 Remove dead code.
* libmisc/find_new_sub_gids.c: Remove dead code.
	find_new_sub_gids() is always called with *range_count set to 0.
	It's more difficult to keep the subordinate GIDs and UIDs
	synchronized, than for the user's UID/GId because the count of
	subordinate IDs may differ.
	* libmisc/find_new_sub_uids.c: Likewise.
	* lib/subordinateio.h, lib/subordinateio.c: Remove APIs that are
	no more needed: is_sub_uid_range_free(), is_sub_gid_range_free(),
	is_range_free().
2013-08-15 17:30:19 +02:00
Nicolas François 1a8d386288 Subordinate IDs require 32bit uid_t/gid_t
* configure.in: Check if sizeof uid_t and gid_t is larger than 32
	bit to support subordinate IDs.
2013-08-14 20:22:15 +02:00
Nicolas François 0f26591422 Align coding style.
* lib/subordinateio.c: Avoid implicit conversion of pointers and
	integers to booleans.
	* lib/subordinateio.c: Added brackets.
2013-08-14 00:19:19 +02:00
Nicolas François cd1bd8bf4c Add schematics with ranges to help reviews.
* lib/subordinateio.c: Add schematics with ranges to help reviews.
2013-08-14 00:19:19 +02:00
Nicolas François b84b918464 Avoid dead branches.
* lib/subordinateio.c: Avoid dead branches.

Note: code is equivalent.
2013-08-14 00:19:19 +02:00
Nicolas François 00f573fce2 Fix copyright dates. 2013-08-13 23:13:26 +02:00
Nicolas François 9951b1f569 Fail in case arguments are provided after options.
* src/vipw.c: Fail in case arguments are provided after options.
	Debian#677812
2013-08-13 23:13:09 +02:00
Nicolas François 0094abea6e Fix count for ranges truncated in remove_range().
* lib/subordinateio.c: Fix count for ranges truncated in
	remove_range().
2013-08-13 22:29:16 +02:00
Nicolas François 8781aff637 Terminate the child before closing the PAM session.
* src/su.c: Terminate the child (if needed) before closing the PAM
	session. This is probably more correct, and avoid reporting
	termination from signals possibly sent by PAM modules (e.g. former
	versions of pam_systemd). Debian#670132
2013-08-13 19:48:53 +02:00
Nicolas François a5e3dbb0e3 Reset caught variable when signal is handled by su.
* src/su.c: When a SIGTSTP is caught, reset caught to 0. There is
	no need to kill the child in such case after su is resumed. This
	remove the "Session terminated, terminating shell...
	...terminated." messages in such case.
2013-08-13 19:42:50 +02:00
Nicolas François 29bd7e1929 Document checks performed by newgidmap/newuidmap
* man/newgidmap.1.xml: Document the checks performed before
	setting the mapping in /proc.
	* man/newuidmap.1.xml: Likewise.
2013-08-13 19:38:41 +02:00
Nicolas François e1a4b6e57b Document the semantic of ranges.
* libmisc/idmapping.h: Document what the upper and lower fields
	are in struct map_range.
	* man/newgidmap.1.xml: Document when the gid, gidlower and count
	argument are.
	* man/newuidmap.1.xml: Likewise for uid, uidlower and count.
2013-08-13 19:28:07 +02:00
Nicolas François 5884ba907c (shadow_random): Use long instead of size_t.
* libmisc/salt.c (shadow_random): Use long instead of size_t.
	Compatibility with size_t is easier to check since it's used for
	smaller numbers (salt size).
2013-08-13 19:16:24 +02:00
Nicolas François 64fe2f7db6 Add splint annotations.
* lib/groupmem.c: Add splint annotations. The added memset makes
	splint think data was allocated.
	* lib/pwmem.c: Likewise.
	* lib/sgroupio.c: Likewise.
	* lib/shadowmem.c: Likewise.
2013-08-13 19:13:45 +02:00
Nicolas François 3bdf723bab Improve documentation.
* man/login.defs.d/SUB_GID_COUNT.xml: Document that the behavior
	of useradd and newusers depends on the existence of /etc/subgid.
	* man/login.defs.d/SUB_UID_COUNT.xml: Likewise for /etc/subuid.
2013-08-13 00:21:02 +02:00
Nicolas François 9126425a21 Improve error reporting.
* src/useradd.c: Change message in case of find_new_sub_uids /
	find_new_sub_gids failure. This complements the messages already
	provided by these APIs.
2013-08-13 00:13:12 +02:00
Nicolas François bfbd83239e Fix handling of boundaries.
* lib/subordinateio.c: Fix handling of boundaries.
	* libmisc/find_new_sub_uids.c: Likewise.
	* libmisc/find_new_sub_gids.c: Likewise.
2013-08-13 00:11:24 +02:00
Nicolas François d9d1bb4acb Fix removal of ranges.
* lib/subordinateio.c: Fix removal of ranges. The database needs
	to be marked as changed or commonio_close will discard any change.
2013-08-12 23:57:32 +02:00
Nicolas François 5d3a785c55 Manpages improvement for subordinate IDs.
* man/newusers.8.xml: Include documentation of SUB_GID_MIN,
	SUB_GID_MAX, SUB_GID_COUNT, SUB_UID_MIN, SUB_UID_MAX,
	SUB_UID_COUNT.
	* man/useradd.8.xml: Likewise.
	* man/usermod.8.xml: Likewise.
	* man/newusers.8.xml: Document usage of /etc/subgid /etc/subuid.
	* man/useradd.8.xml: Likewise.
	* man/userdel.8.xml: Likewise.
	* man/usermod.8.xml: Likewise.
	* man/newusers.8.xml: Add references to subgid(5) and subuid(5).
	* man/useradd.8.xml: Likewise.
	* man/userdel.8.xml: Likewise.
	* man/subgid.5.xml: Sort references alphabetically.
	* man/subuid.5.xml: Likewise.
	* man/subgid.5.xml: Add references to newusers(8), useradd(8),
	userdel(8), usermod(8), user_namespaces(7).
	* man/subuid.5.xml: Likewise.
2013-08-11 16:09:59 +02:00
Nicolas François eeab0bebfa Sort references alphabetically.
* man/newgidmap.1.xml: Sort references alphabetically.
	* man/newuidmap.1.xml: Likewise.
2013-08-11 15:48:57 +02:00
Nicolas François d611d54ed4 Allow disabling of subordinate IDs.
* configure.in: Add configure options --enable-subordinate-ids /
	--disable-subordinate-ids. Enabled by default.
	* lib/prototypes.h: Include <config.h> before using its macros.
	* lib/commonio.h, lib/commonio.c: Define commonio_append only when
	ENABLE_SUBIDS is defined.
	* lib/prototypes.h, libmisc/find_new_sub_gids.c,
	libmisc/find_new_sub_uids.c: Likewise.
	* lib/subordinateio.h, lib/subordinateio.c: Likewise.
	* libmisc/user_busy.c: Only check if subordinate IDs are in use if
	ENABLE_SUBIDS is defined.
	* src/Makefile.am: Create newgidmap and newuidmap only if
	ENABLE_SUBIDS is defined.
	* src/newusers.c: Check for ENABLE_SUBIDS to enable support for
	subordinate IDs.
	* src/useradd.c: Likewise.
	* src/userdel.c: Likewise.
	* src/usermod.c: Likewise.
	* man/Makefile.am: Install man1/newgidmap.1, man1/newuidmap.1,
	man5/subgid.5, and man5/subuid.5 only if ENABLE_SUBIDS is defined.
	* man/fr/Makefile.am: Install man1/newgidmap.1, man1/newuidmap.1,
	man5/subgid.5, and man5/subuid.5 (not translated yet).
	* man/generate_mans.mak: Add xsltproc conditionals
	subids/no_subids.
	* man/login.defs.d/SUB_GID_COUNT.xml: Add dependency on subids
	condition.
	* man/login.defs.d/SUB_UID_COUNT.xml: Likewise.
	* man/usermod.8.xml: Document options for subordinate IDs and
	reference subgid(5) / subuid(5) depending on the subids condition.
2013-08-11 15:46:59 +02:00
Nicolas François 1fb1486c8a Ignore generated newgidmap and newuidmap 2013-08-11 14:48:39 +02:00
Nicolas François d83866d006 Fix typo. 2013-08-11 00:53:50 +02:00
Nicolas François 14ebc92d8c Remove unused variable.
* libmisc/salt.c: Remove unused variable.
2013-08-10 00:11:52 +02:00
Nicolas François 45986f8dc8 Fix for Alioth#314271 (musl libc)
* libmisc/utmp.c: Add include files needed for getaddrinfo().
	See Alioth#314271
2013-08-07 02:18:43 +02:00
Mike Frysinger 561ba96ec7 check for ruserok existence
rlogin support is old school code, so newer C libraries drop support for
ruserok (like uClibc, optionally).  But shadow doesn't build with that,
so have it check for ruserok to optionally enable rlogin.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
2013-08-07 01:44:24 +02:00
Nicolas François cfad7327a5 Editorial changes to usermod(8)
* man/usermod.8.xml: Fix typos and wording.
	* man/usermod.8.xml: Add references to subgid(5) and subuid(5).
2013-08-07 01:36:10 +02:00
Nicolas François 316bc6b3f4 Fix wording: secondary -> subordinate.
* libmisc/find_new_sub_gids.c: Fix wording: secondary ->
	subordinate.
	* libmisc/find_new_sub_uids.c: Likewise.
2013-08-07 01:01:33 +02:00
Nicolas François ac53650da5 Remove duplicate check.
* libmisc/find_new_sub_gids.c: Remove duplicate check (duplicate
	at least in its intent).
2013-08-06 23:59:09 +02:00
Nicolas François 94c52130be Fix typos.
* src/usermod.c: Fix typos.
2013-08-06 22:29:40 +02:00
Nicolas François ee2b88b7b1 I find it clearer with the words in that order.
* man/subgid.5.xml: Reorder words.
	* man/subuid.5.xml: Likewise.
2013-08-06 22:25:08 +02:00
Nicolas François 1955170a14 Fix typos.
* man/subgid.5.xml: Fix typos.
	* man/subuid.5.xml: Likewise.
	* man/subgid.5.xml: Fix copy-paste errors from subuid.5.xml.
2013-08-06 22:22:57 +02:00
Nicolas François 9fdd176e45 Remove copy-pasted NOTE.
* man/newgidmap.1.xml: Remove copy-pasted NOTE.
	* man/newuidmap.1.xml: Likewise.
2013-08-06 21:01:53 +02:00
Nicolas François bae65562ef Remove unused variables.
* lib/subordinateio.c: Remove unused variables.
2013-08-06 20:59:52 +02:00
Nicolas François 95d1e146b2 Fix typos.
* man/login.defs.d/SUB_GID_COUNT.xml: Fix typo.
	* man/login.defs.d/SUB_UID_COUNT.xml: Likewise.
	* man/login.defs.d/SUB_UID_COUNT.xml: Fix copy-paste issue from
	SUB_GID_COUNT.
	* man/newgidmap.1.xml: Fix Typo.
	* src/useradd.c: Fix typos.
	* lib/subordinateio.c: Fix typos.
2013-08-06 20:59:13 +02:00
Nicolas François fcb7222b1a Fix Debian bug #675824
* lib/groupmem.c (__gr_dup): Support libc which define other
	fields in struct group.
	* lib/pwmem.c: Likewise for struct passwd.
	* lib/shadowmem.c: Likewise for struct spwd.
	* lib/sgroupio.c: Apply same logic, even if this structure is
	defined internally.
2013-08-06 16:33:27 +02:00
Nicolas François 5d491ef9da Revert b10cba0e0a
The length of the concatenated 2 lines was correct.
2013-08-05 23:16:00 +02:00
Serge Hallyn c0ce911b5e userns: add argument sanity checking
In find_new_sub_{u,g}ids, check for min, count and max values.

In idmapping.c:get_map_ranges(), make sure that the value passed
in for ranges did not overflow.  Couldn't happen with the current
code, but this is a sanity check for any future potential mis-uses.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2013-08-05 10:08:46 -05:00
Eric W. Biederman 673c2a6f9a newuidmap,newgidmap: New suid helpers for using subordinate uids and gids
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2013-08-05 10:08:46 -05:00
Serge Hallyn 2cffa14105 fix typo in subxid.5
login.defs, not logindefs.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2013-08-05 10:08:45 -05:00
Serge Hallyn c485cfabd8 usermod: add v:w:V:W: to getopt
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2013-08-05 10:08:45 -05:00
Serge Hallyn 3b3c8001fe subordinateio: Fix subordinate_parse to have an internal static buffer
subordinate_parse is supposed to return a static structure that
represents one line in /etc/subuid or /etc/subgid.  I goofed and
failed to make the variable rangebuf that holds the username of
in the returned structure static.

Add this missing static specification.

Author: <Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2013-08-05 10:08:45 -05:00
Serge Hallyn 5f2e4b18f8 Add LIBSELINUX to newuidmap and newgidmap LDADD
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
2013-08-05 10:08:45 -05:00
Eric W. Biederman 2cc8c2c0dc newusers: Add support for assiging subordinate uids and gids.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
2013-08-05 10:08:45 -05:00
Eric W. Biederman d5b3092331 usermod: Add support for subordinate uids and gids.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
2013-08-05 10:08:45 -05:00
Eric W. Biederman 89f7b0868c Add support for detecting busy subordinate user ids
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
2013-08-05 10:08:45 -05:00
Eric W. Biederman 87253ca906 useradd: Add support for subordinate user identifiers
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
2013-08-05 10:08:45 -05:00
Eric W. Biederman 7296cbdbfe userdel: Add support for removing subordinate user and group ids.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
2013-08-05 10:08:45 -05:00
Eric W. Biederman a8f26262cf Implement find_new_sub_uids find_new_sub_gids
Functions for finding new subordinate uid and gids ranges for use
with useradd.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
2013-08-05 10:08:45 -05:00
Eric W. Biederman f28ad4b251 Add backend support for suboridnate uids and gids
These files list the set of subordinate uids and gids that users are allowed
to use.   The expect use case is with the user namespace but other uses are
allowed.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
2013-08-05 10:08:45 -05:00
Eric W. Biederman 5620c5ab5d Implement commonio_append.
To support files that do not have a simple unique key implement
commonio_append to allow new entries to be added.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
2013-08-05 10:08:45 -05:00
Eric W. Biederman 23fd6cb1da login.defs.5: Document the new variables in login.defs
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
2013-08-05 10:08:45 -05:00
Eric W. Biederman a881a2c8d4 Documentation for /etc/subuid and /etc/subgid
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
2013-08-05 10:08:45 -05:00
Nicolas François 60fc4bbf57 Debian bug 677275 - random() max value
* libmisc/salt.c: random() max value is 2^31-1 (same as RAND_MAX
	on GNU). As it is not clear whether on some systems the max value
	can exceed this number and whether some systems have max values
	which would be lower, we take this into account when defining the
	salt size and number of rounds for SHA encrypted passwords. Higher
	values are favored.
2013-08-05 14:19:23 +02:00
Nicolas François 7903a1b767 Fix su/1 documentation of -
* man/su.1.xml: With getopt, '-' does not need to be the last
	option, but it is recommended for portability.
	Closes https://bugs.launchpad.net/bugs/1100775
2013-08-04 23:45:31 +02:00
Nicolas François 4dbca60435 Add NEWS entries. 2013-08-04 23:29:06 +02:00
Nicolas François a168d046f3 Fix typo in comment. 2013-08-04 15:56:32 +02:00
Nicolas François 08489a4e22 Fix translations (--home became --home-dir)
* man/po/da.po: Fix translation (--home became --home-dir).
	* man/po/de.po: Likewise.
	* man/po/fr.po: Likewise.
	* man/po/pl.po: Likewise.
	* man/po/ru.po: Likewise.
	* man/po/sv.po: Likewise.
2013-08-04 15:52:00 +02:00
Nicolas François 0d66002c95 Do not allocate more than necessary
Review b10cba0e0a and 7a16f4582d:
	* lib/groupio.c (merge_group_entries): Do not allocate more than
	necessary (sizeof char* instead of char).
	Thanks for Tomáš Mráz (alioth#313962)
	* lib/groupio.c (merge_group_entries): Document that new_members
	is correctly NULL terminated. (alioth:#313940)

Align previous ChangeLog entries.
2013-08-04 15:36:13 +02:00
Nicolas François e8ab31d009 Review 52a38d5509
* Changelog: Update documentation of 2013-07-28  mancha entry.
	* lib/prototypes.h, lib/encrypt.c: Update splint marker,
	pw_encrypt can return NULL.
	* lib/encrypt.c: Fix outdated statement on GNU crypt.
	* src/chgpasswd.c: Improve diagnostic to user when pw_encrypt
	fails and use fail_exit() instead of exit().
	* src/chpasswd.c: Likewise.
	* src/newusers.c: Likewise.
	* src/passwd.c: Likewise when new password is encrypted.
	* src/newgrp.c: Improve diagnostic to user and syslog when
	pw_encrypt fails.  Do not apply 1s penalty as this is not an
	invalid password issue.
	* src/passwd.c: Likewise when password is checked.
2013-08-04 00:27:53 +02:00
Nicolas François ee1952424d Fix memory leak.
* libmisc/setupenv.c: Free pw_dir and pw_shell before reallocating
	them.
2013-08-02 20:28:24 +02:00
Nicolas François b6c1a8579e Fix segfaults
* libmisc/setupenv.c: xstrdup the static char* temp_pw_dir /
	temp_pw_shell. That way we can continue to use pw_free() without
	segving. Thanks to Serge Hallyn for the patch.
2013-08-02 20:24:20 +02:00
Yuri Kozlov 64ddc26bbf Completed Russian translation 2013-08-01 21:24:46 +02:00
Michael Scherer 4e65be1211 use chdir() before calling chroot() 2013-07-29 11:05:16 +02:00
bubulle 9be164101d Replace "--home" by "--home-dir" in useradd(8) manpage (and
translations)
2013-07-29 10:58:50 +02:00
Ville Skyttä 48b2c4bff4 Syntax fix in Japanese manpage 2013-07-29 10:18:41 +02:00
Brad Hubbard 7a16f4582d fix uninitialised memory in merge_group_entries causes segfault in useradd by
changing a call to malloc to a call to calloc
2013-07-29 10:13:12 +02:00
Brad Hubbard b10cba0e0a add newline char when two lines are concatenated 2013-07-29 10:05:52 +02:00
bubulle d3b95d1d26 Mention Alioth bug fixes 2013-07-29 10:01:23 +02:00
Guido Trentalancia 04b950b824 fix typographic errors and use a better format 2013-07-28 19:04:50 +02:00
Simon Brandmair 4145b98314 German manpages translation update 2013-07-28 18:57:18 +02:00
mancha 52a38d5509 crypt() in glibc/eglibc 2.17 now fails if passed
a salt that violates specs. On Linux, crypt() also fails with
DES/MD5 salts in FIPS140 mode. Rather than exit() on NULL returns
we send them back to the caller for appropriate handling.
2013-07-28 18:41:11 +02:00
bubulle a6769c050b FIx date in changelog 2013-07-28 18:39:10 +02:00
Colin Watson d172cccd07 Kill the child process group, rather than just the immediate child;
this is needed now that su no longer starts a controlling terminal
when not running an interactive shell (closes: Debian#713979)
2013-07-28 14:38:12 +02:00
bubulle 945eb8f50b if using the static char* for pw_dir, strdup it so pw_free() can be used. (Closes: Debian#691459) 2013-07-28 14:16:09 +02:00
bubulle c11132a3a1 Prepare for next point release 4.2 2013-07-28 12:27:15 +02:00
nekral-guest 32726af23a 2012-04-15 Robert Luberda <robert@debian.org>
* man/po/pl.po: Complete translation of logoutd(8) in Polish.
2012-05-25 14:05:30 +00:00
nekral-guest 1c78e3f3b8 * man/po/shadow-man-pages.pot: Regenerated.
* man/po/*.po: Updated PO files.
2012-05-25 13:40:31 +00:00
nekral-guest 9151e673e4 * NEWS: Set release date. 2012-05-25 11:51:53 +00:00
nekral-guest 042d6c48b3 * man/*.xml: Add author based on copyright statement.
* man/<ll>/*.[1358], man/<ll>/man[1358]/*.[1358],
	man/<ll>/Makefile.am: Sort manpages per section as the generated
	manpages.
2012-05-25 11:45:21 +00:00
nekral-guest cdd3ebfcf1 * po/shadow.pot, man/po/shadow-man-pages.pot: Regenerated.
* po/*.po, man/po/*.po: Updated PO files.
2012-05-20 21:03:11 +00:00
nekral-guest faaa8daffb * man/Makefile.am, man/generate_mans.mak: Update clean targets,
due to the generation in separate sub folders.
2012-05-20 21:01:24 +00:00
nekral-guest e108f473ec * man/su.1.xml: Document author to avoid warnings during
generation. This needs to be rolled out to other manpages.
	* man/generate_mans.mak: Do not add a AUTHOR section in the man
	pages.
2012-05-20 17:40:23 +00:00
nekral-guest f100b5ea7e * src/su.c: non PAM enabled versions: do not fail if su is called
without a controlling terminal. Ignore ENXIO errors when opening
	/dev/tty.
2012-05-20 16:15:14 +00:00
nekral-guest 8690c74d6a * src/useradd.c: Cleanup, return code 13 no more used.
* man/useradd.8.xml: Document return code 14, and remove return
	code 13.
2012-05-20 12:26:54 +00:00
nekral-guest 788374bd8c * NEWS, man/generate_mans.mak: Generate manpages in man1, man3,
man5, man8 subdirectories. This fix the generation of .so links
	which did not point to a path relative to the top-level manual
	hierarchy.
	* man/generate_mans.mak: Update man paths accordingly.
	* man/Makefile.am: Likewise.
	* man/da/Makefile.am: Likewise.
	* man/de/Makefile.am: Likewise.
	* man/fr/Makefile.am: Likewise.
	* man/it/Makefile.am: Likewise.
	* man/pl/Makefile.am: Likewise.
	* man/ru/Makefile.am: Likewise.
	* man/sv/Makefile.am: Likewise.
	* man/zh_CN/Makefile.am: Likewise.
2012-05-20 10:18:33 +00:00
nekral-guest d755279fad * configure.in: Prepare for next point release 4.1.5.1. 2012-05-20 10:07:55 +00:00
nekral-guest fb7906760e * configure.in: Remove deprecated AM_C_PROTOTYPES (no more
supported in automake 1.12).
2012-05-19 08:27:42 +00:00
nekral-guest 1a7960421e * src/useradd.c: Keep the default file as much as possible to
avoid issue in case of crash. Use link instead of rename.
2012-05-18 20:28:16 +00:00
nekral-guest 56845ad1c1 * lib/commonio.c: Fix labeling of /etc/{passwd,shadow,group,gshadow}.
It will basically label them with same context as
	/etc/{passwd+,shadow+,group+,gshadow+}
2012-05-18 19:44:53 +00:00
nekral-guest 1e0450dfb1 * src/pwunconv.c: Do not check spw_close() return value (file is
opened readonly).
	* src/grpunconv.c: Do not check sgr_close() return value (file is
	opened readonly).
2012-05-18 19:32:32 +00:00
nekral-guest 46f6d77c55 Cleanup. 2012-05-18 19:27:02 +00:00
nekral-guest 17deaa39f5 * NEWS, src/userdel.c: Fix segfault when userdel removes the
user's group.
2012-05-18 18:56:24 +00:00
nekral-guest f243d4077d * NEWS, src/login.c: Log in utmp / utmpx / wtmp also when PAM is
enabled. This is not done by pam_lastlog. This was broken on
	2011-07-23.
	* NEWS, libmisc/utmp.c: Do not log in wtmp when PAM is enabled.
	This is done by pam_lastlog.
2012-05-18 17:57:52 +00:00
bubulle f741583f1a French translation of manpages completed 2012-05-17 09:17:53 +00:00
bubulle 1586a91909 Add Debian bug closure to avoid forgetting in debian/changelog when uploading a new upstream in Debian 2012-05-17 09:14:42 +00:00
bubulle de8a22a2f4 German translation of manpages updated 2012-05-17 09:13:09 +00:00
bubulle 19d5ec6921 Complete translation of logoutd(8) in Polish. Patch by Robert Luberda 2012-04-15 10:54:03 +00:00
nekral-guest 9f34a68dba * NEWS: New placeholder for the next release (4.1.5.1 expected) 2012-02-13 20:33:28 +00:00
nekral-guest 0c1cbaede8 2012-02-13 Mike Frysinger <vapier@gentoo.org>
* src/passwd.c: (non PAM flavour) Report permission denied when
	access to /etc/shadow fails with EACCES.
2012-02-13 20:32:00 +00:00
nekral-guest e363962dd2 2012-02-13 Mike Frysinger <vapier@gentoo.org>
* lib/nscd.c: Add missing newline to error message.
	* lib/nscd.c: If nscd is installed but not in use, then running
	`nscd -i` will exit(1). We shouldn't warn in this case since this
	is not abnormal behavior.
2012-02-13 20:09:59 +00:00
nekral-guest 659684836d 2012-02-13 Mike Frysinger <vapier@gentoo.org>
* man/.gitignore: Add generate_mans.deps
2012-02-13 20:04:40 +00:00
nekral-guest 19699033bf 2012-02-13 Mike Frysinger <vapier@gentoo.org>
* man/grpck.8.xml: Relocate space.
2012-02-13 20:00:34 +00:00
nekral-guest 011c5155fa 2012-02-13 Mike Frysinger <vapier@gentoo.org>
* libmisc/copydir.c: Add missing #include <stdarg.h>
2012-02-13 19:16:29 +00:00
nekral-guest c18ec76e85 * NEWS: Set release date. 2012-02-12 21:29:41 +00:00
nekral-guest b261fbd7bb * po/shadow.pot, man/po/shadow-man-pages.pot: Regenerated.
* po/*.po, man/po/*.po: Updated PO files.
2012-02-12 15:02:45 +00:00
nekral-guest c0a22d7b56 Ignore generated files. 2012-02-11 18:30:42 +00:00
nekral-guest 4f275ec75b * man/it/Makefile.am: Activate all manpages. 2012-02-11 18:29:17 +00:00
nekral-guest 1528ae16a0 * man/po/it.po: Updated after review. 2012-02-11 18:28:04 +00:00
nekral-guest d069726634 * man/po/it.po: Updated to 1173t. 2012-02-11 09:31:17 +00:00
nekral-guest 2aa73f7823 * man/useradd.8.xml, man/su.1.xml, man/po/da.po, man/po/ru.po,
man/po/fr.po, man/po/de.po, man/po/sv.po, man/po/pl.po,
	man/po/it.po, man/po/shadow-man-pages.pot, man/po/zh_CN.po: Fix
	two typos. Thanks to Giuseppe Sacco. Unfuzzy translations
	* po/kk.po, po/nb.po, po/el.po, po/ca.po, po/ja.po: Re-generate.
	* man/login.defs.d/ENV_PATH.xml, man/login.defs.d/ENV_SUPATH.xml:
	Fix typo.
2012-02-02 19:05:34 +00:00
nekral-guest c71d787454 2012-01-28 Innocent De Marchi <tangram.peces@gmail.com>
* po/ca.po: Updated to 557t.
2012-01-28 19:13:08 +00:00
nekral-guest c1eecc94ec * NEWS, configure.in, man/da/Makefile.am, man/Makefile.am: Build
manpages with more than 50% translated messages.
	* man/fr/Makefile.am: Add missing manpages: chgpasswd.8,
	groupmems.8, nologin.8, sulogin.8.
	* man/de/Makefile.am: Add missing manpages: chage.1, chgpasswd.8,
	chpasswd.8, expiry.1, faillog.5, faillog.8, getspnam.3, gpasswd.1,
	groupadd.8, groupdel.8, groupmems.8, groupmod.8, grpck.8,
	grpconv.8, grpunconv.8, gshadow.5, lastlog.8, login.defs.5,
	logoutd.8, newusers.8, nologin.8, pwck.8, pwconv.8, pwunconv.8,
	sg.1, shadow.3, shadow.5, suauth.5, useradd.8, userdel.8,
	usermod.8, limits.5, login.access.5, porttime.5, id.1, sulogin.8
	* man/zh_CN/Makefile.am: Add missing manpages: chgpasswd.8,
	groupmems.8, nologin.8, sulogin.8
	* man/pl/Makefile.am, man/sv/Makefile.am, man/it/Makefile.am:
	Translate only manpages with more than 50% translated messages.
	* man/po/da.po: Do not translate names of manpages (newusers,
	limits, groups)
2012-01-28 16:53:23 +00:00
bubulle 917e9af67b Russian manpages translation update 2012-01-28 13:29:13 +00:00
bubulle 6e6ef6fd57 French translation updates 2012-01-27 18:45:49 +00:00
bubulle 6e26b9a42c Danish translation added 2012-01-26 18:58:20 +00:00
bubulle 85c27fd775 Danish translation update 2012-01-26 18:54:44 +00:00
nekral-guest 4efcee14e4 2012-01-23 Thomas Vasileiou <thomas-v@wildmail.com>
* po/el.po: Updated to 553t.
2012-01-23 22:29:33 +00:00
nekral-guest e4a5d4de87 2012-01-22 Baurzhan Muftakhidinov <baurthefirst@gmail.com>
* po/kk.po: Updated to 557t.
2012-01-22 17:32:49 +00:00
bubulle 4502d89d87 Portuguese translation update 2012-01-21 07:17:05 +00:00
bubulle b2b259a985 German translation update 2012-01-19 19:37:36 +00:00
nekral-guest 1640d73997 2012-01-18 Bjørn Steensrud <bjornst@skogkatt.homelinux.org>
* po/nb.po: Updated to 557t. Thanks also to Hans Fredrik Nordhaug.
2012-01-18 21:08:28 +00:00
nekral-guest 1b4d4b6708 2012-01-16 NAKANO Takeo <nakano@webmasters.gr.jp>
* po/ja.po: Updated to 557t
2012-01-16  Simon Brandmair  <sbrandmair@gmx.net>
	* man/po/de.po: Updated to 1173t.
2012-01-18 21:01:50 +00:00
nekral-guest 22591a77b2 New entry for vipw. 2012-01-15 21:26:56 +00:00
nekral-guest 1161388b2b Indicate the CVE number. 2012-01-15 21:22:05 +00:00
nekral-guest 4fb8cf2f6b Document last translation updates. 2012-01-15 21:21:01 +00:00
bubulle db0d48471e Simplified Chinese translation update 2012-01-14 13:28:36 +00:00
bubulle b949241d12 Russian translation update 2012-01-09 18:56:42 +00:00
nekral-guest 4dfd1519ac * po/shadow.pot, man/po/shadow-man-pages.pot: Regenerated.
* po/*.po, man/po/*.po: Updated PO files.
2012-01-08 23:36:18 +00:00
nekral-guest 59e64f8b82 * lib/selinux.c, lib/semanage.c: prototypes.h was not included. 2012-01-08 16:06:57 +00:00
nekral-guest 7ac5cc7dd0 * lib/prototypes.h: Cleanup. 2012-01-08 16:04:27 +00:00
nekral-guest 2c24c012bd * lib/prototypes.h, lib/Makefile.am, po/POTFILES.in,
libmisc/copydir.c, lib/selinux.c: Move set_selinux_file_context()
	and reset_selinux_file_context() from libmisc/copydir.c to
	lib/selinux.c.
	* lib/commonio.c: Use set_selinux_file_context() and
	reset_selinux_file_context() instead of using the existing
	database SELinux context to set the context for the newly created
	files.
2011-12-09 22:13:02 +00:00
nekral-guest cc8be680ca * src/vipw.c: Do not use a hardcoded program name in the usage
message.
2011-12-09 21:35:57 +00:00
nekral-guest 3084e71acb * po/ca.po, po/cs.po, po/da.po, po/de.po, po/es.po, po/eu.po,
po/fr.po, po/ja.po, po/kk.po, po/pt.po, po/pt_BR.po, po/ru.po,
	po/sk.po, po/sv.po, po/vi.po, po/zh_CN.po: Quick unfuzzy.
2011-12-09 21:35:47 +00:00
nekral-guest a92f55b609 * src/newusers.c, src/chpasswd.c, src/chgpasswd.c: Harmonize
usage messages.
2011-12-09 21:31:39 +00:00
nekral-guest daa8d1141e * lib/Makefile.am, lib/prototypes.h, lib/selinux.c,
lib/semanage.c, po/POTFILES.in: Move lib/selinux.c to
	lib/semanage.c.
2011-12-09 21:30:19 +00:00
nekral-guest 360f12cd44 * src/usermod.c, man/usermod.8.xml: usermod -Z "" removes the
SELinux user mapping for the modified user.
	* src/useradd.c: Zflg is #defined as user_selinux non empty.
2011-11-21 22:02:15 +00:00
nekral-guest e570b8ded4 * libmisc/copydir.c: Ignore errors to copy ACLs if the operation
is not supported.
2011-11-21 19:34:22 +00:00
nekral-guest bd4a6c9966 * src/passwd.c: Add missing cast.
* lib/commonio.c: Avoid multiple statements per line.
	* lib/commonio.c: Ignore fclose return value when the file was
	open read only or was not changed, or if an error is already
	reported.
2011-11-19 22:00:00 +00:00
nekral-guest 4049c0e69e * src/chage.c: Cast 3rd date_to_str parameter to a time_t 2011-11-19 21:56:10 +00:00
nekral-guest 05823ad867 * lib/selinux.c: vasprintf requires _GNU_SOURCE to be defined
before including stdio.h.
2011-11-19 21:55:00 +00:00
nekral-guest 82d767d121 * libmisc/root_flag.c, src/gpasswd.c, src/chsh.c: Add splint
annotations.
	* src/pwconv.c, src/pwunconv.c, src/grpconv.c, src/grpunconv.c:
	Ignore return value of spw_rewind, pw_rewind, sgr_rewind, and
	gr_rewind.
	* lib/commonio.h: Both head and tail cannot be owned. Set tail as
	dependent.
	* src/expiry.c: Ignore return value of expire ().
	* src/expiry.c: The catch_signals function does not use its sig
	parameter.
	* src/userdel.c: Last audit_logger parameter is a
	shadow_audit_result, use SHADOW_AUDIT_FAILURE instead of 0.
2011-11-19 21:51:52 +00:00
nekral-guest 6e2c6ffdf7 * src/faillog.c: The fail_max field is a short, use a short also
for the max argument of setmax / setmax_one.
	* src/faillog.c: Fail with an error message when faillog fails to
	write to the faillog database.
2011-11-19 21:44:34 +00:00
nekral-guest 5762d08f4f * man/gpasswd.1.xml: Document the difference between the -r and -R
options.
2011-11-19 14:34:59 +00:00
nekral-guest 61bb0aa943 * man/useradd.8.xml, man/groupadd.8.xml, man/usermod.8.xml,
man/groupmod.8.xml: Avoid hardcoded values, and reference instead
	the configuration options (e.g. UID_MIN)
	* man/groupmod.8.xml, man/usermod.8.xml: Add missing reference to
	login.defs
	* man/login.defs.d/UID_MAX.xml, man/login.defs.d/SYS_UID_MAX.xml,
	man/login.defs.d/GID_MAX.xml, man/login.defs.d/SYS_GID_MAX.xml:
	Document the default values.
2011-11-19 14:33:53 +00:00
nekral-guest 2f1e13ff7a Ignore the generated POTFILES file. 2011-11-19 14:29:20 +00:00
nekral-guest 653d22c3e9 * src/gpasswd.c: Change of group password enforces gshadow
password. Set /etc/group password to "x".
2011-11-19 14:27:48 +00:00
nekral-guest 8f008f8319 Fix typos. 2011-11-19 14:20:52 +00:00
nekral-guest e538a4e2a3 Add missing NEWS documentation.
* NEWS, README, src/useradd.c, src/usermod.c, src/userdel.c,
	configure.in: Use libsemanage instead of semanage.
2011-11-17 21:52:49 +00:00
nekral-guest 29050eadb5 * NEWS, src/userdel.c, man/userdel.8.xml: Add option -Z/--selinux-user.
* libmisc/system.c, lib/prototypes.h, libmisc/Makefile.am: Removed
	safe_system().
	* lib/selinux.c, po/POTFILES.in, lib/prototypes.h,
	lib/Makefile.am: Added helper functions for semanage.
	* README, src/useradd.c, src/usermod.c, src/userdel.c,
	configure.in: Use libsemanage instead of semanage.
2011-11-17 21:51:07 +00:00
nekral-guest f3ef11056f Re-indent. 2011-11-17 21:32:26 +00:00
nekral-guest ae0229549d 2011-11-16 Peter Vrabec <pvrabec@redhat.com>
* src/Makefile.am: useradd may need the LIBATTR library.
2011-11-16 21:17:43 +00:00
nekral-guest 2e1652fdec 2011-11-16 Peter Vrabec <pvrabec@redhat.com>
* libmisc/copydir.c: Ignore perm_copy_file() errors with errno set
	to ENOTSUP.
2011-11-16 21:00:43 +00:00
nekral-guest 72ba5c4de7 * libmisc/root_flag.c: Add missing #include <stdio.h> 2011-11-16 19:34:39 +00:00
nekral-guest d2a516a75d * src/useradd.c: Compil fix when SHADOWGRP is not enabled. 2011-11-16 19:33:51 +00:00
nekral-guest 725e83ac21 Unfuzzy. 2011-11-14 23:37:31 +00:00
nekral-guest 3f84cb3699 * po/shadow.pot, man/po/shadow-man-pages.pot: Regenerated.
* po/*.po, man/po/*.po: Updated PO files.
2011-11-13 18:21:43 +00:00
nekral-guest d65129f3c8 Ignore generated file generate_mans.deps 2011-11-13 17:42:05 +00:00
nekral-guest 57f9d5ae9c * src/chage.c, src/chfn.c, src/chgpasswd.c, src/chpasswd.c,
src/chsh.c, src/groupadd.c, src/groupdel.c, src/groupmems.c,
	src/groupmod.c, src/newusers.c, src/useradd.c, src/userdel.c,
	src/usermod.c: Provide the PAM error
	message instead of our own, and log error to syslog.
	* src/groupmems.c: Exit with exit rather than fail_exit in usage().
	* src/newusers.c: Check the number of arguments.
	* src/newusers.c: Do not create the home directory when it is not
	changed.
	* src/useradd.c: Set the group password to "!" rather "x" if there
	are no gshadow file.
2011-11-13 16:24:57 +00:00
nekral-guest 2ecea675ee Fix cut&paste issue from yesterday. 2011-11-13 16:24:49 +00:00
nekral-guest f64c88d629 * src/pwck.c: Removed pw_opened.
* src/pwck.c: optind cannot be greater than argc.
	* src/pwck.c: If spw_opened, then is_shadow is implicitly set.
	* src/pwck.c: Do not report passwd entry without x password and a
	shadow entry in --quiet mode (no interaction with the caller)
	* src/pwck.c: Do not check if the last password change is in the
	future if the time is set to 0.
2011-11-13 16:24:39 +00:00
nekral-guest 3c608e56f6 * libmisc/root_flag.c: Drop privileges before changing root. The
--root option should not be used by regular users for suid utils.
	* libmisc/root_flag.c: Improve error messages.
2011-11-11 12:09:58 +00:00
nekral-guest f54a68ac76 * src/pwck.c: Compile fix for TCB. 2011-11-11 12:00:05 +00:00
nekral-guest 3bb7c43694 * libmisc/copydir.c: Avoid conflict with glibc. Rename error to
error_acl.
2011-11-11 11:59:21 +00:00
nekral-guest 61ba4bf46e * man/newusers.8.xml: Document the optional file argument.
* man/newusers.8.xml: Fix the documentation of the inputs' format.
2011-11-11 11:35:56 +00:00
nekral-guest 184f9d40e6 * man/groupmod.8.xml: Document that the primary group of users may
be changed by groupmod -g.
2011-11-06 19:01:54 +00:00
nekral-guest f3afeb9c04 * NEWS, src/newusers.c, man/newusers.8.xml: Add --root option. 2011-11-06 18:40:22 +00:00
nekral-guest 2a2c8190ec * src/vipw.c: Remove unused variable a. 2011-11-06 18:40:17 +00:00
nekral-guest 45154f1d68 * man/generate_mans.mak: The xml-config files do not depend on the
Makefile.
2011-11-06 18:40:11 +00:00
nekral-guest 7861eaa5ec Re-indent. 2011-11-06 18:40:06 +00:00
nekral-guest f0a63185c9 * src/chage.c, src/chgpasswd.c, src/chpasswd.c, src/chsh.c,
src/faillog.c, src/gpasswd.c, src/groupadd.c, src/groupdel.c,
	src/groupmems.c, src/groupmod.c, src/grpconv.c, src/grpunconv.c,
	src/lastlog.c, src/newusers.c, src/passwd.c, src/pwconv.c,
	src/pwunconv.c, src/su.c, src/useradd.c, src/userdel.c,
	src/usermod.c, src/vipw.c: Align and sort options.
2011-11-06 18:39:59 +00:00
nekral-guest 7d8ca29bea * NEWS, src/pwck.c, man/pwck.8.xm, src/grpck.c, man/grpck.8.xml:
Add --root option.
2011-11-06 18:39:53 +00:00
nekral-guest e4fbf98b18 * man/limits.5.xml, libmisc/limits.c: Sort limit identifiers.
* libmisc/limits.c: Fix support for the K limit identifier.
	* libmisc/limits.c: Add missing default limit for L and U.
2011-11-06 18:39:47 +00:00
nekral-guest f4d95eecc0 Re-indent. 2011-11-06 18:39:42 +00:00
nekral-guest 900943192f * src/pwck.c, man/pwck.8.xml: Add support for long options.
* src/pwck.c, man/pwck.8.xml: Add -h/--help option
	* src/grpck.c, man/grpck.8.xml: Add support for long options.
	* src/grpck.c, man/grpck.8.xml: Add -h/--help option
2011-11-06 18:39:36 +00:00
nekral-guest b9163f6348 * src/expiry.c, man/expiry.1.xml: Add support for long options.
* src/expiry.c, man/expiry.1.xml: Add -h/--help option
2011-11-06 18:39:30 +00:00
nekral-guest 0530588266 * NEWS, src/chfn.c, man/chfn.1.xml: Add --root option. 2011-11-06 18:39:24 +00:00
nekral-guest b26f73f427 * src/chfn.c, man/chfn.1.xml: Add support for long options.
* src/chfn.c, man/chfn.1.xml: Add -u/--help option
2011-11-06 18:39:19 +00:00
nekral-guest e2068416c9 * NEWS, src/vipw.c, man/vipw.8.xml: Add --root option. 2011-11-06 18:39:09 +00:00
nekral-guest a2d23700e4 * NEWS, src/faillog.c, man/faillog.8.xml: Add --root option.
* NEWS, src/lastlog.c, man/lastlog.8.xml: Likewise.
	* src/faillog.c: Add Prog variable, and prefix error messages with
	Prog rather than "faillog".
	* src/lastlog.c: Likewise.
	* src/lastlog.c: Split usage in smaller messages.
2011-11-06 18:39:03 +00:00
nekral-guest 0857837e64 * NEWS, src/chage.c, man/chage.1.xml: Add --root option. Open
audit and syslog after the potential chroot. chage's usage split
	in smaller messages.
2011-11-06 18:38:57 +00:00
nekral-guest d15f2c6214 * src/login.c: re-indent.
* src/login.c: Fix support for sub-logins.
2011-11-06 18:38:51 +00:00
nekral-guest 6eb0500d3d * src/faillog.c, src/chage.c, src/newusers.c, src/su.c: The getopt
index of long options is not used.
2011-11-06 18:38:45 +00:00
nekral-guest 7b8c4952a8 * NEWS, src/gpasswd.c, man/gpasswd.1.xml: Add --root option.
* src/gpasswd.c: The getopt index of long options is not used.
2011-11-06 18:38:39 +00:00
nekral-guest 4beca611fb * NEWS, src/chsh.c, man/chsh.1.xml: Add --root option.
chsh's usage split in smaller messages.
	* src/chsh.c: The getopt index of long options is not used.
2011-11-06 18:38:32 +00:00
nekral-guest 1aa30ba551 * NEWS, src/groupmems.c, man/groupmems.8.xml: Add --root option.
Open syslog after the potential chroot.
	* src/groupmems.c: The getopt index of long options is not used.
2011-11-06 18:38:26 +00:00
nekral-guest fc5cd8840e sort per util. 2011-11-06 18:38:21 +00:00
nekral-guest ec2b9f59f7 * NEWS, src/passwd.c, man/passwd.1.xml: Add --root option.
passwd's usage split in smaller messages.
	* src/passwd.c: Call sanitize_env() before setting the locales.
2011-11-06 18:38:16 +00:00
nekral-guest 799f30b08d * NEWS, src/chpasswd.c, man/chpasswd.8.xml, src/chgpasswd.c,
man/chgpasswd.8.xml: Add --root option.
	* src/chpasswd.c, src/chgpasswd.c: The getopt index of long
	options is not used.
2011-11-06 18:38:10 +00:00
nekral-guest bf90350fe7 * NEWS, src/pwconv.c, src/pwunconv.c, src/grpconv.c,
src/grpunconv.c, man/pwconv.8.xml: Add --root option.
	* src/pwconv.c, src/pwunconv.c, src/grpconv.c, src/grpunconv.c:
	Add --help option.
	* src/pwconv.c, src/pwunconv.c, src/grpconv.c, src/grpunconv.c:
	Add process_flags() and usage().
2011-11-06 18:38:04 +00:00
nekral-guest c017dd73aa * src/groupdel.c: Add process_flags().
* src/groupdel.c, man/groupdel.8.xml: Add --help option.
	* NEWS, src/groupdel.c, man/groupdel.8.xml: Add --root option. Open
	audit and syslog after the potential chroot.
	* src/groupdel.c: Check atexit failures.
2011-11-06 18:37:57 +00:00
nekral-guest 9195f6085d * NEWS, src/groupadd.c, man/groupadd.8.xml: Add --root option. Open
audit and syslog after the potential chroot.
	* src/groupmod.c: The index of long options is not used.
2011-11-06 18:37:51 +00:00
nekral-guest 057cbaa4ae * NEWS, src/groupadd.c, man/groupadd.8.xml: Add --root option. Open
audit after the potential chroot.
	* src/groupadd.c: Check atexit failures.
	* src/groupadd.c: Return E_SUCCESS instead of exit'ing at the end
	of main().
2011-11-06 18:37:45 +00:00
nekral-guest aa2957e62a * NEWS, src/usermod.c, man/usermod.8.xml: Add --root option. Open
audit and syslog after the potential chroot. userdel's usage split
	in smaller messages.
2011-11-06 18:37:39 +00:00
nekral-guest 50eafd769b * NEWS, src/userdel.c, man/userdel.8.xml: Add --root option. Open
audit and syslog after the potential chroot. userdel's usage split
	in smaller messages.
2011-11-06 18:37:32 +00:00
nekral-guest cecae46ccf * NEWS, src/useradd.c, man/useradd.8.xml: Add --root option. Open
audit after the potential chroot.
2011-11-06 18:37:25 +00:00
nekral-guest 0b5574c28a * lib/prototypes.h, libmisc/Makefile.am, libmisc/root_flag.c,
po/POTFILES.in: Add process_root_flag() to process the --root
	option and chroot so that the chroot config is used and changes
	are applied to the chroot.
2011-11-06 18:37:19 +00:00
nekral-guest c237be820b * man/ja/Makefile.am, man/fr/Makefile.am, man/ru/Makefile.am,
man/sv/Makefile.am, man/pl/Makefile.am, man/zh_CN/Makefile.am,
	man/it/Makefile.am, man/Makefile.am: Include man_nopam in
	EXTRA_DIST only when USE_PAM (they are already in man_MANS
	otherwise).
2011-10-22 08:59:08 +00:00
nekral-guest eee4152981 * man/su.1.xml: Document that su -c does not providea controlling
terminal.
2011-10-22 08:56:51 +00:00
nekral-guest 2afa955401 * src/sulogin.c (main): env is only used when USE_PAM is not set. 2011-10-18 20:28:01 +00:00
nekral-guest 704f28df98 * lib/prototypes.h, libmisc/cleanup.c, lib/spawn.c, src/chage.c:
Add splint annotations.
2011-10-18 20:23:33 +00:00
nekral-guest edbdb4bf03 * lib/nscd.c: Remove unused variable. 2011-10-18 20:16:00 +00:00
nekral-guest d3195c6b5f * src/newusers.c: Fix typo.
* src/useradd.c: Likewise.
2011-10-18 20:13:37 +00:00
nekral-guest 8fcb361fb8 * man/login.defs.d/LOGIN_STRING.xml: Fix typo. 2011-10-15 16:01:07 +00:00
nekral-guest f870cc7eab Miscellaneous:
* lib/prototypes, libmisc/basename.c (Basename): Input is a
	constant string.
	* lib/prototypes.h, lib/spawn.h, lib/spawn.c, src/userdel.c,
	lib/nscd.c, lib/Makefile.am: Delete spawn.h. Move from spawn.h to
	prototypes.h.
	* src/userdel.c: Remove unused variables.
	* lib/nscd.c: Remove unused header files.
	* lib/nscd.c: Add the program name to error messages.
	* lib/nscd.c: Indicate when nscd does not terminate normally (signal).
	* lib/spawn.c: Updated header.
	* lib/spawn.c: Flush stdout and stderr to avoid inheriting from
	ongoing buffers.
	* lib/spawn.c: Avoid implicit conversion of pointer to boolean.
	* lib/spawn.c: Replace perror by a complete message.
	* lib/spawn.c: Continue to wait for the child if another child
	terminates.
	* lib/prototypes.h: The name field from cleanup_info_mod is a
	constant string. (username).
2011-09-18 21:02:43 +00:00
nekral-guest 03e5751102 Re-indent. 2011-09-18 20:44:09 +00:00
nekral-guest 05b55446da * libmisc/cleanup.c: Spawn children should no trigger cleanup
actions. Make sure only the parent (initial caller) perform the
	cleanup actions.
2011-09-18 20:43:28 +00:00
nekral-guest f1db2383fc * libmisc/salt.c (SHA_salt_rounds): It is statically ensured that
the format fits in rounds_prefix.
	* libmisc/loginprompt.c: Likewise.
2011-09-18 20:41:38 +00:00
nekral-guest cd10be6c91 * libmisc/salt.c (SHA_salt_rounds): It is statically ensured that
the format fits in rounds_prefix.
2011-09-18 20:40:50 +00:00
nekral-guest 2b5ba27ff8 * src/grpconv.c: Fail if not called correctly.
* src/grpconv.c: At the end of main, the passwd and shadow files
	are locked. No need to check before unlocking. No need to set the
	lock as false neither since there cannot be anymore failures.
2011-09-18 20:26:27 +00:00
nekral-guest fa96d1bb78 * src/chage.c: EPOCH is not needed, it's converted to -1 by
strtoday(). But we need to support "-1" specifically.
	* src/chage.c: Fix usage: LOGIN is mandatory.
	* src/chage.c: Display disabled expiry or last change as "-1"
	instead of 1969-12-31. 1969-12-31 is still supported as input from
	the user.
	* src/chage.c: Exit cleanly with fail_exit() (lock files were not
	removed).
2011-09-18 20:24:36 +00:00
nekral-guest 23afb3fd07 * src/useradd.c: Remove def_file. It was always set to
USER_DEFAULTS_FILE.
	* src/useradd.c: Fix cut&paste issue causing bad warning when
	the useradd.default file contains an invalid INACTIVE= value.
	* src/useradd.c: Added missing end of line for rename errors.
	* src/useradd.c: Added -D synopsis to the usage message.
	* src/useradd.c: Do not scale_age(-1), just use -1.
	* src/useradd.c: Added FIXME to be fixed later.
	* src/useradd.c: Allow -e -1 when there is no shadow file.
	* src/useradd.c: Fail, but do not print the usage message when the
	-e argument is not valid.
	* src/useradd.c: No need to check for oflg since uflg is
	already checked.
2011-09-18 18:00:06 +00:00
nekral-guest 6f05b866bc * src/su.c: Too much const were added on 2011-08-15. pw in
save_caller_context() is allocated and freed.
	* src/su.c: Added missing #endif indication
	* src/su.c save_caller_context(): password only needed if
	SU_ACCESS and !USE_PAM.
2011-09-18 17:47:03 +00:00
nekral-guest 603d949ed5 * src/usermod.c: date_to_str() is always called with negativ set
to "never", remove this argument.
	* src/usermod.c: Added missing cast for gr_free argument.
2011-09-18 17:34:21 +00:00
nekral-guest 4ce849a5ed * src/pwconv.c: Fail if not called correctly.
* src/pwconv.c: At the end of main, the passwd and shadow files
	are locked. No need to check before unlocking.
2011-09-18 17:32:04 +00:00
nekral-guest 7b0116c5b4 * src/newusers.c: Initially set the passwd's password to '*'
instead of 'x'. Only when it is confirmed that a shadow entry is
	(will be) added, set the passwd's password to 'x'.
	* src/newusers.c: An invalid line is an error. A failure needs to
	be reported.
2011-09-18 17:29:52 +00:00
nekral-guest a52a8d8a5d * src/gpasswd.c: Remove log_gpasswd_success_gshadow(). Writing in
gshadowis the last sub-task.
2011-09-18 17:27:18 +00:00
nekral-guest 75936bf9f7 * src/chsh.c: No needto remove lines tarting with '#' from
/etc/shells. This is already done by getusershell() and these
	shell would fail the access(X_OK) test.
2011-09-18 17:24:15 +00:00
nekral-guest 0d00d3eecf * man/generate_mans.mak: Fix the generation of translated man
pages. xml2po removed the comment from empty headers and the
	config was no more inserted.
2011-09-18 17:02:10 +00:00
nekral-guest 93ee4927bc * man/login.defs.d/QUOTAS_ENAB.xml: Document the dependency
between /etc/limits and QUOTAS_ENAB.
2011-09-18 17:00:28 +00:00
nekral-guest 5570ec21b4 * man/chage.1.xml: The LOGIN argument is not optional. 2011-09-18 16:59:16 +00:00
nekral-guest 5530a47d76 * po/POTFILES.in: Added lib/spawn.c. 2011-09-18 16:58:12 +00:00
nekral-guest fc0057ff35 2011-08-20 Jonathan Nieder <jrnieder@gmail.com>
* lib/Makefile.am: Added lib/spawn.c and lib/spawn.h.
	* lib/nscd.c, lib/spawn.c, lib/spawn.h: It is not possible to
	differentiate between an nscd failure, and a failure to execute
	due to no nscd with posix_spawn. Use our own run_command routine.
	* src/userdel.c: Use run_command()
2011-08-20 13:33:38 +00:00
nekral-guest ec309dcac8 re-indent. 2011-08-15 14:40:42 +00:00
nekral-guest ee0e0f9943 * src/groupmod.c: Check atexit failures. 2011-08-15 14:38:49 +00:00
nekral-guest 7f842bdf4f * src/groupmod.c: Ignore return value from snprintf.
* src/groupmod.c: Add static qualifier to the cleanup structures.
2011-08-15 14:22:33 +00:00
nekral-guest 7c96d6cbcc * src/usermod.c: Do not assign static to NULL.
* src/usermod.c (date_to_str): buf needs to be unique (e.g.
	independent from negativ), and is an out buffer.
	* src/usermod.c: Ignore return value from snprintf, and force
	nul-termination of buffer.
	* src/usermod.c: Improve memory management.
	* src/usermod.c: An audit bloc was not reachable, moved above on
	success to move the home directory.
	* src/usermod.c: Ignore close() return value for the mailbox
	(opened read only).
2011-08-15 09:56:43 +00:00
nekral-guest 5eb9ed0aaf * src/su.c: Added const modifiers.
* lib/prototypes: Synchronize splint annotations.
2011-08-15 09:25:58 +00:00
nekral-guest 94c1763f71 * src/su.c: Add splint annotations.
* src/su.c: Set caller_on_console as boolean.
	* src/su.c: Ignore retunr value from fputs (usage) / puts (prompt).
	* src/su.c: Improved memory management.
2011-08-14 21:44:46 +00:00
nekral-guest 1304a3106b * src/chgpasswd.c, src/chpasswd.c, src/newusers.c: Replace cflg by
a test on crypt_method.
2011-08-14 14:44:35 +00:00
nekral-guest a9c38f4902 * src/chgpasswd.c: Add splint annotations.
* src/chpasswd.c: Likewise.
	* src/newusers.c: Likewise.
	* libmisc/salt.c, lib/prototypes.h (crypt_make_salt): Likewise.
2011-08-14 14:37:17 +00:00
nekral-guest e2bdb4ff83 * libmisc/chowndir.c: Add splint annotations. 2011-08-14 14:00:14 +00:00
nekral-guest 41accaf963 * lib/gshadow_.h: Fix typo in comment. 2011-08-14 13:16:54 +00:00
nekral-guest 5f37d13405 * lib/prototypes.h, libmisc/getgr_nam_gid.c: getgr_nam_gid()
returns an allocated structure.
2011-08-14 13:16:26 +00:00
nekral-guest 745bcb5406 * src/su.c: Add annotations to indicate that su_failure() does
not return.
2011-08-14 13:15:20 +00:00
nekral-guest 1f4f00acad * lib/commonio.c: Display PID as unsigned long. 2011-07-30 01:48:42 +00:00
nekral-guest 905e14ee83 * src/useradd.c: Remove unused Zflg. 2011-07-30 01:47:52 +00:00
nekral-guest f8d47df43b * src/chgpasswd.c: Fix typo sp -> sg. sg_namp -> sg_name
* src/chgpasswd.c: Always update the group file when SHADOWGRP is
	not enabled.
2011-07-30 01:46:23 +00:00
nekral-guest 934bfa5969 * src/newgrp.c: Fix typo in notreached annotation. 2011-07-30 01:41:56 +00:00
nekral-guest 00d1ab6454 * src/usermod.c: Add annotations to indicate that fail_exit() does
not return.
	* src/usermod.c: Fix typo in notreached annotation.
2011-07-30 01:41:03 +00:00
nekral-guest 019048c555 * libmisc/find_new_uid.c: free (used_uids) on return.
* libmisc/find_new_gid.c: free (used_gids) on return.
2011-07-30 01:38:07 +00:00
nekral-guest 6223c40c2d * lib/commonio.c: Fix NIS commit from 2011-07-14. 2011-07-28 15:19:40 +00:00
nekral-guest e7c09ab3df * NEWS, src/chpasswd.c: Create a shadow entry if the password is
set to 'x' in passwd and there are no entry in shadow for the
	user.
	* NEWS, src/chgpasswd.c: Create a gshadow entry if the password is 
	set to 'x' in group and there are no entry in gshadow for the 
	group.
2011-07-28 15:18:39 +00:00
nekral-guest 75fa697526 * NEWS, src/chpasswd.c: Create a shadow entry if the password is
set to 'x' in passwd and there are no entry in shadow for the
	user.
	* NEWS, src/chgpasswd.c: Create a gshadow entry if the password is 
	set to 'x' in group and there are no entry in gshadow for the 
	group.
2011-07-28 15:17:28 +00:00
nekral-guest 771a3624f5 * src/pwunconv.c: Exit after printing usage when arguments or
options are provided.
	* src/pwunconv.c: Re-indent.
	* src/pwunconv.c: Open the shadow file read only.
	* src/grpunconv.c: Exit after printing usage when arguments or
	options are provided.
	* src/grpunconv.c: Open the gshadow file read only.
2011-07-28 14:40:56 +00:00
nekral-guest 7fed07f1e9 * src/chgpasswd.c: Fix typo. 2011-07-28 14:36:24 +00:00
nekral-guest 7180f03376 Add more info on the change of behavior. 2011-07-23 11:05:59 +00:00
nekral-guest 2aefca0f2e * NEWS, src/login.c: Do not log in utmp / utmpx / wtmp when PAM is
enabled. This is already done by pam_lastlog.
2011-07-23 11:03:50 +00:00
nekral-guest 7e8aa5429a * src/chpasswd.c: Add annotations to indicate that usage() does
not return.
	* src/chpasswd.c: Reindent.
	* src/chpasswd.c: Remove dead code. No need to set crypt_method
	to NULL when it is already NULL. sflg is only set if crypt_method
	is not NULL.
2011-07-23 08:14:15 +00:00
nekral-guest 2be8650d2c * src/lastlog.c: Add annotations to indicate that usage() does not
return.
2011-07-23 08:10:27 +00:00
nekral-guest 495125415b * src/faillog.c: Add annotations to indicate that usage() does not
return.
	* src/faillog.c: Fix message: this is faillog, not lastlog.
	* src/faillog.c: Check that there are no extra arguments after
	parsing the options.
2011-07-22 23:59:57 +00:00
nekral-guest 1def4ef49d * src/chgpasswd.c: Add annotations to indicate that usage() does
not return.
	* src/chgpasswd.c: Split usage in smaller parts. Those parts are
	already translated for chpasswd. Usage is now closer to
	chpasswd's.
	* src/chgpasswd.c: Remove dead code. No need to set crypt_method
	to NULL when it is already NULL. sflg is only set if crypt_method
	is not NULL.
2011-07-22 23:52:08 +00:00
nekral-guest bb67476209 * src/expiry.c: Remove dead code.
* src/expiry.c: Improve comments.
2011-07-22 22:39:30 +00:00
nekral-guest e8373305b4 * src/grpck.c: Added comments.
* src/grpck.c: Avoid implicit conversion of pointer to boolean.
	* src/grpck.c: Remove dead code. argc cannot be lower than optind.
	Avoid checking twice in a row for NULL != list[i].
2011-07-22 22:07:23 +00:00
nekral-guest 275ffe2e01 * libmisc/find_new_gid.c, libmisc/find_new_uid.c: Fail in case of
invalid configuration. 
	* libmisc/find_new_gid.c, libmisc/find_new_uid.c: Updated
	comments.
	* libmisc/find_new_gid.c, libmisc/find_new_uid.c: Be more strict
	on the loop stop conditions. Stop if we passed the limit, even if
	the limit itself was never noticed.
2011-07-22 21:53:01 +00:00
nekral-guest a210d898b6 * man/po/fr.po: Fix some spacing issues due to configuration
variants.
2011-07-14 14:14:36 +00:00
nekral-guest 8bce7fc016 * src/passwd.c: Overflow when computing the number of days based
on the scaling. Use of long long needed.
2011-07-14 14:03:19 +00:00
nekral-guest 39cecdab06 * NEWS, lib/commonio.h, lib/commonio.c: Additional messages to
indicate why locking failed.
	* NEWS, lib/commonio.c: Fix the sort algorithm in case of NIS. NIS
	entries were dropped.
	* lib/commonio.c: NIS entries can start by '+' or '-'.
2011-07-14 13:58:17 +00:00
nekral-guest a7fee9db00 * NEWS, src/groupmod.c: When the gshadow file exists but there are
no gshadow entries, an entry is created if the password is changed
	and group requires a shadow entry.
2011-07-14 13:30:05 +00:00
nekral-guest d4e630b8cc * src/usermod.c (process_flags): Indicate that the user name is
invalid, instead of just a 'field'.
2011-07-14 13:29:59 +00:00
nekral-guest 82b92af086 * src/usermod.c (process_flags): Do not display the usage in case
of an invalid -f value (similar to -e).
2011-07-14 13:29:54 +00:00
nekral-guest c23e851074 * src/usermod.c (new_pwent): Document that pw_locate will not fail
because getpwnam returned successfully.
2011-07-14 13:29:48 +00:00
nekral-guest c2333946c0 * man/usermod.8.xml: Document behavior of an empty EXPIRE_DATE.
* man/usermod.8.xml: Document that the mail spool might have to be
	renamed (as for the homedir)
2011-07-14 13:29:43 +00:00
nekral-guest 2c6782b501 * NEWS, src/usermod.c; man/usermod.8.xml: When the shadow file
exists but there are no shadow entries, an entry has to be created
	if the password is changed and passwd requires a shadow entry, or
	if aging features are used (-e or -f). Document this and also that
	-e and -f require a shadow file.
2011-07-14 13:29:37 +00:00
nekral-guest c2f5088067 * src/usermod.c (update_group, update_gshadow): Reduce complexity
and document checks. Some checks were always true/false within
	their call context.
2011-07-14 13:29:32 +00:00
nekral-guest 8195a2b5d8 * src/usermod.c (update_gshadow): is_member was computed twice. 2011-07-14 13:29:27 +00:00
nekral-guest 2798e35d86 * src/usermod.c: usage() does not return. Add annotations. 2011-07-14 13:29:22 +00:00
nekral-guest d1753cc25d * src/usermod.c (process_flags): Check for oflg is not needed to
check if changes are needed.
2011-07-14 13:29:16 +00:00
nekral-guest a5ded26850 * src/usermod.c (process_flags): Report usage if no options are
provided. Update the error message.
	* src/usermod.c (process_flags): Check option compatibility and
	dependency before options are discarded when no changes are
	requested.
2011-07-14 13:29:10 +00:00
nekral-guest d51420bb01 * src/usermod.c (move_home): It is always an error to use -m if
the new home directory already exist (independently from the
	existence of the old home directory did not exist)
2011-07-14 13:29:05 +00:00
nekral-guest aec025dbf6 * src/usermod.c: Fix typo in comment. 2011-07-14 13:28:59 +00:00
nekral-guest 95257d63a1 * src/groupmod.c: Avoid implicit conversion of pointer to boolean.
* src/groupmod.c: osgrp can be set only if pflg || nflg. No need
	to check for pflg || nflg again
2011-07-08 19:58:40 +00:00
nekral-guest 9cfc91a935 * configure.in: Fix typo. libcrack default is 'no'. 2011-07-08 19:57:08 +00:00
nekral-guest 13873a8799 * lib/fields.c: Fixed typo from 2010-02-15. field insteadof cp
ought to be checked.
	* src/vipw.c: Use Prog instead of progname. This is needed since
	Prog is used in the library.
2011-07-08 19:56:18 +00:00
nekral-guest cc6eaf9584 Fix typo in comment. 2011-07-08 19:51:32 +00:00
nekral-guest 1a164919f1 Fixed typo. user_home -> mailfile. 2011-07-08 19:50:42 +00:00
nekral-guest 3bdad35e9f * man/*.xml, man/config.xml.in: Add source and version
information. This reduce the amount of warnings during the
	manpages generation.
2011-07-08 19:49:09 +00:00
nekral-guest 275ac4c5e0 * man/po/ru.po: Add space between option and argument. 2011-06-25 09:13:14 +00:00
nekral-guest 504a89d25b * man/passwd.1.xml: Added reference to chpasswd(8). 2011-06-25 09:03:05 +00:00
bubulle 42666a6b03 Spanish translation update 2011-06-18 05:33:27 +00:00
nekral-guest c786f4887f Ignore generated files. 2011-06-16 21:26:35 +00:00
nekral-guest 75f4b049a6 * libmisc/isexpired.c: Added parenthesis.
* libmisc/env.c: Added comments.
	* libmisc/env.c: Avoid implicit conversion of pointer to boolean.
2011-06-16 21:25:36 +00:00
nekral-guest 907025eb40 * src/su.c: environ is provided by <unistd.h>.
* src/su.c: Added function prototypes.
	* src/su.c: Rename shellstr parameter to shellname to avoid
	collision with static variable.
	* NEWS, src/su.c: Added support for PAM modules which change
	PAM_USER.
2011-06-16 21:21:29 +00:00
nekral-guest 66d71aafb7 Cleanup. 2011-06-13 18:27:51 +00:00
nekral-guest 317939e821 * src/su.c: After prepare_pam_close_session() there is no need to
close the session in the child. Added pam_setcred to
	prepare_pam_close_session().
2011-06-13 18:27:46 +00:00
nekral-guest 1340beed16 * src/su.c: Also drop the controlling terminal when PAM is not
used.
	* src/su.c: Remove run_shell().
2011-06-13 18:27:40 +00:00
nekral-guest e9045e9f55 * src/su.c (prepare_pam_close_session): Extract the creation of a
child and listening for signal in the parent from run_shell().
	prepare_pam_close_session() is now executed before the creation of
	the pam session and before the UID is changed. This allows to
	close the session as root.
2011-06-13 18:27:34 +00:00
nekral-guest 69371ba2c2 * src/su.c: Extract export of environment from main(). 2011-06-13 18:27:28 +00:00
nekral-guest dbe0b96404 * src/su.c: Extract command line processing from main(). 2011-06-13 18:27:23 +00:00
nekral-guest 43e65fdd46 * src/su.c: Close the password databases together with syslog. 2011-06-13 18:27:17 +00:00
nekral-guest 5d6f4f8ea4 * src/su.c: Merge environment setting blocks after the creation of
the session.
2011-06-13 18:27:12 +00:00
nekral-guest b63c830547 * src/su.c: Cleanup check_perms_nopam(). 2011-06-13 18:27:06 +00:00
nekral-guest 927c2f06a3 * src/su.c: Split check_perms() in to a PAM (check_perms_pam) and
a non-PAM (check_perms_nopam) version.
2011-06-13 18:26:58 +00:00
nekral-guest 40a16a1b04 Compile fixes & cleanups. 2011-06-13 18:26:52 +00:00
nekral-guest 6be3ac560b * src/su.c (save_caller_context): Extract from main() the code
used to save the caller's context.
2011-06-13 18:26:47 +00:00
nekral-guest b661b913b5 * src/su.c: Cleanup local variables. 2011-06-13 18:26:36 +00:00
nekral-guest b273c4d19f Cleanup comments. 2011-06-13 18:26:31 +00:00
nekral-guest 7ebfb5c90f * lib/prototypes.h, src/suauth.c, src/su.c (check_su_auth): Do not
use the pwent global variable to communicate between APIs of
	different files. Added boolean parameter su_to_root to
	check_su_auth().
	* src/su.c (check_perms): Return the passwd entry of the finally
	authenticated user. Remove usage of the pwent variable.
	* src/su.c: The password of the caller is the one from the
	spwd structure only if the passwd's password is 'x'.
2011-06-13 18:26:26 +00:00
nekral-guest 3abd71c526 * src/su.c: Extract the authentication from the main function. 2011-06-13 18:26:16 +00:00
nekral-guest dc90c77285 * src/su.c: Define shellstr before the environment so that
restricted_shell is called only once. This will allow moving the
	environment definition after the switch to the new user.
2011-06-13 18:26:10 +00:00
nekral-guest 2f71935616 * src/su.c: Move definition of change_environment and shellstr
after the switch to the final subsystem. The previous architecture
	forced to always change the environment (the shell starts with a
	'*' and was thus restricted, and change_environment could not be
	reset to false).
2011-06-13 18:25:57 +00:00
nekral-guest 941e94f1d2 * src/su.c: No need to change the user's shell in case of
subsystem root. Update the comments.
2011-06-13 18:25:51 +00:00
nekral-guest 4be8077a56 * src/su.c: Group some of the environment processing blocks. The
definition of shellstr, PATH and IFS is not influenced (getenv,
	getdef, restricted_shell) by and does not influence (addenv does
	not change environ) the authentication. And the authentication
	does not overwrite those definitions. This will ease an extraction
	from the big main() function.
2011-06-13 18:25:45 +00:00
nekral-guest aef33a89c2 * src/su.c: No need to call expire() if there are no shadow entry.
No need to convert a passwd entry into an spwd entry in that case.
2011-06-13 18:25:40 +00:00
nekral-guest 1ddde00b1d * src/su.c: Updating pwent after expire() is not useful. Only the
password information may have changed and they are not used
	anymore afterwards.
2011-06-13 18:25:34 +00:00
bubulle f66bd259cf French manpages translation 2011-06-12 19:55:58 +00:00
nekral-guest ea34d36d62 Document the updated translations. 2011-06-05 14:56:11 +00:00
nekral-guest b5403415f7 * NEWS, src/su.c: Do not forward the controlling terminal to
commands executed with -c. This prevents tty hijacking which could
	lead to execution with the caller's privileges. This required to
	forward signals from the terminal (SIGINT, SIGQUIT, SIGTSTP) to
	the executed command.
2011-06-05 14:41:15 +00:00
nekral-guest a8ca723277 * NEWS, src/userdel.c: Do not remove a group with the same name as
the user (usergroup) if this group isn't the user's primary group.
2011-06-05 12:23:59 +00:00
nekral-guest 14f44bd9c9 * NEWS, src/userdel.c: Check the existence of the user's mail
spool before trying to remove it. If it does not exist, a warning
	is issued, but no failure.
2011-06-04 22:38:57 +00:00
nekral-guest c9281b5bb9 Harmonize message. 2011-06-03 21:09:27 +00:00
nekral-guest ce737cf543 * src/sulogin.c: Added Prog, needed because of the last xmalloc()
change.
2011-06-03 21:08:56 +00:00
nekral-guest e8723c375f * man/zh_CN/, man/zh_CN/Makefile.am: Added directory, and zh_CN
Makefile.
	* man/Makefile.am: Build zh_CN pages.
	* man/generate_translations.mak: Add config.xml to CLEANFILES.
	* man/po/zh_CN.po: limits, groups, faillog, expiry should not be
	translated (command name, file name), also this broke the build
	system as they are used to derive manpage names.
2011-06-03 21:07:58 +00:00
nekral-guest 6b14946d81 * man/zh_CN/, man/zh_CN/Makefile.am: Added directory, and zh_CN
Makefile.
	* man/Makefile.am: Build zh_CN pages.
	* man/generate_translations.mak: Add config.xml to CLEANFILES.
	* man/po/zh_CN.po: limits, groups, faillog, expiry should not be
	translated (command name, file name), also this broke the build
	system as they are used to derive manpage names.
2011-06-03 21:06:23 +00:00
nekral-guest 597bb764f1 * src/lastlog.c, src/faillog.c: Fix underflows causing wrong entry
to be displayed.
2011-06-02 20:26:30 +00:00
nekral-guest f406d16b7b * libmisc/xmalloc.c: Harmonize message. 2011-06-02 18:41:05 +00:00
nekral-guest 58baa7aa61 * libmisc/find_new_uid.c, libmisc/find_new_gid.c: Add missing
memory allocation check.
2011-06-02 18:40:06 +00:00
nekral-guest f140c3a0e5 * NEWS, libmisc/addgrps.c: Fix allocator loop. Continue to
getgroups() when getgroups fails (-1) with errno==EINVAL.
2011-06-02 15:36:29 +00:00
bubulle 99d0164837 German translation of manpages completed 2011-06-01 12:19:25 +00:00
bubulle 143f479869 Fix typos in manpages
Catalan translation updated
2011-06-01 11:58:04 +00:00
bubulle 7864e1edf5 French and Portuguese translation updates 2011-04-25 10:06:23 +00:00
bubulle ed6107c8c5 German translation completed 2011-04-16 07:31:49 +00:00
bubulle d4d8ab87ac Brazilian Portuguese translation completed 2011-04-15 06:21:10 +00:00
bubulle af89454645 Russian translation completed 2011-04-10 15:50:13 +00:00
bubulle e10346124f Updated Swedish and Danish translations 2011-04-07 17:45:33 +00:00
bubulle 0d3d7722c1 Fixed file 2011-04-06 04:14:12 +00:00
bubulle 72ba55b056 Kazakh and Japanese translation updates 2011-04-05 18:06:32 +00:00
bubulle 82cfc819a8 Simplified Chinese translation completed 2011-03-30 17:51:50 +00:00
bubulle 699edaab3b Convert zh_CN translation of manpages to gettext 2011-03-30 17:50:19 +00:00
nekral-guest a342b207b2 * man/ru/Makefile.am: Remove double inclusion of $(man_nopam) 2011-02-19 16:17:26 +00:00
nekral-guest ee163bed33 * libmisc/user_busy.c, src/userdel.c, src/usermod.c: Warn in
user_busy() rather than in src/userdel.c or src/usermod.c to
	provide more accurate failure cause (user is logged in or user
	still executes processes).
2011-02-16 20:46:27 +00:00
nekral-guest f4b544786c Added missing Changelog entry for lib/fields.c:
* lib/fields.c: Fail if input pointer is NULL.
2011-02-16 20:33:16 +00:00
nekral-guest d7fa77f03b * lib/groupio.c, lib/sgroupio.c, lib/shadowio.c, lib/pwio.c: Check
entry validity before commits to databases.
	* libmisc/fields.c, libmisc/Makefile.am, lib/fields.c,
	lib/Makefile.am, po/POTFILES.in: fields.c moved from libmisc to
	lib.
2011-02-16 20:32:16 +00:00
nekral-guest a9b8e7aaa3 Adapt ignore list to previous commits. 2011-02-16 20:27:25 +00:00
nekral-guest 0419fc4f5f * NEWS, src/chfn.c, src/chsh.c: Fix CVE-2011-0721: forbid \n in
gecos or shell.
2011-02-16 00:18:45 +00:00
nekral-guest 7de49dec7b Cleanup previous commit. 2011-02-13 11:51:39 +00:00
nekral-guest 0398323a60 * autogen.sh: Restore original autoreconf (see 2010-08-29's change
for autogen.sh)
	* configure.in, man/po/Makefile.in.in, man/po/Makefile.in:
	Makefile.in.in replaced by Makefile.in to avoid config.status
	issues when there are multiple po directories.
	* man/po/LINGUAS: Adapted to above change.
	* man/po/POTFILES.in, man/po/XMLFILES: POTFILES.in replaced by
	XMLFILES.
	* man/Makefile.am: generate_mans.deps shall be included by make,
	not automake.
2011-02-12 14:57:37 +00:00
nekral-guest 8b4f07692e * NEWS, libmisc/console.c: Fix CONSOLE parser. This caused login
to hang when CONSOLE was configured with a colon separated list of
	TTYs.  See http://bugs.gentoo.org/show_bug.cgi?id=324419
2010-11-19 21:54:41 +00:00
nekral-guest dffc624b37 Integrate review comments from Julien Cristau
* libmisc/copydir.c: Missing parenthesis in comment.
	* libmisc/chowndir.c: Fixed memory leak on failed realloc().
	* libmisc/chowndir.c: Make sure the buffer for the path is large
	enough.
	* libmisc/remove_tree.c: Remove check for NULL before free().
2010-09-05 15:34:42 +00:00
nekral-guest d1bad25f40 * man/po/fr.po: Fix 2 fuzzy strings. 2010-08-29 19:11:40 +00:00
nekral-guest 229f243ca0 * NEWS, src/usermod.c: Accept options in any order (username not
necessarily at the end)
2010-08-29 19:02:41 +00:00
nekral-guest 91f972bb59 * autogen.sh: Expand autoreconf to avoid running autopoint. 2010-08-29 16:42:25 +00:00
nekral-guest 493009ac91 * po/shadow.pot, man/po/shadow-man-pages.pot: Regenerated.
* po/*.po, man/po/*.po: Updated PO files.
2010-08-29 16:13:47 +00:00
nekral-guest 0355e4e930 * man/chsh.1.xml: Fix comma splice. 2010-08-28 20:16:18 +00:00
nekral-guest 8184041c7e * NEWS, po/kk.po: Updated Kazakh translation. 2010-08-28 20:02:25 +00:00
nekral-guest 1d336d3a1e * lib/protoypes.h, libmisc/copydir.c, src/useradd.c:
selinux_file_context renamed set_selinux_file_context.
	* lib/protoypes.h, libmisc/copydir.c, src/useradd.c:
	Added reset_selinux_file_context.
	* src/useradd.c: Check the return value of
	set_selinux_file_context and reset_selinux_file_context.
	* libmisc/copydir.c: Check the return value of
	reset_selinux_file_context.
2010-08-28 19:58:00 +00:00
nekral-guest 991ce97170 * src/su.c: Fix handling of environment variables when
the environment is not changed. In particular, this makes su
	behave as documented regarding PATH and IFS (i.e. they are reset)
	when -p is provided.
2010-08-28 19:55:31 +00:00
nekral-guest bf480028f5 * man/su.1.xml: Fix typo. 2010-08-28 19:48:17 +00:00
nekral-guest ab9427420e * src/newgrp.c, src/userdel.c, src/grpck.c, src/gpasswd.c,
src/newusers.c, src/pwconv.c, src/chpasswd.c, src/logoutd.c,
	src/chfn.c, src/groupmems.c, src/usermod.c, src/pwunconv.c,
	src/expiry.c, src/groupdel.c, src/chgpasswd.c, src/useradd.c,
	src/su.c, src/groupmod.c, src/passwd.c, src/pwck.c, src/chage.c,
	src/groupadd.c, src/login.c, src/grpconv.c, src/groups.c,
	src/grpunconv.c, src/chsh.c: Prog changed to a constant string.
2010-08-22 19:36:09 +00:00
nekral-guest 07e462f01f * libmisc/limits.c: Avoid implicit conversion of integer to
boolean.
	* libmisc/basename.c: Avoid implicit conversion of pointer to
	boolean.
	* libmisc/basename.c, lib/prototypes.h (Basename): Return a
	constant string.
	* libmisc/basename.c, libmisc/obscure.c, lib/prototypes.h,
	libmisc/xmalloc.c, libmisc/getdate.h, libmisc/system.c,
	libmisc/getgr_nam_gid.c, libmisc/failure.c, libmisc/valid.c: Add
	splint annotations.
	* libmisc/chowndir.c: Avoid memory leak.
	* libmisc/chowndir.c: Do not check *printf/*puts return value.
	* libmisc/chowntty.c: Avoid implicit conversion between integer
	types.
	* libmisc/obscure.c: Return a bool when possible instead of int.
	* libmisc/shell.c: Do not check *printf/*puts return value.
	* libmisc/shell.c: Do not check execle return value.
	* libmisc/setupenv.c: Avoid implicit conversion between integer
	types.
	* libmisc/xmalloc.c: size should not be zero to avoid returning
	NULL pointers.
	* libmisc/hushed.c: Do not check *printf/*puts return value.
	* libmisc/system.c: Avoid implicit conversion of integer to
	boolean. safe_system last argument is a boolean.
	* libmisc/system.c: Check return value of dup2.
	* libmisc/system.c: Do not check *printf/*puts return value.
	* libmisc/system.c: Do not check execve return value. 
	* libmisc/salt.c: Do not check *printf/*puts return value.
	* libmisc/loginprompt.c: Do not check gethostname return value.
	* libmisc/find_new_gid.c, libmisc/find_new_uid.c: Do not check
	gr_rewind/pw_rewind return value.
	* libmisc/ttytype.c: Limit the number of parsed characters in the
	sscanf format.
	* libmisc/ttytype.c: Test if a type was really read.
	* libmisc/sub.c: Do not check *printf/*puts return value.
	* libmisc/sub.c: Avoid implicit conversion of integer to boolean.
	* src/userdel.c: Fix typo in comment.
	* src/userdel.c: Avoid implicit conversion of boolean to integer.
	* src/userdel.c: safe_system last argument is a boolean.
	* src/newusers.c: Avoid implicit conversion of boolean to integer.
	* src/newusers.c: Avoid implicit conversion of integer to boolean.
	* src/usermod.c: Add brackets.
	* src/usermod.c: Avoid implicit conversion of characters or
	integers to booleans.
	* src/vipw.c: Avoid implicit conversion of integer to boolean.
	* src/su.c: Avoid implicit conversion of integer to boolean.
	* src/su.c: Add brackets.
	* src/useradd.c: Avoid implicit conversion of characters or
	integers to booleans.
2010-08-22 19:13:53 +00:00
nekral-guest 7eb6a4b3a4 Updated copyrights. 2010-08-22 13:04:54 +00:00
nekral-guest 471a2df3a6 * libmisc/obscure.c, lib/prototypes.h (obscure): Return a bool
instead of an int.
	* libmisc/obscure.c, libmisc/tz.c, src/passwd.c, lib/encrypt.c,
	libmisc/copydir.c, lib/prototypes.h: Add splint annotations.
	* libmisc/tz.c: Fix some const issues.
	* libmisc/tz.c: Avoid multi-statements lines.
	* libmisc/tz.c: Add brackets.
	* libmisc/copydir.c: Do not check *printf/*puts return value.
	* libmisc/copydir.c: Fail if we cannot set or reset the SELinux
	fscreate context.
	* libmisc/copydir.c: Use xmalloc instead of malloc.
	* libmisc/copydir.c: Do not check lutimes return value
	* src/vipw.c: Avoid implicit conversion of integer to boolean.
	* src/su.c (iswheel): Return a bool instead of an int.
	* src/passwd.c: Remove insert_crypt_passwd(). Use xstrdup instead.
	* src/passwd.c: Return constant strings when sufficient.
	* src/passwd.c: Do not check *printf/*puts return value.
	* src/passwd.c: Avoid implicit conversion of character to boolean.
	* src/passwd.c: Do not check sleep return value.
	* src/sulogin.c: Do not check *printf/*puts return value.
	* lib/encrypt.c: Do not check fprintf return value.
2010-08-22 12:49:07 +00:00
nekral-guest 7e398a169b * src/sulogin.c: Fix a const issue. 2010-08-21 20:37:23 +00:00
nekral-guest 7bb81f6c3e * src/passwd.c: Fix a const issue.
* src/passwd.c: Avoid multi-statements lines.
2010-08-21 19:55:46 +00:00
nekral-guest c56d59c90b Fix additional const issues. 2010-08-21 19:22:32 +00:00
nekral-guest 791ebc58dd * libmisc/copydir.c, lib/prototypes.h: Caller can choose not to
copy the extended attributes (the SELinux context is hence reset)
	* src/usermod.c: Copy the extended attributes.
	* src/useradd.c: Only reset the SELinux context.
2010-08-21 17:31:45 +00:00
nekral-guest 3f63005e91 * configure.in: Fixed typo.
Thanks to Peter Vrabec.
2010-08-21 16:51:53 +00:00
nekral-guest f7a00a2334 * libmisc/console.c, libmisc/motd.c, libmisc/setupenv.c,
libmisc/sulog.c, libmisc/hushed.c, libmisc/failure.c,
	libmisc/loginprompt.c, libmisc/ttytype.c,
	libmisc/pam_pass_non_interractive.c, src/userdel.c, src/login.c,
	lib/commonio.c, lib/commonio.h: Fix some const issues.
	* libmisc/motd.c: Avoid multi-statements lines.
	* libmisc/motd.c: Support long MOTD_FILE.
	* libmisc/list.c, lib/prototypes.h: Revert previous change.
	dup_list and is_on_list are used with members as defined for the
	group structure, and thus even if the list is not modified, the
	list elements cannot be constant strings.
	* libmisc/system.c: Avoid C++ comments.
	* src/vipw.c: WITH_TCB cannot be tested inside a gettextized
	string. Split the Usage string.
	* lib/commonio.h: Re-indent.
2010-08-21 15:32:53 +00:00
nekral-guest 6a2f349ec5 * libmisc/audit_help.c (audit_logger):pgname is not used. We let
audit find out the name of the program.
	* libmisc/audit_help.c: Re-indent.
2010-08-21 15:22:39 +00:00
nekral-guest 4f667bb442 * lib/groupio.c: Avoid implicit conversion from signed to unsigned. 2010-08-20 20:35:52 +00:00
nekral-guest 22294bfac8 * lib/commonio.c: Make sure there are no NULL pointer dereference. 2010-08-20 20:34:44 +00:00
nekral-guest 07e67e1350 * libmisc/remove_tree.c: Ignore snprintf return value. 2010-08-20 20:27:34 +00:00
nekral-guest 660ed49daf * lib/prototypes.h, libmisc/list.c: dup_list() and is_on_list() do
not change the members of the list they receive. Added const
	qualifiers.
2010-08-20 20:26:32 +00:00
nekral-guest fad23b25a1 * src/usermod.c: Re-indent. 2010-08-20 18:24:33 +00:00
nekral-guest 6b74294844 * lib/commonio.c: Avoid multi-statements lines. 2010-08-20 18:09:14 +00:00
nekral-guest 11a564b6bd * man/po/fr.po: Fix a typo. 2010-08-20 17:57:33 +00:00
bubulle 939386aabb Kazakh translation update 2010-06-24 18:43:04 +00:00
nekral-guest 01ed010aed * man/po/fr.po: Fix some typos. Minor updates. 2010-04-12 21:49:09 +00:00
nekral-guest 52ec0ba938 * po/shadow.pot, man/po/shadow-man-pages.pot: Regenerated.
* po/*.po, man/po/*.po: Updated PO files.
2010-04-12 21:05:33 +00:00
nekral-guest 4f8310dfde * man/newusers.8.xml, man/useradd.8.xml, man/groupadd.8.xml,
man/login.defs.d/UMASK.xml, man/login.defs.d/CREATE_HOME.xml,
	man/login.defs.d/LOGIN_RETRIES.xml: Fix typos: choosen, overriden,
	bahavior.
2010-04-04 23:17:11 +00:00
nekral-guest 263f37a69b * man/usermod.8.xml: Document changes of ownerships. 2010-04-04 21:23:02 +00:00
nekral-guest 56483122b6 * man/vipw.8.xml: Fix formatting typo.
* man/vipw.8.xml: Document the login.defs parameters only when tcb
	is enabled.
2010-04-04 20:57:54 +00:00
nekral-guest 16362e289b 2010-04-04 Nicolas François <nicolas.francois@centraliens.net>
* src/useradd.c: spool is a constant string.
	* src/useradd.c: Set the new copy_tree's paramater 'copy_root' to false 

2010-04-04  Nicolas François  <nicolas.francois@centraliens.net>

	* src/usermod.c: move_home() is only called if mflg is set.
	* src/usermod.c: Fail is -m is provided but the old home directory
	is not a directory.
	* src/usermod.c: Use the previous improvement of copy_tree to
	provide better error diagnosis.
	* src/usermod.c: When rename() is used, also change the ownership.
	* src/usermod.c: Do not change the ownership of the root directory
	twice.
	* src/usermod.c: When -u is provided, only change the ownership of
	the home directory if it is a directory.
	* src/usermod.c: Also change ownerships when -g is used.

2010-04-04  Nicolas François  <nicolas.francois@centraliens.net>

	* lib/prototypes.h, libmisc/copydir.c: Add the old UID and GID to
	copy_tree to detect when ownership shall be changed.
	* libmisc/copydir.c: Document the behavior when the IDs are set to
	-1.
	* lib/prototypes.h, libmisc/copydir.c (copy_tree): Add parameter
	copy_root.
	* libmisc/copydir.c: error() and ctx can be static.
	* libmisc/copydir.c (copy_hardlink): Remove parameter src.

2010-04-04  Nicolas François  <nicolas.francois@centraliens.net>

	* libmisc/chowndir.c: Dynamically allocate memory to support
	path longer than 1024 characters.
	* libmisc/chowndir.c: Fix typos in documentation.
	* libmisc/chowndir.c: Support and document the behavior when a old
	or new ID is set to -1.
	* libmisc/chowndir.c: Improved error detection when chown fails.
	* libmisc/chowndir.c: Harmonize error handling strategy when an
	error occurs: stop changing ownership as soon as an error was
	detected.
2010-04-04 20:55:46 +00:00
nekral-guest 586a8f9e9e * man/hu/passwd.5: Fix formatting typo.
* man/id/login.1: Likewise.
2010-04-04 20:48:29 +00:00
nekral-guest a9249dbb0a * man/vipw.8.xml: When TCB is enabled, vipw uses login.defs. 2010-03-31 19:52:30 +00:00
nekral-guest 47733f1a0f Fix typos. 2010-03-31 12:24:03 +00:00
nekral-guest bb02ec3261 Fix typo. 2010-03-31 09:27:11 +00:00
nekral-guest c3689fa60b * NEWS, libmisc/copydir.c: When a hardlink is detected, the
original hardlink should not be removed.
2010-03-30 23:14:04 +00:00
nekral-guest dc0947da78 * po/POTFILES.in, libmisc/Makefile.am, lib/prototypes.h,
libmisc/remove_tree.c, libmisc/copydir.c: Split remove_tree()
	outside of copydir.c to avoid linking against libacl or libattr.
2010-03-30 21:54:29 +00:00
nekral-guest 427b60f288 * src/su.c: shell's name must be -su when a su fakes a login. 2010-03-30 21:32:36 +00:00
nekral-guest 902aad57af * NEWS, configure.in, libmisc/copydir.c, man/useradd.8.xml,
man/usermod.8.xml, src/Makefile.am: Added support for ACLs and
	Extended Attributes.
2010-03-30 21:01:27 +00:00
nekral-guest 6afd7859f8 * libmisc/copydir.c: Document the sections closed by #endif 2010-03-30 21:00:43 +00:00
nekral-guest cfce9890fb * etc/login.defs: Updated description of UMASK to indicate its
usage by pam_umask.
	* man/login.defs.d/UMASK.xml: Likewise.
2010-03-27 20:11:21 +00:00
nekral-guest 4b98379ce1 * man/vipw.8.xml: Add section ENVIRONMENT. 2010-03-27 20:09:49 +00:00
nekral-guest ee3d411024 * etc/login.defs: Updated description of UMASK to indicate its
usage by pam_umask.
2010-03-26 11:53:06 +00:00
nekral-guest 40d1598165 * man/login.1.xml: login does not check for new mails in PAM
enabled versions. This is done by pam_mail.
2010-03-25 20:38:31 +00:00
nekral-guest 97961b8bee * NEWS, src/chpasswd.c, man/chpasswd.8.xml, man/login.defs.5.xml:
PAM enabled versions: restore the -e option to allow restoring
	passwords without knowing those passwords. Restore together the -m
	and -c options.
2010-03-25 20:35:59 +00:00
nekral-guest fcd5b38caf * src/su.c, src/vipw.c, src/newgrp.c: When the child is
interrupted, stop ourself with a SIGSTOP signal.
2010-03-23 13:05:06 +00:00
nekral-guest 052e9105f7 * src/newgrp.c: Limit the scope of variable pid.
* src/login_nopam.c: Limit the scope of variables end, lineno, i,
	str_len.
	* src/logoutd.c: Limit the scope of variable c.
	* src/vipw.c: Re-indent.
	* src/vipw.c: Close the file after the creation of the backup.
	* src/useradd.c (set_default): Close input file on failure.
	* src/useradd.c: Limit the scope of variables spool, file, fd, gr,
	gid, mode.
	* src/passwd.c: Limit the scope of variables last and ok.
	* src/chage.c: Fix typo (non breaking space).
	* src/login.c: Limit the scope of variables erasechar killchar, c,
	failed.
	* src/groups.c: Limit the scope of variable ngroups, pri_grp, i.
	* src/id.c: Limit the scope of variable i.
2010-03-23 11:26:34 +00:00
nekral-guest 4375be4642 * lib/utent.c (getutline): Remove getutline(). This function is
no more used.
	* lib/groupmem.c: Limit the scope of variable i.
	* lib/shadow.c: Avoid implicit conversion of pointers and integers
	to booleans.
	* lib/shadow.c: Added brackets.
	* libmisc/limits.c: Limit the scope of variable tmpmask.
	* libmisc/copydir.c: Close opened file on failure.
	* libmisc/loginprompt.c: Limit the scope of variable envc.
	* libmisc/find_new_uid.c, libmisc/find_new_gid.c: Limit the scope
	of variable id.
2010-03-23 08:56:52 +00:00
nekral-guest 5ebb35654b * libmisc/find_new_gid.c, libmisc/find_new_uid.c: Detect some
misconfigurations of UID_MIN, UID_MAX, SYS_UID_MIN, SYS_UID_MAX (and
	the GID equivalents)
2010-03-21 01:20:50 +00:00
nekral-guest a83124dade * NEWS, configure.in: Next version will be 4.1.5. 2010-03-20 10:31:36 +00:00
nekral-guest f729486b33 * libmisc/limits.c: Re-indent to make pmccabe happy. 2010-03-20 10:29:27 +00:00
nekral-guest d1eae4c7e3 * man/generate_translations.mak, man/generate_mans.mak: Fix
distcheck. All manpages generation code shall be enclosed in
	ENABLE_REGENERATE_MAN conditions.
2010-03-20 10:25:34 +00:00
nekral-guest 9b6beb496a * man/useradd.8.xml: Do not document the features which are not
working.
	* man/useradd.8.xml: Fix typo: -u was meant instead of -o.
	* man/useradd.8.xml: Document that the default behavior depends on
	CREATE_HOME.
2010-03-20 10:23:57 +00:00
nekral-guest 6e0fa02fd0 * lib/groupio.c: Fix memory management insplit_groups(). 2010-03-20 10:21:40 +00:00
nekral-guest f19f67c39c * libmisc/strtoday.c: Empty dates indicate a disabled date, this is
not an error.
2010-03-20 10:19:50 +00:00
nekral-guest 823735750a * libmisc/limits.c: Removed unused variable. 2010-03-19 11:25:56 +00:00
nekral-guest 68b6e6d2be * src/useradd.c, lib/commonio.c, po/POTFILES.in: Fix typos. 2010-03-19 11:01:32 +00:00
nekral-guest e19c7200eb * lib/commonio.c: Stop sorting entries when we reach the first
NIS line.
2010-03-18 23:21:21 +00:00
nekral-guest be3a05eab2 Add Alioth feature request reference. 2010-03-18 23:21:10 +00:00
nekral-guest 5e38d92a95 * src/chsh.c: Even for root, warn if an invalid shell is
specified.
2010-03-18 23:21:00 +00:00
nekral-guest 5204a15f95 * man/limits.5.xml: Document the selection of the limits when
multiple lines match the user.
2010-03-18 23:20:41 +00:00
nekral-guest 680a4985ea * man/limits.5.xml: Document the selection of the limits when
multiple lines match the user.
2010-03-18 23:20:30 +00:00
nekral-guest dfce564026 * libmisc/limits.c: Re-indent.
* libmisc/limits.c: Reformat the documentation. Avoid personal
	comments.
	* man/limits.5.xml: Document the new features.
2010-03-18 23:20:24 +00:00
nekral-guest 52c2bb51fb * NEWS, libmisc/limits.c: Fix parsing of limits.
* NEWS, libmisc/limits.c, man/limits.5.xml: Add support for
	infinite limits.
	* NEWS, libmisc/limits.c, man/limits.5.xml: Add support for @group
	syntax.
2010-03-18 23:20:15 +00:00
nekral-guest 6b14a0d08c * lib/tcbfuncs.h: Re-indent.
* lib/tcbfuncs.h: Explicitly indicate functiontakinga void
	parameter.
2010-03-18 19:23:00 +00:00
nekral-guest 395914c162 Reverse comparison for consistency. 2010-03-18 18:58:52 +00:00
nekral-guest 8e2010a26c * src/useradd.c: When exiting because of a failure, warn if an
home directory created, but cannot be removed.
2010-03-18 18:57:03 +00:00
nekral-guest 86498400da * libmisc/chowndir.c: Re-indent.
* libmisc/chowndir.c: Avoid assignment in comparisons.
	* libmisc/chowndir.c: Added brackets and parenthesis.
2010-03-18 18:52:53 +00:00
nekral-guest abffa73776 - add options -g / -G to specify alternative group / gshadow files 2010-03-18 12:28:25 +00:00
nekral-guest 0cbbdb32c4 * libmisc/strtoday.c: Add support for numerical dates, assuming
they are already specified in number of days since Epoch. Return
	-2 in case of errors to support the specification of -1.
	* src/usermod.c, src/useradd.c: Adapt to the new error value of
	strtoday().
	* src/chage.c:  Remove isnum(). Adapt to the new error value of
	strtoday(). Support for numerical dates is moved to strtoday().
2010-03-18 11:53:49 +00:00
nekral-guest 79fa4f3343 * man/po/fr.po: Harmonize name of parameters. 2010-03-18 10:54:32 +00:00
nekral-guest ab50cd2bd8 * NEWS: Indicate which tools support TCB. 2010-03-18 10:53:56 +00:00
nekral-guest 27f67dcad0 * src/pwck.c: Unlock the password and shadow files when there is a
failure to prepare the update in memory.
2010-03-18 10:52:52 +00:00
nekral-guest 6a1dea6602 * src/pwck.c: Only log to SYSLOG when acting on system files. 2010-03-18 10:35:11 +00:00
nekral-guest 657271eb04 * src/pwck.c: Remove the -s option from the usage when USE_TCB is
enabled. The option is still supported, but has no effect, as
	documented in the manpage.
2010-03-18 10:25:08 +00:00
nekral-guest 2db82460b1 * src/pwck.c: Document the sections closed by #endif
* src/pwck.c, man/pwck.8.xml: No alternative shadow file can be
	given when USE_TCB is enabled.
2010-03-18 10:23:51 +00:00
nekral-guest 07c6e99725 * src/pwck.c: Do not use pwd_file and spw_file. Always use the
dbname() functions.
2010-03-18 09:46:15 +00:00
nekral-guest f77e9d0d80 * src/pwck.c: Re-indent. 2010-03-18 09:33:55 +00:00
nekral-guest a996fac57b * src/userdel.c, src/usermod.c, src/vipw.c, src/useradd.c,
src/pwck.c, src/chage.c, lib/shadowio.c: Explicitly use the
	SHADOWTCB_FAILURE return code instead of 0 or implicit conversion
	to booleans.
2010-03-18 09:21:27 +00:00
nekral-guest 8228f99c36 2010-03-18 Paweł Hajdan, Jr. <phajdan.jr@gentoo.org>
* src/pwck.c: Add support for TCB.
	* src/pwck.c: Use spw_dbname() instead of spw_file since TCB
	changes from a file to another depending on the user. Also use
	pw_dbname() for consistency.
2010-03-18 09:01:04 +00:00
nekral-guest 41b5cc2d20 * src/faillog.c: Re-indent. 2010-03-18 00:07:00 +00:00
nekral-guest d1f5c949a9 * lib/tcbfuncs.c: Re-indent. 2010-03-18 00:06:33 +00:00
nekral-guest 29025e40f4 * lib/tcbfuncs.c: Added brackets and parenthesis. 2010-03-18 00:06:21 +00:00
nekral-guest 1d6673a166 * lib/tcbfuncs.c: Avoid implicit int to mode_t conversion. 2010-03-18 00:05:57 +00:00
nekral-guest fba0a83c03 * lib/tcbfuncs.c: move_dir() and shadowtcb_move() need a non NULL
stored_tcb_user.
2010-03-18 00:05:35 +00:00
nekral-guest 7195eb991d * lib/tcbfuncs.c: Removed dead return. 2010-03-18 00:05:11 +00:00
nekral-guest 9f4653b0df * lib/tcbfuncs.c: Include prototypes.h for the definition of Prog. 2010-03-18 00:04:54 +00:00
nekral-guest 99fbf50fa2 Added splint annotations. 2010-03-18 00:04:33 +00:00
nekral-guest ee15c8717f * lib/tcbfuncs.c: Avoid integer to char conversions. 2010-03-18 00:04:05 +00:00
nekral-guest 37b4c8737f * lib/tcbfuncs.c: Avoid implicit signed to unsigned conversions. 2010-03-18 00:03:48 +00:00
nekral-guest 1d969818fd * lib/tcbfuncs.c: Ignore fflush() return value. 2010-03-18 00:03:29 +00:00
nekral-guest 4ca259adaa * lib/tcbfuncs.c: Include shadowio.h, needed for the
spw_setdbname's prototype.
2010-03-18 00:03:06 +00:00
nekral-guest 11e132c8eb Fix typos. 2010-03-18 00:02:45 +00:00
nekral-guest 8402479e16 * lib/tcbfuncs.c: Do not free path before its last use. 2010-03-18 00:02:17 +00:00
nekral-guest aa35a8e46e Avoid implicit conversion of pointers . 2010-03-18 00:02:02 +00:00
nekral-guest 51d181ca58 * lib/tcbfuncs.c: Avoid implicit conversion of pointers or
integers to booleans.
2010-03-18 00:01:30 +00:00
nekral-guest 1bc0a303dc * lib/tcbfuncs.c: Only FreeBSD specify that the returned buffer is
NULL in case of failure. The return value of asprintf shall be
	checked.
2010-03-18 00:01:00 +00:00
nekral-guest 43211abb65 * lib/commonio.c: Ignore the return value of close when a
failure is reported.
2010-03-18 00:00:05 +00:00
nekral-guest 8acf9cd11d * lib/tcbfuncs.h: Added type shadowtcb_status.
* lib/tcbfuncs.h, lib/tcbfuncs.c: Return a shadowtcb_status
	instead of an int.
	* lib/tcbfuncs.c: Do not return in OUT_OF_MEMORY.
2010-03-17 23:59:55 +00:00
nekral-guest fe71812b1d * lib/commonio.c: Avoid implicit conversion of pointers to
booleans.
	* lib/commonio.c: Ignore the return value of close when a
	failure is reported.
2010-03-17 23:59:47 +00:00
nekral-guest a013f8519b Updated copyright dates. 2010-03-16 19:15:34 +00:00
nekral-guest c0e7dcd2fd * man/faillog.8.xml: Document the behavior in display mode of the
-a option.
	* NEWS, man/faillog.8.xml, src/faillog.c: Extend the -a option to
	the non-display mode. This changes the default behavior of the -l,
	-m, -r, -t options when -a is not specified (restrict to existing
	users).
2010-03-16 19:15:22 +00:00
nekral-guest 5d6c314304 * man/chage.1.xml, man/login.defs.5.xml, man/pwck.8.xml,
man/pwconv.8.xml, man/useradd.8.xml, man/userdel.8.xml,
	man/usermod.8.xml, man/vipw.8.xml: Document the usage of the
	TCB_AUTH_GROUP, TCB_SYMLINKS, and USE_TCB configuration
	parameters.
	* man/pwconv.8.xml, man/pwck.8.xml: Document the behavior when
	USE_TCB is enabled.
2010-03-16 19:15:05 +00:00
nekral-guest c5fc8dd75d * po/POTFILES.in, lib/tcbfuncs.c: Add more strings for
translation.
	* lib/tcbfuncs.c: Indicate the name of the program in error
	messages. Avoid perror.
	* src/useradd.c: Re-indent.
	* src/useradd.c: Add more strings for translation. Indicate the
	name of the program in error messages.
	* src/userdel.c: Re-indent.
	* src/userdel.c: Add more strings for translation. Indicate the
	name of the program in error messages.
2010-03-16 19:14:54 +00:00
nekral-guest ad694905be * src/usermod.c: user_newname and user_newid cannot be used to
test if the username or ID is changed. lflg and uflg should be
	used instead.
2010-03-16 19:14:37 +00:00
nekral-guest 6c4e2931ef * src/userdel.c: Avoid perror. Give more verbose warnings. 2010-03-16 19:13:53 +00:00
nekral-guest fd39a24b34 Remove generated file. 2010-03-11 22:07:50 +00:00
nekral-guest ccc65bfde7 * man/Makefile.am: Indicate that man/generate_mans.deps is
generated.
2010-03-11 22:04:22 +00:00
nekral-guest f13f60504a * lib/commonio.c: Re-indent.
* lib/commonio.c: Document the sections closed by #endif
	* lib/commonio.c: Added brackets.
	* lib/commonio.c: Avoid implicit conversion of integer to
	booleans.
2010-03-11 22:04:14 +00:00
nekral-guest 33d3e28a7f * src/userdel.c: Re-indent.
* src/userdel.c: Added brackets.
	* src/userdel.c: Avoid implicit conversion of pointers to
	booleans.
2010-03-11 22:04:06 +00:00
nekral-guest 69798dde65 * lib/shadowio.c: Re-indent.
* lib/shadowio.c: Added brackets and parenthesis.
	* lib/shadowio.c: Document the sections closed by #endif
	* lib/shadowio.c: Avoid negation of comparisons.
	* lib/shadowio.c: Avoid implicit conversion of integer to booleans
	and booleans to integers.
2010-03-11 22:03:57 +00:00
nekral-guest ad6730687f * src/useradd.c: Re-indent.
* src/useradd.c: Added brackets.
	* src/useradd.c: Avoid implicit conversion of integers to
	booleans.
	* src/useradd.c: Harmonize error messages.
2010-03-11 22:03:45 +00:00
nekral-guest e7d57e1a77 * src/vipw.c: Document the sections closed by #endif
* src/vipw.c: Avoid implicit conversion of pointers or integers to
	booleans.
	* src/vipw.c: Added brackets and parenthesis.
	* src/vipw.c: Limit the definition of some variables and macros to
	the WITH_TCB scope.
	* src/vipw.c: Avoid assignment in comparisons.
	* src/vipw.c: Replace PASSWD_FILE (resp. GROUP_FILE and
	SGROUP_FILE) by pw_dbname () (resp. gr_dbname () and sgr_dbname ()).
	This is more consistent with the shadow file handling and may be
	useful to allow edition of another partition's files.
2010-03-11 22:03:37 +00:00
nekral-guest f9b8a95b92 * src/usermod.c: Re-indent.
* src/usermod.c: Avoid implicit conversion of pointers to
	booleans.
	* src/usermod.c: Added parenthesis.
2010-03-11 22:03:11 +00:00
nekral-guest 5cd1d6e287 * src/pwunconv.c: Only check USE_TCB if configured WITH_TCB. 2010-03-11 22:02:54 +00:00
nekral-guest 59910c45d5 * src/userdel.c: Re-indent.
* src/userdel.c: Avoid implicit conversion of pointers to
	booleans.
	* src/userdel.c: Document the sections closed by #endif
2010-03-11 22:01:59 +00:00
nekral-guest a8b11f5c18 * src/pwconv.c: Only check USE_TCB if configured WITH_TCB. 2010-03-11 22:01:15 +00:00
nekral-guest d562701538 * libmisc/copydir.c: Added parenthesis. 2010-03-11 22:00:41 +00:00
nekral-guest 9866af3777 2010-02-14 Michael Bunk <mb@computer-leipzig.com>
* NEWS, lib/gshadow.c: Fix parsing of gshadow entries.
2010-03-10 22:30:03 +00:00
nekral-guest 391a384715 2010-01-30 Paweł Hajdan, Jr. <phajdan.jr@gentoo.org>
* NEWS: Add support for TCB.
	* lib/tcbfuncs.h, lib/tcbfuncs.c, lib/Makefile.am: New library to
	support TCB.
	* lib/prototypes, libmisc/copydir.c (remove_tree): Add boolean
	parameter remove_root.
	* configure.in: Add conditional WITH_TCB.
	* src/userdel.c, src/usermod.c: Add support for TCB. Update call to
	remove_tree().
	* src/pwconv.c, src/pwunconv.c: Should not be used with TCB enabled.
	* src/vipw.c: Add support for TCB. Update call to remove_tree().
	* src/useradd.c: Add support for TCB. Open the shadow file outside
	of open_files().
	* src/chage.c: Add support for TCB.
	* src/Makefile.am: Install passwd sgid shadow when TCB is enabled.
	* lib/getdefs.c, man/vipw.8.xml, man/login.defs.5.xml,
	man/login.defs/TCB_AUTH_GROUP.xml, man/login.defs/USE_TCB.xml,
	man/login.defs/TCB_SYMLINKS.xml, man/generate_mans.mak,
	man/generate_mans.deps, man/Makefile.am: New configuration
	parameters: TCB_AUTH_GROUP, TCB_SYMLINKS, USE_TCB.
	* lib/shadowio.c, lib/commonio.c: Add support for TCB.
2010-03-04 18:11:13 +00:00
nekral-guest 5ba95d4c53 * libmisc/env.c: Fix sanitize_env() noslash support. This fixes
Alioth#311740. Thanks to Jason Cassell.
2010-01-24 17:23:42 +00:00
nekral-guest 291b28ac52 * src/su.c: Do not sanitize the environment. This breaks
--preserve-environment. This sanitation was disabled on Debian
	since quite some time with no reported issues, and sanitize_env()
	documentation agrees that it should be useless as all modern
	Unixes will handle setuid executables properly. This Fixes
	Alioth#312287.
2010-01-24 17:13:40 +00:00
nekral-guest 0fce70b091 * libmisc/setupenv.c: Fix typo from 2009-11-01. 2010-01-24 17:05:37 +00:00
nekral-guest c5c94a1d2c * configure.in: Add support for TCB in configure.in. Actual TCB
support will follow.
2010-01-24 16:53:15 +00:00
nekral-guest 289913e5ff * NEWS, src/groupmod.c: Fixed groupmod when configured with
--enable-account-tools-setuid.
2009-11-05 22:03:36 +00:00
nekral-guest e770e87035 * NEWS, man/login.defs.d/ENV_SUPATH.xml, libmisc/setupenv.c:
Harmonize other paths and documentation with previous
	change.
2009-11-01 16:59:48 +00:00
nekral-guest 248d5fd870 2009-11-01 Michel Hermier <michel.hermier@gmail.com>
* src/su.c: Set the default ENV_SUPATH to
	/sbin:/bin:/usr/sbin:/usr/bin (i.e. PATH when no ENV_SUPATH is
	specified).
2009-11-01 16:57:59 +00:00
nekral-guest 7fa666b909 2009-10-15 Thorsten Kukuk <kukuk@suse.de>
* src/faillog.c, man/faillog.8.xml: Harmonize long option in code
	and documentation. Use --lock-secs instead of --lock-time.
2009-10-17 20:40:53 +00:00
nekral-guest 27db71370a Indicate new translations. 2009-10-17 20:40:00 +00:00
nekral-guest a632c4047e Changelog police. 2009-10-15 16:50:43 +00:00
bubulle cc873b51c3 Completed Czech translation 2009-10-05 06:11:17 +00:00
bubulle 5c46f26505 Vietnamese translation compelted 2009-09-29 18:11:31 +00:00
bubulle b70e0a466f Czech translation update 2009-09-27 06:23:23 +00:00
bubulle d7ac25f813 French translation update 2009-09-24 20:20:47 +00:00
bubulle 1af98ea784 Vietnamese translation update 2009-09-24 20:18:50 +00:00
nekral-guest 2be243c143 pid_child and kill_child are only used when USE_PAM. 2009-09-08 21:33:14 +00:00
nekral-guest 1e51ab0b23 * lib/commonio.c: Avoid pre-decrement operator (--n). Add some
comments.
	* libmisc/cleanup.c: Fix off by one in an assertion.
2009-09-08 21:00:12 +00:00
nekral-guest a845c67c60 * src/su.c: Fix indentation.
* src/su.c: Add more messages for translation.
	* src/su.c: Ignore kill() return value when sending the TERM
	signal. If it fails, a KILL should be sent anyway.
2009-09-08 20:46:43 +00:00
nekral-guest 756700ddf3 * NEWS, src/su.c: When su receives a signal, wait for the child to
terminate (after sending a SIGTERM), and kill it only if it did
	not terminate by itself. No delay will be enforced if the child
	cooperates. See http://bugs.gentoo.org/282094
	* NEWS, man/su.1.xml: Document su's exit values.
2009-09-08 20:39:15 +00:00
nekral-guest da18e77e9a * src/useradd.c: The default value for the CREATE_MAIL_SPOOL
variable (i.e. if CREATE_MAIL_SPOOL= is specified without any
	values) is "no", not DCREATE_MAIL_SPOOL ("CREATE_MAIL_SPOOL=").
2009-09-08 13:16:58 +00:00
nekral-guest 38e7ec3316 * src/useradd.c: Avoid redefinition of SHELL. Use DSHELL instead.
For consistency, change HOME, INACT, EXPIRE, SKEL, and
	CREATE_MAIL_SPOOL to DHOME, DINACT, DEXPIRE, DSKEL, and
	DCREATE_MAIL_SPOOL.
2009-09-08 13:11:03 +00:00
nekral-guest ee792a8fa1 * src/newusers.c: Prefer #ifdef over #if. 2009-09-08 13:06:57 +00:00
nekral-guest 1f8e2dcda2 * configure.in: We do not use SETPGRP_VOID, and already assume
that setpgrp has a void argument. Remove AC_FUNC_SETPGRP to ease
	cross compiling.
2009-09-08 13:05:59 +00:00
nekral-guest f103e6263d * man/generate_translations.mak, man/generate_mans.mak,
po/Makefile.in.in: Removing and restoring the config.xml file
	broke parallel builds. Build the manpages based on *.xml-config
	files instead of *.xml files.  The *.xml do not include config.xml
	anymore, which permits to run xml2po without needing to remove
	config.xml. The config.xml is restored in the *.xml-config files.
	* man/groupadd.8.xml: Implementation of the above.
	* man/generate_mans.deps: Updated dependencies
2009-09-07 21:49:29 +00:00
nekral-guest 031279dfb2 * libmisc/limits.c: Fix the format to match the unsigned long
variable in argument.
	* libmisc/utmp.c: Fix tests. tmptty is a variable stack. ut_host
	is an array of the ut structure. None of them can be NULL.
2009-09-07 19:50:00 +00:00
nekral-guest 2a58111fc1 Fix typo in the version numbers. 2009-09-07 19:25:07 +00:00
nekral-guest d346c7c6a7 * lib/shadowmem.c: Only copy the required fields of the struct
spwd. (start with the primitive types)
	* lib/shadowmem.c: Avoid memzero() on a possibly NULL pointer.
	* lib/groupmem.c: Only copy the required fields of the struct
	group. (start with the primitive types)
	* lib/groupmem.c: Avoid memzero() on a possibly NULL pointer.
	* lib/groupmem.c: Free gr_mem in addition to its elements.
	* lib/sgroupio.c: The struct sgrp has no primitive types to be
	copied initially.
	* lib/sgroupio.c: Avoid memzero() on a possibly NULL pointer.
	* lib/sgroupio.c: Free sg_mem and sg_add in addition to their
	elements.
	* lib/pwmem.c: Only copy the required fields of the struct
	passwd. (start with the primitive types)
2009-09-07 19:08:10 +00:00
nekral-guest 1a86dc913f * lib/sgroupio.h: Harmonize splint annotations of sgr_locate()
prototype with the one used in its definition.
2009-09-07 18:59:03 +00:00
nekral-guest 1e6b107d99 2009-09-07 Steve Grubb <sgrubb@redhat.com>
* libmisc/copydir.c, lib/shadowmem.c, lib/groupmem.c, lib/pwmem.c:
	Fix some memory leaks.
2009-09-07 18:53:47 +00:00
nekral-guest 8806b07bd2 * src/userdel.c, src/lastlog.c, src/gpasswd.c, src/newusers.c,
src/chpasswd.c, src/groupmems.c, src/usermod.c, src/chgpasswd.c,
	src/vipw.c, src/su.c, src/useradd.c, src/groupmod.c, src/passwd.c,
	src/groupadd.c, src/chage.c, src/faillog.c, src/chsh.c: Use
	booleans for tests.
	* src/userdel.c, src/gpasswd.c, src/groupmems.c, src/usermod.c,
	src/groupmod.c, src/passwd.c: Use a break even after usage().
2009-09-05 22:31:29 +00:00
nekral-guest ff60398b1c Added new TODO item. 2009-09-05 20:26:09 +00:00
nekral-guest 32e2ef34a3 * src/gpasswd.c, src/groupmems.c: Split the groupmems and gpasswd
Usage string. It was changed anyway to add the --help option.
2009-09-05 20:25:40 +00:00
nekral-guest 91b60a955c * NEWS, src/userdel.c, src/lastlog.c, src/gpasswd.c,
src/newusers.c, src/chpasswd.c, src/groupmems.c, src/usermod.c,
	src/chgpasswd.c, src/vipw.c, src/su.c, src/useradd.c,
	src/groupmod.c, src/passwd.c, src/groupadd.c, src/chage.c,
	src/faillog.c, src/chsh.c: If someone uses the -h/--help options,
	the usage should not go to stderr nor should the utility exit with
	non-zero status. All of the shadow utils do just this
	unfortunately, so convert them over to sanity.
	* man/groupmems.8.xml, man/gpasswd.1.xml: Added option -h/--help.
2009-09-04 23:02:33 +00:00
nekral-guest 3d10e75117 * src/useradd.c: Fixed wrong format string.
* lib/gshadow.c: Removed declaration of unused variable.
2009-09-04 22:09:58 +00:00
nekral-guest 915e78ee2d * man/generate_mans.mak, man/generate_translations.mak: Provide an
useful error message when --enable-man is not enabled and the
	translated manpages are not generated.
2009-08-30 19:46:54 +00:00
nekral-guest 9031103c24 * man/login.defs.d/ENCRYPT_METHOD.xml: Avoid using sub-lists. They
break the groff formatting.
2009-08-21 15:02:32 +00:00
nekral-guest 3db03960be * po/fr.po: Fix typos, based on reviews by the Debian French
translation team.
2009-08-14 21:12:15 +00:00
bubulle afa1c65d32 Complete French translation 2009-07-27 22:35:13 +00:00
bubulle 41aa36a0a3 French translation update 2009-07-25 17:23:19 +00:00
10424 changed files with 478211 additions and 46049 deletions
+1
View File
@@ -17,6 +17,7 @@ Makefile.in
/ABOUT-NLS /ABOUT-NLS
/aclocal.m4 /aclocal.m4
/autom4te.cache /autom4te.cache
/compile
/config.guess /config.guess
/config.h /config.h
/config.h.in /config.h.in
+2597 -4
View File
File diff suppressed because it is too large Load Diff
+203 -2
View File
@@ -1,6 +1,207 @@
$Id$ $Id$
shadow-4.1.4.1 -> shadow-4.1.4.2 2009-07-24 shadow-4.1.5.1 -> shadow-4.2 UNRELEASED
*** general
* Handle libc whose crypt() returns NULL when passed a salt that
violates specs or system requirements (e.g. FIPS140). This is needed
with glibc/eglibc 2.17 for tools checking passwords (passwd (non PAM
enabled) or newgrp), and for tools generating encrypted passwords
(chgpasswd, chpasswd, or gpasswd when non PAM enabled or when a fixed
crypt method is requested on the command line, and newusers, or passwd
in their non PAM enabled versions)
* Fix segfault when reading groups split on multiple lines. This impacts
most user/group management tools when MAX_MEMBERS_PER_GROUP is set.
- su
* When su receives a signal (SIGTERM, or SIGINT/SIGQUIT in non
interactive mode), kill the child process group, rather than just the
immediate child.
* Fix segmentation faults for users without a proper home or shell in
their passwd entries.
- login
* Fix segmentation faults for users without a proper home or shell in
their passwd entries.
*** documentation
* Fixed useradd man page (--home-dir option, instead of --home).
*** translation
* Updated Russian translation.
* Updated German man pages translation.
* Fixed gshadow Japanese man page translation.
shadow-4.1.5 -> shadow-4.1.5.1 2012-05-25
- login
* Log into utmp(x) when PAM is enabled, but do not log into wtmp.
This complete pam_lastlog which logs into wtmp and in into utmp(x).
- su
* non PAM enabled versions: do not fail if su is called without a
controlling terminal.
- userdel
* Fix segfault when userdel removes the user's group.
*** documentation
* .so links now point to paths relative to the top-level manual hierarchy
*** translation
* Updated French man pages translation.
* Updated German man pages translation.
* Updated Polish man pages translation. (logoutd.8)
shadow-4.1.4.3 -> shadow-4.1.5 2012-02-12
*** security
* su -c could be abused by the executed command to invoke commands with
the caller privileges. See below. (CVE-2005-4890)
*** general
* report usage error to stderr, but report usage help to stdout (and return
zero) when explicitly requested (e.g. with --help).
* initial support for tcb (http://openwall.com/tcb/) for useradd,
userdel, usermod, chage, pwck, vipw.
* Added support for ACLs and Extended Attributes in useradd and usermod.
Support shall be enabled with the new --with-acl or --with-attr
configure options.
* Added diagnosis for lock failures.
* use libsemanage instead of the semanage tool.
- chage
* Add --root option.
- chfn
* Add --root option.
- chgpasswd
* When the gshadow file exists but there are no gshadow entries, an entry
is created if the password is changed and group requires a
shadow entry.
* Add --root option.
- chpasswd
* PAM enabled versions: restore the -e option to allow restoring
passwords without knowing those passwords. Restore together the -m
and -c options. (These options were removed in shadow-4.1.4 on PAM
enabled versions)
* When the shadow file exists but there are no shadow entries, an entry
is created if the password is changed and passwd requires a
shadow entry.
* Add --root option.
- chsh
* Add --root option.
- faillog
* The -l, -m, -r, -t options only act on the existing users, unless -a is
specified.
* Add --root option.
- gpasswd
* Add --root option.
- groupadd
* Add --root option.
- groupdel
* Add --root option.
- groupmems
* Fix parsing of gshadow entries.
* Add --root option.
- groupmod
* Fixed groupmod when configured with --enable-account-tools-setuid.
* When the gshadow file exists but there are no gshadow entries, an entry
is created if the password is changed and group requires a
shadow entry.
* Add --root option.
- grpck
* Add --root option.
* NIS entries were dropped by -s (sort).
- grpconv
* Add --root option.
- grpunconv
* Add --root option.
- lastlog
* Add --root option.
- login
* Fixed limits support (non PAM enabled versions only)
* Added support for infinite limits and group based limits (non PAM
enabled versions only)
* Fixed infinite loop when CONSOLE is configured with a colon-separated
list of TTYs.
* Fixed warning and support for CONSOLE_GROUPS for users member of more
than 16 groups.
* Do not log into utmp(x) or wtmp when PAM is enabled. This is done by
pam_lastlog.
- newgrp, sg
* Fix parsing of gshadow entries.
- newusers
* Add --root option.
- passwd
* Add --root option.
- pwpck
* NIS entries were dropped by -s (sort).
* Add --root option.
- pwconv
* Add --root option.
- pwunconv
* Add --root option.
- useradd
* If the skeleton directory contained hardlinked files, copies of the
hardlink were removed from the skeleton directory.
* Add --root option.
- userdel
* Check the existence of the user's mail spool before trying to remove
it. If it does not exist, a warning is issued, but no failure.
* Do not remove a group with the same name as the user (usergroup) if
this group isn't the user's primary group.
* Add --root option.
* Add --selinux-user option.
- usermod
* Accept options in any order (username not necessarily at the end)
* When the shadow file exists but there are no shadow entries, an entry
is created if the password is changed and passwd requires a
shadow entry, or if aging features are used (-e or -f).
* Add --root option.
- su
* Document the su exit values.
* When su receives a signal, wait for the child to terminate (after
sending a SIGTERM), and kill it only if it did not terminate by itself.
No delay will be enforced if the child cooperates.
* Default ENV_SUPATH is /sbin:/bin:/usr/sbin:/usr/bin
* Fixed infinite loop when CONSOLE is configured with a colon-separated
list of TTYs.
* Fixed warning and support for CONSOLE_GROUPS for users member of more
than 16 groups.
* Do not forward the controlling terminal to commands executed with -c.
This prevents tty hijacking which could lead to execution with the
caller's privileges.
* Close PAM sessions as root. This will be more friendly to PAM modules
like pam_mount or pam_systemd.
* Added support for PAM modules which change PAM_USER.
*** translation
* Updated Brazilian Portuguese translation.
* Updated Catalan translation.
* Updated Czech translation.
* Updated Danish translation.
* New Danish man pages translation.
* Updated French translation.
* Updated French man pages translation.
* Updated German translation.
* Updated German man pages translation.
* Updated Greek translation.
* Updated Italian man pages translation.
* Updated Japanese translation.
* Updated Kazakh translation.
* Updated Norwegian Bokmål translation.
* Updated Portuguese translation.
* Updated Russian translation.
* Updated Simplified Chinese translation.
* Updated Simplified Chinese man pages translation.
* Updated Swedish translation.
* Updated Vietnamese translation.
shadow-4.1.4.2 -> shadow-4.1.4.3 2011-02-15
*** security
- CVE-2011-0721: An insufficient input sanitation in chfn can be exploited
to create users or groups in a NIS environment.
shadow-4.1.4.1 -> shadow-4.1.4.2 2009-07-24
- general - general
* Improved support for large groups (impacts most user/group management * Improved support for large groups (impacts most user/group management
@@ -310,7 +511,7 @@ shadow-4.1.0 -> shadow-4.1.1 02-04-2008
faillog faster. faillog faster.
- gpasswd - gpasswd
* Fix failures when the gshadow file is not present. * Fix failures when the gshadow file is not present.
* When a password is moved to the gshadow file, use "x" instead of "x" * When a password is moved to the gshadow file, use "x" instead of "!"
to indicate that the password is shadowed (consistency with grpconv). to indicate that the password is shadowed (consistency with grpconv).
* Make sure the group and gshadow files are unlocked on exit. * Make sure the group and gshadow files are unlocked on exit.
- groupadd - groupadd
+5 -1
View File
@@ -37,7 +37,7 @@ S/Key support:
Authors and contributors Authors and contributors
======================== ========================
Thanks to at least the following people for sending me patches, bug Thanks to at least the following people for sending patches, bug
reports and various comments. This list may be incomplete, I received reports and various comments. This list may be incomplete, I received
a lot of mail... a lot of mail...
@@ -69,6 +69,7 @@ Greg Mortensen <loki@world.std.com>
Guido van Rooij Guido van Rooij
Guy Maor <maor@debian.org> Guy Maor <maor@debian.org>
Hrvoje Dogan <hdogan@bjesomar.srce.hr> Hrvoje Dogan <hdogan@bjesomar.srce.hr>
Jakub Hrozek <jhrozek@redhat.com>
Janos Farkas <chexum@bankinf.banki.hu> Janos Farkas <chexum@bankinf.banki.hu>
Jay Soffian <jay@lw.net> Jay Soffian <jay@lw.net>
Jesse Thilo <Jesse.Thilo@pobox.com> Jesse Thilo <Jesse.Thilo@pobox.com>
@@ -80,6 +81,7 @@ Joshua Cowan <jcowan@hermit.reslife.okstate.edu>
Judd Bourgeois <shagboy@bluesky.net> Judd Bourgeois <shagboy@bluesky.net>
Juergen Heinzl <unicorn@noris.net> Juergen Heinzl <unicorn@noris.net>
Juha Virtanen <jiivee@iki.fi> Juha Virtanen <jiivee@iki.fi>
Julian Pidancet <julian.pidancet@gmail.com>
Julianne Frances Haugh <jockgrrl@ix.netcom.com> Julianne Frances Haugh <jockgrrl@ix.netcom.com>
Leonard N. Zubkoff <lnz@dandelion.com> Leonard N. Zubkoff <lnz@dandelion.com>
Luca Berra <bluca@www.polimi.it> Luca Berra <bluca@www.polimi.it>
@@ -95,10 +97,12 @@ Mike Pakovic <mpakovic@users.southeast.net>
Nicolas François <nicolas.francois@centraliens.net> Nicolas François <nicolas.francois@centraliens.net>
Nikos Mavroyanopoulos <nmav@i-net.paiko.gr> Nikos Mavroyanopoulos <nmav@i-net.paiko.gr>
Pavel Machek <pavel@bug.ucw.cz> Pavel Machek <pavel@bug.ucw.cz>
Peter Vrabec <pvrabec@redhat.com>
Phillip Street Phillip Street
Rafał Maszkowski <rzm@icm.edu.pl> Rafał Maszkowski <rzm@icm.edu.pl>
Rani Chouha <ranibey@smartec.com> Rani Chouha <ranibey@smartec.com>
Sami Kerola <kerolasa@rocketmail.com> Sami Kerola <kerolasa@rocketmail.com>
Scott Garman <scott.a.garman@intel.com>
Sebastian Rick Rijkers <srrijkers@gmail.com> Sebastian Rick Rijkers <srrijkers@gmail.com>
Seraphim Mellos <mellos@ceid.upatras.gr> Seraphim Mellos <mellos@ceid.upatras.gr>
Shane Watts <shane@nexus.mlckew.edu.au> Shane Watts <shane@nexus.mlckew.edu.au>
+14 -1
View File
@@ -1,3 +1,10 @@
* 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 /etc/default/useradd
* GROUP=1000 should accept a group name. * GROUP=1000 should accept a group name.
@@ -108,7 +115,13 @@ ALL:
entry (with a password). entry (with a password).
- Add check to move passwd passwords to shadow if there is a shadow - Add check to move passwd passwords to shadow if there is a shadow
file. file.
- Support an alternative /etc/tcb directory as second parameter.
- add options -g / -G to specify alternative group / gshadow files
- su - su
- add a login.defs configuration parameter to add variables to keep in - add a login.defs configuration parameter to add variables to keep in
the environment with "su -l" (TERM/TERMCOLOR/... the environment with "su -l" (TERM/TERMCOLOR/...)
- vipw
- set ACLs and XATTRs on the temporary file (and backups?)
- vipw + selinux -> use lib/selinux.c
+2
View File
@@ -1,5 +1,7 @@
#! /bin/sh #! /bin/sh
autoreconf -v -f --install || exit 1 autoreconf -v -f --install || exit 1
./configure \ ./configure \
CFLAGS="-O2 -Wall" \ CFLAGS="-O2 -Wall" \
--enable-man \ --enable-man \
+146 -15
View File
@@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
AC_INIT AC_INIT
AM_INIT_AUTOMAKE(shadow, 4.1.4.2) AM_INIT_AUTOMAKE(shadow, 4.3)
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
dnl Some hacks... dnl Some hacks...
@@ -19,7 +19,6 @@ AC_PROG_CC
AC_ISC_POSIX AC_ISC_POSIX
AC_PROG_LN_S AC_PROG_LN_S
AC_PROG_YACC AC_PROG_YACC
AM_C_PROTOTYPES
AM_PROG_LIBTOOL AM_PROG_LIBTOOL
dnl Checks for libraries. dnl Checks for libraries.
@@ -33,7 +32,8 @@ AC_HEADER_STDBOOL
AC_CHECK_HEADERS(errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \ AC_CHECK_HEADERS(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 \ utmpx.h termios.h termio.h sgtty.h sys/ioctl.h syslog.h paths.h \
utime.h ulimit.h sys/resource.h gshadow.h lastlog.h \ utime.h ulimit.h sys/resource.h gshadow.h lastlog.h \
locale.h rpc/key_prot.h netdb.h) locale.h rpc/key_prot.h netdb.h acl/libacl.h attr/libattr.h \
attr/error_context.h)
dnl shadow now uses the libc's shadow implementation 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_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
@@ -41,7 +41,8 @@ AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
AC_CHECK_FUNCS(l64a fchmod fchown fsync futimes getgroups gethostname getspnam \ AC_CHECK_FUNCS(l64a fchmod fchown fsync futimes getgroups gethostname getspnam \
gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \ gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \
lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \ lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \
getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo) getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo \
ruserok)
AC_SYS_LARGEFILE AC_SYS_LARGEFILE
dnl Checks for typedefs, structures, and compiler characteristics. dnl Checks for typedefs, structures, and compiler characteristics.
@@ -112,7 +113,6 @@ AC_REPLACE_FUNCS(sgetgrent sgetpwent sgetspent)
AC_REPLACE_FUNCS(snprintf strcasecmp strdup strerror strstr) AC_REPLACE_FUNCS(snprintf strcasecmp strdup strerror strstr)
AC_CHECK_FUNC(setpgrp) AC_CHECK_FUNC(setpgrp)
AC_FUNC_SETPGRP
if test "$ac_cv_header_shadow_h" = "yes"; then if test "$ac_cv_header_shadow_h" = "yes"; then
AC_CACHE_CHECK(for working shadow group support, AC_CACHE_CHECK(for working shadow group support,
@@ -195,8 +195,10 @@ AC_DEFINE_UNQUOTED(PASSWD_PROGRAM, "$shadow_cv_passwd_dir/passwd",
dnl XXX - quick hack, should disappear before anyone notices :). dnl XXX - quick hack, should disappear before anyone notices :).
AC_DEFINE(USE_SYSLOG, 1, [Define to use syslog().]) AC_DEFINE(USE_SYSLOG, 1, [Define to use syslog().])
AC_DEFINE(RLOGIN, 1, [Define if login should support the -r flag for rlogind.]) if test "$ac_cv_func_ruserok" = "yes"; then
AC_DEFINE(RUSEROK, 0, [Define to the ruserok() "success" return value (0 or 1).]) 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, AC_ARG_ENABLE(shadowgrp,
[AC_HELP_STRING([--enable-shadowgrp], [enable shadow group support @<:@default=yes@:>@])], [AC_HELP_STRING([--enable-shadowgrp], [enable shadow group support @<:@default=yes@:>@])],
@@ -238,6 +240,13 @@ AC_ARG_ENABLE(utmpx,
[enable_utmpx="no"] [enable_utmpx="no"]
) )
AC_ARG_ENABLE(subordinate-ids,
[AC_HELP_STRING([--enable-subordinate-ids],
[support subordinate ids @<:@default=yes@:>@])],
[enable_subids="${enableval}"],
[enable_subids="maybe"]
)
AC_ARG_WITH(audit, AC_ARG_WITH(audit,
[AC_HELP_STRING([--with-audit], [use auditing support @<:@default=yes if found@:>@])], [AC_HELP_STRING([--with-audit], [use auditing support @<:@default=yes if found@:>@])],
[with_audit=$withval], [with_audit=maybe]) [with_audit=$withval], [with_audit=maybe])
@@ -247,11 +256,20 @@ AC_ARG_WITH(libpam,
AC_ARG_WITH(selinux, AC_ARG_WITH(selinux,
[AC_HELP_STRING([--with-selinux], [use SELinux support @<:@default=yes if found@:>@])], [AC_HELP_STRING([--with-selinux], [use SELinux support @<:@default=yes if found@:>@])],
[with_selinux=$withval], [with_selinux=maybe]) [with_selinux=$withval], [with_selinux=maybe])
AC_ARG_WITH(acl,
[AC_HELP_STRING([--with-acl], [use ACL support @<:@default=yes if found@:>@])],
[with_acl=$withval], [with_acl=maybe])
AC_ARG_WITH(attr,
[AC_HELP_STRING([--with-attr], [use Extended Attribute support @<:@default=yes if found@:>@])],
[with_attr=$withval], [with_attr=maybe])
AC_ARG_WITH(skey, AC_ARG_WITH(skey,
[AC_HELP_STRING([--with-skey], [use S/Key support @<:@default=no@:>@])], [AC_HELP_STRING([--with-skey], [use S/Key support @<:@default=no@:>@])],
[with_skey=$withval], [with_skey=no]) [with_skey=$withval], [with_skey=no])
AC_ARG_WITH(tcb,
[AC_HELP_STRING([--with-tcb], [use tcb support (incomplete) @<:@default=yes if found@:>@])],
[with_tcb=$withval], [with_tcb=maybe])
AC_ARG_WITH(libcrack, AC_ARG_WITH(libcrack,
[AC_HELP_STRING([--with-libcrack], [use libcrack @<:@default=yes if found and if PAM not enabled@:>@])], [AC_HELP_STRING([--with-libcrack], [use libcrack @<:@default=no@:>@])],
[with_libcrack=$withval], [with_libcrack=no]) [with_libcrack=$withval], [with_libcrack=no])
AC_ARG_WITH(sha-crypt, AC_ARG_WITH(sha-crypt,
[AC_HELP_STRING([--with-sha-crypt], [allow the SHA256 and SHA512 password encryption algorithms @<:@default=yes@:>@])], [AC_HELP_STRING([--with-sha-crypt], [allow the SHA256 and SHA512 password encryption algorithms @<:@default=yes@:>@])],
@@ -313,10 +331,81 @@ if test "$enable_man" = "yes"; then
fi fi
AM_CONDITIONAL(ENABLE_REGENERATE_MAN, test "x$enable_man" != "xno") AM_CONDITIONAL(ENABLE_REGENERATE_MAN, test "x$enable_man" != "xno")
if test "$enable_subids" != "no"; then
dnl
dnl FIXME: check if 32 bit UIDs/GIDs are supported by libc
dnl
AC_CHECK_SIZEOF([uid_t],, [#include "sys/types.h"])
AC_CHECK_SIZEOF([gid_t],, [#include "sys/types.h"])
if test "$ac_cv_sizeof_uid_t" -ge 4 && test "$ac_cv_sizeof_gid_t" -ge 4; then
AC_DEFINE(ENABLE_SUBIDS, 1, [Define to support the subordinate IDs.])
enable_subids="yes"
else
if test "x$enable_subids" = "xyes"; then
AC_MSG_ERROR([Cannot enable support the subordinate IDs on systems where gid_t or uid_t has less than 32 bits])
fi
enable_subids="no"
fi
fi
AM_CONDITIONAL(ENABLE_SUBIDS, test "x$enable_subids" != "xno")
AC_SUBST(LIBCRYPT) AC_SUBST(LIBCRYPT)
AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt], AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt],
[AC_MSG_ERROR([crypt() not found])]) [AC_MSG_ERROR([crypt() not found])])
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"])
if test "$acl_header$with_acl" = "noyes" ; then
AC_MSG_ERROR([acl/libacl.h or attr/error_context.h is missing])
elif test "$acl_header" = "yes" ; then
AC_CHECK_LIB(acl, perm_copy_file,
[AC_CHECK_LIB(acl, perm_copy_fd,
[acl_lib="yes"],
[acl_lib="no"])],
[acl_lib="no"])
if test "$acl_lib$with_acl" = "noyes" ; then
AC_MSG_ERROR([libacl not found])
elif test "$acl_lib" = "no" ; then
with_acl="no"
else
AC_DEFINE(WITH_ACL, 1,
[Build shadow with ACL support])
LIBACL="-lacl"
with_acl="yes"
fi
else
with_acl="no"
fi
fi
AC_SUBST(LIBATTR)
if test "$with_attr" != "no"; then
AC_CHECK_HEADERS(attr/libattr.h attr/error_context.h, [attr_header="yes"], [attr_header="no"])
if test "$attr_header$with_attr" = "noyes" ; then
AC_MSG_ERROR([attr/libattr.h or attr/error_context.h is missing])
elif test "$attr_header" = "yes" ; then
AC_CHECK_LIB(attr, attr_copy_file,
[AC_CHECK_LIB(attr, attr_copy_fd,
[attr_lib="yes"],
[attr_lib="no"])],
[attr_lib="no"])
if test "$attr_lib$with_attr" = "noyes" ; then
AC_MSG_ERROR([libattr not found])
elif test "$attr_lib" = "no" ; then
with_attr="no"
else
AC_DEFINE(WITH_ATTR, 1,
[Build shadow with Extended Attributes support])
LIBATTR="-lattr"
with_attr="yes"
fi
else
with_attr="no"
fi
fi
AC_SUBST(LIBAUDIT) AC_SUBST(LIBAUDIT)
if test "$with_audit" != "no"; then if test "$with_audit" != "no"; then
AC_CHECK_HEADER(libaudit.h, [audit_header="yes"], [audit_header="no"]) AC_CHECK_HEADER(libaudit.h, [audit_header="yes"], [audit_header="no"])
@@ -361,28 +450,65 @@ if test "$with_libcrack" = "yes"; then
fi fi
AC_SUBST(LIBSELINUX) AC_SUBST(LIBSELINUX)
AC_SUBST(LIBSEMANAGE)
if test "$with_selinux" != "no"; then if test "$with_selinux" != "no"; then
AC_CHECK_HEADERS(selinux/selinux.h, [selinux_header="yes"], [selinux_header="no"]) AC_CHECK_HEADERS(selinux/selinux.h, [selinux_header="yes"], [selinux_header="no"])
if test "$selinux_header$with_selinux" = "noyes" ; then if test "$selinux_header$with_selinux" = "noyes" ; then
AC_MSG_ERROR([selinux/selinux.h is missing]) AC_MSG_ERROR([selinux/selinux.h is missing])
elif test "$selinux_header" = "yes" ; then fi
AC_CHECK_LIB(selinux, is_selinux_enabled,
[selinux_lib="yes"], [selinux_lib="no"]) AC_CHECK_HEADERS(semanage/semanage.h, [semanage_header="yes"], [semanage_header="no"])
if test "$semanage_header$with_selinux" = "noyes" ; then
AC_MSG_ERROR([semanage/semanage.h is missing])
fi
if test "$selinux_header$semanage_header" = "yesyes" ; then
AC_CHECK_LIB(selinux, is_selinux_enabled, [selinux_lib="yes"], [selinux_lib="no"])
if test "$selinux_lib$with_selinux" = "noyes" ; then if test "$selinux_lib$with_selinux" = "noyes" ; then
AC_MSG_ERROR([libselinux not found]) AC_MSG_ERROR([libselinux not found])
elif test "$selinux_lib" = "no" ; then fi
with_selinux="no"
else AC_CHECK_LIB(semanage, semanage_connect, [semanage_lib="yes"], [semanage_lib="no"])
if test "$semanage_lib$with_selinux" = "noyes" ; then
AC_MSG_ERROR([libsemanage not found])
fi
if test "$selinux_lib$semanage_lib" == "yesyes" ; then
AC_DEFINE(WITH_SELINUX, 1, AC_DEFINE(WITH_SELINUX, 1,
[Build shadow with SELinux support]) [Build shadow with SELinux support])
LIBSELINUX="-lselinux" LIBSELINUX="-lselinux"
LIBSEMANAGE="-lsemanage"
with_selinux="yes" with_selinux="yes"
else
with_selinux="no"
fi fi
else else
with_selinux="no" with_selinux="no"
fi fi
fi fi
AC_SUBST(LIBTCB)
if test "$with_tcb" != "no"; then
AC_CHECK_HEADERS(tcb.h, [tcb_header="yes"], [tcb_header="no"])
if test "$tcb_header$with_tcb" = "noyes" ; then
AC_MSG_ERROR([tcb.h is missing])
elif test "$tcb_header" = "yes" ; then
AC_CHECK_LIB(tcb, tcb_is_suspect, [tcb_lib="yes"], [tcb_lib="no"])
if test "$tcb_lib$with_tcb" = "noyes" ; then
AC_MSG_ERROR([libtcb not found])
elif test "$tcb_lib" = "no" ; then
with_tcb="no"
else
AC_DEFINE(WITH_TCB, 1, [Build shadow with tcb support (incomplete)])
LIBTCB="-ltcb"
with_tcb="yes"
fi
else
with_tcb="no"
fi
fi
AM_CONDITIONAL(WITH_TCB, test x$with_tcb = xyes)
AC_SUBST(LIBPAM) AC_SUBST(LIBPAM)
if test "$with_libpam" != "no"; then if test "$with_libpam" != "no"; then
AC_CHECK_LIB(pam, pam_start, AC_CHECK_LIB(pam, pam_start,
@@ -503,8 +629,9 @@ AC_CONFIG_FILES([
doc/Makefile doc/Makefile
man/Makefile man/Makefile
man/config.xml man/config.xml
man/po/Makefile.in man/po/Makefile
man/cs/Makefile man/cs/Makefile
man/da/Makefile
man/de/Makefile man/de/Makefile
man/es/Makefile man/es/Makefile
man/fi/Makefile man/fi/Makefile
@@ -541,8 +668,12 @@ if test "$with_libpam" = "yes"; then
echo " suid account management tools: $enable_acct_tools_setuid" echo " suid account management tools: $enable_acct_tools_setuid"
fi fi
echo " SELinux support: $with_selinux" echo " SELinux support: $with_selinux"
echo " ACL support: $with_acl"
echo " Extended Attributes support: $with_attr"
echo " tcb support (incomplete): $with_tcb"
echo " shadow group support: $enable_shadowgrp" echo " shadow group support: $enable_shadowgrp"
echo " S/Key support: $with_skey" echo " S/Key support: $with_skey"
echo " SHA passwords encryption: $with_sha_crypt" echo " SHA passwords encryption: $with_sha_crypt"
echo " nscd support: $with_nscd" echo " nscd support: $with_nscd"
echo " subordinate IDs support: $enable_subids"
echo echo
+64 -50
View File
@@ -6,18 +6,18 @@
# #
# Delay in seconds before being allowed another attempt after a login failure # Delay in seconds before being allowed another attempt after a login failure
# Note: When PAM is used, some modules may enfore a minimal delay (e.g. # Note: When PAM is used, some modules may enforce a minimum delay (e.g.
# pam_unix enforces a 2s delay) # pam_unix(8) enforces a 2s delay)
# #
FAIL_DELAY 3 FAIL_DELAY 3
# #
# Enable logging and display of /var/log/faillog login failure info. # Enable logging and display of /var/log/faillog login(1) failure info.
# #
FAILLOG_ENAB yes FAILLOG_ENAB yes
# #
# Enable display of unknown usernames when login failures are recorded. # Enable display of unknown usernames when login(1) failures are recorded.
# #
LOG_UNKFAIL_ENAB no LOG_UNKFAIL_ENAB no
@@ -27,7 +27,7 @@ LOG_UNKFAIL_ENAB no
LOG_OK_LOGINS no LOG_OK_LOGINS no
# #
# Enable logging and display of /var/log/lastlog login time info. # Enable logging and display of /var/log/lastlog login(1) time info.
# #
LASTLOG_ENAB yes LASTLOG_ENAB yes
@@ -50,13 +50,13 @@ OBSCURE_CHECKS_ENAB yes
PORTTIME_CHECKS_ENAB yes PORTTIME_CHECKS_ENAB yes
# #
# Enable setting of ulimit, umask, and niceness from passwd gecos field. # Enable setting of ulimit, umask, and niceness from passwd(5) gecos field.
# #
QUOTAS_ENAB yes QUOTAS_ENAB yes
# #
# Enable "syslog" logging of su activity - in addition to sulog file logging. # Enable "syslog" logging of su(1) activity - in addition to sulog file logging.
# SYSLOG_SG_ENAB does the same for newgrp and sg. # SYSLOG_SG_ENAB does the same for newgrp(1) and sg(1).
# #
SYSLOG_SU_ENAB yes SYSLOG_SU_ENAB yes
SYSLOG_SG_ENAB yes SYSLOG_SG_ENAB yes
@@ -64,13 +64,13 @@ SYSLOG_SG_ENAB yes
# #
# If defined, either full pathname of a file containing device names or # If defined, either full pathname of a file containing device names or
# a ":" delimited list of device names. Root logins will be allowed only # a ":" delimited list of device names. Root logins will be allowed only
# upon these devices. # from these devices.
# #
CONSOLE /etc/securetty CONSOLE /etc/securetty
#CONSOLE console:tty01:tty02:tty03:tty04 #CONSOLE console:tty01:tty02:tty03:tty04
# #
# If defined, all su activity is logged to this file. # If defined, all su(1) activity is logged to this file.
# #
#SULOG_FILE /var/log/sulog #SULOG_FILE /var/log/sulog
@@ -82,33 +82,33 @@ MOTD_FILE /etc/motd
#MOTD_FILE /etc/motd:/usr/lib/news/news-motd #MOTD_FILE /etc/motd:/usr/lib/news/news-motd
# #
# If defined, this file will be output before each login prompt. # If defined, this file will be output before each login(1) prompt.
# #
#ISSUE_FILE /etc/issue #ISSUE_FILE /etc/issue
# #
# If defined, file which maps tty line to TERM environment parameter. # If defined, file which maps tty line to TERM environment parameter.
# Each line of the file is in a format something like "vt100 tty01". # Each line of the file is in a format similar to "vt100 tty01".
# #
#TTYTYPE_FILE /etc/ttytype #TTYTYPE_FILE /etc/ttytype
# #
# If defined, login failures will be logged here in a utmp format. # If defined, login(1) failures will be logged here in a utmp format.
# last, when invoked as lastb, will read /var/log/btmp, so... # last(1), when invoked as lastb(1), will read /var/log/btmp, so...
# #
FTMP_FILE /var/log/btmp FTMP_FILE /var/log/btmp
# #
# If defined, name of file whose presence which will inhibit non-root # If defined, name of file whose presence will inhibit non-root
# logins. The contents of this file should be a message indicating # logins. The content of this file should be a message indicating
# why logins are inhibited. # why logins are inhibited.
# #
NOLOGINS_FILE /etc/nologin NOLOGINS_FILE /etc/nologin
# #
# If defined, the command name to display when running "su -". For # If defined, the command name to display when running "su -". For
# example, if this is defined as "su" then a "ps" will display the # example, if this is defined as "su" then ps(1) will display the
# command is "-su". If not defined, then "ps" would display the # command as "-su". If not defined, then ps(1) will display the
# name of the shell actually being run, e.g. something like "-sh". # name of the shell actually being run, e.g. something like "-sh".
# #
SU_NAME su SU_NAME su
@@ -158,10 +158,10 @@ ENV_PATH PATH=/bin:/usr/bin
# TTYGROUP Login tty will be assigned this group ownership. # TTYGROUP Login tty will be assigned this group ownership.
# TTYPERM Login tty will be set to this permission. # TTYPERM Login tty will be set to this permission.
# #
# If you have a "write" program which is "setgid" to a special group # If you have a write(1) program which is "setgid" to a special group
# which owns the terminals, define TTYGROUP to the group number and # which owns the terminals, define TTYGROUP as the number of such group
# TTYPERM to 0620. Otherwise leave TTYGROUP commented out and assign # and TTYPERM as 0620. Otherwise leave TTYGROUP commented out and
# TTYPERM to either 622 or 600. # set TTYPERM to either 622 or 600.
# #
TTYGROUP tty TTYGROUP tty
TTYPERM 0600 TTYPERM 0600
@@ -183,12 +183,13 @@ ERASECHAR 0177
KILLCHAR 025 KILLCHAR 025
#ULIMIT 2097152 #ULIMIT 2097152
# Default initial "umask" value for non-PAM enabled systems. # Default initial "umask" value used by login(1) on non-PAM enabled systems.
# UMASK is also used by useradd and newusers to set the mode of new home # Default "umask" value for pam_umask(8) on PAM enabled systems.
# directories. # UMASK is also used by useradd(8) and newusers(8) to set the mode for new
# home directories.
# 022 is the default value, but 027, or even 077, could be considered # 022 is the default value, but 027, or even 077, could be considered
# better for privacy. There is no One True Answer here: each sysadmin # for increased privacy. There is no One True Answer here: each sysadmin
# must make up her mind. # must make up his/her mind.
UMASK 022 UMASK 022
# #
@@ -213,35 +214,43 @@ PASS_WARN_AGE 7
SU_WHEEL_ONLY no SU_WHEEL_ONLY no
# #
# If compiled with cracklib support, where are the dictionaries # If compiled with cracklib support, sets the path to the dictionaries
# #
CRACKLIB_DICTPATH /var/cache/cracklib/cracklib_dict CRACKLIB_DICTPATH /var/cache/cracklib/cracklib_dict
# #
# Min/max values for automatic uid selection in useradd # Min/max values for automatic uid selection in useradd(8)
# #
UID_MIN 1000 UID_MIN 1000
UID_MAX 60000 UID_MAX 60000
# System accounts # System accounts
SYS_UID_MIN 101 SYS_UID_MIN 101
SYS_UID_MAX 999 SYS_UID_MAX 999
# Extra per user uids
SUB_UID_MIN 100000
SUB_UID_MAX 600100000
SUB_UID_COUNT 65536
# #
# Min/max values for automatic gid selection in groupadd # Min/max values for automatic gid selection in groupadd(8)
# #
GID_MIN 1000 GID_MIN 1000
GID_MAX 60000 GID_MAX 60000
# System accounts # System accounts
SYS_GID_MIN 101 SYS_GID_MIN 101
SYS_GID_MAX 999 SYS_GID_MAX 999
# Extra per user group ids
SUB_GID_MIN 100000
SUB_GID_MAX 600100000
SUB_GID_COUNT 65536
# #
# Max number of login retries if password is bad # Max number of login(1) retries if password is bad
# #
LOGIN_RETRIES 5 LOGIN_RETRIES 5
# #
# Max time in seconds for login # Max time in seconds for login(1)
# #
LOGIN_TIMEOUT 60 LOGIN_TIMEOUT 60
@@ -263,12 +272,12 @@ PASS_ALWAYS_WARN yes
#PASS_MAX_LEN 8 #PASS_MAX_LEN 8
# #
# Require password before chfn/chsh can make any changes. # Require password before chfn(1)/chsh(1) can make any changes.
# #
CHFN_AUTH yes CHFN_AUTH yes
# #
# Which fields may be changed by regular users using chfn - use # Which fields may be changed by regular users using chfn(1) - use
# any combination of letters "frwh" (full name, room number, work # any combination of letters "frwh" (full name, room number, work
# phone, home phone). If not defined, no changes are allowed. # phone, home phone). If not defined, no changes are allowed.
# For backward compatibility, "yes" = "rwh" and "no" = "frwh". # For backward compatibility, "yes" = "rwh" and "no" = "frwh".
@@ -293,13 +302,13 @@ CHFN_RESTRICT rwh
# Note: If you use PAM, it is recommended to use a value consistent with # Note: If you use PAM, it is recommended to use a value consistent with
# the PAM modules configuration. # the PAM modules configuration.
# #
# This variable is deprecated. You should use ENCRYPT_METHOD. # This variable is deprecated. You should use ENCRYPT_METHOD instead.
# #
#MD5_CRYPT_ENAB no #MD5_CRYPT_ENAB no
# #
# Only works if compiled with ENCRYPTMETHOD_SELECT defined: # Only works if compiled with ENCRYPTMETHOD_SELECT defined:
# If set to MD5 , MD5-based algorithm will be used for encrypting password # If set to MD5, MD5-based algorithm will be used for encrypting password
# If set to SHA256, SHA256-based algorithm will be used for encrypting password # If set to SHA256, SHA256-based algorithm will be used for encrypting password
# If set to SHA512, SHA512-based algorithm will be used for encrypting password # If set to SHA512, SHA512-based algorithm will be used for encrypting password
# If set to DES, DES-based algorithm will be used for encrypting password (default) # If set to DES, DES-based algorithm will be used for encrypting password (default)
@@ -314,12 +323,12 @@ CHFN_RESTRICT rwh
# Only works if ENCRYPT_METHOD is set to SHA256 or SHA512. # Only works if ENCRYPT_METHOD is set to SHA256 or SHA512.
# #
# Define the number of SHA rounds. # Define the number of SHA rounds.
# With a lot of rounds, it is more difficult to brute forcing the password. # With a lot of rounds, it is more difficult to brute-force the password.
# But note also that it more CPU resources will be needed to authenticate # However, more CPU resources will be needed to authenticate users if
# users. # this value is increased.
# #
# If not specified, the libc will choose the default number of rounds (5000). # If not specified, the libc will choose the default number of rounds (5000).
# The values must be inside the 1000-999999999 range. # The values must be within the 1000-999999999 range.
# If only one of the MIN or MAX values is set, then this value will be used. # If only one of the MIN or MAX values is set, then this value will be used.
# If MIN > MAX, the highest value will be used. # If MIN > MAX, the highest value will be used.
# #
@@ -328,18 +337,18 @@ CHFN_RESTRICT rwh
# #
# List of groups to add to the user's supplementary group set # List of groups to add to the user's supplementary group set
# when logging in on the console (as determined by the CONSOLE # when logging in from the console (as determined by the CONSOLE
# setting). Default is none. # setting). Default is none.
# #
# Use with caution - it is possible for users to gain permanent # Use with caution - it is possible for users to gain permanent
# access to these groups, even when not logged in on the console. # access to these groups, even when not logged in from the console.
# How to do it is left as an exercise for the reader... # How to do it is left as an exercise for the reader...
# #
#CONSOLE_GROUPS floppy:audio:cdrom #CONSOLE_GROUPS floppy:audio:cdrom
# #
# Should login be allowed if we can't cd to the home directory? # Should login be allowed if we can't cd to the home directory?
# Default in no. # Default is no.
# #
DEFAULT_HOME yes DEFAULT_HOME yes
@@ -361,14 +370,14 @@ ENVIRON_FILE /etc/environment
# (examples: 022 -> 002, 077 -> 007) for non-root users, if the uid is # (examples: 022 -> 002, 077 -> 007) for non-root users, if the uid is
# the same as gid, and username is the same as the primary group name. # the same as gid, and username is the same as the primary group name.
# #
# This also enables userdel to remove user groups if no members exist. # This also enables userdel(8) to remove user groups if no members exist.
# #
USERGROUPS_ENAB yes USERGROUPS_ENAB yes
# #
# If set to a non-nul number, the shadow utilities will make sure that # If set to a non-zero number, the shadow utilities will make sure that
# groups never have more than this number of users on one line. # groups never have more than this number of users on one line.
# This permit to support split groups (groups split into multiple lines, # This permits to support split groups (groups split into multiple lines,
# with the same group ID, to avoid limitation of the line length in the # with the same group ID, to avoid limitation of the line length in the
# group file). # group file).
# #
@@ -377,10 +386,15 @@ USERGROUPS_ENAB yes
#MAX_MEMBERS_PER_GROUP 0 #MAX_MEMBERS_PER_GROUP 0
# #
# If useradd should create home directories for users by default (non # If useradd(8) should create home directories for users by default (non
# system users only) # system users only).
# This option is overridden with the -M or -m flags on the useradd command # This option is overridden with the -M or -m flags on the useradd(8)
# line. # command-line.
# #
#CREATE_HOME yes #CREATE_HOME yes
#
# Force use shadow, even if shadow passwd & shadow group files are
# missing.
#
#FORCE_SHADOW yes
+10
View File
@@ -14,6 +14,7 @@ libshadow_la_SOURCES = \
encrypt.c \ encrypt.c \
exitcodes.h \ exitcodes.h \
faillog.h \ faillog.h \
fields.c \
fputsx.c \ fputsx.c \
getdef.c \ getdef.c \
getdef.h \ getdef.h \
@@ -38,6 +39,10 @@ libshadow_la_SOURCES = \
pwio.c \ pwio.c \
pwio.h \ pwio.h \
pwmem.c \ pwmem.c \
subordinateio.h \
subordinateio.c \
selinux.c \
semanage.c \
sgetgrent.c \ sgetgrent.c \
sgetpwent.c \ sgetpwent.c \
sgetspent.c \ sgetspent.c \
@@ -47,8 +52,13 @@ libshadow_la_SOURCES = \
shadowio.c \ shadowio.c \
shadowio.h \ shadowio.h \
shadowmem.c \ shadowmem.c \
spawn.c \
utent.c utent.c
if WITH_TCB
libshadow_la_SOURCES += tcbfuncs.c tcbfuncs.h
endif
# These files are unneeded for some reason, listed in # These files are unneeded for some reason, listed in
# order of appearance: # order of appearance:
# #
+213 -84
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1990 - 1994, Julianne Frances Haugh * Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2001, Marek Michałkiewicz * Copyright (c) 1996 - 2001, Marek Michałkiewicz
* Copyright (c) 2001 - 2006, Tomasz Kłoczko * Copyright (c) 2001 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François * Copyright (c) 2007 - 2011, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -45,16 +45,16 @@
#include <stdio.h> #include <stdio.h>
#include <signal.h> #include <signal.h>
#include "nscd.h" #include "nscd.h"
#ifdef WITH_SELINUX #ifdef WITH_TCB
#include <selinux/selinux.h> #include <tcb.h>
#endif #endif /* WITH_TCB */
#include "prototypes.h" #include "prototypes.h"
#include "commonio.h" #include "commonio.h"
/* local function prototypes */ /* local function prototypes */
static int lrename (const char *, const char *); static int lrename (const char *, const char *);
static int check_link_count (const char *file); static int check_link_count (const char *file);
static int do_lock_file (const char *file, const char *lock); static int do_lock_file (const char *file, const char *lock, bool log);
static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms ( static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
const char *name, const char *name,
const char *mode, const char *mode,
@@ -132,7 +132,7 @@ static int check_link_count (const char *file)
} }
static int do_lock_file (const char *file, const char *lock) static int do_lock_file (const char *file, const char *lock, bool log)
{ {
int fd; int fd;
pid_t pid; pid_t pid;
@@ -142,6 +142,11 @@ static int do_lock_file (const char *file, const char *lock)
fd = open (file, O_CREAT | O_EXCL | O_WRONLY, 0600); fd = open (file, O_CREAT | O_EXCL | O_WRONLY, 0600);
if (-1 == fd) { if (-1 == fd) {
if (log) {
(void) fprintf (stderr,
"%s: %s: %s\n",
Prog, file, strerror (errno));
}
return 0; return 0;
} }
@@ -149,6 +154,11 @@ static int do_lock_file (const char *file, const char *lock)
snprintf (buf, sizeof buf, "%lu", (unsigned long) pid); snprintf (buf, sizeof buf, "%lu", (unsigned long) pid);
len = (ssize_t) strlen (buf) + 1; len = (ssize_t) strlen (buf) + 1;
if (write (fd, buf, (size_t) len) != len) { if (write (fd, buf, (size_t) len) != len) {
if (log) {
(void) fprintf (stderr,
"%s: %s: %s\n",
Prog, file, strerror (errno));
}
(void) close (fd); (void) close (fd);
unlink (file); unlink (file);
return 0; return 0;
@@ -157,12 +167,22 @@ static int do_lock_file (const char *file, const char *lock)
if (link (file, lock) == 0) { if (link (file, lock) == 0) {
retval = check_link_count (file); retval = check_link_count (file);
if ((0==retval) && log) {
(void) fprintf (stderr,
"%s: %s: lock file already used\n",
Prog, file);
}
unlink (file); unlink (file);
return retval; return retval;
} }
fd = open (lock, O_RDWR); fd = open (lock, O_RDWR);
if (-1 == fd) { if (-1 == fd) {
if (log) {
(void) fprintf (stderr,
"%s: %s: %s\n",
Prog, lock, strerror (errno));
}
unlink (file); unlink (file);
errno = EINVAL; errno = EINVAL;
return 0; return 0;
@@ -170,29 +190,60 @@ static int do_lock_file (const char *file, const char *lock)
len = read (fd, buf, sizeof (buf) - 1); len = read (fd, buf, sizeof (buf) - 1);
close (fd); close (fd);
if (len <= 0) { if (len <= 0) {
if (log) {
(void) fprintf (stderr,
"%s: existing lock file %s without a PID\n",
Prog, lock);
}
unlink (file); unlink (file);
errno = EINVAL; errno = EINVAL;
return 0; return 0;
} }
buf[len] = '\0'; buf[len] = '\0';
if (get_pid (buf, &pid) == 0) { if (get_pid (buf, &pid) == 0) {
if (log) {
(void) fprintf (stderr,
"%s: existing lock file %s with an invalid PID '%s'\n",
Prog, lock, buf);
}
unlink (file); unlink (file);
errno = EINVAL; errno = EINVAL;
return 0; return 0;
} }
if (kill (pid, 0) == 0) { if (kill (pid, 0) == 0) {
if (log) {
(void) fprintf (stderr,
"%s: lock %s already used by PID %lu\n",
Prog, lock, (unsigned long) pid);
}
unlink (file); unlink (file);
errno = EEXIST; errno = EEXIST;
return 0; return 0;
} }
if (unlink (lock) != 0) { if (unlink (lock) != 0) {
if (log) {
(void) fprintf (stderr,
"%s: cannot get lock %s: %s\n",
Prog, lock, strerror (errno));
}
unlink (file); unlink (file);
return 0; return 0;
} }
retval = 0; retval = 0;
if ((link (file, lock) == 0) && (check_link_count (file) != 0)) { if (link (file, lock) == 0) {
retval = 1; retval = check_link_count (file);
if ((0==retval) && log) {
(void) fprintf (stderr,
"%s: %s: lock file already used\n",
Prog, file);
}
} else {
if (log) {
(void) fprintf (stderr,
"%s: cannot get lock %s: %s\n",
Prog, lock, strerror (errno));
}
} }
unlink (file); unlink (file);
@@ -219,21 +270,21 @@ static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
if (fchown (fileno (fp), sb->st_uid, sb->st_gid) != 0) { if (fchown (fileno (fp), sb->st_uid, sb->st_gid) != 0) {
goto fail; goto fail;
} }
#else #else /* !HAVE_FCHOWN */
if (chown (name, sb->st_mode) != 0) { if (chown (name, sb->st_mode) != 0) {
goto fail; goto fail;
} }
#endif #endif /* !HAVE_FCHOWN */
#ifdef HAVE_FCHMOD #ifdef HAVE_FCHMOD
if (fchmod (fileno (fp), sb->st_mode & 0664) != 0) { if (fchmod (fileno (fp), sb->st_mode & 0664) != 0) {
goto fail; goto fail;
} }
#else #else /* !HAVE_FCHMOD */
if (chmod (name, sb->st_mode & 0664) != 0) { if (chmod (name, sb->st_mode & 0664) != 0) {
goto fail; goto fail;
} }
#endif #endif /* !HAVE_FCHMOD */
return fp; return fp;
fail: fail:
@@ -325,7 +376,7 @@ bool commonio_present (const struct commonio_db *db)
} }
int commonio_lock_nowait (struct commonio_db *db) int commonio_lock_nowait (struct commonio_db *db, bool log)
{ {
char file[1024]; char file[1024];
char lock[1024]; char lock[1024];
@@ -337,7 +388,7 @@ int commonio_lock_nowait (struct commonio_db *db)
snprintf (file, sizeof file, "%s.%lu", snprintf (file, sizeof file, "%s.%lu",
db->filename, (unsigned long) getpid ()); db->filename, (unsigned long) getpid ());
snprintf (lock, sizeof lock, "%s.lock", db->filename); snprintf (lock, sizeof lock, "%s.lock", db->filename);
if (do_lock_file (file, lock) != 0) { if (do_lock_file (file, lock, log) != 0) {
db->locked = true; db->locked = true;
lock_count++; lock_count++;
return 1; return 1;
@@ -361,17 +412,22 @@ int commonio_lock (struct commonio_db *db)
*/ */
if (0 == lock_count) { if (0 == lock_count) {
if (lckpwdf () == -1) { if (lckpwdf () == -1) {
if (geteuid () != 0) {
(void) fprintf (stderr,
"%s: Permission denied.\n",
Prog);
}
return 0; /* failure */ return 0; /* failure */
} }
} }
if (commonio_lock_nowait (db) != 0) { if (commonio_lock_nowait (db, true) != 0) {
return 1; /* success */ return 1; /* success */
} }
ulckpwdf (); ulckpwdf ();
return 0; /* failure */ return 0; /* failure */
#else #else /* !HAVE_LCKPWDF */
int i; int i;
/* /*
@@ -388,16 +444,18 @@ int commonio_lock (struct commonio_db *db)
if (i > 0) { if (i > 0) {
sleep (LOCK_SLEEP); /* delay between retries */ sleep (LOCK_SLEEP); /* delay between retries */
} }
if (commonio_lock_nowait (db) != 0) { if (commonio_lock_nowait (db, i==LOCK_TRIES-1) != 0) {
return 1; /* success */ return 1; /* success */
} }
/* no unnecessary retries on "permission denied" errors */ /* no unnecessary retries on "permission denied" errors */
if (geteuid () != 0) { if (geteuid () != 0) {
(void) fprintf (stderr, "%s: Permission denied.\n",
Prog);
return 0; return 0;
} }
} }
return 0; /* failure */ return 0; /* failure */
#endif #endif /* !HAVE_LCKPWDF */
} }
static void dec_lock_count (void) static void dec_lock_count (void)
@@ -414,7 +472,7 @@ static void dec_lock_count (void)
} }
#ifdef HAVE_LCKPWDF #ifdef HAVE_LCKPWDF
ulckpwdf (); ulckpwdf ();
#endif #endif /* HAVE_LCKPWDF */
} }
} }
} }
@@ -533,6 +591,7 @@ int commonio_open (struct commonio_db *db, int mode)
void *eptr = NULL; void *eptr = NULL;
int flags = mode; int flags = mode;
size_t buflen; size_t buflen;
int fd;
int saved_errno; int saved_errno;
mode &= ~O_CREAT; mode &= ~O_CREAT;
@@ -549,11 +608,31 @@ int commonio_open (struct commonio_db *db, int mode)
return 0; return 0;
} }
db->head = db->tail = NULL; db->head = NULL;
db->tail = NULL;
db->cursor = NULL; db->cursor = NULL;
db->changed = false; db->changed = false;
db->fp = fopen (db->filename, db->readonly ? "r" : "r+"); fd = open (db->filename,
(db->readonly ? O_RDONLY : O_RDWR)
| O_NOCTTY | O_NONBLOCK | O_NOFOLLOW);
saved_errno = errno;
db->fp = NULL;
if (fd >= 0) {
#ifdef WITH_TCB
if (tcb_is_suspect (fd) != 0) {
(void) close (fd);
errno = EINVAL;
return 0;
}
#endif /* WITH_TCB */
db->fp = fdopen (fd, db->readonly ? "r" : "r+");
saved_errno = errno;
if (NULL == db->fp) {
(void) close (fd);
}
}
errno = saved_errno;
/* /*
* If O_CREAT was specified and the file didn't exist, it will be * If O_CREAT was specified and the file didn't exist, it will be
@@ -568,16 +647,7 @@ int commonio_open (struct commonio_db *db, int mode)
} }
/* Do not inherit fd in spawned processes (e.g. nscd) */ /* Do not inherit fd in spawned processes (e.g. nscd) */
fcntl(fileno(db->fp), F_SETFD, FD_CLOEXEC); fcntl (fileno (db->fp), F_SETFD, FD_CLOEXEC);
#ifdef WITH_SELINUX
db->scontext = NULL;
if ((is_selinux_enabled () > 0) && (!db->readonly)) {
if (fgetfilecon (fileno (db->fp), &db->scontext) < 0) {
goto cleanup_errno;
}
}
#endif
buflen = BUFLEN; buflen = BUFLEN;
buf = (char *) malloc (buflen); buf = (char *) malloc (buflen);
@@ -663,12 +733,6 @@ int commonio_open (struct commonio_db *db, int mode)
cleanup_errno: cleanup_errno:
saved_errno = errno; saved_errno = errno;
free_linked_list (db); free_linked_list (db);
#ifdef WITH_SELINUX
if (db->scontext != NULL) {
freecon (db->scontext);
db->scontext = NULL;
}
#endif
fclose (db->fp); fclose (db->fp);
db->fp = NULL; db->fp = NULL;
errno = saved_errno; errno = saved_errno;
@@ -683,10 +747,26 @@ commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
{ {
struct commonio_entry **entries, *ptr; struct commonio_entry **entries, *ptr;
size_t n = 0, i; size_t n = 0, i;
#if KEEP_NIS_AT_END
struct commonio_entry *nis = NULL;
#endif
for (ptr = db->head; NULL != ptr; ptr = ptr->next) { for (ptr = db->head;
(NULL != ptr)
#if KEEP_NIS_AT_END
&& (NULL != ptr->line)
&& ( ('+' != ptr->line[0])
&& ('-' != ptr->line[0]))
#endif
;
ptr = ptr->next) {
n++; n++;
} }
#if KEEP_NIS_AT_END
if ((NULL != ptr) && (NULL != ptr->line)) {
nis = ptr;
}
#endif
if (n <= 1) { if (n <= 1) {
return 0; return 0;
@@ -698,18 +778,40 @@ commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
} }
n = 0; n = 0;
for (ptr = db->head; NULL != ptr; ptr = ptr->next) { for (ptr = db->head;
entries[n++] = ptr; #if KEEP_NIS_AT_END
nis != ptr;
#else
NULL != ptr;
#endif
/*@ -nullderef @*/
ptr = ptr->next
/*@ +nullderef @*/
) {
entries[n] = ptr;
n++;
} }
qsort (entries, n, sizeof (struct commonio_entry *), cmp); qsort (entries, n, sizeof (struct commonio_entry *), cmp);
/* Take care of the head and tail separately */
db->head = entries[0]; db->head = entries[0];
db->tail = entries[--n]; n--;
#if KEEP_NIS_AT_END
if (NULL == nis)
#endif
{
db->tail = entries[n];
}
db->head->prev = NULL; db->head->prev = NULL;
db->head->next = entries[1]; db->head->next = entries[1];
db->tail->prev = entries[n - 1]; entries[n]->prev = entries[n - 1];
db->tail->next = NULL; #if KEEP_NIS_AT_END
entries[n]->next = nis;
#else
entries[n]->next = NULL;
#endif
/* Now other elements have prev and next entries */
for (i = 1; i < n; i++) { for (i = 1; i < n; i++) {
entries[i]->prev = entries[i - 1]; entries[i]->prev = entries[i - 1];
entries[i]->next = entries[i + 1]; entries[i]->next = entries[i + 1];
@@ -724,7 +826,8 @@ commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
/* /*
* Sort entries in db according to order in another. * Sort entries in db according to order in another.
*/ */
int commonio_sort_wrt (struct commonio_db *shadow, struct commonio_db *passwd) int commonio_sort_wrt (struct commonio_db *shadow,
const struct commonio_db *passwd)
{ {
struct commonio_entry *head = NULL, *pw_ptr, *spw_ptr; struct commonio_entry *head = NULL, *pw_ptr, *spw_ptr;
const char *name; const char *name;
@@ -811,10 +914,6 @@ int commonio_close (struct commonio_db *db)
int errors = 0; int errors = 0;
struct stat sb; struct stat sb;
#ifdef WITH_SELINUX
/*@null@*/security_context_t old_context = NULL;
#endif
if (!db->isopen) { if (!db->isopen) {
errno = EINVAL; errno = EINVAL;
return 0; return 0;
@@ -822,7 +921,7 @@ int commonio_close (struct commonio_db *db)
db->isopen = false; db->isopen = false;
if (!db->changed || db->readonly) { if (!db->changed || db->readonly) {
fclose (db->fp); (void) fclose (db->fp);
db->fp = NULL; db->fp = NULL;
goto success; goto success;
} }
@@ -834,27 +933,21 @@ int commonio_close (struct commonio_db *db)
memzero (&sb, sizeof sb); memzero (&sb, sizeof sb);
if (NULL != db->fp) { if (NULL != db->fp) {
if (fstat (fileno (db->fp), &sb) != 0) { if (fstat (fileno (db->fp), &sb) != 0) {
fclose (db->fp); (void) fclose (db->fp);
db->fp = NULL; db->fp = NULL;
goto fail; goto fail;
} }
#ifdef WITH_SELINUX
if (db->scontext != NULL) {
if (getfscreatecon (&old_context) < 0) {
errors++;
goto fail;
}
if (setfscreatecon (db->scontext) < 0) {
errors++;
goto fail;
}
}
#endif
/* /*
* Create backup file. * Create backup file.
*/ */
snprintf (buf, sizeof buf, "%s-", db->filename); snprintf (buf, sizeof buf, "%s-", db->filename);
#ifdef WITH_SELINUX
if (set_selinux_file_context (buf) != 0) {
errors++;
}
#endif
if (create_backup (buf, db->fp) != 0) { if (create_backup (buf, db->fp) != 0) {
errors++; errors++;
} }
@@ -863,6 +956,11 @@ int commonio_close (struct commonio_db *db)
errors++; errors++;
} }
#ifdef WITH_SELINUX
if (reset_selinux_file_context () != 0) {
errors++;
}
#endif
if (errors != 0) { if (errors != 0) {
db->fp = NULL; db->fp = NULL;
goto fail; goto fail;
@@ -870,15 +968,20 @@ int commonio_close (struct commonio_db *db)
} else { } else {
/* /*
* Default permissions for new [g]shadow files. * Default permissions for new [g]shadow files.
* (passwd and group always exist...)
*/ */
sb.st_mode = 0400; sb.st_mode = db->st_mode;
sb.st_uid = 0; sb.st_uid = db->st_uid;
sb.st_gid = 0; sb.st_gid = db->st_gid;
} }
snprintf (buf, sizeof buf, "%s+", db->filename); snprintf (buf, sizeof buf, "%s+", db->filename);
#ifdef WITH_SELINUX
if (set_selinux_file_context (buf) != 0) {
errors++;
}
#endif
db->fp = fopen_set_perms (buf, "w", &sb); db->fp = fopen_set_perms (buf, "w", &sb);
if (NULL == db->fp) { if (NULL == db->fp) {
goto fail; goto fail;
@@ -895,9 +998,9 @@ int commonio_close (struct commonio_db *db)
if (fsync (fileno (db->fp)) != 0) { if (fsync (fileno (db->fp)) != 0) {
errors++; errors++;
} }
#else #else /* !HAVE_FSYNC */
sync (); sync ();
#endif #endif /* !HAVE_FSYNC */
if (fclose (db->fp) != 0) { if (fclose (db->fp) != 0) {
errors++; errors++;
} }
@@ -913,25 +1016,18 @@ int commonio_close (struct commonio_db *db)
goto fail; goto fail;
} }
#ifdef WITH_SELINUX
if (reset_selinux_file_context () != 0) {
goto fail;
}
#endif
nscd_need_reload = true; nscd_need_reload = true;
goto success; goto success;
fail: fail:
errors++; errors++;
success: success:
#ifdef WITH_SELINUX
if (db->scontext != NULL) {
if (NULL != old_context) {
if (setfscreatecon (old_context) < 0) {
errors++;
}
freecon (old_context);
old_context = NULL;
}
freecon (db->scontext);
db->scontext = NULL;
}
#endif
free_linked_list (db); free_linked_list (db);
return errors == 0; return errors == 0;
} }
@@ -962,7 +1058,7 @@ static /*@dependent@*/ /*@null@*/struct commonio_entry *find_entry_by_name (
struct commonio_db *db, struct commonio_db *db,
const char *name) const char *name)
{ {
return next_entry_by_name(db, db->head, name); return next_entry_by_name (db, db->head, name);
} }
@@ -984,6 +1080,7 @@ int commonio_update (struct commonio_db *db, const void *eptr)
if (NULL != p) { if (NULL != p) {
if (next_entry_by_name (db, p->next, db->ops->getname (eptr)) != NULL) { if (next_entry_by_name (db, p->next, db->ops->getname (eptr)) != NULL) {
fprintf (stderr, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), db->ops->getname (eptr), db->filename); fprintf (stderr, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), db->ops->getname (eptr), db->filename);
db->ops->free (nentry);
return 0; return 0;
} }
db->ops->free (p->eptr); db->ops->free (p->eptr);
@@ -1008,14 +1105,46 @@ int commonio_update (struct commonio_db *db, const void *eptr)
#if KEEP_NIS_AT_END #if KEEP_NIS_AT_END
add_one_entry_nis (db, p); add_one_entry_nis (db, p);
#else #else /* !KEEP_NIS_AT_END */
add_one_entry (db, p); add_one_entry (db, p);
#endif #endif /* !KEEP_NIS_AT_END */
db->changed = true; db->changed = true;
return 1; return 1;
} }
#ifdef ENABLE_SUBIDS
int commonio_append (struct commonio_db *db, const void *eptr)
{
struct commonio_entry *p;
void *nentry;
if (!db->isopen || db->readonly) {
errno = EINVAL;
return 0;
}
nentry = db->ops->dup (eptr);
if (NULL == nentry) {
errno = ENOMEM;
return 0;
}
/* new entry */
p = (struct commonio_entry *) malloc (sizeof *p);
if (NULL == p) {
db->ops->free (nentry);
errno = ENOMEM;
return 0;
}
p->eptr = nentry;
p->line = NULL;
p->changed = true;
add_one_entry (db, p);
db->changed = true;
return 1;
}
#endif /* ENABLE_SUBIDS */
void commonio_del_entry (struct commonio_db *db, const struct commonio_entry *p) void commonio_del_entry (struct commonio_db *db, const struct commonio_entry *p)
{ {
+16 -6
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1990 - 1994, Julianne Frances Haugh * Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 - 2005, Tomasz Kłoczko * Copyright (c) 2001 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2008, Nicolas François * Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -123,10 +123,17 @@ struct commonio_db {
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
/*@null@*/security_context_t scontext; /*@null@*/security_context_t scontext;
#endif #endif
/*
* Default permissions and owner for newly created data file.
*/
mode_t st_mode;
uid_t st_uid;
gid_t st_gid;
/* /*
* Head, tail, current position in linked list. * Head, tail, current position in linked list.
*/ */
/*@owned@*/ /*@null@*/struct commonio_entry *head, *tail; /*@owned@*/ /*@null@*/struct commonio_entry *head;
/*@dependent@*/ /*@null@*/struct commonio_entry *tail;
/*@dependent@*/ /*@null@*/struct commonio_entry *cursor; /*@dependent@*/ /*@null@*/struct commonio_entry *cursor;
/* /*
@@ -141,20 +148,23 @@ struct commonio_db {
extern int commonio_setname (struct commonio_db *, const char *); extern int commonio_setname (struct commonio_db *, const char *);
extern bool commonio_present (const struct commonio_db *db); extern bool commonio_present (const struct commonio_db *db);
extern int commonio_lock (struct commonio_db *); extern int commonio_lock (struct commonio_db *);
extern int commonio_lock_nowait (struct commonio_db *); extern int commonio_lock_nowait (struct commonio_db *, bool log);
extern int commonio_open (struct commonio_db *, int); extern int commonio_open (struct commonio_db *, int);
extern /*@observer@*/ /*@null@*/const void *commonio_locate (struct commonio_db *, const char *); extern /*@observer@*/ /*@null@*/const void *commonio_locate (struct commonio_db *, const char *);
extern int commonio_update (struct commonio_db *, const void *); extern int commonio_update (struct commonio_db *, const void *);
#ifdef ENABLE_SUBIDS
extern int commonio_append (struct commonio_db *, const void *);
#endif /* ENABLE_SUBIDS */
extern int commonio_remove (struct commonio_db *, const char *); extern int commonio_remove (struct commonio_db *, const char *);
extern int commonio_rewind (struct commonio_db *); extern int commonio_rewind (struct commonio_db *);
extern /*@observer@*/ /*@null@*/const void *commonio_next (struct commonio_db *); extern /*@observer@*/ /*@null@*/const void *commonio_next (struct commonio_db *);
extern int commonio_close (struct commonio_db *); extern int commonio_close (struct commonio_db *);
extern int commonio_unlock (struct commonio_db *); extern int commonio_unlock (struct commonio_db *);
extern void commonio_del_entry (struct commonio_db *, extern void commonio_del_entry (struct commonio_db *,
const struct commonio_entry *); const struct commonio_entry *);
extern int commonio_sort_wrt (struct commonio_db *shadow, extern int commonio_sort_wrt (struct commonio_db *shadow,
struct commonio_db *passwd); const struct commonio_db *passwd);
extern int commonio_sort (struct commonio_db *db, extern int commonio_sort (struct commonio_db *db,
int (*cmp) (const void *, const void *)); int (*cmp) (const void *, const void *));
#endif #endif
+1 -1
View File
@@ -177,7 +177,7 @@ char *strchr (), *strrchr (), *strtok ();
* --Nekral */ * --Nekral */
#define SYSLOG(x) \ #define SYSLOG(x) \
do { \ do { \
char *old_locale = setlocale(LC_ALL, NULL); \ char *old_locale = setlocale (LC_ALL, NULL); \
char *saved_locale = NULL; \ char *saved_locale = NULL; \
if (NULL != old_locale) { \ if (NULL != old_locale) { \
saved_locale = strdup (old_locale); \ saved_locale = strdup (old_locale); \
+11 -12
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1990 - 1993, Julianne Frances Haugh * Copyright (c) 1990 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2005 , Tomasz Kłoczko * Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2008, Nicolas François * Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -40,27 +40,26 @@
#include "prototypes.h" #include "prototypes.h"
#include "defines.h" #include "defines.h"
char *pw_encrypt (const char *clear, const char *salt) /*@exposed@*//*@null@*/char *pw_encrypt (const char *clear, const char *salt)
{ {
static char cipher[128]; static char cipher[128];
char *cp; char *cp;
cp = crypt (clear, salt); cp = crypt (clear, salt);
if (!cp) { if (NULL == cp) {
/* /*
* Single Unix Spec: crypt() may return a null pointer, * Single Unix Spec: crypt() may return a null pointer,
* and set errno to indicate an error. The caller doesn't * and set errno to indicate an error. In this case return
* expect us to return NULL, so... * the NULL so the caller can handle appropriately.
*/ */
perror ("crypt"); return NULL;
exit (EXIT_FAILURE);
} }
/* The GNU crypt does not return NULL if the algorithm is not /* Some crypt() do not return NULL if the algorithm is not
* supported, and return a DES encrypted password. */ * supported, and return a DES encrypted password. */
if ((NULL != salt) && (salt[0] == '$') && (strlen (cp) <= 13)) if ((NULL != salt) && (salt[0] == '$') && (strlen (cp) <= 13))
{ {
const char *method; /*@observer@*/const char *method;
switch (salt[1]) switch (salt[1])
{ {
case '1': case '1':
@@ -79,9 +78,9 @@ char *pw_encrypt (const char *clear, const char *salt)
method = &nummethod[0]; method = &nummethod[0];
} }
} }
fprintf (stderr, (void) fprintf (stderr,
_("crypt method not supported by libcrypt? (%s)\n"), _("crypt method not supported by libcrypt? (%s)\n"),
method); method);
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
+4
View File
@@ -54,6 +54,10 @@ int valid_field (const char *field, const char *illegal)
const char *cp; const char *cp;
int err = 0; int err = 0;
if (NULL == field) {
return -1;
}
/* For each character of field, search if it appears in the list /* For each character of field, search if it appears in the list
* of illegal characters. */ * of illegal characters. */
for (cp = field; '\0' != *cp; cp++) { for (cp = field; '\0' != *cp; cp++) {
+62 -29
View File
@@ -49,6 +49,32 @@ struct itemdef {
/*@null@*/char *value; /* value given, or NULL if no value */ /*@null@*/char *value; /* value given, or NULL if no value */
}; };
#define PAMDEFS \
{"CHFN_AUTH", NULL}, \
{"CHSH_AUTH", NULL}, \
{"CRACKLIB_DICTPATH", NULL}, \
{"ENV_HZ", NULL}, \
{"ENVIRON_FILE", NULL}, \
{"ENV_TZ", NULL}, \
{"FAILLOG_ENAB", NULL}, \
{"FTMP_FILE", NULL}, \
{"ISSUE_FILE", NULL}, \
{"LASTLOG_ENAB", NULL}, \
{"LOGIN_STRING", NULL}, \
{"MAIL_CHECK_ENAB", NULL}, \
{"MOTD_FILE", NULL}, \
{"NOLOGINS_FILE", NULL}, \
{"OBSCURE_CHECKS_ENAB", NULL}, \
{"PASS_ALWAYS_WARN", NULL}, \
{"PASS_CHANGE_TRIES", NULL}, \
{"PASS_MAX_LEN", NULL}, \
{"PASS_MIN_LEN", NULL}, \
{"PORTTIME_CHECKS_ENAB", NULL}, \
{"QUOTAS_ENAB", NULL}, \
{"SU_WHEEL_ONLY", NULL}, \
{"ULIMIT", NULL},
#define NUMDEFS (sizeof(def_table)/sizeof(def_table[0])) #define NUMDEFS (sizeof(def_table)/sizeof(def_table[0]))
static struct itemdef def_table[] = { static struct itemdef def_table[] = {
{"CHFN_RESTRICT", NULL}, {"CHFN_RESTRICT", NULL},
@@ -81,6 +107,12 @@ static struct itemdef def_table[] = {
{"SHA_CRYPT_MAX_ROUNDS", NULL}, {"SHA_CRYPT_MAX_ROUNDS", NULL},
{"SHA_CRYPT_MIN_ROUNDS", NULL}, {"SHA_CRYPT_MIN_ROUNDS", NULL},
#endif #endif
{"SUB_GID_COUNT", NULL},
{"SUB_GID_MAX", NULL},
{"SUB_GID_MIN", NULL},
{"SUB_UID_COUNT", NULL},
{"SUB_UID_MAX", NULL},
{"SUB_UID_MIN", NULL},
{"SULOG_FILE", NULL}, {"SULOG_FILE", NULL},
{"SU_NAME", NULL}, {"SU_NAME", NULL},
{"SYS_GID_MAX", NULL}, {"SYS_GID_MAX", NULL},
@@ -96,37 +128,28 @@ static struct itemdef def_table[] = {
{"USERDEL_CMD", NULL}, {"USERDEL_CMD", NULL},
{"USERGROUPS_ENAB", NULL}, {"USERGROUPS_ENAB", NULL},
#ifndef USE_PAM #ifndef USE_PAM
{"CHFN_AUTH", NULL}, PAMDEFS
{"CHSH_AUTH", NULL},
{"CRACKLIB_DICTPATH", NULL},
{"ENV_HZ", NULL},
{"ENVIRON_FILE", NULL},
{"ENV_TZ", NULL},
{"FAILLOG_ENAB", NULL},
{"FTMP_FILE", NULL},
{"ISSUE_FILE", NULL},
{"LASTLOG_ENAB", NULL},
{"LOGIN_STRING", NULL},
{"MAIL_CHECK_ENAB", NULL},
{"MOTD_FILE", NULL},
{"NOLOGINS_FILE", NULL},
{"OBSCURE_CHECKS_ENAB", NULL},
{"PASS_ALWAYS_WARN", NULL},
{"PASS_CHANGE_TRIES", NULL},
{"PASS_MAX_LEN", NULL},
{"PASS_MIN_LEN", NULL},
{"PORTTIME_CHECKS_ENAB", NULL},
{"QUOTAS_ENAB", NULL},
{"SU_WHEEL_ONLY", NULL},
{"ULIMIT", NULL},
#endif #endif
#ifdef USE_SYSLOG #ifdef USE_SYSLOG
{"SYSLOG_SG_ENAB", NULL}, {"SYSLOG_SG_ENAB", NULL},
{"SYSLOG_SU_ENAB", NULL}, {"SYSLOG_SU_ENAB", NULL},
#endif #endif
#ifdef WITH_TCB
{"TCB_AUTH_GROUP", NULL},
{"TCB_SYMLINKS", NULL},
{"USE_TCB", NULL},
#endif
{"FORCE_SHADOW", NULL},
{NULL, NULL} {NULL, NULL}
}; };
#define NUMKNOWNDEFS (sizeof(knowndef_table)/sizeof(knowndef_table[0]))
static struct itemdef knowndef_table[] = {
#ifdef USE_PAM
PAMDEFS
#endif
};
#ifndef LOGINDEFS #ifndef LOGINDEFS
#define LOGINDEFS "/etc/login.defs" #define LOGINDEFS "/etc/login.defs"
#endif #endif
@@ -386,10 +409,17 @@ static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name)
* Item was never found. * Item was never found.
*/ */
for (ptr = knowndef_table; NULL != ptr->name; ptr++) {
if (strcmp (ptr->name, name) == 0) {
goto out;
}
}
fprintf (stderr, fprintf (stderr,
_("configuration error - unknown item '%s' (notify administrator)\n"), _("configuration error - unknown item '%s' (notify administrator)\n"),
name); name);
SYSLOG ((LOG_CRIT, "unknown configuration item `%s'", name)); SYSLOG ((LOG_CRIT, "unknown configuration item `%s'", name));
out:
return (struct itemdef *) NULL; return (struct itemdef *) NULL;
} }
@@ -405,23 +435,26 @@ static void def_load (void)
FILE *fp; FILE *fp;
char buf[1024], *name, *value, *s; char buf[1024], *name, *value, *s;
/*
* Set the initialized flag.
* (do it early to prevent recursion in putdef_str())
*/
def_loaded = true;
/* /*
* Open the configuration definitions file. * Open the configuration definitions file.
*/ */
fp = fopen (def_fname, "r"); fp = fopen (def_fname, "r");
if (NULL == fp) { if (NULL == fp) {
if (errno == ENOENT)
return;
int err = errno; int err = errno;
SYSLOG ((LOG_CRIT, "cannot open login definitions %s [%s]", SYSLOG ((LOG_CRIT, "cannot open login definitions %s [%s]",
def_fname, strerror (err))); def_fname, strerror (err)));
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
/*
* Set the initialized flag.
* (do it early to prevent recursion in putdef_str())
*/
def_loaded = true;
/* /*
* Go through all of the lines in the file. * Go through all of the lines in the file.
*/ */
+48 -8
View File
@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal * Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2005 , Tomasz Kłoczko * Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François * Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -80,6 +80,23 @@ static int group_put (const void *ent, FILE * file)
{ {
const struct group *gr = ent; const struct group *gr = ent;
if ( (NULL == gr)
|| (valid_field (gr->gr_name, ":\n") == -1)
|| (valid_field (gr->gr_passwd, ":\n") == -1)
|| (gr->gr_gid == (gid_t)-1)) {
return -1;
}
/* FIXME: fail also if gr->gr_mem == NULL ?*/
if (NULL != gr->gr_mem) {
size_t i;
for (i = 0; NULL != gr->gr_mem[i]; i++) {
if (valid_field (gr->gr_mem[i], ",:\n") == -1) {
return -1;
}
}
}
return (putgrent (gr, file) == -1) ? -1 : 0; return (putgrent (gr, file) == -1) ? -1 : 0;
} }
@@ -113,6 +130,9 @@ static /*@owned@*/struct commonio_db group_db = {
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
NULL, /* scontext */ NULL, /* scontext */
#endif #endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */ NULL, /* head */
NULL, /* tail */ NULL, /* tail */
NULL, /* cursor */ NULL, /* cursor */
@@ -313,7 +333,7 @@ static /*@null@*/struct commonio_entry *merge_group_entries (
/* Concatenate the 2 lines */ /* Concatenate the 2 lines */
new_line_len = strlen (gr1->line) + strlen (gr2->line) +1; new_line_len = strlen (gr1->line) + strlen (gr2->line) +1;
new_line = (char *)malloc ((new_line_len + 1) * sizeof(char*)); new_line = (char *)malloc (new_line_len + 1);
if (NULL == new_line) { if (NULL == new_line) {
errno = ENOMEM; errno = ENOMEM;
return NULL; return NULL;
@@ -336,7 +356,7 @@ static /*@null@*/struct commonio_entry *merge_group_entries (
members++; members++;
} }
} }
new_members = (char **)malloc ( (members+1) * sizeof(char*) ); new_members = (char **)calloc ( (members+1), sizeof(char*) );
if (NULL == new_members) { if (NULL == new_members) {
free (new_line); free (new_line);
errno = ENOMEM; errno = ENOMEM;
@@ -345,6 +365,8 @@ static /*@null@*/struct commonio_entry *merge_group_entries (
for (i=0; NULL != gptr1->gr_mem[i]; i++) { for (i=0; NULL != gptr1->gr_mem[i]; i++) {
new_members[i] = gptr1->gr_mem[i]; new_members[i] = gptr1->gr_mem[i];
} }
/* NULL termination enforced by above calloc */
members = i; members = i;
for (i=0; NULL != gptr2->gr_mem[i]; i++) { for (i=0; NULL != gptr2->gr_mem[i]; i++) {
char **pmember = new_members; char **pmember = new_members;
@@ -382,15 +404,19 @@ static int split_groups (unsigned int max_members)
struct commonio_entry *new; struct commonio_entry *new;
struct group *new_gptr; struct group *new_gptr;
unsigned int members = 0; unsigned int members = 0;
unsigned int i;
/* Check if this group must be split */ /* Check if this group must be split */
if (!gr->changed) if (!gr->changed) {
continue; continue;
if (NULL == gptr) }
if (NULL == gptr) {
continue; continue;
}
for (members = 0; NULL != gptr->gr_mem[members]; members++); for (members = 0; NULL != gptr->gr_mem[members]; members++);
if (members <= max_members) if (members <= max_members) {
continue; continue;
}
new = (struct commonio_entry *) malloc (sizeof *new); new = (struct commonio_entry *) malloc (sizeof *new);
if (NULL == new) { if (NULL == new) {
@@ -408,9 +434,23 @@ static int split_groups (unsigned int max_members)
new->changed = true; new->changed = true;
/* Enforce the maximum number of members on gptr */ /* Enforce the maximum number of members on gptr */
gptr->gr_mem[max_members] = NULL; for (i = max_members; NULL != gptr->gr_mem[i]; i++) {
free (gptr->gr_mem[i]);
gptr->gr_mem[i] = NULL;
}
/* Shift all the members */
/* The number of members in new_gptr will be check later */ /* The number of members in new_gptr will be check later */
new_gptr->gr_mem = &new_gptr->gr_mem[max_members]; for (i = 0; NULL != new_gptr->gr_mem[i + max_members]; i++) {
if (NULL != new_gptr->gr_mem[i]) {
free (new_gptr->gr_mem[i]);
}
new_gptr->gr_mem[i] = new_gptr->gr_mem[i + max_members];
new_gptr->gr_mem[i + max_members] = NULL;
}
for (; NULL != new_gptr->gr_mem[i]; i++) {
free (new_gptr->gr_mem[i]);
new_gptr->gr_mem[i] = NULL;
}
/* insert the new entry in the list */ /* insert the new entry in the list */
new->prev = gr; new->prev = gr;
+24 -7
View File
@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal * Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2005 , Tomasz Kłoczko * Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François * Copyright (c) 2007 - 2013, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -48,25 +48,37 @@
if (NULL == gr) { if (NULL == gr) {
return NULL; return NULL;
} }
*gr = *grent; /* The libc might define other fields. They won't be copied. */
memset (gr, 0, sizeof *gr);
gr->gr_gid = grent->gr_gid;
/*@-mustfreeonly@*/
gr->gr_name = strdup (grent->gr_name); gr->gr_name = strdup (grent->gr_name);
/*@=mustfreeonly@*/
if (NULL == gr->gr_name) { if (NULL == gr->gr_name) {
gr_free(gr);
return NULL; return NULL;
} }
/*@-mustfreeonly@*/
gr->gr_passwd = strdup (grent->gr_passwd); gr->gr_passwd = strdup (grent->gr_passwd);
/*@=mustfreeonly@*/
if (NULL == gr->gr_passwd) { if (NULL == gr->gr_passwd) {
gr_free(gr);
return NULL; return NULL;
} }
for (i = 0; grent->gr_mem[i]; i++); for (i = 0; grent->gr_mem[i]; i++);
/*@-mustfreeonly@*/
gr->gr_mem = (char **) malloc ((i + 1) * sizeof (char *)); gr->gr_mem = (char **) malloc ((i + 1) * sizeof (char *));
/*@=mustfreeonly@*/
if (NULL == gr->gr_mem) { if (NULL == gr->gr_mem) {
gr_free(gr);
return NULL; return NULL;
} }
for (i = 0; grent->gr_mem[i]; i++) { for (i = 0; grent->gr_mem[i]; i++) {
gr->gr_mem[i] = strdup (grent->gr_mem[i]); gr->gr_mem[i] = strdup (grent->gr_mem[i]);
if (NULL == gr->gr_mem[i]) { if (NULL == gr->gr_mem[i]) {
gr_free(gr);
return NULL; return NULL;
} }
} }
@@ -78,11 +90,16 @@
void gr_free (/*@out@*/ /*@only@*/struct group *grent) void gr_free (/*@out@*/ /*@only@*/struct group *grent)
{ {
free (grent->gr_name); free (grent->gr_name);
memzero (grent->gr_passwd, strlen (grent->gr_passwd)); if (NULL != grent->gr_passwd) {
free (grent->gr_passwd); memzero (grent->gr_passwd, strlen (grent->gr_passwd));
while (*(grent->gr_mem)) { free (grent->gr_passwd);
free (*(grent->gr_mem)); }
grent->gr_mem++; if (NULL != grent->gr_mem) {
size_t i;
for (i = 0; NULL != grent->gr_mem[i]; i++) {
free (grent->gr_mem[i]);
}
free (grent->gr_mem);
} }
free (grent); free (grent);
} }
+3 -3
View File
@@ -216,13 +216,13 @@ void endsgent (void)
static char *buf = NULL; static char *buf = NULL;
char *cp; char *cp;
struct sgrp *ret;
if (0 == buflen) { if (0 == buflen) {
buf = (char *) malloc (BUFSIZ); buf = (char *) malloc (BUFSIZ);
if (NULL == buf) { if (NULL == buf) {
return NULL; return NULL;
} }
buflen = BUFSIZ;
} }
if (NULL == fp) { if (NULL == fp) {
@@ -230,9 +230,9 @@ void endsgent (void)
} }
#ifdef USE_NIS #ifdef USE_NIS
while (fgetsx (buf, (int) sizeof buf, fp) == buf) while (fgetsx (buf, (int) buflen, fp) == buf)
#else #else
if (fgetsx (buf, (int) sizeof buf, fp) == buf) if (fgetsx (buf, (int) buflen, fp) == buf)
#endif #endif
{ {
while ( ((cp = strrchr (buf, '\n')) == NULL) while ( ((cp = strrchr (buf, '\n')) == NULL)
+1 -1
View File
@@ -43,7 +43,7 @@
struct sgrp { struct sgrp {
char *sg_name; /* group name */ char *sg_name; /* group name */
char *sg_passwd; /* group password */ char *sg_passwd; /* group password */
char **sg_adm; /* group administator list */ char **sg_adm; /* group administrator list */
char **sg_mem; /* group membership list */ char **sg_mem; /* group membership list */
}; };
+26 -34
View File
@@ -3,57 +3,49 @@
#include <config.h> #include <config.h>
#ifdef USE_NSCD #ifdef USE_NSCD
/* because of TEMP_FAILURE_RETRY */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <features.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <spawn.h>
#include <errno.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/types.h> #include <sys/types.h>
#include "exitcodes.h"
#include "defines.h" #include "defines.h"
#include "prototypes.h"
#include "nscd.h" #include "nscd.h"
#define MSG_NSCD_FLUSH_CACHE_FAILED "Failed to flush the nscd cache.\n" #define MSG_NSCD_FLUSH_CACHE_FAILED "%s: Failed to flush the nscd cache.\n"
/* /*
* nscd_flush_cache - flush specified service buffer in nscd cache * nscd_flush_cache - flush specified service buffer in nscd cache
*/ */
int nscd_flush_cache (const char *service) int nscd_flush_cache (const char *service)
{ {
pid_t pid, termpid; int status, code;
int err, status; const char *cmd = "/usr/sbin/nscd";
char *spawnedArgs[] = {"/usr/sbin/nscd", "nscd", "-i", service, NULL}; const char *spawnedArgs[] = {"nscd", "-i", service, NULL};
char *spawnedEnv[] = {NULL}; const char *spawnedEnv[] = {NULL};
/* spawn process */ if (run_command (cmd, spawnedArgs, spawnedEnv, &status) != 0) {
err = posix_spawn (&pid, spawnedArgs[0], NULL, NULL, /* run_command writes its own more detailed message. */
spawnedArgs, spawnedEnv); (void) fprintf (stderr, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog);
if(0 != err)
{
(void) fputs (_(MSG_NSCD_FLUSH_CACHE_FAILED), stderr);
(void) fprintf (stderr, "posix_spawn() error=%d\n", err);
return -1; return -1;
} }
/* Wait for the spawned process to exit */ code = WEXITSTATUS (status);
termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); if (!WIFEXITED (status)) {
if (-1 == termpid) (void) fprintf (stderr,
{ _("%s: nscd did not terminate normally (signal %d)\n"),
(void) fputs (_(MSG_NSCD_FLUSH_CACHE_FAILED), stderr); Prog, WTERMSIG (status));
perror("waitpid");
return -1; return -1;
} } else if (code == E_CMD_NOTFOUND) {
else if (termpid != pid) /* nscd is not installed, or it is installed but uses an
{ interpreter that is missing. Probably the former. */
(void) fputs (_(MSG_NSCD_FLUSH_CACHE_FAILED), stderr); return 0;
(void) fprintf (stderr, "waitpid returned %ld != %ld\n", } else if (code == 1) {
(long int) termpid, (long int) pid); /* nscd is installed, but it isn't active. */
return 0;
} else if (code != 0) {
(void) fprintf (stderr, _("%s: nscd exited with status %d\n"),
Prog, code);
(void) fprintf (stderr, _(MSG_NSCD_FLUSH_CACHE_FAILED), Prog);
return -1; return -1;
} }
+59 -28
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1990 - 1994, Julianne Frances Haugh * Copyright (c) 1990 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko * Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François * Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -42,6 +42,8 @@
#ifndef _PROTOTYPES_H #ifndef _PROTOTYPES_H
#define _PROTOTYPES_H #define _PROTOTYPES_H
#include <config.h>
#include <sys/stat.h> #include <sys/stat.h>
#ifdef USE_UTMPX #ifdef USE_UTMPX
#include <utmpx.h> #include <utmpx.h>
@@ -57,7 +59,7 @@
#include "defines.h" #include "defines.h"
#include "commonio.h" #include "commonio.h"
extern char *Prog; extern /*@observer@*/ const char *Prog;
/* addgrps.c */ /* addgrps.c */
#if defined (HAVE_SETGROUPS) && ! defined (USE_PAM) #if defined (HAVE_SETGROUPS) && ! defined (USE_PAM)
@@ -72,25 +74,27 @@ extern int isexpired (const struct passwd *, /*@null@*/const struct spwd *);
/* basename() renamed to Basename() to avoid libc name space confusion */ /* basename() renamed to Basename() to avoid libc name space confusion */
/* basename.c */ /* basename.c */
extern char *Basename (char *str); extern /*@observer@*/const char *Basename (const char *str);
/* chowndir.c */ /* chowndir.c */
extern int chown_tree (const char *, uid_t, uid_t, gid_t, gid_t); extern int chown_tree (const char *root,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
/* chowntty.c */ /* chowntty.c */
extern void chown_tty (const struct passwd *); extern void chown_tty (const struct passwd *);
/* cleanup.c */ /* cleanup.c */
typedef void (*cleanup_function) (/*@null@*/void *arg); typedef /*@null@*/void (*cleanup_function) (/*@null@*/void *arg);
void add_cleanup (cleanup_function pcf, /*@null@*/void *arg); void add_cleanup (/*@notnull@*/cleanup_function pcf, /*@null@*/void *arg);
void del_cleanup (cleanup_function pcf); void del_cleanup (/*@notnull@*/cleanup_function pcf);
void do_cleanups (void); void do_cleanups (void);
/* cleanup_group.c */ /* cleanup_group.c */
struct cleanup_info_mod { struct cleanup_info_mod {
char *audit_msg; char *audit_msg;
char *action; char *action;
char *name; /*@observer@*/const char *name;
}; };
void cleanup_report_add_group (void *group_name); void cleanup_report_add_group (void *group_name);
void cleanup_report_add_group_group (void *group_name); void cleanup_report_add_group_group (void *group_name);
@@ -116,15 +120,13 @@ extern bool console (const char *);
/* copydir.c */ /* copydir.c */
extern int copy_tree (const char *src_root, const char *dst_root, extern int copy_tree (const char *src_root, const char *dst_root,
long int uid, long int gid); bool copy_root,
extern int remove_tree (const char *root); bool reset_selinux,
uid_t old_uid, uid_t new_uid,
#ifdef WITH_SELINUX gid_t old_gid, gid_t new_gid);
extern int selinux_file_context (const char *dst_name);
#endif
/* encrypt.c */ /* encrypt.c */
extern char *pw_encrypt (const char *, const char *); extern /*@exposed@*//*@null@*/char *pw_encrypt (const char *, const char *);
/* entry.c */ /* entry.c */
extern void pw_entry (const char *, struct passwd *); extern void pw_entry (const char *, struct passwd *);
@@ -149,11 +151,22 @@ extern int find_new_uid (bool sys_user,
uid_t *uid, uid_t *uid,
/*@null@*/uid_t const *preferred_uid); /*@null@*/uid_t const *preferred_uid);
#ifdef ENABLE_SUBIDS
/* find_new_sub_gids.c */
extern int find_new_sub_gids (const char *owner,
gid_t *range_start, unsigned long *range_count);
/* find_new_sub_uids.c */
extern int find_new_sub_uids (const char *owner,
uid_t *range_start, unsigned long *range_count);
#endif /* ENABLE_SUBIDS */
/* get_gid.c */ /* get_gid.c */
extern int get_gid (const char *gidstr, gid_t *gid); extern int get_gid (const char *gidstr, gid_t *gid);
/* getgr_nam_gid.c */ /* getgr_nam_gid.c */
extern /*@null@*/struct group *getgr_nam_gid (const char *grname); extern /*@only@*//*@null@*/struct group *getgr_nam_gid (/*@null@*/const char *grname);
/* getlong.c */ /* getlong.c */
extern int getlong (const char *numstr, /*@out@*/long int *result); extern int getlong (const char *numstr, /*@out@*/long int *result);
@@ -236,7 +249,7 @@ extern void mailcheck (void);
extern void motd (void); extern void motd (void);
/* myname.c */ /* myname.c */
extern /*@null@*/struct passwd *get_my_pwent (void); extern /*@null@*//*@only@*/struct passwd *get_my_pwent (void);
/* pam_pass_non_interractive.c */ /* pam_pass_non_interractive.c */
#ifdef USE_PAM #ifdef USE_PAM
@@ -247,7 +260,7 @@ extern int do_pam_passwd_non_interractive (const char *pam_service,
/* obscure.c */ /* obscure.c */
#ifndef USE_PAM #ifndef USE_PAM
extern int obscure (const char *, const char *, const struct passwd *); extern bool obscure (const char *, const char *, const struct passwd *);
#endif #endif
/* pam_pass.c */ /* pam_pass.c */
@@ -280,12 +293,30 @@ extern /*@dependent@*/ /*@null@*/struct commonio_entry *__pw_get_head (void);
extern /*@null@*/ /*@only@*/struct passwd *__pw_dup (const struct passwd *pwent); extern /*@null@*/ /*@only@*/struct passwd *__pw_dup (const struct passwd *pwent);
extern void pw_free (/*@out@*/ /*@only@*/struct passwd *pwent); extern void pw_free (/*@out@*/ /*@only@*/struct passwd *pwent);
/* remove_tree.c */
extern int remove_tree (const char *root, bool remove_root);
/* rlogin.c */ /* rlogin.c */
extern int do_rlogin (const char *remote_host, char *name, size_t namelen, extern int do_rlogin (const char *remote_host, char *name, size_t namelen,
char *term, size_t termlen); char *term, size_t termlen);
/* root_flag.c */
extern void process_root_flag (const char* short_opt, int argc, char **argv);
/* salt.c */ /* salt.c */
extern /*@observer@*/const char *crypt_make_salt (/*@null@*/const char *meth, /*@null@*/void *arg); extern /*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const char *meth, /*@null@*/void *arg);
/* selinux.c */
#ifdef WITH_SELINUX
extern int set_selinux_file_context (const char *dst_name);
extern int reset_selinux_file_context (void);
#endif
/* semanage.c */
#ifdef WITH_SELINUX
extern int set_seuser(const char *login_name, const char *seuser_name);
extern int del_seuser(const char *login_name);
#endif
/* setugid.c */ /* setugid.c */
extern int setup_groups (const struct passwd *info); extern int setup_groups (const struct passwd *info);
@@ -331,17 +362,17 @@ extern void spw_free (/*@out@*/ /*@only@*/struct spwd *spent);
/* shell.c */ /* shell.c */
extern int shell (const char *file, /*@null@*/const char *arg, char *const envp[]); extern int shell (const char *file, /*@null@*/const char *arg, char *const envp[]);
/* system.c */ /* spawn.c */
extern int safe_system (const char *command, extern int run_command (const char *cmd, const char *argv[],
const char *argv[], /*@null@*/const char *envp[], /*@out@*/int *status);
const char *env[],
int ignore_stderr);
/* strtoday.c */ /* strtoday.c */
extern long strtoday (const char *); extern long strtoday (const char *);
/* suauth.c */ /* suauth.c */
extern int check_su_auth (const char *actual_id, const char *wanted_id); extern int check_su_auth (const char *actual_id,
const char *wanted_id,
bool su_to_root);
/* sulog.c */ /* sulog.c */
extern void sulog (const char *tty, extern void sulog (const char *tty,
@@ -357,7 +388,7 @@ extern void ttytype (const char *);
/* tz.c */ /* tz.c */
#ifndef USE_PAM #ifndef USE_PAM
extern char *tz (const char *); extern /*@observer@*/const char *tz (const char *);
#endif #endif
/* ulimit.c */ /* ulimit.c */
@@ -385,9 +416,9 @@ extern int setutmpx (struct utmpx *utx);
extern bool valid (const char *, const struct passwd *); extern bool valid (const char *, const struct passwd *);
/* xmalloc.c */ /* xmalloc.c */
extern /*@maynotreturn@*/ /*@out@*//*@only@*/char *xmalloc (size_t size) extern /*@maynotreturn@*/ /*@only@*//*@out@*//*@notnull@*/char *xmalloc (size_t size)
/*@ensures MaxSet(result) == (size - 1); @*/; /*@ensures MaxSet(result) == (size - 1); @*/;
extern /*@maynotreturn@*/ /*@only@*/char *xstrdup (const char *); extern /*@maynotreturn@*/ /*@only@*//*@notnull@*/char *xstrdup (const char *);
/* xgetpwnam.c */ /* xgetpwnam.c */
extern /*@null@*/ /*@only@*/struct passwd *xgetpwnam (const char *); extern /*@null@*/ /*@only@*/struct passwd *xgetpwnam (const char *);
+7 -1
View File
@@ -73,6 +73,7 @@ int pw_auth (const char *cipher,
char prompt[1024]; char prompt[1024];
char *clear = NULL; char *clear = NULL;
const char *cp; const char *cp;
const char *encrypted;
int retval; int retval;
#ifdef SKEY #ifdef SKEY
@@ -177,7 +178,12 @@ int pw_auth (const char *cipher,
* the results there as well. * the results there as well.
*/ */
retval = strcmp (pw_encrypt (input, cipher), cipher); encrypted = pw_encrypt (input, cipher);
if (NULL != encrypted) {
retval = strcmp (encrypted, cipher);
} else {
retval = -1;
}
#ifdef SKEY #ifdef SKEY
/* /*
+14
View File
@@ -72,6 +72,17 @@ static int passwd_put (const void *ent, FILE * file)
{ {
const struct passwd *pw = ent; const struct passwd *pw = ent;
if ( (NULL == pw)
|| (valid_field (pw->pw_name, ":\n") == -1)
|| (valid_field (pw->pw_passwd, ":\n") == -1)
|| (pw->pw_uid == (uid_t)-1)
|| (pw->pw_gid == (gid_t)-1)
|| (valid_field (pw->pw_gecos, ":\n") == -1)
|| (valid_field (pw->pw_dir, ":\n") == -1)
|| (valid_field (pw->pw_shell, ":\n") == -1)) {
return -1;
}
return (putpwent (pw, file) == -1) ? -1 : 0; return (putpwent (pw, file) == -1) ? -1 : 0;
} }
@@ -94,6 +105,9 @@ static struct commonio_db passwd_db = {
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
NULL, /* scontext */ NULL, /* scontext */
#endif #endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */ NULL, /* head */
NULL, /* tail */ NULL, /* tail */
NULL, /* cursor */ NULL, /* cursor */
+24 -4
View File
@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal * Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François * Copyright (c) 2007 - 2013, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -48,25 +48,43 @@
if (NULL == pw) { if (NULL == pw) {
return NULL; return NULL;
} }
*pw = *pwent; /* The libc might define other fields. They won't be copied. */
memset (pw, 0, sizeof *pw);
pw->pw_uid = pwent->pw_uid;
pw->pw_gid = pwent->pw_gid;
/*@-mustfreeonly@*/
pw->pw_name = strdup (pwent->pw_name); pw->pw_name = strdup (pwent->pw_name);
/*@=mustfreeonly@*/
if (NULL == pw->pw_name) { if (NULL == pw->pw_name) {
pw_free(pw);
return NULL; return NULL;
} }
/*@-mustfreeonly@*/
pw->pw_passwd = strdup (pwent->pw_passwd); pw->pw_passwd = strdup (pwent->pw_passwd);
/*@=mustfreeonly@*/
if (NULL == pw->pw_passwd) { if (NULL == pw->pw_passwd) {
pw_free(pw);
return NULL; return NULL;
} }
/*@-mustfreeonly@*/
pw->pw_gecos = strdup (pwent->pw_gecos); pw->pw_gecos = strdup (pwent->pw_gecos);
/*@=mustfreeonly@*/
if (NULL == pw->pw_gecos) { if (NULL == pw->pw_gecos) {
pw_free(pw);
return NULL; return NULL;
} }
/*@-mustfreeonly@*/
pw->pw_dir = strdup (pwent->pw_dir); pw->pw_dir = strdup (pwent->pw_dir);
/*@=mustfreeonly@*/
if (NULL == pw->pw_dir) { if (NULL == pw->pw_dir) {
pw_free(pw);
return NULL; return NULL;
} }
/*@-mustfreeonly@*/
pw->pw_shell = strdup (pwent->pw_shell); pw->pw_shell = strdup (pwent->pw_shell);
/*@=mustfreeonly@*/
if (NULL == pw->pw_shell) { if (NULL == pw->pw_shell) {
pw_free(pw);
return NULL; return NULL;
} }
@@ -76,8 +94,10 @@
void pw_free (/*@out@*/ /*@only@*/struct passwd *pwent) void pw_free (/*@out@*/ /*@only@*/struct passwd *pwent)
{ {
free (pwent->pw_name); free (pwent->pw_name);
memzero (pwent->pw_passwd, strlen (pwent->pw_passwd)); if (pwent->pw_passwd) {
free (pwent->pw_passwd); memzero (pwent->pw_passwd, strlen (pwent->pw_passwd));
free (pwent->pw_passwd);
}
free (pwent->pw_gecos); free (pwent->pw_gecos);
free (pwent->pw_dir); free (pwent->pw_dir);
free (pwent->pw_shell); free (pwent->pw_shell);
+103
View File
@@ -0,0 +1,103 @@
/*
* Copyright (c) 2011 , Peter Vrabec <pvrabec@redhat.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ifdef WITH_SELINUX
#include "defines.h"
#include <selinux/selinux.h>
#include "prototypes.h"
static bool selinux_checked = false;
static bool selinux_enabled;
/*
* set_selinux_file_context - Set the security context before any file or
* directory creation.
*
* set_selinux_file_context () should be called before any creation
* of file, symlink, directory, ...
*
* Callers may have to Reset SELinux to create files with default
* contexts with reset_selinux_file_context
*/
int set_selinux_file_context (const char *dst_name)
{
/*@null@*/security_context_t scontext = NULL;
if (!selinux_checked) {
selinux_enabled = is_selinux_enabled () > 0;
selinux_checked = true;
}
if (selinux_enabled) {
/* Get the default security context for this file */
if (matchpathcon (dst_name, 0, &scontext) < 0) {
if (security_getenforce () != 0) {
return 1;
}
}
/* Set the security context for the next created file */
if (setfscreatecon (scontext) < 0) {
if (security_getenforce () != 0) {
return 1;
}
}
freecon (scontext);
}
return 0;
}
/*
* reset_selinux_file_context - Reset the security context to the default
* policy behavior
*
* reset_selinux_file_context () should be called after the context
* was changed with set_selinux_file_context ()
*/
int reset_selinux_file_context (void)
{
if (!selinux_checked) {
selinux_enabled = is_selinux_enabled () > 0;
selinux_checked = true;
}
if (selinux_enabled) {
if (setfscreatecon (NULL) != 0) {
return 1;
}
}
return 0;
}
#else /* !WITH_SELINUX */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !WITH_SELINUX */
+378
View File
@@ -0,0 +1,378 @@
/*
* Copyright (c) 2010 , Jakub Hrozek <jhrozek@redhat.com>
* Copyright (c) 2011 , Peter Vrabec <pvrabec@redhat.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ifdef WITH_SELINUX
#include "defines.h"
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdarg.h>
#include <selinux/selinux.h>
#include <semanage/semanage.h>
#include "prototypes.h"
#ifndef DEFAULT_SERANGE
#define DEFAULT_SERANGE "s0"
#endif
static void semanage_error_callback (unused void *varg,
semanage_handle_t *handle,
const char *fmt, ...)
{
int ret;
char * message = NULL;
va_list ap;
va_start (ap, fmt);
ret = vasprintf (&message, fmt, ap);
va_end (ap);
if (ret < 0) {
/* ENOMEM */
return;
}
switch (semanage_msg_get_level (handle)) {
case SEMANAGE_MSG_ERR:
case SEMANAGE_MSG_WARN:
fprintf (stderr, _("[libsemanage]: %s\n"), message);
break;
case SEMANAGE_MSG_INFO:
/* nop */
break;
}
free (message);
}
static semanage_handle_t *semanage_init (void)
{
int ret;
semanage_handle_t *handle = NULL;
handle = semanage_handle_create ();
if (NULL == handle) {
fprintf (stderr,
_("Cannot create SELinux management handle\n"));
return NULL;
}
semanage_msg_set_callback (handle, semanage_error_callback, NULL);
ret = semanage_is_managed (handle);
if (ret != 1) {
fprintf (stderr, _("SELinux policy not managed\n"));
goto fail;
}
ret = semanage_access_check (handle);
if (ret < SEMANAGE_CAN_READ) {
fprintf (stderr, _("Cannot read SELinux policy store\n"));
goto fail;
}
ret = semanage_connect (handle);
if (ret != 0) {
fprintf (stderr,
_("Cannot establish SELinux management connection\n"));
goto fail;
}
ret = semanage_begin_transaction (handle);
if (ret != 0) {
fprintf (stderr, _("Cannot begin SELinux transaction\n"));
goto fail;
}
return handle;
fail:
semanage_handle_destroy (handle);
return NULL;
}
static int semanage_user_mod (semanage_handle_t *handle,
semanage_seuser_key_t *key,
const char *login_name,
const char *seuser_name)
{
int ret;
semanage_seuser_t *seuser = NULL;
semanage_seuser_query (handle, key, &seuser);
if (NULL == seuser) {
fprintf (stderr,
_("Could not query seuser for %s\n"), login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
if (ret != 0) {
fprintf (stderr,
_("Could not set serange for %s\n"), login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
if (ret != 0) {
fprintf (stderr,
_("Could not set sename for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_modify_local (handle, key, seuser);
if (ret != 0) {
fprintf (stderr,
_("Could not modify login mapping for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = 0;
done:
semanage_seuser_free (seuser);
return ret;
}
static int semanage_user_add (semanage_handle_t *handle,
semanage_seuser_key_t *key,
const char *login_name,
const char *seuser_name)
{
int ret;
semanage_seuser_t *seuser = NULL;
ret = semanage_seuser_create (handle, &seuser);
if (ret != 0) {
fprintf (stderr,
_("Cannot create SELinux login mapping for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_set_name (handle, seuser, login_name);
if (ret != 0) {
fprintf (stderr, _("Could not set name for %s\n"), login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
if (ret != 0) {
fprintf (stderr,
_("Could not set serange for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
if (ret != 0) {
fprintf (stderr,
_("Could not set SELinux user for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = semanage_seuser_modify_local (handle, key, seuser);
if (ret != 0) {
fprintf (stderr,
_("Could not add login mapping for %s\n"),
login_name);
ret = 1;
goto done;
}
ret = 0;
done:
semanage_seuser_free (seuser);
return ret;
}
int set_seuser (const char *login_name, const char *seuser_name)
{
semanage_handle_t *handle = NULL;
semanage_seuser_key_t *key = NULL;
int ret;
int seuser_exists = 0;
if (NULL == seuser_name) {
/* don't care, just let system pick the defaults */
return 0;
}
handle = semanage_init ();
if (NULL == handle) {
fprintf (stderr, _("Cannot init SELinux management\n"));
ret = 1;
goto done;
}
ret = semanage_seuser_key_create (handle, login_name, &key);
if (ret != 0) {
fprintf (stderr, _("Cannot create SELinux user key\n"));
ret = 1;
goto done;
}
ret = semanage_seuser_exists (handle, key, &seuser_exists);
if (ret < 0) {
fprintf (stderr, _("Cannot verify the SELinux user\n"));
ret = 1;
goto done;
}
if (0 != seuser_exists) {
ret = semanage_user_mod (handle, key, login_name, seuser_name);
if (ret != 0) {
fprintf (stderr,
_("Cannot modify SELinux user mapping\n"));
ret = 1;
goto done;
}
} else {
ret = semanage_user_add (handle, key, login_name, seuser_name);
if (ret != 0) {
fprintf (stderr,
_("Cannot add SELinux user mapping\n"));
ret = 1;
goto done;
}
}
ret = semanage_commit (handle);
if (ret < 0) {
fprintf (stderr, _("Cannot commit SELinux transaction\n"));
ret = 1;
goto done;
}
ret = 0;
done:
semanage_seuser_key_free (key);
semanage_handle_destroy (handle);
return ret;
}
int del_seuser (const char *login_name)
{
semanage_handle_t *handle = NULL;
semanage_seuser_key_t *key = NULL;
int ret;
int exists = 0;
handle = semanage_init ();
if (NULL == handle) {
fprintf (stderr, _("Cannot init SELinux management\n"));
ret = 1;
goto done;
}
ret = semanage_seuser_key_create (handle, login_name, &key);
if (ret != 0) {
fprintf (stderr, _("Cannot create SELinux user key\n"));
ret = 1;
goto done;
}
ret = semanage_seuser_exists (handle, key, &exists);
if (ret < 0) {
fprintf (stderr, _("Cannot verify the SELinux user\n"));
ret = 1;
goto done;
}
if (0 == exists) {
fprintf (stderr,
_("Login mapping for %s is not defined, OK if default mapping was used\n"),
login_name);
ret = 0; /* probably default mapping */
goto done;
}
ret = semanage_seuser_exists_local (handle, key, &exists);
if (ret < 0) {
fprintf (stderr, _("Cannot verify the SELinux user\n"));
ret = 1;
goto done;
}
if (0 == exists) {
fprintf (stderr,
_("Login mapping for %s is defined in policy, cannot be deleted\n"),
login_name);
ret = 0; /* Login mapping defined in policy can't be deleted */
goto done;
}
ret = semanage_seuser_del_local (handle, key);
if (ret != 0) {
fprintf (stderr,
_("Could not delete login mapping for %s"),
login_name);
ret = 1;
goto done;
}
ret = semanage_commit (handle);
if (ret < 0) {
fprintf (stderr, _("Cannot commit SELinux transaction\n"));
ret = 1;
goto done;
}
ret = 0;
done:
semanage_handle_destroy (handle);
return ret;
}
#else /* !WITH_SELINUX */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !WITH_SELINUX */
+54 -10
View File
@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal * Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2005 , Tomasz Kłoczko * Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2008, Nicolas François * Copyright (c) 2007 - 2013, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -51,13 +51,19 @@
if (NULL == sg) { if (NULL == sg) {
return NULL; return NULL;
} }
*sg = *sgent; /* Do the same as the other _dup function, even if we know the
* structure. */
memset (sg, 0, sizeof *sg);
/*@-mustfreeonly@*/
sg->sg_name = strdup (sgent->sg_name); sg->sg_name = strdup (sgent->sg_name);
/*@=mustfreeonly@*/
if (NULL == sg->sg_name) { if (NULL == sg->sg_name) {
free (sg); free (sg);
return NULL; return NULL;
} }
/*@-mustfreeonly@*/
sg->sg_passwd = strdup (sgent->sg_passwd); sg->sg_passwd = strdup (sgent->sg_passwd);
/*@=mustfreeonly@*/
if (NULL == sg->sg_passwd) { if (NULL == sg->sg_passwd) {
free (sg->sg_name); free (sg->sg_name);
free (sg); free (sg);
@@ -65,7 +71,9 @@
} }
for (i = 0; NULL != sgent->sg_adm[i]; i++); for (i = 0; NULL != sgent->sg_adm[i]; i++);
/*@-mustfreeonly@*/
sg->sg_adm = (char **) malloc ((i + 1) * sizeof (char *)); sg->sg_adm = (char **) malloc ((i + 1) * sizeof (char *));
/*@=mustfreeonly@*/
if (NULL == sg->sg_adm) { if (NULL == sg->sg_adm) {
free (sg->sg_passwd); free (sg->sg_passwd);
free (sg->sg_name); free (sg->sg_name);
@@ -88,7 +96,9 @@
sg->sg_adm[i] = NULL; sg->sg_adm[i] = NULL;
for (i = 0; NULL != sgent->sg_mem[i]; i++); for (i = 0; NULL != sgent->sg_mem[i]; i++);
/*@-mustfreeonly@*/
sg->sg_mem = (char **) malloc ((i + 1) * sizeof (char *)); sg->sg_mem = (char **) malloc ((i + 1) * sizeof (char *));
/*@=mustfreeonly@*/
if (NULL == sg->sg_mem) { if (NULL == sg->sg_mem) {
for (i = 0; NULL != sg->sg_adm[i]; i++) { for (i = 0; NULL != sg->sg_adm[i]; i++) {
free (sg->sg_adm[i]); free (sg->sg_adm[i]);
@@ -137,17 +147,20 @@ static void gshadow_free (/*@out@*/ /*@only@*/void *ent)
void sgr_free (/*@out@*/ /*@only@*/struct sgrp *sgent) void sgr_free (/*@out@*/ /*@only@*/struct sgrp *sgent)
{ {
size_t i;
free (sgent->sg_name); free (sgent->sg_name);
memzero (sgent->sg_passwd, strlen (sgent->sg_passwd)); if (NULL != sgent->sg_passwd) {
free (sgent->sg_passwd); memzero (sgent->sg_passwd, strlen (sgent->sg_passwd));
while (NULL != *(sgent->sg_adm)) { free (sgent->sg_passwd);
free (*(sgent->sg_adm));
sgent->sg_adm++;
} }
while (NULL != *(sgent->sg_mem)) { for (i = 0; NULL != sgent->sg_adm[i]; i++) {
free (*(sgent->sg_mem)); free (sgent->sg_adm[i]);
sgent->sg_mem++;
} }
free (sgent->sg_adm);
for (i = 0; NULL != sgent->sg_mem[i]; i++) {
free (sgent->sg_mem[i]);
}
free (sgent->sg_mem);
free (sgent); free (sgent);
} }
@@ -167,6 +180,32 @@ static int gshadow_put (const void *ent, FILE * file)
{ {
const struct sgrp *sg = ent; const struct sgrp *sg = ent;
if ( (NULL == sg)
|| (valid_field (sg->sg_name, ":\n") == -1)
|| (valid_field (sg->sg_passwd, ":\n") == -1)) {
return -1;
}
/* FIXME: fail also if sg->sg_adm == NULL ?*/
if (NULL != sg->sg_adm) {
size_t i;
for (i = 0; NULL != sg->sg_adm[i]; i++) {
if (valid_field (sg->sg_adm[i], ",:\n") == -1) {
return -1;
}
}
}
/* FIXME: fail also if sg->sg_mem == NULL ?*/
if (NULL != sg->sg_mem) {
size_t i;
for (i = 0; NULL != sg->sg_mem[i]; i++) {
if (valid_field (sg->sg_mem[i], ",:\n") == -1) {
return -1;
}
}
}
return (putsgent (sg, file) == -1) ? -1 : 0; return (putsgent (sg, file) == -1) ? -1 : 0;
} }
@@ -189,6 +228,9 @@ static struct commonio_db gshadow_db = {
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
NULL, /* scontext */ NULL, /* scontext */
#endif #endif
0400, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */ NULL, /* head */
NULL, /* tail */ NULL, /* tail */
NULL, /* cursor */ NULL, /* cursor */
@@ -210,6 +252,8 @@ int sgr_setdbname (const char *filename)
bool sgr_file_present (void) bool sgr_file_present (void)
{ {
if (getdef_bool ("FORCE_SHADOW"))
return true;
return commonio_present (&gshadow_db); return commonio_present (&gshadow_db);
} }
+1 -1
View File
@@ -37,7 +37,7 @@
extern int sgr_close (void); extern int sgr_close (void);
extern bool sgr_file_present (void); extern bool sgr_file_present (void);
extern /*@null@*/const struct sgrp *sgr_locate (const char *name); extern /*@observer@*/ /*@null@*/const struct sgrp *sgr_locate (const char *name);
extern int sgr_lock (void); extern int sgr_lock (void);
extern int sgr_setdbname (const char *filename); extern int sgr_setdbname (const char *filename);
extern /*@observer@*/const char *sgr_dbname (void); extern /*@observer@*/const char *sgr_dbname (void);
+47 -27
View File
@@ -42,10 +42,10 @@
#include "defines.h" #include "defines.h"
#include <stdio.h> #include <stdio.h>
#ifdef USE_NIS #ifdef USE_NIS
static int nis_used; static bool nis_used;
static int nis_ignore; static bool nis_ignore;
static enum { native, start, middle, native2 } nis_state; static enum { native, start, middle, native2 } nis_state;
static int nis_bound; static bool nis_bound;
static char *nis_domain; static char *nis_domain;
static char *nis_key; static char *nis_key;
static int nis_keylen; static int nis_keylen;
@@ -66,12 +66,12 @@ static FILE *shadow;
* __setspNIS - turn on or off NIS searches * __setspNIS - turn on or off NIS searches
*/ */
void __setspNIS (int flag) void __setspNIS (bool flag)
{ {
nis_ignore = !flag; nis_ignore = !flag;
if (nis_ignore) { if (nis_ignore) {
nis_used = 0; nis_used = false;
} }
} }
@@ -81,10 +81,11 @@ void __setspNIS (int flag)
static int bind_nis (void) static int bind_nis (void)
{ {
if (yp_get_default_domain (&nis_domain)) if (yp_get_default_domain (&nis_domain)) {
return -1; return -1;
}
nis_bound = 1; nis_bound = true;
return 0; return 0;
} }
#endif #endif
@@ -95,10 +96,11 @@ static int bind_nis (void)
void setspent (void) void setspent (void)
{ {
if (shadow) if (NULL != shadow) {
rewind (shadow); rewind (shadow);
else }else {
shadow = fopen (SHADOW_FILE, "r"); shadow = fopen (SHADOW_FILE, "r");
}
#ifdef USE_NIS #ifdef USE_NIS
nis_state = native; nis_state = native;
@@ -111,8 +113,9 @@ void setspent (void)
void endspent (void) void endspent (void)
{ {
if (shadow) if (NULL != shadow) {
(void) fclose (shadow); (void) fclose (shadow);
}
shadow = (FILE *) 0; shadow = (FILE *) 0;
} }
@@ -172,8 +175,9 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_namp = fields[0]; spwd.sp_namp = fields[0];
#ifdef USE_NIS #ifdef USE_NIS
if (IS_NISCHAR (fields[0][0])) if (IS_NISCHAR (fields[0][0])) {
nis_used = 1; nis_used = true;
}
#endif #endif
spwd.sp_pwdp = fields[1]; spwd.sp_pwdp = fields[1];
@@ -211,7 +215,9 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_min = -1; spwd.sp_min = -1;
} else } else
#endif #endif
{
return 0; return 0;
}
} else if (spwd.sp_min < 0) { } else if (spwd.sp_min < 0) {
return 0; return 0;
} }
@@ -263,7 +269,9 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_warn = -1; spwd.sp_warn = -1;
} else } else
#endif #endif
{
return 0; return 0;
}
} else if (spwd.sp_warn < 0) { } else if (spwd.sp_warn < 0) {
return 0; return 0;
} }
@@ -283,7 +291,9 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_inact = -1; spwd.sp_inact = -1;
} else } else
#endif #endif
{
return 0; return 0;
}
} else if (spwd.sp_inact < 0) { } else if (spwd.sp_inact < 0) {
return 0; return 0;
} }
@@ -303,7 +313,9 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_expire = -1; spwd.sp_expire = -1;
} else } else
#endif #endif
{
return 0; return 0;
}
} else if (spwd.sp_expire < 0) { } else if (spwd.sp_expire < 0) {
return 0; return 0;
} }
@@ -324,7 +336,9 @@ static struct spwd *my_sgetspent (const char *string)
spwd.sp_flag = SHADOW_SP_FLAG_UNSET; spwd.sp_flag = SHADOW_SP_FLAG_UNSET;
} else } else
#endif #endif
{
return 0; return 0;
}
} else if (spwd.sp_flag < 0) { } else if (spwd.sp_flag < 0) {
return 0; return 0;
} }
@@ -377,8 +391,9 @@ struct spwd *getspent (void)
struct spwd *val; struct spwd *val;
char buf[BUFSIZ]; char buf[BUFSIZ];
#endif #endif
if (!shadow) if (NULL == shadow) {
setspent (); setspent ();
}
#ifdef USE_NIS #ifdef USE_NIS
again: again:
@@ -432,7 +447,7 @@ struct spwd *getspent (void)
return 0; return 0;
} else { } else {
if (nis_bound == 0) { if (!nis_bound) {
if (bind_nis ()) { if (bind_nis ()) {
nis_state = native2; nis_state = native2;
goto again; goto again;
@@ -440,15 +455,15 @@ struct spwd *getspent (void)
} }
if (nis_state == start) { if (nis_state == start) {
if (yp_first (nis_domain, "shadow.bynam", &nis_key, if (yp_first (nis_domain, "shadow.bynam", &nis_key,
&nis_keylen, &nis_val, &nis_vallen)) { &nis_keylen, &nis_val, &nis_vallen)) {
nis_state = native2; nis_state = native2;
goto again; goto again;
} }
nis_state = middle; nis_state = middle;
} else if (nis_state == middle) { } else if (nis_state == middle) {
if (yp_next (nis_domain, "shadow.bynam", nis_key, if (yp_next (nis_domain, "shadow.bynam", nis_key,
nis_keylen, &nis_key, &nis_keylen, nis_keylen, &nis_key, &nis_keylen,
&nis_val, &nis_vallen)) { &nis_val, &nis_vallen)) {
nis_state = native2; nis_state = native2;
goto again; goto again;
} }
@@ -471,7 +486,7 @@ struct spwd *getspnam (const char *name)
#ifdef USE_NIS #ifdef USE_NIS
char buf[BUFSIZ]; char buf[BUFSIZ];
static char save_name[16]; static char save_name[16];
int nis_disabled = 0; bool nis_disabled = false;
#endif #endif
setspent (); setspent ();
@@ -481,18 +496,20 @@ struct spwd *getspnam (const char *name)
* Search the shadow.byname map for this user. * Search the shadow.byname map for this user.
*/ */
if (!nis_ignore && !nis_bound) if (!nis_ignore && !nis_bound) {
bind_nis (); bind_nis ();
}
if (!nis_ignore && nis_bound) { if (!nis_ignore && nis_bound) {
char *cp; char *cp;
if (yp_match (nis_domain, "shadow.byname", name, if (yp_match (nis_domain, "shadow.byname", name,
strlen (name), &nis_val, &nis_vallen) == 0) { strlen (name), &nis_val, &nis_vallen) == 0) {
cp = strchr (nis_val, '\n'); cp = strchr (nis_val, '\n');
if (NULL != cp) if (NULL != cp) {
*cp = '\0'; *cp = '\0';
}
nis_state = middle; nis_state = middle;
sp = my_sgetspent (nis_val); sp = my_sgetspent (nis_val);
@@ -503,8 +520,9 @@ struct spwd *getspnam (const char *name)
} }
endspent (); endspent ();
return sp; return sp;
} else } else {
nis_state = native2; nis_state = native2;
}
} }
#endif #endif
#ifdef USE_NIS #ifdef USE_NIS
@@ -516,17 +534,19 @@ struct spwd *getspnam (const char *name)
*/ */
if (nis_used) { if (nis_used) {
nis_ignore++; nis_ignore = true;
nis_disabled++; nis_disabled = true;
} }
#endif #endif
while ((sp = getspent ()) != (struct spwd *) 0) { while ((sp = getspent ()) != (struct spwd *) 0) {
if (strcmp (name, sp->sp_namp) == 0) if (strcmp (name, sp->sp_namp) == 0) {
break; break;
}
} }
#ifdef USE_NIS #ifdef USE_NIS
if (nis_disabled) if (nis_disabled) {
nis_ignore--; nis_ignore = false;
}
#endif #endif
endspent (); endspent ();
return (sp); return (sp);
+91 -5
View File
@@ -41,6 +41,10 @@
#include <stdio.h> #include <stdio.h>
#include "commonio.h" #include "commonio.h"
#include "shadowio.h" #include "shadowio.h"
#ifdef WITH_TCB
#include <tcb.h>
#include "tcbfuncs.h"
#endif /* WITH_TCB */
static /*@null@*/ /*@only@*/void *shadow_dup (const void *ent) static /*@null@*/ /*@only@*/void *shadow_dup (const void *ent)
{ {
@@ -72,6 +76,12 @@ static int shadow_put (const void *ent, FILE * file)
{ {
const struct spwd *sp = ent; const struct spwd *sp = ent;
if ( (NULL == sp)
|| (valid_field (sp->sp_namp, ":\n") == -1)
|| (valid_field (sp->sp_pwdp, ":\n") == -1)) {
return -1;
}
return (putspent (sp, file) == -1) ? -1 : 0; return (putspent (sp, file) == -1) ? -1 : 0;
} }
@@ -93,7 +103,10 @@ static struct commonio_db shadow_db = {
NULL, /* fp */ NULL, /* fp */
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
NULL, /* scontext */ NULL, /* scontext */
#endif #endif /* WITH_SELINUX */
0400, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */ NULL, /* head */
NULL, /* tail */ NULL, /* tail */
NULL, /* cursor */ NULL, /* cursor */
@@ -115,17 +128,52 @@ int spw_setdbname (const char *filename)
bool spw_file_present (void) bool spw_file_present (void)
{ {
if (getdef_bool ("FORCE_SHADOW"))
return true;
return commonio_present (&shadow_db); return commonio_present (&shadow_db);
} }
int spw_lock (void) int spw_lock (void)
{ {
return commonio_lock (&shadow_db); #ifdef WITH_TCB
int retval = 0;
if (!getdef_bool ("USE_TCB")) {
#endif /* WITH_TCB */
return commonio_lock (&shadow_db);
#ifdef WITH_TCB
}
if (shadowtcb_drop_priv () == SHADOWTCB_FAILURE) {
return 0;
}
if (lckpwdf_tcb (shadow_db.filename) == 0) {
shadow_db.locked = 1;
retval = 1;
}
if (shadowtcb_gain_priv () == SHADOWTCB_FAILURE) {
return 0;
}
return retval;
#endif /* WITH_TCB */
} }
int spw_open (int mode) int spw_open (int mode)
{ {
return commonio_open (&shadow_db, mode); int retval = 0;
#ifdef WITH_TCB
bool use_tcb = getdef_bool ("USE_TCB");
if (use_tcb && (shadowtcb_drop_priv () == SHADOWTCB_FAILURE)) {
return 0;
}
#endif /* WITH_TCB */
retval = commonio_open (&shadow_db, mode);
#ifdef WITH_TCB
if (use_tcb && (shadowtcb_gain_priv () == SHADOWTCB_FAILURE)) {
return 0;
}
#endif /* WITH_TCB */
return retval;
} }
/*@observer@*/ /*@null@*/const struct spwd *spw_locate (const char *name) /*@observer@*/ /*@null@*/const struct spwd *spw_locate (const char *name)
@@ -155,12 +203,45 @@ int spw_rewind (void)
int spw_close (void) int spw_close (void)
{ {
return commonio_close (&shadow_db); int retval = 0;
#ifdef WITH_TCB
bool use_tcb = getdef_bool ("USE_TCB");
if (use_tcb && (shadowtcb_drop_priv () == SHADOWTCB_FAILURE)) {
return 0;
}
#endif /* WITH_TCB */
retval = commonio_close (&shadow_db);
#ifdef WITH_TCB
if (use_tcb && (shadowtcb_gain_priv () == SHADOWTCB_FAILURE)) {
return 0;
}
#endif /* WITH_TCB */
return retval;
} }
int spw_unlock (void) int spw_unlock (void)
{ {
return commonio_unlock (&shadow_db); #ifdef WITH_TCB
int retval = 0;
if (!getdef_bool ("USE_TCB")) {
#endif /* WITH_TCB */
return commonio_unlock (&shadow_db);
#ifdef WITH_TCB
}
if (shadowtcb_drop_priv () == SHADOWTCB_FAILURE) {
return 0;
}
if (ulckpwdf_tcb () == 0) {
shadow_db.locked = 0;
retval = 1;
}
if (shadowtcb_gain_priv () == SHADOWTCB_FAILURE) {
return 0;
}
return retval;
#endif /* WITH_TCB */
} }
struct commonio_entry *__spw_get_head (void) struct commonio_entry *__spw_get_head (void)
@@ -176,5 +257,10 @@ void __spw_del_entry (const struct commonio_entry *ent)
/* Sort with respect to passwd ordering. */ /* Sort with respect to passwd ordering. */
int spw_sort () int spw_sort ()
{ {
#ifdef WITH_TCB
if (getdef_bool ("USE_TCB")) {
return 0;
}
#endif /* WITH_TCB */
return commonio_sort_wrt (&shadow_db, __pw_get_db ()); return commonio_sort_wrt (&shadow_db, __pw_get_db ());
} }
+22 -5
View File
@@ -3,7 +3,7 @@
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 , Michał Moskal * Copyright (c) 2001 , Michał Moskal
* Copyright (c) 2005 , Tomasz Kłoczko * Copyright (c) 2005 , Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François * Copyright (c) 2007 - 2013, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -49,13 +49,28 @@
if (NULL == sp) { if (NULL == sp) {
return NULL; return NULL;
} }
*sp = *spent; /* The libc might define other fields. They won't be copied. */
sp->sp_namp = strdup (spent->sp_namp); memset (sp, 0, sizeof *sp);
sp->sp_lstchg = spent->sp_lstchg;
sp->sp_min = spent->sp_min;
sp->sp_max = spent->sp_max;
sp->sp_warn = spent->sp_warn;
sp->sp_inact = spent->sp_inact;
sp->sp_expire = spent->sp_expire;
sp->sp_flag = spent->sp_flag;
/*@-mustfreeonly@*/
sp->sp_namp = strdup (spent->sp_namp);
/*@=mustfreeonly@*/
if (NULL == sp->sp_namp) { if (NULL == sp->sp_namp) {
free(sp);
return NULL; return NULL;
} }
/*@-mustfreeonly@*/
sp->sp_pwdp = strdup (spent->sp_pwdp); sp->sp_pwdp = strdup (spent->sp_pwdp);
/*@=mustfreeonly@*/
if (NULL == sp->sp_pwdp) { if (NULL == sp->sp_pwdp) {
free(sp->sp_namp);
free(sp);
return NULL; return NULL;
} }
@@ -65,8 +80,10 @@
void spw_free (/*@out@*/ /*@only@*/struct spwd *spent) void spw_free (/*@out@*/ /*@only@*/struct spwd *spent)
{ {
free (spent->sp_namp); free (spent->sp_namp);
memzero (spent->sp_pwdp, strlen (spent->sp_pwdp)); if (NULL != spent->sp_pwdp) {
free (spent->sp_pwdp); memzero (spent->sp_pwdp, strlen (spent->sp_pwdp));
free (spent->sp_pwdp);
}
free (spent); free (spent);
} }
+82
View File
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2011 , Jonathan Nieder
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "exitcodes.h"
#include "prototypes.h"
int run_command (const char *cmd, const char *argv[],
/*@null@*/const char *envp[], /*@out@*/int *status)
{
pid_t pid, wpid;
if (NULL == envp) {
envp = (const char **)environ;
}
(void) fflush (stdout);
(void) fflush (stderr);
pid = fork ();
if (0 == pid) {
(void) execve (cmd, (char * const *) argv,
(char * const *) envp);
if (ENOENT == errno) {
exit (E_CMD_NOTFOUND);
}
fprintf (stderr, "%s: cannot execute %s: %s\n",
Prog, cmd, strerror (errno));
exit (E_CMD_NOEXEC);
} else if ((pid_t)-1 == pid) {
fprintf (stderr, "%s: cannot execute %s: %s\n",
Prog, cmd, strerror (errno));
return -1;
}
do {
wpid = waitpid (pid, status, 0);
} while ( ((pid_t)-1 == wpid && errno == EINTR)
|| (wpid != pid));
if ((pid_t)-1 == wpid) {
fprintf (stderr, "%s: waitpid (status: %d): %s\n",
Prog, *status, strerror (errno));
return -1;
}
return 0;
}
+701
View File
@@ -0,0 +1,701 @@
/*
* Copyright (c) 2012 - Eric Biederman
*/
#include <config.h>
#ifdef ENABLE_SUBIDS
#include "prototypes.h"
#include "defines.h"
#include <stdio.h>
#include "commonio.h"
#include "subordinateio.h"
#include <sys/types.h>
#include <pwd.h>
struct subordinate_range {
const char *owner;
unsigned long start;
unsigned long count;
};
#define NFIELDS 3
/*
* subordinate_dup: create a duplicate range
*
* @ent: a pointer to a subordinate_range struct
*
* Returns a pointer to a newly allocated duplicate subordinate_range struct
* or NULL on failure
*/
static /*@null@*/ /*@only@*/void *subordinate_dup (const void *ent)
{
const struct subordinate_range *rangeent = ent;
struct subordinate_range *range;
range = (struct subordinate_range *) malloc (sizeof *range);
if (NULL == range) {
return NULL;
}
range->owner = strdup (rangeent->owner);
if (NULL == range->owner) {
free(range);
return NULL;
}
range->start = rangeent->start;
range->count = rangeent->count;
return range;
}
/*
* subordinate_free: free a subordinate_range struct
*
* @ent: pointer to a subordinate_range struct to free.
*/
static void subordinate_free (/*@out@*/ /*@only@*/void *ent)
{
struct subordinate_range *rangeent = ent;
free ((void *)(rangeent->owner));
free (rangeent);
}
/*
* subordinate_parse:
*
* @line: a line to parse
*
* Returns a pointer to a subordinate_range struct representing the values
* in @line, or NULL on failure. Note that the returned value should not
* be freed by the caller.
*/
static void *subordinate_parse (const char *line)
{
static struct subordinate_range range;
static char rangebuf[1024];
int i;
char *cp;
char *fields[NFIELDS];
/*
* Copy the string to a temporary buffer so the substrings can
* be modified to be NULL terminated.
*/
if (strlen (line) >= sizeof rangebuf)
return NULL; /* fail if too long */
strcpy (rangebuf, line);
/*
* Save a pointer to the start of each colon separated
* field. The fields are converted into NUL terminated strings.
*/
for (cp = rangebuf, i = 0; (i < NFIELDS) && (NULL != cp); i++) {
fields[i] = cp;
while (('\0' != *cp) && (':' != *cp)) {
cp++;
}
if ('\0' != *cp) {
*cp = '\0';
cp++;
} else {
cp = NULL;
}
}
/*
* There must be exactly NFIELDS colon separated fields or
* the entry is invalid. Also, fields must be non-blank.
*/
if (i != NFIELDS || *fields[0] == '\0' || *fields[1] == '\0' || *fields[2] == '\0')
return NULL;
range.owner = fields[0];
if (getulong (fields[1], &range.start) == 0)
return NULL;
if (getulong (fields[2], &range.count) == 0)
return NULL;
return &range;
}
/*
* subordinate_put: print a subordinate_range value to a file
*
* @ent: a pointer to a subordinate_range struct to print out.
* @file: file to which to print.
*
* Returns 0 on success, -1 on error.
*/
static int subordinate_put (const void *ent, FILE * file)
{
const struct subordinate_range *range = ent;
return fprintf(file, "%s:%lu:%lu\n",
range->owner,
range->start,
range->count) < 0 ? -1 : 0;
}
static struct commonio_ops subordinate_ops = {
subordinate_dup, /* dup */
subordinate_free, /* free */
NULL, /* getname */
subordinate_parse, /* parse */
subordinate_put, /* put */
fgets, /* fgets */
fputs, /* fputs */
NULL, /* open_hook */
NULL, /* close_hook */
};
static /*@observer@*/ /*@null*/const struct subordinate_range *subordinate_next(struct commonio_db *db)
{
return (const struct subordinate_range *)commonio_next (db);
}
/*
* range_exists: Check whether @owner owns any ranges
*
* @db: database to query
* @owner: owner being queried
*
* Returns true if @owner owns any subuid ranges, false otherwise.
*/
static const bool range_exists(struct commonio_db *db, const char *owner)
{
const struct subordinate_range *range;
commonio_rewind(db);
while ((range = commonio_next(db)) != NULL) {
if (0 == strcmp(range->owner, owner))
return true;
}
return false;
}
/*
* find_range: find a range which @owner is authorized to use which includes
* subuid @val.
*
* @db: database to query
* @owner: owning uid being queuried
* @val: subuid being searched for.
*
* Returns a range of subuids belonging to @owner and including the subuid
* @val, or NULL if no such range exists.
*/
static const struct subordinate_range *find_range(struct commonio_db *db,
const char *owner, unsigned long val)
{
const struct subordinate_range *range;
/*
* Search for exact username/group specification
*
* This is the original method - go fast through the db, doing only
* exact username/group string comparison. Therefore we leave it as-is
* for the time being, in order to keep it equally fast as it was
* before.
*/
commonio_rewind(db);
while ((range = commonio_next(db)) != NULL) {
unsigned long first = range->start;
unsigned long last = first + range->count - 1;
if (0 != strcmp(range->owner, owner))
continue;
if ((val >= first) && (val <= last))
return range;
}
/*
* We only do special handling for these two files
*/
if ((0 != strcmp(db->filename, "/etc/subuid")) && (0 != strcmp(db->filename, "/etc/subgid")))
return NULL;
/*
* Search loop above did not produce any result. Let's rerun it,
* but this time try to matcha actual UIDs. The first entry that
* matches is considered a success.
* (It may be specified as literal UID or as another username which
* has the same UID as the username we are looking for.)
*/
struct passwd *pwd;
uid_t owner_uid;
char owner_uid_string[33] = "";
/* Get UID of the username we are looking for */
pwd = getpwnam(owner);
if (NULL == pwd) {
/* Username not defined in /etc/passwd, or error occured during lookup */
return NULL;
}
owner_uid = pwd->pw_uid;
sprintf(owner_uid_string, "%lu", (unsigned long int)owner_uid);
commonio_rewind(db);
while ((range = commonio_next(db)) != NULL) {
unsigned long first = range->start;
unsigned long last = first + range->count - 1;
/* For performance reasons check range before using getpwnam() */
if ((val < first) || (val > last)) {
continue;
}
/*
* Range matches. Check if range owner is specified
* as numeric UID and if it matches.
*/
if (0 == strcmp(range->owner, owner_uid_string)) {
return range;
}
/*
* Ok, this range owner is not specified as numeric UID
* we are looking for. It may be specified as another
* UID or as a literal username.
*
* If specified as another UID, the call to getpwnam()
* will return NULL.
*
* If specified as literal username, we will get its
* UID and compare that to UID we are looking for.
*/
const struct passwd *range_owner_pwd;
range_owner_pwd = getpwnam(range->owner);
if (NULL == range_owner_pwd) {
continue;
}
if (owner_uid == range_owner_pwd->pw_uid) {
return range;
}
}
return NULL;
}
/*
* have_range: check whether @owner is authorized to use the range
* (@start .. @start+@count-1).
* @db: database to check
* @owner: owning uid being queried
* @start: start of range
* @count: number of uids in range
*
* Returns true if @owner is authorized to use the range, false otherwise.
*/
static bool have_range(struct commonio_db *db,
const char *owner, unsigned long start, unsigned long count)
{
const struct subordinate_range *range;
unsigned long end;
if (count == 0)
return false;
end = start + count - 1;
range = find_range (db, owner, start);
while (range) {
unsigned long last;
last = range->start + range->count - 1;
if (last >= (start + count - 1))
return true;
count = end - last;
start = last + 1;
range = find_range(db, owner, start);
}
return false;
}
/*
* subordinate_range_cmp: compare uid ranges
*
* @p1: pointer to a commonio_entry struct to compare
* @p2: pointer to second commonio_entry struct to compare
*
* Returns 0 if the entries are the same. Otherwise return -1
* if the range in p1 is lower than that in p2, or (if the ranges are
* equal) if the owning uid in p1 is lower than p2's. Return 1 if p1's
* range or owning uid is great than p2's.
*/
static int subordinate_range_cmp (const void *p1, const void *p2)
{
struct subordinate_range *range1, *range2;
if ((*(struct commonio_entry **) p1)->eptr == NULL)
return 1;
if ((*(struct commonio_entry **) p2)->eptr == NULL)
return -1;
range1 = ((struct subordinate_range *) (*(struct commonio_entry **) p1)->eptr);
range2 = ((struct subordinate_range *) (*(struct commonio_entry **) p2)->eptr);
if (range1->start < range2->start)
return -1;
else if (range1->start > range2->start)
return 1;
else if (range1->count < range2->count)
return -1;
else if (range1->count > range2->count)
return 1;
else
return strcmp(range1->owner, range2->owner);
}
/*
* find_free_range: find an unused consecutive sequence of ids to allocate
* to a user.
* @db: database to search
* @min: the first uid in the range to find
* @max: the highest uid to find
* @count: the number of uids needed
*
* Return the lowest new uid, or ULONG_MAX on failure.
*/
static unsigned long find_free_range(struct commonio_db *db,
unsigned long min, unsigned long max,
unsigned long count)
{
const struct subordinate_range *range;
unsigned long low, high;
/* When given invalid parameters fail */
if ((count == 0) || (max < min))
goto fail;
/* Sort by range then by owner */
commonio_sort (db, subordinate_range_cmp);
commonio_rewind(db);
low = min;
while ((range = commonio_next(db)) != NULL) {
unsigned long first = range->start;
unsigned long last = first + range->count - 1;
/* Find the top end of the hole before this range */
high = first;
/* Don't allocate IDs after max (included) */
if (high > max + 1) {
high = max + 1;
}
/* Is the hole before this range large enough? */
if ((high > low) && ((high - low) >= count))
return low;
/* Compute the low end of the next hole */
if (low < (last + 1))
low = last + 1;
if (low > max)
goto fail;
}
/* Is the remaining unclaimed area large enough? */
if (((max - low) + 1) >= count)
return low;
fail:
return ULONG_MAX;
}
/*
* add_range: add a subuid range to an owning uid's list of authorized
* subuids.
* @db: database to which to add
* @owner: uid which owns the subuid
* @start: the first uid in the owned range
* @count: the number of uids in the range
*
* Return 1 if the range is already present or on succcess. On error
* return 0 and set errno appropriately.
*/
static int add_range(struct commonio_db *db,
const char *owner, unsigned long start, unsigned long count)
{
struct subordinate_range range;
range.owner = owner;
range.start = start;
range.count = count;
/* See if the range is already present */
if (have_range(db, owner, start, count))
return 1;
/* Otherwise append the range */
return commonio_append(db, &range);
}
/*
* remove_range: remove a range of subuids from an owning uid's list
* of authorized subuids.
* @db: database to work on
* @owner: owning uid whose range is being removed
* @start: start of the range to be removed
* @count: number of uids in the range.
*
* Returns 0 on failure, 1 on success. Failure means that we needed to
* create a new range to represent the new limits, and failed doing so.
*/
static int remove_range (struct commonio_db *db,
const char *owner,
unsigned long start, unsigned long count)
{
struct commonio_entry *ent;
unsigned long end;
if (count == 0) {
return 1;
}
end = start + count - 1;
for (ent = db->head; NULL != ent; ent = ent->next) {
struct subordinate_range *range = ent->eptr;
unsigned long first;
unsigned long last;
/* Skip unparsed entries */
if (NULL == range) {
continue;
}
first = range->start;
last = first + range->count - 1;
/* Skip entries with a different owner */
if (0 != strcmp (range->owner, owner)) {
continue;
}
/* Skip entries outside of the range to remove */
if ((end < first) || (start > last)) {
continue;
}
if (start <= first) {
if (end >= last) {
/* to be removed: [start, end]
* range: [first, last] */
/* entry completely contained in the
* range to remove */
commonio_del_entry (db, ent);
} else {
/* to be removed: [start, end]
* range: [first, last] */
/* Remove only the start of the entry */
range->start = end + 1;
range->count = (last - range->start) + 1;
ent->changed = true;
db->changed = true;
}
} else {
if (end >= last) {
/* to be removed: [start, end]
* range: [first, last] */
/* Remove only the end of the entry */
range->count = start - range->start;
ent->changed = true;
db->changed = true;
} else {
/* to be removed: [start, end]
* range: [first, last] */
/* Remove the middle of the range
* This requires to create a new range */
struct subordinate_range tail;
tail.owner = range->owner;
tail.start = end + 1;
tail.count = (last - tail.start) + 1;
if (commonio_append (db, &tail) == 0) {
return 0;
}
range->count = start - range->start;
ent->changed = true;
db->changed = true;
}
}
}
return 1;
}
static struct commonio_db subordinate_uid_db = {
"/etc/subuid", /* filename */
&subordinate_ops, /* ops */
NULL, /* fp */
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
false, /* changed */
false, /* isopen */
false, /* locked */
false /* readonly */
};
int sub_uid_setdbname (const char *filename)
{
return commonio_setname (&subordinate_uid_db, filename);
}
/*@observer@*/const char *sub_uid_dbname (void)
{
return subordinate_uid_db.filename;
}
bool sub_uid_file_present (void)
{
return commonio_present (&subordinate_uid_db);
}
int sub_uid_lock (void)
{
return commonio_lock (&subordinate_uid_db);
}
int sub_uid_open (int mode)
{
return commonio_open (&subordinate_uid_db, mode);
}
bool sub_uid_assigned(const char *owner)
{
return range_exists (&subordinate_uid_db, owner);
}
bool have_sub_uids(const char *owner, uid_t start, unsigned long count)
{
return have_range (&subordinate_uid_db, owner, start, count);
}
int sub_uid_add (const char *owner, uid_t start, unsigned long count)
{
return add_range (&subordinate_uid_db, owner, start, count);
}
int sub_uid_remove (const char *owner, uid_t start, unsigned long count)
{
return remove_range (&subordinate_uid_db, owner, start, count);
}
int sub_uid_close (void)
{
return commonio_close (&subordinate_uid_db);
}
int sub_uid_unlock (void)
{
return commonio_unlock (&subordinate_uid_db);
}
uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count)
{
unsigned long start;
start = find_free_range (&subordinate_uid_db, min, max, count);
return start == ULONG_MAX ? (uid_t) -1 : start;
}
static struct commonio_db subordinate_gid_db = {
"/etc/subgid", /* filename */
&subordinate_ops, /* ops */
NULL, /* fp */
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
false, /* changed */
false, /* isopen */
false, /* locked */
false /* readonly */
};
int sub_gid_setdbname (const char *filename)
{
return commonio_setname (&subordinate_gid_db, filename);
}
/*@observer@*/const char *sub_gid_dbname (void)
{
return subordinate_gid_db.filename;
}
bool sub_gid_file_present (void)
{
return commonio_present (&subordinate_gid_db);
}
int sub_gid_lock (void)
{
return commonio_lock (&subordinate_gid_db);
}
int sub_gid_open (int mode)
{
return commonio_open (&subordinate_gid_db, mode);
}
bool have_sub_gids(const char *owner, gid_t start, unsigned long count)
{
return have_range(&subordinate_gid_db, owner, start, count);
}
bool sub_gid_assigned(const char *owner)
{
return range_exists (&subordinate_gid_db, owner);
}
int sub_gid_add (const char *owner, gid_t start, unsigned long count)
{
return add_range (&subordinate_gid_db, owner, start, count);
}
int sub_gid_remove (const char *owner, gid_t start, unsigned long count)
{
return remove_range (&subordinate_gid_db, owner, start, count);
}
int sub_gid_close (void)
{
return commonio_close (&subordinate_gid_db);
}
int sub_gid_unlock (void)
{
return commonio_unlock (&subordinate_gid_db);
}
gid_t sub_gid_find_free_range(gid_t min, gid_t max, unsigned long count)
{
unsigned long start;
start = find_free_range (&subordinate_gid_db, min, max, count);
return start == ULONG_MAX ? (gid_t) -1 : start;
}
#else /* !ENABLE_SUBIDS */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !ENABLE_SUBIDS */
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2012- Eric W. Biederman
*/
#ifndef _SUBORDINATEIO_H
#define _SUBORDINATEIO_H
#include <config.h>
#ifdef ENABLE_SUBIDS
#include <sys/types.h>
extern int sub_uid_close(void);
extern bool have_sub_uids(const char *owner, uid_t start, unsigned long count);
extern bool sub_uid_file_present (void);
extern bool sub_uid_assigned(const char *owner);
extern int sub_uid_lock (void);
extern int sub_uid_setdbname (const char *filename);
extern /*@observer@*/const char *sub_uid_dbname (void);
extern int sub_uid_open (int mode);
extern int sub_uid_unlock (void);
extern int sub_uid_add (const char *owner, uid_t start, unsigned long count);
extern int sub_uid_remove (const char *owner, uid_t start, unsigned long count);
extern uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count);
extern int sub_gid_close(void);
extern bool have_sub_gids(const char *owner, gid_t start, unsigned long count);
extern bool sub_gid_file_present (void);
extern bool sub_gid_assigned(const char *owner);
extern int sub_gid_lock (void);
extern int sub_gid_setdbname (const char *filename);
extern /*@observer@*/const char *sub_gid_dbname (void);
extern int sub_gid_open (int mode);
extern int sub_gid_unlock (void);
extern int sub_gid_add (const char *owner, gid_t start, unsigned long count);
extern int sub_gid_remove (const char *owner, gid_t start, unsigned long count);
extern uid_t sub_gid_find_free_range(gid_t min, gid_t max, unsigned long count);
#endif /* ENABLE_SUBIDS */
#endif
+613
View File
@@ -0,0 +1,613 @@
/*
* Copyright (c) 2001 Rafal Wojtczuk, Solar Designer
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <tcb.h>
#include <unistd.h>
#include "config.h"
#include "defines.h"
#include "prototypes.h"
#include "getdef.h"
#include "shadowio.h"
#include "tcbfuncs.h"
#define SHADOWTCB_HASH_BY 1000
#define SHADOWTCB_LOCK_SUFFIX ".lock"
static /*@null@*//*@only@*/char *stored_tcb_user = NULL;
shadowtcb_status shadowtcb_drop_priv (void)
{
if (!getdef_bool ("USE_TCB")) {
return SHADOWTCB_SUCCESS;
}
if (NULL != stored_tcb_user) {
if (tcb_drop_priv (stored_tcb_user) == 0) {
return SHADOWTCB_SUCCESS;
}
}
return SHADOWTCB_FAILURE;
}
shadowtcb_status shadowtcb_gain_priv (void)
{
if (!getdef_bool ("USE_TCB")) {
return SHADOWTCB_SUCCESS;
}
return (tcb_gain_priv () == 0) ? SHADOWTCB_SUCCESS : SHADOWTCB_FAILURE;
}
/* In case something goes wrong, we return immediately, not polluting the
* code with free(). All errors are fatal, so the application is expected
* to exit soon.
*/
#define OUT_OF_MEMORY do { \
fprintf (stderr, _("%s: out of memory\n"), Prog); \
(void) fflush (stderr); \
} while (false)
/* Returns user's tcb directory path relative to TCB_DIR. */
static /*@null@*/ char *shadowtcb_path_rel (const char *name, uid_t uid)
{
char *ret;
if (!getdef_bool ("TCB_SYMLINKS") || uid < SHADOWTCB_HASH_BY) {
if (asprintf (&ret, "%s", name) == -1) {
OUT_OF_MEMORY;
return NULL;
}
} else if (uid < SHADOWTCB_HASH_BY * SHADOWTCB_HASH_BY) {
if (asprintf (&ret, ":%dK/%s",
uid / SHADOWTCB_HASH_BY, name) == -1) {
OUT_OF_MEMORY;
return NULL;
}
} else {
if (asprintf (&ret, ":%dM/:%dK/%s",
uid / (SHADOWTCB_HASH_BY * SHADOWTCB_HASH_BY),
(uid % (SHADOWTCB_HASH_BY * SHADOWTCB_HASH_BY)) / SHADOWTCB_HASH_BY,
name) == -1) {
OUT_OF_MEMORY;
return NULL;
}
}
return ret;
}
static /*@null@*/ char *shadowtcb_path_rel_existing (const char *name)
{
char *path, *rval;
struct stat st;
char link[8192];
ssize_t ret;
if (asprintf (&path, TCB_DIR "/%s", name) == -1) {
OUT_OF_MEMORY;
return NULL;
}
if (lstat (path, &st) != 0) {
fprintf (stderr,
_("%s: Cannot stat %s: %s\n"),
Prog, path, strerror (errno));
free (path);
return NULL;
}
if (S_ISDIR (st.st_mode)) {
free (path);
rval = strdup (name);
if (NULL == rval) {
OUT_OF_MEMORY;
return NULL;
}
return rval;
}
if (!S_ISLNK (st.st_mode)) {
fprintf (stderr,
_("%s: %s is neither a directory, nor a symlink.\n"),
Prog, path);
free (path);
return NULL;
}
ret = readlink (path, link, sizeof (link) - 1);
if (-1 == ret) {
fprintf (stderr,
_("%s: Cannot read symbolic link %s: %s\n"),
Prog, path, strerror (errno));
free (path);
return NULL;
}
free (path);
if ((size_t)ret >= sizeof(link) - 1) {
link[sizeof(link) - 1] = '\0';
fprintf (stderr,
_("%s: Suspiciously long symlink: %s\n"),
Prog, link);
return NULL;
}
link[(size_t)ret] = '\0';
rval = strdup (link);
if (NULL == rval) {
OUT_OF_MEMORY;
return NULL;
}
return rval;
}
static /*@null@*/ char *shadowtcb_path (const char *name, uid_t uid)
{
char *ret, *rel;
rel = shadowtcb_path_rel (name, uid);
if (NULL == rel) {
return NULL;
}
if (asprintf (&ret, TCB_DIR "/%s", rel) == -1) {
OUT_OF_MEMORY;
free (rel);
return NULL;
}
free (rel);
return ret;
}
static /*@null@*/ char *shadowtcb_path_existing (const char *name)
{
char *ret, *rel;
rel = shadowtcb_path_rel_existing (name);
if (NULL == rel) {
return NULL;
}
if (asprintf (&ret, TCB_DIR "/%s", rel) == -1) {
OUT_OF_MEMORY;
free (rel);
return NULL;
}
free (rel);
return ret;
}
static shadowtcb_status mkdir_leading (const char *name, uid_t uid)
{
char *ind, *dir, *ptr, *path = shadowtcb_path_rel (name, uid);
struct stat st;
if (NULL == path) {
return SHADOWTCB_FAILURE;
}
ptr = path;
if (stat (TCB_DIR, &st) != 0) {
fprintf (stderr,
_("%s: Cannot stat %s: %s\n"),
Prog, TCB_DIR, strerror (errno));
goto out_free_path;
}
while ((ind = strchr (ptr, '/'))) {
*ind = '\0';
if (asprintf (&dir, TCB_DIR "/%s", path) == -1) {
OUT_OF_MEMORY;
return SHADOWTCB_FAILURE;
}
if ((mkdir (dir, 0700) != 0) && (errno != EEXIST)) {
fprintf (stderr,
_("%s: Cannot create directory %s: %s\n"),
Prog, dir, strerror (errno));
goto out_free_dir;
}
if (chown (dir, 0, st.st_gid) != 0) {
fprintf (stderr,
_("%s: Cannot change owner of %s: %s\n"),
Prog, dir, strerror (errno));
goto out_free_dir;
}
if (chmod (dir, 0711) != 0) {
fprintf (stderr,
_("%s: Cannot change mode of %s: %s\n"),
Prog, dir, strerror (errno));
goto out_free_dir;
}
free (dir);
*ind = '/';
ptr = ind + 1;
}
free (path);
return SHADOWTCB_SUCCESS;
out_free_dir:
free (dir);
out_free_path:
free (path);
return SHADOWTCB_FAILURE;
}
static shadowtcb_status unlink_suffs (const char *user)
{
static char *suffs[] = { "+", "-", SHADOWTCB_LOCK_SUFFIX };
char *tmp;
int i;
for (i = 0; i < 3; i++) {
if (asprintf (&tmp, TCB_FMT "%s", user, suffs[i]) == -1) {
OUT_OF_MEMORY;
return SHADOWTCB_FAILURE;
}
if ((unlink (tmp) != 0) && (errno != ENOENT)) {
fprintf (stderr,
_("%s: unlink: %s: %s\n"),
Prog, tmp, strerror (errno));
free (tmp);
return SHADOWTCB_FAILURE;
}
free (tmp);
}
return SHADOWTCB_SUCCESS;
}
/* path should be a relative existing tcb directory */
static shadowtcb_status rmdir_leading (char *path)
{
char *ind, *dir;
shadowtcb_status ret = SHADOWTCB_SUCCESS;
while ((ind = strrchr (path, '/'))) {
*ind = '\0';
if (asprintf (&dir, TCB_DIR "/%s", path) == -1) {
OUT_OF_MEMORY;
return SHADOWTCB_FAILURE;
}
if (rmdir (dir) != 0) {
if (errno != ENOTEMPTY) {
fprintf (stderr,
_("%s: Cannot remove directory %s: %s\n"),
Prog, dir, strerror (errno));
ret = SHADOWTCB_FAILURE;
}
free (dir);
break;
}
free (dir);
}
return ret;
}
static shadowtcb_status move_dir (const char *user_newname, uid_t user_newid)
{
char *olddir = NULL, *newdir = NULL;
char *real_old_dir = NULL, *real_new_dir = NULL;
char *real_old_dir_rel = NULL, *real_new_dir_rel = NULL;
uid_t old_uid, the_newid;
struct stat oldmode;
shadowtcb_status ret = SHADOWTCB_FAILURE;
if (NULL == stored_tcb_user) {
return SHADOWTCB_FAILURE;
}
if (asprintf (&olddir, TCB_DIR "/%s", stored_tcb_user) == -1) {
goto out_free_nomem;
}
if (stat (olddir, &oldmode) != 0) {
fprintf (stderr,
_("%s: Cannot stat %s: %s\n"),
Prog, olddir, strerror (errno));
goto out_free;
}
old_uid = oldmode.st_uid;
the_newid = (user_newid == -1) ? old_uid : user_newid;
real_old_dir = shadowtcb_path_existing (stored_tcb_user);
if (NULL == real_old_dir) {
goto out_free;
}
real_new_dir = shadowtcb_path (user_newname, the_newid);
if (NULL == real_new_dir) {
goto out_free;
}
if (strcmp (real_old_dir, real_new_dir) == 0) {
ret = SHADOWTCB_SUCCESS;
goto out_free;
}
real_old_dir_rel = shadowtcb_path_rel_existing (stored_tcb_user);
if (NULL == real_old_dir_rel) {
goto out_free;
}
if (mkdir_leading (user_newname, the_newid) == SHADOWTCB_FAILURE) {
goto out_free;
}
if (rename (real_old_dir, real_new_dir) != 0) {
fprintf (stderr,
_("%s: Cannot rename %s to %s: %s\n"),
Prog, real_old_dir, real_new_dir, strerror (errno));
goto out_free;
}
if (rmdir_leading (real_old_dir_rel) == SHADOWTCB_FAILURE) {
goto out_free;
}
if ((unlink (olddir) != 0) && (errno != ENOENT)) {
fprintf (stderr,
_("%s: Cannot remove %s: %s\n"),
Prog, olddir, strerror (errno));
goto out_free;
}
if (asprintf (&newdir, TCB_DIR "/%s", user_newname) == -1) {
goto out_free_nomem;
}
real_new_dir_rel = shadowtcb_path_rel (user_newname, the_newid);
if (NULL == real_new_dir_rel) {
goto out_free;
}
if ( (strcmp (real_new_dir, newdir) != 0)
&& (symlink (real_new_dir_rel, newdir) != 0)) {
fprintf (stderr,
_("%s: Cannot create symbolic link %s: %s\n"),
Prog, real_new_dir_rel, strerror (errno));
goto out_free;
}
ret = SHADOWTCB_SUCCESS;
goto out_free;
out_free_nomem:
OUT_OF_MEMORY;
out_free:
free (olddir);
free (newdir);
free (real_old_dir);
free (real_new_dir);
free (real_old_dir_rel);
free (real_new_dir_rel);
return ret;
}
shadowtcb_status shadowtcb_set_user (const char* name)
{
char *buf;
shadowtcb_status retval;
if (!getdef_bool ("USE_TCB")) {
return SHADOWTCB_SUCCESS;
}
if (NULL != stored_tcb_user) {
free (stored_tcb_user);
}
stored_tcb_user = strdup (name);
if (NULL == stored_tcb_user) {
OUT_OF_MEMORY;
return SHADOWTCB_FAILURE;
}
if (asprintf (&buf, TCB_FMT, name) == -1) {
OUT_OF_MEMORY;
return SHADOWTCB_FAILURE;
}
retval = (spw_setdbname (buf) != 0) ? SHADOWTCB_SUCCESS : SHADOWTCB_FAILURE;
free (buf);
return retval;
}
/* tcb directory must be empty before shadowtcb_remove is called. */
shadowtcb_status shadowtcb_remove (const char *name)
{
shadowtcb_status ret = SHADOWTCB_SUCCESS;
char *path = shadowtcb_path_existing (name);
char *rel = shadowtcb_path_rel_existing (name);
if ((NULL == path) || (NULL == rel) || (rmdir (path) != 0)) {
return SHADOWTCB_FAILURE;
}
if (rmdir_leading (rel) == SHADOWTCB_FAILURE) {
return SHADOWTCB_FAILURE;
}
free (path);
free (rel);
if (asprintf (&path, TCB_DIR "/%s", name) == -1) {
OUT_OF_MEMORY;
return SHADOWTCB_FAILURE;
}
if ((unlink (path) != 0) && (errno != ENOENT)) {
ret = SHADOWTCB_FAILURE;
}
free (path);
return ret;
}
shadowtcb_status shadowtcb_move (/*@NULL@*/const char *user_newname, uid_t user_newid)
{
struct stat dirmode, filemode;
char *tcbdir, *shadow;
shadowtcb_status ret = SHADOWTCB_FAILURE;
if (!getdef_bool ("USE_TCB")) {
return SHADOWTCB_SUCCESS;
}
if (NULL == stored_tcb_user) {
return SHADOWTCB_FAILURE;
}
if (NULL == user_newname) {
user_newname = stored_tcb_user;
}
if (move_dir (user_newname, user_newid) == SHADOWTCB_FAILURE) {
return SHADOWTCB_FAILURE;
}
if (-1 == user_newid) {
return SHADOWTCB_SUCCESS;
}
if ( (asprintf (&tcbdir, TCB_DIR "/%s", user_newname) == -1)
|| (asprintf (&shadow, TCB_FMT, user_newname) == -1)) {
OUT_OF_MEMORY;
return SHADOWTCB_FAILURE;
}
if (stat (tcbdir, &dirmode) != 0) {
fprintf (stderr,
_("%s: Cannot stat %s: %s\n"),
Prog, tcbdir, strerror (errno));
goto out_free;
}
if (chown (tcbdir, 0, 0) != 0) {
fprintf (stderr,
_("%s: Cannot change owners of %s: %s\n"),
Prog, tcbdir, strerror (errno));
goto out_free;
}
if (chmod (tcbdir, 0700) != 0) {
fprintf (stderr,
_("%s: Cannot change mode of %s: %s\n"),
Prog, tcbdir, strerror (errno));
goto out_free;
}
if (lstat (shadow, &filemode) != 0) {
if (errno != ENOENT) {
fprintf (stderr,
_("%s: Cannot lstat %s: %s\n"),
Prog, shadow, strerror (errno));
goto out_free;
}
fprintf (stderr,
_("%s: Warning, user %s has no tcb shadow file.\n"),
Prog, user_newname);
} else {
if (!S_ISREG (filemode.st_mode) ||
filemode.st_nlink != 1) {
fprintf (stderr,
_("%s: Emergency: %s's tcb shadow is not a "
"regular file with st_nlink=1.\n"
"The account is left locked.\n"),
Prog, user_newname);
goto out_free;
}
if (chown (shadow, user_newid, filemode.st_gid) != 0) {
fprintf (stderr,
_("%s: Cannot change owner of %s: %s\n"),
Prog, shadow, strerror (errno));
goto out_free;
}
if (chmod (shadow, filemode.st_mode & 07777) != 0) {
fprintf (stderr,
_("%s: Cannot change mode of %s: %s\n"),
Prog, shadow, strerror (errno));
goto out_free;
}
}
if (unlink_suffs (user_newname) == SHADOWTCB_FAILURE) {
goto out_free;
}
if (chown (tcbdir, user_newid, dirmode.st_gid) != 0) {
fprintf (stderr,
_("%s: Cannot change owner of %s: %s\n"),
Prog, tcbdir, strerror (errno));
goto out_free;
}
ret = SHADOWTCB_SUCCESS;
out_free:
free (tcbdir);
free (shadow);
return ret;
}
shadowtcb_status shadowtcb_create (const char *name, uid_t uid)
{
char *dir, *shadow;
struct stat tcbdir_stat;
gid_t shadowgid, authgid;
struct group *gr;
int fd;
shadowtcb_status ret = SHADOWTCB_FAILURE;
if (!getdef_bool ("USE_TCB")) {
return SHADOWTCB_SUCCESS;
}
if (stat (TCB_DIR, &tcbdir_stat) != 0) {
fprintf (stderr,
_("%s: Cannot stat %s: %s\n"),
Prog, TCB_DIR, strerror (errno));
return SHADOWTCB_FAILURE;
}
shadowgid = tcbdir_stat.st_gid;
authgid = shadowgid;
if (getdef_bool ("TCB_AUTH_GROUP")) {
gr = getgrnam ("auth");
if (NULL != gr) {
authgid = gr->gr_gid;
}
}
if ( (asprintf (&dir, TCB_DIR "/%s", name) == -1)
|| (asprintf (&shadow, TCB_FMT, name) == -1)) {
OUT_OF_MEMORY;
return SHADOWTCB_FAILURE;
}
if (mkdir (dir, 0700) != 0) {
fprintf (stderr,
_("%s: mkdir: %s: %s\n"),
Prog, dir, strerror (errno));
goto out_free;
}
fd = open (shadow, O_RDWR | O_CREAT | O_TRUNC, 0600);
if (fd < 0) {
fprintf (stderr,
_("%s: Cannot open %s: %s\n"),
Prog, shadow, strerror (errno));
goto out_free;
}
close (fd);
if (chown (shadow, 0, authgid) != 0) {
fprintf (stderr,
_("%s: Cannot change owner of %s: %s\n"),
Prog, shadow, strerror (errno));
goto out_free;
}
if (chmod (shadow, (mode_t) ((authgid == shadowgid) ? 0600 : 0640)) != 0) {
fprintf (stderr,
_("%s: Cannot change mode of %s: %s\n"),
Prog, shadow, strerror (errno));
goto out_free;
}
if (chown (dir, 0, authgid) != 0) {
fprintf (stderr,
_("%s: Cannot change owner of %s: %s\n"),
Prog, dir, strerror (errno));
goto out_free;
}
if (chmod (dir, (mode_t) ((authgid == shadowgid) ? 02700 : 02710)) != 0) {
fprintf (stderr,
_("%s: Cannot change mode of %s: %s\n"),
Prog, dir, strerror (errno));
goto out_free;
}
if ( (shadowtcb_set_user (name) == SHADOWTCB_FAILURE)
|| (shadowtcb_move (NULL, uid) == SHADOWTCB_FAILURE)) {
goto out_free;
}
ret = SHADOWTCB_SUCCESS;
out_free:
free (dir);
free (shadow);
return ret;
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef _TCBFUNCS_H
#define _TCBFUNCS_H
#include <sys/types.h>
typedef enum {
SHADOWTCB_FAILURE = 0,
SHADOWTCB_SUCCESS = 1
} shadowtcb_status;
extern shadowtcb_status shadowtcb_drop_priv (void);
extern shadowtcb_status shadowtcb_gain_priv (void);
extern shadowtcb_status shadowtcb_set_user (const char *name);
extern shadowtcb_status shadowtcb_remove (const char *name);
extern shadowtcb_status shadowtcb_move (/*@null@*/const char *user_newname,
uid_t user_newid);
extern shadowtcb_status shadowtcb_create (const char *name, uid_t uid);
#endif
-19
View File
@@ -88,25 +88,6 @@ struct utmp *getutent (void)
return &utmp_buf; return &utmp_buf;
} }
/*
* getutline - get the utmp entry matching ut_line
*/
struct utmp *getutline (const struct utmp *utent)
{
struct utmp save;
struct utmp *new;
save = *utent;
while (new = getutent ())
if (strncmp (new->ut_line, save.ut_line, sizeof new->ut_line))
continue;
else
return new;
return (struct utmp *) 0;
}
#else #else
extern int errno; /* warning: ANSI C forbids an empty source file */ extern int errno; /* warning: ANSI C forbids an empty source file */
#endif #endif
+6 -2
View File
@@ -23,14 +23,17 @@ libmisc_a_SOURCES = \
env.c \ env.c \
failure.c \ failure.c \
failure.h \ failure.h \
fields.c \
find_new_gid.c \ find_new_gid.c \
find_new_uid.c \ find_new_uid.c \
find_new_sub_gids.c \
find_new_sub_uids.c \
getdate.h \ getdate.h \
getdate.y \ getdate.y \
getgr_nam_gid.c \ getgr_nam_gid.c \
getrange.c \ getrange.c \
hushed.c \ hushed.c \
idmapping.h \
idmapping.c \
isexpired.c \ isexpired.c \
limits.c \ limits.c \
list.c log.c \ list.c log.c \
@@ -44,12 +47,13 @@ libmisc_a_SOURCES = \
pwd2spwd.c \ pwd2spwd.c \
pwdcheck.c \ pwdcheck.c \
pwd_init.c \ pwd_init.c \
remove_tree.c \
rlogin.c \ rlogin.c \
root_flag.c \
salt.c \ salt.c \
setugid.c \ setugid.c \
setupenv.c \ setupenv.c \
shell.c \ shell.c \
system.c \
strtoday.c \ strtoday.c \
sub.c \ sub.c \
sulog.c \ sulog.c \
+5 -1
View File
@@ -71,7 +71,11 @@ int add_groups (const char *list)
return -1; return -1;
} }
ngroups = getgroups (i, grouplist); ngroups = getgroups (i, grouplist);
if ((-1 == ngroups) || (i > (size_t)ngroups)) { if ( ( (-1 == ngroups)
&& (EINVAL != errno))
|| (i > (size_t)ngroups)) {
/* Unexpected failure of getgroups or successful
* reception of the groups */
break; break;
} }
/* not enough room, so try allocating a larger buffer */ /* not enough room, so try allocating a larger buffer */
+2 -2
View File
@@ -76,7 +76,7 @@ void audit_help_open (void)
* id - uid or gid that the operation is being performed on. This is used * id - uid or gid that the operation is being performed on. This is used
* only when user is NULL. * only when user is NULL.
*/ */
void audit_logger (int type, const char *pgname, const char *op, void audit_logger (int type, unused const char *pgname, const char *op,
const char *name, unsigned int id, const char *name, unsigned int id,
shadow_audit_result result) shadow_audit_result result)
{ {
@@ -84,7 +84,7 @@ void audit_logger (int type, const char *pgname, const char *op,
return; return;
} else { } else {
audit_log_acct_message (audit_fd, type, NULL, op, name, id, audit_log_acct_message (audit_fd, type, NULL, op, name, id,
NULL, NULL, NULL, (int) result); NULL, NULL, NULL, (int) result);
} }
} }
+2 -2
View File
@@ -42,9 +42,9 @@
#include "defines.h" #include "defines.h"
#include "prototypes.h" #include "prototypes.h"
char *Basename (char *str) /*@observer@*/const char *Basename (const char *str)
{ {
char *cp = strrchr (str, '/'); char *cp = strrchr (str, '/');
return cp ? cp + 1 : str; return (NULL != cp) ? cp + 1 : str;
} }
+89 -24
View File
@@ -2,6 +2,7 @@
* Copyright (c) 1992 - 1993, Julianne Frances Haugh * Copyright (c) 1992 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2010 - , Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -44,59 +45,92 @@
* *
* chown_dir() walks a directory tree and changes the ownership * chown_dir() walks a directory tree and changes the ownership
* of all files owned by the provided user ID. * of all files owned by the provided user ID.
*
* Only files owned (resp. group-owned) by old_uid (resp. by old_gid)
* will have their ownership (resp. group-ownership) modified, unless
* old_uid (resp. old_gid) is set to -1.
*
* new_uid and new_gid can be set to -1 to indicate that no owner or
* group-owner shall be changed.
*/ */
int int chown_tree (const char *root,
chown_tree (const char *root, uid_t old_uid, uid_t new_uid, gid_t old_gid, uid_t old_uid,
gid_t new_gid) uid_t new_uid,
gid_t old_gid,
gid_t new_gid)
{ {
char new_name[1024]; char *new_name;
size_t new_name_len;
int rc = 0; int rc = 0;
struct DIRECT *ent; struct DIRECT *ent;
struct stat sb; struct stat sb;
DIR *dir; DIR *dir;
new_name = malloc (1024);
if (NULL == new_name) {
return -1;
}
new_name_len = 1024;
/* /*
* Make certain the directory exists. This routine is called * Make certain the directory exists. This routine is called
* directory by the invoker, or recursively. * directly by the invoker, or recursively.
*/ */
if (access (root, F_OK) != 0) if (access (root, F_OK) != 0) {
free (new_name);
return -1; return -1;
}
/* /*
* Open the directory and read each entry. Every entry is tested * Open the directory and read each entry. Every entry is tested
* to see if it is a directory, and if so this routine is called * to see if it is a directory, and if so this routine is called
* recursively. If not, it is checked to see if it is owned by * recursively. If not, it is checked to see if an ownership
* old user ID. * shall be changed.
*/ */
if (!(dir = opendir (root))) dir = opendir (root);
if (NULL == dir) {
free (new_name);
return -1; return -1;
}
while ((ent = readdir (dir))) { while ((ent = readdir (dir))) {
size_t ent_name_len;
uid_t tmpuid = (uid_t) -1;
gid_t tmpgid = (gid_t) -1;
/* /*
* Skip the "." and ".." entries * Skip the "." and ".." entries
*/ */
if (strcmp (ent->d_name, ".") == 0 || if ( (strcmp (ent->d_name, ".") == 0)
strcmp (ent->d_name, "..") == 0) || (strcmp (ent->d_name, "..") == 0)) {
continue; continue;
}
/* /*
* Make the filename for both the source and the * Make the filename for both the source and the
* destination files. * destination files.
*/ */
if (strlen (root) + strlen (ent->d_name) + 2 > sizeof new_name) ent_name_len = strlen (root) + strlen (ent->d_name) + 2;
break; if (ent_name_len > new_name_len) {
/*@only@*/char *tmp = realloc (new_name, ent_name_len);
if (NULL == tmp) {
rc = -1;
break;
}
new_name = tmp;
new_name_len = ent_name_len;
}
snprintf (new_name, sizeof new_name, "%s/%s", root, (void) snprintf (new_name, new_name_len, "%s/%s", root, ent->d_name);
ent->d_name);
/* Don't follow symbolic links! */ /* Don't follow symbolic links! */
if (LSTAT (new_name, &sb) == -1) if (LSTAT (new_name, &sb) == -1) {
continue; continue;
}
if (S_ISDIR (sb.st_mode) && !S_ISLNK (sb.st_mode)) { if (S_ISDIR (sb.st_mode) && !S_ISLNK (sb.st_mode)) {
@@ -112,25 +146,56 @@ chown_tree (const char *root, uid_t old_uid, uid_t new_uid, gid_t old_gid,
} }
#ifndef HAVE_LCHOWN #ifndef HAVE_LCHOWN
/* don't use chown (follows symbolic links!) */ /* don't use chown (follows symbolic links!) */
if (S_ISLNK (sb.st_mode)) if (S_ISLNK (sb.st_mode)) {
continue; continue;
}
#endif #endif
if (sb.st_uid == old_uid) /*
LCHOWN (new_name, new_uid, * By default, the IDs are not changed (-1).
sb.st_gid == old_gid ? new_gid : sb.st_gid); *
* If the file is not owned by the user, the owner is not
* changed.
*
* If the file is not group-owned by the group, the
* group-owner is not changed.
*/
if (((uid_t) -1 == old_uid) || (sb.st_uid == old_uid)) {
tmpuid = new_uid;
}
if (((gid_t) -1 == old_gid) || (sb.st_gid == old_gid)) {
tmpgid = new_gid;
}
if (((uid_t) -1 != tmpuid) || ((gid_t) -1 != tmpgid)) {
rc = LCHOWN (new_name, tmpuid, tmpgid);
if (0 != rc) {
break;
}
}
} }
free (new_name);
(void) closedir (dir); (void) closedir (dir);
/* /*
* Now do the root of the tree * Now do the root of the tree
*/ */
if (stat (root, &sb) == 0) { if ((0 == rc) && (stat (root, &sb) == 0)) {
if (sb.st_uid == old_uid) { uid_t tmpuid = (uid_t) -1;
LCHOWN (root, new_uid, gid_t tmpgid = (gid_t) -1;
sb.st_gid == old_gid ? new_gid : sb.st_gid); if (((uid_t) -1 == old_uid) || (sb.st_uid == old_uid)) {
tmpuid = new_uid;
} }
if (((gid_t) -1 == old_gid) || (sb.st_gid == old_gid)) {
tmpgid = new_gid;
}
if (((uid_t) -1 != tmpuid) || ((gid_t) -1 != tmpgid)) {
rc = LCHOWN (root, tmpuid, tmpgid);
}
} else {
rc = -1;
} }
return rc; return rc;
} }
+1 -1
View File
@@ -72,7 +72,7 @@ void chown_tty (const struct passwd *info)
*/ */
if ( (fchown (STDIN_FILENO, info->pw_uid, gid) != 0) if ( (fchown (STDIN_FILENO, info->pw_uid, gid) != 0)
|| (fchmod (STDIN_FILENO, getdef_num ("TTYPERM", 0600)) != 0)) { || (fchmod (STDIN_FILENO, (mode_t)getdef_num ("TTYPERM", 0600)) != 0)) {
int err = errno; int err = errno;
fprintf (stderr, fprintf (stderr,
+21 -5
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008 , Nicolas François * Copyright (c) 2008 - 2011, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -38,8 +38,12 @@
* The cleanup_functions stack. * The cleanup_functions stack.
*/ */
#define CLEANUP_FUNCTIONS 10 #define CLEANUP_FUNCTIONS 10
typedef /*@null@*/void * parg_t;
static cleanup_function cleanup_functions[CLEANUP_FUNCTIONS]; static cleanup_function cleanup_functions[CLEANUP_FUNCTIONS];
static void * cleanup_function_args[CLEANUP_FUNCTIONS]; static parg_t cleanup_function_args[CLEANUP_FUNCTIONS];
static pid_t cleanup_pid = 0;
/* /*
* - Cleanup functions shall not fail. * - Cleanup functions shall not fail.
@@ -53,6 +57,9 @@ static void * cleanup_function_args[CLEANUP_FUNCTIONS];
/* /*
* do_cleanups - perform the actions stored in the cleanup_functions stack. * do_cleanups - perform the actions stored in the cleanup_functions stack.
* *
* Cleanup action are not executed on exit of the processes started by the
* parent (first caller of add_cleanup).
*
* It is intended to be used as: * It is intended to be used as:
* atexit (do_cleanups); * atexit (do_cleanups);
*/ */
@@ -63,6 +70,10 @@ void do_cleanups (void)
/* Make sure there were no overflow */ /* Make sure there were no overflow */
assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-1]); assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-1]);
if (getpid () != cleanup_pid) {
return;
}
i = CLEANUP_FUNCTIONS; i = CLEANUP_FUNCTIONS;
do { do {
i--; i--;
@@ -75,13 +86,17 @@ void do_cleanups (void)
/* /*
* add_cleanup - Add a cleanup_function to the cleanup_functions stack. * add_cleanup - Add a cleanup_function to the cleanup_functions stack.
*/ */
void add_cleanup (cleanup_function pcf, /*@null@*/void *arg) void add_cleanup (/*@notnull@*/cleanup_function pcf, /*@null@*/void *arg)
{ {
unsigned int i; unsigned int i;
assert (NULL != pcf); assert (NULL != pcf);
assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-2]); assert (NULL == cleanup_functions[CLEANUP_FUNCTIONS-2]);
if (0 == cleanup_pid) {
cleanup_pid = getpid ();
}
/* Add the cleanup_function at the end of the stack */ /* Add the cleanup_function at the end of the stack */
for (i=0; NULL != cleanup_functions[i]; i++); for (i=0; NULL != cleanup_functions[i]; i++);
cleanup_functions[i] = pcf; cleanup_functions[i] = pcf;
@@ -91,7 +106,7 @@ void add_cleanup (cleanup_function pcf, /*@null@*/void *arg)
/* /*
* del_cleanup - Remove a cleanup_function from the cleanup_functions stack. * del_cleanup - Remove a cleanup_function from the cleanup_functions stack.
*/ */
void del_cleanup (cleanup_function pcf) void del_cleanup (/*@notnull@*/cleanup_function pcf)
{ {
unsigned int i; unsigned int i;
assert (NULL != pcf); assert (NULL != pcf);
@@ -109,7 +124,8 @@ void del_cleanup (cleanup_function pcf)
/* Move the rest of the cleanup functions */ /* Move the rest of the cleanup functions */
for (; i<CLEANUP_FUNCTIONS; i++) { for (; i<CLEANUP_FUNCTIONS; i++) {
/* Make sure the cleanup function was specified only once */ /* Make sure the cleanup function was specified only once */
assert (cleanup_functions[i+1] != pcf); assert ( (i == (CLEANUP_FUNCTIONS -1))
|| (cleanup_functions[i+1] != pcf));
if (i == (CLEANUP_FUNCTIONS -1)) { if (i == (CLEANUP_FUNCTIONS -1)) {
cleanup_functions[i] = NULL; cleanup_functions[i] = NULL;
+7 -4
View File
@@ -3,7 +3,7 @@
* Copyright (c) 1991 , Chip Rosenthal * Copyright (c) 1991 , Chip Rosenthal
* Copyright (c) 1996 - 1998, Marek Michałkiewicz * Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2008, Nicolas François * Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -50,7 +50,8 @@ static bool is_listed (const char *cfgin, const char *tty, bool def);
static bool is_listed (const char *cfgin, const char *tty, bool def) static bool is_listed (const char *cfgin, const char *tty, bool def)
{ {
FILE *fp; FILE *fp;
char buf[200], *cons, *s; char buf[200], *s;
const char *cons;
/* /*
* If the CONSOLE configuration definition isn't given, * If the CONSOLE configuration definition isn't given,
@@ -68,13 +69,15 @@ static bool is_listed (const char *cfgin, const char *tty, bool def)
*/ */
if (*cons != '/') { if (*cons != '/') {
char *pbuf;
strcpy (buf, cons); strcpy (buf, cons);
while ((s = strtok (buf, ":")) != NULL) { pbuf = &buf[0];
while ((s = strtok (pbuf, ":")) != NULL) {
if (strcmp (s, tty) == 0) { if (strcmp (s, tty) == 0) {
return true; return true;
} }
cons = NULL; pbuf = NULL;
} }
return false; return false;
} }
+310 -221
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1991 - 1994, Julianne Frances Haugh * Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2001, Marek Michałkiewicz * Copyright (c) 1996 - 2001, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko * Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2008, Nicolas François * Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,19 @@
#include "defines.h" #include "defines.h"
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
#include <selinux/selinux.h> #include <selinux/selinux.h>
#endif #endif /* WITH_SELINUX */
#if defined(WITH_ACL) || defined(WITH_ATTR)
#include <stdarg.h>
#include <attr/error_context.h>
#endif /* WITH_ACL || WITH_ATTR */
#ifdef WITH_ACL
#include <acl/libacl.h>
#endif /* WITH_ACL */
#ifdef WITH_ATTR
#include <attr/libattr.h>
#endif /* WITH_ATTR */
static /*@null@*/const char *src_orig; static /*@null@*/const char *src_orig;
static /*@null@*/const char *dst_orig; static /*@null@*/const char *dst_orig;
@@ -58,66 +70,73 @@ struct link_name {
static /*@exposed@*/struct link_name *links; static /*@exposed@*/struct link_name *links;
static int copy_entry (const char *src, const char *dst, static int copy_entry (const char *src, const char *dst,
long int uid, long int gid); bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int copy_dir (const char *src, const char *dst, static int copy_dir (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
long int uid, long int gid); uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
#ifdef S_IFLNK #ifdef S_IFLNK
static char *readlink_malloc (const char *filename); static /*@null@*/char *readlink_malloc (const char *filename);
static int copy_symlink (const char *src, const char *dst, static int copy_symlink (const char *src, const char *dst,
unused bool reset_selinux,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
long int uid, long int gid); uid_t old_uid, uid_t new_uid,
#endif gid_t old_gid, gid_t new_gid);
static int copy_hardlink (const char *src, const char *dst, #endif /* S_IFLNK */
static int copy_hardlink (const char *dst,
unused bool reset_selinux,
struct link_name *lp); struct link_name *lp);
static int copy_special (const char *dst, static int copy_special (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
long int uid, long int gid); uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int copy_file (const char *src, const char *dst, static int copy_file (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
long int uid, long int gid); uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int chown_if_needed (const char *dst, const struct stat *statp,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int lchown_if_needed (const char *dst, const struct stat *statp,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
static int fchown_if_needed (int fdst, const struct stat *statp,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid);
#ifdef WITH_SELINUX #if defined(WITH_ACL) || defined(WITH_ATTR)
/* /*
* selinux_file_context - Set the security context before any file or * error_acl - format the error messages for the ACL and EQ libraries.
* directory creation.
*
* selinux_file_context () should be called before any creation of file,
* symlink, directory, ...
*
* Callers may have to Reset SELinux to create files with default
* contexts:
* setfscreatecon (NULL);
*/ */
int selinux_file_context (const char *dst_name) static void error_acl (struct error_context *ctx, const char *fmt, ...)
{ {
static bool selinux_checked = false; va_list ap;
static bool selinux_enabled;
security_context_t scontext = NULL;
if (!selinux_checked) { /* ignore the case when destination does not support ACLs
selinux_enabled = is_selinux_enabled () > 0; * or extended attributes */
selinux_checked = true; if (ENOTSUP == errno) {
errno = 0;
return;
} }
if (selinux_enabled) { va_start (ap, fmt);
/* Get the default security context for this file */ (void) fprintf (stderr, _("%s: "), Prog);
if (matchpathcon (dst_name, 0, &scontext) < 0) { if (vfprintf (stderr, fmt, ap) != 0) {
if (security_getenforce () != 0) { (void) fputs (_(": "), stderr);
return 1;
}
}
/* Set the security context for the next created file */
if (setfscreatecon (scontext) < 0) {
if (security_getenforce () != 0) {
return 1;
}
}
freecon (scontext);
} }
return 0; (void) fprintf (stderr, "%s\n", strerror (errno));
va_end (ap);
} }
#endif
static struct error_context ctx = {
error_acl
};
#endif /* WITH_ACL || WITH_ATTR */
/* /*
* remove_link - delete a link from the linked list * remove_link - delete a link from the linked list
@@ -184,7 +203,7 @@ static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, c
lp->ln_count = sb->st_nlink; lp->ln_count = sb->st_nlink;
len = name_len - src_len + dst_len + 1; len = name_len - src_len + dst_len + 1;
lp->ln_name = (char *) xmalloc (len); lp->ln_name = (char *) xmalloc (len);
snprintf (lp->ln_name, len, "%s%s", dst_orig, name + src_len); (void) snprintf (lp->ln_name, len, "%s%s", dst_orig, name + src_len);
lp->ln_next = links; lp->ln_next = links;
links = lp; links = lp;
@@ -196,15 +215,49 @@ static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, c
* *
* copy_tree() walks a directory tree and copies ordinary files * copy_tree() walks a directory tree and copies ordinary files
* as it goes. * as it goes.
*
* When reset_selinux is enabled, extended attributes (and thus
* SELinux attributes) are not copied.
*
* old_uid and new_uid are used to set the ownership of the copied
* files. Unless old_uid is set to -1, only the files owned by
* old_uid have their ownership changed to new_uid. In addition, if
* new_uid is set to -1, no ownership will be changed.
*
* The same logic applies for the group-ownership and
* old_gid/new_gid.
*/ */
int copy_tree (const char *src_root, const char *dst_root, int copy_tree (const char *src_root, const char *dst_root,
long int uid, long int gid) bool copy_root, bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{ {
int err = 0; int err = 0;
bool set_orig = false; bool set_orig = false;
struct DIRECT *ent; struct DIRECT *ent;
DIR *dir; DIR *dir;
if (copy_root) {
struct stat sb;
if (access (dst_root, F_OK) == 0) {
return -1;
}
if (LSTAT (src_root, &sb) == -1) {
return -1;
}
if (!S_ISDIR (sb.st_mode)) {
fprintf (stderr,
"%s: %s is not a directory",
Prog, src_root);
return -1;
}
return copy_entry (src_root, dst_root, reset_selinux,
old_uid, new_uid, old_gid, new_gid);
}
/* /*
* Make certain both directories exist. This routine is called * Make certain both directories exist. This routine is called
* after the home directory is created, or recursively after the * after the home directory is created, or recursively after the
@@ -256,12 +309,15 @@ int copy_tree (const char *src_root, const char *dst_root,
* Build the filename for both the source and * Build the filename for both the source and
* the destination files. * the destination files.
*/ */
snprintf (src_name, src_len, "%s/%s", (void) snprintf (src_name, src_len, "%s/%s",
src_root, ent->d_name); src_root, ent->d_name);
snprintf (dst_name, dst_len, "%s/%s", (void) snprintf (dst_name, dst_len, "%s/%s",
dst_root, ent->d_name); dst_root, ent->d_name);
err = copy_entry (src_name, dst_name, uid, gid); err = copy_entry (src_name, dst_name,
reset_selinux,
old_uid, new_uid,
old_gid, new_gid);
} }
if (NULL != src_name) { if (NULL != src_name) {
free (src_name); free (src_name);
@@ -276,16 +332,25 @@ int copy_tree (const char *src_root, const char *dst_root,
if (set_orig) { if (set_orig) {
src_orig = NULL; src_orig = NULL;
dst_orig = NULL; dst_orig = NULL;
/* FIXME: clean links
* Since there can be hardlinks elsewhere on the device,
* we cannot check that all the hardlinks were found:
assert (NULL == links);
*/
} }
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
/* Reset SELinux to create files with default contexts */ /* Reset SELinux to create files with default contexts.
setfscreatecon (NULL); * Note that the context is only reset on exit of copy_tree (it is
#endif * assumed that the program would quit without needing a restored
* context if copy_tree failed previously), and that copy_tree can
/* FIXME: with the call to remove_link, we could also check that * be called recursively (hence the context is set on the
* no links remain in links. * sub-functions of copy_entry).
* assert (NULL == links); */ */
if (reset_selinux_file_context () != 0) {
err = -1;
}
#endif /* WITH_SELINUX */
return err; return err;
} }
@@ -300,13 +365,19 @@ int copy_tree (const char *src_root, const char *dst_root,
* *
* The access and modification time will not be modified. * The access and modification time will not be modified.
* *
* The permissions will be set to uid/gid. * The permissions will be set to new_uid/new_gid.
* *
* If uid (resp. gid) is equal to -1, the user (resp. group) will * If new_uid (resp. new_gid) is equal to -1, the user (resp. group) will
* not be modified. * not be modified.
*
* Only the files owned (resp. group-owned) by old_uid (resp.
* old_gid) will be modified, unless old_uid (resp. old_gid) is set
* to -1.
*/ */
static int copy_entry (const char *src, const char *dst, static int copy_entry (const char *src, const char *dst,
long int uid, long int gid) bool reset_selinux,
uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{ {
int err = 0; int err = 0;
struct stat sb; struct stat sb;
@@ -319,29 +390,30 @@ static int copy_entry (const char *src, const char *dst,
#ifdef HAVE_STRUCT_STAT_ST_ATIM #ifdef HAVE_STRUCT_STAT_ST_ATIM
mt[0].tv_sec = sb.st_atim.tv_sec; mt[0].tv_sec = sb.st_atim.tv_sec;
mt[0].tv_usec = sb.st_atim.tv_nsec / 1000; mt[0].tv_usec = sb.st_atim.tv_nsec / 1000;
#else #else /* !HAVE_STRUCT_STAT_ST_ATIM */
mt[0].tv_sec = sb.st_atime; mt[0].tv_sec = sb.st_atime;
#ifdef HAVE_STRUCT_STAT_ST_ATIMENSEC # ifdef HAVE_STRUCT_STAT_ST_ATIMENSEC
mt[0].tv_usec = sb.st_atimensec / 1000; mt[0].tv_usec = sb.st_atimensec / 1000;
#else # else /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */
mt[0].tv_usec = 0; mt[0].tv_usec = 0;
#endif # endif /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */
#endif #endif /* !HAVE_STRUCT_STAT_ST_ATIM */
#ifdef HAVE_STRUCT_STAT_ST_MTIM #ifdef HAVE_STRUCT_STAT_ST_MTIM
mt[1].tv_sec = sb.st_mtim.tv_sec; mt[1].tv_sec = sb.st_mtim.tv_sec;
mt[1].tv_usec = sb.st_mtim.tv_nsec / 1000; mt[1].tv_usec = sb.st_mtim.tv_nsec / 1000;
#else #else /* !HAVE_STRUCT_STAT_ST_MTIM */
mt[1].tv_sec = sb.st_mtime; mt[1].tv_sec = sb.st_mtime;
#ifdef HAVE_STRUCT_STAT_ST_MTIMENSEC # ifdef HAVE_STRUCT_STAT_ST_MTIMENSEC
mt[1].tv_usec = sb.st_mtimensec / 1000; mt[1].tv_usec = sb.st_mtimensec / 1000;
#else # else /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */
mt[1].tv_usec = 0; mt[1].tv_usec = 0;
#endif # endif /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */
#endif #endif /* !HAVE_STRUCT_STAT_ST_MTIM */
if (S_ISDIR (sb.st_mode)) { if (S_ISDIR (sb.st_mode)) {
err = copy_dir (src, dst, &sb, mt, uid, gid); err = copy_dir (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
} }
#ifdef S_IFLNK #ifdef S_IFLNK
@@ -350,16 +422,17 @@ static int copy_entry (const char *src, const char *dst,
*/ */
else if (S_ISLNK (sb.st_mode)) { else if (S_ISLNK (sb.st_mode)) {
err = copy_symlink (src, dst, &sb, mt, uid, gid); err = copy_symlink (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
} }
#endif #endif /* S_IFLNK */
/* /*
* See if this is a previously copied link * See if this is a previously copied link
*/ */
else if ((lp = check_link (src, &sb)) != NULL) { else if ((lp = check_link (src, &sb)) != NULL) {
err = copy_hardlink (src, dst, lp); err = copy_hardlink (dst, reset_selinux, lp);
} }
/* /*
@@ -369,7 +442,8 @@ static int copy_entry (const char *src, const char *dst,
*/ */
else if (!S_ISREG (sb.st_mode)) { else if (!S_ISREG (sb.st_mode)) {
err = copy_special (dst, &sb, mt, uid, gid); err = copy_special (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
} }
/* /*
@@ -378,7 +452,8 @@ static int copy_entry (const char *src, const char *dst,
*/ */
else { else {
err = copy_file (src, dst, &sb, mt, uid, gid); err = copy_file (src, dst, reset_selinux, &sb, mt,
old_uid, new_uid, old_gid, new_gid);
} }
} }
@@ -390,14 +465,16 @@ static int copy_entry (const char *src, const char *dst,
* *
* Copy a directory (recursively) from src to dst. * Copy a directory (recursively) from src to dst.
* *
* statp, mt, uid, gid are used to set the access and modification and the * statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
* access rights. * the access and modification and the access rights.
* *
* Return 0 on success, -1 on error. * Return 0 on success, -1 on error.
*/ */
static int copy_dir (const char *src, const char *dst, static int copy_dir (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
long int uid, long int gid) uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{ {
int err = 0; int err = 0;
@@ -407,14 +484,33 @@ static int copy_dir (const char *src, const char *dst,
*/ */
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
selinux_file_context (dst); if (set_selinux_file_context (dst) != 0) {
#endif return -1;
}
#endif /* WITH_SELINUX */
if ( (mkdir (dst, statp->st_mode) != 0) if ( (mkdir (dst, statp->st_mode) != 0)
|| (chown (dst, || (chown_if_needed (dst, statp,
(uid == - 1) ? statp->st_uid : (uid_t) uid, old_uid, new_uid, old_gid, new_gid) != 0)
(gid == - 1) ? statp->st_gid : (gid_t) gid) != 0) #ifdef WITH_ACL
|| ( (perm_copy_file (src, dst, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
|| (chmod (dst, statp->st_mode) != 0) || (chmod (dst, statp->st_mode) != 0)
|| (copy_tree (src, dst, uid, gid) != 0) #endif /* !WITH_ACL */
#ifdef WITH_ATTR
/*
* If the third parameter is NULL, all extended attributes
* except those that define Access Control Lists are copied.
* ACLs are excluded by default because copying them between
* file systems with and without ACL support needs some
* additional logic so that no unexpected permissions result.
*/
|| ( !reset_selinux
&& (attr_copy_file (src, dst, NULL, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ATTR */
|| (copy_tree (src, dst, false, reset_selinux,
old_uid, new_uid, old_gid, new_gid) != 0)
|| (utimes (dst, mt) != 0)) { || (utimes (dst, mt) != 0)) {
err = -1; err = -1;
} }
@@ -429,11 +525,11 @@ static int copy_dir (const char *src, const char *dst,
* return NULL on error. * return NULL on error.
* The return string shall be freed by the caller. * The return string shall be freed by the caller.
*/ */
static char *readlink_malloc (const char *filename) static /*@null@*/char *readlink_malloc (const char *filename)
{ {
size_t size = 1024; size_t size = 1024;
while (1) { while (true) {
ssize_t nchars; ssize_t nchars;
char *buffer = (char *) malloc (size); char *buffer = (char *) malloc (size);
if (NULL == buffer) { if (NULL == buffer) {
@@ -443,10 +539,11 @@ static char *readlink_malloc (const char *filename)
nchars = readlink (filename, buffer, size); nchars = readlink (filename, buffer, size);
if (nchars < 0) { if (nchars < 0) {
free(buffer);
return NULL; return NULL;
} }
if ( (size_t) nchars < size) { /* The buffer was large enough */ if ((size_t) nchars < size) { /* The buffer was large enough */
/* readlink does not nul-terminate */ /* readlink does not nul-terminate */
buffer[nchars] = '\0'; buffer[nchars] = '\0';
return buffer; return buffer;
@@ -463,14 +560,16 @@ static char *readlink_malloc (const char *filename)
* *
* Copy a symlink from src to dst. * Copy a symlink from src to dst.
* *
* statp, mt, uid, gid are used to set the access and modification and the * statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
* access rights. * the access and modification and the access rights.
* *
* Return 0 on success, -1 on error. * Return 0 on success, -1 on error.
*/ */
static int copy_symlink (const char *src, const char *dst, static int copy_symlink (const char *src, const char *dst,
unused bool reset_selinux,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
long int uid, long int gid) uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{ {
char *oldlink; char *oldlink;
@@ -494,25 +593,33 @@ static int copy_symlink (const char *src, const char *dst,
/* If src was a link to an entry of the src_orig directory itself, /* If src was a link to an entry of the src_orig directory itself,
* create a link to the corresponding entry in the dst_orig * create a link to the corresponding entry in the dst_orig
* directory. * directory.
* FIXME: This may change a relative link to an absolute link
*/ */
if (strncmp (oldlink, src_orig, strlen (src_orig)) == 0) { if (strncmp (oldlink, src_orig, strlen (src_orig)) == 0) {
size_t len = strlen (dst_orig) + strlen (oldlink) - strlen (src_orig) + 1; size_t len = strlen (dst_orig) + strlen (oldlink) - strlen (src_orig) + 1;
char *dummy = (char *) malloc (len); char *dummy = (char *) xmalloc (len);
snprintf (dummy, len, "%s%s", (void) snprintf (dummy, len, "%s%s",
dst_orig, dst_orig,
oldlink + strlen (src_orig)); oldlink + strlen (src_orig));
free (oldlink); free (oldlink);
oldlink = dummy; oldlink = dummy;
} }
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
selinux_file_context (dst); if (set_selinux_file_context (dst) != 0) {
#endif free (oldlink);
return -1;
}
#endif /* WITH_SELINUX */
if ( (symlink (oldlink, dst) != 0) if ( (symlink (oldlink, dst) != 0)
|| (lchown (dst, || (lchown_if_needed (dst, statp,
(uid == -1) ? statp->st_uid : (uid_t) uid, old_uid, new_uid, old_gid, new_gid) != 0)) {
(gid == -1) ? statp->st_gid : (gid_t) gid) != 0)) { /* FIXME: there are no modes on symlinks, right?
* ACL could be copied, but this would be much more
* complex than calling perm_copy_file.
* Ditto for Extended Attributes.
* We currently only document that ACL and Extended
* Attributes are not copied.
*/
free (oldlink); free (oldlink);
return -1; return -1;
} }
@@ -524,12 +631,12 @@ static int copy_symlink (const char *src, const char *dst,
* it returns ENOSYS on many system * it returns ENOSYS on many system
* - not implemented * - not implemented
*/ */
lutimes (dst, mt); (void) lutimes (dst, mt);
#endif #endif /* HAVE_LUTIMES */
return 0; return 0;
} }
#endif #endif /* S_IFLNK */
/* /*
* copy_hardlink - copy a hardlink * copy_hardlink - copy a hardlink
@@ -538,23 +645,18 @@ static int copy_symlink (const char *src, const char *dst,
* *
* Return 0 on success, -1 on error. * Return 0 on success, -1 on error.
*/ */
static int copy_hardlink (const char *src, const char *dst, static int copy_hardlink (const char *dst,
unused bool reset_selinux,
struct link_name *lp) struct link_name *lp)
{ {
/* TODO: selinux needed? */ /* FIXME: selinux, ACL, Extended Attributes needed? */
if (link (lp->ln_name, dst) != 0) { if (link (lp->ln_name, dst) != 0) {
return -1; return -1;
} }
/* FIXME: why is it unlinked? This is a copy, not a move */
if (unlink (src) != 0) {
return -1;
}
/* FIXME: idem, although it may never be used again */
/* If the file could be unlinked, decrement the links counter, /* If the file could be unlinked, decrement the links counter,
* and delete the file if it was the last reference */ * and forget about this link if it was the last reference */
lp->ln_count--; lp->ln_count--;
if (lp->ln_count <= 0) { if (lp->ln_count <= 0) {
remove_link (lp); remove_link (lp);
@@ -568,26 +670,46 @@ static int copy_hardlink (const char *src, const char *dst,
* *
* Copy a special file from src to dst. * Copy a special file from src to dst.
* *
* statp, mt, uid, gid are used to set the access and modification and the * statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
* access rights. * the access and modification and the access rights.
* *
* Return 0 on success, -1 on error. * Return 0 on success, -1 on error.
*/ */
static int copy_special (const char *dst, static int copy_special (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
long int uid, long int gid) uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{ {
int err = 0; int err = 0;
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
selinux_file_context (dst); if (set_selinux_file_context (dst) != 0) {
#endif return -1;
}
#endif /* WITH_SELINUX */
if ( (mknod (dst, statp->st_mode & ~07777, statp->st_rdev) != 0) if ( (mknod (dst, statp->st_mode & ~07777, statp->st_rdev) != 0)
|| (chown (dst, || (chown_if_needed (dst, statp,
(uid == -1) ? statp->st_uid : (uid_t) uid, old_uid, new_uid, old_gid, new_gid) != 0)
(gid == -1) ? statp->st_gid : (gid_t) gid) != 0) #ifdef WITH_ACL
|| ( (perm_copy_file (src, dst, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
|| (chmod (dst, statp->st_mode & 07777) != 0) || (chmod (dst, statp->st_mode & 07777) != 0)
#endif /* !WITH_ACL */
#ifdef WITH_ATTR
/*
* If the third parameter is NULL, all extended attributes
* except those that define Access Control Lists are copied.
* ACLs are excluded by default because copying them between
* file systems with and without ACL support needs some
* additional logic so that no unexpected permissions result.
*/
|| ( !reset_selinux
&& (attr_copy_file (src, dst, NULL, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ATTR */
|| (utimes (dst, mt) != 0)) { || (utimes (dst, mt) != 0)) {
err = -1; err = -1;
} }
@@ -600,14 +722,16 @@ static int copy_special (const char *dst,
* *
* Copy a file from src to dst. * Copy a file from src to dst.
* *
* statp, mt, uid, gid are used to set the access and modification and the * statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
* access rights. * the access and modification and the access rights.
* *
* Return 0 on success, -1 on error. * Return 0 on success, -1 on error.
*/ */
static int copy_file (const char *src, const char *dst, static int copy_file (const char *src, const char *dst,
bool reset_selinux,
const struct stat *statp, const struct timeval mt[], const struct stat *statp, const struct timeval mt[],
long int uid, long int gid) uid_t old_uid, uid_t new_uid,
gid_t old_gid, gid_t new_gid)
{ {
int err = 0; int err = 0;
int ifd; int ifd;
@@ -620,20 +744,40 @@ static int copy_file (const char *src, const char *dst,
return -1; return -1;
} }
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
selinux_file_context (dst); if (set_selinux_file_context (dst) != 0) {
#endif return -1;
}
#endif /* WITH_SELINUX */
ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC, statp->st_mode & 07777); ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC, statp->st_mode & 07777);
if ( (ofd < 0) if ( (ofd < 0)
|| (fchown (ofd, || (fchown_if_needed (ofd, statp,
(uid == -1) ? statp->st_uid : (uid_t) uid, old_uid, new_uid, old_gid, new_gid) != 0)
(gid == -1) ? statp->st_gid : (gid_t) gid) != 0) #ifdef WITH_ACL
|| (fchmod (ofd, statp->st_mode & 07777) != 0)) { || ( (perm_copy_fd (src, ifd, dst, ofd, &ctx) != 0)
&& (errno != 0))
#else /* !WITH_ACL */
|| (fchmod (ofd, statp->st_mode & 07777) != 0)
#endif /* !WITH_ACL */
#ifdef WITH_ATTR
/*
* If the third parameter is NULL, all extended attributes
* except those that define Access Control Lists are copied.
* ACLs are excluded by default because copying them between
* file systems with and without ACL support needs some
* additional logic so that no unexpected permissions result.
*/
|| ( !reset_selinux
&& (attr_copy_fd (src, ifd, dst, ofd, NULL, &ctx) != 0)
&& (errno != 0))
#endif /* WITH_ATTR */
) {
(void) close (ifd); (void) close (ifd);
return -1; return -1;
} }
while ((cnt = read (ifd, buf, sizeof buf)) > 0) { while ((cnt = read (ifd, buf, sizeof buf)) > 0) {
if (write (ofd, buf, (size_t)cnt) != cnt) { if (write (ofd, buf, (size_t)cnt) != cnt) {
(void) close (ifd);
return -1; return -1;
} }
} }
@@ -644,7 +788,7 @@ static int copy_file (const char *src, const char *dst,
if (futimes (ofd, mt) != 0) { if (futimes (ofd, mt) != 0) {
return -1; return -1;
} }
#endif #endif /* HAVE_FUTIMES */
if (close (ofd) != 0) { if (close (ofd) != 0) {
return -1; return -1;
@@ -654,97 +798,42 @@ static int copy_file (const char *src, const char *dst,
if (utimes(dst, mt) != 0) { if (utimes(dst, mt) != 0) {
return -1; return -1;
} }
#endif #endif /* !HAVE_FUTIMES */
return err; return err;
} }
/* #define def_chown_if_needed(chown_function, type_dst) \
* remove_tree - delete a directory tree static int chown_function ## _if_needed (type_dst dst, \
* const struct stat *statp, \
* remove_tree() walks a directory tree and deletes all the files uid_t old_uid, uid_t new_uid, \
* and directories. gid_t old_gid, gid_t new_gid) \
* At the end, it deletes the root directory itself. { \
*/ uid_t tmpuid = (uid_t) -1; \
gid_t tmpgid = (gid_t) -1; \
int remove_tree (const char *root) \
{ /* Use new_uid if old_uid is set to -1 or if the file was \
char *new_name = NULL; * owned by the user. */ \
int err = 0; if (((uid_t) -1 == old_uid) || (statp->st_uid == old_uid)) { \
struct DIRECT *ent; tmpuid = new_uid; \
struct stat sb; } \
DIR *dir; /* Otherwise, or if new_uid was set to -1, we keep the same \
* owner. */ \
/* if ((uid_t) -1 == tmpuid) { \
* Open the source directory and read each entry. Every file tmpuid = statp->st_uid; \
* entry in the directory is copied with the UID and GID set } \
* to the provided values. As an added security feature only \
* regular files (and directories ...) are copied, and no file if (((gid_t) -1 == old_gid) || (statp->st_gid == old_gid)) { \
* is made set-ID. tmpgid = new_gid; \
*/ } \
dir = opendir (root); if ((gid_t) -1 == tmpgid) { \
if (NULL == dir) { tmpgid = statp->st_gid; \
return -1; } \
} \
return chown_function (dst, tmpuid, tmpgid); \
while ((ent = readdir (dir))) {
size_t new_len = strlen (root) + strlen (ent->d_name) + 2;
/*
* Skip the "." and ".." entries
*/
if (strcmp (ent->d_name, ".") == 0 ||
strcmp (ent->d_name, "..") == 0) {
continue;
}
/*
* Make the filename for the current entry.
*/
if (NULL != new_name) {
free (new_name);
}
new_name = (char *) malloc (new_len);
if (NULL == new_name) {
err = -1;
break;
}
snprintf (new_name, new_len, "%s/%s", root, ent->d_name);
if (LSTAT (new_name, &sb) == -1) {
continue;
}
if (S_ISDIR (sb.st_mode)) {
/*
* Recursively delete this directory.
*/
if (remove_tree (new_name) != 0) {
err = -1;
break;
}
} else {
/*
* Delete the file.
*/
if (unlink (new_name) != 0) {
err = -1;
break;
}
}
}
if (NULL != new_name) {
free (new_name);
}
(void) closedir (dir);
if (0 == err) {
if (rmdir (root) != 0) {
err = -1;
}
}
return err;
} }
def_chown_if_needed (chown, const char *)
def_chown_if_needed (lchown, const char *)
def_chown_if_needed (fchown, int)
+13 -3
View File
@@ -115,6 +115,9 @@ void addenv (const char *string, /*@null@*/const char *value)
n = (size_t) (cp - newstring); n = (size_t) (cp - newstring);
/*
* If this environment variable is already set, change its value.
*/
for (i = 0; i < newenvc; i++) { for (i = 0; i < newenvc; i++) {
if ( (strncmp (newstring, newenvp[i], n) == 0) if ( (strncmp (newstring, newenvp[i], n) == 0)
&& (('=' == newenvp[i][n]) || ('\0' == newenvp[i][n]))) { && (('=' == newenvp[i][n]) || ('\0' == newenvp[i][n]))) {
@@ -128,8 +131,15 @@ void addenv (const char *string, /*@null@*/const char *value)
return; return;
} }
/*
* Otherwise, save the new environment variable
*/
newenvp[newenvc++] = newstring; newenvp[newenvc++] = newstring;
/*
* And extend the environment if needed.
*/
/* /*
* Check whether newenvc is a multiple of NEWENVP_STEP. * Check whether newenvc is a multiple of NEWENVP_STEP.
* If so we have to resize the vector. * If so we have to resize the vector.
@@ -143,14 +153,14 @@ void addenv (const char *string, /*@null@*/const char *value)
size_t newsize; size_t newsize;
/* /*
* If the resize operation succeds we can * If the resize operation succeeds we can
* happily go on, else print a message. * happily go on, else print a message.
*/ */
newsize = (newenvc + NEWENVP_STEP) * sizeof (char *); newsize = (newenvc + NEWENVP_STEP) * sizeof (char *);
__newenvp = (char **) realloc (newenvp, newsize); __newenvp = (char **) realloc (newenvp, newsize);
if (__newenvp) { if (NULL != __newenvp) {
/* /*
* If this is our current environment, update * If this is our current environment, update
* environ so that it doesn't point to some * environ so that it doesn't point to some
@@ -251,7 +261,7 @@ void sanitize_env (void)
if (strncmp (*cur, *bad, strlen (*bad)) != 0) { if (strncmp (*cur, *bad, strlen (*bad)) != 0) {
continue; continue;
} }
if (strchr (*cur, '/') != NULL) { if (strchr (*cur, '/') == NULL) {
continue; /* OK */ continue; /* OK */
} }
for (move = cur; NULL != *move; move++) { for (move = cur; NULL != *move; move++) {
+4 -2
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh * Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz * Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2002 - 2005, Tomasz Kłoczko * Copyright (c) 2002 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François * Copyright (c) 2008 - 2010, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -273,12 +273,14 @@ void failprint (const struct faillog *fail)
lasttime++; lasttime++;
} }
#endif #endif
/*@-formatconst@*/
(void) printf (ngettext ("%d failure since last login.\n" (void) printf (ngettext ("%d failure since last login.\n"
"Last was %s on %s.\n", "Last was %s on %s.\n",
"%d failures since last login.\n" "%d failures since last login.\n"
"Last was %s on %s.\n", "Last was %s on %s.\n",
(unsigned long) fail->fail_cnt), (unsigned long) fail->fail_cnt),
fail->fail_cnt, lasttime, fail->fail_line); fail->fail_cnt, lasttime, fail->fail_line);
/*@=formatconst@*/
} }
/* /*
@@ -296,7 +298,7 @@ void failtmp (const char *username,
#endif /* !USE_UTMPX */ #endif /* !USE_UTMPX */
) )
{ {
char *ftmp; const char *ftmp;
int fd; int fd;
/* /*
+38 -13
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh * Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 2008 - 2009, Nicolas François * Copyright (c) 2008 - 2011, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h>
#include "prototypes.h" #include "prototypes.h"
#include "groupio.h" #include "groupio.h"
@@ -52,7 +53,7 @@ int find_new_gid (bool sys_group,
/*@null@*/gid_t const *preferred_gid) /*@null@*/gid_t const *preferred_gid)
{ {
const struct group *grp; const struct group *grp;
gid_t gid_min, gid_max, group_id, id; gid_t gid_min, gid_max, group_id;
bool *used_gids; bool *used_gids;
assert (gid != NULL); assert (gid != NULL);
@@ -60,12 +61,30 @@ int find_new_gid (bool sys_group,
if (!sys_group) { if (!sys_group) {
gid_min = (gid_t) getdef_ulong ("GID_MIN", 1000UL); gid_min = (gid_t) getdef_ulong ("GID_MIN", 1000UL);
gid_max = (gid_t) getdef_ulong ("GID_MAX", 60000UL); gid_max = (gid_t) getdef_ulong ("GID_MAX", 60000UL);
if (gid_max < gid_min) {
(void) fprintf (stderr,
_("%s: Invalid configuration: GID_MIN (%lu), GID_MAX (%lu)\n"),
Prog, (unsigned long) gid_min, (unsigned long) gid_max);
return -1;
}
} else { } else {
gid_min = (gid_t) getdef_ulong ("SYS_GID_MIN", 101UL); gid_min = (gid_t) getdef_ulong ("SYS_GID_MIN", 101UL);
gid_max = (gid_t) getdef_ulong ("GID_MIN", 1000UL) - 1; gid_max = (gid_t) getdef_ulong ("GID_MIN", 1000UL) - 1;
gid_max = (gid_t) getdef_ulong ("SYS_GID_MAX", (unsigned long) gid_max); gid_max = (gid_t) getdef_ulong ("SYS_GID_MAX", (unsigned long) gid_max);
if (gid_max < gid_min) {
(void) fprintf (stderr,
_("%s: Invalid configuration: SYS_GID_MIN (%lu), GID_MIN (%lu), SYS_GID_MAX (%lu)\n"),
Prog, (unsigned long) gid_min, getdef_ulong ("GID_MIN", 1000UL), (unsigned long) gid_max);
return -1;
}
}
used_gids = malloc (sizeof (bool) * (gid_max +1));
if (NULL == used_gids) {
fprintf (stderr,
_("%s: failed to allocate memory: %s\n"),
Prog, strerror (errno));
return -1;
} }
used_gids = alloca (sizeof (bool) * (gid_max +1));
memset (used_gids, false, sizeof (bool) * (gid_max + 1)); memset (used_gids, false, sizeof (bool) * (gid_max + 1));
if ( (NULL != preferred_gid) if ( (NULL != preferred_gid)
@@ -77,6 +96,7 @@ int find_new_gid (bool sys_group,
* changes */ * changes */
&& (gr_locate_gid (*preferred_gid) == NULL)) { && (gr_locate_gid (*preferred_gid) == NULL)) {
*gid = *preferred_gid; *gid = *preferred_gid;
free (used_gids);
return 0; return 0;
} }
@@ -90,6 +110,7 @@ int find_new_gid (bool sys_group,
* some groups were created but the changes were not committed yet. * some groups were created but the changes were not committed yet.
*/ */
if (sys_group) { if (sys_group) {
gid_t id;
/* setgrent / getgrent / endgrent can be very slow with /* setgrent / getgrent / endgrent can be very slow with
* LDAP configurations (and many accounts). * LDAP configurations (and many accounts).
* Since there is a limited amount of IDs to be tested * Since there is a limited amount of IDs to be tested
@@ -104,7 +125,7 @@ int find_new_gid (bool sys_group,
} }
} }
gr_rewind (); (void) gr_rewind ();
while ((grp = gr_next ()) != NULL) { while ((grp = gr_next ()) != NULL) {
if ((grp->gr_gid <= group_id) && (grp->gr_gid >= gid_min)) { if ((grp->gr_gid <= group_id) && (grp->gr_gid >= gid_min)) {
group_id = grp->gr_gid - 1; group_id = grp->gr_gid - 1;
@@ -128,7 +149,7 @@ int find_new_gid (bool sys_group,
} }
endgrent (); endgrent ();
gr_rewind (); (void) gr_rewind ();
while ((grp = gr_next ()) != NULL) { while ((grp = gr_next ()) != NULL) {
if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) { if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) {
group_id = grp->gr_gid + 1; group_id = grp->gr_gid + 1;
@@ -141,43 +162,47 @@ int find_new_gid (bool sys_group,
} }
/* /*
* If a group with GID equal to GID_MAX exists, the above algorithm * If a group (resp. system group) with GID equal to GID_MAX (resp.
* will give us GID_MAX+1 even if not unique. Search for the first * GID_MIN) exists, the above algorithm will give us GID_MAX+1
* free GID starting with GID_MIN. * (resp. GID_MIN-1) even if not unique. Search for the first free
* GID starting with GID_MIN (resp. GID_MAX).
*/ */
if (sys_group) { if (sys_group) {
if (group_id == gid_min - 1) { if (group_id < gid_min) {
for (group_id = gid_max; group_id >= gid_min; group_id--) { for (group_id = gid_max; group_id >= gid_min; group_id--) {
if (false == used_gids[group_id]) { if (false == used_gids[group_id]) {
break; break;
} }
} }
if ( group_id < gid_min ) { if (group_id < gid_min) {
fprintf (stderr, fprintf (stderr,
_("%s: Can't get unique system GID (no more available GIDs)\n"), _("%s: Can't get unique system GID (no more available GIDs)\n"),
Prog); Prog);
SYSLOG ((LOG_WARN, SYSLOG ((LOG_WARN,
"no more available GID on the system")); "no more available GID on the system"));
free (used_gids);
return -1; return -1;
} }
} }
} else { } else {
if (group_id == gid_max + 1) { if (group_id > gid_max) {
for (group_id = gid_min; group_id < gid_max; group_id++) { for (group_id = gid_min; group_id <= gid_max; group_id++) {
if (false == used_gids[group_id]) { if (false == used_gids[group_id]) {
break; break;
} }
} }
if (group_id == gid_max) { if (group_id > gid_max) {
fprintf (stderr, fprintf (stderr,
_("%s: Can't get unique GID (no more available GIDs)\n"), _("%s: Can't get unique GID (no more available GIDs)\n"),
Prog); Prog);
SYSLOG ((LOG_WARN, "no more available GID on the system")); SYSLOG ((LOG_WARN, "no more available GID on the system"));
free (used_gids);
return -1; return -1;
} }
} }
} }
free (used_gids);
*gid = group_id; *gid = group_id;
return 0; return 0;
} }
+86
View File
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2012 Eric Biederman
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ifdef ENABLE_SUBIDS
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include "prototypes.h"
#include "subordinateio.h"
#include "getdef.h"
/*
* find_new_sub_gids - Find a new unused range of GIDs.
*
* If successful, find_new_sub_gids provides a range of unused
* user IDs in the [SUB_GID_MIN:SUB_GID_MAX] range.
*
* Return 0 on success, -1 if no unused GIDs are available.
*/
int find_new_sub_gids (const char *owner,
gid_t *range_start, unsigned long *range_count)
{
unsigned long min, max;
unsigned long count;
gid_t start;
assert (range_start != NULL);
assert (range_count != NULL);
min = getdef_ulong ("SUB_GID_MIN", 100000UL);
max = getdef_ulong ("SUB_GID_MAX", 600100000UL);
count = getdef_ulong ("SUB_GID_COUNT", 65536);
if (min > max || count >= max || (min + count - 1) > max) {
(void) fprintf (stderr,
_("%s: Invalid configuration: SUB_GID_MIN (%lu),"
" SUB_GID_MAX (%lu), SUB_GID_COUNT (%lu)\n"),
Prog, min, max, count);
return -1;
}
start = sub_gid_find_free_range(min, max, count);
if (start == (gid_t)-1) {
fprintf (stderr,
_("%s: Can't get unique subordinate GID range\n"),
Prog);
SYSLOG ((LOG_WARN, "no more available subordinate GIDs on the system"));
return -1;
}
*range_start = start;
*range_count = count;
return 0;
}
#else /* !ENABLE_SUBIDS */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !ENABLE_SUBIDS */
+86
View File
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2012 Eric Biederman
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ifdef ENABLE_SUBIDS
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include "prototypes.h"
#include "subordinateio.h"
#include "getdef.h"
/*
* find_new_sub_uids - Find a new unused range of UIDs.
*
* If successful, find_new_sub_uids provides a range of unused
* user IDs in the [SUB_UID_MIN:SUB_UID_MAX] range.
*
* Return 0 on success, -1 if no unused UIDs are available.
*/
int find_new_sub_uids (const char *owner,
uid_t *range_start, unsigned long *range_count)
{
unsigned long min, max;
unsigned long count;
uid_t start;
assert (range_start != NULL);
assert (range_count != NULL);
min = getdef_ulong ("SUB_UID_MIN", 100000UL);
max = getdef_ulong ("SUB_UID_MAX", 600100000UL);
count = getdef_ulong ("SUB_UID_COUNT", 65536);
if (min > max || count >= max || (min + count - 1) > max) {
(void) fprintf (stderr,
_("%s: Invalid configuration: SUB_UID_MIN (%lu),"
" SUB_UID_MAX (%lu), SUB_UID_COUNT (%lu)\n"),
Prog, min, max, count);
return -1;
}
start = sub_uid_find_free_range(min, max, count);
if (start == (uid_t)-1) {
fprintf (stderr,
_("%s: Can't get unique subordinate UID range\n"),
Prog);
SYSLOG ((LOG_WARN, "no more available subordinate UIDs on the system"));
return -1;
}
*range_start = start;
*range_count = count;
return 0;
}
#else /* !ENABLE_SUBIDS */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !ENABLE_SUBIDS */
+37 -12
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh * Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 2008 - 2009, Nicolas François * Copyright (c) 2008 - 2011, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h>
#include "prototypes.h" #include "prototypes.h"
#include "pwio.h" #include "pwio.h"
@@ -52,7 +53,7 @@ int find_new_uid (bool sys_user,
/*@null@*/uid_t const *preferred_uid) /*@null@*/uid_t const *preferred_uid)
{ {
const struct passwd *pwd; const struct passwd *pwd;
uid_t uid_min, uid_max, user_id, id; uid_t uid_min, uid_max, user_id;
bool *used_uids; bool *used_uids;
assert (uid != NULL); assert (uid != NULL);
@@ -60,12 +61,30 @@ int find_new_uid (bool sys_user,
if (!sys_user) { if (!sys_user) {
uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL); uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL);
uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL); uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL);
if (uid_max < uid_min) {
(void) fprintf (stderr,
_("%s: Invalid configuration: UID_MIN (%lu), UID_MAX (%lu)\n"),
Prog, (unsigned long) uid_min, (unsigned long) uid_max);
return -1;
}
} else { } else {
uid_min = (uid_t) getdef_ulong ("SYS_UID_MIN", 101UL); uid_min = (uid_t) getdef_ulong ("SYS_UID_MIN", 101UL);
uid_max = (uid_t) getdef_ulong ("UID_MIN", 1000UL) - 1; uid_max = (uid_t) getdef_ulong ("UID_MIN", 1000UL) - 1;
uid_max = (uid_t) getdef_ulong ("SYS_UID_MAX", (unsigned long) uid_max); uid_max = (uid_t) getdef_ulong ("SYS_UID_MAX", (unsigned long) uid_max);
if (uid_max < uid_min) {
(void) fprintf (stderr,
_("%s: Invalid configuration: SYS_UID_MIN (%lu), UID_MIN (%lu), SYS_UID_MAX (%lu)\n"),
Prog, (unsigned long) uid_min, getdef_ulong ("UID_MIN", 1000UL), (unsigned long) uid_max);
return -1;
}
}
used_uids = malloc (sizeof (bool) * (uid_max +1));
if (NULL == used_uids) {
fprintf (stderr,
_("%s: failed to allocate memory: %s\n"),
Prog, strerror (errno));
return -1;
} }
used_uids = alloca (sizeof (bool) * (uid_max +1));
memset (used_uids, false, sizeof (bool) * (uid_max + 1)); memset (used_uids, false, sizeof (bool) * (uid_max + 1));
if ( (NULL != preferred_uid) if ( (NULL != preferred_uid)
@@ -77,6 +96,7 @@ int find_new_uid (bool sys_user,
* changes */ * changes */
&& (pw_locate_uid (*preferred_uid) == NULL)) { && (pw_locate_uid (*preferred_uid) == NULL)) {
*uid = *preferred_uid; *uid = *preferred_uid;
free (used_uids);
return 0; return 0;
} }
@@ -90,6 +110,7 @@ int find_new_uid (bool sys_user,
* some users were created but the changes were not committed yet. * some users were created but the changes were not committed yet.
*/ */
if (sys_user) { if (sys_user) {
uid_t id;
/* setpwent / getpwent / endpwent can be very slow with /* setpwent / getpwent / endpwent can be very slow with
* LDAP configurations (and many accounts). * LDAP configurations (and many accounts).
* Since there is a limited amount of IDs to be tested * Since there is a limited amount of IDs to be tested
@@ -104,7 +125,7 @@ int find_new_uid (bool sys_user,
} }
} }
pw_rewind (); (void) pw_rewind ();
while ((pwd = pw_next ()) != NULL) { while ((pwd = pw_next ()) != NULL) {
if ((pwd->pw_uid <= user_id) && (pwd->pw_uid >= uid_min)) { if ((pwd->pw_uid <= user_id) && (pwd->pw_uid >= uid_min)) {
user_id = pwd->pw_uid - 1; user_id = pwd->pw_uid - 1;
@@ -128,7 +149,7 @@ int find_new_uid (bool sys_user,
} }
endpwent (); endpwent ();
pw_rewind (); (void) pw_rewind ();
while ((pwd = pw_next ()) != NULL) { while ((pwd = pw_next ()) != NULL) {
if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) { if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) {
user_id = pwd->pw_uid + 1; user_id = pwd->pw_uid + 1;
@@ -141,12 +162,13 @@ int find_new_uid (bool sys_user,
} }
/* /*
* If a user with UID equal to UID_MAX exists, the above algorithm * If a user (resp. system user) with UID equal to UID_MAX (resp.
* will give us UID_MAX+1 even if not unique. Search for the first * UID_MIN) exists, the above algorithm will give us UID_MAX+1
* free UID starting with UID_MIN. * (resp. UID_MIN-1) even if not unique. Search for the first free
* UID starting with UID_MIN (resp. UID_MAX).
*/ */
if (sys_user) { if (sys_user) {
if (user_id == uid_min - 1) { if (user_id < uid_min) {
for (user_id = uid_max; user_id >= uid_min; user_id--) { for (user_id = uid_max; user_id >= uid_min; user_id--) {
if (false == used_uids[user_id]) { if (false == used_uids[user_id]) {
break; break;
@@ -158,26 +180,29 @@ int find_new_uid (bool sys_user,
Prog); Prog);
SYSLOG ((LOG_WARN, SYSLOG ((LOG_WARN,
"no more available UID on the system")); "no more available UID on the system"));
free (used_uids);
return -1; return -1;
} }
} }
} else { } else {
if (user_id == uid_max + 1) { if (user_id > uid_max) {
for (user_id = uid_min; user_id < uid_max; user_id++) { for (user_id = uid_min; user_id <= uid_max; user_id++) {
if (false == used_uids[user_id]) { if (false == used_uids[user_id]) {
break; break;
} }
} }
if (user_id == uid_max) { if (user_id > uid_max) {
fprintf (stderr, fprintf (stderr,
_("%s: Can't get unique UID (no more available UIDs)\n"), _("%s: Can't get unique UID (no more available UIDs)\n"),
Prog); Prog);
SYSLOG ((LOG_WARN, "no more available UID on the system")); SYSLOG ((LOG_WARN, "no more available UID on the system"));
free (used_uids);
return -1; return -1;
} }
} }
} }
free (used_uids);
*uid = user_id; *uid = user_id;
return 0; return 0;
} }
+1 -1
View File
@@ -35,5 +35,5 @@
#include <config.h> #include <config.h>
#include "defines.h" #include "defines.h"
time_t get_date (const char *, const time_t *); time_t get_date (const char *p, /*@null@*/const time_t *now);
#endif #endif
+1 -1
View File
@@ -44,7 +44,7 @@
* The string may be a valid GID or a valid groupname. * The string may be a valid GID or a valid groupname.
* If the group does not exist on the system, NULL is returned. * If the group does not exist on the system, NULL is returned.
*/ */
extern /*@null@*/struct group *getgr_nam_gid (const char *grname) extern /*@only@*//*@null@*/struct group *getgr_nam_gid (/*@null@*/const char *grname)
{ {
long long int gid; long long int gid;
char *endptr; char *endptr;
+3 -3
View File
@@ -3,7 +3,7 @@
* Copyright (c) 1991 - 1993, Chip Rosenthal * Copyright (c) 1991 - 1993, Chip Rosenthal
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François * Copyright (c) 2008 - 2010, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -50,7 +50,7 @@
bool hushed (const char *username) bool hushed (const char *username)
{ {
struct passwd *pw; struct passwd *pw;
char *hushfile; const char *hushfile;
char buf[BUFSIZ]; char buf[BUFSIZ];
bool found; bool found;
FILE *fp; FILE *fp;
@@ -76,7 +76,7 @@ bool hushed (const char *username)
*/ */
if (hushfile[0] != '/') { if (hushfile[0] != '/') {
snprintf (buf, sizeof (buf), "%s/%s", pw->pw_dir, hushfile); (void) snprintf (buf, sizeof (buf), "%s/%s", pw->pw_dir, hushfile);
return (access (buf, F_OK) == 0); return (access (buf, F_OK) == 0);
} }
+143
View File
@@ -0,0 +1,143 @@
/*
* Copyright (c) 2013 Eric Biederman
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include "prototypes.h"
#include "idmapping.h"
struct map_range *get_map_ranges(int ranges, int argc, char **argv)
{
struct map_range *mappings, *mapping;
int idx, argidx;
if (ranges < 0 || argc < 0) {
fprintf(stderr, "%s: error calculating number of arguments\n", Prog);
return NULL;
}
if (ranges != ((argc + 2) / 3)) {
fprintf(stderr, "%s: ranges: %u is wrong for argc: %d\n", Prog, ranges, argc);
return NULL;
}
if ((ranges * 3) > argc) {
fprintf(stderr, "ranges: %u argc: %d\n",
ranges, argc);
fprintf(stderr,
_( "%s: Not enough arguments to form %u mappings\n"),
Prog, ranges);
return NULL;
}
mappings = calloc(ranges, sizeof(*mappings));
if (!mappings) {
fprintf(stderr, _( "%s: Memory allocation failure\n"),
Prog);
exit(EXIT_FAILURE);
}
/* Gather up the ranges from the command line */
mapping = mappings;
for (idx = 0, argidx = 0; idx < ranges; idx++, argidx += 3, mapping++) {
if (!getulong(argv[argidx + 0], &mapping->upper)) {
free(mappings);
return NULL;
}
if (!getulong(argv[argidx + 1], &mapping->lower)) {
free(mappings);
return NULL;
}
if (!getulong(argv[argidx + 2], &mapping->count)) {
free(mappings);
return NULL;
}
}
return mappings;
}
/* Number of ascii digits needed to print any unsigned long in decimal.
* There are approximately 10 bits for every 3 decimal digits.
* So from bits to digits the formula is roundup((Number of bits)/10) * 3.
* For common sizes of integers this works out to:
* 2bytes --> 6 ascii estimate -> 65536 (5 real)
* 4bytes --> 12 ascii estimated -> 4294967296 (10 real)
* 8bytes --> 21 ascii estimated -> 18446744073709551616 (20 real)
* 16bytes --> 39 ascii estimated -> 340282366920938463463374607431768211456 (39 real)
*/
#define ULONG_DIGITS ((((sizeof(unsigned long) * CHAR_BIT) + 9)/10)*3)
void write_mapping(int proc_dir_fd, int ranges, struct map_range *mappings,
const char *map_file)
{
int idx;
struct map_range *mapping;
size_t bufsize;
char *buf, *pos;
int fd;
bufsize = ranges * ((ULONG_DIGITS + 1) * 3);
pos = buf = xmalloc(bufsize);
/* Build the mapping command */
mapping = mappings;
for (idx = 0; idx < ranges; idx++, mapping++) {
/* Append this range to the string that will be written */
int written = snprintf(pos, bufsize - (pos - buf),
"%lu %lu %lu\n",
mapping->upper,
mapping->lower,
mapping->count);
if ((written <= 0) || (written >= (bufsize - (pos - buf)))) {
fprintf(stderr, _("%s: snprintf failed!\n"), Prog);
exit(EXIT_FAILURE);
}
pos += written;
}
/* Write the mapping to the maping file */
fd = openat(proc_dir_fd, map_file, O_WRONLY);
if (fd < 0) {
fprintf(stderr, _("%s: open of %s failed: %s\n"),
Prog, map_file, strerror(errno));
exit(EXIT_FAILURE);
}
if (write(fd, buf, pos - buf) != (pos - buf)) {
fprintf(stderr, _("%s: write to %s failed: %s\n"),
Prog, map_file, strerror(errno));
exit(EXIT_FAILURE);
}
close(fd);
}
+12 -40
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009 , Dan Walsh <dwalsh@redhat.com> * Copyright (c) 2013 Eric Biederman
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -26,47 +26,19 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <config.h>
#ident "$Id$" #ifndef _IDMAPPING_H_
#define _IDMAPPING_H_
#include <stdio.h> struct map_range {
#include <sys/wait.h> unsigned long upper; /* first ID inside the namespace */
#include <fcntl.h> unsigned long lower; /* first ID outside the namespace */
#include "prototypes.h" unsigned long count; /* Length of the inside and outside ranges */
#include "defines.h" };
int safe_system (const char *command, extern struct map_range *get_map_ranges(int ranges, int argc, char **argv);
const char *argv[], extern void write_mapping(int proc_dir_fd, int ranges,
const char *env[], struct map_range *mappings, const char *map_file);
int ignore_stderr)
{
int status = -1;
int fd;
pid_t pid;
pid = fork();
if (pid < 0) {
return -1;
}
if (pid) { /* Parent */ #endif /* _ID_MAPPING_H_ */
if (waitpid (pid, &status, 0) > 0) {
return status;
} else {
return -1;
}
}
fd = open ("/dev/null", O_RDWR);
/* Child */
dup2 (fd, 0); // Close Stdin
if (ignore_stderr) {
dup2 (fd, 2); // Close Stderr
}
execve (command, (char *const *) argv, (char *const *) env);
fprintf (stderr, _("Failed to exec '%s'\n"), argv[0]);
exit (EXIT_FAILURE);
}
+1 -1
View File
@@ -107,7 +107,7 @@ int isexpired (const struct passwd *pw, /*@null@*/const struct spwd *sp)
if ( (-1 == sp->sp_lstchg) if ( (-1 == sp->sp_lstchg)
|| (-1 == sp->sp_max) || (-1 == sp->sp_max)
|| (sp->sp_max >= (10000L * DAY / SCALE))) { || (sp->sp_max >= ((10000L * DAY) / SCALE))) {
return 0; return 0;
} }
+184 -70
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh * Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz * Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko * Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2008, Nicolas François * Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@
/* /*
* Separated from setup.c. --marekm * Separated from setup.c. --marekm
* Resource limits thanks to Cristian Gafton. * Resource limits thanks to Cristian Gafton.
* Enhancements of resource limit code by Thomas Orgis <thomas@orgis.org>
*/ */
#include <config.h> #include <config.h>
@@ -44,6 +45,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <stdio.h> #include <stdio.h>
#include <ctype.h>
#include "prototypes.h" #include "prototypes.h"
#include "defines.h" #include "defines.h"
#include <pwd.h> #include <pwd.h>
@@ -64,22 +66,46 @@
* value - string value to be read * value - string value to be read
* multiplier - value*multiplier is the actual limit * multiplier - value*multiplier is the actual limit
*/ */
static int static int setrlimit_value (unsigned int resource,
setrlimit_value (unsigned int resource, const char *value, const char *value,
unsigned int multiplier) unsigned int multiplier)
{ {
struct rlimit rlim; struct rlimit rlim;
long limit; rlim_t limit;
if (getlong (value, &limit) == 0) { /* The "-" is special, not belonging to a strange negative limit.
return 0; * It is infinity, in a controlled way.
*/
if ('-' == value[0]) {
limit = RLIM_INFINITY;
} }
limit *= multiplier; else {
if (limit != (rlim_t) limit) { /* We cannot use getlong here because it fails when there
return 0; * is more to the value than just this number!
* Also, we are limited to base 10 here (hex numbers will not
* work with the limit string parser as is anyway)
*/
char *endptr;
long longlimit = strtol (value, &endptr, 10);
if ((0 == longlimit) && (value == endptr)) {
/* No argument at all. No-op.
* FIXME: We could instead throw an error, though.
*/
return 0;
}
longlimit *= multiplier;
limit = (rlim_t)longlimit;
if (longlimit != limit)
{
/* FIXME: Again, silent error handling...
* Wouldn't screaming make more sense?
*/
return 0;
}
} }
rlim.rlim_cur = (rlim_t) limit;
rlim.rlim_max = (rlim_t) limit; rlim.rlim_cur = limit;
rlim.rlim_max = limit;
if (setrlimit (resource, &rlim) != 0) { if (setrlimit (resource, &rlim) != 0) {
return LOGIN_ERROR_RLIMIT; return LOGIN_ERROR_RLIMIT;
} }
@@ -138,11 +164,12 @@ static int check_logins (const char *name, const char *maxlogins)
count = 0; count = 0;
#ifdef USE_UTMPX #ifdef USE_UTMPX
setutxent (); setutxent ();
while ((ut = getutxent ())) { while ((ut = getutxent ()))
#else /* !USE_UTMPX */ #else /* !USE_UTMPX */
setutent (); setutent ();
while ((ut = getutent ())) { while ((ut = getutent ()))
#endif /* !USE_UTMPX */ #endif /* !USE_UTMPX */
{
if (USER_PROCESS != ut->ut_type) { if (USER_PROCESS != ut->ut_type) {
continue; continue;
} }
@@ -167,8 +194,9 @@ static int check_logins (const char *name, const char *maxlogins)
* includes the user who is currently trying to log in. * includes the user who is currently trying to log in.
*/ */
if (count > limit) { if (count > limit) {
SYSLOG ((LOG_WARN, "Too many logins (max %d) for %s\n", SYSLOG ((LOG_WARN,
limit, name)); "Too many logins (max %lu) for %s\n",
limit, name));
return LOGIN_ERROR_LOGIN; return LOGIN_ERROR_LOGIN;
} }
return 0; return 0;
@@ -186,17 +214,20 @@ static int check_logins (const char *name, const char *maxlogins)
* [Cc]: c = RLIMIT_CORE max core file size (KB) * [Cc]: c = RLIMIT_CORE max core file size (KB)
* [Dd]: d = RLIMIT_DATA max data size (KB) * [Dd]: d = RLIMIT_DATA max data size (KB)
* [Ff]: f = RLIMIT_FSIZE max file size (KB) * [Ff]: f = RLIMIT_FSIZE max file size (KB)
* [Ii]: i = RLIMIT_NICE max nice value (0..39 translates to 20..-19)
* [Kk]: k = file creation masK (umask)
* [Ll]: l = max number of logins for this user
* [Mm]: m = RLIMIT_MEMLOCK max locked-in-memory address space (KB) * [Mm]: m = RLIMIT_MEMLOCK max locked-in-memory address space (KB)
* [Nn]: n = RLIMIT_NOFILE max number of open files * [Nn]: n = RLIMIT_NOFILE max number of open files
* [Oo]: o = RLIMIT_RTPRIO max real time priority (linux/sched.h 0..MAX_RT_PRIO)
* [Pp]: p = process priority -20..20 (negative = high, positive = low)
* [Rr]: r = RLIMIT_RSS max resident set size (KB) * [Rr]: r = RLIMIT_RSS max resident set size (KB)
* [Ss]: s = RLIMIT_STACK max stack size (KB) * [Ss]: s = RLIMIT_STACK max stack size (KB)
* [Tt]: t = RLIMIT_CPU max CPU time (MIN) * [Tt]: t = RLIMIT_CPU max CPU time (MIN)
* [Uu]: u = RLIMIT_NPROC max number of processes * [Uu]: u = RLIMIT_NPROC max number of processes
* [Kk]: k = file creation masK (umask) *
* [Ll]: l = max number of logins for this user * NOTE: Remember to extend the "no-limits" string below when adding a new
* [Pp]: p = process priority -20..20 (negative = high, positive = low) * limit...
* [Ii]: i = RLIMIT_NICE max nice value (0..39 translates to 20..-19)
* [Oo]: o = RLIMIT_RTPRIO max real time priority (linux/sched.h 0..MAX_RT_PRIO)
* *
* Return value: * Return value:
* 0 = okay, of course * 0 = okay, of course
@@ -213,6 +244,24 @@ static int do_user_limits (const char *buf, const char *name)
bool reported = false; bool reported = false;
pp = buf; pp = buf;
/* Skip leading whitespace. */
while ((' ' == *pp) || ('\t' == *pp)) {
pp++;
}
/* The special limit string "-" results in no limit for all known
* limits.
* We achieve that by parsing a full limit string, parts of it
* being ignored if a limit type is not known to the system.
* Though, there will be complaining for unknown limit types.
*/
if (strcmp (pp, "-") == 0) {
/* Remember to extend this, too, when adding new limits!
* Oh... but "unlimited" does not make sense for umask,
* or does it? (K-)
*/
pp = "A- C- D- F- I- L- M- N- O- P- R- S- T- U-";
}
while ('\0' != *pp) { while ('\0' != *pp) {
switch (*pp++) { switch (*pp++) {
@@ -223,11 +272,11 @@ static int do_user_limits (const char *buf, const char *name)
retval |= setrlimit_value (RLIMIT_AS, pp, 1024); retval |= setrlimit_value (RLIMIT_AS, pp, 1024);
break; break;
#endif #endif
#ifdef RLIMIT_CPU #ifdef RLIMIT_CORE
case 't': case 'c':
case 'T': case 'C':
/* RLIMIT_CPU - max CPU time (MIN) */ /* RLIMIT_CORE - max core file size (KB) */
retval |= setrlimit_value (RLIMIT_CPU, pp, 60); retval |= setrlimit_value (RLIMIT_CORE, pp, 1024);
break; break;
#endif #endif
#ifdef RLIMIT_DATA #ifdef RLIMIT_DATA
@@ -244,20 +293,22 @@ static int do_user_limits (const char *buf, const char *name)
retval |= setrlimit_value (RLIMIT_FSIZE, pp, 1024); retval |= setrlimit_value (RLIMIT_FSIZE, pp, 1024);
break; break;
#endif #endif
#ifdef RLIMIT_NPROC #ifdef RLIMIT_NICE
case 'u': case 'i':
case 'U': case 'I':
/* RLIMIT_NPROC - max number of processes */ /* RLIMIT_NICE - max scheduling priority (0..39) */
retval |= setrlimit_value (RLIMIT_NPROC, pp, 1); retval |= setrlimit_value (RLIMIT_NICE, pp, 1);
break; break;
#endif #endif
#ifdef RLIMIT_CORE case 'k':
case 'c': case 'K':
case 'C': retval |= set_umask (pp);
/* RLIMIT_CORE - max core file size (KB) */ break;
retval |= setrlimit_value (RLIMIT_CORE, pp, 1024); case 'l':
case 'L':
/* LIMIT the number of concurrent logins */
retval |= check_logins (name, pp);
break; break;
#endif
#ifdef RLIMIT_MEMLOCK #ifdef RLIMIT_MEMLOCK
case 'm': case 'm':
case 'M': case 'M':
@@ -272,6 +323,17 @@ static int do_user_limits (const char *buf, const char *name)
retval |= setrlimit_value (RLIMIT_NOFILE, pp, 1); retval |= setrlimit_value (RLIMIT_NOFILE, pp, 1);
break; break;
#endif #endif
#ifdef RLIMIT_RTPRIO
case 'o':
case 'O':
/* RLIMIT_RTPRIO - max real time priority (0..MAX_RT_PRIO) */
retval |= setrlimit_value (RLIMIT_RTPRIO, pp, 1);
break;
#endif
case 'p':
case 'P':
retval |= set_prio (pp);
break;
#ifdef RLIMIT_RSS #ifdef RLIMIT_RSS
case 'r': case 'r':
case 'R': case 'R':
@@ -286,35 +348,28 @@ static int do_user_limits (const char *buf, const char *name)
retval |= setrlimit_value (RLIMIT_STACK, pp, 1024); retval |= setrlimit_value (RLIMIT_STACK, pp, 1024);
break; break;
#endif #endif
#ifdef RLIMIT_NICE #ifdef RLIMIT_CPU
case 'i': case 't':
case 'I': case 'T':
/* RLIMIT_NICE - max scheduling priority (0..39) */ /* RLIMIT_CPU - max CPU time (MIN) */
retval |= setrlimit_value (RLIMIT_NICE, pp, 1); retval |= setrlimit_value (RLIMIT_CPU, pp, 60);
break; break;
#endif #endif
#ifdef RLIMIT_RTPRIO #ifdef RLIMIT_NPROC
case 'o': case 'u':
case 'O': case 'U':
/* RLIMIT_RTPRIO - max real time priority (0..MAX_RT_PRIO) */ /* RLIMIT_NPROC - max number of processes */
retval |= setrlimit_value (RLIMIT_RTPRIO, pp, 1); retval |= setrlimit_value (RLIMIT_NPROC, pp, 1);
break; break;
#endif #endif
case 'k':
case 'K':
retval |= set_umask (pp);
break;
case 'l':
case 'L':
/* LIMIT the number of concurrent logins */
retval |= check_logins (name, pp);
break;
case 'p':
case 'P':
retval |= set_prio (pp);
break;
default: default:
/* Only report invalid strings once */ /* Only report invalid strings once */
/* Note: A string can be invalid just because a
* specific (theoretically valid) setting is not
* supported by this build.
* It is just a warning in syslog anyway. The line
* is still processed
*/
if (!reported) { if (!reported) {
SYSLOG ((LOG_WARN, SYSLOG ((LOG_WARN,
"Invalid limit string: '%s'", "Invalid limit string: '%s'",
@@ -323,13 +378,51 @@ static int do_user_limits (const char *buf, const char *name)
retval |= LOGIN_ERROR_RLIMIT; retval |= LOGIN_ERROR_RLIMIT;
} }
} }
/* After parsing one limit setting (or just complaining
* about it), one still needs to skip its argument to
* prevent a bogus warning on trying to parse that as
* limit specification.
* So, let's skip all digits, "-" and our limited set of
* whitespace.
*/
while ( isdigit (*pp)
|| ('-' == *pp)
|| (' ' == *pp)
|| ('\t' ==*pp)) {
pp++;
}
} }
return retval; return retval;
} }
/* Check if user uname is in the group gname.
* Can I be sure that gr_mem contains no UID as string?
* Returns true when user is in the group, false when not.
* Any error is treated as false.
*/
static bool user_in_group (const char *uname, const char *gname)
{
struct group *groupdata;
if (uname == NULL || gname == NULL){
return false;
}
/* We are not claiming to be re-entrant!
* In case of paranoia or a multithreaded login program,
* one needs to add some mess for getgrnam_r. */
groupdata = getgrnam (gname);
if (NULL == groupdata) {
SYSLOG ((LOG_WARN, "Nonexisting group `%s' in limits file.",
gname));
return false;
}
return is_on_list (groupdata->gr_mem, uname);
}
static int setup_user_limits (const char *uname) static int setup_user_limits (const char *uname)
{ {
/* TODO: allow and use @group syntax --cristiang */
FILE *fil; FILE *fil;
char buf[1024]; char buf[1024];
char name[1024]; char name[1024];
@@ -351,8 +444,10 @@ static int setup_user_limits (const char *uname)
} }
/* The limits file have the following format: /* The limits file have the following format:
* - '#' (comment) chars only as first chars on a line; * - '#' (comment) chars only as first chars on a line;
* - username must start on first column * - username must start on first column (or *, or @group)
* A better (smarter) checking should be done --cristiang */ *
* FIXME: A better (smarter) checking should be done
*/
while (fgets (buf, 1024, fil) != NULL) { while (fgets (buf, 1024, fil) != NULL) {
if (('#' == buf[0]) || ('\n' == buf[0])) { if (('#' == buf[0]) || ('\n' == buf[0])) {
continue; continue;
@@ -364,15 +459,35 @@ static int setup_user_limits (const char *uname)
* username L2 D2048 R4096 * username L2 D2048 R4096
* where spaces={' ',\t}. Also, we reject invalid limits. * where spaces={' ',\t}. Also, we reject invalid limits.
* Imposing a limit should be done with care, so a wrong * Imposing a limit should be done with care, so a wrong
* entry means no care anyway :-). A '-' as a limits * entry means no care anyway :-).
* strings means no limits --cristiang */ *
if (sscanf (buf, "%s%[ACDFMNRSTULPIOacdfmnrstulpio0-9 \t-]", * A '-' as a limits strings means no limits
name, tempbuf) == 2) { *
* The username can also be:
* '*': the default limits (only the last is taken into
* account)
* @group: the limit applies to the members of the group
*
* To clarify: The first entry with matching user name rules,
* everything after it is ignored. If there is no user entry,
* the last encountered entry for a matching group rules.
* If there is no matching group entry, the default limits rule.
*/
if (sscanf (buf, "%s%[ACDFIKLMNOPRSTUacdfiklmnoprstu0-9 \t-]",
name, tempbuf) == 2) {
if (strcmp (name, uname) == 0) { if (strcmp (name, uname) == 0) {
strcpy (limits, tempbuf); strcpy (limits, tempbuf);
break; break;
} else if (strcmp (name, "*") == 0) { } else if (strcmp (name, "*") == 0) {
strcpy (deflimits, tempbuf); strcpy (deflimits, tempbuf);
} else if (name[0] == '@') {
/* If the user is in the group, the group
* limits apply unless later a line for
* the specific user is found.
*/
if (user_in_group (uname, name+1)) {
strcpy (limits, tempbuf);
}
} }
} }
} }
@@ -392,7 +507,6 @@ static int setup_user_limits (const char *uname)
static void setup_usergroups (const struct passwd *info) static void setup_usergroups (const struct passwd *info)
{ {
const struct group *grp; const struct group *grp;
mode_t tmpmask;
/* /*
* if not root, and UID == GID, and username is the same as primary * if not root, and UID == GID, and username is the same as primary
@@ -404,6 +518,7 @@ static void setup_usergroups (const struct passwd *info)
grp = getgrgid (info->pw_gid); grp = getgrgid (info->pw_gid);
if ( (NULL != grp) if ( (NULL != grp)
&& (strcmp (info->pw_name, grp->gr_name) == 0)) { && (strcmp (info->pw_name, grp->gr_name) == 0)) {
mode_t tmpmask;
tmpmask = umask (0777); tmpmask = umask (0777);
tmpmask = (tmpmask & ~070) | ((tmpmask >> 3) & 070); tmpmask = (tmpmask & ~070) | ((tmpmask >> 3) & 070);
(void) umask (tmpmask); (void) umask (tmpmask);
@@ -432,8 +547,7 @@ void setup_limits (const struct passwd *info)
if (getdef_bool ("QUOTAS_ENAB")) { if (getdef_bool ("QUOTAS_ENAB")) {
#ifdef LIMITS #ifdef LIMITS
if (info->pw_uid != 0) { if (info->pw_uid != 0) {
if (setup_user_limits (info->pw_name) & if ((setup_user_limits (info->pw_name) & LOGIN_ERROR_LOGIN) != 0) {
LOGIN_ERROR_LOGIN) {
(void) fputs (_("Too many logins.\n"), stderr); (void) fputs (_("Too many logins.\n"), stderr);
(void) sleep (2); /* XXX: Should be FAIL_DELAY */ (void) sleep (2); /* XXX: Should be FAIL_DELAY */
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
+13 -1
View File
@@ -141,6 +141,12 @@
return tmp; return tmp;
} }
/*
* Duplicate a list.
* The input list is not modified, but in order to allow the use of this
* function with list of members, the list elements are not enforced to be
* constant strings here.
*/
/*@only@*/ /*@out@*/char **dup_list (char *const *list) /*@only@*/ /*@out@*/char **dup_list (char *const *list)
{ {
int i; int i;
@@ -163,6 +169,12 @@
return tmp; return tmp;
} }
/*
* Check if member is part of the input list
* The input list is not modified, but in order to allow the use of this
* function with list of members, the list elements are not enforced to be
* constant strings here.
*/
bool is_on_list (char *const *list, const char *member) bool is_on_list (char *const *list, const char *member)
{ {
assert (NULL != member); assert (NULL != member);
@@ -187,7 +199,7 @@ bool is_on_list (char *const *list, const char *member)
char *members; char *members;
char **array; char **array;
int i; int i;
const char *cp; char *cp;
char *cp2; char *cp2;
assert (NULL != comma); assert (NULL != comma);
+8 -9
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1993, Julianne Frances Haugh * Copyright (c) 1989 - 1993, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François * Copyright (c) 2008 - 2011, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -60,7 +60,6 @@ void login_prompt (const char *prompt, char *name, int namesize)
#define MAX_ENV 32 #define MAX_ENV 32
char *envp[MAX_ENV]; char *envp[MAX_ENV];
int envc;
char *cp; char *cp;
int i; int i;
FILE *fp; FILE *fp;
@@ -88,9 +87,9 @@ void login_prompt (const char *prompt, char *name, int namesize)
*/ */
if (NULL != prompt) { if (NULL != prompt) {
cp = getdef_str ("ISSUE_FILE"); const char *fname = getdef_str ("ISSUE_FILE");
if (NULL != cp) { if (NULL != fname) {
fp = fopen (cp, "r"); fp = fopen (fname, "r");
if (NULL != fp) { if (NULL != fp) {
while ((i = getc (fp)) != EOF) { while ((i = getc (fp)) != EOF) {
(void) putc (i, stdout); (void) putc (i, stdout);
@@ -99,7 +98,7 @@ void login_prompt (const char *prompt, char *name, int namesize)
(void) fclose (fp); (void) fclose (fp);
} }
} }
gethostname (buf, sizeof buf); (void) gethostname (buf, sizeof buf);
printf (prompt, buf); printf (prompt, buf);
(void) fflush (stdout); (void) fflush (stdout);
} }
@@ -148,6 +147,7 @@ void login_prompt (const char *prompt, char *name, int namesize)
if ('\0' != *cp) { /* process new variables */ if ('\0' != *cp) { /* process new variables */
char *nvar; char *nvar;
int count = 1; int count = 1;
int envc;
for (envc = 0; envc < MAX_ENV; envc++) { for (envc = 0; envc < MAX_ENV; envc++) {
nvar = strtok ((0 != envc) ? (char *) 0 : cp, " \t,"); nvar = strtok ((0 != envc) ? (char *) 0 : cp, " \t,");
@@ -158,10 +158,9 @@ void login_prompt (const char *prompt, char *name, int namesize)
envp[envc] = nvar; envp[envc] = nvar;
} else { } else {
size_t len = strlen (nvar) + 32; size_t len = strlen (nvar) + 32;
int wlen;
envp[envc] = xmalloc (len); envp[envc] = xmalloc (len);
wlen = snprintf (envp[envc], len, "L%d=%s", count++, nvar); (void) snprintf (envp[envc], len,
assert (wlen == (int) len -1); "L%d=%s", count++, nvar);
} }
} }
set_env (envc, envp); set_env (envc, envp);
+21 -7
View File
@@ -2,6 +2,7 @@
* Copyright (c) 1989 - 1991, Julianne Frances Haugh * Copyright (c) 1989 - 1991, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz * Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2010 , Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -47,21 +48,34 @@
void motd (void) void motd (void)
{ {
FILE *fp; FILE *fp;
char motdlist[BUFSIZ], *motdfile, *mb; char *motdlist;
const char *motdfile;
char *mb;
register int c; register int c;
if ((mb = getdef_str ("MOTD_FILE")) == NULL) motdfile = getdef_str ("MOTD_FILE");
if (NULL == motdfile) {
return; return;
}
strncpy (motdlist, mb, sizeof (motdlist)); motdlist = xstrdup (motdfile);
motdlist[sizeof (motdlist) - 1] = '\0';
for (mb = motdlist; (motdfile = strtok (mb, ":")) != NULL; mb = NULL) { for (mb = motdlist; ;mb = NULL) {
if ((fp = fopen (motdfile, "r")) != NULL) { motdfile = strtok (mb, ":");
while ((c = getc (fp)) != EOF) if (NULL == motdfile) {
break;
}
fp = fopen (motdfile, "r");
if (NULL != fp) {
while ((c = getc (fp)) != EOF) {
putchar (c); putchar (c);
}
fclose (fp); fclose (fp);
} }
} }
fflush (stdout); fflush (stdout);
free (motdlist);
} }
+16 -13
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh * Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz * Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2008, Nicolas François * Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -69,7 +69,7 @@ static bool palindrome (unused const char *old, const char *new)
* more than half of the characters are different ones. * more than half of the characters are different ones.
*/ */
static bool similar (const char *old, const char *new) static bool similar (/*@notnull@*/const char *old, /*@notnull@*/const char *new)
{ {
int i, j; int i, j;
@@ -100,7 +100,7 @@ static bool similar (const char *old, const char *new)
* a nice mix of characters. * a nice mix of characters.
*/ */
static int simple (unused const char *old, const char *new) static bool simple (unused const char *old, const char *new)
{ {
bool digits = false; bool digits = false;
bool uppers = false; bool uppers = false;
@@ -147,7 +147,7 @@ static int simple (unused const char *old, const char *new)
return true; return true;
} }
static char *str_lower (char *string) static char *str_lower (/*@returned@*/char *string)
{ {
char *cp; char *cp;
@@ -157,8 +157,10 @@ static char *str_lower (char *string)
return string; return string;
} }
static const char *password_check (const char *old, const char *new, static /*@observer@*//*@null@*/const char *password_check (
const struct passwd *pwdp) /*@notnull@*/const char *old,
/*@notnull@*/const char *new,
/*@notnull@*/const struct passwd *pwdp)
{ {
const char *msg = NULL; const char *msg = NULL;
char *oldmono, *newmono, *wrapped; char *oldmono, *newmono, *wrapped;
@@ -219,14 +221,15 @@ static const char *password_check (const char *old, const char *new,
return msg; return msg;
} }
/*ARGSUSED*/ static /*@observer@*//*@null@*/const char *obscure_msg (
static const char *obscure_msg (const char *old, const char *new, /*@notnull@*/const char *old,
const struct passwd *pwdp) /*@notnull@*/const char *new,
/*@notnull@*/const struct passwd *pwdp)
{ {
size_t maxlen, oldlen, newlen; size_t maxlen, oldlen, newlen;
char *new1, *old1; char *new1, *old1;
const char *msg; const char *msg;
char *result; const char *result;
oldlen = strlen (old); oldlen = strlen (old);
newlen = strlen (new); newlen = strlen (new);
@@ -304,15 +307,15 @@ static const char *obscure_msg (const char *old, const char *new,
* check passwords. * check passwords.
*/ */
int obscure (const char *old, const char *new, const struct passwd *pwdp) bool obscure (const char *old, const char *new, const struct passwd *pwdp)
{ {
const char *msg = obscure_msg (old, new, pwdp); const char *msg = obscure_msg (old, new, pwdp);
if (NULL != msg) { if (NULL != msg) {
printf (_("Bad password: %s. "), msg); printf (_("Bad password: %s. "), msg);
return 0; return false;
} }
return 1; return true;
} }
#else /* !USE_PAM */ #else /* !USE_PAM */
+2 -2
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009, Nicolas François * Copyright (c) 2009 - 2010, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,7 @@
#include <security/pam_appl.h> #include <security/pam_appl.h>
#include "prototypes.h" #include "prototypes.h"
/*@null@*/ /*@only@*/static char *non_interactive_password = NULL; /*@null@*/ /*@only@*/static const char *non_interactive_password = NULL;
static int ni_conv (int num_msg, static int ni_conv (int num_msg,
const struct pam_message **msg, const struct pam_message **msg,
struct pam_response **resp, struct pam_response **resp,
+133
View File
@@ -0,0 +1,133 @@
/*
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2001, Marek Michałkiewicz
* Copyright (c) 2003 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id$"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include "prototypes.h"
#include "defines.h"
/*
* remove_tree - delete a directory tree
*
* remove_tree() walks a directory tree and deletes all the files
* and directories.
* At the end, it deletes the root directory itself.
*/
int remove_tree (const char *root, bool remove_root)
{
char *new_name = NULL;
int err = 0;
struct DIRECT *ent;
struct stat sb;
DIR *dir;
/*
* Open the source directory and read each entry. Every file
* entry in the directory is copied with the UID and GID set
* to the provided values. As an added security feature only
* regular files (and directories ...) are copied, and no file
* is made set-ID.
*/
dir = opendir (root);
if (NULL == dir) {
return -1;
}
while ((ent = readdir (dir))) {
size_t new_len = strlen (root) + strlen (ent->d_name) + 2;
/*
* Skip the "." and ".." entries
*/
if (strcmp (ent->d_name, ".") == 0 ||
strcmp (ent->d_name, "..") == 0) {
continue;
}
/*
* Make the filename for the current entry.
*/
free (new_name);
new_name = (char *) malloc (new_len);
if (NULL == new_name) {
err = -1;
break;
}
(void) snprintf (new_name, new_len, "%s/%s", root, ent->d_name);
if (LSTAT (new_name, &sb) == -1) {
continue;
}
if (S_ISDIR (sb.st_mode)) {
/*
* Recursively delete this directory.
*/
if (remove_tree (new_name, true) != 0) {
err = -1;
break;
}
} else {
/*
* Delete the file.
*/
if (unlink (new_name) != 0) {
err = -1;
break;
}
}
}
if (NULL != new_name) {
free (new_name);
}
(void) closedir (dir);
if (remove_root && (0 == err)) {
if (rmdir (root) != 0) {
err = -1;
}
}
return err;
}
+124
View File
@@ -0,0 +1,124 @@
/*
* Copyright (c) 2011 , Julian Pidancet
* Copyright (c) 2011 , Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the copyright holders or contributors may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ident "$Id$"
#include <stdio.h>
#include <assert.h>
#include "defines.h"
#include "prototypes.h"
/*@-exitarg@*/
#include "exitcodes.h"
static void change_root (const char* newroot);
/*
* process_root_flag - chroot if given the --root option
*
* This shall be called before accessing the passwd, group, shadow,
* gshadow, useradd's default, login.defs files (non exhaustive list)
* or authenticating the caller.
*
* The audit, syslog, or locale files shall be open before
*/
extern void process_root_flag (const char* short_opt, int argc, char **argv)
{
/*
* Parse the command line options.
*/
int i;
const char *newroot = NULL;
for (i = 0; i < argc; i++) {
if ( (strcmp (argv[i], "--root") == 0)
|| (strcmp (argv[i], short_opt) == 0)) {
if (NULL != newroot) {
fprintf (stderr,
_("%s: multiple --root options\n"),
Prog);
exit (E_BAD_ARG);
}
if (i + 1 == argc) {
fprintf (stderr,
_("%s: option '%s' requires an argument\n"),
Prog, argv[i]);
exit (E_BAD_ARG);
}
newroot = argv[i + 1];
}
}
if (NULL != newroot) {
change_root (newroot);
}
}
static void change_root (const char* newroot)
{
/* Drop privileges */
if ( (setregid (getgid (), getgid ()) != 0)
|| (setreuid (getuid (), getuid ()) != 0)) {
fprintf (stderr, _("%s: failed to drop privileges (%s)\n"),
Prog, strerror (errno));
exit (EXIT_FAILURE);
}
if ('/' != newroot[0]) {
fprintf (stderr,
_("%s: invalid chroot path '%s'\n"),
Prog, newroot);
exit (E_BAD_ARG);
}
if (access (newroot, F_OK) != 0) {
fprintf(stderr,
_("%s: cannot access chroot directory %s: %s\n"),
Prog, newroot, strerror (errno));
exit (E_BAD_ARG);
}
if (chdir (newroot) != 0) {
fprintf(stderr,
_("%s: cannot chdir to chroot directory %s: %s\n"),
Prog, newroot, strerror (errno));
exit (E_BAD_ARG);
}
if (chroot (newroot) != 0) {
fprintf(stderr,
_("%s: unable to chroot to directory %s: %s\n"),
Prog, newroot, strerror (errno));
exit (E_BAD_ARG);
}
}
+27 -24
View File
@@ -23,7 +23,7 @@
static void seedRNG (void); static void seedRNG (void);
static /*@observer@*/const char *gensalt (size_t salt_size); static /*@observer@*/const char *gensalt (size_t salt_size);
#ifdef USE_SHA_CRYPT #ifdef USE_SHA_CRYPT
static size_t SHA_salt_size (void); static long shadow_random (long min, long max);
static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds); static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds);
#endif /* USE_SHA_CRYPT */ #endif /* USE_SHA_CRYPT */
@@ -81,17 +81,29 @@ static void seedRNG (void)
#define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0' #define MAGNUM(array,ch) (array)[0]=(array)[2]='$',(array)[1]=(ch),(array)[3]='\0'
#ifdef USE_SHA_CRYPT #ifdef USE_SHA_CRYPT
/* It is not clear what is the maximum value of random().
* We assume 2^31-1.*/
#define RANDOM_MAX 0x7FFFFFFF
/* /*
* Return the salt size. * Return a random number between min and max (both included).
* The size of the salt string is between 8 and 16 bytes for the SHA crypt *
* methods. * It favors slightly the higher numbers.
*/ */
static size_t SHA_salt_size (void) static long shadow_random (long min, long max)
{ {
double rand_size; double drand;
long ret;
seedRNG (); seedRNG ();
rand_size = (double) 9.0 * random () / RAND_MAX; drand = (double) (max - min + 1) * random () / RANDOM_MAX;
return (size_t) (8 + rand_size); /* On systems were this is not random() range is lower, we favor
* higher numbers of salt. */
ret = (long) (max + 1 - drand);
/* And we catch limits, and use the highest number */
if ((ret < min) || (ret > max)) {
ret = max;
}
return ret;
} }
/* Default number of rounds if not explicitly specified. */ /* Default number of rounds if not explicitly specified. */
@@ -106,13 +118,12 @@ static size_t SHA_salt_size (void)
*/ */
static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds) static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds)
{ {
static char rounds_prefix[18]; static char rounds_prefix[18]; /* Max size: rounds=999999999$ */
long rounds; long rounds;
if (NULL == prefered_rounds) { if (NULL == prefered_rounds) {
long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1); long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1);
long max_rounds = getdef_long ("SHA_CRYPT_MAX_ROUNDS", -1); long max_rounds = getdef_long ("SHA_CRYPT_MAX_ROUNDS", -1);
double rand_rounds;
if ((-1 == min_rounds) && (-1 == max_rounds)) { if ((-1 == min_rounds) && (-1 == max_rounds)) {
return ""; return "";
@@ -130,10 +141,7 @@ static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds
max_rounds = min_rounds; max_rounds = min_rounds;
} }
seedRNG (); rounds = shadow_random (min_rounds, max_rounds);
rand_rounds = (double) (max_rounds-min_rounds+1.0) * random ();
rand_rounds /= RAND_MAX;
rounds = min_rounds + rand_rounds;
} else if (0 == *prefered_rounds) { } else if (0 == *prefered_rounds) {
return ""; return "";
} else { } else {
@@ -150,13 +158,8 @@ static /*@observer@*/const char *SHA_salt_rounds (/*@null@*/int *prefered_rounds
rounds = ROUNDS_MAX; rounds = ROUNDS_MAX;
} }
snprintf (rounds_prefix, 18, "rounds=%ld$", rounds); (void) snprintf (rounds_prefix, sizeof rounds_prefix,
"rounds=%ld$", rounds);
/* Sanity checks. That should not be necessary. */
rounds_prefix[17] = '\0';
if ('$' != rounds_prefix[16]) {
rounds_prefix[17] = '$';
}
return rounds_prefix; return rounds_prefix;
} }
@@ -202,7 +205,7 @@ static /*@observer@*/const char *gensalt (size_t salt_size)
* * For the SHA256 and SHA512 method, this specifies the number of rounds * * For the SHA256 and SHA512 method, this specifies the number of rounds
* (if not NULL). * (if not NULL).
*/ */
/*@observer@*/const char *crypt_make_salt (/*@null@*/const char *meth, /*@null@*/void *arg) /*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const char *meth, /*@null@*/void *arg)
{ {
/* Max result size for the SHA methods: /* Max result size for the SHA methods:
* +3 $5$ * +3 $5$
@@ -231,11 +234,11 @@ static /*@observer@*/const char *gensalt (size_t salt_size)
} else if (0 == strcmp (method, "SHA256")) { } else if (0 == strcmp (method, "SHA256")) {
MAGNUM(result, '5'); MAGNUM(result, '5');
strcat(result, SHA_salt_rounds((int *)arg)); strcat(result, SHA_salt_rounds((int *)arg));
salt_len = SHA_salt_size(); salt_len = (size_t) shadow_random (8, 16);
} else if (0 == strcmp (method, "SHA512")) { } else if (0 == strcmp (method, "SHA512")) {
MAGNUM(result, '6'); MAGNUM(result, '6');
strcat(result, SHA_salt_rounds((int *)arg)); strcat(result, SHA_salt_rounds((int *)arg));
salt_len = SHA_salt_size(); salt_len = (size_t) shadow_random (8, 16);
#endif /* USE_SHA_CRYPT */ #endif /* USE_SHA_CRYPT */
} else if (0 != strcmp (method, "DES")) { } else if (0 != strcmp (method, "DES")) {
fprintf (stderr, fprintf (stderr,
+2 -2
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh * Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1998, Marek Michałkiewicz * Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 - 2009, Nicolas François * Copyright (c) 2008 - 2010, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -131,7 +131,7 @@ int setup_uid_gid (const struct passwd *info)
#if defined (HAVE_INITGROUPS) && ! defined (USE_PAM) #if defined (HAVE_INITGROUPS) && ! defined (USE_PAM)
if (is_console) { if (is_console) {
char *cp = getdef_str ("CONSOLE_GROUPS"); const char *cp = getdef_str ("CONSOLE_GROUPS");
if ((NULL != cp) && (add_groups (cp) != 0)) { if ((NULL != cp) && (add_groups (cp) != 0)) {
perror ("Warning: add_groups"); perror ("Warning: add_groups");
+9 -7
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh * Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 - 2006, Tomasz Kłoczko * Copyright (c) 2001 - 2006, Tomasz Kłoczko
* Copyright (c) 2007 - 2009, Nicolas François * Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -74,7 +74,7 @@ static void read_env_file (const char *filename)
if (NULL == fp) { if (NULL == fp) {
return; return;
} }
while (fgets (buf, sizeof buf, fp) == buf) { while (fgets (buf, (int)(sizeof buf), fp) == buf) {
cp = strrchr (buf, '\n'); cp = strrchr (buf, '\n');
if (NULL == cp) { if (NULL == cp) {
break; break;
@@ -200,9 +200,9 @@ static void read_env_file (const char *filename)
void setup_env (struct passwd *info) void setup_env (struct passwd *info)
{ {
#ifndef USE_PAM #ifndef USE_PAM
char *envf; const char *envf;
#endif #endif
char *cp; const char *cp;
/* /*
* Change the current working directory to be the home directory * Change the current working directory to be the home directory
@@ -228,7 +228,8 @@ void setup_env (struct passwd *info)
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
(void) puts (_("No directory, logging in with HOME=/")); (void) puts (_("No directory, logging in with HOME=/"));
info->pw_dir = temp_pw_dir; free (info->pw_dir);
info->pw_dir = xstrdup (temp_pw_dir);
} }
/* /*
@@ -244,7 +245,8 @@ void setup_env (struct passwd *info)
if ((NULL == info->pw_shell) || ('\0' == *info->pw_shell)) { if ((NULL == info->pw_shell) || ('\0' == *info->pw_shell)) {
static char temp_pw_shell[] = SHELL; static char temp_pw_shell[] = SHELL;
info->pw_shell = temp_pw_shell; free (info->pw_shell);
info->pw_shell = xstrdup (temp_pw_shell);
} }
addenv ("SHELL", info->pw_shell); addenv ("SHELL", info->pw_shell);
@@ -265,7 +267,7 @@ void setup_env (struct passwd *info)
if (NULL == cp) { if (NULL == cp) {
/* not specified, use a minimal default */ /* not specified, use a minimal default */
addenv ("PATH=/bin:/usr/bin", NULL); addenv ((info->pw_uid == 0) ? "PATH=/sbin:/bin:/usr/sbin:/usr/bin" : "PATH=/bin:/usr/bin", NULL);
} else if (strchr (cp, '=')) { } else if (strchr (cp, '=')) {
/* specified as name=value (PATH=...) */ /* specified as name=value (PATH=...) */
addenv (cp, NULL); addenv (cp, NULL);
+5 -4
View File
@@ -68,7 +68,8 @@ int shell (const char *file, /*@null@*/const char *arg, char *const envp[])
* don't want to tell us what it is themselves. * don't want to tell us what it is themselves.
*/ */
if (arg == (char *) 0) { if (arg == (char *) 0) {
snprintf (arg0, sizeof arg0, "-%s", Basename ((char *) file)); (void) snprintf (arg0, sizeof arg0, "-%s", Basename ((char *) file));
arg0[sizeof arg0 - 1] = '\0';
arg = arg0; arg = arg0;
} }
@@ -77,7 +78,7 @@ int shell (const char *file, /*@null@*/const char *arg, char *const envp[])
* able to figure out what we are up to without too much * able to figure out what we are up to without too much
* grief. * grief.
*/ */
execle (file, arg, (char *) 0, envp); (void) execle (file, arg, (char *) 0, envp);
err = errno; err = errno;
if (access (file, R_OK|X_OK) == 0) { if (access (file, R_OK|X_OK) == 0) {
@@ -85,7 +86,7 @@ int shell (const char *file, /*@null@*/const char *arg, char *const envp[])
* Assume this is a shell script (with no shebang). * Assume this is a shell script (with no shebang).
* Interpret it with /bin/sh * Interpret it with /bin/sh
*/ */
execle (SHELL, "sh", "-", file, (char *)0, envp); (void) execle (SHELL, "sh", "-", file, (char *)0, envp);
err = errno; err = errno;
} }
@@ -94,7 +95,7 @@ int shell (const char *file, /*@null@*/const char *arg, char *const envp[])
* how to execute this stupid shell, so I might as well give * how to execute this stupid shell, so I might as well give
* up in disgust ... * up in disgust ...
*/ */
snprintf (arg0, sizeof arg0, _("Cannot execute %s"), file); (void) snprintf (arg0, sizeof arg0, _("Cannot execute %s"), file);
errno = err; errno = err;
perror (arg0); perror (arg0);
return err; return err;
+30 -2
View File
@@ -36,6 +36,8 @@
#include <config.h> #include <config.h>
#include <ctype.h>
#ident "$Id$" #ident "$Id$"
#include "defines.h" #include "defines.h"
@@ -44,6 +46,7 @@
#ifndef USE_GETDATE #ifndef USE_GETDATE
#define USE_GETDATE 1 #define USE_GETDATE 1
#endif #endif
#if USE_GETDATE #if USE_GETDATE
#include "getdate.h" #include "getdate.h"
/* /*
@@ -63,6 +66,8 @@
long strtoday (const char *str) long strtoday (const char *str)
{ {
time_t t; time_t t;
bool isnum = true;
const char *s = str;
/* /*
* get_date() interprets an empty string as the current date, * get_date() interprets an empty string as the current date,
@@ -73,9 +78,32 @@ long strtoday (const char *str)
return -1; return -1;
} }
t = get_date (str, (time_t *) 0); /* If a numerical value is provided, this is already a number of
* days since EPOCH.
*/
if ('-' == *s) {
s++;
}
while (' ' == *s) {
s++;
}
while (isnum && ('\0' != *s)) {
if (!isdigit (*s)) {
isnum = false;
}
s++;
}
if (isnum) {
long retdate;
if (getlong (str, &retdate) == 0) {
return -2;
}
return retdate;
}
t = get_date (str, NULL);
if ((time_t) - 1 == t) { if ((time_t) - 1 == t) {
return -1; return -2;
} }
/* convert seconds to days since 1970-01-01 */ /* convert seconds to days since 1970-01-01 */
return (long) (t + DAY / 2) / DAY; return (long) (t + DAY / 2) / DAY;
+6 -4
View File
@@ -43,7 +43,7 @@
/* /*
* subsystem - change to subsystem root * subsystem - change to subsystem root
* *
* A subsystem login is indicated by the presense of a "*" as * A subsystem login is indicated by the presence of a "*" as
* the first character of the login shell. The given home * the first character of the login shell. The given home
* directory will be used as the root of a new filesystem which * directory will be used as the root of a new filesystem which
* the user is actually logged into. * the user is actually logged into.
@@ -66,11 +66,13 @@ void subsystem (const struct passwd *pw)
* must be able to change into it. * must be able to change into it.
*/ */
if (chdir (pw->pw_dir) || chroot (pw->pw_dir)) { if ( (chdir (pw->pw_dir) != 0)
printf (_("Can't change root directory to '%s'\n"), || (chroot (pw->pw_dir) != 0)) {
pw->pw_dir); (void) printf (_("Can't change root directory to '%s'\n"),
pw->pw_dir);
SYSLOG ((LOG_WARN, NO_SUBROOT2, pw->pw_dir, pw->pw_name)); SYSLOG ((LOG_WARN, NO_SUBROOT2, pw->pw_dir, pw->pw_name));
closelog (); closelog ();
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
} }
+5 -3
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1992, Julianne Frances Haugh * Copyright (c) 1989 - 1992, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2001 - 2005, Tomasz Kłoczko * Copyright (c) 2001 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François * Copyright (c) 2008 - 2010, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -47,7 +47,7 @@
*/ */
void sulog (const char *tty, bool success, const char *oldname, const char *name) void sulog (const char *tty, bool success, const char *oldname, const char *name)
{ {
char *sulog_file; const char *sulog_file;
time_t now; time_t now;
struct tm *tm; struct tm *tm;
FILE *fp; FILE *fp;
@@ -62,8 +62,10 @@ void sulog (const char *tty, bool success, const char *oldname, const char *name
"FAILED su for %s by %s",name,oldname)); "FAILED su for %s by %s",name,oldname));
} }
if ((sulog_file = getdef_str ("SULOG_FILE")) == (char *) 0) sulog_file = getdef_str ("SULOG_FILE");
if (NULL == sulog_file) {
return; return;
}
oldgid = getgid (); oldgid = getgid ();
oldmask = umask (077); oldmask = umask (077);
+7 -7
View File
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh * Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1997, Marek Michałkiewicz * Copyright (c) 1996 - 1997, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2008 , Nicolas François * Copyright (c) 2008 - 2010, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -45,10 +45,10 @@ void ttytype (const char *line)
{ {
FILE *fp; FILE *fp;
char buf[BUFSIZ]; char buf[BUFSIZ];
char *typefile; const char *typefile;
char *cp; char *cp;
char type[BUFSIZ]; char type[1024] = "";
char port[BUFSIZ]; char port[1024];
if (getenv ("TERM") != NULL) { if (getenv ("TERM") != NULL) {
return; return;
@@ -76,12 +76,12 @@ void ttytype (const char *line)
*cp = '\0'; *cp = '\0';
} }
if ((sscanf (buf, "%s %s", type, port) == 2) && if ( (sscanf (buf, "%1023s %1023s", type, port) == 2)
(strcmp (line, port) == 0)) { && (strcmp (line, port) == 0)) {
break; break;
} }
} }
if ((feof (fp) == 0) && (ferror (fp) == 0)) { if ((feof (fp) == 0) && (ferror (fp) == 0) && (type[0] != '\0')) {
addenv ("TERM", type); addenv ("TERM", type);
} }
+13 -8
View File
@@ -3,7 +3,7 @@
* Copyright (c) 1991 - 1994, Chip Rosenthal * Copyright (c) 1991 - 1994, Chip Rosenthal
* Copyright (c) 1996 - 1998, Marek Michałkiewicz * Copyright (c) 1996 - 1998, Marek Michałkiewicz
* Copyright (c) 2003 - 2005, Tomasz Kłoczko * Copyright (c) 2003 - 2005, Tomasz Kłoczko
* Copyright (c) 2007 - 2008, Nicolas François * Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -49,23 +49,28 @@
* tz() determines the name of the local timezone by reading the * tz() determines the name of the local timezone by reading the
* contents of the file named by ``fname''. * contents of the file named by ``fname''.
*/ */
char *tz (const char *fname) /*@observer@*/const char *tz (const char *fname)
{ {
FILE *fp = 0; FILE *fp = NULL;
static char tzbuf[BUFSIZ]; static char tzbuf[BUFSIZ];
const char *def_tz = "TZ=CST6CDT"; const char *def_tz = "TZ=CST6CDT";
if ((fp = fopen (fname, "r")) == NULL || fp = fopen (fname, "r");
fgets (tzbuf, (int) sizeof (tzbuf), fp) == NULL) { if ( (NULL == fp)
if (!(def_tz = getdef_str ("ENV_TZ")) || def_tz[0] == '/') || (fgets (tzbuf, (int) sizeof (tzbuf), fp) == NULL)) {
def_tz = getdef_str ("ENV_TZ");
if ((NULL == def_tz) || ('/' == def_tz[0])) {
def_tz = "TZ=CST6CDT"; def_tz = "TZ=CST6CDT";
}
strcpy (tzbuf, def_tz); strcpy (tzbuf, def_tz);
} else } else {
tzbuf[strlen (tzbuf) - 1] = '\0'; tzbuf[strlen (tzbuf) - 1] = '\0';
}
if (fp) if (NULL != fp) {
(void) fclose (fp); (void) fclose (fp);
}
return tzbuf; return tzbuf;
} }
+43 -8
View File
@@ -38,12 +38,16 @@
#include <stdio.h> #include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
#include <dirent.h> #include <dirent.h>
#include <fcntl.h>
#include "defines.h" #include "defines.h"
#include "prototypes.h" #include "prototypes.h"
#ifdef ENABLE_SUBIDS
#include "subordinateio.h"
#endif /* ENABLE_SUBIDS */
#ifdef __linux__ #ifdef __linux__
static int check_status (const char *sname, uid_t uid); static int check_status (const char *name, const char *sname, uid_t uid);
static int user_busy_processes (uid_t uid); static int user_busy_processes (const char *name, uid_t uid);
#else /* !__linux__ */ #else /* !__linux__ */
static int user_busy_utmp (const char *name); static int user_busy_utmp (const char *name);
#endif /* !__linux__ */ #endif /* !__linux__ */
@@ -58,7 +62,7 @@ int user_busy (const char *name, uid_t uid)
*/ */
#ifdef __linux__ #ifdef __linux__
/* On Linux, directly parse /proc */ /* On Linux, directly parse /proc */
return user_busy_processes (uid); return user_busy_processes (name, uid);
#else /* !__linux__ */ #else /* !__linux__ */
/* If we cannot rely on /proc, check is there is a record in utmp /* If we cannot rely on /proc, check is there is a record in utmp
* indicating that the user is still logged in */ * indicating that the user is still logged in */
@@ -91,6 +95,9 @@ static int user_busy_utmp (const char *name)
continue; continue;
} }
fprintf (stderr,
_("%s: user %s is currently logged in\n"),
Prog, name);
return 1; return 1;
} }
@@ -99,7 +106,7 @@ static int user_busy_utmp (const char *name)
#endif /* !__linux__ */ #endif /* !__linux__ */
#ifdef __linux__ #ifdef __linux__
static int check_status (const char *sname, uid_t uid) static int check_status (const char *name, const char *sname, uid_t uid)
{ {
/* 40: /proc/xxxxxxxxxx/task/xxxxxxxxxx/status + \0 */ /* 40: /proc/xxxxxxxxxx/task/xxxxxxxxxx/status + \0 */
char status[40]; char status[40];
@@ -122,7 +129,13 @@ static int check_status (const char *sname, uid_t uid)
&ruid, &euid, &suid) == 3) { &ruid, &euid, &suid) == 3) {
if ( (ruid == (unsigned long) uid) if ( (ruid == (unsigned long) uid)
|| (euid == (unsigned long) uid) || (euid == (unsigned long) uid)
|| (suid == (unsigned long) uid)) { || (suid == (unsigned long) uid)
#ifdef ENABLE_SUBIDS
|| have_sub_uids(name, ruid, 1)
|| have_sub_uids(name, euid, 1)
|| have_sub_uids(name, suid, 1)
#endif /* ENABLE_SUBIDS */
) {
(void) fclose (sfile); (void) fclose (sfile);
return 1; return 1;
} }
@@ -137,7 +150,7 @@ static int check_status (const char *sname, uid_t uid)
return 0; return 0;
} }
static int user_busy_processes (uid_t uid) static int user_busy_processes (const char *name, uid_t uid)
{ {
DIR *proc; DIR *proc;
struct dirent *ent; struct dirent *ent;
@@ -150,6 +163,10 @@ static int user_busy_processes (uid_t uid)
struct stat sbroot; struct stat sbroot;
struct stat sbroot_process; struct stat sbroot_process;
#ifdef ENABLE_SUBIDS
sub_uid_open (O_RDONLY);
#endif /* ENABLE_SUBIDS */
proc = opendir ("/proc"); proc = opendir ("/proc");
if (proc == NULL) { if (proc == NULL) {
perror ("opendir /proc"); perror ("opendir /proc");
@@ -158,6 +175,9 @@ static int user_busy_processes (uid_t uid)
if (stat ("/", &sbroot) != 0) { if (stat ("/", &sbroot) != 0) {
perror ("stat (\"/\")"); perror ("stat (\"/\")");
(void) closedir (proc); (void) closedir (proc);
#ifdef ENABLE_SUBIDS
sub_uid_close();
#endif
return 0; return 0;
} }
@@ -193,8 +213,14 @@ static int user_busy_processes (uid_t uid)
continue; continue;
} }
if (check_status (tmp_d_name, uid) != 0) { if (check_status (name, tmp_d_name, uid) != 0) {
(void) closedir (proc); (void) closedir (proc);
#ifdef ENABLE_SUBIDS
sub_uid_close();
#endif
fprintf (stderr,
_("%s: user %s is currently used by process %d\n"),
Prog, name, pid);
return 1; return 1;
} }
@@ -210,8 +236,14 @@ static int user_busy_processes (uid_t uid)
if (tid == pid) { if (tid == pid) {
continue; continue;
} }
if (check_status (task_path+6, uid) != 0) { if (check_status (name, task_path+6, uid) != 0) {
(void) closedir (proc); (void) closedir (proc);
#ifdef ENABLE_SUBIDS
sub_uid_close();
#endif
fprintf (stderr,
_("%s: user %s is currently used by process %d\n"),
Prog, name, pid);
return 1; return 1;
} }
} }
@@ -222,6 +254,9 @@ static int user_busy_processes (uid_t uid)
} }
(void) closedir (proc); (void) closedir (proc);
#ifdef ENABLE_SUBIDS
sub_uid_close();
#endif /* ENABLE_SUBIDS */
return 0; return 0;
} }
#endif /* __linux__ */ #endif /* __linux__ */
+11 -2
View File
@@ -42,6 +42,8 @@
#endif #endif
#include <assert.h> #include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h> #include <netdb.h>
#include <stdio.h> #include <stdio.h>
@@ -71,7 +73,7 @@ static bool is_my_tty (const char *tty)
} }
} }
if (NULL == tmptty) { if ('\0' == tmptty[0]) {
(void) puts (_("Unable to determine your tty name.")); (void) puts (_("Unable to determine your tty name."));
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} else if (strncmp (tty, tmptty, sizeof (tmptty)) != 0) { } else if (strncmp (tty, tmptty, sizeof (tmptty)) != 0) {
@@ -129,6 +131,7 @@ static bool is_my_tty (const char *tty)
return ret; return ret;
} }
#ifndef USE_PAM
/* /*
* Some systems already have updwtmp() and possibly updwtmpx(). Others * Some systems already have updwtmp() and possibly updwtmpx(). Others
* don't, so we re-implement these functions if necessary. * don't, so we re-implement these functions if necessary.
@@ -160,6 +163,7 @@ static void updwtmpx (const char *filename, const struct utmpx *utx)
} }
#endif /* ! HAVE_UPDWTMPX */ #endif /* ! HAVE_UPDWTMPX */
#endif /* ! USE_UTMPX */ #endif /* ! USE_UTMPX */
#endif /* ! USE_PAM */
/* /*
@@ -200,7 +204,6 @@ static void updwtmpx (const char *filename, const struct utmpx *utx)
strcpy (hostname, host); strcpy (hostname, host);
#ifdef HAVE_STRUCT_UTMP_UT_HOST #ifdef HAVE_STRUCT_UTMP_UT_HOST
} else if ( (NULL != ut) } else if ( (NULL != ut)
&& (NULL != ut->ut_host)
&& ('\0' != ut->ut_host[0])) { && ('\0' != ut->ut_host[0])) {
hostname = (char *) xmalloc (sizeof (ut->ut_host) + 1); hostname = (char *) xmalloc (sizeof (ut->ut_host) + 1);
strncpy (hostname, ut->ut_host, sizeof (ut->ut_host)); strncpy (hostname, ut->ut_host, sizeof (ut->ut_host));
@@ -314,7 +317,10 @@ int setutmp (struct utmp *ut)
} }
endutent (); endutent ();
#ifndef USE_PAM
/* This is done by pam_lastlog */
updwtmp (_WTMP_FILE, ut); updwtmp (_WTMP_FILE, ut);
#endif /* ! USE_PAM */
return err; return err;
} }
@@ -447,7 +453,10 @@ int setutmpx (struct utmpx *utx)
} }
endutxent (); endutxent ();
#ifndef USE_PAM
/* This is done by pam_lastlog */
updwtmpx (_WTMP_FILE "x", utx); updwtmpx (_WTMP_FILE "x", utx);
#endif /* ! USE_PAM */
return err; return err;
} }
+2 -1
View File
@@ -52,7 +52,7 @@
bool valid (const char *password, const struct passwd *ent) bool valid (const char *password, const struct passwd *ent)
{ {
const char *encrypted; const char *encrypted;
const char *salt; /*@observer@*/const char *salt;
/* /*
* Start with blank or empty password entries. Always encrypt * Start with blank or empty password entries. Always encrypt
@@ -95,6 +95,7 @@ bool valid (const char *password, const struct passwd *ent)
*/ */
if ( (NULL != ent->pw_name) if ( (NULL != ent->pw_name)
&& (NULL != encrypted)
&& (strcmp (encrypted, ent->pw_passwd) == 0)) { && (strcmp (encrypted, ent->pw_passwd) == 0)) {
return true; return true;
} else { } else {
+1 -1
View File
@@ -91,7 +91,7 @@
errno = 0; errno = 0;
status = REENTRANT_NAME(ARG_NAME, result, buffer, status = REENTRANT_NAME(ARG_NAME, result, buffer,
length, &resbuf); length, &resbuf);
if ((0 ==status) && (resbuf == result)) { if ((0 == status) && (resbuf == result)) {
/* Build a result structure that can be freed by /* Build a result structure that can be freed by
* the shadow *_free functions. */ * the shadow *_free functions. */
LOOKUP_TYPE *ret_result = DUP_FUNCTION(result); LOOKUP_TYPE *ret_result = DUP_FUNCTION(result);
+7 -4
View File
@@ -44,22 +44,25 @@
#ident "$Id$" #ident "$Id$"
#include <stdio.h> #include <stdio.h>
#include <errno.h>
#include "defines.h" #include "defines.h"
#include "prototypes.h" #include "prototypes.h"
char *xmalloc (size_t size) /*@maynotreturn@*/ /*@only@*//*@out@*//*@notnull@*/char *xmalloc (size_t size)
{ {
char *ptr; char *ptr;
ptr = (char *) malloc (size); ptr = (char *) malloc (size);
if ((NULL == ptr) && (0 != size)) { if (NULL == ptr) {
fprintf (stderr, _("malloc(%d) failed\n"), (int) size); (void) fprintf (stderr,
_("%s: failed to allocate memory: %s\n"),
Prog, strerror (errno));
exit (13); exit (13);
} }
return ptr; return ptr;
} }
char *xstrdup (const char *str) /*@maynotreturn@*/ /*@only@*//*@notnull@*/char *xstrdup (const char *str)
{ {
return strcpy (xmalloc (strlen (str) + 1), str); return strcpy (xmalloc (strlen (str) + 1), str);
} }
+1
View File
@@ -1,5 +1,6 @@
.xml2po.mo .xml2po.mo
config.xml config.xml
generate_mans.deps
*.[0-9] *.[0-9]
+78 -51
View File
@@ -1,63 +1,73 @@
# subdirectories for translated manual pages # subdirectories for translated manual pages
if USE_NLS if USE_NLS
SUBDIRS = po cs de es fi fr hu id it ja ko pl pt_BR ru sv tr zh_CN zh_TW SUBDIRS = po cs da de es fi fr hu id it ja ko pl pt_BR ru sv tr zh_CN zh_TW
else else
SUBDIRS = SUBDIRS =
endif endif
man_MANS = \ man_MANS = \
chage.1 \ man1/chage.1 \
chfn.1 \ man1/chfn.1 \
chgpasswd.8 \ man8/chgpasswd.8 \
chpasswd.8 \ man8/chpasswd.8 \
chsh.1 \ man1/chsh.1 \
expiry.1 \ man1/expiry.1 \
faillog.5 \ man5/faillog.5 \
faillog.8 \ man8/faillog.8 \
getspnam.3 \ man3/getspnam.3 \
gpasswd.1 \ man1/gpasswd.1 \
groupadd.8 \ man8/groupadd.8 \
groupdel.8 \ man8/groupdel.8 \
groupmems.8 \ man8/groupmems.8 \
groupmod.8 \ man8/groupmod.8 \
groups.1 \ man1/groups.1 \
grpck.8 \ man8/grpck.8 \
grpconv.8 \ man8/grpconv.8 \
grpunconv.8 \ man8/grpunconv.8 \
gshadow.5 \ man5/gshadow.5 \
lastlog.8 \ man8/lastlog.8 \
login.1 \ man1/login.1 \
login.defs.5 \ man5/login.defs.5 \
logoutd.8 \ man8/logoutd.8 \
newgrp.1 \ man1/newgrp.1 \
newusers.8 \ man8/newusers.8 \
nologin.8 \ man8/nologin.8 \
passwd.1 \ man1/passwd.1 \
passwd.5 \ man5/passwd.5 \
pwck.8 \ man8/pwck.8 \
pwconv.8 \ man8/pwconv.8 \
pwunconv.8 \ man8/pwunconv.8 \
sg.1 \ man1/sg.1 \
shadow.3 \ man3/shadow.3 \
shadow.5 \ man5/shadow.5 \
su.1 \ man1/su.1 \
suauth.5 \ man5/suauth.5 \
useradd.8 \ man8/useradd.8 \
userdel.8 \ man8/userdel.8 \
usermod.8 \ man8/usermod.8 \
vigr.8 \ man8/vigr.8 \
vipw.8 man8/vipw.8
man_nopam = \ man_nopam = \
limits.5 \ man5/limits.5 \
login.access.5 \ man5/login.access.5 \
porttime.5 man5/porttime.5
if !USE_PAM if !USE_PAM
man_MANS += $(man_nopam) man_MANS += $(man_nopam)
endif endif
man_subids = \
man1/newgidmap.1 \
man1/newuidmap.1 \
man5/subgid.5 \
man5/subuid.5
if ENABLE_SUBIDS
man_MANS += $(man_subids)
endif
man_XMANS = \ man_XMANS = \
chage.1.xml \ chage.1.xml \
chfn.1.xml \ chfn.1.xml \
@@ -81,7 +91,9 @@ man_XMANS = \
login.access.5.xml \ login.access.5.xml \
login.defs.5.xml \ login.defs.5.xml \
logoutd.8.xml \ logoutd.8.xml \
newgidmap.1.xml \
newgrp.1.xml \ newgrp.1.xml \
newuidmap.1.xml \
newusers.8.xml \ newusers.8.xml \
nologin.8.xml \ nologin.8.xml \
passwd.1.xml \ passwd.1.xml \
@@ -94,6 +106,8 @@ man_XMANS = \
sg.1.xml \ sg.1.xml \
su.1.xml \ su.1.xml \
suauth.5.xml \ suauth.5.xml \
subgid.5.xml \
subuid.5.xml \
useradd.8.xml \ useradd.8.xml \
userdel.8.xml \ userdel.8.xml \
usermod.8.xml \ usermod.8.xml \
@@ -149,6 +163,8 @@ login_defs_v = \
SU_WHEEL_ONLY.xml \ SU_WHEEL_ONLY.xml \
SYSLOG_SG_ENAB.xml \ SYSLOG_SG_ENAB.xml \
SYSLOG_SU_ENAB.xml \ SYSLOG_SU_ENAB.xml \
TCB_AUTH_GROUP.xml \
TCB_SYMLINKS.xml \
TTYGROUP.xml \ TTYGROUP.xml \
TTYTYPE_FILE.xml \ TTYTYPE_FILE.xml \
UID_MAX.xml \ UID_MAX.xml \
@@ -156,6 +172,9 @@ login_defs_v = \
UMASK.xml \ UMASK.xml \
USERDEL_CMD.xml \ USERDEL_CMD.xml \
USERGROUPS_ENAB.xml \ USERGROUPS_ENAB.xml \
USE_TCB.xml \
SUB_GID_COUNT.xml \
SUB_UID_COUNT.xml \
SYS_GID_MAX.xml \ SYS_GID_MAX.xml \
SYS_UID_MAX.xml SYS_UID_MAX.xml
@@ -163,24 +182,32 @@ EXTRA_DIST = \
$(man_MANS) \ $(man_MANS) \
$(man_XMANS) \ $(man_XMANS) \
$(addprefix login.defs.d/,$(login_defs_v)) \ $(addprefix login.defs.d/,$(login_defs_v)) \
$(man_nopam) \ man1/id.1 \
id.1 \
id.1.xml \ id.1.xml \
sulogin.8 \ man8/sulogin.8 \
sulogin.8.xml \ sulogin.8.xml \
generate_mans.mak \ generate_mans.mak \
generate_translations.mak generate_translations.mak
if USE_PAM
EXTRA_DIST += $(man_nopam)
endif
if !ENABLE_SUBIDS
EXTRA_DIST += $(man_subids)
endif
generate_mans.deps: *.xml generate_mans.deps: *.xml
awk 'BEGIN{FS="\"";} /^<!ENTITY .* * SYSTEM ".*">$$/{ f=FILENAME; sub(/.xml/,"",f); print f ": " $$2 }' $(man_XMANS) > $@ echo "# This file is generated" > $@
awk 'BEGIN{FS="\"";} /^<!ENTITY .* * SYSTEM ".*">$$/{ f=FILENAME; sub(/.xml/,"",f); print "man" substr(f, length (f)) "/" f ": " $$2 }' $(man_XMANS) >> $@
if ENABLE_REGENERATE_MAN if ENABLE_REGENERATE_MAN
include generate_mans.deps @ENABLE_REGENERATE_MAN_TRUE@include generate_mans.deps
include generate_mans.mak include generate_mans.mak
CLEANFILES = $(man_MANS) CLEANFILES = $(man_MANS) man1/id.1 man8/sulogin.8
else else
$(man_MANS): $(man_MANS):
+59 -9
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Copyright (c) 1990 - 1994, Julianne Frances Haugh Copyright (c) 1990 - 1994, Julianne Frances Haugh
Copyright (c) 2007 - 2008, Nicolas François Copyright (c) 2007 - 2011, Nicolas François
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -28,12 +28,38 @@
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--> -->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY USE_TCB SYSTEM "login.defs.d/USE_TCB.xml">
<!-- SHADOW-CONFIG-HERE -->
]>
<refentry id='chage.1'> <refentry id='chage.1'>
<!-- $Id$ --> <!-- $Id$ -->
<refentryinfo>
<author>
<firstname>Julianne Frances</firstname>
<surname>Haugh</surname>
<contrib>Creation, 1990</contrib>
</author>
<author>
<firstname>Thomas</firstname>
<surname>Kłoczko</surname>
<email>kloczek@pld.org.pl</email>
<contrib>shadow-utils maintainer, 2000 - 2007</contrib>
</author>
<author>
<firstname>Nicolas</firstname>
<surname>François</surname>
<email>nicolas.francois@centraliens.net</email>
<contrib>shadow-utils maintainer, 2007 - now</contrib>
</author>
</refentryinfo>
<refmeta> <refmeta>
<refentrytitle>chage</refentrytitle> <refentrytitle>chage</refentrytitle>
<manvolnum>1</manvolnum> <manvolnum>1</manvolnum>
<refmiscinfo class="sectdesc">User Commands</refmiscinfo> <refmiscinfo class="sectdesc">User Commands</refmiscinfo>
<refmiscinfo class="source">shadow-utils</refmiscinfo>
<refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
</refmeta> </refmeta>
<refnamediv id='name'> <refnamediv id='name'>
<refname>chage</refname> <refname>chage</refname>
@@ -45,8 +71,8 @@
<arg choice='opt'> <arg choice='opt'>
<replaceable>options</replaceable> <replaceable>options</replaceable>
</arg> </arg>
<arg choice='opt'> <arg choice='plain'>
<replaceable>LOGIN</replaceable> <replaceable>LOGIN</replaceable>
</arg> </arg>
</cmdsynopsis> </cmdsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
@@ -69,7 +95,7 @@
<variablelist remap='IP'> <variablelist remap='IP'>
<varlistentry> <varlistentry>
<term> <term>
<option>-d</option>, <option>--lastday</option> <replaceable>LAST_DAY</replaceable> <option>-d</option>, <option>--lastday</option>&nbsp;<replaceable>LAST_DAY</replaceable>
</term> </term>
<listitem> <listitem>
<para> <para>
@@ -81,7 +107,7 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>-E</option>, <option>--expiredate</option> <replaceable>EXPIRE_DATE</replaceable> <option>-E</option>, <option>--expiredate</option>&nbsp;<replaceable>EXPIRE_DATE</replaceable>
</term> </term>
<listitem> <listitem>
<para> <para>
@@ -107,7 +133,7 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>-I</option>, <option>--inactive</option> <replaceable>INACTIVE</replaceable> <option>-I</option>, <option>--inactive</option>&nbsp;<replaceable>INACTIVE</replaceable>
</term> </term>
<listitem> <listitem>
<para> <para>
@@ -136,7 +162,7 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>-m</option>, <option>--mindays</option> <replaceable>MIN_DAYS</replaceable> <option>-m</option>, <option>--mindays</option>&nbsp;<replaceable>MIN_DAYS</replaceable>
</term> </term>
<listitem> <listitem>
<para> <para>
@@ -148,7 +174,7 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>-M</option>, <option>--maxdays</option> <replaceable>MAX_DAYS</replaceable> <option>-M</option>, <option>--maxdays</option>&nbsp;<replaceable>MAX_DAYS</replaceable>
</term> </term>
<listitem> <listitem>
<para> <para>
@@ -169,7 +195,19 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>-W</option>, <option>--warndays</option> <replaceable>WARN_DAYS</replaceable> <option>-R</option>, <option>--root</option>&nbsp;<replaceable>CHROOT_DIR</replaceable>
</term>
<listitem>
<para>
Apply changes in the <replaceable>CHROOT_DIR</replaceable>
directory and use the configuration files from the
<replaceable>CHROOT_DIR</replaceable> directory.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-W</option>, <option>--warndays</option>&nbsp;<replaceable>WARN_DAYS</replaceable>
</term> </term>
<listitem> <listitem>
<para> <para>
@@ -202,6 +240,18 @@
</para> </para>
</refsect1> </refsect1>
<refsect1 id='configuration'>
<title>CONFIGURATION</title>
<para>
The following configuration variables in
<filename>/etc/login.defs</filename> change the behavior of this
tool:
</para>
<variablelist>
&USE_TCB;
</variablelist>
</refsect1>
<refsect1 id='files'> <refsect1 id='files'>
<title>FILES</title> <title>FILES</title>
<variablelist> <variablelist>
+103 -9
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Copyright (c) 1990 - 1994, Julianne Frances Haugh Copyright (c) 1990 - 1994, Julianne Frances Haugh
Copyright (c) 2007 - 2008, Nicolas François Copyright (c) 2007 - 2011, Nicolas François
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -33,14 +33,35 @@
<!ENTITY CHFN_AUTH SYSTEM "login.defs.d/CHFN_AUTH.xml"> <!ENTITY CHFN_AUTH SYSTEM "login.defs.d/CHFN_AUTH.xml">
<!ENTITY CHFN_RESTRICT SYSTEM "login.defs.d/CHFN_RESTRICT.xml"> <!ENTITY CHFN_RESTRICT SYSTEM "login.defs.d/CHFN_RESTRICT.xml">
<!ENTITY LOGIN_STRING SYSTEM "login.defs.d/LOGIN_STRING.xml"> <!ENTITY LOGIN_STRING SYSTEM "login.defs.d/LOGIN_STRING.xml">
<!-- SHADOW-CONFIG-HERE -->
]> ]>
<refentry id='chfn.1'> <refentry id='chfn.1'>
<!-- $Id$ --> <!-- $Id$ -->
<refentryinfo>
<author>
<firstname>Julianne Frances</firstname>
<surname>Haugh</surname>
<contrib>Creation, 1990</contrib>
</author>
<author>
<firstname>Thomas</firstname>
<surname>Kłoczko</surname>
<email>kloczek@pld.org.pl</email>
<contrib>shadow-utils maintainer, 2000 - 2007</contrib>
</author>
<author>
<firstname>Nicolas</firstname>
<surname>François</surname>
<email>nicolas.francois@centraliens.net</email>
<contrib>shadow-utils maintainer, 2007 - now</contrib>
</author>
</refentryinfo>
<refmeta> <refmeta>
<refentrytitle>chfn</refentrytitle> <refentrytitle>chfn</refentrytitle>
<manvolnum>1</manvolnum> <manvolnum>1</manvolnum>
<refmiscinfo class="sectdesc">User Commands</refmiscinfo> <refmiscinfo class="sectdesc">User Commands</refmiscinfo>
<refmiscinfo class="source">shadow-utils</refmiscinfo>
<refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
</refmeta> </refmeta>
<refnamediv id='name'> <refnamediv id='name'>
<refname>chfn</refname> <refname>chfn</refname>
@@ -50,12 +71,12 @@
<refsynopsisdiv id='synopsis'> <refsynopsisdiv id='synopsis'>
<cmdsynopsis> <cmdsynopsis>
<command>chfn</command> <command>chfn</command>
<arg choice='opt'>-f <replaceable>full_name</replaceable></arg> <arg choice='opt'>
<arg choice='opt'>-r <replaceable>room_no</replaceable></arg> <replaceable>options</replaceable>
<arg choice='opt'>-w <replaceable>work_ph</replaceable></arg> </arg>
<arg choice='opt'>-h <replaceable>home_ph</replaceable></arg> <arg choice='opt'>
<arg choice='opt'>-o <replaceable>other</replaceable></arg> <replaceable>LOGIN</replaceable>
<arg choice='opt'><replaceable>user</replaceable></arg> </arg>
</cmdsynopsis> </cmdsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
@@ -63,7 +84,7 @@
<title>DESCRIPTION</title> <title>DESCRIPTION</title>
<para> <para>
The <command>chfn</command> command changes user fullname, The <command>chfn</command> command changes user fullname,
office number, office extension, and home phone number information office room number, office phone number, and home phone number information
for a user's account. This information is typically printed by for a user's account. This information is typically printed by
<citerefentry><refentrytitle>finger</refentrytitle><manvolnum>1</manvolnum> <citerefentry><refentrytitle>finger</refentrytitle><manvolnum>1</manvolnum>
</citerefentry> and similar programs. A normal user may only change </citerefentry> and similar programs. A normal user may only change
@@ -84,6 +105,79 @@
store accounting information used by other applications. store accounting information used by other applications.
</para> </para>
</refsect1>
<refsect1 id='options'>
<title>OPTIONS</title>
<para>
The options which apply to the <command>chfn</command> command are:
</para>
<variablelist remap='IP'>
<varlistentry>
<term>
<option>-f</option>, <option>--full-name</option>&nbsp;<replaceable>FULL_NAME</replaceable>
</term>
<listitem>
<para>Change the user's full name.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-h</option>, <option>--home-phone</option>&nbsp;<replaceable>HOME_PHONE</replaceable>
</term>
<listitem>
<para>Change the user's home phone number.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-o</option>, <option>--other</option>&nbsp;<replaceable>OTHER</replaceable>
</term>
<listitem>
<para>
Change the user's other GECOS information. This field is used to
store accounting information used by other applications, and can
be changed only by a superuser.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-r</option>, <option>--room</option>&nbsp;<replaceable>ROOM_NUMBER</replaceable>
</term>
<listitem>
<para>Change the user's room number.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-R</option>, <option>--root</option>&nbsp;<replaceable>CHROOT_DIR</replaceable>
</term>
<listitem>
<para>
Apply changes in the <replaceable>CHROOT_DIR</replaceable>
directory and use the configuration files from the
<replaceable>CHROOT_DIR</replaceable> directory.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-u</option>, <option>--help</option>
</term>
<listitem>
<para>Display help message and exit.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-w</option>, <option>--work-phone</option>&nbsp;<replaceable>WORK_PHONE</replaceable>
</term>
<listitem>
<para>Change the user's office phone number.</para>
</listitem>
</varlistentry>
</variablelist>
<para> <para>
If none of the options are selected, <command>chfn</command> If none of the options are selected, <command>chfn</command>
operates in an interactive fashion, prompting the user with the operates in an interactive fashion, prompting the user with the
+31 -2
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Copyright (c) 2006 , Tomasz Kłoczko Copyright (c) 2006 , Tomasz Kłoczko
Copyright (c) 2007 - 2009, Nicolas François Copyright (c) 2007 - 2011, Nicolas François
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -34,14 +34,31 @@
<!ENTITY MAX_MEMBERS_PER_GROUP SYSTEM "login.defs.d/MAX_MEMBERS_PER_GROUP.xml"> <!ENTITY MAX_MEMBERS_PER_GROUP SYSTEM "login.defs.d/MAX_MEMBERS_PER_GROUP.xml">
<!ENTITY MD5_CRYPT_ENAB SYSTEM "login.defs.d/MD5_CRYPT_ENAB.xml"> <!ENTITY MD5_CRYPT_ENAB SYSTEM "login.defs.d/MD5_CRYPT_ENAB.xml">
<!ENTITY SHA_CRYPT_MIN_ROUNDS SYSTEM "login.defs.d/SHA_CRYPT_MIN_ROUNDS.xml"> <!ENTITY SHA_CRYPT_MIN_ROUNDS SYSTEM "login.defs.d/SHA_CRYPT_MIN_ROUNDS.xml">
<!-- SHADOW-CONFIG-HERE -->
]> ]>
<refentry id='chgpasswd.8'> <refentry id='chgpasswd.8'>
<!-- $Id$ --> <!-- $Id$ -->
<refentryinfo>
<author>
<firstname>Thomas</firstname>
<surname>Kłoczko</surname>
<email>kloczek@pld.org.pl</email>
<contrib>Creation, 2006</contrib>
</author>
<author>
<firstname>Nicolas</firstname>
<surname>François</surname>
<email>nicolas.francois@centraliens.net</email>
<contrib>shadow-utils maintainer, 2007 - now</contrib>
</author>
</refentryinfo>
<refmeta> <refmeta>
<refentrytitle>chgpasswd</refentrytitle> <refentrytitle>chgpasswd</refentrytitle>
<manvolnum>8</manvolnum> <manvolnum>8</manvolnum>
<refmiscinfo class="sectdesc">System Management Commands</refmiscinfo> <refmiscinfo class="sectdesc">System Management Commands</refmiscinfo>
<refmiscinfo class="source">shadow-utils</refmiscinfo>
<refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
</refmeta> </refmeta>
<refnamediv id='name'> <refnamediv id='name'>
<refname>chgpasswd</refname> <refname>chgpasswd</refname>
@@ -74,7 +91,7 @@
</para> </para>
<para> <para>
The default encryption algorithm can be defined for the system with The default encryption algorithm can be defined for the system with
the ENCRYPT_METHOD variable of <filename>/etc/login.defs</filename>, the <option>ENCRYPT_METHOD</option> variable of <filename>/etc/login.defs</filename>,
and can be overwiten with the <option>-e</option>, and can be overwiten with the <option>-e</option>,
<option>-m</option>, or <option>-c</option> options. <option>-m</option>, or <option>-c</option> options.
</para> </para>
@@ -125,6 +142,18 @@
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>
<option>-R</option>, <option>--root</option>&nbsp;<replaceable>CHROOT_DIR</replaceable>
</term>
<listitem>
<para>
Apply changes in the <replaceable>CHROOT_DIR</replaceable>
directory and use the configuration files from the
<replaceable>CHROOT_DIR</replaceable> directory.
</para>
</listitem>
</varlistentry>
<varlistentry condition="sha_crypt"> <varlistentry condition="sha_crypt">
<term><option>-s</option>, <option>--sha-rounds</option></term> <term><option>-s</option>, <option>--sha-rounds</option></term>
<listitem> <listitem>
+89 -42
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Copyright (c) 1991 , Julianne Frances Haugh Copyright (c) 1991 , Julianne Frances Haugh
Copyright (c) 2007 - 2009, Nicolas François Copyright (c) 2007 - 2011, Nicolas François
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -33,14 +33,36 @@
<!ENTITY ENCRYPT_METHOD SYSTEM "login.defs.d/ENCRYPT_METHOD.xml"> <!ENTITY ENCRYPT_METHOD SYSTEM "login.defs.d/ENCRYPT_METHOD.xml">
<!ENTITY MD5_CRYPT_ENAB SYSTEM "login.defs.d/MD5_CRYPT_ENAB.xml"> <!ENTITY MD5_CRYPT_ENAB SYSTEM "login.defs.d/MD5_CRYPT_ENAB.xml">
<!ENTITY SHA_CRYPT_MIN_ROUNDS SYSTEM "login.defs.d/SHA_CRYPT_MIN_ROUNDS.xml"> <!ENTITY SHA_CRYPT_MIN_ROUNDS SYSTEM "login.defs.d/SHA_CRYPT_MIN_ROUNDS.xml">
<!-- SHADOW-CONFIG-HERE -->
]> ]>
<refentry id='chpasswd.8'> <refentry id='chpasswd.8'>
<!-- $Id$ --> <!-- $Id$ -->
<refentryinfo>
<author>
<firstname>Julianne Frances</firstname>
<surname>Haugh</surname>
<contrib>Creation, 1991</contrib>
</author>
<author>
<firstname>Thomas</firstname>
<surname>Kłoczko</surname>
<email>kloczek@pld.org.pl</email>
<contrib>shadow-utils maintainer, 2000 - 2007</contrib>
</author>
<author>
<firstname>Nicolas</firstname>
<surname>François</surname>
<email>nicolas.francois@centraliens.net</email>
<contrib>shadow-utils maintainer, 2007 - now</contrib>
</author>
</refentryinfo>
<refmeta> <refmeta>
<refentrytitle>chpasswd</refentrytitle> <refentrytitle>chpasswd</refentrytitle>
<manvolnum>8</manvolnum> <manvolnum>8</manvolnum>
<refmiscinfo class="sectdesc">System Management Commands</refmiscinfo> <refmiscinfo class="sectdesc">System Management Commands</refmiscinfo>
<refmiscinfo class="source">shadow-utils</refmiscinfo>
<refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
</refmeta> </refmeta>
<refnamediv id='name'> <refnamediv id='name'>
<refname>chpasswd</refname> <refname>chpasswd</refname>
@@ -67,38 +89,37 @@
<emphasis remap='I'>user_name</emphasis>:<emphasis <emphasis remap='I'>user_name</emphasis>:<emphasis
remap='I'>password</emphasis> remap='I'>password</emphasis>
</para> </para>
<refsect2 condition="no_pam">
<para> <para>
By default the supplied password must be in clear-text, and is By default the passwords must be supplied in clear-text, and are
encrypted by <command>chpasswd</command>. encrypted by <command>chpasswd</command>.
Also the password age will be updated, if present. Also the password age will be updated, if present.
</para> </para>
<para> <para condition="no_pam">
The default encryption algorithm can be defined for the system with The default encryption algorithm can be defined for the system with
the ENCRYPT_METHOD variable of <filename>/etc/login.defs</filename>, the <option>ENCRYPT_METHOD</option> or
and can be overwiten with the <option>-e</option>, <option>MD5_CRYPT_ENAB</option> variables of
<option>-m</option>, or <option>-c</option> options. <filename>/etc/login.defs</filename>, and can be overwitten with the
<option>-e</option>, <option>-m</option>, or <option>-c</option>
options.
</para>
<para condition="pam">
By default, passwords are encrypted by PAM, but (even if not
recommended) you can select a different encryption method with the
<option>-e</option>, <option>-m</option>, or <option>-c</option>
options.
</para>
<para>
<phrase condition="pam">Except when PAM is used to encrypt the
passwords,</phrase> <command>chpasswd</command> first updates all the
passwords in memory, and then commits all the changes to disk if no
errors occured for any user.
</para>
<para condition="pam">
When PAM is used to encrypt the passwords (and update the passwords in
the system database) then if a password cannot be updated
<command>chpasswd</command> continues updating the passwords of the
next users, and will return an error code on exit.
</para> </para>
<para>
<command>chpasswd</command> first update the password in memory,
and then commit all the changes to disk if no errors occured for
any users.
</para>
</refsect2>
<refsect2 condition="pam">
<para>
The supplied passwords must be in clear-text.
</para>
<para>
PAM is used to update the password in the system database
according to the PAM chpasswd configuration.
</para>
<para>
When <command>chpasswd</command> fails to update a password, it
continues updating the passwords of the next users, and will
return an error code on exit.
</para>
</refsect2>
<para> <para>
This command is intended to be used in a large system environment This command is intended to be used in a large system environment
where many accounts are created at a single time. where many accounts are created at a single time.
@@ -111,9 +132,11 @@
The options which apply to the <command>chpasswd</command> command The options which apply to the <command>chpasswd</command> command
are: are:
</para> </para>
<variablelist remap='IP' condition="no_pam"> <variablelist remap='IP'>
<varlistentry> <varlistentry>
<term><option>-c</option>, <option>--crypt-method</option></term> <term>
<option>-c</option>, <option>--crypt-method</option>&nbsp;<replaceable>METHOD</replaceable>
</term>
<listitem> <listitem>
<para>Use the specified method to encrypt the passwords.</para> <para>Use the specified method to encrypt the passwords.</para>
<para condition="no_sha_crypt"> <para condition="no_sha_crypt">
@@ -123,6 +146,17 @@
The available methods are DES, MD5, NONE, and SHA256 or SHA512 The available methods are DES, MD5, NONE, and SHA256 or SHA512
if your libc support these methods. if your libc support these methods.
</para> </para>
<para condition="pam">
By default, PAM is used to encrypt the passwords.
</para>
<para condition="no_pam">
By default (if none of the <option>-c</option>,
<option>-m</option>, or <option>-e</option> options are
specified), the encryption method is defined by the
<option>ENCRYPT_METHOD</option> or
<option>MD5_CRYPT_ENAB</option> variables of
<filename>/etc/login.defs</filename>.
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
@@ -140,7 +174,7 @@
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
<variablelist remap='IP' condition="no_pam"> <variablelist remap='IP'>
<varlistentry> <varlistentry>
<term><option>-m</option>, <option>--md5</option></term> <term><option>-m</option>, <option>--md5</option></term>
<listitem> <listitem>
@@ -150,8 +184,22 @@
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>
<option>-R</option>, <option>--root</option>&nbsp;<replaceable>CHROOT_DIR</replaceable>
</term>
<listitem>
<para>
Apply changes in the <replaceable>CHROOT_DIR</replaceable>
directory and use the configuration files from the
<replaceable>CHROOT_DIR</replaceable> directory.
</para>
</listitem>
</varlistentry>
<varlistentry condition="sha_crypt"> <varlistentry condition="sha_crypt">
<term><option>-s</option>, <option>--sha-rounds</option></term> <term>
<option>-s</option>, <option>--sha-rounds</option>&nbsp;<replaceable>ROUNDS</replaceable>
</term>
<listitem> <listitem>
<para> <para>
Use the specified number of rounds to encrypt the passwords. Use the specified number of rounds to encrypt the passwords.
@@ -170,7 +218,8 @@
</para> </para>
<para> <para>
By default, the number of rounds is defined by the By default, the number of rounds is defined by the
SHA_CRYPT_MIN_ROUNDS and SHA_CRYPT_MAX_ROUNDS variables in <option>SHA_CRYPT_MIN_ROUNDS</option> and
<option>SHA_CRYPT_MAX_ROUNDS</option> variables in
<filename>/etc/login.defs</filename>. <filename>/etc/login.defs</filename>.
</para> </para>
</listitem> </listitem>
@@ -184,22 +233,20 @@
Remember to set permissions or umask to prevent readability of Remember to set permissions or umask to prevent readability of
unencrypted files by other users. unencrypted files by other users.
</para> </para>
<para condition="no_pam">
You should make sure the passwords and the encryption method respect
the system's password policy.
</para>
</refsect1> </refsect1>
<refsect1 id='configuration' condition="no_pam"> <refsect1 id='configuration'>
<title>CONFIGURATION</title> <title>CONFIGURATION</title>
<para> <para>
The following configuration variables in The following configuration variables in
<filename>/etc/login.defs</filename> change the behavior of this <filename>/etc/login.defs</filename> change the behavior of this
tool: tool:
</para> </para>
<variablelist> <variablelist condition="no_pam">
&ENCRYPT_METHOD; &ENCRYPT_METHOD;
&MD5_CRYPT_ENAB; &MD5_CRYPT_ENAB;
</variablelist>
<variablelist>
&SHA_CRYPT_MIN_ROUNDS; <!--documents also SHA_CRYPT_MAX_ROUNDS--> &SHA_CRYPT_MIN_ROUNDS; <!--documents also SHA_CRYPT_MAX_ROUNDS-->
</variablelist> </variablelist>
</refsect1> </refsect1>
@@ -207,19 +254,19 @@
<refsect1 id='files'> <refsect1 id='files'>
<title>FILES</title> <title>FILES</title>
<variablelist> <variablelist>
<varlistentry condition="no_pam"> <varlistentry>
<term><filename>/etc/passwd</filename></term> <term><filename>/etc/passwd</filename></term>
<listitem> <listitem>
<para>User account information.</para> <para>User account information.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry condition="no_pam"> <varlistentry>
<term><filename>/etc/shadow</filename></term> <term><filename>/etc/shadow</filename></term>
<listitem> <listitem>
<para>Secure user account information.</para> <para>Secure user account information.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry condition="no_pam"> <varlistentry>
<term><filename>/etc/login.defs</filename></term> <term><filename>/etc/login.defs</filename></term>
<listitem> <listitem>
<para>Shadow password suite configuration.</para> <para>Shadow password suite configuration.</para>
@@ -243,7 +290,7 @@
<citerefentry> <citerefentry>
<refentrytitle>newusers</refentrytitle><manvolnum>8</manvolnum> <refentrytitle>newusers</refentrytitle><manvolnum>8</manvolnum>
</citerefentry>, </citerefentry>,
<phrase condition="no_pam"> <phrase>
<citerefentry> <citerefentry>
<refentrytitle>login.defs</refentrytitle><manvolnum>5</manvolnum> <refentrytitle>login.defs</refentrytitle><manvolnum>5</manvolnum>
</citerefentry>, </citerefentry>,
+37 -3
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Copyright (c) 1990 , Julianne Frances Haugh Copyright (c) 1990 , Julianne Frances Haugh
Copyright (c) 2007 - 2008, Nicolas François Copyright (c) 2007 - 2011, Nicolas François
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -32,14 +32,36 @@
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY CHSH_AUTH SYSTEM "login.defs.d/CHSH_AUTH.xml"> <!ENTITY CHSH_AUTH SYSTEM "login.defs.d/CHSH_AUTH.xml">
<!ENTITY LOGIN_STRING SYSTEM "login.defs.d/LOGIN_STRING.xml"> <!ENTITY LOGIN_STRING SYSTEM "login.defs.d/LOGIN_STRING.xml">
<!-- SHADOW-CONFIG-HERE -->
]> ]>
<refentry id='chsh.1'> <refentry id='chsh.1'>
<!-- $Id$ --> <!-- $Id$ -->
<refentryinfo>
<author>
<firstname>Julianne Frances</firstname>
<surname>Haugh</surname>
<contrib>Creation, 1990</contrib>
</author>
<author>
<firstname>Thomas</firstname>
<surname>Kłoczko</surname>
<email>kloczek@pld.org.pl</email>
<contrib>shadow-utils maintainer, 2000 - 2007</contrib>
</author>
<author>
<firstname>Nicolas</firstname>
<surname>François</surname>
<email>nicolas.francois@centraliens.net</email>
<contrib>shadow-utils maintainer, 2007 - now</contrib>
</author>
</refentryinfo>
<refmeta> <refmeta>
<refentrytitle>chsh</refentrytitle> <refentrytitle>chsh</refentrytitle>
<manvolnum>1</manvolnum> <manvolnum>1</manvolnum>
<refmiscinfo class="sectdesc">User Commands</refmiscinfo> <refmiscinfo class="sectdesc">User Commands</refmiscinfo>
<refmiscinfo class="source">shadow-utils</refmiscinfo>
<refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
</refmeta> </refmeta>
<refnamediv id='name'> <refnamediv id='name'>
<refname>chsh</refname> <refname>chsh</refname>
@@ -63,7 +85,7 @@
<para> <para>
The <command>chsh</command> command changes the user login shell. The <command>chsh</command> command changes the user login shell.
This determines the name of the user's initial login command. A normal This determines the name of the user's initial login command. A normal
user may only change the login shell for her own account, the user may only change the login shell for her own account; the
superuser may change the login shell for any account. superuser may change the login shell for any account.
</para> </para>
@@ -83,7 +105,19 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>-s</option>, <option>--shell</option> <replaceable>SHELL</replaceable> <option>-R</option>, <option>--root</option>&nbsp;<replaceable>CHROOT_DIR</replaceable>
</term>
<listitem>
<para>
Apply changes in the <replaceable>CHROOT_DIR</replaceable>
directory and use the configuration files from the
<replaceable>CHROOT_DIR</replaceable> directory.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-s</option>, <option>--shell</option>&nbsp;<replaceable>SHELL</replaceable>
</term> </term>
<listitem> <listitem>
<para> <para>
+1
View File
@@ -1 +1,2 @@
<!ENTITY GROUP_NAME_MAX_LENGTH '@GROUP_NAME_MAX_LENGTH@'> <!ENTITY GROUP_NAME_MAX_LENGTH '@GROUP_NAME_MAX_LENGTH@'>
<!ENTITY SHADOW_UTILS_VERSION '@VERSION@'>
+20 -19
View File
@@ -2,24 +2,25 @@
mandir = @mandir@/cs mandir = @mandir@/cs
man_MANS = \ man_MANS = \
expiry.1 \ man1/expiry.1 \
faillog.5 \ man5/faillog.5 \
faillog.8 \ man8/faillog.8 \
gpasswd.1 \ man1/gpasswd.1 \
groupadd.8 \ man8/groupadd.8 \
groupdel.8 \ man8/groupdel.8 \
groupmod.8 \ man8/groupmod.8 \
groups.1 \ man1/groups.1 \
grpck.8 \ man8/grpck.8 \
gshadow.5 \ man5/gshadow.5 \
lastlog.8 \ man8/lastlog.8 \
nologin.8 \ man8/nologin.8 \
passwd.5 \ man5/passwd.5 \
shadow.5 \ man5/shadow.5 \
su.1 \ man1/su.1 \
vipw.8 man8/vipw.8
EXTRA_DIST = $(man_MANS) \ EXTRA_DIST = $(man_MANS) \
id.1 \ man1/id.1 \
groupmems.8 \ man8/groupmems.8 \
logoutd.8 man8/logoutd.8
View File
View File

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