Compare commits

...

56 Commits
4.2.1 ... 4.3.0

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

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

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

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

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

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

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

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

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

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

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

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

With this patch it will be like:

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

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

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

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

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

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

Thanks!

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

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

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

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

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

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

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

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

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

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

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

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

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

Reported-by: Philippe Grégoire <gregoirep@hotmail.com>
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
2014-06-13 09:41:09 -05:00
10074 changed files with 369677 additions and 219 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)
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

@@ -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,19 @@ 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;
}
}
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

@@ -103,6 +103,17 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-C</option>, <option>--clear</option>
</term>
<listitem>
<para>
Clear lastlog record of an 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 an 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

@@ -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>
@@ -85,6 +82,8 @@
<para>
The <command>newgidmap</command> sets <filename>/proc/[pid]/gid_map</filename> based on it's
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>

View File

@@ -82,6 +82,8 @@
<para>
The <command>newuidmap</command> sets <filename>/proc/[pid]/uid_map</filename> based on it's
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>

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

@@ -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

@@ -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

@@ -370,7 +370,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 +380,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

@@ -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;
@@ -120,6 +120,7 @@ int main(int argc, char **argv)
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

@@ -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;
@@ -120,6 +120,7 @@ int main(int argc, char **argv)
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

@@ -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

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::

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

View File

@@ -0,0 +1,54 @@
#!/bin/sh
set -e
cd $(dirname $0)
. ../../common/config.sh
. ../../common/log.sh
log_start "$0" "chage displays its usage message when an invalid option is used"
save_config
# restore the files on exit
trap 'log_status "$0" "FAILURE"; restore_config' 0
change_config
echo -n "Use chage with an invalid option (chage -Z bin)..."
chage -Z bin 2>tmp/usage.out && exit 1 || {
status=$?
}
echo "OK"
echo -n "Check returned status ($status)..."
test "$status" = "2"
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

@@ -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::

View File

@@ -0,0 +1,17 @@
chage: invalid option -- 'Z'
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

View File

@@ -0,0 +1,54 @@
#!/bin/sh
set -e
cd $(dirname $0)
. ../../common/config.sh
. ../../common/log.sh
log_start "$0" "chage displays its usage message when 2 users are provided"
save_config
# restore the files on exit
trap 'log_status "$0" "FAILURE"; restore_config' 0
change_config
echo -n "Use chage with 2 users (chage -I 12 bin nobody)..."
chage -I 12 bin nobody 2>tmp/usage.out && exit 1 || {
status=$?
}
echo "OK"
echo -n "Check returned status ($status)..."
test "$status" = "2"
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

@@ -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::

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

View File

@@ -0,0 +1,54 @@
#!/bin/sh
set -e
cd $(dirname $0)
. ../../common/config.sh
. ../../common/log.sh
log_start "$0" "chage displays its usage message when no users are provided"
save_config
# restore the files on exit
trap 'log_status "$0" "FAILURE"; restore_config' 0
change_config
echo -n "Use chage without an user (chage -I 12)..."
chage -I 12 2>tmp/usage.out && exit 1 || {
status=$?
}
echo "OK"
echo -n "Check returned status ($status)..."
test "$status" = "2"
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

@@ -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:

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