From d72194c6a56899eed06adfc2cf23e05fa2396b0a Mon Sep 17 00:00:00 2001 From: zyppe <210hcl@gmail.com> Date: Mon, 5 Feb 2024 14:57:53 +0800 Subject: [PATCH] Initialize for shadow --- .gitignore | 2 + .shadow.metadata | 2 + README.changes-pwdutils | 62 ++ chkname-regex.patch | 105 +++ disable_new_audit_function.patch | 28 + shadow-4.1.5.1-logmsg.patch | 11 + shadow-4.1.5.1-userdel-helpfix.patch | 14 + shadow-4.8.1-AUDIT_NO_ID.patch | 18 + ...8.1-add-prefix-passwd-chpasswd-chage.patch | 673 ++++++++++++++++++ shadow-4.8.1-lock-mechanism.patch | 232 ++++++ shadow-4.8.1.tar.xz.asc | 11 + shadow-CVE-2023-29383.patch | 51 ++ shadow-login_defs-check.sh | 256 +++++++ shadow-login_defs-comments.patch | 104 +++ shadow-login_defs-suse.patch | 154 ++++ shadow-login_defs-unused-by-pam.patch | 253 +++++++ shadow-util-linux.patch | 162 +++++ shadow.changes | 392 ++++++++++ shadow.keyring | 54 ++ shadow.service | 10 + shadow.spec | 385 ++++++++++ shadow.timer | 7 + useradd-default.patch | 9 + useradd-script.patch | 88 +++ useradd-userkeleton.patch | 165 +++++ useradd.local | 49 ++ userdel-post.local | 29 + userdel-pre.local | 32 + userdel-script.patch | 104 +++ 29 files changed, 3462 insertions(+) create mode 100644 .gitignore create mode 100644 .shadow.metadata create mode 100644 README.changes-pwdutils create mode 100644 chkname-regex.patch create mode 100644 disable_new_audit_function.patch create mode 100644 shadow-4.1.5.1-logmsg.patch create mode 100644 shadow-4.1.5.1-userdel-helpfix.patch create mode 100644 shadow-4.8.1-AUDIT_NO_ID.patch create mode 100644 shadow-4.8.1-add-prefix-passwd-chpasswd-chage.patch create mode 100644 shadow-4.8.1-lock-mechanism.patch create mode 100644 shadow-4.8.1.tar.xz.asc create mode 100644 shadow-CVE-2023-29383.patch create mode 100644 shadow-login_defs-check.sh create mode 100644 shadow-login_defs-comments.patch create mode 100644 shadow-login_defs-suse.patch create mode 100644 shadow-login_defs-unused-by-pam.patch create mode 100644 shadow-util-linux.patch create mode 100644 shadow.changes create mode 100644 shadow.keyring create mode 100644 shadow.service create mode 100644 shadow.spec create mode 100644 shadow.timer create mode 100644 useradd-default.patch create mode 100644 useradd-script.patch create mode 100644 useradd-userkeleton.patch create mode 100644 useradd.local create mode 100644 userdel-post.local create mode 100644 userdel-pre.local create mode 100644 userdel-script.patch diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8c0a906 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +pamd.tar.bz2 +shadow-4.8.1.tar.xz diff --git a/.shadow.metadata b/.shadow.metadata new file mode 100644 index 0000000..88410f7 --- /dev/null +++ b/.shadow.metadata @@ -0,0 +1,2 @@ +340cc50379d3e79da3848d313129d12d69d364f1023973c933c509d251fbaf0a pamd.tar.bz2 +b0f578b81b5f4f46ab93dfbe7998b30707e90e9f5d8fcb41b88f2c2a3d8380c7 shadow-4.8.1.tar.xz diff --git a/README.changes-pwdutils b/README.changes-pwdutils new file mode 100644 index 0000000..f754ba7 --- /dev/null +++ b/README.changes-pwdutils @@ -0,0 +1,62 @@ +This file lists changes between pwdutils used in the past and +the shadow utils used now. + +General changes: +================ +- No support to modify LDAP accounts anymore (-D and --service option) +- No -P/--path option +- /etc/default/passwd was removed. The configure options are + partly available in /etc/login.defs. + +/etc/login.defs: +---------------- +SYSTEM_UID_MIN/SYSTEM_UID_MAX were renamed to SYS_UID_MIN/SYS_UID_MAX +SYSTEM_GID_MIN/SYSTEM_GID_MAX were renamed to SYS_GID_MIN/SYS_GID_MAX + +chfn +---- +-m/--other has changed to -o/--other +-o/--office has changed to -r/--room. +-p/--phone has changed to -w/--work-phone + +chpasswd +-------- +-c blowfish is now longer supported, instead SHA256 and SHA512 were added. + +chsh +---- +-l/--list-shells was removed. + +gpasswd +------- +-l/-u option are missing + +groupadd +-------- +/usr/sbin/groupadd.local is missing +--preferred-gid was removed + +groupmod +-------- +-A/--add-user was removed +-R/--remove-user was removed + +passwd +------ +-f was dropped (use chfn instead) +-g was dropped (use gpasswd instead) +-s was dropped (use chsh instead) + +useradd +------- +-e/--expire has changed to -e/--expiredate (incompatible arguments!) +-U/--umask was removed, -U has now another meaning +--preferred-uid was removed + +userdel +------- +-r/--remove-home was renamed to -r/--remove + +usermod +------- +-e/--expire has changed to -e/--expiredate (incompatible arguments!) diff --git a/chkname-regex.patch b/chkname-regex.patch new file mode 100644 index 0000000..83b3af8 --- /dev/null +++ b/chkname-regex.patch @@ -0,0 +1,105 @@ +Index: etc/login.defs +=================================================================== +--- etc/login.defs.orig ++++ etc/login.defs +@@ -299,3 +299,11 @@ USERGROUPS_ENAB yes + # missing. + # + #FORCE_SHADOW yes ++ ++# ++# User/group names must match the following regex expression. ++# The default is [A-Za-z_][A-Za-z0-9_.-]*[A-Za-z0-9_.$-]\?, ++# but be aware that the result could depend on the locale settings. ++# ++#CHARACTER_CLASS [A-Za-z_][A-Za-z0-9_.-]*[A-Za-z0-9_.$-]\? ++CHARACTER_CLASS [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_][ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.-]*[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.$-]\? +Index: lib/getdef.c +=================================================================== +--- lib/getdef.c.orig ++++ lib/getdef.c +@@ -80,6 +80,7 @@ struct itemdef { + + #define NUMDEFS (sizeof(def_table)/sizeof(def_table[0])) + static struct itemdef def_table[] = { ++ {"CHARACTER_CLASS", NULL}, + {"CHFN_RESTRICT", NULL}, + {"CONSOLE_GROUPS", NULL}, + {"CONSOLE", NULL}, +Index: libmisc/chkname.c +=================================================================== +--- libmisc/chkname.c.orig ++++ libmisc/chkname.c +@@ -43,8 +43,11 @@ + #ident "$Id$" + + #include ++#include + #include "defines.h" + #include "chkname.h" ++#include "getdef.h" ++#include + + int allow_bad_names = false; + +@@ -54,24 +57,46 @@ static bool is_valid_name (const char *n + return true; + } + +- /* +- * User/group names must match [a-z_][a-z0-9_-]*[$] +- */ ++ const char *class; ++ regex_t reg; ++ int result; ++ char *buf; ++ ++ /* User/group names must match [A-Za-z_][A-Za-z0-9_-.]*[A-Za-z0-9_-.$]?. ++ This is the POSIX portable character class. The $ at the end is ++ needed for SAMBA. But user can also specify something else in ++ /etc/login.defs. */ ++ class = getdef_str ("CHARACTER_CLASS"); ++ if (!class) ++ class = "[a-z_][a-z0-9_.-]*[a-z0-9_.$-]\\?"; ++ ++ if (asprintf (&buf, "^%s$", class) < 0) ++ return -1; ++ ++ memset (®, 0, sizeof (regex_t)); ++ result = regcomp (®, buf, 0); ++ free (buf); ++ ++ if (result) { ++ size_t length = regerror (result, ®, NULL, 0); ++ char *buffer = malloc (length); ++ if (buffer == NULL) ++ fputs ("running out of memory!\n", stderr); ++ ++ /* else ++ { ++ regerror (result, ®, buffer, length); ++ fprintf (stderr, _("Can't compile regular expression: %s\n"), ++ buffer); ++ } */ + +- if (('\0' == *name) || +- !((('a' <= *name) && ('z' >= *name)) || ('_' == *name))) { ++ regfree(®); + return false; + } + +- while ('\0' != *++name) { +- if (!(( ('a' <= *name) && ('z' >= *name) ) || +- ( ('0' <= *name) && ('9' >= *name) ) || +- ('_' == *name) || +- ('-' == *name) || +- ( ('$' == *name) && ('\0' == *(name + 1)) ) +- )) { +- return false; +- } ++ if (regexec (®, name, 0, NULL, 0) != 0) { ++ regfree(®); ++ return false; + } + + return true; diff --git a/disable_new_audit_function.patch b/disable_new_audit_function.patch new file mode 100644 index 0000000..48be0b0 --- /dev/null +++ b/disable_new_audit_function.patch @@ -0,0 +1,28 @@ +Index: shadow-4.5/src/lastlog.c +=================================================================== +--- shadow-4.5.orig/src/lastlog.c ++++ shadow-4.5/src/lastlog.c +@@ -221,12 +221,15 @@ static void update_one (/*@null@*/const + 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, +@@ -234,6 +237,7 @@ static void update_one (/*@null@*/const + pw->pw_name, (unsigned int) pw->pw_uid, SHADOW_AUDIT_SUCCESS); + } + #endif ++*/ + + if (fwrite (&ll, sizeof(ll), 1, lastlogfile) != 1) { + fprintf (stderr, diff --git a/shadow-4.1.5.1-logmsg.patch b/shadow-4.1.5.1-logmsg.patch new file mode 100644 index 0000000..2085022 --- /dev/null +++ b/shadow-4.1.5.1-logmsg.patch @@ -0,0 +1,11 @@ +--- src/useradd.c ++++ src/useradd.c +@@ -320,7 +320,7 @@ static void fail_exit (int code) + user_name, AUDIT_NO_ID, + SHADOW_AUDIT_FAILURE); + #endif +- SYSLOG ((LOG_INFO, "failed adding user '%s', data deleted", user_name)); ++ SYSLOG ((LOG_INFO, "failed adding user '%s', exit code: %d", user_name, code)); + exit (code); + } + diff --git a/shadow-4.1.5.1-userdel-helpfix.patch b/shadow-4.1.5.1-userdel-helpfix.patch new file mode 100644 index 0000000..9a2d0aa --- /dev/null +++ b/shadow-4.1.5.1-userdel-helpfix.patch @@ -0,0 +1,14 @@ +--- src/userdel.c ++++ src/userdel.c +@@ -143,8 +143,9 @@ static void usage (int status) + "\n" + "Options:\n"), + Prog); +- (void) fputs (_(" -f, --force force removal of files,\n" +- " even if not owned by user\n"), ++ (void) fputs (_(" -f, --force force some actions that would fail otherwise\n" ++ " e.g. removal of user still logged in\n" ++ " or files, even if not owned by the user\n"), + usageout); + (void) fputs (_(" -h, --help display this help message and exit\n"), usageout); + (void) fputs (_(" -r, --remove remove home directory and mail spool\n"), usageout); diff --git a/shadow-4.8.1-AUDIT_NO_ID.patch b/shadow-4.8.1-AUDIT_NO_ID.patch new file mode 100644 index 0000000..7d808c3 --- /dev/null +++ b/shadow-4.8.1-AUDIT_NO_ID.patch @@ -0,0 +1,18 @@ +--- shadow-4.8.1/src/useradd.c 2022-11-18 13:46:45.884713381 +0100 ++++ shadow-4.8.1/src/useradd.c 2022-11-18 14:41:32.774509203 +0100 +@@ -2085,9 +2085,14 @@ + #endif /* ENABLE_SUBIDS */ + + #ifdef WITH_AUDIT ++ /* ++ * Even though we have the ID of the user, we won't send it now ++ * because its not written to disk yet. After close_files it is ++ * and we can use the real ID thereafter. ++ */ + audit_logger (AUDIT_ADD_USER, Prog, + "adding user", +- user_name, (unsigned int) user_id, ++ user_name, AUDIT_NO_ID, + SHADOW_AUDIT_SUCCESS); + #endif + /* diff --git a/shadow-4.8.1-add-prefix-passwd-chpasswd-chage.patch b/shadow-4.8.1-add-prefix-passwd-chpasswd-chage.patch new file mode 100644 index 0000000..061dab0 --- /dev/null +++ b/shadow-4.8.1-add-prefix-passwd-chpasswd-chage.patch @@ -0,0 +1,673 @@ +Patch is a backport of https://github.com/shadow-maint/shadow/pull/714 +by Jaroslav Jindrak +Index: shadow-4.8.1/configure.ac +=================================================================== +--- shadow-4.8.1.orig/configure.ac ++++ shadow-4.8.1/configure.ac +@@ -682,6 +682,8 @@ if test "$enable_utmpx" = "yes"; then + [Define if utmpx should be used]) + fi + ++AC_CHECK_FUNC(fgetpwent_r, [AC_DEFINE(HAVE_FGETPWENT_R, 1, [Defined to 1 if you have the declaration of 'fgetpwent_r'])]) ++ + AC_DEFINE_UNQUOTED(SHELL, ["$SHELL"], [The default shell.]) + + AM_GNU_GETTEXT_VERSION(0.16) +Index: shadow-4.8.1/lib/prototypes.h +=================================================================== +--- shadow-4.8.1.orig/lib/prototypes.h ++++ shadow-4.8.1/lib/prototypes.h +@@ -270,9 +270,7 @@ extern int do_pam_passwd_non_interactive + #endif /* USE_PAM */ + + /* obscure.c */ +-#ifndef USE_PAM + extern bool obscure (const char *, const char *, const struct passwd *); +-#endif + + /* pam_pass.c */ + #ifdef USE_PAM +@@ -288,6 +286,10 @@ extern struct group *prefix_getgrnam(con + extern struct group *prefix_getgrgid(gid_t gid); + extern struct passwd *prefix_getpwuid(uid_t uid); + extern struct passwd *prefix_getpwnam(const char* name); ++#if HAVE_FGETPWENT_R ++extern int prefix_getpwnam_r(const char* name, struct passwd* pwd, ++ char* buf, size_t buflen, struct passwd** result); ++#endif + extern struct spwd *prefix_getspnam(const char* name); + extern struct group *prefix_getgr_nam_gid(const char *grname); + extern void prefix_setpwent(); +@@ -298,9 +300,7 @@ extern struct group* prefix_getgrent(); + extern void prefix_endgrent(); + + /* pwd2spwd.c */ +-#ifndef USE_PAM + extern struct spwd *pwd_to_spwd (const struct passwd *); +-#endif + + /* pwdcheck.c */ + #ifndef USE_PAM +@@ -451,6 +451,8 @@ extern /*@maynotreturn@*/ /*@only@*//*@n + + /* xgetpwnam.c */ + extern /*@null@*/ /*@only@*/struct passwd *xgetpwnam (const char *); ++/* xprefix_getpwnam.c */ ++extern /*@null@*/ /*@only@*/struct passwd *xprefix_getpwnam (const char *); + /* xgetpwuid.c */ + extern /*@null@*/ /*@only@*/struct passwd *xgetpwuid (uid_t); + /* xgetgrnam.c */ +Index: shadow-4.8.1/libmisc/Makefile.am +=================================================================== +--- shadow-4.8.1.orig/libmisc/Makefile.am ++++ shadow-4.8.1/libmisc/Makefile.am +@@ -5,6 +5,14 @@ AM_CPPFLAGS = -I$(top_srcdir)/lib $(ECON + + noinst_LIBRARIES = libmisc.a + ++if USE_PAM ++LIBCRYPT_PAM = $(LIBCRYPT) ++else ++ LIBCRYPT_PAM = ++endif ++ ++libmisc_la_CFLAGS = $(LIBCRYPT_PAM) ++ + libmisc_a_SOURCES = \ + addgrps.c \ + age.c \ +@@ -66,6 +74,7 @@ libmisc_a_SOURCES = \ + utmp.c \ + valid.c \ + xgetpwnam.c \ ++ xprefix_getpwnam.c \ + xgetpwuid.c \ + xgetgrnam.c \ + xgetgrgid.c \ +Index: shadow-4.8.1/libmisc/obscure.c +=================================================================== +--- shadow-4.8.1.orig/libmisc/obscure.c ++++ shadow-4.8.1/libmisc/obscure.c +@@ -32,8 +32,6 @@ + + #include + +-#ifndef USE_PAM +- + #ident "$Id$" + + +@@ -321,6 +319,3 @@ bool obscure (const char *old, const cha + return true; + } + +-#else /* !USE_PAM */ +-extern int errno; /* warning: ANSI C forbids an empty source file */ +-#endif /* !USE_PAM */ +Index: shadow-4.8.1/libmisc/prefix_flag.c +=================================================================== +--- shadow-4.8.1.orig/libmisc/prefix_flag.c ++++ shadow-4.8.1/libmisc/prefix_flag.c +@@ -237,6 +237,29 @@ extern struct passwd *prefix_getpwnam(co + return getpwnam(name); + } + } ++#if HAVE_FGETPWENT_R ++extern int prefix_getpwnam_r(const char* name, struct passwd* pwd, ++ char* buf, size_t buflen, struct passwd** result) ++{ ++ if (passwd_db_file) { ++ FILE* fg; ++ int ret = 0; ++ ++ fg = fopen(passwd_db_file, "rt"); ++ if (!fg) ++ return errno; ++ while ((ret = fgetpwent_r(fg, pwd, buf, buflen, result)) == 0) { ++ if (!strcmp(name, pwd->pw_name)) ++ break; ++ } ++ fclose(fg); ++ return ret; ++ } ++ else { ++ return getpwnam_r(name, pwd, buf, buflen, result); ++ } ++} ++#endif + extern struct spwd *prefix_getspnam(const char* name) + { + if (spw_db_file) { +Index: shadow-4.8.1/libmisc/pwd2spwd.c +=================================================================== +--- shadow-4.8.1.orig/libmisc/pwd2spwd.c ++++ shadow-4.8.1/libmisc/pwd2spwd.c +@@ -34,8 +34,6 @@ + + #ident "$Id$" + +-#ifndef USE_PAM +- + #include + #include "prototypes.h" + #include "defines.h" +@@ -84,7 +82,3 @@ struct spwd *pwd_to_spwd (const struct p + + return &sp; + } +-#else /* USE_PAM */ +-extern int errno; /* warning: ANSI C forbids an empty source file */ +-#endif /* !USE_PAM */ +- +Index: shadow-4.8.1/libmisc/xprefix_getpwnam.c +=================================================================== +--- /dev/null ++++ shadow-4.8.1/libmisc/xprefix_getpwnam.c +@@ -0,0 +1,41 @@ ++/* ++ * SPDX-FileCopyrightText: 2007 - 2009, Nicolas François ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++/* ++ * According to the Linux-PAM documentation: ++ * ++ * 4.1. Care about standard library calls ++ * ++ * In general, writers of authorization-granting applications should ++ * assume that each module is likely to call any or all 'libc' functions. ++ * For 'libc' functions that return pointers to static/dynamically ++ * allocated structures (ie. the library allocates the memory and the ++ * user is not expected to 'free()' it) any module call to this function ++ * is likely to corrupt a pointer previously obtained by the application. ++ * The application programmer should either re-call such a 'libc' ++ * function after a call to the Linux-PAM library, or copy the structure ++ * contents to some safe area of memory before passing control to the ++ * Linux-PAM library. ++ * ++ * Two important function classes that fall into this category are ++ * getpwnam(3) and syslog(3). ++ * ++ * This file provides wrapper to the prefix_getpwnam or prefix_getpwnam_r functions. ++ */ ++ ++#include ++ ++#include "pwio.h" ++ ++#define LOOKUP_TYPE struct passwd ++#define FUNCTION_NAME prefix_getpwnam ++#define ARG_TYPE const char * ++#define ARG_NAME name ++#define DUP_FUNCTION __pw_dup ++#define HAVE_FUNCTION_R HAVE_FGETPWENT_R ++ ++#include "xgetXXbyYY.c" ++ +Index: shadow-4.8.1/src/Makefile.am +=================================================================== +--- shadow-4.8.1.orig/src/Makefile.am ++++ shadow-4.8.1/src/Makefile.am +@@ -80,7 +80,8 @@ endif + LDADD = $(INTLLIBS) \ + $(top_builddir)/libmisc/libmisc.a \ + $(top_builddir)/lib/libshadow.la \ +- $(LIBTCB) ++ $(LIBTCB) \ ++ $(LIBCRYPT) + + if ACCT_TOOLS_SETUID + LIBPAM_SUID = $(LIBPAM) +@@ -94,13 +95,13 @@ else + LIBCRYPT_NOPAM = $(LIBCRYPT) + endif + +-chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) ++chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) -ldl + newuidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) + newgidmap_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCAP) + chfn_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) + chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) + chsh_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD) $(LIBECONF) +-chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) ++chpasswd_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) -ldl + expiry_LDADD = $(LDADD) $(LIBECONF) + gpasswd_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) + groupadd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) +@@ -118,7 +119,7 @@ login_LDADD = $(LDADD) $(LIBPAM) $(LI + newgrp_LDADD = $(LDADD) $(LIBAUDIT) $(LIBCRYPT) $(LIBECONF) + newusers_LDADD = $(LDADD) $(LIBPAM) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT) $(LIBECONF) + nologin_LDADD = +-passwd_LDADD = $(LDADD) $(LIBPAM) $(LIBCRACK) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBECONF) ++passwd_LDADD = $(LDADD) $(LIBPAM) $(LIBCRACK) $(LIBAUDIT) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBECONF) -ldl + pwck_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) + pwconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) + pwunconv_LDADD = $(LDADD) $(LIBAUDIT) $(LIBSELINUX) $(LIBECONF) +Index: shadow-4.8.1/src/chage.c +=================================================================== +--- shadow-4.8.1.orig/src/chage.c ++++ shadow-4.8.1/src/chage.c +@@ -74,6 +74,8 @@ static bool + Wflg = false; /* set expiration warning days */ + static bool amroot = false; + ++static const char *prefix = ""; ++ + static bool pw_locked = false; /* Indicate if the password file is locked */ + static bool spw_locked = false; /* Indicate if the shadow file is locked */ + /* The name and UID of the user being worked on */ +@@ -155,6 +157,7 @@ static /*@noreturn@*/void usage (int sta + (void) fputs (_(" -M, --maxdays MAX_DAYS set maximum number of days before password\n" + " change to MAX_DAYS\n"), usageout); + (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); ++ (void) fputs (_(" -P, --prefix PREFIX_DIR directory prefix\n"), usageout); + (void) fputs (_(" -W, --warndays WARN_DAYS set expiration warning days to WARN_DAYS\n"), usageout); + (void) fputs ("\n", usageout); + exit (status); +@@ -400,12 +403,13 @@ static void process_flags (int argc, cha + {"mindays", required_argument, NULL, 'm'}, + {"maxdays", required_argument, NULL, 'M'}, + {"root", required_argument, NULL, 'R'}, ++ {"prefix", required_argument, NULL, 'P'}, + {"warndays", required_argument, NULL, 'W'}, + {"iso8601", no_argument, NULL, 'i'}, + {NULL, 0, NULL, '\0'} + }; + +- while ((c = getopt_long (argc, argv, "d:E:hiI:lm:M:R:W:", ++ while ((c = getopt_long (argc, argv, "d:E:hiI:lm:M:R:P:W:", + long_options, NULL)) != -1) { + switch (c) { + case 'd': +@@ -469,6 +473,8 @@ static void process_flags (int argc, cha + break; + case 'R': /* no-op, handled in process_root_flag () */ + break; ++ case 'P': /* no-op, handled in process_prefix_flag () */ ++ break; + case 'W': + Wflg = true; + if ( (getlong (optarg, &warndays) == 0) +@@ -818,6 +824,7 @@ int main (int argc, char **argv) + (void) textdomain (PACKAGE); + + process_root_flag ("-R", argc, argv); ++ prefix = process_prefix_flag ("-P", argc, argv); + + #ifdef WITH_AUDIT + audit_help_open (); +Index: shadow-4.8.1/src/chpasswd.c +=================================================================== +--- shadow-4.8.1.orig/src/chpasswd.c ++++ shadow-4.8.1/src/chpasswd.c +@@ -71,6 +71,8 @@ static long sha_rounds = 5000; + static long bcrypt_rounds = 13; + #endif + ++static const char *prefix = ""; ++ + static bool is_shadow_pwd; + static bool pw_locked = false; + static bool spw_locked = false; +@@ -137,6 +139,7 @@ static /*@noreturn@*/void usage (int sta + " the MD5 algorithm\n"), + usageout); + (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); ++ (void) fputs (_(" -P, --prefix PREFIX_DIR directory prefix\n"), usageout); + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) + (void) fputs (_(" -s, --sha-rounds number of rounds for the SHA or BCRYPT\n" + " crypt algorithms\n"), +@@ -161,6 +164,7 @@ static void process_flags (int argc, cha + {"help", no_argument, NULL, 'h'}, + {"md5", no_argument, NULL, 'm'}, + {"root", required_argument, NULL, 'R'}, ++ {"prefix", required_argument, NULL, 'P'}, + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) + {"sha-rounds", required_argument, NULL, 's'}, + #endif /* USE_SHA_CRYPT || USE_BCRYPT */ +@@ -169,9 +173,9 @@ static void process_flags (int argc, cha + + while ((c = getopt_long (argc, argv, + #if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) +- "c:ehmR:s:", ++ "c:ehmR:P:s:", + #else +- "c:ehmR:", ++ "c:ehmR:P:", + #endif + long_options, NULL)) != -1) { + switch (c) { +@@ -189,6 +193,8 @@ static void process_flags (int argc, cha + break; + case 'R': /* no-op, handled in process_root_flag () */ + break; ++ case 'P': /* no-op, handled in process_prefix_flag () */ ++ break; + #if defined(USE_SHA_CRYPT) && defined(USE_BCRYPT) + case 's': + sflg = true; +@@ -429,11 +435,12 @@ int main (int argc, char **argv) + (void) textdomain (PACKAGE); + + process_root_flag ("-R", argc, argv); ++ prefix = process_prefix_flag ("-P", argc, argv); + + process_flags (argc, argv); + + #ifdef USE_PAM +- if (md5flg || eflg || cflg) { ++ if (md5flg || eflg || cflg || prefix[0]) { + use_pam = false; + } + #endif /* USE_PAM */ +Index: shadow-4.8.1/src/passwd.c +=================================================================== +--- shadow-4.8.1.orig/src/passwd.c ++++ shadow-4.8.1/src/passwd.c +@@ -71,6 +71,8 @@ static char *name; /* The name of user + static char *myname; /* The current user's name */ + static bool amroot; /* The caller's real UID was 0 */ + ++static const char *prefix = ""; ++ + static bool + aflg = false, /* -a - show status for all users */ + dflg = false, /* -d - delete password */ +@@ -96,14 +98,16 @@ static long age_max = 0; /* Maximum days + static long warn = 0; /* Warning days before change */ + static long inact = 0; /* Days without change before locked */ + +-#ifndef USE_PAM + static bool do_update_age = false; +-#endif /* ! USE_PAM */ ++#ifdef USE_PAM ++static bool use_pam = true; ++#else ++static bool use_pam = false; ++#endif /* USE_PAM */ + + static bool pw_locked = false; + static bool spw_locked = false; + +-#ifndef USE_PAM + /* + * Size of the biggest passwd: + * $6$ 3 +@@ -119,7 +123,6 @@ static bool spw_locked = false; + */ + static char crypt_passwd[256]; + static bool do_update_pwd = false; +-#endif /* !USE_PAM */ + + /* + * External identifiers +@@ -128,12 +131,10 @@ static bool do_update_pwd = false; + /* local function prototypes */ + static /*@noreturn@*/void usage (int); + +-#ifndef USE_PAM + static bool reuse (const char *, const struct passwd *); + static int new_password (const struct passwd *); + + static void check_password (const struct passwd *, const struct spwd *); +-#endif /* !USE_PAM */ + static /*@observer@*/const char *date_to_str (time_t); + static /*@observer@*/const char *pw_status (const char *); + static void print_status (const struct passwd *); +@@ -168,6 +169,7 @@ static /*@noreturn@*/void usage (int sta + (void) fputs (_(" -q, --quiet quiet mode\n"), usageout); + (void) fputs (_(" -r, --repository REPOSITORY change password in REPOSITORY repository\n"), usageout); + (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout); ++ (void) fputs (_(" -P, --prefix PREFIX_DIR directory prefix\n"), usageout); + (void) fputs (_(" -S, --status report password status on the named account\n"), usageout); + (void) fputs (_(" -u, --unlock unlock the password of the named account\n"), usageout); + (void) fputs (_(" -w, --warndays WARN_DAYS set expiration warning days to WARN_DAYS\n"), usageout); +@@ -177,7 +179,6 @@ static /*@noreturn@*/void usage (int sta + exit (status); + } + +-#ifndef USE_PAM + static bool reuse (const char *pass, const struct passwd *pw) + { + #ifdef HAVE_LIBCRACK_HIST +@@ -441,7 +442,6 @@ static void check_password (const struct + } + } + } +-#endif /* !USE_PAM */ + + static /*@observer@*/const char *date_to_str (time_t t) + { +@@ -476,7 +476,7 @@ static void print_status (const struct p + { + struct spwd *sp; + +- sp = getspnam (pw->pw_name); /* local, no need for xgetspnam */ ++ sp = prefix_getspnam (pw->pw_name); /* local, no need for xprefix_getspnam */ + if (NULL != sp) { + (void) printf ("%s %s %s %lld %lld %lld %lld\n", + pw->pw_name, +@@ -522,11 +522,12 @@ static /*@noreturn@*/void oom (void) + + static char *update_crypt_pw (char *cp) + { +-#ifndef USE_PAM +- if (do_update_pwd) { +- cp = xstrdup (crypt_passwd); ++ if (!use_pam) ++ { ++ if (do_update_pwd) { ++ cp = xstrdup (crypt_passwd); ++ } + } +-#endif /* !USE_PAM */ + + if (dflg) { + *cp = '\0'; +@@ -659,17 +660,18 @@ static void update_shadow (void) + } + if (iflg) { + nsp->sp_inact = (inact * DAY) / SCALE; +- } +-#ifndef USE_PAM +- if (do_update_age) { +- nsp->sp_lstchg = (long) gettime () / SCALE; +- if (0 == nsp->sp_lstchg) { +- /* Better disable aging than requiring a password +- * change */ +- nsp->sp_lstchg = -1; ++ } ++ ++ if (!use_pam) { ++ if (do_update_age) { ++ nsp->sp_lstchg = gettime () / SCALE; ++ if (0 == nsp->sp_lstchg) { ++ /* Better disable aging than requiring a password ++ * change */ ++ nsp->sp_lstchg = -1; ++ } ++ } + } +- } +-#endif /* !USE_PAM */ + + /* + * Force change on next login, like SunOS 4.x passwd -e or Solaris +@@ -736,11 +738,9 @@ int main (int argc, char **argv) + { + const struct passwd *pw; /* Password file entry for user */ + +-#ifndef USE_PAM + char *cp; /* Miscellaneous character pointing */ + + const struct spwd *sp; /* Shadow file entry for user */ +-#endif /* !USE_PAM */ + + sanitize_env (); + +@@ -755,6 +755,12 @@ int main (int argc, char **argv) + (void) textdomain (PACKAGE); + + process_root_flag ("-R", argc, argv); ++ prefix = process_prefix_flag ("-P", argc, argv); ++ ++ if (prefix[0]) { ++ use_pam = false; ++ do_update_age = true; ++ } + + /* + * The program behaves differently when executed by root than when +@@ -781,6 +787,7 @@ int main (int argc, char **argv) + {"quiet", no_argument, NULL, 'q'}, + {"repository", required_argument, NULL, 'r'}, + {"root", required_argument, NULL, 'R'}, ++ {"prefix", required_argument, NULL, 'P'}, + {"status", no_argument, NULL, 'S'}, + {"unlock", no_argument, NULL, 'u'}, + {"warndays", required_argument, NULL, 'w'}, +@@ -788,7 +795,7 @@ int main (int argc, char **argv) + {NULL, 0, NULL, '\0'} + }; + +- while ((c = getopt_long (argc, argv, "adehi:kln:qr:R:Suw:x:", ++ while ((c = getopt_long (argc, argv, "adehi:kln:qr:R:P:Suw:x:", + long_options, NULL)) != -1) { + switch (c) { + case 'a': +@@ -850,6 +857,8 @@ int main (int argc, char **argv) + break; + case 'R': /* no-op, handled in process_root_flag () */ + break; ++ case 'P': /* no-op, handled in process_prefix_flag () */ ++ break; + case 'S': + Sflg = true; /* ok for users */ + break; +@@ -927,11 +936,11 @@ int main (int argc, char **argv) + Prog); + exit (E_NOPERM); + } +- setpwent (); +- while ( (pw = getpwent ()) != NULL ) { ++ prefix_setpwent (); ++ while ( (pw = prefix_getpwent ()) != NULL ) { + print_status (pw); + } +- endpwent (); ++ prefix_endpwent (); + exit (E_SUCCESS); + } + #if 0 +@@ -968,7 +977,7 @@ int main (int argc, char **argv) + exit (E_NOPERM); + } + +- pw = xgetpwnam (name); ++ pw = xprefix_getpwnam (name); + if (NULL == pw) { + (void) fprintf (stderr, + _("%s: user '%s' does not exist\n"), +@@ -1008,53 +1017,56 @@ int main (int argc, char **argv) + print_status (pw); + exit (E_SUCCESS); + } +-#ifndef USE_PAM ++ ++ if (!use_pam) ++ { + /* + * The user name is valid, so let's get the shadow file entry. + */ +- sp = getspnam (name); /* !USE_PAM, no need for xgetspnam */ +- if (NULL == sp) { +- if (errno == EACCES) { +- (void) fprintf (stderr, +- _("%s: Permission denied.\n"), +- Prog); +- exit (E_NOPERM); ++ sp = prefix_getspnam (name); /* !use_pam, no need for xprefix_getspnam */ ++ if (NULL == sp) { ++ if (errno == EACCES) { ++ (void) fprintf (stderr, ++ _("%s: Permission denied.\n"), ++ Prog); ++ exit (E_NOPERM); ++ } ++ sp = pwd_to_spwd (pw); + } +- sp = pwd_to_spwd (pw); +- } +- +- cp = sp->sp_pwdp; +- +- /* +- * If there are no other flags, just change the password. +- */ +- if (!anyflag) { +- STRFCPY (crypt_passwd, cp); +- +- /* +- * See if the user is permitted to change the password. +- * Otherwise, go ahead and set a new password. +- */ +- check_password (pw, sp); + ++ cp = sp->sp_pwdp; + /* + * Let the user know whose password is being changed. ++ * If there are no other flags, just change the password. + */ +- if (!qflg) { +- (void) printf (_("Changing password for %s\n"), name); +- } ++ if (!anyflag) { ++ STRFCPY (crypt_passwd, cp); + +- if (new_password (pw) != 0) { +- (void) fprintf (stderr, +- _("The password for %s is unchanged.\n"), +- name); +- closelog (); +- exit (E_NOPERM); ++ /* ++ * See if the user is permitted to change the password. ++ * Otherwise, go ahead and set a new password. ++ */ ++ check_password (pw, sp); ++ ++ /* ++ * Let the user know whose password is being changed. ++ */ ++ if (!qflg) { ++ (void) printf (_("Changing password for %s\n"), name); ++ } ++ ++ if (new_password (pw) != 0) { ++ (void) fprintf (stderr, ++ _("The password for %s is unchanged.\n"), ++ name); ++ closelog (); ++ exit (E_NOPERM); ++ } ++ do_update_pwd = true; ++ do_update_age = true; + } +- do_update_pwd = true; +- do_update_age = true; + } +-#endif /* !USE_PAM */ ++ + /* + * Before going any further, raise the ulimit to prevent colliding + * into a lowered ulimit, and set the real UID to root to protect +@@ -1067,7 +1079,7 @@ int main (int argc, char **argv) + /* + * Don't set the real UID for PAM... + */ +- if (!anyflag) { ++ if (!anyflag && use_pam) { + do_pam_passwd (name, qflg, kflg); + exit (E_SUCCESS); + } diff --git a/shadow-4.8.1-lock-mechanism.patch b/shadow-4.8.1-lock-mechanism.patch new file mode 100644 index 0000000..1731e84 --- /dev/null +++ b/shadow-4.8.1-lock-mechanism.patch @@ -0,0 +1,232 @@ +Based on: +https://github.com/shadow-maint/shadow/commit/65470e5c7ddbc2885ad35fbd0218b91a75626c2f +Index: shadow-4.8.1/lib/commonio.c +=================================================================== +--- shadow-4.8.1.orig/lib/commonio.c ++++ shadow-4.8.1/lib/commonio.c +@@ -54,8 +54,6 @@ + + /* local function prototypes */ + static int lrename (const char *, const char *); +-static int check_link_count (const char *file); +-static int do_lock_file (const char *file, const char *lock, bool log); + static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms ( + const char *name, + const char *mode, +@@ -117,140 +115,6 @@ int lrename (const char *old, const char + return res; + } + +-static int check_link_count (const char *file) +-{ +- struct stat sb; +- +- if (stat (file, &sb) != 0) { +- return 0; +- } +- +- if (sb.st_nlink != 2) { +- return 0; +- } +- +- return 1; +-} +- +- +-static int do_lock_file (const char *file, const char *lock, bool log) +-{ +- int fd; +- pid_t pid; +- ssize_t len; +- int retval; +- char buf[32]; +- +- fd = open (file, O_CREAT | O_TRUNC | O_WRONLY, 0600); +- if (-1 == fd) { +- if (log) { +- (void) fprintf (stderr, +- "%s: %s: %s\n", +- Prog, file, strerror (errno)); +- } +- return 0; +- } +- +- pid = getpid (); +- snprintf (buf, sizeof buf, "%lu", (unsigned long) pid); +- len = (ssize_t) strlen (buf) + 1; +- if (write (fd, buf, (size_t) len) != len) { +- if (log) { +- (void) fprintf (stderr, +- "%s: %s: %s\n", +- Prog, file, strerror (errno)); +- } +- (void) close (fd); +- unlink (file); +- return 0; +- } +- close (fd); +- +- if (link (file, lock) == 0) { +- retval = check_link_count (file); +- if ((0==retval) && log) { +- (void) fprintf (stderr, +- "%s: %s: lock file already used\n", +- Prog, file); +- } +- unlink (file); +- return retval; +- } +- +- fd = open (lock, O_RDWR); +- if (-1 == fd) { +- if (log) { +- (void) fprintf (stderr, +- "%s: %s: %s\n", +- Prog, lock, strerror (errno)); +- } +- unlink (file); +- errno = EINVAL; +- return 0; +- } +- len = read (fd, buf, sizeof (buf) - 1); +- close (fd); +- if (len <= 0) { +- if (log) { +- (void) fprintf (stderr, +- "%s: existing lock file %s without a PID\n", +- Prog, lock); +- } +- unlink (file); +- errno = EINVAL; +- return 0; +- } +- buf[len] = '\0'; +- if (get_pid (buf, &pid) == 0) { +- if (log) { +- (void) fprintf (stderr, +- "%s: existing lock file %s with an invalid PID '%s'\n", +- Prog, lock, buf); +- } +- unlink (file); +- errno = EINVAL; +- return 0; +- } +- if (kill (pid, 0) == 0) { +- if (log) { +- (void) fprintf (stderr, +- "%s: lock %s already used by PID %lu\n", +- Prog, lock, (unsigned long) pid); +- } +- unlink (file); +- errno = EEXIST; +- return 0; +- } +- if (unlink (lock) != 0) { +- if (log) { +- (void) fprintf (stderr, +- "%s: cannot get lock %s: %s\n", +- Prog, lock, strerror (errno)); +- } +- unlink (file); +- return 0; +- } +- +- retval = 0; +- if (link (file, lock) == 0) { +- retval = check_link_count (file); +- if ((0==retval) && log) { +- (void) fprintf (stderr, +- "%s: %s: lock file already used\n", +- Prog, file); +- } +- } else { +- if (log) { +- (void) fprintf (stderr, +- "%s: cannot get lock %s: %s\n", +- Prog, lock, strerror (errno)); +- } +- } +- +- unlink (file); +- return retval; +-} +- + + static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms ( + const char *name, +@@ -374,6 +238,29 @@ bool commonio_present (const struct comm + return (access (db->filename, F_OK) == 0); + } + ++int do_fcntl_lock (const char *file, bool log, short type) ++{ ++ int fd; ++ struct flock lck = { ++ .l_type = type, ++ .l_whence = SEEK_SET, ++ .l_start = 0, ++ .l_len = 0, ++ }; ++ ++ fd = open (file, O_WRONLY, 0600); ++ if (-1 == fd) { ++ if (log) { ++ (void) fprintf (stderr, "%s: %s: %s\n", ++ Prog, file, strerror (errno)); ++ } ++ return 0; ++ } ++ ++ fcntl (fd, F_OFD_SETLKW, &lck); ++ close(fd); ++ return(1); ++} + + int commonio_lock_nowait (struct commonio_db *db, bool log) + { +@@ -398,8 +285,7 @@ int commonio_lock_nowait (struct commoni + } + snprintf (file, file_len, "%s.%lu", + db->filename, (unsigned long) getpid ()); +- snprintf (lock, lock_file_len, "%s.lock", db->filename); +- if (do_lock_file (file, lock, log) != 0) { ++ if (do_fcntl_lock (db->filename, log, F_WRLCK | F_RDLCK) != 0) { + db->locked = true; + lock_count++; + err = 1; +@@ -499,8 +385,6 @@ static void dec_lock_count (void) + + int commonio_unlock (struct commonio_db *db) + { +- char lock[1024]; +- + if (db->isopen) { + db->readonly = true; + if (commonio_close (db) == 0) { +@@ -511,13 +395,8 @@ int commonio_unlock (struct commonio_db + } + } + if (db->locked) { +- /* +- * Unlock in reverse order: remove the lock file, +- * then call ulckpwdf() (if used) on last unlock. +- */ + db->locked = false; +- snprintf (lock, sizeof lock, "%s.lock", db->filename); +- unlink (lock); ++ do_fcntl_lock (db->filename, false, F_UNLCK); + dec_lock_count (); + return 1; + } +Index: shadow-4.8.1/lib/commonio.h +=================================================================== +--- shadow-4.8.1.orig/lib/commonio.h ++++ shadow-4.8.1/lib/commonio.h +@@ -150,6 +150,7 @@ extern int commonio_setname (struct comm + extern bool commonio_present (const struct commonio_db *db); + extern int commonio_lock (struct commonio_db *); + extern int commonio_lock_nowait (struct commonio_db *, bool log); ++extern int do_fcntl_lock (const char *file, bool log, short type); + extern int commonio_open (struct commonio_db *, int); + extern /*@observer@*/ /*@null@*/const void *commonio_locate (struct commonio_db *, const char *); + extern int commonio_update (struct commonio_db *, const void *); diff --git a/shadow-4.8.1.tar.xz.asc b/shadow-4.8.1.tar.xz.asc new file mode 100644 index 0000000..3a6e6ac --- /dev/null +++ b/shadow-4.8.1.tar.xz.asc @@ -0,0 +1,11 @@ +-----BEGIN PGP SIGNATURE----- + +iQEzBAABCgAdFiEE8dCNt3gYW/eEAC3/6f7qBqheP50FAl4qDlEACgkQ6f7qBqhe +P51Lfwf/b2gxtqo9WRUTOhau4kCy+zDbg3S/K7ZD/20I2t205FNCOyV+cR4Q/PRA ++hBLFsA/WAVqZm0/3re09VDV0eaBpI7hgNF0JFODawIixKdLVff9mbfbLdgzy2Dl +IvbNrUVDJV1wSlEJLIeUpUT4ClFaiExM/XaCvHSUUbRsJ5cutH2wt0neNC8mJHMu +srXoCp8lb4fT+BDgRKoGA6RMvnJSkExBbhrRqaARWWCGnS++5oJiD7UwPAOu9Imb +LtouVitkrjrpQncnQN+zCaKwyTGw/xlQyl0z86DXWbvhnTwUeeWZbyfRAglIsSkk +DRpWh2m7ejcvf1pGt66UBuMNr0yb1w== +=8I3q +-----END PGP SIGNATURE----- diff --git a/shadow-CVE-2023-29383.patch b/shadow-CVE-2023-29383.patch new file mode 100644 index 0000000..362191b --- /dev/null +++ b/shadow-CVE-2023-29383.patch @@ -0,0 +1,51 @@ +Index: shadow-4.8.1/lib/fields.c +=================================================================== +--- shadow-4.8.1.orig/lib/fields.c ++++ shadow-4.8.1/lib/fields.c +@@ -44,9 +44,9 @@ + * + * The supplied field is scanned for non-printable and other illegal + * characters. +- * + -1 is returned if an illegal character is present. +- * + 1 is returned if no illegal characters are present, but the field +- * contains a non-printable character. ++ * + -1 is returned if an illegal or control character is present. ++ * + 1 is returned if no illegal or control characters are present, ++ * but the field contains a non-printable character. + * + 0 is returned otherwise. + */ + int valid_field (const char *field, const char *illegal) +@@ -60,23 +60,22 @@ int valid_field (const char *field, cons + + /* For each character of field, search if it appears in the list + * of illegal characters. */ ++ if (illegal && NULL != strpbrk (field, illegal)) { ++ return -1; ++ } ++ ++ /* Search if there are non-printable or control characters */ + for (cp = field; '\0' != *cp; cp++) { +- if (strchr (illegal, *cp) != NULL) { ++ unsigned char c = *cp; ++ if (!isprint (c)) { ++ err = 1; ++ } ++ if (iscntrl (c)) { + err = -1; + break; + } + } + +- if (0 == err) { +- /* Search if there are some non-printable characters */ +- for (cp = field; '\0' != *cp; cp++) { +- if (!isprint (*cp)) { +- err = 1; +- break; +- } +- } +- } +- + return err; + } + diff --git a/shadow-login_defs-check.sh b/shadow-login_defs-check.sh new file mode 100644 index 0000000..6994294 --- /dev/null +++ b/shadow-login_defs-check.sh @@ -0,0 +1,256 @@ +#!/bin/bash + +# login.defs and lib/getdef.c contain support for third party variables. +# It also contains support for variables that are unusable in installations with PAM support enabled. +# This script generates a list of used and unused variables in login.defs +# with respect to the current configuration. +# Arguments: arguments of osc build +# If the shadow-login_defs-check-unused.lst is generated, you should +# update login.defs. + +set -o errexit + +echo "Preparing..." + +# Check for required commands +which quilt >/dev/null +which osc >/dev/null + +# login.defs is shared with util-linux login, su and runuser. +# Extract list of referenced variables. +if ! test -f openSUSE:Factory/util-linux/BUILD/*/configure.ac ; then + echo "Checking out util-linux..." + osc co openSUSE:Factory util-linux + cd openSUSE:Factory/util-linux + quilt setup -d BUILD util-linux.spec + cd BUILD/* + quilt push -a + cd ../../../.. +fi + +echo "Extracting variables from util-linux..." +cd openSUSE:Factory/util-linux/BUILD/* +( + grep -rh getlogindefs . | + sed -n 's/^.*getlogindefs[a-z_]*("\([A-Z0-9_]*\)".*$/\1/p' + grep -rh logindefs_setenv . | + sed -n 's/^.*logindefs_setenv*("[A-Z0-9_]*", "\([A-Z0-9_]*\)".*$/\1/p' +) | + LC_ALL=C sort -u >../../../../shadow-login_defs-check-util-linux.lst +cd ../../../.. + +# login.defs is shared pam_unix*.so, pam_faildelay.so and pam_umask.so. +# Extract list of referenced variables. +if ! test -f openSUSE:Factory/pam/BUILD/*/configure.ac ; then + echo "Checking out pam..." + osc co openSUSE:Factory pam + cd openSUSE:Factory/pam + quilt setup -d BUILD pam.spec + cd BUILD/* + quilt push -a + cd ../../../.. +fi + +echo "Extracting variables from pam..." +cd openSUSE:Factory/pam/BUILD/* +grep -rh LOGIN_DEFS . | + sed -n 's/^.*search_key *([A-Za-z_]*, *[A-Z_]*LOGIN_DEFS, *"\([A-Z0-9_]*\)").*$/\1/p' | + LC_ALL=C sort -u >../../../../shadow-login_defs-check-pam.lst +cd ../../../.. + +if ! test -f shadow-login_defs-check-build/stamp ; then + echo "Performing preprocessing of shadow by osc..." + if ! test -f shadow.spec.shadow-login_defs-check-save ; then + cp -a shadow.spec shadow.spec.shadow-login_defs-check-save + +# In case of shadow, variables extraction is more complicated. The list +# depends on configure options, so we have to perform a fake build and +# extract variables from prepreocessed sources. + patch <shadow-login_defs-check-deleted.lst + +# The build above is optional only for case of failure or edits in the +# code below. If any other build was performed, don't expect correct +# results. + +cd shadow-login_defs-check-build/shadow-* + +echo "Extracting variables from etc/login.defs..." +# Extract variables referenced in login.defs, both active and commented out. +sed -n "s/^#//;s/\([A-Z0-9_]*\)\([[:space:]].*\|\)$/\1/p" ../../shadow-login_defs-check-login_defs.lst +LC_ALL=C sort -u ../../shadow-login_defs-check-login_defs.lst >../../shadow-login_defs-check-login_defs-sorted.lst + +echo "Extracting variables from lib/getdef.c..." +# Extract variables referenced in lib/getdef.c using current defines. +sed -n 's/^\(},\|\) {"\([A-Z0-9_]*\)", /\2/p' ../../shadow-login_defs-check-getdef.lst +LC_ALL=C sort -u ../../shadow-login_defs-check-getdef.lst >../../shadow-login_defs-check-getdef-sorted.lst + +echo "Extracting variables from shadow..." +# Extract variables referenced in preprocessed files. +grep -r '\(getdef[a-z_]*\|call_script\|is_listed\) *( *"[A-Za-z0-9_]*"' | + grep '[^ ]*\.o:' >../../shadow-login_defs-check-shadow.log + +cd ../.. + +export RC=0 +echo "" +echo "" +echo "Performing checks..." + +sed ' + s/^.*\(getdef[a-z_]*\|call_script\|is_listed*\) *( *"\([A-Za-z0-9_]*\)".*$/\2/ +' ../../shadow-login_defs-check-shadow-all.lst + +sed 's%^\(.*\)%/^.*\\\/\1\.o:/d%' shadow-login_defs-check-deleted.sed +sed -f shadow-login_defs-check-deleted.sed shadow-login_defs-check-shadow-used.lst + +if ! test -s shadow-login_defs-check-deleted.sed ; then + echo " BUG: Empty shadow-login_defs-check-deleted.sed Results will be unreliable!" + if test $RC -le 4 ; then export RC=4 ; fi +fi + +echo "" +echo "Checking that variables in login.defs are referred only once..." +if test $(wc -l shadow-login_defs-check-login_defs.lst | sed 's/ .*//') != $(wc -l shadow-login_defs-check-login_defs-sorted.lst | sed 's/ .*//') ; then + echo " ERROR: Some variable referred at more places of login.defs!" + LC_ALL=C sort shadow-login_defs-check-login_defs.lst >shadow-login_defs-check-login_defs-sorted-nu.lst + diff shadow-login_defs-check-login_defs-sorted-nu.lst shadow-login_defs-check-login_defs-sorted.lst + if test $RC -le 3 ; then export RC=3 ; fi +fi + +echo "" +echo "Checking that variables in lib/getdef.c are referred only once..." +if test $(wc -l shadow-login_defs-check-getdef.lst | sed 's/ .*//') != $(wc -l shadow-login_defs-check-getdef-sorted.lst | sed 's/ .*//') ; then + echo " ERROR: Some variable referred at more places of lib/getdef.c!" + LC_ALL=C sort shadow-login_defs-check-getdef.lst >shadow-login_defs-check-getdef-sorted-nu.lst + diff shadow-login_defs-check-getdef-sorted-nu.lst shadow-login_defs-check-getdef-sorted.lst + if test $RC -le 3 ; then export RC=3 ; fi +fi + +cat shadow-login_defs-check-shadow-used.lst shadow-login_defs-check-util-linux.lst shadow-login_defs-check-pam.lst | LC_ALL=C sort -u >shadow-login_defs-check-all-used.lst +# RC inside pipe cannot be read directly. Use 3 for a real stdout inside the pipe, and use stdout for RC. +exec 3>&1 +function report_packages() { + echo -n " (" + grep -l $1 shadow-login_defs-check-{shadow-used,util-linux,pam}.lst | + sed 's/shadow-login_defs-check-//;s/\.lst//;s/-used//;s/$/, /;$s/, $//' | + tr -d '\n' + echo -n ")" +} + +# Extracting variables from shadow is not capable to identify compiled-but-unused library code. +# This function will identify known false matches. +function falsematch() { + case "$1" in +# MAIL_* used by library call mailcheck() used only by login.c that is deleted in the spec. + MAIL_* ) return 0 ;; +# FTMP_FILE used by library call failtmp() used only by login.c that is deleted in the spec. + FTMP_FILE ) return 0 ;; +# ISSUE_FILE used by library call login_prompt() used only by login.c that is deleted in the spec. + ISSUE_FILE ) return 0 ;; + * ) return 1 ;; + esac +} + +echo "" +echo "Checking that all used variables are covered by login.defs..." +RC=$(cat shadow-login_defs-check-all-used.lst | ( + while read ; do + if falsematch "$REPLY" ; then + echo " FALSE MATCH: Variable $REPLY is not present in login.defs$(report_packages $REPLY)" >&3 + continue + fi + if ! grep -q -x "$REPLY" shadow-login_defs-check-login_defs-sorted.lst ; then + echo " NOTICE: Variable $REPLY is not present in login.defs$(report_packages $REPLY)" >&3 + if test $RC -le 2 ; then RC=2 ; fi + fi + done + echo $RC +) ) + +echo "" +echo "Checking that all used variables are covered by lib/getdef.c..." +RC=$(cat shadow-login_defs-check-all-used.lst | ( + while read ; do + if falsematch "$REPLY" ; then continue ; fi + if ! grep -q -x "$REPLY" shadow-login_defs-check-getdef.lst ; then + echo " ERROR: Variable $REPLY is missing in the parser$(report_packages $REPLY)" >&3 + if test $RC -le 3 ; then RC=3 ; fi + fi + done + echo $RC +) ) + +echo "" +echo "Checking that all used variables referred in login.defs are valid..." +RC=$(cat shadow-login_defs-check-login_defs.lst | ( + while read ; do + if ! grep -q -x "$REPLY" shadow-login_defs-check-all-used.lst ; then + echo " ERROR: Failed to find reference for $REPLY" >&3 + if test $RC -le 3 ; then RC=3 ; fi + fi + if ! grep -q -x "$REPLY" shadow-login_defs-check-getdef.lst ; then + echo " BUG: Parser does not contain reference for $REPLY" >&3 + if test $RC -le 4 ; then RC=4 ; fi + fi + done + echo $RC +) ) + + +echo "" +echo "" +echo "All checks finished." +echo -n "Result: " +case $RC in +0) echo "OK." ;; +1) echo "Notices only. Action is optional." ;; +2) echo "Warnings only. Evaluation is needed." ;; +3) echo "Errors found. Fix is recommended." ;; +4) echo "Fatal error. Fix has to be done." ;; +esac + +if test $RC -ge 1 ; then + exit 1 +fi + +echo " +If you ported shadow-util-linux.patch to the new util-linux version, +please submit these updates: +Change in util-linux.spec:" +sed -n 's/^Version:[[:space:]]*/Requires: login_defs-support-for-util-linux >= /p' = /p' = 2.37. +- Refresh shadow-login_defs-suse.patch. +* Thu Jan 28 2021 sbrabec@suse.com +- Do not require libeconf-devel on products without /usr/etc. +* Thu Jan 21 2021 kukuk@suse.com +- Split login.defs configuration file into own sub-package, which + allows to install util-linux or pam on small embedded/edge + systems or container without the need to pull in the full shadow + suite. +* Wed Nov 11 2020 fvogt@suse.com +- Amend patches/useradd-userkeleton.patch to also write into + existing directories and prefer files from /etc +* Wed Nov 11 2020 werner@suse.de +- Add patch useradd-userkeleton.patch to extend original C code + of useradd to handle /usr/etc/skel (boo#1173321) +- Remove /usr/etc/skel support in useradd.local script +* Mon Nov 2 2020 werner@suse.de +- Change again useradd.local script to let it work even for system + accounts and work together with SELinux (bsc#1178296) +- Change patch useradd-script.patch to support the four arguments + used by the useradd.local script (bsc#1178296) +* Fri Oct 9 2020 werner@suse.de +- Add support for /usr/etc/skel to useradd.local script (boo#1173321) +* Thu Oct 8 2020 sbrabec@suse.com +- shadow-login_defs-check.sh: Fix the regexp to get a real variable + list (boo#1164274). +* Tue Sep 8 2020 sbrabec@suse.com +- login.defs: Add support for new util-linux-2.36 login variable + MOTD_FIRSTONLY (shadow-util-linux.patch). +- shadow-login_defs-comments.patch: Remove duplicated + LASTLOG_UID_MAX. +- shadow-login_defs-check.sh: Update for new build system. +- shadow-util-linux.patch: Restore lost chunk: SYSLOG_SU_ENAB is + not used in SUSE Linux. +- Refresh shadow-login_defs-suse.patch and + shadow-login_defs-comments.patch. +* Fri May 22 2020 fvogt@suse.com +- Use pure #!/bin/sh in: + * useradd.local + * userdel-post.local + * userdel-pre.local +* Fri Jan 24 2020 mvetter@suse.com +- Update to 4.8.1: + * selinux: include stdio + * man: don't suggest making groupmems user-writeable + * Makefile: bail out on error in for loops + * Adding logging of SSH_ORIGINAL_COMMAND to nologin + * add new HOME_MODE login.defs option + * Add tty logging to useradd + * Useradd: make non-executable shell check only a warning + * Update Dutch translation + * user_busy: Do not mistake a regular user process for a namespaced one + * Revert "Honor --sbindir and --bindir for binary installation" +- Remove shadow-4.8-shell-check.patch: included +- Remove shadow-4.8-selinux-include.patch: upstreamed +* Mon Jan 20 2020 mvetter@suse.com +- Set 0755 for chpasswd, groupadd, groupdel, groupmod, newusers, + useradd, userdel, usermod explicitly. +* Thu Jan 16 2020 mvetter@suse.com +- bsc#1160729: Make valid shell check only a warning + * Add shadow-4.8-shell-check.patch +* Tue Dec 17 2019 mvetter@suse.com +- Update to 4.8: + * Initial optional bcrypt support. + * Make build/install of 'su' optional. + * Fix for vipw not resuming correctly when suspended + * Sync password field descriptions in manpages + * Check for valid shell argument in useradd + * Allow translation of new strings through POTFILES.in + * Migrate to itstool for translations + * Migrate to new SELinux api + * Support --enable-vendordir + * pwck: Only check homedir if set and not a system user + * Support nonstandard usernames + * sget{pw,gr}ent: check for data at EOL + * Add YYY-MM-DD support in chage + * Fix failing chmod calls for suidubins + * Fix --sbindir and --bindir for binary installations + * Fix LASTLOG_UID_MAX in login.defs + * Fix configure error with dash +- Remove because upstreamed: + * libeconf.patch + * shadow-usermod-variable.patch +- Rebase: + * shadow-login_defs-unused-by-pam.patch + * chkname-regex.patch + * shadow-util-linux.patch + * shadow-login_defs-comments.patch +- Add shadow-4.8-selinux-include.patch + See https://github.com/shadow-maint/shadow/pull/200 +* Mon Oct 7 2019 kukuk@suse.de +- libeconf.patch: Add support for libeconf and /usr/etc for + login.defs. +- Move first configuration files and pam config files to /usr/etc +* Mon Sep 2 2019 mvetter@suse.com +- bsc#1144060: Add pam_keyinit.so to /etc/pam.d configuration files + to support kernel keyring feature +- Update pamd.tar.bz2 with pam configuration files accordingly +* Mon Aug 19 2019 kukuk@suse.de +- encryption_method_nis.patch: drop, DES should really not be used + anymore anywhere, even with NIS +- shadow-login_defs-suse.patch: remove encryption NIS entry +* Fri Jul 26 2019 sbrabec@suse.com +- Fix incorrect variable name in usermod + (shadow-usermod-variable.patch). +- shadow-login_defs-comments.patch: + * Drop SHA_CRYPT_*_ROUNDS that are in the upstream login.defs. + * Add missing LASTLOG_UID_MAX. + * Refresh shadow-login_defs-suse.patch. +- Port shadow-login_defs-check.sh to match the current spec file + and login.defs. +* Thu Jul 25 2019 kukuk@suse.de +- Provide "useradd_or_adduser_dep" for sysuser-shadow +* Sat Jul 20 2019 sbrabec@suse.com +- shadow-login_defs-suse.patch: Set ALWAYS_SET_PATH default to + "yes" (bsc#353876#c7). +* Fri Jul 19 2019 sbrabec@suse.com +- Fix comment about patch in spec file +* Fri Jun 14 2019 mvetter@suse.com +- Update to 4.7: + * Spawn: don't loop forever on ECHILD + * Do not fail locking if there is a stale lockfile (Tomas Mraz) + * Use lckpwdf if prefix not set (Tomas Mraz) + * Build: check correct DocBook version (Jan Tojnar) + * Usermod: Print 'no changes' to stdout, not stderr (Serge Hallyn) + * Add support for btrfs subvolumes for home (Adam Majer) + * Fix chpasswd long line handling (Nathan Ruiz) + * Use secure_getenv for gettime (Chris Lamb) + * Make sp_lstchg reproducible (Chris Lamb) + * Do not crash commonio_close if db file is not open (Tomas Mraz) + * Don't flush nscd and sssd cache in read-only mode (Charlie Vuillemez) + * French manpage update (Alban VIDAL) + * Fix manpage defaults for SUB_UID/GID_COUNT (Tomas Mraz) + * Sync po files from shadow.pot (Alban VIDAL) + * Usermod: guard against unsafe chown of homedir contents (Tomas Mraz) + * Add LASTLOG_UID_MAX to login.defs (Tomas Mraz) + * new[ug]idmap file capabilities support (Giuseppe Scrivano and Christian Brauner) + * Fix segfault in useradd (bsc#1141113, Tomas Mraz) + * Coverity issues (Tomas Mraz) + * Flush sssd caches (Jakub Hrozek) + * Log UID in nologin (Vladimir Ivanov) + * run pam_getenvlist after setup_env in su.c (Michael Vogt) + * Support systems with only utmpx (A. Wilcox) + * Fix unguarded ENABLE_SUBIDS code (Jan Chren (rindeal)) + * Update po/zh_CN translation (Lion Yang) + * Create parent dirs for useradd -m (Michael Vetter) + * Prevent usermod segv + * Fix usermod crash (fariouche) +- Remove btrfs-subvolumes.patch (fate#316134): + upstreamed: https://github.com/shadow-maint/shadow/pull/149 +- Remove useradd-mkdirs.patch (bsc#865563): + upstreamed https://github.com/shadow-maint/shadow/pull/112 +- Remove shadow-4.6.0-fix-usermod-prefix-crash.patch + upstreamed https://github.com/shadow-maint/shadow/issues/110 +- Remove shadow-4.6-bsc1141113-useradd-segfault.patch + (SLE15 SP3 and openSUSE Leap 15.3 only) + upstreamed https://github.com/shadow-maint/shadow/issues/125 +- Rebase userdel-script.patch +- Rebase useradd-script.patch +- Rebase shadow-util-linux.patch +* Thu May 30 2019 mpluskal@suse.com +- Make building more verbose +- Use spec-cleaner +* Thu May 2 2019 lnussel@suse.de +- don't specify MOTD_FILE in login.defs but fall back to built in + defaults of login (boo#1133929) +* Tue Apr 30 2019 sbrabec@suse.com +- Split shadow-login_defs.patch hunks to its logical components + (bsc#1121197): + * shadow-login_defs-unused-by-pam.patch + * shadow-login_defs-comments.patch + * shadow-util-linux.patch + * shadow-login_defs-suse.patch + * Move appropriate hunks to chkname-regex.patch and + encryption_method_nis.patch + * Remove GROUPADD_CMD that is not supported (bsc#1121197#c14). +- Split getdef-new-defs.patch hunks to its logical components + (bsc#1121197): + * encryption_method_nis.patch + * chkname-regex.patch + * shadow-util-linux.patch + Add support for login: ALWAYS_SET_PATH and LOGIN_PLAIN_PROMPT. + * useradd-script.patch, userdel-script.patch + * Remove duplicated definitions of MOTD_FILE and ENV_PATH. +- Add shadow-login_defs-unused-check.sh to allow verification of + login.defs variable usage (bsc#1121197). +- Add virtual symbols for login.defs compatibility (bsc#1121197). +* Wed Jan 23 2019 adam.majer@suse.de +- btrfs-subvolumes.patch: implement support for creating user home + directories on btrfs subvolumes (fate#316134) +* Wed Oct 31 2018 vrothberg@suse.com +- Add empty /etc/sub{u,g}id files. useradd and usermod add entries for users + only when those files exist. Having those entries is a requirement to create + user namespaces, for instance, when running podman as a non-root user. +* Mon May 14 2018 mvetter@suse.com +- Update to 4.6: + * Newgrp: avoid unnecessary lookups + * Make language less binary + * Add error when turning off man switch + * Spelling fixes + * Make userdel work with -R + * newgidmap: enforce setgroups=deny if self-mapping a group + * Norwegian bokmål translation + * pwck: prevent crash by not passing O_CREAT + * WITH_TCB fixes from Mandriva + * Fix pwconv and grpconv entry skips + * Fix -- slurping in su + * add --prefix option +- Remove CVE-2018-7169.patch: upstreamed +- Remove shadow-4.1.5.1-pam_group.patch: upstreamed +- Update userdel-script.patch: change due to prefix +- Update useradd-mkdirs.patch: change due to prefix + Additionally changed in that patch (bsc#1106914): + * Test for strdup() failure + * Directory to 0755 instead 0777 +- Add shadow-4.6.0-fix-usermod-prefix-crash.patch: + Fixes crash in usermod when called with --prefix. + See https://github.com/shadow-maint/shadow/issues/110 +* Thu Feb 22 2018 fvogt@suse.com +- Use %%license (boo#1082318) +* Fri Feb 16 2018 kbabioch@suse.com +- Added CVE-2018-7169.patch: Fixed an privilege escalation in newgidmap, + which allowed an unprivileged user to be placed in a user namespace where + setgroups(2) is allowed. (CVE-2018-7169 bsc#1081294) +* Wed Nov 8 2017 mvetter@suse.com +- bsc#1061838: + Revert: Requires: group(mail) + Introduced circular dependency +* Fri Oct 13 2017 adam.majer@suse.de +- Revert accidentalied prerequisites. + Use PreReq for permissions +* Thu Oct 12 2017 schwab@suse.de +- Prequire group(shadow), group(root), user(root) +* Mon Oct 9 2017 mvetter@suse.com +- bsc#1061838: + Add Requires for group(mail) +* Thu Sep 14 2017 mvetter@suse.com +- boo#1048645: + Set suid bit for newuidmap and newgimap +* Thu Sep 14 2017 mvetter@suse.com +- Revert the changes for bsc#1023895 back + Pulls in too many deps into ring0. + Next version of shadow plans to have no conditional man pages. +* Fri Sep 8 2017 mvetter@suse.com +- run spec-cleaner +- bsc#1023895: + man page contained invalid options because they depend + on compile flags and we shipped pre built ones. + New BuildRequires: docbook-xsl-stylesheets docbook_4 xml2po + xsltproc +* Thu Jun 8 2017 kukuk@suse.de +- Adjust requires (we need user/group root instead of aaa_base now) +* Mon May 22 2017 adam.majer@suse.de +- New upstream version 4.5 +- Refreshed patches: + * shadow-login_defs.patch + * chkname-regex.patch + * getdef-new-defs.patch + * useradd-mkdirs.patch +- Upstreamed patches: + * shadow-4.1.5.1-manfix.patch + * shadow-4.1.5.1-errmsg.patch + * shadow-4.1.5.1-backup-mode.patch + * shadow-4.1.5.1-audit-owner.patch + * shadow-4.2.1-defs-chroot.patch + * shadow-4.2.1-merge-group.patch + * Fix-user-busy-errors-at-userdel.patch + * useradd-clear-tallylog.patch +- shadow-4.1.5.1-pam_group.patch + dynamically added users via pam_group are not listed in groups + databases but are still valid +- shadow.keyring: update keyring with current maintainer's keyid + only - Serge Hallyn 'F1D08DB778185BF784002DFFE9FEEA06A85E3F9D' +- disable_new_audit_function.patch: + Disable newer libaudit functionality for older distributions +* Mon Feb 20 2017 josef.moellers@suse.com +- useradd: call external program "/sbin/pam_tally2" to reset + failed login counter in "/var/log/tallylog" + (bsc#980486, useradd-clear-tallylog.patch) +* Wed Nov 2 2016 meissner@suse.com +- add keyring, three public keys from https://pkg-shadow.alioth.debian.org/download.php +* Tue Oct 18 2016 mvetter@suse.com +- bsc#1002975: Use permissions according to permissions package + and dont try to manipulate them in %%files section. +* Wed Sep 14 2016 mvetter@suse.com +- boo#994486: Include shadow.5 manpage + Previously this was provided by man-pages package in + the man-pages-addons tarball which got removed later on. +* Tue May 31 2016 mvetter@suse.com +- Add package dependency for aaa_base, fixing bnc#899409 + (was done by tbehrens@suse.com but not submitted to Factory) +* Mon May 30 2016 mvetter@suse.com +- shadow 4.2.1 requested by fate#320422 +- bsc#979069: Dont include shadow-4.1.5.1-bug935203-manpage.patch +- Dont set SUID bit yet. Once bsc#979282 is through, which will adapt the permissions package, we can enable the SUID bits. + Remove the files used to circumvent the check. +- Remove: + * shadow-rpmlintrc + * shadow-subids + * shadow-subids.easy + * shadow-subids.secure + * shadow-subids.paranoid +* Thu May 19 2016 christian.brauner@mailbox.org +- Update to shadow-4.2.1: + - add support for subuids/subgids via newuidmap/newgidmap +- Rename chkname-regex.diff to chkname-regex.patch +- Rename encryption_method_nis.diff to encryption_method_nis.patch +- Rename getdef-new-defs.diff to getdef-new-defs.patch +- Rename shadow-login_defs.diff to shadow-login_defs.patch +- Rename userdel-scripts.diff to userdel-script.patch +- Rename useradd-script.diff to useradd-script.patch +- Rename useradd-default.diff to useradd-default.patch +- Rename useradd-mkdirs.diff to useradd-mkdirs.patch +- Add fixes from Red Hat/Fedora: + - shadow-4.1.5.1-audit-owner.patch.patch: + - log owner changes for home directory + - shadow-4.1.5.1-userdel-helpfix.patch.patch: + - give a hint about what happens when you force the removal of a user + - shadow-4.2.1-defs-chroot.patch.patch: + - initialize uid_t uid_min and uid_t uid_max not before we need them + - shadow-4.2.1-merge-group.patch.patch: + - simplify by using a single call to snprintf() +- Add upstream fix + - Fix-user-busy-errors-at-userdel.patch: + - call sub_uid_close() +* Fri Jan 15 2016 fvogt@suse.com +- Moved call from %%verifyscript into %%post: + * Caused call to %%service_add_post shadow.service shadow.timer + during rpm -qV shadow +* Wed Jul 15 2015 jkeil@suse.de +- Add systemd unit files to continuously check password & groupfile integrity + * Idea from Arch Linux + * pending request to systemd-presets-branding-openSUSE to enable by default +* Mon Mar 31 2014 tbehrens@suse.com +- Add patch useradd-mkdirs.diff: fix for bnc#865563, create all parts + of the path +* Fri Nov 22 2013 werner@suse.de +- Stop any systemd user manager instance in case a user entry will + be deleted (bnc#849870). Nevertheless a running process requires + the option --force for the userdel command. +* Tue Nov 12 2013 kukuk@suse.de +- Add ENCRYPT_METHOD_NIS for pam_unix.so (encryption_method_nis.diff) +* Tue Sep 17 2013 kukuk@suse.de +- Add some fixes from Fedora: + - shadow-4.1.5.1-backup-mode.patch: open backup file with correct + permissions. + - shadow-4.1.5.1-logmsg.patch: fix error message + - shadow-4.1.5.1-errmsg.patch: print error reason + - shadow-4.1.5.1-manfix.patch: fix manual page +* Tue Feb 5 2013 kukuk@suse.de +- Cleanup login.defs and enable ENCRYPT_METHOD [bnc#802006] +* Tue Nov 13 2012 kukuk@suse.de +- Fix getdef default variables (getdef-new-defs.diff) +* Tue Nov 13 2012 kukuk@suse.de +- Fix default group value in /etc/default/useradd + (useradd-default.diff) +* Thu Sep 27 2012 kukuk@suse.de +- Implement CHARACTER_CLASS support + (chkname-regex.diff) +* Wed Sep 26 2012 kukuk@suse.de +- Add support for useradd.local + (useradd-script.diff) +* Tue Sep 25 2012 kukuk@suse.de +- Fix spec file +- Adjust login.defs + (shadow-login_defs.diff) +- Add userdel*.local script support and scrips + (userdel-scripts.diff) +* Mon Sep 24 2012 kukuk@suse.de +- Initial package [FATE#314473] diff --git a/shadow.keyring b/shadow.keyring new file mode 100644 index 0000000..86eb922 --- /dev/null +++ b/shadow.keyring @@ -0,0 +1,54 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2 + +mQENBEwNOlIBCAC3QrrJj77hRME8JMMrH7tQlakvpw6ycn8VHle509z0w1q5Elld +fwTPNdbczSiC4xo80G639kWqC3lV9qV/iM/1QQQMFH4QvqkYoLgw9lj4u7S5Wc/9 +i2E6y7zbjNOUsBLY1wvhhjaD6jixURkTKgfxx2JVUBtqU5EyMqlabDEn3zt1xCDl +ami0kJxFAQz/03/aSOZ01KwuPSvxcnn01uWvE7co8hsSWwVaZ6ADt8nuT2kSCi4P +AI1IzVVn3d02qTjk1t1KCcGvnOOtOMpFcZ38lmh+XMnrK8zlLXwisnAy0BnYXzWx +Z4jG62KaEP4Lz9ez5jZLOXlPNxyrqmJ/5ICdABEBAAG0JlNlcmdlIEhhbGx5biA8 +c2VyZ2UuaGFsbHluQHVidW50dS5jb20+iQEcBBABAgAGBQJNMM+FAAoJEFOMB2b0 +vLOOW/EH/j/svOOPWcBnyt+UZ7p7HAwV8NhUgFz53t81Oubg8NWrYBo0hnqgQtAn +YXo9e42AD635qRDKFUbIhYRBGxwBbTYhXIhBfy0XHzqbpGDUGMt9cGEX77oQ+XH5 +6AeEMAqnDsJ/QAa0shkAix6p2/LUkahjoizG55SDpja+JfTjhmvd7dVG2AukzVtS +y2oOrWQMle+I97xqX9Bm/hJ6vjkEaerlB/z10oc68Wx7CtcqBmk1930SqbZXNRGw +4Rkwmgx9fB8rzRvohoqcerJF9iqqoXIB5/15+KuKNw/yewmIM1J1zgfoqPhWMqpp +XvmIZsFeMXPp0JfhT6X4XL7hCGlAGhWJARwEEAECAAYFAk0w0RcACgkQnK/PEVZ0 +b5Wa5gf/Snv2UY9WtnNIAVR9KReRi3sSEUCBaVNAyzka6+3RxR7ST9D6Owise+6D +h5SmDe79hwW2P2ibSxD5X5uIwmeKXxlI/jrJcRa5XBEmvEpxFyOZEXul8b8U8cqC +aUpgMYQG54KR27xnFwGPlu8Fi4Mv1rFm6f9iYvX8QU6D21aHqRd3VfSpbIdju8Xo +N7+egr31mO2slZYM+FeRve35VQSjEqPYZUW0C6y84l0rJex/2s5D/v069nFQpk/2 +Monw4F1oFHH+12AlDvtLqjzo1MnS0M9DaNvkWIf2QSilXiK0GIRSjedNCVXFUFys +8B8voHOD+ocNlpIeqG4n9wUoHlJ9WYkBOAQTAQIAIgUCTA06UgIbAwYLCQgHAwIG +FQgCCQoLBBYCAwECHgECF4AACgkQ6f7qBqheP53lFQgAnD/IgTPEqWaavxakJ8kK +u2acaCVIrSxk2LFUpwrdsEcCFfqSQPSqev2fDFO75NTJbgTd3B7YrLh81HkefS9n +kcbjGvX2MKCsqE/o7reRI2vPpJdGrrMhTDlXKBnbApIrxzEQ1l+zLrtUMqKTvBx1 +qSHk6SA+mDaXkI/sppwf6uMvkpXnZ8TlCXpLmNaCfzOWTTdneV3CguROGoqYi7Nm +nUQmzFoFGuuI2Iw7dyodV1HActDs0B4hvZI7RF3ePOAv3wtWlMv0mOIaXO68B8Kw +d3DN1WsuouwFb/BAe8DtJTGGv1ymehCi7ycKhdxSlWaO3UxJOoE6RHP4abG1lkPB +aokCHAQQAQIABgUCTTDebAAKCRAeRBCkAkvG8GLaD/95DKcgzWJvbixoMDUpxZuv +uDvRFJPG3V7edxlJoHbh+kA9+ly9PmPtjoEkrsiYHoDEU+Di+CTc4C866DV+1PkZ +YXGFsLX4ZmCBkvXRmjlmIr3EljPORgTkv7UgP1GotqPDqvPl0jsFC8BBdexPLQoQ +PYFc6Loc5qvRrotpTGbPrNQOQTi8v4XiZqnMrLXuBBKstHrrbHCDgN2Je62e5VlO +Wu0AfmCFJQPq/7CVRzV25d9861RZCXvHZAptCrBi6k8q8tmRyNjtRkgPFR8TcqCp +YHjm38okuV+aSaLbcFeMii4bIgKPLcVl761DD6T/MAU69AwLHZUqYYGGLnUKfnSF +Iddfeww516FqozM93IaeWeGz2jazoMOHDYHKVxcCgfI4gc6W0yPiGKJtA75wuyII +B2tH+g5mAj7z12+2c/VRybow87zfgg/y/7Od3oOV51yIP9Z/L9EIwu72RIoMTkGL +v+dYJX6qj4ub3jJbWwqpsepCdDvdRmlpzw3vi6LMQyeRfU4QZTSdFxfJqrSPgPVx +uJ9AMNr6odss4yRVputGVnHBm+GTmeMbkW566pfkvlmq0vapdEr/mpnM5lfWGJgx +VrCsthj7cs/tMHhBaJtB2ZicN1wj805qCrY+KyLjGr/wSk4yqGoSTZsPeIm0tyP1 +PiwY0RBQz07o5SovXEGNYbkBDQRMDTpSAQgAncegUtRmavfq6bMY36Oab+I4vtD5 +nQ3mJXQZXV0tX6cyu3kUpEsUXpuOojFYtDofvJvqoo0tT6jBkJCmP1J3FSraHi3R +En6DQs3sig54/JBNzWN/Ax4w04ADy7VYRD37dUDtxIMqbsEi1Oack1USctQXrPZK +SiQ6yH+x3xCuym7jOymnyCpB734fwH0F98sEHTRiPDkhPZlV6jiRCDQYi7zXEpyL +vQLRj0v1ecd8tssUbqyv46fikH+7op3K2zljoeAxbRXqLmcCvpQQaZ3CUHbIcYQK +MviJkGImTDZnEXOc+DHIHJJsiv8oZlsUZuRXexwBAvqsfEGX30kxvuvAzwARAQAB +iQEfBBgBAgAJBQJMDTpSAhsMAAoJEOn+6gaoXj+dKxAH/1mYuXihJx0ctq2p48rZ +fQsGpqE+HdnHTFqTVNK5cV5lxTxRmuZw0BMgHAoATlgHP7KvAaa78MfccNLsypJ0 +FxC2/dtK1YlemC9udJJKGw/3C/AwneMigxK+R2bSHvpXQdEVBAld+KPYYuYyublw +Ex/N0RPE1WfVYahh5bbbcViP4Bwto3lpYcRVKdhvSKj1yv0vQ3O4GZAziYru+Uj2 +mpDQWsfOi3ErpJ/lhs8I+T3w+FGuA5CYJiXn4cQldYdbLGil/XSXvM8N8rp08bLr +RU6E+xm2a5LP9MSoym0YwPlriklWbteagYE9EvlrWG0Xyt77SkfegZdDKW0W0BKB +Fj0= +=YE9s +-----END PGP PUBLIC KEY BLOCK----- diff --git a/shadow.service b/shadow.service new file mode 100644 index 0000000..b9e08ad --- /dev/null +++ b/shadow.service @@ -0,0 +1,10 @@ +[Unit] +Description=Verify integrity of password and group files + +[Service] +Type=oneshot +ExecStart=/usr/sbin/pwck -r +ExecStart=/usr/sbin/grpck -r +Nice=19 +IOSchedulingClass=best-effort +IOSchedulingPriority=7 diff --git a/shadow.spec b/shadow.spec new file mode 100644 index 0000000..25c3b78 --- /dev/null +++ b/shadow.spec @@ -0,0 +1,385 @@ +# +# spec file for package shadow +# +# Copyright (c) 2022-2023 ZhuningOS +# + + +%if ! %{defined _distconfdir} + %define _distconfdir %{_sysconfdir} +%else + %define no_config 1 +%endif + +Name: shadow +Version: 4.8.1 +Release: 150400.10.9.1 +Summary: Utilities to Manage User and Group Accounts +License: BSD-3-Clause AND GPL-2.0-or-later +Group: System/Base +URL: https://github.com/shadow-maint/shadow +Source: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz +Source1: pamd.tar.bz2 +Source2: README.changes-pwdutils +Source3: useradd.local +Source4: userdel-pre.local +Source5: userdel-post.local +Source6: shadow.service +Source7: shadow.timer +Source42: https://github.com/shadow-maint/shadow/releases/download/%{version}/shadow-%{version}.tar.xz.asc +Source43: %{name}.keyring +# SOURCE-FEATURE-SUSE shadow-login_defs-check.sh sbrabec@suse.com -- Supplementary script that verifies coverage of variables in shadow-login_defs-unused-by-pam.patch and other patches. +Source44: shadow-login_defs-check.sh +# PATCH-FIX-SUSE shadow-login_defs-unused-by-pam.patch kukuk@suse.com -- Remove variables that have no use with PAM. +Patch0: shadow-login_defs-unused-by-pam.patch +# PATCH-FEATURE-SUSE userdel-script.patch kukuk@suse.com -- Add support for USERDEL_PRECMD and USERDEL_POSTCMD. +Patch1: userdel-script.patch +# PATCH-FEATURE-SUSE useradd-script.patch kukuk@suse.com -- Add support for USERADD_CMD. +Patch2: useradd-script.patch +# PATCH-FEATURE-SUSE chkname-regex.patch kukuk@suse.com -- Username restriction by regex. +Patch3: chkname-regex.patch +# PATCH-FEATURE-SUSE useradd-default.patch kukuk@suse.com -- Change useradd defaults group to 1000. +Patch4: useradd-default.patch +# PATCH-FEATURE-SUSE shadow-util-linux.patch sbrabec@suse.com -- Add support for util-linux specific variables, delete shadow login, su runuser specific. +Patch5: shadow-util-linux.patch +# PATCH-FEATURE-FEDORA shadow-4.1.5.1-userdel-helpfix.patch christian.brauner@mailbox.org -- Give a hint about what happens when you force the removal of a user. +Patch6: shadow-4.1.5.1-userdel-helpfix.patch +# PATCH-FIX-FEDORA shadow-4.1.5.1-logmsg.patch kukuk@suse.com -- Fix error message. +Patch7: shadow-4.1.5.1-logmsg.patch +# PATCH-FEATURE-SUSE shadow-login_defs-comments.patch kukuk@suse.com -- Adjust login.defs comments. +Patch13: shadow-login_defs-comments.patch +# PATCH-FEATURE-SUSE shadow-login_defs-suse.patch kukuk@suse.com -- Customize login.defs. +Patch14: shadow-login_defs-suse.patch +# PATCH-FEATURE-SUSE Copy also skeleton files from /usr/etc/skel (boo#1173321) +Patch15: useradd-userkeleton.patch +# PATCH-FIX-SUSE useradd audit event user id field cannot be interpreted (boo#1205502) +Patch16: shadow-4.8.1-AUDIT_NO_ID.patch +# PATCH-FIX-SUSE disable_new_audit_function.patch adam.majer@suse.de -- Disable newer libaudit functionality for older distributions. +Patch20: disable_new_audit_function.patch +Patch21: shadow-CVE-2023-29383.patch +# PATCH-FEATURE-UPSTREAM mvetter@suse.com -- Add --prefix support to passwd, chpasswd, chage (bsc#1206627) +Patch22: shadow-4.8.1-add-prefix-passwd-chpasswd-chage.patch +# PATCH-FIX-UPSTREAM mvetter@suse.com -- Change lock mechanism to file locking (bsc#1213189) +Patch23: shadow-4.8.1-lock-mechanism.patch +BuildRequires: audit-devel > 2.3 +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: libacl-devel +BuildRequires: libattr-devel +BuildRequires: libeconf-devel +BuildRequires: libselinux-devel +BuildRequires: libsemanage-devel +BuildRequires: libtool +BuildRequires: pam-devel +BuildRequires: xz +Requires(pre): group(root) +Requires(pre): group(shadow) +Requires(pre): permissions +Requires(pre): user(root) +Provides: pwdutils = 3.2.20 +Obsoletes: pwdutils <= 3.2.19 +Requires: login_defs >= %{version} +Provides: useradd_or_adduser_dep + +%description +This package includes the necessary programs for converting plain +password files to the shadow password format and to manage user and +group accounts. + +%package -n login_defs +Summary: login.defs configuration file +Group: System/Base +BuildArch: noarch +# Virtual provides for supported variables in login.defs. +# It prevents references to unknown variables. +# Upgrade them only if shadow-util-linux.patch or +# encryption_method_nis.patch has to be ported! +# Call shadow-login_defs-check.sh before! +Provides: login_defs-support-for-pam = 1.3.1 +Provides: login_defs-support-for-util-linux = 2.37 + +%description -n login_defs +This package contains the default login.defs configuration file +as used by util-linux, pam and shadow. + +%prep +%setup -q -a 1 +%patch0 +%patch1 +%patch2 +%patch3 +%patch4 +%patch5 +%patch6 +%patch7 +%patch13 +%patch14 +%patch15 +%patch16 -p1 +%if 0%{?suse_version} < 1330 +%patch20 -p1 +%endif +%patch21 -p1 +%patch22 -p1 +%patch23 -p1 + +iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8 +mv -v doc/HOWTO.utf8 doc/HOWTO + +%build +export CFLAGS="%{optflags} -fpie" +export LDFLAGS="-pie" + +autoreconf -fvi +%configure \ + --disable-shadowgrp \ + --enable-account-tools-setuid \ + --with-audit \ + --with-libpam \ + --with-sha-crypt \ + --with-acl \ + --with-attr \ + --with-nscd \ + --with-selinux \ + --without-libcrack \ + --disable-shared \ + --with-group-name-max-length=32 \ + --enable-vendordir=%{_distconfdir} +make %{?_smp_mflags} V=1 + +%install +cp %{SOURCE2} . +%make_install gnulocaledir=%{buildroot}/%{_datadir}/locale MKINSTALLDIRS=`pwd`/mkinstalldirs + +# install useradd.local, userdel.local, ... +install -m 0755 %{SOURCE3} %{buildroot}/%{_sbindir}/ +install -m 0755 %{SOURCE4} %{buildroot}/%{_sbindir}/ +install -m 0755 %{SOURCE5} %{buildroot}/%{_sbindir}/ +install -Dm644 %{SOURCE6} %{buildroot}%{_unitdir}/shadow.service +install -Dm644 %{SOURCE7} %{buildroot}%{_unitdir}/shadow.timer + +# add empty /etc/sub{u,g}id files +touch %{buildroot}/%{_sysconfdir}/subuid +touch %{buildroot}/%{_sysconfdir}/subgid + +# Remove binaries we don't use. +rm %{buildroot}/%{_bindir}/groups +rm %{buildroot}/%{_mandir}/man1/groups.* +rm %{buildroot}/%{_mandir}/*/man1/groups.* + +rm %{buildroot}/%{_sbindir}/grpconv +rm %{buildroot}/%{_mandir}/man8/grpconv.* +rm %{buildroot}/%{_mandir}/*/man8/grpconv.* +rm %{buildroot}/%{_sbindir}/grpunconv +rm %{buildroot}/%{_mandir}/man8/grpunconv.* +rm %{buildroot}/%{_mandir}/*/man8/grpunconv.* + +rm %{buildroot}/%{_sbindir}/groupmems +rm %{buildroot}/%{_mandir}/man8/groupmems.* +rm %{buildroot}/%{_mandir}/*/man8/groupmems.* +rm %{buildroot}%{_sysconfdir}/pam.d/groupmems + +rm %{buildroot}/%{_bindir}/login +rm %{buildroot}/%{_mandir}/man1/login.* +rm %{buildroot}/%{_mandir}/*/man1/login.* +rm %{buildroot}%{_sysconfdir}/pam.d/login + +rm %{buildroot}/%{_bindir}/su +rm %{buildroot}/%{_mandir}/man1/su.* +rm %{buildroot}/%{_mandir}/*/man1/su.* +rm %{buildroot}/%{_mandir}/man5/suauth.* +rm %{buildroot}/%{_mandir}/*/man5/suauth.* +rm %{buildroot}%{_sysconfdir}/pam.d/su + +rm %{buildroot}/%{_bindir}/faillog +rm %{buildroot}/%{_mandir}/man5/faillog.* +rm %{buildroot}/%{_mandir}/*/man5/faillog.* +rm %{buildroot}/%{_mandir}/man8/faillog.* +rm %{buildroot}/%{_mandir}/*/man8/faillog.* + +rm %{buildroot}/%{_sbindir}/logoutd +rm %{buildroot}/%{_mandir}/man8/logoutd.* +rm %{buildroot}/%{_mandir}/*/man8/logoutd.* +rm %{buildroot}/%{_sbindir}/nologin +rm %{buildroot}/%{_mandir}/man8/nologin.* +rm %{buildroot}/%{_mandir}/*/man8/nologin.* + +rm %{buildroot}/%{_sbindir}/chgpasswd +rm %{buildroot}/%{_mandir}/man8/chgpasswd.* +rm %{buildroot}/%{_mandir}/*/man8/chgpasswd.* +rm %{buildroot}%{_sysconfdir}/pam.d/chgpasswd + +rm %{buildroot}/%{_mandir}/man3/getspnam.* +rm %{buildroot}/%{_mandir}/*/man3/getspnam.* +rm %{buildroot}/%{_mandir}/man5/gshadow.5* +rm %{buildroot}/%{_mandir}/*/man5/gshadow.5* +rm %{buildroot}/%{_mandir}/man5/passwd.5* +rm %{buildroot}/%{_mandir}/*/man5/passwd.5* + +rm -rf %{buildroot}%{_mandir}/{??,??_??} + +# Move /etc to /usr/etc +if [ ! -d %{buildroot}%{_distconfdir} ]; then + mkdir -p %{buildroot}%{_distconfdir} + mv %{buildroot}%{_sysconfdir}/{login.defs,pam.d} %{buildroot}%{_distconfdir} +fi + +%find_lang shadow + +%pre +%service_add_pre shadow.service shadow.timer +for i in pam.d/chage pam.d/chfn pam.d/chpasswd pam.d/chsh pam.d/groupadd pam.d/groupdel pam.d/groupmod pam.d/newusers pam.d/passwd pam.d/useradd pam.d/userdel pam.d/usermod; do + test -f /etc/${i}.rpmsave && mv -v /etc/${i}.rpmsave /etc/${i}.rpmsave.old ||: +done + +%pre -n login_defs +test -f /etc/login.defs.rpmsave && mv -v /etc/login.defs.rpmsave /etc/login.defs.rpmsave.old ||: + +%post +%set_permissions %{_bindir}/chage +%set_permissions %{_bindir}/chfn +%set_permissions %{_bindir}/chsh +%set_permissions %{_bindir}/expiry +%set_permissions %{_bindir}/gpasswd +%set_permissions %{_bindir}/newgrp +%set_permissions %{_bindir}/passwd +%set_permissions %{_bindir}/newgidmap +%set_permissions %{_bindir}/newuidmap + +%service_add_post shadow.service shadow.timer + +%verifyscript +%verify_permissions %{_bindir}/chage +%verify_permissions %{_bindir}/chfn +%verify_permissions %{_bindir}/chsh +%verify_permissions %{_bindir}/expiry +%verify_permissions %{_bindir}/gpasswd +%verify_permissions %{_bindir}/newgrp +%verify_permissions %{_bindir}/passwd +%verify_permissions %{_bindir}/newgidmap +%verify_permissions %{_bindir}/newuidmap + +%preun +%service_del_preun shadow.service shadow.timer + +%postun +%service_del_postun shadow.service shadow.timer + +%posttrans +%if %{defined no_config} +# Migration to /usr/etc +for i in pam.d/chage pam.d/chfn pam.d/chpasswd pam.d/chsh pam.d/groupadd pam.d/groupdel pam.d/groupmod pam.d/newusers pam.d/passwd pam.d/useradd pam.d/userdel pam.d/usermod; do + test -f /etc/${i}.rpmsave && mv -v /etc/${i}.rpmsave /etc/${i} ||: +done +%endif + +%posttrans -n login_defs +# rpmsave file can be created by +# - change of owning package (SLE15 SP2->SP3, Leap 15.2->15.3) +# - Migration to /usr/etc (after SLE15 and Leap 15) +test -f /etc/login.defs.rpmsave && mv -v /etc/login.defs.rpmsave /etc/login.defs ||: + +%files -f shadow.lang +%license COPYING +%doc NEWS doc/HOWTO README README.changes-pwdutils +%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/default/useradd +%verify(not md5 size mtime) %config(noreplace) %{_sysconfdir}/subuid +%verify(not md5 size mtime) %config(noreplace) %{_sysconfdir}/subgid +%if %{defined no_config} +%{_distconfdir}/pam.d/chage +%{_distconfdir}/pam.d/chfn +%{_distconfdir}/pam.d/chsh +%{_distconfdir}/pam.d/passwd +%{_distconfdir}/pam.d/useradd +%{_distconfdir}/pam.d/chpasswd +%{_distconfdir}/pam.d/groupadd +%{_distconfdir}/pam.d/groupdel +%{_distconfdir}/pam.d/groupmod +%{_distconfdir}/pam.d/newusers +%{_distconfdir}/pam.d/useradd +%{_distconfdir}/pam.d/userdel +%{_distconfdir}/pam.d/usermod +%else +%config %{_sysconfdir}/pam.d/chage +%config %{_sysconfdir}/pam.d/chfn +%config %{_sysconfdir}/pam.d/chsh +%config %{_sysconfdir}/pam.d/passwd +%config %{_sysconfdir}/pam.d/useradd +%config %{_sysconfdir}/pam.d/chpasswd +%config %{_sysconfdir}/pam.d/groupadd +%config %{_sysconfdir}/pam.d/groupdel +%config %{_sysconfdir}/pam.d/groupmod +%config %{_sysconfdir}/pam.d/newusers +%config %{_sysconfdir}/pam.d/useradd +%config %{_sysconfdir}/pam.d/userdel +%config %{_sysconfdir}/pam.d/usermod +%endif +%verify(not mode) %attr(2755,root,shadow) %{_bindir}/chage +%verify(not mode) %attr(4755,root,shadow) %{_bindir}/chfn +%verify(not mode) %attr(4755,root,shadow) %{_bindir}/chsh +%verify(not mode) %attr(4755,root,shadow) %{_bindir}/expiry +%verify(not mode) %attr(4755,root,shadow) %{_bindir}/gpasswd +%verify(not mode) %attr(4755,root,root) %{_bindir}/newgrp +%verify(not mode) %attr(4755,root,shadow) %{_bindir}/passwd +%verify(not mode) %attr(4755,root,shadow) %{_bindir}/newgidmap +%verify(not mode) %attr(4755,root,shadow) %{_bindir}/newuidmap +%{_bindir}/lastlog +%{_bindir}/sg +%attr(0755,root,root) %{_sbindir}/groupadd +%attr(0755,root,root) %{_sbindir}/groupdel +%attr(0755,root,root) %{_sbindir}/groupmod +%{_sbindir}/grpck +%{_sbindir}/pwck +%attr(0755,root,root) %{_sbindir}/useradd +%attr(0755,root,root) %{_sbindir}/userdel +%attr(0755,root,root) %{_sbindir}/usermod +%{_sbindir}/pwconv +%{_sbindir}/pwunconv +%attr(0755,root,root) %{_sbindir}/chpasswd +%attr(0755,root,root) %{_sbindir}/newusers +%{_sbindir}/vipw +%{_sbindir}/vigr +%verify(not md5 size mtime) %config(noreplace) %{_sbindir}/useradd.local +%verify(not md5 size mtime) %config(noreplace) %{_sbindir}/userdel-pre.local +%verify(not md5 size mtime) %config(noreplace) %{_sbindir}/userdel-post.local +%{_mandir}/man1/chage.1%{?ext_man} +%{_mandir}/man1/chfn.1%{?ext_man} +%{_mandir}/man1/chsh.1%{?ext_man} +%{_mandir}/man1/expiry.1%{?ext_man} +%{_mandir}/man1/gpasswd.1%{?ext_man} +%{_mandir}/man1/newgrp.1%{?ext_man} +%{_mandir}/man1/passwd.1%{?ext_man} +%{_mandir}/man1/sg.1%{?ext_man} +%{_mandir}/man3/shadow.3%{?ext_man} +%{_mandir}/man5/shadow.5%{?ext_man} +%{_mandir}/man8/chpasswd.8%{?ext_man} +%{_mandir}/man8/groupadd.8%{?ext_man} +%{_mandir}/man8/groupdel.8%{?ext_man} +%{_mandir}/man8/groupmod.8%{?ext_man} +%{_mandir}/man8/grpck.8%{?ext_man} +%{_mandir}/man8/lastlog.8%{?ext_man} +%{_mandir}/man8/newusers.8%{?ext_man} +%{_mandir}/man8/pwck.8%{?ext_man} +%{_mandir}/man8/pwconv.8%{?ext_man} +%{_mandir}/man8/pwunconv.8%{?ext_man} +%{_mandir}/man8/useradd.8%{?ext_man} +%{_mandir}/man8/userdel.8%{?ext_man} +%{_mandir}/man8/usermod.8%{?ext_man} +%{_mandir}/man8/vigr.8%{?ext_man} +%{_mandir}/man8/vipw.8%{?ext_man} +%{_mandir}/man5/subuid.5%{?ext_man} +%{_mandir}/man5/subgid.5%{?ext_man} +%{_mandir}/man1/newgidmap.1%{?ext_man} +%{_mandir}/man1/newuidmap.1%{?ext_man} + +%{_unitdir}/* + +%files -n login_defs +%if %{defined no_config} +%attr(0644,root,root) %{_distconfdir}/login.defs +%else +%attr(0644,root,root) %config %{_sysconfdir}/login.defs +%endif +%{_mandir}/man5/login.defs.5%{?ext_man} + +%changelog diff --git a/shadow.timer b/shadow.timer new file mode 100644 index 0000000..9cc6baa --- /dev/null +++ b/shadow.timer @@ -0,0 +1,7 @@ +[Unit] +Description=Daily verification of password and group files + +[Timer] +OnCalendar=daily +AccuracySec=12h +Persistent=true diff --git a/useradd-default.patch b/useradd-default.patch new file mode 100644 index 0000000..b313edf --- /dev/null +++ b/useradd-default.patch @@ -0,0 +1,9 @@ +--- etc/useradd ++++ etc/useradd +@@ -1,5 +1,5 @@ + # useradd defaults file +-GROUP=1000 ++GROUP=100 + HOME=/home + INACTIVE=-1 + EXPIRE= diff --git a/useradd-script.patch b/useradd-script.patch new file mode 100644 index 0000000..c1a1bce --- /dev/null +++ b/useradd-script.patch @@ -0,0 +1,88 @@ +--- + etc/login.defs | 7 +++++++ + lib/getdef.c | 1 + + src/useradd.c | 41 ++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 48 insertions(+), 1 deletion(-) + +--- etc/login.defs ++++ etc/login.defs 2020-10-30 12:54:38.117849829 +0000 +@@ -242,6 +242,13 @@ CHFN_RESTRICT rwh + DEFAULT_HOME yes + + # ++# If defined, this command is run when adding a user. ++# It should rebuild any NIS database etc. to add the ++# new created account. ++# ++USERADD_CMD /usr/sbin/useradd.local ++ ++# + # If defined, this command is run when removing a user. + # It should remove any at/cron/print jobs etc. owned by + # the user to be removed (passed as the first argument). +--- lib/getdef.c ++++ lib/getdef.c 2020-10-30 12:54:38.117849829 +0000 +@@ -134,6 +134,7 @@ static struct itemdef def_table[] = { + {"UID_MAX", NULL}, + {"UID_MIN", NULL}, + {"UMASK", NULL}, ++ {"USERADD_CMD", NULL}, + {"USERDEL_CMD", NULL}, + {"USERDEL_PRECMD", NULL}, + {"USERDEL_POSTCMD", NULL}, +--- src/useradd.c ++++ src/useradd.c 2020-10-30 13:08:17.378336989 +0000 +@@ -2238,6 +2238,44 @@ static void create_mail (void) + } + + /* ++ * call_script - call a script to do some work ++ * ++ * call_script calls a script for additional changes to the ++ * account. ++ */ ++ ++static void call_script (const char *user, const uid_t uid, const gid_t gid, const char *home) ++{ ++ const char *cmd; ++ const char *argv[6]; ++ char *strgid, *struid; ++ int status; ++ ++ cmd = getdef_str ("USERADD_CMD"); ++ if (NULL == cmd) { ++ return; ++ } ++ if (asprintf(&struid, "%lu", (long unsigned)uid) < 0) { ++ (void) fprintf (stderr, _("%s: out of memory\n"), Prog); ++ exit(1); ++ } ++ if (asprintf(&strgid, "%lu", (long unsigned)gid) < 0) { ++ (void) fprintf (stderr, _("%s: out of memory\n"), Prog); ++ exit(1); ++ } ++ argv[0] = cmd; ++ argv[1] = user; ++ argv[2] = struid; ++ argv[3] = strgid; ++ argv[4] = home; ++ argv[5] = (char *)0; ++ (void) run_command (cmd, argv, NULL, &status); ++ free(strgid); ++ free(struid); ++} ++ ++ ++/* + * main - useradd command + */ + int main (int argc, char **argv) +@@ -2514,6 +2552,7 @@ int main (int argc, char **argv) + nscd_flush_cache ("group"); + sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); + ++ call_script (user_name, user_id, user_gid, user_home); ++ + return E_SUCCESS; + } +- diff --git a/useradd-userkeleton.patch b/useradd-userkeleton.patch new file mode 100644 index 0000000..1226119 --- /dev/null +++ b/useradd-userkeleton.patch @@ -0,0 +1,165 @@ +Copy also skeleton files from /usr/etc/skel (boo#1173321) + +--- + etc/useradd | 1 + + src/useradd.c | 37 +++++++++++++++++++++++++++++++++++++ + 2 files changed, 38 insertions(+) + +Index: etc/useradd +=================================================================== +--- etc/useradd.orig ++++ etc/useradd +@@ -5,4 +5,5 @@ INACTIVE=-1 + EXPIRE= + SHELL=/bin/bash + SKEL=/etc/skel ++USRSKEL=/usr/etc/skel + CREATE_MAIL_SPOOL=yes +Index: src/useradd.c +=================================================================== +--- src/useradd.c.orig ++++ src/useradd.c +@@ -78,6 +78,9 @@ + #ifndef SKEL_DIR + #define SKEL_DIR "/etc/skel" + #endif ++#ifndef USRSKELDIR ++#define USRSKELDIR "/usr/etc/skel" ++#endif + #ifndef USER_DEFAULTS_FILE + #define USER_DEFAULTS_FILE "/etc/default/useradd" + #define NEW_USER_FILE "/etc/default/nuaddXXXXXX" +@@ -101,6 +104,7 @@ static const char *def_gname = "other"; + static const char *def_home = "/home"; + static const char *def_shell = ""; + static const char *def_template = SKEL_DIR; ++static const char *def_usrtemplate = USRSKELDIR; + static const char *def_create_mail_spool = "no"; + + static long def_inactive = -1; +@@ -202,6 +206,7 @@ static bool home_added = false; + #define DINACT "INACTIVE=" + #define DEXPIRE "EXPIRE=" + #define DSKEL "SKEL=" ++#define DUSRSKEL "USRSKEL=" + #define DCREATE_MAIL_SPOOL "CREATE_MAIL_SPOOL=" + + /* local function prototypes */ +@@ -469,6 +474,29 @@ static void get_defaults (void) + } + + /* ++ * Default Usr Skeleton information ++ */ ++ else if (MATCH (buf, DUSRSKEL)) { ++ if ('\0' == *cp) { ++ cp = USRSKELDIR; /* XXX warning: const */ ++ } ++ ++ if(prefix[0]) { ++ size_t len; ++ int wlen; ++ char* _def_usrtemplate; /* avoid const warning */ ++ ++ len = strlen(prefix) + strlen(cp) + 2; ++ _def_usrtemplate = xmalloc(len); ++ wlen = snprintf(_def_usrtemplate, len, "%s/%s", prefix, cp); ++ assert (wlen == (int) len -1); ++ def_usrtemplate = _def_usrtemplate; ++ } ++ else { ++ def_usrtemplate = xstrdup (cp); ++ } ++ } ++ /* + * Create by default user mail spool or not ? + */ + else if (MATCH (buf, DCREATE_MAIL_SPOOL)) { +@@ -500,6 +528,7 @@ static void show_defaults (void) + printf ("EXPIRE=%s\n", def_expire); + printf ("SHELL=%s\n", def_shell); + printf ("SKEL=%s\n", def_template); ++ printf ("USRSKEL=%s\n", def_usrtemplate); + printf ("CREATE_MAIL_SPOOL=%s\n", def_create_mail_spool); + } + +@@ -526,6 +555,7 @@ static int set_defaults (void) + bool out_expire = false; + bool out_shell = false; + bool out_skel = false; ++ bool out_usrskel = false; + bool out_create_mail_spool = false; + size_t len; + int ret = -1; +@@ -620,6 +650,9 @@ static int set_defaults (void) + } else if (!out_skel && MATCH (buf, DSKEL)) { + fprintf (ofp, DSKEL "%s\n", def_template); + out_skel = true; ++ } else if (!out_usrskel && MATCH (buf, DUSRSKEL)) { ++ fprintf (ofp, DUSRSKEL "%s\n", def_usrtemplate); ++ out_usrskel = true; + } else if (!out_create_mail_spool + && MATCH (buf, DCREATE_MAIL_SPOOL)) { + fprintf (ofp, +@@ -649,6 +682,8 @@ static int set_defaults (void) + fprintf (ofp, DSHELL "%s\n", def_shell); + if (!out_skel) + fprintf (ofp, DSKEL "%s\n", def_template); ++ if (!out_usrskel) ++ fprintf (ofp, DUSRSKEL "%s\n", def_usrtemplate); + + if (!out_create_mail_spool) + fprintf (ofp, DCREATE_MAIL_SPOOL "%s\n", def_create_mail_spool); +@@ -2507,6 +2542,8 @@ int main (int argc, char **argv) + if (home_added) { + copy_tree (def_template, prefix_user_home, false, false, + (uid_t)-1, user_id, (gid_t)-1, user_gid); ++ copy_tree (def_usrtemplate, prefix_user_home, false, false, ++ (uid_t)-1, user_id, (gid_t)-1, user_gid); + } else { + fprintf (stderr, + _("%s: warning: the home directory %s already exists.\n" +Index: libmisc/copydir.c +=================================================================== +--- libmisc/copydir.c.orig ++++ libmisc/copydir.c +@@ -416,6 +416,14 @@ static int copy_entry (const char *src, + old_uid, new_uid, old_gid, new_gid); + } + ++ /* ++ * If the destination already exists do nothing. ++ * This is after the copy_dir above to still iterate into subdirectories. ++ */ ++ if (LSTAT (dst, &sb) != -1) { ++ return 0; ++ } ++ + #ifdef S_IFLNK + /* + * Copy any symbolic links +@@ -477,6 +485,7 @@ static int copy_dir (const char *src, co + gid_t old_gid, gid_t new_gid) + { + int err = 0; ++ struct stat dst_sb; + + /* + * Create a new target directory, make it owned by +@@ -488,6 +497,16 @@ static int copy_dir (const char *src, co + return -1; + } + #endif /* WITH_SELINUX */ ++ ++ /* ++ * If the destination is already a directory, don't change it ++ * but copy into it (recursively). ++ */ ++ if (LSTAT (dst, &dst_sb) == 0 && S_ISDIR(dst_sb.st_mode)) { ++ return (copy_tree (src, dst, false, reset_selinux, ++ old_uid, new_uid, old_gid, new_gid) != 0); ++ } ++ + if ( (mkdir (dst, statp->st_mode) != 0) + || (chown_if_needed (dst, statp, + old_uid, new_uid, old_gid, new_gid) != 0) diff --git a/useradd.local b/useradd.local new file mode 100644 index 0000000..c5b35ce --- /dev/null +++ b/useradd.local @@ -0,0 +1,49 @@ +#!/bin/sh +# +# Here you can add your own stuff, that should be done for every user who +# was new created. +# +# When you create a user with useradd, this script will be called +# with the login name as parameter. Optional, UID, GID and the HOME +# directory are added. +# + +case "$1" in + --help|--version) + echo Usage: $0 username [uid gid home] + exit 0 + ;; +esac + +# Check for the required argument. +if [ $# -lt 1 -o $# -gt 4 ]; then + echo Usage: $0 username [uid gid home] + exit 1 +fi + +USER=$1 + +if [ $# -eq 4 ]; then + GID=$3 + HOMEDIR=$4 +else + GID=$(id -g $USER) + HOMEDIR=$(grep -E "^${USER}:" /etc/passwd| cut -d: -f6,6) +fi + +# Update NIS database +# make -C /var/yp + +# Main useradd tool creates this if specified on command line +[ -d $HOMEDIR ] || exit 0 + +# If SELinux is enabled, we have to run restorecon to assign +# appropriate fcontexts to the respective $HOME and files under it +if [ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled ; then + test -x /sbin/restorecon || exit 2 + + /sbin/restorecon -R $HOMEDIR +fi + +# All done. +exit 0 diff --git a/userdel-post.local b/userdel-post.local new file mode 100644 index 0000000..4a2e110 --- /dev/null +++ b/userdel-post.local @@ -0,0 +1,29 @@ +#!/bin/sh +# +# Here you can add your own stuff, that should be done for every user +# which we deleted. +# +# If you delete a user with userdel, this script will be called +# with the login name as parameter after the account and optional +# home directory was removed from the system. +# + +case "$1" in + --help|--version) + echo Usage: $0 username uid gid home + exit 0 + ;; +esac + +# Check for the required argument. +if [ $# != 1 ]; then + echo Usage: $0 username + exit 1 +fi + +# Rebuild NIS database to remove the account from it. +# make -C /var/yp + +# All done. +exit 0 + diff --git a/userdel-pre.local b/userdel-pre.local new file mode 100644 index 0000000..0424cd7 --- /dev/null +++ b/userdel-pre.local @@ -0,0 +1,32 @@ +#!/bin/sh +# +# Here you can add your own stuff, that should be done for every user +# who will be deleted. +# +# When you delete a user with userdel, this script will be called +# with the login name as parameter before any other action is done. +# + +case "$1" in + --help|--version) + echo Usage: $0 username uid gid home + exit 0 + ;; +esac + +# Check for the required argument. +if [ $# != 1 ]; then + echo Usage: $0 username + exit 1 +fi + +# Remove cron jobs +test -x /usr/bin/crontab && /usr/bin/crontab -r -u $1 + +# Stop systemd user jobs, even this requires --force +id=$(id -u $1) +systemctl stop user@${id}.service > /dev/null 2>&1 & + +# All done. +exit 0 + diff --git a/userdel-script.patch b/userdel-script.patch new file mode 100644 index 0000000..966fbc9 --- /dev/null +++ b/userdel-script.patch @@ -0,0 +1,104 @@ +Index: lib/getdef.c +=================================================================== +--- lib/getdef.c.orig ++++ lib/getdef.c +@@ -127,6 +127,8 @@ static struct itemdef def_table[] = { + {"UID_MIN", NULL}, + {"UMASK", NULL}, + {"USERDEL_CMD", NULL}, ++ {"USERDEL_PRECMD", NULL}, ++ {"USERDEL_POSTCMD", NULL}, + {"USERGROUPS_ENAB", NULL}, + #ifndef USE_PAM + PAMDEFS +Index: etc/login.defs +=================================================================== +--- etc/login.defs.orig ++++ etc/login.defs +@@ -216,9 +216,25 @@ DEFAULT_HOME yes + # It should remove any at/cron/print jobs etc. owned by + # the user to be removed (passed as the first argument). + # ++# See also USERDEL_PRECMD and USERDEL_POSTCMD below. ++# + #USERDEL_CMD /usr/sbin/userdel_local + + # ++# If defined, this command is run before removing a user. ++# It should remove any at/cron/print jobs etc. owned by ++# the user to be removed. ++# ++USERDEL_PRECMD /usr/sbin/userdel-pre.local ++ ++# ++# If defined, this command is run after removing a user. ++# It should rebuild any NIS database etc. to remove the ++# account from it. ++# ++USERDEL_POSTCMD /usr/sbin/userdel-post.local ++ ++# + # Enable setting of the umask group bits to be the same as owner bits + # (examples: 022 -> 002, 077 -> 007) for non-root users, if the uid is + # the same as gid, and username is the same as the primary group name. +Index: src/userdel.c +=================================================================== +--- src/userdel.c.orig ++++ src/userdel.c +@@ -126,7 +126,7 @@ static void close_files (void); + static void fail_exit (int); + static void open_files (void); + static void update_user (void); +-static void user_cancel (const char *); ++static void call_script (const char *, const char *); + + #ifdef EXTRA_CHECK_HOME_DIR + static bool path_prefix (const char *, const char *); +@@ -768,13 +768,13 @@ static void update_user (void) + * cron, at, or print jobs. + */ + +-static void user_cancel (const char *user) ++static void call_script (const char *program, const char *user) + { + const char *cmd; + const char *argv[3]; + int status; + +- cmd = getdef_str ("USERDEL_CMD"); ++ cmd = getdef_str (program); + if (NULL == cmd) { + return; + } +@@ -1214,9 +1214,10 @@ int main (int argc, char **argv) + } + + /* +- * Do the hard stuff - open the files, create the user entries, +- * create the home directory, then close and update the files. ++ * Do the hard stuff - open the files, remove the user entries, ++ * remove the home directory, then close and update the files. + */ ++ call_script ("USERDEL_PRECMD", user_name); + open_files (); + update_user (); + update_groups (); +@@ -1337,7 +1338,7 @@ int main (int argc, char **argv) + * the entry from /etc/passwd. + */ + if(prefix[0] == '\0') +- user_cancel (user_name); ++ call_script ("USERDEL_CMD", user_name); + close_files (); + + #ifdef WITH_TCB +@@ -1348,6 +1349,9 @@ int main (int argc, char **argv) + nscd_flush_cache ("group"); + sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); + ++ /* Call the post script, for example to rebuild NIS database */ ++ call_script ("USERDEL_POSTCMD", user_name); ++ + return ((0 != errors) ? E_HOMEDIR : E_SUCCESS); + } +