673 lines
21 KiB
Diff
673 lines
21 KiB
Diff
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 <config.h>
|
||
|
||
-#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 <sys/types.h>
|
||
#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 <config.h>
|
||
+
|
||
+#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);
|
||
}
|