Compare commits

...

75 Commits
4.2.1 ... 4.3.1

Author SHA1 Message Date
Serge Hallyn
6fbc11ce21 configure.ac: release 4.3.1
Signed-off-by: Serge Hallyn <serge@hallyn.com>
2016-08-14 23:00:59 -05:00
Serge Hallyn
ff2baed5db idmapping: add more checks for overflow
At this point they are redundant but should be safe.  Thanks to
Sebastian Krahmer for the first check.
2016-08-14 21:48:50 -05:00
Serge Hallyn
94da3dc5c8 also check upper for wrap 2016-08-14 21:48:45 -05:00
Serge Hallyn
9df58a7545 Merge pull request #30 from jwilk/spelling
man: Fix typos
2016-08-05 11:59:45 -05:00
Serge Hallyn
5b017af90d Merge pull request #29 from hemio-ev/lower-su-syslog-priority
Reduces syslog priority of common usage events
2016-08-05 11:59:15 -05:00
Jakub Wilk
a7a7a1fdea man: Fix typos 2016-08-05 18:50:51 +02:00
Serge Hallyn
ca0ccaba27 Merge pull request #24 from stoeckmann/typos
Fixed typos in new{g,u}idmap tools.
2016-08-04 23:39:25 -05:00
Serge Hallyn
8f1836bad9 Merge pull request #25 from stoeckmann/sigrace
Fixed signal races in shadow tools.
2016-08-04 23:38:24 -05:00
Michael Herold
61fc90b268 Reduces syslog priority of common usage events
- Log INFO instead of ERR on `su missing-user`
- Log NOTICE/WARN instead of ERR on pam_authenticate failure (wrong password for example)
2016-08-04 22:17:31 +02:00
Sebastian Krahmer
1d5a926cc2 Simplify getulong
Use strtoul to read an unsigned long, rather than reading
a signed long long and casting it.

https://bugzilla.suse.com/show_bug.cgi?id=979282
2016-08-03 11:51:07 -05:00
Serge Hallyn
7f5a14817d get_map_ranges: check for overflow
The kernel accepts u32 values, so make sure that userspace
is not passing large values.

Signed-off-by: Serge Hallyn <serge@hallyn.com>
2016-07-31 12:56:48 -05:00
Serge Hallyn
9bf01bf010 Merge pull request #26 from jubalh/master
Fix sentence in usermod manual
2016-07-19 08:02:31 -05:00
Michael Vetter
358bd9b359 Fix sentence in usermod manual
Should have been: '[...] but only checkS [...]'.
So there was a missing 's'. Architectures isn't the right word either.
I decided to write the whole sentence new.
2016-07-18 15:21:08 +02:00
Tobias Stoeckmann
dd50014055 Fixed signal races in shadow tools.
Some of the supplied tools use functions which are not signal-safe.

Most of the times it's exit() vs. _exit().

In other times it's how the standard output or standard error is
handled. FILE-related functions shall be avoided, therefore I replaced
them with write().

Also there is no need to call closelog(). At worst, it allows to
trigger a deadlock by issuing different signal types at bad timings.
But as these fixes are about race conditions, expect bad timings in
general for these bugs to be triggered. :)
2016-07-02 18:11:09 +02:00
Tobias Stoeckmann
a84b0cafdd Fixed typos in new{g,u}idmap tools.
Fixed small typos in manual pages and code comments.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2016-07-02 16:39:18 +02:00
Serge Hallyn
a4dee3d1ad Merge pull request #16 from sebras/master
man: Fix a number of typos for various commands.
2016-05-20 14:05:56 -05:00
Serge Hallyn
340729bbe8 Merge pull request #19 from brauner/manfix
add long option --no-create-home to -M
2016-05-05 16:18:15 -05:00
Christian Brauner
4518826376 add long option --no-create-home to -M
Let's get rid of all the downstream fixes floating around.

Signed-off-by: Christian Brauner <christian.brauner@mailbox.org>
2016-05-05 12:00:07 +02:00
Sebastian Rasmussen
aa38e0da9a man: Fix a number of typos for various commands. 2016-04-28 15:56:28 +02:00
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
10093 changed files with 369765 additions and 285 deletions

1
.gitignore vendored
View File

@@ -17,6 +17,7 @@ Makefile.in
/ABOUT-NLS
/aclocal.m4
/autom4te.cache
/compile
/config.guess
/config.h
/config.h.in

View File

@@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT
AM_INIT_AUTOMAKE(shadow, 4.2)
AM_INIT_AUTOMAKE(shadow, 4.3.1)
AC_CONFIG_HEADERS([config.h])
dnl Some hacks...
@@ -335,16 +335,10 @@ if test "$enable_subids" != "no"; then
dnl
dnl FIXME: check if 32 bit UIDs/GIDs are supported by libc
dnl
AC_RUN_IFELSE([AC_LANG_SOURCE([
#include <sys/types.h>
int main(void) {
uid_t u;
gid_t g;
return (sizeof u < 4) || (sizeof g < 4);
}
])], [id32bit="yes"], [id32bit="no"])
AC_CHECK_SIZEOF([uid_t],, [#include "sys/types.h"])
AC_CHECK_SIZEOF([gid_t],, [#include "sys/types.h"])
if test "x$id32bit" = "xyes"; then
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

View File

@@ -229,7 +229,7 @@ SYS_UID_MAX 999
# Extra per user uids
SUB_UID_MIN 100000
SUB_UID_MAX 600100000
SUB_UID_COUNT 10000
SUB_UID_COUNT 65536
#
# Min/max values for automatic gid selection in groupadd(8)
@@ -242,7 +242,7 @@ SYS_GID_MAX 999
# Extra per user group ids
SUB_GID_MIN 100000
SUB_GID_MAX 600100000
SUB_GID_COUNT 10000
SUB_GID_COUNT 65536
#
# Max number of login(1) retries if password is bad
@@ -393,3 +393,8 @@ USERGROUPS_ENAB yes
#
#CREATE_HOME yes
#
# Force use shadow, even if shadow passwd & shadow group files are
# missing.
#
#FORCE_SHADOW yes

View File

@@ -968,11 +968,10 @@ int commonio_close (struct commonio_db *db)
} else {
/*
* Default permissions for new [g]shadow files.
* (passwd and group always exist...)
*/
sb.st_mode = 0400;
sb.st_uid = 0;
sb.st_gid = 0;
sb.st_mode = db->st_mode;
sb.st_uid = db->st_uid;
sb.st_gid = db->st_gid;
}
snprintf (buf, sizeof buf, "%s+", db->filename);
@@ -1081,6 +1080,7 @@ int commonio_update (struct commonio_db *db, const void *eptr)
if (NULL != p) {
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);
db->ops->free (nentry);
return 0;
}
db->ops->free (p->eptr);

View File

@@ -123,6 +123,12 @@ struct commonio_db {
#ifdef WITH_SELINUX
/*@null@*/security_context_t scontext;
#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.
*/

View File

@@ -49,6 +49,32 @@ struct itemdef {
/*@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]))
static struct itemdef def_table[] = {
{"CHFN_RESTRICT", NULL},
@@ -102,29 +128,7 @@ static struct itemdef def_table[] = {
{"USERDEL_CMD", NULL},
{"USERGROUPS_ENAB", NULL},
#ifndef USE_PAM
{"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},
PAMDEFS
#endif
#ifdef USE_SYSLOG
{"SYSLOG_SG_ENAB", NULL},
@@ -135,9 +139,17 @@ static struct itemdef def_table[] = {
{"TCB_SYMLINKS", NULL},
{"USE_TCB", NULL},
#endif
{"FORCE_SHADOW", NULL},
{NULL, NULL}
};
#define NUMKNOWNDEFS (sizeof(knowndef_table)/sizeof(knowndef_table[0]))
static struct itemdef knowndef_table[] = {
#ifdef USE_PAM
PAMDEFS
#endif
};
#ifndef LOGINDEFS
#define LOGINDEFS "/etc/login.defs"
#endif
@@ -397,10 +409,17 @@ static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name)
* Item was never found.
*/
for (ptr = knowndef_table; NULL != ptr->name; ptr++) {
if (strcmp (ptr->name, name) == 0) {
goto out;
}
}
fprintf (stderr,
_("configuration error - unknown item '%s' (notify administrator)\n"),
name);
SYSLOG ((LOG_CRIT, "unknown configuration item `%s'", name));
out:
return (struct itemdef *) NULL;
}
@@ -416,23 +435,26 @@ static void def_load (void)
FILE *fp;
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.
*/
fp = fopen (def_fname, "r");
if (NULL == fp) {
if (errno == ENOENT)
return;
int err = errno;
SYSLOG ((LOG_CRIT, "cannot open login definitions %s [%s]",
def_fname, strerror (err)));
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.
*/

View File

@@ -44,22 +44,19 @@
*/
int getulong (const char *numstr, /*@out@*/unsigned long int *result)
{
long long int val;
unsigned long int val;
char *endptr;
errno = 0;
val = strtoll (numstr, &endptr, 0);
val = strtoul (numstr, &endptr, 0);
if ( ('\0' == *numstr)
|| ('\0' != *endptr)
|| (ERANGE == errno)
/*@+ignoresigns@*/
|| (val != (unsigned long int)val)
/*@=ignoresigns@*/
) {
return 0;
}
*result = (unsigned long int)val;
*result = val;
return 1;
}

View File

@@ -130,6 +130,9 @@ static /*@owned@*/struct commonio_db group_db = {
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */

View File

@@ -55,15 +55,14 @@
gr->gr_name = strdup (grent->gr_name);
/*@=mustfreeonly@*/
if (NULL == gr->gr_name) {
free(gr);
gr_free(gr);
return NULL;
}
/*@-mustfreeonly@*/
gr->gr_passwd = strdup (grent->gr_passwd);
/*@=mustfreeonly@*/
if (NULL == gr->gr_passwd) {
free(gr->gr_name);
free(gr);
gr_free(gr);
return NULL;
}
@@ -73,21 +72,13 @@
gr->gr_mem = (char **) malloc ((i + 1) * sizeof (char *));
/*@=mustfreeonly@*/
if (NULL == gr->gr_mem) {
free(gr->gr_passwd);
free(gr->gr_name);
free(gr);
gr_free(gr);
return NULL;
}
for (i = 0; grent->gr_mem[i]; i++) {
gr->gr_mem[i] = strdup (grent->gr_mem[i]);
if (NULL == gr->gr_mem[i]) {
int j;
for (j=0; j<i; j++)
free(gr->gr_mem[j]);
free(gr->gr_mem);
free(gr->gr_passwd);
free(gr->gr_name);
free(gr);
gr_free(gr);
return NULL;
}
}

View File

@@ -105,6 +105,9 @@ static struct commonio_db passwd_db = {
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */

View File

@@ -56,45 +56,35 @@
pw->pw_name = strdup (pwent->pw_name);
/*@=mustfreeonly@*/
if (NULL == pw->pw_name) {
free(pw);
pw_free(pw);
return NULL;
}
/*@-mustfreeonly@*/
pw->pw_passwd = strdup (pwent->pw_passwd);
/*@=mustfreeonly@*/
if (NULL == pw->pw_passwd) {
free(pw->pw_name);
free(pw);
pw_free(pw);
return NULL;
}
/*@-mustfreeonly@*/
pw->pw_gecos = strdup (pwent->pw_gecos);
/*@=mustfreeonly@*/
if (NULL == pw->pw_gecos) {
free(pw->pw_passwd);
free(pw->pw_name);
free(pw);
pw_free(pw);
return NULL;
}
/*@-mustfreeonly@*/
pw->pw_dir = strdup (pwent->pw_dir);
/*@=mustfreeonly@*/
if (NULL == pw->pw_dir) {
free(pw->pw_gecos);
free(pw->pw_passwd);
free(pw->pw_name);
free(pw);
pw_free(pw);
return NULL;
}
/*@-mustfreeonly@*/
pw->pw_shell = strdup (pwent->pw_shell);
/*@=mustfreeonly@*/
if (NULL == pw->pw_shell) {
free(pw->pw_dir);
free(pw->pw_gecos);
free(pw->pw_passwd);
free(pw->pw_name);
free(pw);
pw_free(pw);
return NULL;
}

View File

@@ -228,6 +228,9 @@ static struct commonio_db gshadow_db = {
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0400, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
@@ -249,6 +252,8 @@ int sgr_setdbname (const char *filename)
bool sgr_file_present (void)
{
if (getdef_bool ("FORCE_SHADOW"))
return true;
return commonio_present (&gshadow_db);
}

View File

@@ -104,6 +104,9 @@ static struct commonio_db shadow_db = {
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif /* WITH_SELINUX */
0400, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
@@ -125,6 +128,8 @@ int spw_setdbname (const char *filename)
bool spw_file_present (void)
{
if (getdef_bool ("FORCE_SHADOW"))
return true;
return commonio_present (&shadow_db);
}

View File

@@ -11,6 +11,8 @@
#include <stdio.h>
#include "commonio.h"
#include "subordinateio.h"
#include <sys/types.h>
#include <pwd.h>
struct subordinate_range {
const char *owner;
@@ -189,6 +191,15 @@ 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;
@@ -200,6 +211,76 @@ static const struct subordinate_range *find_range(struct commonio_db *db,
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;
}
@@ -460,6 +541,9 @@ static struct commonio_db subordinate_uid_db = {
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
@@ -538,6 +622,9 @@ static struct commonio_db subordinate_gid_db = {
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */

View File

@@ -58,7 +58,7 @@ int find_new_sub_gids (const char *owner,
min = getdef_ulong ("SUB_GID_MIN", 100000UL);
max = getdef_ulong ("SUB_GID_MAX", 600100000UL);
count = getdef_ulong ("SUB_GID_COUNT", 10000);
count = getdef_ulong ("SUB_GID_COUNT", 65536);
if (min > max || count >= max || (min + count - 1) > max) {
(void) fprintf (stderr,

View File

@@ -58,7 +58,7 @@ int find_new_sub_uids (const char *owner,
min = getdef_ulong ("SUB_UID_MIN", 100000UL);
max = getdef_ulong ("SUB_UID_MAX", 600100000UL);
count = getdef_ulong ("SUB_UID_COUNT", 10000);
count = getdef_ulong ("SUB_UID_COUNT", 65536);
if (min > max || count >= max || (min + count - 1) > max) {
(void) fprintf (stderr,

View File

@@ -70,13 +70,40 @@ struct map_range *get_map_ranges(int ranges, int argc, char **argv)
/* Gather up the ranges from the command line */
mapping = mappings;
for (idx = 0; idx < ranges; idx++, argidx += 3, mapping++) {
if (!getulong(argv[argidx + 0], &mapping->upper))
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))
}
if (!getulong(argv[argidx + 1], &mapping->lower)) {
free(mappings);
return NULL;
if (!getulong(argv[argidx + 2], &mapping->count))
}
if (!getulong(argv[argidx + 2], &mapping->count)) {
free(mappings);
return NULL;
}
if (ULONG_MAX - mapping->upper <= mapping->count || ULONG_MAX - mapping->lower <= mapping->count) {
fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog);
exit(EXIT_FAILURE);
}
if (mapping->upper > UINT_MAX ||
mapping->lower > UINT_MAX ||
mapping->count > UINT_MAX) {
fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog);
exit(EXIT_FAILURE);
}
if (mapping->lower + mapping->count > UINT_MAX ||
mapping->upper + mapping->count > UINT_MAX) {
fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog);
exit(EXIT_FAILURE);
}
if (mapping->lower + mapping->count < mapping->lower ||
mapping->upper + mapping->count < mapping->upper) {
/* this one really shouldn't be possible given previous checks */
fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog);
exit(EXIT_FAILURE);
}
}
return mappings;
}

View File

@@ -175,6 +175,9 @@ static int user_busy_processes (const char *name, uid_t uid)
if (stat ("/", &sbroot) != 0) {
perror ("stat (\"/\")");
(void) closedir (proc);
#ifdef ENABLE_SUBIDS
sub_uid_close();
#endif
return 0;
}
@@ -212,6 +215,9 @@ static int user_busy_processes (const char *name, uid_t uid)
if (check_status (name, tmp_d_name, uid) != 0) {
(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);
@@ -232,6 +238,9 @@ static int user_busy_processes (const char *name, uid_t uid)
}
if (check_status (name, task_path+6, uid) != 0) {
(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);

View File

@@ -92,7 +92,7 @@
<para>
The default encryption algorithm can be defined for the system with
the <option>ENCRYPT_METHOD</option> variable of <filename>/etc/login.defs</filename>,
and can be overwiten with the <option>-e</option>,
and can be overwritten with the <option>-e</option>,
<option>-m</option>, or <option>-c</option> options.
</para>
<para>

View File

@@ -98,7 +98,7 @@
The default encryption algorithm can be defined for the system with
the <option>ENCRYPT_METHOD</option> or
<option>MD5_CRYPT_ENAB</option> variables of
<filename>/etc/login.defs</filename>, and can be overwitten with the
<filename>/etc/login.defs</filename>, and can be overwritten with the
<option>-e</option>, <option>-m</option>, or <option>-c</option>
options.
</para>
@@ -112,7 +112,7 @@
<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.
errors occurred for any user.
</para>
<para condition="pam">
When PAM is used to encrypt the passwords (and update the passwords in

View File

@@ -106,7 +106,7 @@
<varlistentry>
<term><option>-a</option>, <option>--add</option>&nbsp;<replaceable>user_name</replaceable></term>
<listitem>
<para>Add an user to the group membership list.</para>
<para>Add a user to the group membership list.</para>
<para condition="gshadow">
If the <filename>/etc/gshadow</filename> file exist, and the
group has no entry in the <filename>/etc/gshadow</filename>

View File

@@ -95,7 +95,7 @@
group (but group members do not need the password).
</para>
<para>
The password is used when an user who is not a member of the
The password is used when a user who is not a member of the
group wants to gain the permissions of this group (see
<citerefentry><refentrytitle>newgrp</refentrytitle>
<manvolnum>1</manvolnum></citerefentry>).
@@ -105,7 +105,7 @@
can gain the group permissions.
</para>
<para>
A password field which starts with a exclamation mark means
A password field which starts with an exclamation mark means
that the password is locked. The remaining characters on the
line represent the password field before the password was
locked.

View File

@@ -103,6 +103,17 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-C</option>, <option>--clear</option>
</term>
<listitem>
<para>
Clear lastlog record of a user. This option can be used only together
with <option>-u</option> (<option>--user</option>)).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-h</option>, <option>--help</option>
@@ -123,6 +134,17 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-S</option>, <option>--set</option>
</term>
<listitem>
<para>
Set lastlog record of a user to the current time. This option can be
used only together with <option>-u</option> (<option>--user</option>)).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-t</option>, <option>--time</option>&nbsp;<replaceable>DAYS</replaceable>

View File

@@ -108,7 +108,7 @@
<listitem><para>A: max address space (KB)</para></listitem>
<listitem><para>C: max core file size (KB)</para></listitem>
<listitem><para>D: max data size (KB)</para></listitem>
<listitem><para>F: maximum filesize (KB)</para></listitem>
<listitem><para>F: maximum file size (KB)</para></listitem>
<listitem><para>K: file creation mask, set by
<citerefentry>
<refentrytitle>umask</refentrytitle><manvolnum>2</manvolnum>
@@ -145,7 +145,7 @@
<para>
Be aware that after <emphasis remap='I'>username</emphasis> the rest
of the line is considered a limit string, thus comments are not
allowed. A invalid limits string will be rejected (not considered) by
allowed. An invalid limits string will be rejected (not considered) by
the <command>login</command> program.
</para>
@@ -163,12 +163,12 @@
</para>
<para>
If more than one line with limits for an user exist, only the first line for
If more than one line with limits for a user exist, only the first line for
this user will be considered.
</para>
<para>
If no lines are specified for an user, the last
If no lines are specified for a user, the last
<replaceable>@group</replaceable> line matching a group whose the
user is a member of will be considered, or the last line with
default limits if no groups contain the user.

View File

@@ -61,9 +61,6 @@
<replaceable>count</replaceable>
</arg>
<arg choice='opt'>
<arg choice='plain'>
<replaceable>pid</replaceable>
</arg>
<arg choice='plain'>
<replaceable>gid</replaceable>
</arg>
@@ -83,8 +80,10 @@
<refsect1 id='description'>
<title>DESCRIPTION</title>
<para>
The <command>newgidmap</command> sets <filename>/proc/[pid]/gid_map</filename> based on it's
The <command>newgidmap</command> sets <filename>/proc/[pid]/gid_map</filename> based on its
command line arguments and the gids allowed in <filename>/etc/subgid</filename>.
Note that the root user is not exempted from the requirement for a valid
<filename>/etc/subgid</filename> entry.
</para>
<para>
@@ -94,7 +93,7 @@
<term>gid</term>
<listitem>
<para>
Begining of the range of GIDs inside the user namespace.
Beginning of the range of GIDs inside the user namespace.
</para>
</listitem>
</varlistentry>
@@ -102,7 +101,7 @@
<term>lowergid</term>
<listitem>
<para>
Begining of the range of GIDs outside the user namespace.
Beginning of the range of GIDs outside the user namespace.
</para>
</listitem>
</varlistentry>
@@ -146,7 +145,7 @@
<varlistentry>
<term><filename>/etc/subgid</filename></term>
<listitem>
<para>List of users subordinate group IDs.</para>
<para>List of user's subordinate group IDs.</para>
</listitem>
</varlistentry>
<varlistentry>

View File

@@ -80,8 +80,10 @@
<refsect1 id='description'>
<title>DESCRIPTION</title>
<para>
The <command>newuidmap</command> sets <filename>/proc/[pid]/uid_map</filename> based on it's
The <command>newuidmap</command> sets <filename>/proc/[pid]/uid_map</filename> based on its
command line arguments and the uids allowed in <filename>/etc/subuid</filename>.
Note that the root user is not exempted from the requirement for a valid
<filename>/etc/subuid</filename> entry.
</para>
<para>
@@ -91,7 +93,7 @@
<term>uid</term>
<listitem>
<para>
Begining of the range of UIDs inside the user namespace.
Beginning of the range of UIDs inside the user namespace.
</para>
</listitem>
</varlistentry>
@@ -99,7 +101,7 @@
<term>loweruid</term>
<listitem>
<para>
Begining of the range of UIDs outside the user namespace.
Beginning of the range of UIDs outside the user namespace.
</para>
</listitem>
</varlistentry>
@@ -142,7 +144,7 @@
<varlistentry>
<term><filename>/etc/subuid</filename></term>
<listitem>
<para>List of users subordinate user IDs.</para>
<para>List of user's subordinate user IDs.</para>
</listitem>
</varlistentry>
<varlistentry>

View File

@@ -115,7 +115,7 @@
</para>
<para>
It can be the name of a new user or the name of an existing
user (or an user created before by
user (or a user created before by
<command>newusers</command>). In case of an existing user,
the user's information will be changed, otherwise a new user
will be created.
@@ -142,7 +142,7 @@
This field is used to define the UID of the user.
</para>
<para>
If the field is empty, an new (unused) UID will be defined
If the field is empty, a new (unused) UID will be defined
automatically by <command>newusers</command>.
</para>
<para>
@@ -151,7 +151,7 @@
</para>
<para>
If this field contains the name of an existing user (or the
name of an user created before by
name of a user created before by
<command>newusers</command>), the UID of the specified user
will be used.
</para>

View File

@@ -89,7 +89,7 @@
<refsect1 id='history'>
<title>HISTORY</title>
<para>
The <command>nologin</command> command appearred in BSD 4.4.
The <command>nologin</command> command appeared in BSD 4.4.
</para>
</refsect1>
</refentry>

View File

@@ -164,7 +164,7 @@
</para>
<para>
You can find advices on how to choose a strong password on
You can find advice on how to choose a strong password on
http://en.wikipedia.org/wiki/Password_strength
</para>
</refsect2>

View File

@@ -2226,8 +2226,8 @@ msgid ""
"default."
msgstr ""
"Falls nicht definiert, hängt das Verhalten von <command>useradd</command> "
"von der Variable <option>USERGROUPS_ENAB</option> in <filename>/etc/default/"
"useradd</filename> ab. Wenn diese Variable auf <replaceable>yes</"
"von der Variable <option>USERGROUPS_ENAB</option> in <filename>/etc/login.def"
"s</filename> ab. Wenn diese Variable auf <replaceable>yes</"
"replaceable> gesetzt ist (oder auf der Befehlszeile <option>-U/--user-group</"
"option> angegeben wurde), wird für den Benutzer eine Gruppe, die auf seinen "
"Namen lautet, erstellt. Wenn die Variable auf <replaceable>no</replaceable> "

View File

@@ -243,7 +243,7 @@
<para condition="tcb">
Note that when <option>USE_TCB</option> is enabled, you cannot
specify an alternative <replaceable>shadow</replaceable> file. In
future releases, this paramater could be replaced by an alternate
future releases, this parameter could be replaced by an alternate
TCB directory.
</para>
</refsect1>

View File

@@ -115,7 +115,7 @@
any access at all if the password field is empty.
</para>
<para>
A password field which starts with a exclamation mark means
A password field which starts with an exclamation mark means
that the password is locked. The remaining characters on the
line represent the password field before the password was
locked.
@@ -133,7 +133,7 @@
</para>
<para>
The value 0 has a special meaning, which is that the user
should change her pasword the next time she will log in the
should change her password the next time she will log in the
system.
</para>
<para>
@@ -228,7 +228,7 @@
</para>
<para>
Note that an account expiration differs from a password
expiration. In case of an acount expiration, the user shall
expiration. In case of an account expiration, the user shall
not be allowed to login. In case of a password expiration,
the user is not allowed to login using her password.
</para>

View File

@@ -157,7 +157,7 @@
</para>
<para>
The executed command will have no controlling terminal. This
option cannot be used to execute interractive programs which
option cannot be used to execute interactive programs which
need a controlling TTY.
<!-- This avoids TTY hijacking when su is used to lower
privileges -->
@@ -191,7 +191,7 @@
<para>The shell that will be invoked.</para>
<para>
The invoked shell is chosen from (highest priority first):
<!--This should be an orderedlist, but lists inside another
<!--This should be an ordered list, but lists inside another
list does not work well with current docbook.
- nekral - 2009.06.03 -->
<variablelist>

View File

@@ -81,7 +81,7 @@
<!-- .RS -->
<literallayout remap='.nf'>
1) the user su is targetting
1) the user su is targeting
</literallayout>
<!-- .fi -->
<para>
@@ -106,13 +106,13 @@
<para>
from-id is formatted the same as to-id except the extra word
<emphasis>GROUP</emphasis> is recognised. <emphasis>ALL EXCEPT
<emphasis>GROUP</emphasis> is recognized. <emphasis>ALL EXCEPT
GROUP</emphasis> is perfectly valid too. Following
<emphasis>GROUP</emphasis> appears one or more group names, delimited
by ",". It is not sufficient to have primary group id of the relevant
group, an entry in
<citerefentry><refentrytitle>/etc/group</refentrytitle>
<manvolnum>5</manvolnum></citerefentry> is neccessary.
<manvolnum>5</manvolnum></citerefentry> is necessary.
</para>
<para>

View File

@@ -57,7 +57,7 @@
</para>
<itemizedlist mark='bullet'>
<listitem>
<para>login name</para>
<para>login name or UID</para>
</listitem>
<listitem>
<para>numerical subordinate group ID</para>
@@ -77,6 +77,13 @@
Multiple ranges may be specified per user.
</para>
<para>
When large number of entries (10000-100000 or more) are defined in
<filename>/etc/subgid</filename>, parsing performance penalty will
become noticeable. In this case it is recommended to use UIDs
instead of login names. Benchmarks have shown speed-ups up to 20x.
</para>
</refsect1>
<refsect1 id='files'>

View File

@@ -57,7 +57,7 @@
</para>
<itemizedlist mark='bullet'>
<listitem>
<para>login name</para>
<para>login name or UID</para>
</listitem>
<listitem>
<para>numerical subordinate user ID</para>
@@ -77,6 +77,13 @@
Multiple ranges may be specified per user.
</para>
<para>
When large number of entries (10000-100000 or more) are defined in
<filename>/etc/subuid</filename>, parsing performance penalty will
become noticeable. In this case it is recommended to use UIDs
instead of login names. Benchmarks have shown speed-ups up to 20x.
</para>
</refsect1>
<refsect1 id='files'>

View File

@@ -307,7 +307,7 @@
</para>
Example: <option>-K</option>&nbsp;<replaceable>PASS_MAX_DAYS</replaceable>=<replaceable>-1</replaceable>
can be used when creating system account to turn off password
ageing, even though system account has no password at all.
aging, even though system account has no password at all.
Multiple <option>-K</option> options can be specified, e.g.:
<option>-K</option>&nbsp;<replaceable>UID_MIN</replaceable>=<replaceable>100</replaceable>&nbsp;
<option>-K</option>&nbsp;<replaceable>UID_MAX</replaceable>=<replaceable>499</replaceable>
@@ -326,7 +326,7 @@
</para>
<para>
By default, the user's entries in the lastlog and faillog
databases are resetted to avoid reusing the entry from a previously
databases are reset to avoid reusing the entry from a previously
deleted user.
</para>
</listitem>
@@ -351,7 +351,7 @@
</varlistentry>
<varlistentry>
<term>
<option>-M</option>
<option>-M</option>, <option>--no-create-home</option>
</term>
<listitem>
<para>
@@ -433,7 +433,7 @@
</para>
<para>
Note that <command>useradd</command> will not create a home
directory for such an user, regardless of the default setting
directory for such a user, regardless of the default setting
in <filename>/etc/login.defs</filename>
(<option>CREATE_HOME</option>). You have to specify the
<option>-m</option> options if you want a home directory for a

View File

@@ -481,8 +481,7 @@
not executing any processes when this command is being executed if the
user's numerical user ID, the user's name, or the user's home
directory is being changed. <command>usermod</command> checks this
on Linux, but only check if the user is logged in according to utmp
on other architectures.
on Linux. On other platforms it only uses utmp to check if the user is logged in.
</para>
<para>
You must change the owner of any <command>crontab</command> files or

View File

@@ -2017,7 +2017,7 @@ msgid " -s, --shell SHELL login shell of the new account\n"
msgstr " -s, --shell SHELL 新アカウントのログインシェル\n"
msgid " -u, --uid UID user ID of the new account\n"
msgstr " -u, --iud UID 新アカウントのユーザ ID\n"
msgstr " -u, --uid UID 新アカウントのユーザ ID\n"
msgid ""
" -U, --user-group create a group with the same name as the "

View File

@@ -52,10 +52,13 @@ usbin_PROGRAMS = \
noinst_PROGRAMS = id sulogin
suidbins = su
suidubins = chage chfn chsh expiry gpasswd newgrp passwd newuidmap newgidmap
suidubins = chage chfn chsh expiry gpasswd newgrp passwd
if ACCT_TOOLS_SETUID
suidubins += chage chgpasswd chpasswd groupadd groupdel groupmod newusers useradd userdel usermod
endif
if ENABLE_SUBIDS
suidubins += newgidmap newuidmap
endif
if WITH_TCB
suidubins -= passwd
@@ -95,6 +98,7 @@ groupmod_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX)
grpck_LDADD = $(LDADD) $(LIBSELINUX)
grpconv_LDADD = $(LDADD) $(LIBSELINUX)
grpunconv_LDADD = $(LDADD) $(LIBSELINUX)
lastlog_LDADD = $(LDADD) $(LIBAUDIT)
login_SOURCES = \
login.c \
login_nopam.c

View File

@@ -592,7 +592,7 @@ static void open_files (bool readonly)
}
pw_locked = true;
}
if (pw_open (readonly ? O_RDONLY: O_RDWR) == 0) {
if (pw_open (readonly ? O_RDONLY: O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ());
SYSLOG ((LOG_WARN, "cannot open %s", pw_dbname ()));
fail_exit (E_NOPERM);
@@ -613,7 +613,7 @@ static void open_files (bool readonly)
}
spw_locked = true;
}
if (spw_open (readonly ? O_RDONLY: O_RDWR) == 0) {
if (spw_open (readonly ? O_RDONLY: O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"), Prog, spw_dbname ());
SYSLOG ((LOG_WARN, "cannot open %s", spw_dbname ()));

View File

@@ -463,7 +463,7 @@ static void update_gecos (const char *user, char *gecos)
fail_exit (E_NOPERM);
}
pw_locked = true;
if (pw_open (O_RDWR) == 0) {
if (pw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"), Prog, pw_dbname ());
fail_exit (E_NOPERM);

View File

@@ -316,7 +316,7 @@ static void open_files (void)
fail_exit (1);
}
gr_locked = true;
if (gr_open (O_RDWR) == 0) {
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"), Prog, gr_dbname ());
fail_exit (1);
@@ -332,7 +332,7 @@ static void open_files (void)
fail_exit (1);
}
sgr_locked = true;
if (sgr_open (O_RDWR) == 0) {
if (sgr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"),
Prog, sgr_dbname ());
fail_exit (1);

View File

@@ -313,7 +313,7 @@ static void open_files (void)
fail_exit (1);
}
pw_locked = true;
if (pw_open (O_RDWR) == 0) {
if (pw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"), Prog, pw_dbname ());
fail_exit (1);
@@ -328,7 +328,7 @@ static void open_files (void)
fail_exit (1);
}
spw_locked = true;
if (spw_open (O_RDWR) == 0) {
if (spw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, spw_dbname ());

View File

@@ -373,7 +373,7 @@ static void update_shell (const char *user, char *newshell)
fail_exit (1);
}
pw_locked = true;
if (pw_open (O_RDWR) == 0) {
if (pw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ());
SYSLOG ((LOG_WARN, "cannot open %s", pw_dbname ()));
fail_exit (1);

View File

@@ -58,7 +58,7 @@ static void process_flags (int argc, char **argv);
*/
static RETSIGTYPE catch_signals (unused int sig)
{
exit (10);
_exit (10);
}
/*

View File

@@ -169,9 +169,8 @@ static RETSIGTYPE catch_signals (int killed)
}
if (0 != killed) {
(void) putchar ('\n');
(void) fflush (stdout);
exit (killed);
(void) write (STDOUT_FILENO, "\n", 1);
_exit (killed);
}
}
@@ -370,7 +369,7 @@ static void open_files (void)
add_cleanup (log_gpasswd_failure_system, NULL);
if (gr_open (O_RDWR) == 0) {
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, gr_dbname ());
@@ -380,7 +379,7 @@ static void open_files (void)
#ifdef SHADOWGRP
if (is_shadowgrp) {
if (sgr_open (O_RDWR) == 0) {
if (sgr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sgr_dbname ());

View File

@@ -346,7 +346,7 @@ static void open_files (void)
add_cleanup (cleanup_report_add_group, group_name);
/* And now open the databases */
if (gr_open (O_RDWR) == 0) {
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ()));
exit (E_GRP_UPDATE);
@@ -354,7 +354,7 @@ static void open_files (void)
#ifdef SHADOWGRP
if (is_shadow_grp) {
if (sgr_open (O_RDWR) == 0) {
if (sgr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sgr_dbname ());

View File

@@ -60,6 +60,7 @@ const char *Prog;
static char *group_name;
static gid_t group_id = -1;
static bool check_group_busy = true;
#ifdef SHADOWGRP
static bool is_shadow_grp;
@@ -96,6 +97,7 @@ static /*@noreturn@*/void usage (int status)
Prog);
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
(void) fputs (_(" -f, --force delete group even if it is the primary group of a user\n"), usageout);
(void) fputs ("\n", usageout);
exit (status);
}
@@ -246,7 +248,7 @@ static void open_files (void)
add_cleanup (cleanup_report_del_group, group_name);
/* An now open the databases */
if (gr_open (O_RDWR) == 0) {
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, gr_dbname ());
@@ -255,7 +257,7 @@ static void open_files (void)
}
#ifdef SHADOWGRP
if (is_shadow_grp) {
if (sgr_open (O_RDWR) == 0) {
if (sgr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sgr_dbname ());
@@ -321,7 +323,7 @@ static void process_flags (int argc, char **argv)
{NULL, 0, NULL, '\0'}
};
while ((c = getopt_long (argc, argv, "hR:",
while ((c = getopt_long (argc, argv, "hfR:",
long_options, NULL)) != -1) {
switch (c) {
case 'h':
@@ -329,6 +331,9 @@ static void process_flags (int argc, char **argv)
/*@notreached@*/break;
case 'R': /* no-op, handled in process_root_flag () */
break;
case 'f':
check_group_busy = false;
break;
default:
usage (E_USAGE);
}
@@ -465,7 +470,9 @@ int main (int argc, char **argv)
/*
* Make sure this isn't the primary group of anyone.
*/
group_busy (group_id);
if (check_group_busy) {
group_busy (group_id);
}
/*
* Do the hard stuff - open the files, delete the group entries,

View File

@@ -536,14 +536,14 @@ static void open_files (void)
#endif
}
if (gr_open (list ? O_RDONLY : O_RDWR) == 0) {
if (gr_open (list ? O_RDONLY : O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
fail_exit (EXIT_GROUP_FILE);
}
#ifdef SHADOWGRP
if (is_shadowgrp) {
if (sgr_open (list ? O_RDONLY : O_RDWR) == 0) {
if (sgr_open (list ? O_RDONLY : O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ());
fail_exit (EXIT_GROUP_FILE);
}

View File

@@ -663,7 +663,7 @@ static void lock_files (void)
*/
static void open_files (void)
{
if (gr_open (O_RDWR) == 0) {
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ()));
exit (E_GRP_UPDATE);
@@ -672,7 +672,7 @@ static void open_files (void)
#ifdef SHADOWGRP
if ( is_shadow_grp
&& (pflg || nflg)) {
if (sgr_open (O_RDWR) == 0) {
if (sgr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sgr_dbname ());
@@ -683,7 +683,7 @@ static void open_files (void)
#endif /* SHADOWGRP */
if (gflg) {
if (pw_open (O_RDWR) == 0) {
if (pw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, pw_dbname ());

View File

@@ -299,7 +299,7 @@ static void open_files (void)
* Open the files. Use O_RDONLY if we are in read_only mode,
* O_RDWR otherwise.
*/
if (gr_open (read_only ? O_RDONLY : O_RDWR) == 0) {
if (gr_open (read_only ? O_RDONLY : O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog,
grp_file);
if (use_system_grp_file) {
@@ -308,7 +308,7 @@ static void open_files (void)
fail_exit (E_CANT_OPEN);
}
#ifdef SHADOWGRP
if (is_shadow && (sgr_open (read_only ? O_RDONLY : O_RDWR) == 0)) {
if (is_shadow && (sgr_open (read_only ? O_RDONLY : O_CREAT | O_RDWR) == 0)) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog,
sgr_file);
if (use_system_sgr_file) {

View File

@@ -163,7 +163,7 @@ int main (int argc, char **argv)
fail_exit (5);
}
gr_locked = true;
if (gr_open (O_RDWR) == 0) {
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
fail_exit (1);
}

View File

@@ -166,7 +166,7 @@ int main (int argc, char **argv)
fail_exit (5);
}
gr_locked = true;
if (gr_open (O_RDWR) == 0) {
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"), Prog, gr_dbname ());
fail_exit (1);

View File

@@ -71,6 +71,8 @@ static struct stat statbuf; /* fstat buffer for file size */
static bool uflg = false; /* print only an user of range of users */
static bool tflg = false; /* print is restricted to most recent days */
static bool bflg = false; /* print excludes most recent days */
static bool Cflg = false; /* clear record for user */
static bool Sflg = false; /* set record for user */
#define NOW (time ((time_t *) 0))
@@ -83,8 +85,10 @@ static /*@noreturn@*/void usage (int status)
"Options:\n"),
Prog);
(void) fputs (_(" -b, --before DAYS print only lastlog records older than DAYS\n"), usageout);
(void) fputs (_(" -C, --clear clear lastlog record of an user (usable only with -u)\n"), usageout);
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
(void) fputs (_(" -S, --set set lastlog record to current time (usable only with -u)\n"), usageout);
(void) fputs (_(" -t, --time DAYS print only lastlog records more recent than DAYS\n"), usageout);
(void) fputs (_(" -u, --user LOGIN print lastlog record of the specified LOGIN\n"), usageout);
(void) fputs ("\n", usageout);
@@ -194,6 +198,80 @@ static void print (void)
}
}
static void update_one (/*@null@*/const struct passwd *pw)
{
off_t offset;
struct lastlog ll;
int err;
if (NULL == pw) {
return;
}
offset = (off_t) pw->pw_uid * sizeof (ll);
/* fseeko errors are not really relevant for us. */
err = fseeko (lastlogfile, offset, SEEK_SET);
assert (0 == err);
memzero (&ll, sizeof (ll));
if (Sflg) {
ll.ll_time = NOW;
#ifdef HAVE_LL_HOST
strcpy (ll.ll_host, "localhost");
#endif
strcpy (ll.ll_line, "lastlog");
#ifdef WITH_AUDIT
audit_logger (AUDIT_ACCT_UNLOCK, Prog,
"clearing-lastlog",
pw->pw_name, (unsigned int) pw->pw_uid, SHADOW_AUDIT_SUCCESS);
#endif
}
#ifdef WITH_AUDIT
else {
audit_logger (AUDIT_ACCT_UNLOCK, Prog,
"refreshing-lastlog",
pw->pw_name, (unsigned int) pw->pw_uid, SHADOW_AUDIT_SUCCESS);
}
#endif
if (fwrite (&ll, sizeof(ll), 1, lastlogfile) != 1) {
fprintf (stderr,
_("%s: Failed to update the entry for UID %lu\n"),
Prog, (unsigned long int)pw->pw_uid);
exit (EXIT_FAILURE);
}
}
static void update (void)
{
const struct passwd *pwent;
if (!uflg) /* safety measure */
return;
if (has_umin && has_umax && (umin == umax)) {
update_one (getpwuid ((uid_t)umin));
} else {
setpwent ();
while ( (pwent = getpwent ()) != NULL ) {
if ((has_umin && (pwent->pw_uid < (uid_t)umin))
|| (has_umax && (pwent->pw_uid > (uid_t)umax))) {
continue;
}
update_one (pwent);
}
endpwent ();
}
if (fflush (lastlogfile) != 0 || fsync (fileno (lastlogfile)) != 0) {
fprintf (stderr,
_("%s: Failed to update the lastlog file\n"),
Prog);
exit (EXIT_FAILURE);
}
}
int main (int argc, char **argv)
{
/*
@@ -208,18 +286,24 @@ int main (int argc, char **argv)
process_root_flag ("-R", argc, argv);
#ifdef WITH_AUDIT
audit_help_open ();
#endif
{
int c;
static struct option const longopts[] = {
{"before", required_argument, NULL, 'b'},
{"clear", no_argument, NULL, 'C'},
{"help", no_argument, NULL, 'h'},
{"root", required_argument, NULL, 'R'},
{"set", no_argument, NULL, 'S'},
{"time", required_argument, NULL, 't'},
{"user", required_argument, NULL, 'u'},
{NULL, 0, NULL, '\0'}
};
while ((c = getopt_long (argc, argv, "b:hR:t:u:", longopts,
while ((c = getopt_long (argc, argv, "b:ChR:St:u:", longopts,
NULL)) != -1) {
switch (c) {
case 'b':
@@ -235,11 +319,21 @@ int main (int argc, char **argv)
bflg = true;
break;
}
case 'C':
{
Cflg = true;
break;
}
case 'h':
usage (EXIT_SUCCESS);
/*@notreached@*/break;
case 'R': /* no-op, handled in process_root_flag () */
break;
case 'S':
{
Sflg = true;
break;
}
case 't':
{
unsigned long days;
@@ -294,9 +388,21 @@ int main (int argc, char **argv)
Prog, argv[optind]);
usage (EXIT_FAILURE);
}
if (Cflg && Sflg) {
fprintf (stderr,
_("%s: Option -C cannot be used together with option -S\n"),
Prog);
usage (EXIT_FAILURE);
}
if ((Cflg || Sflg) && !uflg) {
fprintf (stderr,
_("%s: Options -C and -S require option -u to specify the user\n"),
Prog);
usage (EXIT_FAILURE);
}
}
lastlogfile = fopen (LASTLOG_FILE, "r");
lastlogfile = fopen (LASTLOG_FILE, (Cflg || Sflg)?"r+":"r");
if (NULL == lastlogfile) {
perror (LASTLOG_FILE);
exit (EXIT_FAILURE);
@@ -310,7 +416,10 @@ int main (int argc, char **argv)
exit (EXIT_FAILURE);
}
print ();
if (Cflg || Sflg)
update ();
else
print ();
(void) fclose (lastlogfile);

View File

@@ -103,7 +103,7 @@ static bool hflg = false;
static bool preauth_flag = false;
static bool amroot;
static unsigned int timeout;
static char tmsg[256];
/*
* External identifiers.
@@ -416,8 +416,8 @@ static void init_env (void)
static RETSIGTYPE alarm_handler (unused int sig)
{
fprintf (stderr, _("\nLogin timed out after %u seconds.\n"), timeout);
exit (0);
write (STDERR_FILENO, tmsg, strlen (tmsg));
_exit (0);
}
#ifdef USE_PAM
@@ -532,6 +532,7 @@ int main (int argc, char **argv)
bool is_console;
#endif
int err;
unsigned int timeout;
const char *cp;
const char *tmp;
char fromhost[512];
@@ -698,8 +699,10 @@ int main (int argc, char **argv)
top:
/* only allow ALARM sec. for login */
(void) signal (SIGALRM, alarm_handler);
timeout = getdef_unum ("LOGIN_TIMEOUT", ALARM);
snprintf (tmsg, sizeof tmsg,
_("\nLogin timed out after %u seconds.\n"), timeout);
(void) signal (SIGALRM, alarm_handler);
if (timeout > 0) {
(void) alarm (timeout);
}

View File

@@ -56,7 +56,7 @@ static bool verify_range(struct passwd *pw, struct map_range *range)
if (have_sub_gids(pw->pw_name, range->lower, range->count))
return true;
/* Allow a process to map it's own gid */
/* Allow a process to map its own gid */
if ((range->count == 1) && (pw->pw_gid == range->lower))
return true;
@@ -94,7 +94,7 @@ static void usage(void)
*/
int main(int argc, char **argv)
{
char proc_dir_name[PATH_MAX];
char proc_dir_name[32];
char *target_str;
pid_t target, parent;
int proc_dir_fd;
@@ -113,13 +113,14 @@ int main(int argc, char **argv)
if (argc < 2)
usage();
/* Find the process that needs it's user namespace
/* Find the process that needs its user namespace
* gid mapping set.
*/
target_str = argv[1];
if (!get_pid(target_str, &target))
usage();
/* max string length is 6 + 10 + 1 + 1 = 18, allocate 32 bytes */
written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/",
target);
if ((written <= 0) || (written >= sizeof(proc_dir_name))) {
@@ -160,8 +161,10 @@ int main(int argc, char **argv)
(getgid() != pw->pw_gid) ||
(pw->pw_uid != st.st_uid) ||
(pw->pw_gid != st.st_gid)) {
fprintf(stderr, _( "%s: Target %u is owned by a different user\n" ),
Prog, target);
fprintf(stderr, _( "%s: Target %u is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ),
Prog, target,
(unsigned long int)getuid(), (unsigned long int)pw->pw_uid, (unsigned long int)st.st_uid,
(unsigned long int)getgid(), (unsigned long int)pw->pw_gid, (unsigned long int)st.st_gid);
return EXIT_FAILURE;
}

View File

@@ -255,12 +255,15 @@ static void syslog_sg (const char *name, const char *group)
{
const char *loginname = getlogin ();
const char *tty = ttyname (0);
char *free_login = NULL, *free_tty = NULL;
if (loginname != NULL) {
loginname = xstrdup (loginname);
free_login = xstrdup (loginname);
loginname = free_login;
}
if (tty != NULL) {
tty = xstrdup (tty);
free_tty = xstrdup (tty);
tty = free_tty;
}
if (loginname == NULL) {
@@ -372,6 +375,8 @@ static void syslog_sg (const char *name, const char *group)
(void) signal (SIGTTOU, SIG_DFL);
}
#endif /* USE_PAM */
free(free_login);
free(free_tty);
}
#endif /* USE_SYSLOG */

View File

@@ -56,7 +56,7 @@ static bool verify_range(struct passwd *pw, struct map_range *range)
if (have_sub_uids(pw->pw_name, range->lower, range->count))
return true;
/* Allow a process to map it's own uid */
/* Allow a process to map its own uid */
if ((range->count == 1) && (pw->pw_uid == range->lower))
return true;
@@ -94,7 +94,7 @@ void usage(void)
*/
int main(int argc, char **argv)
{
char proc_dir_name[PATH_MAX];
char proc_dir_name[32];
char *target_str;
pid_t target, parent;
int proc_dir_fd;
@@ -113,13 +113,14 @@ int main(int argc, char **argv)
if (argc < 2)
usage();
/* Find the process that needs it's user namespace
/* Find the process that needs its user namespace
* uid mapping set.
*/
target_str = argv[1];
if (!get_pid(target_str, &target))
usage();
/* max string length is 6 + 10 + 1 + 1 = 18, allocate 32 bytes */
written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/",
target);
if ((written <= 0) || (written >= sizeof(proc_dir_name))) {
@@ -160,8 +161,10 @@ int main(int argc, char **argv)
(getgid() != pw->pw_gid) ||
(pw->pw_uid != st.st_uid) ||
(pw->pw_gid != st.st_gid)) {
fprintf(stderr, _( "%s: Target %u is owned by a different user\n" ),
Prog, target);
fprintf(stderr, _( "%s: Target process %u is owned by a different user: uid:%lu pw_uid:%lu st_uid:%lu, gid:%lu pw_gid:%lu st_gid:%lu\n" ),
Prog, target,
(unsigned long int)getuid(), (unsigned long int)pw->pw_uid, (unsigned long int)st.st_uid,
(unsigned long int)getgid(), (unsigned long int)pw->pw_gid, (unsigned long int)st.st_gid);
return EXIT_FAILURE;
}

View File

@@ -805,27 +805,27 @@ static void open_files (void)
}
#endif /* ENABLE_SUBIDS */
if (pw_open (O_RDWR) == 0) {
if (pw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ());
fail_exit (EXIT_FAILURE);
}
if (is_shadow && (spw_open (O_RDWR) == 0)) {
if (is_shadow && (spw_open (O_CREAT | O_RDWR) == 0)) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, spw_dbname ());
fail_exit (EXIT_FAILURE);
}
if (gr_open (O_RDWR) == 0) {
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
fail_exit (EXIT_FAILURE);
}
#ifdef SHADOWGRP
if (is_shadow_grp && (sgr_open (O_RDWR) == 0)) {
if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ());
fail_exit (EXIT_FAILURE);
}
#endif
#ifdef ENABLE_SUBIDS
if (is_sub_uid) {
if (sub_uid_open (O_RDWR) == 0) {
if (sub_uid_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sub_uid_dbname ());
@@ -833,7 +833,7 @@ static void open_files (void)
}
}
if (is_sub_gid) {
if (sub_gid_open (O_RDWR) == 0) {
if (sub_gid_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sub_gid_dbname ());

View File

@@ -573,7 +573,7 @@ static void update_noshadow (void)
exit (E_PWDBUSY);
}
pw_locked = true;
if (pw_open (O_RDWR) == 0) {
if (pw_open (O_CREAT | O_RDWR) == 0) {
(void) fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, pw_dbname ());
@@ -627,7 +627,7 @@ static void update_shadow (void)
exit (E_PWDBUSY);
}
spw_locked = true;
if (spw_open (O_RDWR) == 0) {
if (spw_open (O_CREAT | O_RDWR) == 0) {
(void) fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, spw_dbname ());

View File

@@ -281,7 +281,7 @@ static void open_files (void)
* Open the files. Use O_RDONLY if we are in read_only mode, O_RDWR
* otherwise.
*/
if (pw_open (read_only ? O_RDONLY : O_RDWR) == 0) {
if (pw_open (read_only ? O_RDONLY : O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"),
Prog, pw_dbname ());
if (use_system_pw_file) {
@@ -290,7 +290,7 @@ static void open_files (void)
fail_exit (E_CANTOPEN);
}
if (is_shadow && !use_tcb) {
if (spw_open (read_only ? O_RDONLY : O_RDWR) == 0) {
if (spw_open (read_only ? O_RDONLY : O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"),
Prog, spw_dbname ());
if (use_system_spw_file) {
@@ -566,7 +566,7 @@ static void check_pw_file (int *errors, bool *changed)
continue;
}
spw_locked = true;
if (spw_open (read_only ? O_RDONLY : O_RDWR) == 0) {
if (spw_open (read_only ? O_RDONLY : O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, spw_dbname ());

View File

@@ -200,7 +200,7 @@ int main (int argc, char **argv)
fail_exit (E_PWDBUSY);
}
pw_locked = true;
if (pw_open (O_RDWR) == 0) {
if (pw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"), Prog, pw_dbname ());
fail_exit (E_MISSING);
@@ -305,7 +305,8 @@ int main (int argc, char **argv)
}
/* /etc/passwd- (backup file) */
if (chmod (PASSWD_FILE "-", 0600) != 0) {
errno = 0;
if ((chmod (PASSWD_FILE "-", 0600) != 0) && (errno != ENOENT)) {
fprintf (stderr,
_("%s: failed to change the mode of %s to 0600\n"),
Prog, PASSWD_FILE "-");

View File

@@ -166,7 +166,7 @@ int main (int argc, char **argv)
fail_exit (5);
}
pw_locked = true;
if (pw_open (O_RDWR) == 0) {
if (pw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, pw_dbname ());

View File

@@ -105,6 +105,8 @@ static char caller_name[BUFSIZ];
static bool change_environment = true;
#ifdef USE_PAM
static char kill_msg[256];
static char wait_msg[256];
static pam_handle_t *pamh = NULL;
static int caught = 0;
/* PID of the child, in case it needs to be killed */
@@ -161,8 +163,7 @@ static RETSIGTYPE die (int killed)
}
if (killed != 0) {
closelog ();
exit (128+killed);
_exit (128+killed);
}
}
@@ -182,12 +183,11 @@ static RETSIGTYPE kill_child (int unused(s))
{
if (0 != pid_child) {
(void) kill (-pid_child, SIGKILL);
(void) fputs (_(" ...killed.\n"), stderr);
(void) write (STDERR_FILENO, kill_msg, strlen (kill_msg));
} else {
(void) fputs (_(" ...waiting for child to terminate.\n"),
stderr);
(void) write (STDERR_FILENO, wait_msg, strlen (wait_msg));
}
exit (255);
_exit (255);
}
#endif /* USE_PAM */
@@ -373,6 +373,9 @@ static void prepare_pam_close_session (void)
stderr);
(void) kill (-pid_child, caught);
snprintf (kill_msg, _(" ...killed.\n"));
snprintf (wait_msg, _(" ...waiting for child to terminate.\n"));
(void) signal (SIGALRM, kill_child);
(void) alarm (2);
@@ -422,7 +425,7 @@ static void check_perms_pam (const struct passwd *pw)
int ret;
ret = pam_authenticate (pamh, 0);
if (PAM_SUCCESS != ret) {
SYSLOG ((LOG_ERR, "pam_authenticate: %s",
SYSLOG (((pw->pw_uid != 0)? LOG_NOTICE : LOG_WARN, "pam_authenticate: %s",
pam_strerror (pamh, ret)));
fprintf (stderr, _("%s: %s\n"), Prog, pam_strerror (pamh, ret));
(void) pam_end (pamh, ret);
@@ -585,7 +588,7 @@ static /*@only@*/struct passwd * check_perms (void)
if (NULL == pw) {
(void) fprintf (stderr,
_("No passwd entry for user '%s'\n"), name);
SYSLOG ((LOG_ERR, "No passwd entry for user '%s'", name));
SYSLOG ((LOG_NOTICE, "No passwd entry for user '%s'", name));
su_failure (caller_tty, true);
}
@@ -615,7 +618,7 @@ static /*@only@*/struct passwd * check_perms (void)
(void) fprintf (stderr,
_("No passwd entry for user '%s'\n"),
name);
SYSLOG ((LOG_ERR,
SYSLOG ((LOG_NOTICE,
"No passwd entry for user '%s'", name));
su_failure (caller_tty, true);
}

View File

@@ -70,7 +70,7 @@ static RETSIGTYPE catch_signals (int);
static RETSIGTYPE catch_signals (unused int sig)
{
exit (1);
_exit (1);
}
/*

View File

@@ -1537,7 +1537,7 @@ static void open_files (void)
exit (E_PW_UPDATE);
}
pw_locked = true;
if (pw_open (O_RDWR) == 0) {
if (pw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ());
fail_exit (E_PW_UPDATE);
}
@@ -1554,7 +1554,7 @@ static void open_files (void)
fail_exit (E_GRP_UPDATE);
}
gr_locked = true;
if (gr_open (O_RDWR) == 0) {
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
fail_exit (E_GRP_UPDATE);
}
@@ -1567,7 +1567,7 @@ static void open_files (void)
fail_exit (E_GRP_UPDATE);
}
sgr_locked = true;
if (sgr_open (O_RDWR) == 0) {
if (sgr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sgr_dbname ());
@@ -1584,7 +1584,7 @@ static void open_files (void)
fail_exit (E_SUB_UID_UPDATE);
}
sub_uid_locked = true;
if (sub_uid_open (O_RDWR) == 0) {
if (sub_uid_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sub_uid_dbname ());
@@ -1599,7 +1599,7 @@ static void open_files (void)
fail_exit (E_SUB_GID_UPDATE);
}
sub_gid_locked = true;
if (sub_gid_open (O_RDWR) == 0) {
if (sub_gid_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sub_gid_dbname ());
@@ -1621,7 +1621,7 @@ static void open_shadow (void)
fail_exit (E_PW_UPDATE);
}
spw_locked = true;
if (spw_open (O_RDWR) == 0) {
if (spw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, spw_dbname ());
@@ -1993,6 +1993,11 @@ int main (int argc, char **argv)
#endif /* USE_PAM */
#endif /* ACCT_TOOLS_SETUID */
#ifdef ENABLE_SUBIDS
uid_t uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL);
uid_t uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL);
#endif
/*
* Get my name so that I can use it to report errors.
*/
@@ -2021,15 +2026,18 @@ int main (int argc, char **argv)
#ifdef SHADOWGRP
is_shadow_grp = sgr_file_present ();
#endif
process_flags (argc, argv);
#ifdef ENABLE_SUBIDS
is_sub_uid = sub_uid_file_present ();
is_sub_gid = sub_gid_file_present ();
is_sub_uid = sub_uid_file_present () && !rflg &&
(!user_id || (user_id <= uid_max && user_id >= uid_min));
is_sub_gid = sub_gid_file_present () && !rflg &&
(!user_id || (user_id <= uid_max && user_id >= uid_min));
#endif /* ENABLE_SUBIDS */
get_defaults ();
process_flags (argc, argv);
#ifdef ACCT_TOOLS_SETUID
#ifdef USE_PAM
{

View File

@@ -565,7 +565,7 @@ static void open_files (void)
fail_exit (E_PW_UPDATE);
}
pw_locked = true;
if (pw_open (O_RDWR) == 0) {
if (pw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"), Prog, pw_dbname ());
#ifdef WITH_AUDIT
@@ -590,7 +590,7 @@ static void open_files (void)
fail_exit (E_PW_UPDATE);
}
spw_locked = true;
if (spw_open (O_RDWR) == 0) {
if (spw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, spw_dbname ());
@@ -616,7 +616,7 @@ static void open_files (void)
fail_exit (E_GRP_UPDATE);
}
gr_locked = true;
if (gr_open (O_RDWR) == 0) {
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
#ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog,
@@ -641,7 +641,7 @@ static void open_files (void)
fail_exit (E_GRP_UPDATE);
}
sgr_locked= true;
if (sgr_open (O_RDWR) == 0) {
if (sgr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"),
Prog, sgr_dbname ());
#ifdef WITH_AUDIT
@@ -669,7 +669,7 @@ static void open_files (void)
fail_exit (E_SUB_UID_UPDATE);
}
sub_uid_locked = true;
if (sub_uid_open (O_RDWR) == 0) {
if (sub_uid_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"), Prog, sub_uid_dbname ());
#ifdef WITH_AUDIT
@@ -695,7 +695,7 @@ static void open_files (void)
fail_exit (E_SUB_GID_UPDATE);
}
sub_gid_locked = true;
if (sub_gid_open (O_RDWR) == 0) {
if (sub_gid_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"), Prog, sub_gid_dbname ());
#ifdef WITH_AUDIT

View File

@@ -1361,6 +1361,7 @@ static void process_flags (int argc, char **argv)
exit (E_UID_IN_USE);
}
#ifdef ENABLE_SUBIDS
if ( (vflg || Vflg)
&& !is_sub_uid) {
fprintf (stderr,
@@ -1376,6 +1377,7 @@ static void process_flags (int argc, char **argv)
Prog, sub_gid_dbname (), "-w", "-W");
exit (E_USAGE);
}
#endif /* ENABLE_SUBIDS */
}
/*
@@ -1530,7 +1532,7 @@ static void open_files (void)
fail_exit (E_PW_UPDATE);
}
pw_locked = true;
if (pw_open (O_RDWR) == 0) {
if (pw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, pw_dbname ());
@@ -1543,7 +1545,7 @@ static void open_files (void)
fail_exit (E_PW_UPDATE);
}
spw_locked = true;
if (is_shadow_pwd && (spw_open (O_RDWR) == 0)) {
if (is_shadow_pwd && (spw_open (O_CREAT | O_RDWR) == 0)) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, spw_dbname ());
@@ -1562,7 +1564,7 @@ static void open_files (void)
fail_exit (E_GRP_UPDATE);
}
gr_locked = true;
if (gr_open (O_RDWR) == 0) {
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, gr_dbname ());
@@ -1576,7 +1578,7 @@ static void open_files (void)
fail_exit (E_GRP_UPDATE);
}
sgr_locked = true;
if (is_shadow_grp && (sgr_open (O_RDWR) == 0)) {
if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sgr_dbname ());
@@ -1593,7 +1595,7 @@ static void open_files (void)
fail_exit (E_SUB_UID_UPDATE);
}
sub_uid_locked = true;
if (sub_uid_open (O_RDWR) == 0) {
if (sub_uid_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sub_uid_dbname ());
@@ -1608,7 +1610,7 @@ static void open_files (void)
fail_exit (E_SUB_GID_UPDATE);
}
sub_gid_locked = true;
if (sub_gid_open (O_RDWR) == 0) {
if (sub_gid_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sub_gid_dbname ());
@@ -1717,60 +1719,6 @@ static void usr_update (void)
fail_exit (E_PW_UPDATE);
}
}
#ifdef ENABLE_SUBIDS
if (Vflg) {
struct ulong_range_list_entry *ptr;
for (ptr = del_sub_uids; ptr != NULL; ptr = ptr->next) {
unsigned long count = ptr->range.last - ptr->range.first + 1;
if (sub_uid_remove(user_name, ptr->range.first, count) == 0) {
fprintf (stderr,
_("%s: failed to remove uid range %lu-%lu from '%s'\n"),
Prog, ptr->range.first, ptr->range.last,
sub_uid_dbname ());
fail_exit (E_SUB_UID_UPDATE);
}
}
}
if (vflg) {
struct ulong_range_list_entry *ptr;
for (ptr = add_sub_uids; ptr != NULL; ptr = ptr->next) {
unsigned long count = ptr->range.last - ptr->range.first + 1;
if (sub_uid_add(user_name, ptr->range.first, count) == 0) {
fprintf (stderr,
_("%s: failed to add uid range %lu-%lu from '%s'\n"),
Prog, ptr->range.first, ptr->range.last,
sub_uid_dbname ());
fail_exit (E_SUB_UID_UPDATE);
}
}
}
if (Wflg) {
struct ulong_range_list_entry *ptr;
for (ptr = del_sub_gids; ptr != NULL; ptr = ptr->next) {
unsigned long count = ptr->range.last - ptr->range.first + 1;
if (sub_gid_remove(user_name, ptr->range.first, count) == 0) {
fprintf (stderr,
_("%s: failed to remove gid range %lu-%lu from '%s'\n"),
Prog, ptr->range.first, ptr->range.last,
sub_gid_dbname ());
fail_exit (E_SUB_GID_UPDATE);
}
}
}
if (wflg) {
struct ulong_range_list_entry *ptr;
for (ptr = add_sub_gids; ptr != NULL; ptr = ptr->next) {
unsigned long count = ptr->range.last - ptr->range.first + 1;
if (sub_gid_add(user_name, ptr->range.first, count) == 0) {
fprintf (stderr,
_("%s: failed to add gid range %lu-%lu from '%s'\n"),
Prog, ptr->range.first, ptr->range.last,
sub_gid_dbname ());
fail_exit (E_SUB_GID_UPDATE);
}
}
}
#endif /* ENABLE_SUBIDS */
}
/*
@@ -2174,16 +2122,66 @@ int main (int argc, char **argv)
*/
open_files ();
if ( cflg || dflg || eflg || fflg || gflg || Lflg || lflg || pflg
|| sflg || uflg || Uflg
#ifdef ENABLE_SUBIDS
|| vflg || Vflg || wflg || Wflg
#endif /* ENABLE_SUBIDS */
) {
|| sflg || uflg || Uflg) {
usr_update ();
}
if (Gflg || lflg) {
grp_update ();
}
#ifdef ENABLE_SUBIDS
if (Vflg) {
struct ulong_range_list_entry *ptr;
for (ptr = del_sub_uids; ptr != NULL; ptr = ptr->next) {
unsigned long count = ptr->range.last - ptr->range.first + 1;
if (sub_uid_remove(user_name, ptr->range.first, count) == 0) {
fprintf (stderr,
_("%s: failed to remove uid range %lu-%lu from '%s'\n"),
Prog, ptr->range.first, ptr->range.last,
sub_uid_dbname ());
fail_exit (E_SUB_UID_UPDATE);
}
}
}
if (vflg) {
struct ulong_range_list_entry *ptr;
for (ptr = add_sub_uids; ptr != NULL; ptr = ptr->next) {
unsigned long count = ptr->range.last - ptr->range.first + 1;
if (sub_uid_add(user_name, ptr->range.first, count) == 0) {
fprintf (stderr,
_("%s: failed to add uid range %lu-%lu from '%s'\n"),
Prog, ptr->range.first, ptr->range.last,
sub_uid_dbname ());
fail_exit (E_SUB_UID_UPDATE);
}
}
}
if (Wflg) {
struct ulong_range_list_entry *ptr;
for (ptr = del_sub_gids; ptr != NULL; ptr = ptr->next) {
unsigned long count = ptr->range.last - ptr->range.first + 1;
if (sub_gid_remove(user_name, ptr->range.first, count) == 0) {
fprintf (stderr,
_("%s: failed to remove gid range %lu-%lu from '%s'\n"),
Prog, ptr->range.first, ptr->range.last,
sub_gid_dbname ());
fail_exit (E_SUB_GID_UPDATE);
}
}
}
if (wflg) {
struct ulong_range_list_entry *ptr;
for (ptr = add_sub_gids; ptr != NULL; ptr = ptr->next) {
unsigned long count = ptr->range.last - ptr->range.first + 1;
if (sub_gid_add(user_name, ptr->range.first, count) == 0) {
fprintf (stderr,
_("%s: failed to add gid range %lu-%lu from '%s'\n"),
Prog, ptr->range.first, ptr->range.last,
sub_gid_dbname ());
fail_exit (E_SUB_GID_UPDATE);
}
}
}
#endif /* ENABLE_SUBIDS */
close_files ();
#ifdef WITH_TCB

21
tests/README Normal file
View File

@@ -0,0 +1,21 @@
This testsuite is NOT SECURE: it will temporarily change your passwords file
with known passwords.
You should run it on a chroot, or on a secured dedicated system.
To test a Debian system:
$ mkdir sid-chroot
$ sudo debootstrap sid sid-chroot/ http://ftp.fr.debian.org/debian/
edit or copy a sources.list
$ sudo cp /etc/apt/sources.list sid-chroot/etc/apt/
edit or copy a resolv.conf
$ sudo cp /etc/resolv.conf sid-chroot/etc/
$ su - root -c "chroot sid-chroot/ /bin/bash"
# mount -t proc proc /proc
# mount -t devpts devpts /dev/pts
# aptitude update
# aptitude install expect
# cd /dev ; mknod --mode=666 /dev/ptmx c 5 2

61
tests/bug332198-test.exp Executable file
View File

@@ -0,0 +1,61 @@
#!/usr/bin/expect -f
# This is a script for repeatedly logging into the localhost
# using `rlogin` in order to apparently see a symptoms described
# in bug #332198.
# As described in the bug log, sometimes `rlogind` will fail to
# establish a connection, because it starts "login" process and
# the latter fails with "unable to determine TTY name, got /dev/pts/1"
# message.
#
# BUGS
#
# * the script rlogins to localhost
# * the script doesn't handle passwdord prompt, because it's intended
# to use .rhosts auth and expects shell prompt immediately after
# `rlogin`
# * the regexp for shell prompt is hardcoded
log_user 0
match_max 8192
while {1} {
set rlogin_spawn [spawn rlogin localhost]
if { $rlogin_spawn == 0 } { exit 1 }
expect {
-timeout 10 -re "^.*(Last login\[^\r\n\]*).*\n(\[^\r\n\]*\[#$\] )$" {
send_error "$expect_out(1,string)\n"
send_error "$expect_out(2,string)\n"
# send_error "$expect_out(0,string)\n"
}
timeout {
send_error "TIMEOUT/prompt\n"
send_error "$expect_out(buffer)\n"
send_error "RETRYING\n"
log_user 1
send "tty /\r"
expect -timeout 2 -re "^.*\r?\n(\[^\r\n\]*# )$" {}
send "tty /\r"
expect -timeout 2 -re "^.*\r?\n(\[^\r\n\]*# )$" {}
send_error "\n"
exit 2
}
}
send "tty\r"
expect {
-timeout 4 -re "tty\r?\n(\[^\r\n\]*)\r?\n(\[^\r\n\]*\[#$\] )$" {
send_error "$expect_out(2,string)$expect_out(1,string)\n"
# send_error "$expect_out(0,string)\n"
}
timeout { send_error "TIMEOUT/tty\n" ; exit 3 }
}
send "exit\r"
expect {
-timeout 2 eof {
# send_error "OK4: EOF\n"
}
timeout { send_error "TIMEOUT/eof\n" ; exit 4 }
}
wait
}
# vi: set sw=4:

83
tests/bug334803-test.exp Executable file
View File

@@ -0,0 +1,83 @@
#!/usr/bin/expect --
# This is a script for switching to another user and then
# suspending (`suspend -f`) and resuming (`fg`) his shell
package require cmdline
set opts {
{s.arg "sudo su -" "user switching method"}
{u.arg "" "username to switch to"}
}
set usage ": \[options]\noptions:"
array set conf [::cmdline::getoptions argv $opts $usage]
log_user 1
match_max 8192
expect_after {
timeout { send_error "TIMEOUT\n" ; exit 1 }
eof { send_error "EXITED\n" ; exit 2 }
}
set timeout 2
# user switching command, by default `sudo su -`
set swcmd $conf(s)
# ending of typicall shell prompt (zsh/sh):
set shpmt "(%|#|\\$) \\Z"
catch {set shpmt $env(EXPECT_PROMPT)}
# initial username:
set user0 [exec id -un]
# user we switch to (with $swcmd), by default initial user
if {$conf(u) != ""} {set swuser $conf(u)} else {set swuser $user0}
# 1. start shell
spawn bash
expect -re "$shpmt" {}
# 2. sudo-ing swuser's shell:
send "$swcmd $swuser\r"
expect {
-re "$swuser.*$shpmt" {}
-re "assword: ?\\Z" {
stty -echo
expect_user -timeout -1 -re "(.*)\n" {set swpwd $expect_out(1,string)}
stty echo
send "$swpwd\r"
expect -re "$swuser.*$shpmt" {}
}
}
# 3. getting pid and ppid of swuser's shell (needed for 5b):
send "echo \$\$:\$PPID\r"
expect -re "(?n)^(\[\[:digit:\]\]*):(\[\[:digit:\]\]*)\r?\n(.*)$shpmt" {}
set swpid $expect_out(1,string)
set swppid $expect_out(2,string)
#send_error "$user0:$swpid:$swppid\n"
# 4. suspending swuser's shell (trying to return to parent shell):
send "suspend -f\r"
expect {
-re "$shpmt" {
# 5a. got to parent shell -- resuming swuser's shell by `fg`:
send "fg\r"
set hung no
}
timeout {
# 5b. `suspend -f` has hung -- resuming swuser's shell by SIGCONT:
send_error "kill $swppid\n"
send_error [exec kill -CONT $swppid]
set hung yes
}
}
expect -re "$shpmt" {}
# 6. exiting [both] shells
#set swstat [wait -nowait]
#send_error [pid]:[exp_pid]:$swstat\n
send "exit\rexit\r"
expect eof {}
#send_error [wait -nowait]\n
#exec kill -KILL -[exp_pid]
if {$hung} {send_error "BUGGY\n" ; exit 3 }
# vi:set sw=4:

View File

@@ -0,0 +1,7 @@
Last password change : Jul 27, 2005
Password expires : never
Password inactive : never
Account expires : never
Minimum number of days between password change : 0
Maximum number of days between password change : 99999
Number of days of warning before password expires : 7

View File

@@ -0,0 +1,7 @@
Last password change : Jul 28, 2005
Password expires : never
Password inactive : never
Account expires : never
Minimum number of days between password change : 1
Maximum number of days between password change : 99996
Number of days of warning before password expires : 5

View File

@@ -0,0 +1,7 @@
Last password change : Jul 27, 2005
Password expires : never
Password inactive : never
Account expires : Jan 01, 1970
Minimum number of days between password change : 0
Maximum number of days between password change : 99999
Number of days of warning before password expires : 7

View File

@@ -0,0 +1,7 @@
Last password change : Jul 27, 2005
Password expires : never
Password inactive : never
Account expires : Jan 02, 1970
Minimum number of days between password change : 0
Maximum number of days between password change : 99999
Number of days of warning before password expires : 7

View File

@@ -0,0 +1,7 @@
Last password change : Jul 27, 2005
Password expires : never
Password inactive : never
Account expires : never
Minimum number of days between password change : 0
Maximum number of days between password change : 99999
Number of days of warning before password expires : 7

View File

@@ -0,0 +1,7 @@
Last password change : Jul 27, 2005
Password expires : never
Password inactive : never
Account expires : never
Minimum number of days between password change : 0
Maximum number of days between password change : 99999
Number of days of warning before password expires : 7

View File

@@ -0,0 +1,7 @@
Last password change : Jul 27, 2005
Password expires : never
Password inactive : never
Account expires : never
Minimum number of days between password change : 0
Maximum number of days between password change : 99999
Number of days of warning before password expires : 7

View File

@@ -0,0 +1,7 @@
Last password change : Jul 26, 2005
Password expires : Aug 09, 2005
Password inactive : Sep 13, 2005
Account expires : Jul 27, 2012
Minimum number of days between password change : 13
Maximum number of days between password change : 14
Number of days of warning before password expires : 9

View File

@@ -0,0 +1 @@
chage: user 'myuser8' does not exist in /etc/passwd

42
tests/chage/01/data/group Normal file
View File

@@ -0,0 +1,42 @@
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
lp:x:7:
mail:x:8:
news:x:9:
uucp:x:10:
man:x:12:
proxy:x:13:
kmem:x:15:
dialout:x:20:
fax:x:21:
voice:x:22:
cdrom:x:24:
floppy:x:25:
tape:x:26:
sudo:x:27:
audio:x:29:
dip:x:30:
www-data:x:33:
backup:x:34:
operator:x:37:
list:x:38:
irc:x:39:
src:x:40:
gnats:x:41:
shadow:x:42:
utmp:x:43:
video:x:44:
sasl:x:45:
plugdev:x:46:
staff:x:50:
games:x:60:
users:x:100:
nogroup:x:65534:
crontab:x:101:
Debian-exim:x:102:
myuser:x:424242:

View File

@@ -0,0 +1,42 @@
root:*::
daemon:*::
bin:*::
sys:*::
adm:*::
tty:*::
disk:*::
lp:*::
mail:*::
news:*::
uucp:*::
man:*::
proxy:*::
kmem:*::
dialout:*::
fax:*::
voice:*::
cdrom:*::
floppy:*::
tape:*::
sudo:*::
audio:*::
dip:*::
www-data:*::
backup:*::
operator:*::
list:*::
irc:*::
src:*::
gnats:*::
shadow:*::
utmp:*::
video:*::
sasl:*::
plugdev:*::
staff:*::
games:*::
users:*::
nogroup:*::
crontab:x::
Debian-exim:x::
myuser:x::

View File

@@ -0,0 +1,26 @@
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
Debian-exim:x:102:102::/var/spool/exim4:/bin/false
myuser1:x:424242:424242::/home:/bin/bash
myuser2:x:424243:424242::/home:/bin/bash
myuser3:x:424244:424242::/home:/bin/bash
myuser4:x:424245:424242::/home:/bin/bash
myuser5:x:424246:424242::/home:/bin/bash
myuser6:x:424247:424242::/home:/bin/bash
myuser7:x:424248:424242::/home:/bin/bash

View File

@@ -0,0 +1,26 @@
root:$1$NBLBLIXb$WUgojj1bNuxWEADQGt1m9.:12991:0:99999:7:::
daemon:*:12977:0:99999:7:::
bin:*:12977:0:99999:7:::
sys:*:12977:0:99999:7:::
sync:*:12977:0:99999:7:::
games:*:12977:0:99999:7:::
man:*:12977:0:99999:7:::
lp:*:12977:0:99999:7:::
mail:*:12977:0:99999:7:::
news:*:12977:0:99999:7:::
uucp:*:12977:0:99999:7:::
proxy:*:12977:0:99999:7:::
www-data:*:12977:0:99999:7:::
backup:*:12977:0:99999:7:::
list:*:12977:0:99999:7:::
irc:*:12977:0:99999:7:::
gnats:*:12977:0:99999:7:::
nobody:*:12977:0:99999:7:::
Debian-exim:!:12977:0:99999:7:::
myuser1:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:12991:0:99999:7:::
myuser2:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:12992:1:99996:5:::
myuser3:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:12991:0:99999:7::0:
myuser4:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:12991:0:99999:7::1:
myuser5:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:12991:0:99999:7:0::
myuser6:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:12991:0:99999:7:1::
myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:12991:0:99999:7:1::

16
tests/chage/01/data/usage Normal file
View File

@@ -0,0 +1,16 @@
Usage: chage [options] LOGIN
Options:
-d, --lastday LAST_DAY set date of last password change to LAST_DAY
-E, --expiredate EXPIRE_DATE set account expiration date to EXPIRE_DATE
-h, --help display this help message and exit
-I, --inactive INACTIVE set password inactive after expiration
to INACTIVE
-l, --list show account aging information
-m, --mindays MIN_DAYS set minimum number of days before password
change to MIN_DAYS
-M, --maxdays MAX_DAYS set maximim number of days before password
change to MAX_DAYS
-R, --root CHROOT_DIR directory to chroot into
-W, --warndays WARN_DAYS set expiration warning days to WARN_DAYS

206
tests/chage/01/run Executable file
View File

@@ -0,0 +1,206 @@
#!/bin/sh
set -e
cd $(dirname $0)
# Rational:
# Test chage options
# no testsuite password
# root password: rootF00barbaz
# myuser password: myuserF00barbaz
save()
{
[ ! -d tmp ] && mkdir tmp
for i in passwd group shadow gshadow
do
[ -f /etc/$i ] && cp /etc/$i tmp/$i
[ -f /etc/$i- ] && cp /etc/$i- tmp/$i-
done
true
}
restore()
{
for i in passwd group shadow gshadow
do
[ -f tmp/$i ] && cp tmp/$i /etc/$i && rm tmp/$i
[ -f tmp/$i- ] && cp tmp/$i- /etc/$i- && rm tmp/$i-
done
rm -f tmp/out
rmdir tmp
}
save
# restore the files on exit
trap 'if [ "$?" != "0" ]; then echo "FAIL"; fi; restore' 0
for i in passwd group shadow gshadow
do
cp data/$i /etc
done
echo -n "testing option -l"
chage -l myuser1 > tmp/out
diff -au data/chage1 tmp/out
echo -n .
chage -l myuser2 > tmp/out
diff -au data/chage2 tmp/out
echo -n .
chage -l myuser3 > tmp/out
diff -au data/chage3 tmp/out
echo -n .
chage -l myuser4 > tmp/out
diff -au data/chage4 tmp/out
echo -n .
chage -l myuser5 > tmp/out
diff -au data/chage5 tmp/out
echo -n .
chage -l myuser6 > tmp/out
diff -au data/chage6 tmp/out
echo -n .
chage --list myuser7 > tmp/out
diff -au data/chage7 tmp/out
echo -n .
msg=$(chage -l myuser8 2> tmp/out) || err=$?
[ "$err" = "1" ] && [ "$msg" = "" ] || exit 1
diff -au data/chage8 tmp/out
echo .
echo "testing option -d"
chage -d 2001-10-02 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:11597:0:99999:7:1::' ] || exit 1
echo "testing option -d -1"
chage -d -1 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.::0:99999:7:1::' ] || exit 1
echo "testing option -d 0"
chage -d 0 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:0:0:99999:7:1::' ] || exit 1
echo "testing option --lastday"
chage --lastday 2011-11-02 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:0:99999:7:1::' ] || exit 1
echo "testing option -E"
chage -E 2010-10-02 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:0:99999:7:1:14884:' ] || exit 1
echo "testing option -E -1"
chage -E -1 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:0:99999:7:1::' ] || exit 1
echo "testing option -E 0"
chage -E 0 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:0:99999:7:1:0:' ] || exit 1
echo "testing option --expiredate"
chage --expiredate 2020-02-02 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:0:99999:7:1:18294:' ] || exit 1
echo "testing option -I"
# NOTE: I could pass a date to -I
chage -I 42 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:0:99999:7:42:18294:' ] || exit 1
echo "testing option -I -1"
# NOTE: this behavior is not documented
chage -I -1 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:0:99999:7::18294:' ] || exit 1
echo "testing option -I 0"
# NOTE: We should check that this is the expected behavior
chage -I 0 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:0:99999:7:0:18294:' ] || exit 1
echo "testing option --inactive"
chage --inactive 12 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:0:99999:7:12:18294:' ] || exit 1
echo "testing option -m"
chage -m 24 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:24:99999:7:12:18294:' ] || exit 1
echo "testing option -m -1"
# NOTE: this behavior is not documented
chage -m -1 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280::99999:7:12:18294:' ] || exit 1
echo "testing option -m 0"
chage -m 0 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:0:99999:7:12:18294:' ] || exit 1
echo "testing option --mindays"
chage --min 1 myuser7
# NOTE: that shouldn't have work
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:1:99999:7:12:18294:' ] || exit 1
echo "testing option -M"
chage -M 25 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:1:25:7:12:18294:' ] || exit 1
echo "testing option -M -1"
# NOTE: this behavior is not documented
chage -M -1 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:1::7:12:18294:' ] || exit 1
echo "testing option -M 0"
chage -M 0 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:1:0:7:12:18294:' ] || exit 1
echo "testing option --maxdays"
chage --max 2 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:1:2:7:12:18294:' ] || exit 1
echo "testing option -W"
chage -W 26 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:1:2:26:12:18294:' ] || exit 1
echo "testing option -W -1"
# NOTE: this behavior is not documented
chage -W -1 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:1:2::12:18294:' ] || exit 1
echo "testing option -W 0"
chage -W 0 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:1:2:0:12:18294:' ] || exit 1
echo "testing option --warndays"
chage --warndays 3 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:15280:1:2:3:12:18294:' ] || exit 1
echo "testing with all options"
chage -d 2030-03-02 -E 1979-11-24 -I 10 -m 11 -M 12 --warndays 4 myuser7
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:21975:11:12:4:10:3614:' ] || exit 1
echo "interractive test"
./run1.exp
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:12990:13:14:9:35:15548:' ] || exit 1
echo "interractive test (default)"
./run2.exp
ent=$(getent shadow myuser7)
[ "$ent" = 'myuser7:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:12990:13:14:9:35:15548:' ] || exit 1
chage -l myuser7 > tmp/out
diff -au data/chage7b tmp/out
echo "usage"
chage -h > tmp/out || {
if [ "$?" != "2" ]; then false; fi
}
diff -au data/usage tmp/out
echo "OK"

31
tests/chage/01/run1.exp Executable file
View File

@@ -0,0 +1,31 @@
#!/usr/bin/expect
set timeout 5
# I've not been able to put the opening bracket in the regular expressions
# If anyone knows...
spawn /usr/bin/chage myuser7
expect -re "Minimum Password Age .11\]: "
send "13\r"
expect -re "Maximum Password Age .12\]: "
send "14\r"
expect -re "Last Password Change \[(]YYYY-MM-DD\[)] .2030-03-02\]: "
send "2005-07-26\r"
expect -re "Password Expiration Warning .4\]: "
send "9\r"
expect -re "Password Inactive .10\]: "
send "35\r"
expect -re "Account Expiration Date \[(]YYYY-MM-DD\[)] .1979-11-24\]: "
send "2012-07-27\r"
expect {
eof {
} default {
puts "\nFAIL"
exit 1
}
}
puts "\nPASS"
exit 0

31
tests/chage/01/run2.exp Executable file
View File

@@ -0,0 +1,31 @@
#!/usr/bin/expect
set timeout 5
# I've not been able to put the opening bracket in the regular expressions
# If anyone knows...
spawn /usr/bin/chage myuser7
expect -re "Minimum Password Age .13\]: "
send "\r"
expect -re "Maximum Password Age .14\]: "
send "\r"
expect -re "Last Password Change \[(]YYYY-MM-DD\[)] .2005-07-26\]: "
send "\r"
expect -re "Password Expiration Warning .9\]: "
send "\r"
expect -re "Password Inactive .35\]: "
send "\r"
expect -re "Account Expiration Date \[(]YYYY-MM-DD\[)] .2012-07-27\]: "
send "\r"
expect {
eof {
} default {
puts "\nFAIL"
exit 1
}
}
puts "\nPASS"
exit 0

42
tests/chage/02/data/group Normal file
View File

@@ -0,0 +1,42 @@
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
lp:x:7:
mail:x:8:
news:x:9:
uucp:x:10:
man:x:12:
proxy:x:13:
kmem:x:15:
dialout:x:20:
fax:x:21:
voice:x:22:
cdrom:x:24:
floppy:x:25:
tape:x:26:
sudo:x:27:
audio:x:29:
dip:x:30:
www-data:x:33:
backup:x:34:
operator:x:37:
list:x:38:
irc:x:39:
src:x:40:
gnats:x:41:
shadow:x:42:
utmp:x:43:
video:x:44:
sasl:x:45:
plugdev:x:46:
staff:x:50:
games:x:60:
users:x:100:
nogroup:x:65534:
crontab:x:101:
Debian-exim:x:102:
myuser:x:424242:

View File

@@ -0,0 +1,42 @@
root:*::
daemon:*::
bin:*::
sys:*::
adm:*::
tty:*::
disk:*::
lp:*::
mail:*::
news:*::
uucp:*::
man:*::
proxy:*::
kmem:*::
dialout:*::
fax:*::
voice:*::
cdrom:*::
floppy:*::
tape:*::
sudo:*::
audio:*::
dip:*::
www-data:*::
backup:*::
operator:*::
list:*::
irc:*::
src:*::
gnats:*::
shadow:*::
utmp:*::
video:*::
sasl:*::
plugdev:*::
staff:*::
games:*::
users:*::
nogroup:*::
crontab:x::
Debian-exim:x::
myuser:x::

View File

@@ -0,0 +1,20 @@
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
Debian-exim:x:102:102::/var/spool/exim4:/bin/false
myuser:x:424248:424242::/home:/bin/bash

View File

@@ -0,0 +1,20 @@
root:$1$NBLBLIXb$WUgojj1bNuxWEADQGt1m9.:12991:0:99999:7:::
daemon:*:12977:0:99999:7:::
bin:*:12977:0:99999:7:::
sys:*:12977:0:99999:7:::
sync:*:12977:0:99999:7:::
games:*:12977:0:99999:7:::
man:*:12977:0:99999:7:::
lp:*:12977:0:99999:7:::
mail:*:12977:0:99999:7:::
news:*:12977:0:99999:7:::
uucp:*:12977:0:99999:7:::
proxy:*:12977:0:99999:7:::
www-data:*:12977:0:99999:7:::
backup:*:12977:0:99999:7:::
list:*:12977:0:99999:7:::
irc:*:12977:0:99999:7:::
gnats:*:12977:0:99999:7:::
nobody:*:12977:0:99999:7:::
Debian-exim:!:12977:0:99999:7:::
myuser:$1$yQnIAZWV$gDAMB2IkqaONgrQiRdo4y.:12991:0:99999:7:::

50
tests/chage/02/run Executable file
View File

@@ -0,0 +1,50 @@
#!/bin/sh
set -e
cd $(dirname $0)
# Rational:
# Test chage with bogus inputs
# no testsuite password
# root password: rootF00barbaz
# myuser password: myuserF00barbaz
save()
{
[ ! -d tmp ] && mkdir tmp
for i in passwd group shadow gshadow
do
[ -f /etc/$i ] && cp /etc/$i tmp/$i
[ -f /etc/$i- ] && cp /etc/$i- tmp/$i-
done
true
}
restore()
{
for i in passwd group shadow gshadow
do
[ -f tmp/$i ] && cp tmp/$i /etc/$i && rm tmp/$i
[ -f tmp/$i- ] && cp tmp/$i- /etc/$i- && rm tmp/$i-
done
rm -f tmp/out
rmdir tmp
}
save
# restore the files on exit
trap 'if [ "$?" != "0" ]; then echo "FAIL"; fi; restore' 0
for i in passwd group shadow gshadow
do
cp data/$i /etc
done
echo "interractive test"
./run.exp $(date "+%Y-%m-%d")
echo "OK"

83
tests/chage/02/run.exp Executable file
View File

@@ -0,0 +1,83 @@
#!/usr/bin/expect
set timeout 5
proc expect_error {} {
expect {
"chage: error changing fields" {
expect {
eof {
} default {
puts "\nFAIL"
exit 1
}
}
} default {
puts "\nFAIL"
exit 1
}
}
}
# I've not been able to put the opening bracket in the regular expressions
# If anyone knows...
spawn /usr/bin/chage myuser
expect -re "Minimum Password Age .0\]: "
send -- "-2\r"
expect_error
spawn /usr/bin/chage myuser
expect -re "Minimum Password Age .0\]: "
send "foo\r"
expect_error
# chage accepts to be given only spaces
#spawn /usr/bin/chage myuser
#expect -re "Minimum Password Age .0\]: "
#send -- " \r"
#expect_error
#
#chage may not parse all the arguments.
#This may be a problem is a date is provided instead of just a number
#spawn /usr/bin/chage myuser
#expect -re "Minimum Password Age .0\]: "
#send -- "1 2\r"
#expect_error
spawn /usr/bin/chage myuser
expect -re "Minimum Password Age .0\]: "
send "11\r"
expect -re "Maximum Password Age .99999\]: "
send -- "-2\r"
expect_error
spawn /usr/bin/chage myuser
expect -re "Minimum Password Age .0\]: "
send "\r"
expect -re "Maximum Password Age .99999\]: "
send "foo\r"
expect_error
# chage should verify the range of the arguments
#spawn /usr/bin/chage myuser
#expect -re "Minimum Password Age .0\]: "
#send "\r"
#expect -re "Maximum Password Age .99999\]: "
#send "100000\r"
#expect_error
#spawn /usr/bin/chage myuser
#expect -re "Minimum Password Age .0\]: "
#send "\r"
#expect -re "Maximum Password Age .99999\]: "
#send "\r"
#expect -re "Last Password Change \[(]YYYY-MM-DD\[)] .2005-07-25]: "
#send "12\n"
#expect_error
puts "\nPASS"
exit 0

View File

@@ -0,0 +1,48 @@
#!/bin/sh
set -e
cd $(dirname $0)
. ../../common/config.sh
. ../../common/log.sh
log_start "$0" "chage can display its usage message"
save_config
# restore the files on exit
trap 'log_status "$0" "FAILURE"; restore_config' 0
change_config
echo -n "Get chage usage (chage -h)..."
chage -h >tmp/usage.out
echo "OK"
echo "chage reported:"
echo "======================================================================="
cat tmp/usage.out
echo "======================================================================="
echo -n "Check the usage message..."
diff -au data/usage.out tmp/usage.out
echo "usage message OK."
rm -f tmp/usage.out
echo -n "Check the passwd file..."
../../common/compare_file.pl config/etc/passwd /etc/passwd
echo "OK"
echo -n "Check the group file..."
../../common/compare_file.pl config/etc/group /etc/group
echo "OK"
echo -n "Check the shadow file..."
../../common/compare_file.pl config/etc/shadow /etc/shadow
echo "OK"
echo -n "Check the gshadow file..."
../../common/compare_file.pl config/etc/gshadow /etc/gshadow
echo "OK"
log_status "$0" "SUCCESS"
restore_config
trap '' 0

View File

View File

@@ -0,0 +1,42 @@
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
lp:x:7:
mail:x:8:
news:x:9:
uucp:x:10:
man:x:12:
proxy:x:13:
kmem:x:15:
dialout:x:20:
fax:x:21:
voice:x:22:
cdrom:x:24:
floppy:x:25:
tape:x:26:
sudo:x:27:
audio:x:29:
dip:x:30:
www-data:x:33:
backup:x:34:
operator:x:37:
list:x:38:
irc:x:39:
src:x:40:
gnats:x:41:
shadow:x:42:
utmp:x:43:
video:x:44:
sasl:x:45:
plugdev:x:46:
staff:x:50:
games:x:60:
users:x:100:
nogroup:x:65534:
crontab:x:101:
Debian-exim:x:102:
myuser:x:424242:

View File

@@ -0,0 +1,42 @@
root:*::
daemon:*::
bin:*::
sys:*::
adm:*::
tty:*::
disk:*::
lp:*::
mail:*::
news:*::
uucp:*::
man:*::
proxy:*::
kmem:*::
dialout:*::
fax:*::
voice:*::
cdrom:*::
floppy:*::
tape:*::
sudo:*::
audio:*::
dip:*::
www-data:*::
backup:*::
operator:*::
list:*::
irc:*::
src:*::
gnats:*::
shadow:*::
utmp:*::
video:*::
sasl:*::
plugdev:*::
staff:*::
games:*::
users:*::
nogroup:*::
crontab:x::
Debian-exim:x::
myuser:x::

View File

@@ -0,0 +1,26 @@
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
Debian-exim:x:102:102::/var/spool/exim4:/bin/false
myuser1:x:424242:424242::/home:/bin/bash
myuser2:x:424243:424242::/home:/bin/bash
myuser3:x:424244:424242::/home:/bin/bash
myuser4:x:424245:424242::/home:/bin/bash
myuser5:x:424246:424242::/home:/bin/bash
myuser6:x:424247:424242::/home:/bin/bash
myuser7:x:424248:424242::/home:/bin/bash

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